artifacts: the height ratchet fixed, invert switch persisted + restyled (release polish 7.2)
- bridge measures the BODY (scrollHeight + rect + margins) instead of the viewport-clamped documentElement — documentElement.scrollHeight latches at the parent's own height, so demos could grow but never shrink on window resize (owner-reported); smoke: 1036 → 2386 → 1036 px - invert now PERSISTS as details.ui.inverted on the steer record, written by the silent artifact-ui route (dismissal pattern: no wake, no SSE) and seeded through the projection (SubagentArtifactData.ui); survives navigation + reload, never enters teacher context or exports - invert restyled as the house Toggle switch (settings controls) on both cards; demo header is the caption grammar: 'INTERACTIVE DEMO — title' left (title normal-case, same size/tracking), switch + download far right; figure header: label left, switch/download/open far right 1439 tests green (route + pure-seam pins added); live smoke passed
This commit is contained in:
@@ -271,12 +271,36 @@ export interface SubagentResultMeta {
|
||||
export interface SubagentArtifactData {
|
||||
kind: JobKind;
|
||||
result: ResearchResult | DemoResult | VisualResult | PdfResult;
|
||||
/** The learner's pinned UI state (invert switch) riding the record. */
|
||||
ui?: { inverted?: boolean };
|
||||
}
|
||||
|
||||
/** A result steer's marker details: the UI's meta + artifact in one
|
||||
* payload (the projection splits it into metadata + data part). */
|
||||
export interface SteerDetails extends SubagentResultMeta {
|
||||
result: ResearchResult | DemoResult | VisualResult | PdfResult;
|
||||
/** LEARNER UI state pinned onto the artifact (owner, 2026-10-07): the
|
||||
* invert switch's position, persisted so navigating away and back (or
|
||||
* restarting) keeps it. A VIEW preference — never enters the teacher's
|
||||
* context, never exports (the markdown engine reads `result` only). */
|
||||
ui?: { inverted?: boolean };
|
||||
}
|
||||
|
||||
/** Set a steer message's ui.inverted (pure): returns a NEW message array
|
||||
* with the target's details updated — no-op (same array) when the message
|
||||
* is missing or not an invertible artifact steer. The silent route's
|
||||
* whole body. */
|
||||
export function setSteerUiInverted(
|
||||
messages: readonly LhMessage[],
|
||||
messageId: string,
|
||||
inverted: boolean,
|
||||
): LhMessage[] {
|
||||
return messages.map((m) => {
|
||||
if (m.id !== messageId) return m;
|
||||
const d = (m as LhMarkerMessage).details as Partial<SteerDetails> | undefined;
|
||||
if (!d || (d.kind !== "demo" && d.kind !== "visual")) return m;
|
||||
return { ...m, details: { ...d, ui: { ...d.ui, inverted } } } as LhMessage;
|
||||
});
|
||||
}
|
||||
|
||||
/** Anything the wake pipeline may queue and deliver — a native marker. */
|
||||
|
||||
+6
-1
@@ -368,6 +368,7 @@ function projectMarker(marker: LhMarkerMessage, out: LhViewMessage[]): void {
|
||||
const artifact = marker.details as {
|
||||
kind: SubagentArtifactData["kind"];
|
||||
result: SubagentArtifactData["result"];
|
||||
ui?: SubagentArtifactData["ui"];
|
||||
};
|
||||
out.push({
|
||||
id: marker.id,
|
||||
@@ -375,7 +376,11 @@ function projectMarker(marker: LhMarkerMessage, out: LhViewMessage[]): void {
|
||||
metadata: { subagentResult: meta },
|
||||
parts: [
|
||||
textPart(marker.content),
|
||||
{ type: "data-subagent-artifact", id: `sa_${marker.id}`, data: { kind: artifact.kind, result: artifact.result } },
|
||||
{
|
||||
type: "data-subagent-artifact",
|
||||
id: `sa_${marker.id}`,
|
||||
data: { kind: artifact.kind, result: artifact.result, ui: artifact.ui },
|
||||
},
|
||||
],
|
||||
});
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user