practice: the agent's data drawer — full transparency on every conclude card (round 17)
Owner ask (2026-10-06): reveal everything the agent filled in when writing the problem and concluding it, at the very bottom of the conclude card, collapsible, arriving collapsed. The fields, both calls: - problem: mode (recall/discrimination/composition), target proposition ids, statement, modelSolution (the last two ARE the visible card — the drawer shows the metadata only) - conclude: outcome, hint rung (R0–R5/null), miss class (cue/discrimination/execution/careless/structural/null), retest. Seams: problemInputForConclude (native-messages) walks the reveal's walk and folds the WHOLE problem-call input onto the conclude part (projectView join; same refused-pose law — an unacked pose folds nothing); ArtifactPartProps grows problemInput. Targets resolve to proposition NAMES at render (one lazy module-cached /api/graph fetch; failure degrades to raw ids — observability never breaks the card). The drawer: divider + chevron 'AGENT'S DATA' toggle (mono-caps eyebrow register), definition rows with mono values, 'untagged'/ 'none' honest empties, absent entirely when the calls filled nothing (the dismissal line, legacy bare records).
This commit is contained in:
@@ -298,6 +298,10 @@ export interface ArtifactPartProps {
|
||||
toolCallId: string;
|
||||
input?: unknown;
|
||||
output?: unknown;
|
||||
/** The pose-side fold (owner round 17): the whole problem-call
|
||||
* arguments joined onto the conclude part by projectView — the
|
||||
* observability drawer's data. */
|
||||
problemInput?: unknown;
|
||||
/** The view-seam join for conclude cards (owner round, 2026-10-05):
|
||||
* the modelSolution committed at POSE time, folded onto the part by
|
||||
* projectView — the reveal is never re-authored. */
|
||||
|
||||
@@ -364,6 +364,20 @@ export function modelSolutionForConclude(
|
||||
messages: readonly LhMessage[],
|
||||
concludeCallId: string,
|
||||
): string | undefined {
|
||||
const input = problemInputForConclude(messages, concludeCallId);
|
||||
return typeof input?.modelSolution === "string" ? input.modelSolution : undefined;
|
||||
}
|
||||
|
||||
/** The full pose-side fold (owner round 17, 2026-10-06 — observability):
|
||||
* EVERYTHING the agent filled into the problem call — mode, target ids,
|
||||
* statement, the committed solution — joined onto the conclude part so
|
||||
* the card's collapsible "agent's data" drawer renders pure. Same walk
|
||||
* and refusal law as the reveal: a pose the record never acked (a
|
||||
* refused call) folds nothing. */
|
||||
export function problemInputForConclude(
|
||||
messages: readonly LhMessage[],
|
||||
concludeCallId: string,
|
||||
): { statement?: unknown; mode?: unknown; target?: unknown; modelSolution?: unknown } | undefined {
|
||||
let mi = messages.findIndex(
|
||||
(m) =>
|
||||
(m as { role?: string }).role === "assistant" &&
|
||||
@@ -381,8 +395,9 @@ export function modelSolutionForConclude(
|
||||
const block = assistant.content[bi]!;
|
||||
if (block.type !== "toolCall" || block.name !== PRACTICE_PROBLEM_TOOL) continue;
|
||||
if (!clean.has(block.id)) continue; // a refused pose revealed nothing
|
||||
const solution = (block.arguments as { modelSolution?: unknown } | undefined)?.modelSolution;
|
||||
return typeof solution === "string" ? solution : undefined;
|
||||
return (block.arguments ?? undefined) as
|
||||
| { statement?: unknown; mode?: unknown; target?: unknown; modelSolution?: unknown }
|
||||
| undefined;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
|
||||
+2
-1
@@ -34,7 +34,7 @@
|
||||
|
||||
import type { AssistantMessage, ToolResultMessage } from "@earendil-works/pi-ai";
|
||||
import type { LhMarkerMessage, LhMessage } from "./native-messages.ts";
|
||||
import { modelSolutionForConclude, PRACTICE_CONCLUDE_TOOL } from "./native-messages.ts";
|
||||
import { modelSolutionForConclude, PRACTICE_CONCLUDE_TOOL, problemInputForConclude } from "./native-messages.ts";
|
||||
import { activeCompactionOf, type CompactionDetails } from "./compaction.ts";
|
||||
import { QUESTION_TOOLS } from "./pending.ts";
|
||||
import type { SubagentArtifactData, SubagentResultMeta } from "./contracts/jobs.ts";
|
||||
@@ -223,6 +223,7 @@ export function projectView(messages: readonly LhMessage[], live?: LiveTurnState
|
||||
// time — a record fold, enriched here so the card renders pure.
|
||||
if (block.name === PRACTICE_CONCLUDE_TOOL) {
|
||||
part.reveal = modelSolutionForConclude(messages, block.id);
|
||||
part.problemInput = problemInputForConclude(messages, block.id);
|
||||
}
|
||||
rest.push(part);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user