You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 9049c69
Browse filesBrowse the repository at this point in the historyBrowse files
Declare what each frame projection reads and returns, and fix two copies that had drifted
A frame line can name a projection but a Markdown file cannot hold a function, so until now a host got only the name - how lastOrNone differs from resultMaybe was answerable only by reading our code, and that difference is part of the criterion.
src/frame-projections.ts now declares, for each of the 14 names, the cell it reads, the shape it returns, and what it promises on a missing value. The names and every from have one source of truth; decisions.ts supplies only function bodies, so a missing or extra implementation is a compile error.
This also corrects a real mistake from an earlier commit. canDeliver's evidence is declared in DECISION.md as writeEvidence, and the file wins over the code fallback - but writeEvidence returned an array while I had changed only the fallback, so the declared chars bound still never applied and the delivery gate's input was still unmarked. My test used the fallback, so it passed for the wrong layer. Both copies are now identical and a new guard compiles each node's file spec against its fallback and fails on any field that differs; I verified the guard by breaking it.
The projection test caught a phantom too: the published capability report listed a lastResult projection that exists nowhere. A report naming a capability that does not exist is worse than no report.
Copy file name to clipboardExpand all lines: TODO.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -169,7 +169,7 @@ What is missing is the only thing that would turn that into more than a claim: *
169
169
The pieces a second implementer would hit first, in the order we expect them to bite:
170
170
171
171
-[x]**Action semantics.***(2026-09-28. `src/action-semantics.ts` declares, for each of the 14 actions, the branch a host takes (`next`), whether it ends the tool loop, whether the run still has model calls afterwards, whether it needs evidence, and how many retries it allows. Exported through `jevloop/contract`; the table is in `docs/DECISION-CONTRACT.md` §3. **Checked against the runtime, not against itself** — `tests/action-semantics.test.ts` drives the loop once per action and asserts the observed behaviour, which caught two wrong assumptions while writing it. The field split that mattered: `stop`, `finish`, `answer` and `escalate` all end the **tool loop** and the run then generates anyway — a single `terminal` flag would have made a second implementer drop that generation.)*
172
-
-[ ]**Projection capability declarations.** A host must register `earlierMaybe`, `toolOrEmpty` and thirteen more; the only description of what each one means is our implementation. Write down what each projection reads and returns, or let the file declare it.
172
+
- [x] **Projection capability declarations.** *(2026-09-28. `src/frame-projections.ts` declares, for each of the 14 names, which state cell it reads, what shape it returns, and **what it promises on a missing value** — that last column is the point: `lastOrNone` sends `(还没有做过任何动作)` where `resultMaybe` sends an empty string, and the difference is part of the criterion, not cosmetics. The name list and every `from` have one source of truth; `decisions.ts` supplies only function bodies, so a missing or extra implementation is a compile error. `tests/frame-projections.test.ts` checks each `from` is a real state cell, each declared `returns` matches what the implementation returns, no projection is declared without being used, and the external host's capability list matches exactly — which is how this caught a phantom: the published report listed a `lastResult` projection that **exists nowhere**, not in the registry and not in `DECISION.md`. A capability report naming a capability that does not exist is worse than no report.)*
173
173
-[ ]**Dynamic provider inputs.**`dynamic: toolsFor(ctx) → candidates` says the provider reads the context; it does not say *which state cells* it reads, so a host cannot check the declaration against its own state.
174
174
-[ ]**Evidence and replay schema.**`frameDigest` and `requestDigest` are recorded, but there is no portable format for replaying one decision inside another runtime.
175
175
-[ ]**One real adopter.** An issue or a partial PR from a host we did not write — three nodes is enough — is worth more here than any further extension of the format.
0 commit comments