Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 3 additions & 3 deletions .tours/01-primary-user-flow.tour
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
},
{
"file": "src/features/node-agent/components/NodeAgentThread.tsx",
"line": 91,
"line": 126,
"anchor": "<ComposerPrimitive.Send",
"description": "The control the user actually presses. Note it is the only button on the page while a run is in flight, and it is disabled — there is no cancel. That is open defect D3."
"description": "Send starts a response. While it runs, Stop response ends its display updates and preserves completed work; it does not undo already computed or external work. An incomplete response offers explicit Retry through the existing runtime, never automatic retry. This local demo does not certify provider cancellation."
},
{
"file": "src/features/node-agent/runtime/nodeAgentChatAdapter.ts",
Expand All @@ -53,7 +53,7 @@
},
{
"file": "src/features/node-agent/components/toolUIs.tsx",
"line": 56,
"line": 62,
"anchor": "toolName: \"collect_context\"",
"description": "Tool REGISTRATION. A tool here is a name string with a card bound to it — there is no model doing tool-calling, no schema registry, no dispatch table."
},
Expand Down
38 changes: 38 additions & 0 deletions HANDOFF.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# NodeAgent developer handoff

Read this file first, then [the runtime walkthrough](docs/START_HERE.md). This review candidate starts from canonical `4e525fd0`. The separately preserved Pi draft is not integrated. Independent source and installed-consumer review passes for the bounded slice below. The [portable judgment](evidence/current-consumer-20260905/judge/E6e_NODEAGENT_CURRENT_CONSUMER_FINAL_JUDGE.md.txt), manifest and Git history identify the reviewed implementation and its later publication metadata.

A developer can run the repository's local scenario and generate a separate chat application without credentials. Both chats use scripted local adapters; displayed confidence numbers come from fixtures. Their browser conversations reset on reload. The library's durable/SQLite demonstration is a separate integration and does not persist either browser chat.

Use Node 22; this proof used Node 22.22.2. From this repository run `npm ci`, `npm test`, `npm run build` and `npm run tours:validate`. The 41 tests, typecheck/build, three tours/36 steps and 11 walkthrough citations pass. To generate a consumer, run `npm pack`, install that exact tarball in a new empty npm project, then use its installed CLI:

```powershell
node node_modules/nodeagent/bin/nodeagent.mjs doctor
node node_modules/nodeagent/bin/nodeagent.mjs apps scaffold chat-ui --dir "../NodeAgent Chat" --auto
Set-Location "../NodeAgent Chat"
npm run dev
```

`--auto` performs normal install, demo, smoke and build. Keep the included template lock; use `npm ci` for repeatable reinstall. Existing-target refusal was verified with an owner sentinel and without force. Each failed and repaired consumer was retained separately.

The original unlocked template resolved incompatible assistant-ui dependencies and failed its first real prompt despite smoke/build passing. A tested compatible template lock fixes that install seam without changing dependency ranges. The final packed consumer binds 242 source/tarball/installed files and the exact generated lock. Its tarball SHA-256 is `1a6e980a684f433fcdc80021eb5569fa5c4b94e09a71e8a2adbe5d821e654c69`. That package predates this final handoff/evidence metadata; it is an uncommitted candidate proof, not a published release certificate.

Both current chats expose **Stop response**, visible incomplete/failed tool status, and explicit **Retry response**. Stop ends response display updates and keeps completed work. It cannot undo work already computed by the adapter, graph facts already recorded, durable work or external actions. Retry re-executes only the current response through the native runtime and preserves earlier turns. It is never automatic. A synchronous claim on the current response ID rejects immediate double activation; actual SDK IDs were observed to change on each retry, so a second failed response remains retryable. This is a local UI guarantee, not external-service idempotency or provider cancellation.

[Portable evidence](evidence/current-consumer-20260905/README.md) contains the actual before boundaries, failure history, command logs, source bindings and final browser reports. The response-recovery run passed 289 checks and saved 76 captures across 320/390/768/1024/1440/1920 for both source and installed generated apps. It covers ordinary pointer/keyboard Stop, stable incomplete output, preserved earlier cards/graph snapshot, failure then explicit retry then failure again then explicit recovery, duplicate activation, pointer target stability, keyboard-visible error/Retry at enlarged text, and reload reset. An additional 12 turns produced 15 responses/60 cards in 21.182 seconds generated and 29.482 seconds source. These are bounded accumulation checks, not production longevity measurements.

The unchanged first-run scenario separately passed 59 checks/25 captures on the final installed app, including eight sequential turns/32 cards in 13.968 seconds. Reproduce the two browser journeys from the source checkout with a fresh installed generated target and NEW output directories:

```powershell
node e2e/current-consumer-proof.mjs "<generated app>" "<new baseline evidence>"
node e2e/current-consumer-recovery-proof.mjs "<generated app>" "<new recovery evidence>"
```

Separate offline frame/durable/SQLite runs completed. SQLite closed/reopened the retained database and replayed the same frame with one journal entry; lease exclusion, expiry recovery and fencing passed. Use `nodeagent:frame:smoke`, `nodeagent:durable:smoke` and `nodeagent:sqlite:smoke` for that separate library integration. Their fixture confidence is not an external provider measurement.

