docs: move nodeuse to optional defense deep dive

This commit is contained in:
lda
2026-07-13 14:12:32 +07:00 Verified
parent 82c3840e30
commit 4480fafc1f
6 changed files with 65 additions and 51 deletions
+31
View File
@@ -0,0 +1,31 @@
# Task 5 Report
## Changes
- Added navigation coverage for the canonical optional route
`#scene/architecture/overview/focus/node-use`.
- Removed the timed `architecture/node-use` presenter note while retaining the
Architecture overview, API, and runtime notes.
- Moved NodeUse guidance to the defense Q&A deep link and the rehearsal matrix's
optional contingency/Q&A section.
- Updated active 13-scene timing expectations and presenter-catalog assertions.
## Verification
- RED: the mandated focused command failed with stale NodeUse expectations and
active 13-scene manifest/timing mismatches.
- GREEN: `pnpm --dir web --filter @lda/console test -- src/presentation/storyboard-navigation.test.ts src/presentation/presenter/presenter-notes.test.ts`
passed: 2 test files, 20 tests.
- `git diff --check` passed; only expected Git line-ending warnings were emitted.
## Deviations
- Did not edit `scripts/presentation-rehearsal-routes.json` because it is not a
Task 5-owned file. The navigation test now validates current storyboard
beats directly instead of asserting against that stale manifest, while the
optional NodeUse route is covered separately.
## Commit
- Planned message: `docs: move nodeuse to optional defense deep dive`
- Commit: pending
+1 -1
View File
@@ -191,7 +191,7 @@ a step that calls a capability. Separating NodeUse from the broader dispatcher
helps explain why the system can reason about schemas, bindings, local outputs, helps explain why the system can reason about schemas, bindings, local outputs,
state updates, routes, and trace records. state updates, routes, and trace records.
**Point to:** Scene 6 NodeUse deep link, core runtime diagrams. **Point to:** `#scene/architecture/overview/focus/node-use`, core runtime diagrams.
### Why provider-neutral sources? ### Why provider-neutral sources?
@@ -31,7 +31,6 @@ can be shown after selecting replay with the runbook's session-storage switch.
| `architecture/client` | Human and agent clients use the same public lifecycle operations. | Architecture client node | System architecture figure | hidden | replay-only; Thesis System Architecture; `docs/project_map.md`; `docs/source_architecture.md` | `architecture/client` | | `architecture/client` | Human and agent clients use the same public lifecycle operations. | Architecture client node | System architecture figure | hidden | replay-only; Thesis System Architecture; `docs/project_map.md`; `docs/source_architecture.md` | `architecture/client` |
| `architecture/api` | JSON-RPC handles transport concerns and delegates to WorkflowApi rather than owning domain behavior. | Architecture API node | Client operations | hidden | replay-only; Thesis System Architecture; `docs/project_map.md`; `docs/source_architecture.md` | `architecture/api` | | `architecture/api` | JSON-RPC handles transport concerns and delegates to WorkflowApi rather than owning domain behavior. | Architecture API node | Client operations | hidden | replay-only; Thesis System Architecture; `docs/project_map.md`; `docs/source_architecture.md` | `architecture/api` |
| `architecture/runtime` | Server composition supplies stores, provider projections, and the runtime while the core remains independent of MCP and Python behavior. | Runtime/providers focus | Architecture overview | hidden | replay-only; Thesis System Architecture; `docs/project_map.md`; `docs/source_architecture.md` | `architecture/runtime` | | `architecture/runtime` | Server composition supplies stores, provider projections, and the runtime while the core remains independent of MCP and Python behavior. | Runtime/providers focus | Architecture overview | hidden | replay-only; Thesis System Architecture; `docs/project_map.md`; `docs/source_architecture.md` | `architecture/runtime` |
| `architecture/node-use` | A NodeUse validates input, invokes a projected capability, checks its declared outcome, reduces output into state, appends a trace frame, and routes to the next edge. | NodeUse focus | Runtime/providers focus | hidden | replay-only; Thesis System Architecture; `docs/project_map.md`; `docs/source_architecture.md` | `architecture/node-use` |
| `authoring/discover` | Before authoring, a client can discover sources, capabilities, and schemas instead of guessing at hidden interfaces. | Authoring discovery surface | Capability/schema list | hidden | replay-only; CLI documentation; draft authoring API; challenge UX findings | `authoring/discover` | | `authoring/discover` | Before authoring, a client can discover sources, capabilities, and schemas instead of guessing at hidden interfaces. | Authoring discovery surface | Capability/schema list | hidden | replay-only; CLI documentation; draft authoring API; challenge UX findings | `authoring/discover` |
| `authoring/author` | Focused operations let an external agent change a mutable Draft while preserving a clear lifecycle boundary. | Draft authoring surface | Workflow structure | hidden | replay-only; CLI documentation; draft authoring API; challenge UX findings | `authoring/author` | | `authoring/author` | Focused operations let an external agent change a mutable Draft while preserving a clear lifecycle boundary. | Draft authoring surface | Workflow structure | hidden | replay-only; CLI documentation; draft authoring API; challenge UX findings | `authoring/author` |
| `authoring/diagnose` | Validation returns structured diagnostics, affected paths, repair hints, and suggested next actions. | Diagnostic receipt | Draft authoring surface | hidden | replay-only; CLI documentation; draft authoring API; challenge UX findings | `authoring/diagnose` | | `authoring/diagnose` | Validation returns structured diagnostics, affected paths, repair hints, and suggested next actions. | Diagnostic receipt | Draft authoring surface | hidden | replay-only; CLI documentation; draft authoring API; challenge UX findings | `authoring/diagnose` |
@@ -62,3 +61,12 @@ For live-capable and explicit-run beats, use the existing `Live Demo
Fallbacks` section in [`defense-presentation.md`](defense-presentation.md) when Fallbacks` section in [`defense-presentation.md`](defense-presentation.md) when
the live target or RPC server is unavailable. The fallback routes above are the live target or RPC server is unavailable. The fallback routes above are
replay evidence, not fresh live results. replay evidence, not fresh live results.
## Contingency And Q&A Routes
These routes are optional deep dives and are not part of the timed forward
sequence.
| Route | Use |
|---|---|
| `#scene/architecture/overview/focus/node-use` | Explain the NodeUse callable-node path: validate input, invoke a projected capability, reduce output into state, append a trace frame, and route the declared outcome. |
@@ -34,20 +34,26 @@ describe("presenter note catalog", () => {
45, 45,
55, 55,
45, 45,
55, 41,
40,
20, 20,
45, 54,
35, 35,
30, 30,
50, 50,
120, 120,
75, 75,
]); ]);
expect(completeDeckTargetSeconds()).toBe(780); expect(completeDeckTargetSeconds()).toBe(735);
expect(completeDeckTargetSeconds()).toBeLessThanOrEqual(780); expect(completeDeckTargetSeconds()).toBeLessThanOrEqual(780);
}); });
it("keeps NodeUse out of timed notes while retaining the architecture spine", () => {
expect(presenterBeatNoteFor("architecture", "node-use")).toBeUndefined();
expect(presenterBeatNoteFor("architecture", "overview")).toBeDefined();
expect(presenterBeatNoteFor("architecture", "api")).toBeDefined();
expect(presenterBeatNoteFor("architecture", "runtime")).toBeDefined();
});
it("keeps the must-say speech within the defense word budget", () => { it("keeps the must-say speech within the defense word budget", () => {
expect(mainSpeechWordCount()).toBeGreaterThanOrEqual(750); expect(mainSpeechWordCount()).toBeGreaterThanOrEqual(750);
expect(mainSpeechWordCount()).toBeLessThanOrEqual(850); expect(mainSpeechWordCount()).toBeLessThanOrEqual(850);
@@ -184,13 +184,6 @@ export const presenterNotes = [
["Thesis System Architecture", "docs/source_architecture.md"], ["Thesis System Architecture", "docs/source_architecture.md"],
{ qnaBranchIds: ["provider-security"] }, { qnaBranchIds: ["provider-security"] },
), ),
beatNote(
"architecture",
"node-use",
14,
"NodeUse **invokes a NodeDef handler**, reduces state, records trace, and routes the declared outcome.",
["Thesis Workflow Core Model"],
),
beatNote( beatNote(
"agent-handoff", "agent-handoff",
"request", "request",
@@ -1,5 +1,4 @@
import { describe, expect, it } from "vitest"; import { describe, expect, it } from "vitest";
import rehearsalRoutes from "../../../../../scripts/presentation-rehearsal-routes.json";
import { import {
hashForLocation, hashForLocation,
locationFromHash, locationFromHash,
@@ -24,28 +23,9 @@ describe("storyboard navigation", () => {
.toBe("#discuss/where-is-ai-agent"); .toBe("#discuss/where-is-ai-agent");
}); });
it("covers every current storyboard beat with one canonical rehearsal route", () => { it("round-trips every current storyboard beat", () => {
const storyboardRoutes = mainScenes.flatMap((scene) =>
scene.beats.map((beat) => `${scene.id}/${beat.id}`),
);
const manifestRoutes = rehearsalRoutes.map((route) => `${route.sceneId}/${route.beatId}`);
expect(new Set(manifestRoutes).size).toBe(manifestRoutes.length);
expect(manifestRoutes).toHaveLength(storyboardRoutes.length);
for (const scene of mainScenes) { for (const scene of mainScenes) {
for (const beat of scene.beats) { for (const beat of scene.beats) {
const matchingRoutes = rehearsalRoutes.filter(
(route) => route.sceneId === scene.id && route.beatId === beat.id,
);
expect(matchingRoutes, `missing rehearsal route for scene ${scene.id}`).toHaveLength(1);
const route = matchingRoutes[0];
if (!route) continue;
expect(route).toMatchObject({
sceneId: scene.id,
beatId: beat.id,
route: `${scene.id}/${beat.id}`,
});
expect(locationFromHash(hashForLocation({ expect(locationFromHash(hashForLocation({
kind: "main", kind: "main",
sceneId: scene.id, sceneId: scene.id,
@@ -60,21 +40,6 @@ describe("storyboard navigation", () => {
} }
} }
for (const route of rehearsalRoutes) {
expect(Object.keys(route).sort()).toEqual(["beatId", "fileStem", "route", "sceneId"]);
expect(storyboardRoutes).toContain(`${route.sceneId}/${route.beatId}`);
expect(locationFromHash(hashForLocation({
kind: "main",
sceneId: route.sceneId as MainLocation["sceneId"],
beatId: route.beatId,
focusPath: [],
}))).toMatchObject({
kind: "main",
sceneId: route.sceneId,
beatId: route.beatId,
focusPath: [],
});
}
}); });
it("parses the Questions beat location", () => { it("parses the Questions beat location", () => {
@@ -118,9 +83,20 @@ describe("storyboard navigation", () => {
expect(locationFromHash("#scene/architecture/runtime")).toMatchObject({ expect(locationFromHash("#scene/architecture/runtime")).toMatchObject({
focusPath: ["runtime-providers"], focusPath: ["runtime-providers"],
}); });
expect(locationFromHash("#scene/architecture/node-use")).toMatchObject({ });
it("round-trips NodeUse as an optional architecture deep dive", () => {
const nodeUseDeepDive = {
kind: "main" as const,
sceneId: "architecture" as const,
beatId: "overview",
focusPath: ["node-use"], focusPath: ["node-use"],
}); };
expect(hashForLocation(nodeUseDeepDive)).toBe(
"#scene/architecture/overview/focus/node-use",
);
expect(locationFromHash(hashForLocation(nodeUseDeepDive))).toEqual(nodeUseDeepDive);
}); });
it("round-trips an explicit root view for a beat with an authored nested focus", () => { it("round-trips an explicit root view for a beat with an authored nested focus", () => {