practice record mechanics: active-problem fold, thinking channel, deferred conclude

The native shapes beneath the practice tools (owner design 2026-10-04):
- activeProblemOf — the conclude-before-next-problem gate's fold (a
  conclude call OR a dismissal marker deactivates; the pose-time ack
  never does — nudges keep the card up).
- The thinking input: {problemCallId, commit, text} → practice-thinking
  marker; the label (THINKING_HINT/COMMIT_LABEL, single-sourced in
  contracts) is the only register difference the model sees.
- Ask-style problem dismissal: silent route appends the UI-only marker;
  the user's NEXT input prepends the synthesized conclude pair (call
  outcome:'dismissed' + shared ack) so the agent reads the discard in
  its own vocabulary and the slot frees.
- toLlmMessages: dismissal marker filtered; pair passes natively.
This commit is contained in:
amosblomqvist
2026-10-04 21:41:29 +03:00
parent 7dcb006cf3
commit eb7454900c
4 changed files with 512 additions and 8 deletions
+16
View File
@@ -179,6 +179,22 @@ export const HANDOFF_TEXT =
"Take your time here and really think this through. " +
"When it's genuinely reasoned out, call plan_init and present the plan; I'll accept it or ask for changes.";
// ─── Practice sessions (owner, 2026-10-04) — marker + ack texts ──────────────
// Single-sourced here per the marker law: the model-facing text of every
// custom marker lives in core/contracts, never in the flattening seam.
/** The model-facing register of a thinking submission (newThinkingMessage
* prefixes the learner's text with this label). Hints and commits ride
* one channel — the label is the ONLY difference the model sees. */
export const THINKING_HINT_LABEL = "Thinking trace (working, not committed)";
export const THINKING_COMMIT_LABEL = "Committed answer";
/** The conclude tool's ack — shared by the executed call (agent layer) and
* the dismissal-synthesized pair (input-events), so a concluded problem
* reads identically to the model however it concluded. */
export const CONCLUDE_ACK_TEXT =
"Problem concluded — the composer is free; pose the next problem or wrap up.";
export interface PlanBlockData {
/** Only "full" survives (the 2026-09-11 pivot): the plan renders IN