Remaining limits are explicit. Source-header text still overflows by 21 pixels in the 390-pixel, doubled-computed-text fixture; the changed recovery/composer regions fit and remain visible. The text fixture is not an operating-system zoom certificate. The source graph still needs its own visual/readability assessment. There is no React render-error boundary or New Thread control. Full visual, responsive, accessibility and performance grades remain null. Source full audit has nine development advisories, including one critical; the locked generated app has four development advisories, three high and one low. Both recorded production-only audits have zero findings. Those full-audit findings remain open.

No provider, Convex, login, external-host hook, deployment or Pi capability was activated. The historical dependency checkpoint and previous promotion records retain their original outcomes. This handoff closes the bounded offline consumer and response-recovery implementation for independent review; it does not claim complete repository readiness.


Independent replay adds130 checks/34 captures, including late Stop after an actual completed tool result and two distinct failed-response Retry identities. Fresh41 tests, typecheck and citations pass. The original publication judgment records60 line-ending mismatches; packet-local attributes preserve those exact raw bytes before commit. Existing header overflow, graph readability, development advisories, browser reset and provider/durability limits remain unchanged. This local source/installed proof does not certify deployment or the whole product.
41 changes: 24 additions & 17 deletions docs/START_HERE.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ send button is what starts the agent.

**Core code**
```tsx
// src/features/node-agent/components/NodeAgentThread.tsx:84-93
// src/features/node-agent/components/NodeAgentThread.tsx:118-135
<ComposerPrimitive.Root className="na-composer">
<ComposerPrimitive.Input placeholder="Ask the room anything…" rows={1} autoFocus />
<ComposerPrimitive.Send className="na-send" aria-label="Send">↑</ComposerPrimitive.Send>
Expand All @@ -130,9 +130,11 @@ actually start.
**Input** — typed text, or a click on a suggestion chip.
**Output** — a user message appended to the thread; assistant-ui then calls the
adapter in Step 4.
**Failure behavior** — the send button is disabled while a run is in flight.
There is no cancel button; that is a known open defect (D3 in
`promotion/PROMOTION_LOG.md`).
**Failure behavior** — while a response runs, Send gives way to Stop response.
Stop ends its display updates and preserves completed work; it does not undo
already computed or external work. Incomplete responses offer explicit Retry
through the existing runtime. Retry is never automatic; this local demo does
not certify provider cancellation.
**Next** — Step 4 receives the message.

---
Expand Down Expand Up @@ -236,7 +238,7 @@ The four names are `collect_context`, `search_synthesize`,

**Core code**
```ts
// registration — src/features/node-agent/components/toolUIs.tsx:55
// registration — src/features/node-agent/components/toolUIs.tsx:61
const ContextToolUI = makeAssistantToolUI<{ focus: string }, ContextToolResult>({
toolName: "collect_context",

Expand Down Expand Up @@ -345,19 +347,24 @@ function safe<T>(step: AgentStep, fn: () => T, fallback: T): T {
}
```

**Be told this plainly, because the UI does not tell you:**

- **There is no error state on screen.** `nodeAgentChatAdapter.run` has no
`catch`, and no component in the tree is a React error boundary. A throw inside
a rendered child unmounts the whole app to a blank page. That is exactly how
defect D1 presented.
- **There is no stop, cancel, or retry.** While a run is in flight the page has
one button, `Send`, and it is disabled. A user whose run misbehaves can only
reload, which discards the thread. Open as **D3**.
**Response recovery and remaining limits:**

- **Adapter failures are visible.** The existing assistant-ui runtime marks the
response incomplete; the thread presents a constant failure message, marks
unfinished tool cards failed, and offers explicit Retry. Earlier results stay.
- **Stop response ends display updates.** It preserves completed work and cannot
undo computation already performed by the local adapter or external work.
Retry replaces the current response through the native runtime, runs only on
an explicit action, and rejects duplicate immediate activation.
- **Rendering exceptions remain separate.** There is still no React render-error
boundary; a throw in a rendered child can unmount the app, as defect D1 showed.
- **"New Thread" does not exist here.** This runtime holds a single thread.
Reload discards the browser conversation.

These are recorded, with reproductions, in `promotion/PROMOTION_LOG.md` and
scored in `promotion/PRODUCT_GOAL.md` (conditions 2 and 5, both FAIL).
`promotion/PROMOTION_LOG.md` and `promotion/PRODUCT_GOAL.md` preserve their
historical defect reproductions and grades. Read `HANDOFF.md` for the current
D3 proof and remaining limits; no provider cancellation or full UI grade is
certified by this local response-recovery work.

**Input** — a step body that may throw.
**Output** — the fallback value, with the step marked `error`.
Expand Down Expand Up @@ -420,7 +427,7 @@ byte-stable.
| Change how sources are ranked | `searchAndSynthesize.ts` (`W_GROUNDING`, `W_RETRIEVAL`) | `npm test` |
| Change how a tool card looks | `components/toolUIs.tsx` | `npm run dev` |
| Add a fifth step | `nodeAgentRuntime.ts`, then a name in `toolUIs.tsx` **and** `nodeAgentChatAdapter.ts` | `npm test && npm run e2e:journey` |
| Give the app an error state | `NodeAgentDemoApp.tsx` (add a boundary) + `nodeAgentChatAdapter.ts` (add a catch) | `npm run e2e:journey` |
| Change response recovery | `components/NodeAgentThread.tsx` + `components/toolUIs.tsx` | `node e2e/current-consumer-recovery-proof.mjs "<installed generated app>" "<new proof output>"` |

Adding a step means touching three files, and the two name lists in Step 6 must
agree. That is the sharpest edge in this codebase.
Loading
Loading