agentfootprint 9.84.0 → 9.86.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/CHANGELOG.md +438 -8
  2. package/dist/artifacts/present.js +21 -3
  3. package/dist/artifacts/present.js.map +1 -1
  4. package/dist/artifacts/wants.js +19 -4
  5. package/dist/artifacts/wants.js.map +1 -1
  6. package/dist/core/Agent.js +15 -4
  7. package/dist/core/Agent.js.map +1 -1
  8. package/dist/core/agent/AgentBuilder.js.map +1 -1
  9. package/dist/core/agent/buildAgentChart.js +5 -0
  10. package/dist/core/agent/buildAgentChart.js.map +1 -1
  11. package/dist/core/agent/buildDynamicAgentChart.js +22 -4
  12. package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
  13. package/dist/core/agent/buildToolRegistry.js +149 -1
  14. package/dist/core/agent/buildToolRegistry.js.map +1 -1
  15. package/dist/core/agent/selfCallNotice.js +20 -7
  16. package/dist/core/agent/selfCallNotice.js.map +1 -1
  17. package/dist/core/agent/skillBrains.js +3 -2
  18. package/dist/core/agent/skillBrains.js.map +1 -1
  19. package/dist/core/agent/stages/routeTurn.js +28 -3
  20. package/dist/core/agent/stages/routeTurn.js.map +1 -1
  21. package/dist/core/agent/stages/stepNudge.js +13 -4
  22. package/dist/core/agent/stages/stepNudge.js.map +1 -1
  23. package/dist/core/agent/stages/toolCalls.js +389 -58
  24. package/dist/core/agent/stages/toolCalls.js.map +1 -1
  25. package/dist/core/agent/stages/wrapUp.js +43 -6
  26. package/dist/core/agent/stages/wrapUp.js.map +1 -1
  27. package/dist/core/agent/window/currentRequest.js +4 -2
  28. package/dist/core/agent/window/currentRequest.js.map +1 -1
  29. package/dist/core/codeRunnerTool.js +25 -6
  30. package/dist/core/codeRunnerTool.js.map +1 -1
  31. package/dist/core/slots/buildToolsSlot.js +20 -4
  32. package/dist/core/slots/buildToolsSlot.js.map +1 -1
  33. package/dist/doors/skill-graph.js +4 -1
  34. package/dist/doors/skill-graph.js.map +1 -1
  35. package/dist/esm/artifacts/present.js +21 -3
  36. package/dist/esm/artifacts/present.js.map +1 -1
  37. package/dist/esm/artifacts/wants.js +19 -4
  38. package/dist/esm/artifacts/wants.js.map +1 -1
  39. package/dist/esm/core/Agent.js +15 -4
  40. package/dist/esm/core/Agent.js.map +1 -1
  41. package/dist/esm/core/agent/AgentBuilder.d.ts +2 -1
  42. package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
  43. package/dist/esm/core/agent/buildAgentChart.js +5 -0
  44. package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
  45. package/dist/esm/core/agent/buildDynamicAgentChart.js +22 -4
  46. package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
  47. package/dist/esm/core/agent/buildToolRegistry.d.ts +157 -0
  48. package/dist/esm/core/agent/buildToolRegistry.js +149 -1
  49. package/dist/esm/core/agent/buildToolRegistry.js.map +1 -1
  50. package/dist/esm/core/agent/selfCallNotice.d.ts +20 -7
  51. package/dist/esm/core/agent/selfCallNotice.js +20 -7
  52. package/dist/esm/core/agent/selfCallNotice.js.map +1 -1
  53. package/dist/esm/core/agent/skillBrains.d.ts +12 -4
  54. package/dist/esm/core/agent/skillBrains.js +3 -2
  55. package/dist/esm/core/agent/skillBrains.js.map +1 -1
  56. package/dist/esm/core/agent/stages/routeTurn.js +28 -3
  57. package/dist/esm/core/agent/stages/routeTurn.js.map +1 -1
  58. package/dist/esm/core/agent/stages/stepNudge.d.ts +13 -4
  59. package/dist/esm/core/agent/stages/stepNudge.js +13 -4
  60. package/dist/esm/core/agent/stages/stepNudge.js.map +1 -1
  61. package/dist/esm/core/agent/stages/toolCalls.d.ts +171 -0
  62. package/dist/esm/core/agent/stages/toolCalls.js +385 -57
  63. package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
  64. package/dist/esm/core/agent/stages/wrapUp.d.ts +33 -2
  65. package/dist/esm/core/agent/stages/wrapUp.js +41 -5
  66. package/dist/esm/core/agent/stages/wrapUp.js.map +1 -1
  67. package/dist/esm/core/agent/types.d.ts +21 -4
  68. package/dist/esm/core/agent/window/currentRequest.d.ts +4 -2
  69. package/dist/esm/core/agent/window/currentRequest.js +4 -2
  70. package/dist/esm/core/agent/window/currentRequest.js.map +1 -1
  71. package/dist/esm/core/codeRunnerTool.js +25 -6
  72. package/dist/esm/core/codeRunnerTool.js.map +1 -1
  73. package/dist/esm/core/slots/buildToolsSlot.d.ts +1 -1
  74. package/dist/esm/core/slots/buildToolsSlot.js +20 -4
  75. package/dist/esm/core/slots/buildToolsSlot.js.map +1 -1
  76. package/dist/esm/doors/skill-graph.d.ts +1 -1
  77. package/dist/esm/doors/skill-graph.js +4 -1
  78. package/dist/esm/doors/skill-graph.js.map +1 -1
  79. package/dist/esm/events/payloads.d.ts +26 -2
  80. package/dist/esm/index.js +6 -5
  81. package/dist/esm/index.js.map +1 -1
  82. package/dist/esm/lib/injection-engine/index.d.ts +1 -1
  83. package/dist/esm/lib/injection-engine/index.js +4 -1
  84. package/dist/esm/lib/injection-engine/index.js.map +1 -1
  85. package/dist/esm/lib/injection-engine/skillGraph.d.ts +56 -0
  86. package/dist/esm/lib/injection-engine/skillGraph.js +29 -3
  87. package/dist/esm/lib/injection-engine/skillGraph.js.map +1 -1
  88. package/dist/esm/lib/injection-engine/skillSteps.d.ts +20 -1
  89. package/dist/esm/lib/injection-engine/skillSteps.js +24 -3
  90. package/dist/esm/lib/injection-engine/skillSteps.js.map +1 -1
  91. package/dist/esm/lib/injection-engine/skillToolDescriptors.d.ts +18 -0
  92. package/dist/esm/lib/injection-engine/skillToolDescriptors.js +151 -11
  93. package/dist/esm/lib/injection-engine/skillToolDescriptors.js.map +1 -1
  94. package/dist/esm/lib/injection-engine/types.d.ts +12 -10
  95. package/dist/esm/lib/injection-engine/types.js +5 -4
  96. package/dist/esm/lib/injection-engine/types.js.map +1 -1
  97. package/dist/esm/lib/saidByPerson.d.ts +48 -15
  98. package/dist/esm/lib/saidByPerson.js +52 -17
  99. package/dist/esm/lib/saidByPerson.js.map +1 -1
  100. package/dist/esm/lib/spokenIds.d.ts +52 -0
  101. package/dist/esm/lib/spokenIds.js +11 -0
  102. package/dist/esm/lib/spokenIds.js.map +1 -0
  103. package/dist/esm/lib/trace-toolpack/traceToolpack.js +12 -5
  104. package/dist/esm/lib/trace-toolpack/traceToolpack.js.map +1 -1
  105. package/dist/esm/maps/engagement/parkCard.js +7 -1
  106. package/dist/esm/maps/engagement/parkCard.js.map +1 -1
  107. package/dist/index.js +6 -5
  108. package/dist/index.js.map +1 -1
  109. package/dist/lib/injection-engine/index.js +5 -2
  110. package/dist/lib/injection-engine/index.js.map +1 -1
  111. package/dist/lib/injection-engine/skillGraph.js +31 -4
  112. package/dist/lib/injection-engine/skillGraph.js.map +1 -1
  113. package/dist/lib/injection-engine/skillSteps.js +24 -3
  114. package/dist/lib/injection-engine/skillSteps.js.map +1 -1
  115. package/dist/lib/injection-engine/skillToolDescriptors.js +151 -11
  116. package/dist/lib/injection-engine/skillToolDescriptors.js.map +1 -1
  117. package/dist/lib/injection-engine/types.js +5 -4
  118. package/dist/lib/injection-engine/types.js.map +1 -1
  119. package/dist/lib/saidByPerson.js +53 -18
  120. package/dist/lib/saidByPerson.js.map +1 -1
  121. package/dist/lib/spokenIds.js +15 -0
  122. package/dist/lib/spokenIds.js.map +1 -0
  123. package/dist/lib/trace-toolpack/traceToolpack.js +12 -5
  124. package/dist/lib/trace-toolpack/traceToolpack.js.map +1 -1
  125. package/dist/maps/engagement/parkCard.js +7 -1
  126. package/dist/maps/engagement/parkCard.js.map +1 -1
  127. package/dist/types/artifacts/present.d.ts.map +1 -1
  128. package/dist/types/artifacts/wants.d.ts.map +1 -1
  129. package/dist/types/core/Agent.d.ts.map +1 -1
  130. package/dist/types/core/agent/AgentBuilder.d.ts +2 -1
  131. package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
  132. package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
  133. package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
  134. package/dist/types/core/agent/buildToolRegistry.d.ts +157 -0
  135. package/dist/types/core/agent/buildToolRegistry.d.ts.map +1 -1
  136. package/dist/types/core/agent/selfCallNotice.d.ts +20 -7
  137. package/dist/types/core/agent/selfCallNotice.d.ts.map +1 -1
  138. package/dist/types/core/agent/skillBrains.d.ts +12 -4
  139. package/dist/types/core/agent/skillBrains.d.ts.map +1 -1
  140. package/dist/types/core/agent/stages/routeTurn.d.ts.map +1 -1
  141. package/dist/types/core/agent/stages/stepNudge.d.ts +13 -4
  142. package/dist/types/core/agent/stages/stepNudge.d.ts.map +1 -1
  143. package/dist/types/core/agent/stages/toolCalls.d.ts +171 -0
  144. package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
  145. package/dist/types/core/agent/stages/wrapUp.d.ts +33 -2
  146. package/dist/types/core/agent/stages/wrapUp.d.ts.map +1 -1
  147. package/dist/types/core/agent/types.d.ts +21 -4
  148. package/dist/types/core/agent/types.d.ts.map +1 -1
  149. package/dist/types/core/agent/window/currentRequest.d.ts +4 -2
  150. package/dist/types/core/agent/window/currentRequest.d.ts.map +1 -1
  151. package/dist/types/core/slots/buildToolsSlot.d.ts +1 -1
  152. package/dist/types/core/slots/buildToolsSlot.d.ts.map +1 -1
  153. package/dist/types/doors/skill-graph.d.ts +1 -1
  154. package/dist/types/doors/skill-graph.d.ts.map +1 -1
  155. package/dist/types/events/payloads.d.ts +26 -2
  156. package/dist/types/events/payloads.d.ts.map +1 -1
  157. package/dist/types/index.d.ts.map +1 -1
  158. package/dist/types/lib/injection-engine/index.d.ts +1 -1
  159. package/dist/types/lib/injection-engine/index.d.ts.map +1 -1
  160. package/dist/types/lib/injection-engine/skillGraph.d.ts +56 -0
  161. package/dist/types/lib/injection-engine/skillGraph.d.ts.map +1 -1
  162. package/dist/types/lib/injection-engine/skillSteps.d.ts +20 -1
  163. package/dist/types/lib/injection-engine/skillSteps.d.ts.map +1 -1
  164. package/dist/types/lib/injection-engine/skillToolDescriptors.d.ts +18 -0
  165. package/dist/types/lib/injection-engine/skillToolDescriptors.d.ts.map +1 -1
  166. package/dist/types/lib/injection-engine/types.d.ts +12 -10
  167. package/dist/types/lib/injection-engine/types.d.ts.map +1 -1
  168. package/dist/types/lib/saidByPerson.d.ts +48 -15
  169. package/dist/types/lib/saidByPerson.d.ts.map +1 -1
  170. package/dist/types/lib/spokenIds.d.ts +53 -0
  171. package/dist/types/lib/spokenIds.d.ts.map +1 -0
  172. package/dist/types/lib/trace-toolpack/traceToolpack.d.ts.map +1 -1
  173. package/dist/types/maps/engagement/parkCard.d.ts.map +1 -1
  174. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,423 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [9.86.0] - 2026-09-05
11
+
12
+ Every hand-counted list in 9.84.0 and 9.85.0 was short by one or two.
13
+
14
+ "Five classes of `role: 'user'` message are authored by this library" — seven
15
+ were. "Reachability OR posture" — three arms refuse. "Sixty configurations,
16
+ crossing every source" — the cross skipped four of the seven sources it named,
17
+ and there are seventy-six. The rules that catch a sentence which outlives its
18
+ moment were a transcript of the wordings that had already escaped: thirteen of
19
+ fifteen plausible forward-looking sentences walked straight through them.
20
+
21
+ None of those was a typo. Each was a fact the library computed in one place and
22
+ re-derived, by hand, wherever a second consumer needed it — and a hand-derived
23
+ list is a list that is short the day after somebody adds the next case. Three
24
+ of them are now WALKS rather than counts: the user-turn producers are parsed out
25
+ of `src/` with the TypeScript compiler, every sentence-shaped literal in `src/`
26
+ is run through the model-facing rules with a file and a line on failure, and the
27
+ offer/dispatch cross iterates its source list whole instead of filtering it.
28
+ Two more are single owners: one function answers "is this `read_skill` target
29
+ the cursor?", and one scope key answers "which skill ids may this role see?".
30
+
31
+ ### Fixed
32
+
33
+ - **`read_skill` refusals answered for a fact nobody owned.** Five call sites
34
+ needed to know that `makeReachableSkills` filters the cursor out of its own
35
+ successor set — correct for a MOVE, silent about a READ. Three of them wrote
36
+ their own `requested === cursor` line. Two never heard: a tool proposing
37
+ `propose-transition` back to the cursor's own skill was refused as unreachable,
38
+ and the `skill_read` permission gate was asked to grant a capability the model
39
+ was already exercising, then told the model that its own skill was "not
40
+ available in this context".
41
+
42
+ `classifySkillTarget({ cursor, target, hops, open })` now owns it, returning
43
+ `'self' | 'hop' | 'open' | 'unreachable'`. It is a pure function in the
44
+ injection engine, exported through the `agentfootprint/context` barrel and the
45
+ `agentfootprint/skill-graph` door — the same function object through both, so a
46
+ foreign host cannot re-derive it wrongly either. The five consumers switch on
47
+ it: the gate arm, `describeOffer`, the tool-effects judge, the `skill_read`
48
+ permission gate, and the refusal composer. `makeReachableSkills` keeps its own
49
+ exclusion — it is the PRODUCER of the hop set, and excluding the cursor is what
50
+ a move means — and its doc comment now says the exclusion is about movement and
51
+ sends the next reader to `classifySkillTarget`.
52
+
53
+ - **A refusal could name a skill the caller's own policy hides.** Role visibility
54
+ was a property of one builder: `Agent.hiddenSkillIdsNow()` fed
55
+ `buildReadSkillTool` and nothing else. So the description named nothing hidden
56
+ while the gate, one stage downstream, composed its refusals — and filled
57
+ `skill.rejected.allowed` — from the graph's raw sets.
58
+
59
+ The tools slot now resolves the hidden set once per iteration, publishes it on
60
+ `scope.hiddenSkillIds`, and both chart shapes bubble it. The gate keeps two sets
61
+ on purpose: the RAW one it judges with, and the filtered one it speaks with. It
62
+ judges with the raw set because a narrowing may take a schema off the wire and
63
+ may never take a name out of the dispatch map — filtering admission would remove
64
+ a capability, which the monotone rule forbids. In practice a hidden id never
65
+ reaches the gate, because the same checker denies it upstream; the filter is what
66
+ makes that true by construction rather than by coincidence.
67
+
68
+ - **Two refusal composers that contradicted each other forty lines apart are one.**
69
+ `skillRefusal` and `postureRefusal` are replaced by `composeReadSkillRefusal`,
70
+ and every arm of it is a past fact about the one call it names. Gone with them:
71
+ "from here" (deixis — a different place on every re-read), "Pick one of these, or
72
+ finish" (an exhortation in a string that persists for the rest of the run), and a
73
+ posture arm that named a hop the very next arm would have declined. A refusal now
74
+ opens `read_skill("X") was not granted on that call:` and every clause after it
75
+ refers back to that call.
76
+
77
+ - **`Unknown tool: X` told the model it was wrong and never what would have
78
+ worked.** Both dispatch doors now compose one exported `unknownToolResult`, which
79
+ names the dispatch roster: `Unknown tool 'X' on that call. Tool names that
80
+ resolved to an implementation on that call: …`, or, with an empty roster, that
81
+ none did. The leading `Unknown tool` token is preserved, so every matcher on it
82
+ is untouched.
83
+
84
+ It says *resolved*, not *could be dispatched*, because two gates sit between
85
+ resolution and a tool running — the `tool_call` permission check and the
86
+ middleware chain — and neither is asked to phrase an error. And the roster is
87
+ role-filtered before it is named: it used to read the dispatch map raw and could
88
+ name a tool belonging to a skill the caller's own policy hides, which is the
89
+ leak the refusals had just closed, one sentence over. `buildToolRegistry` now
90
+ returns `toolDeclaringSkills` (tool name → the skills that declare it) from the
91
+ walk it was already doing, and a name is withheld only when EVERY declaring
92
+ skill is hidden — a tool two skills share stays named. Dispatch is untouched.
93
+
94
+ - **A filtered-empty list was reported as an empty one — a Lens denying what the
95
+ Fold holds.** Three sentences branched on `length > 0` over an already-filtered
96
+ array, so "the graph held nothing" and "the role filter emptied it" composed the
97
+ same words. A cursor whose only declared hop was hidden answered `read_skill`
98
+ with *"No skill was reachable from 'alpha' when that call was made."* while the
99
+ graph was routing `alpha`; a `'guard'` menu whose every id had been hidden since
100
+ the turn started said *"no menu was outstanding when that call was made.
101
+ Declared routes moved the cursor instead."* — two false clauses in one breath.
102
+
103
+ A model told the map is a dead end stops asking for the door it may not be
104
+ shown, and the checker cannot see it: every one of those sentences passes
105
+ `unprovable()`, because the defect is in what the composer was handed, not in
106
+ how it was worded. So the fact is now a type. `SpokenIds` carries both halves of
107
+ a filtered set — `named`, and `held` for whether the unfiltered set held
108
+ anything — and `held` is required, so the compiler asks every caller the
109
+ question every call site forgot to answer. Where a filter empties a set the
110
+ clause is OMITTED. Omission is free and always true; the negative is a denial.
111
+
112
+ The fourth sentence was the one the model reads to CHOOSE. `describeOffer`
113
+ computed its columns from an already-filtered catalog, so a cursor whose only
114
+ declared hop is hidden was told *"Nothing is reachable from here — answer with
115
+ the skill you are in, or finish."* while the graph held that edge. It classifies
116
+ the hop set over the unfiltered catalog now and drops the clause when the filter
117
+ is what emptied it; with nothing wired out at all the sentence still stands,
118
+ because that absence is one the description has evidence for. Reaching it meant
119
+ moving `SpokenIds`/`spoken` to `src/lib/spokenIds.ts`: it lived in the tool-calls
120
+ stage, on the wrong side of the skill-graph fence, so the description — composed
121
+ inside `src/lib/injection-engine/`, which may not import the agent loop — was the
122
+ one surface that could not use the fact its own refusals were repaired with.
123
+
124
+ - **Under a `.tree()` with nothing open, `read_skill` is no longer offered.** A
125
+ tree routes by predicate on every iteration and keeps no cursor, so the tool had
126
+ nothing it could do and a menu of one refusal is worse than no menu. The schema
127
+ leaves the request; the NAME stays in the dispatch map, which is the same law as
128
+ everywhere else. With open skills present, the description explains the tree and
129
+ lists exactly what a pick can open, instead of printing "Nothing is reachable
130
+ from here".
131
+
132
+ - **Two library-authored user turns were credited to a person.** The out-of-budget
133
+ wrap-up instruction and the stepped-skill nudge both append to `scope.history`
134
+ with `role: 'user'` and took no registered opening, so `isSaidByPerson` said a
135
+ person wrote them. Two things followed. The window's refusal engine could pin
136
+ "the current request" on the framework's own wrap-up instruction and drop the
137
+ real request underneath it. And a routing rule written the documented way —
138
+ `saidByPerson(ctx).some((m) => m.content.includes(…))` — matched on the library's
139
+ own bookkeeping: the wrap-up said "Do not request tools", and the nudge names a
140
+ skill id and every unrun step's tool name.
141
+
142
+ Both are registered now, and `LIBRARY_AUTHORED_PREFIXES` holds all six openings
143
+ frozen, so the writer and the recogniser read one constant. Both sentences were
144
+ also rewritten: each was composed once and re-read on every later call of the
145
+ turn, which made their present-tense clauses predictions.
146
+
147
+ - **Three trace-toolpack results said "this call" and "right now".** They are
148
+ anchored to the call they answer, in the past tense — including the one arm the
149
+ new deictic-container rule caught the first time it was ever composed.
150
+
151
+ - **`escalation` counts three kinds of refusal, and its docs named two.**
152
+ "Reachability OR posture" is wrong in the JSDoc behind `EscalationPolicy` and
153
+ `SkillGraphOptions`, in the `skill.escalated` payload doc and on the skills page:
154
+ the counter fires beside all three `skill.rejected` emit sites, self-call
155
+ included. No behaviour changed — the self-call site has counted since 9.84.0,
156
+ deliberately.
157
+
158
+ ### Added
159
+
160
+ - **A WALK over every `role: 'user'` construction site in `src/`.**
161
+ `test/lib/injection-engine/userTurnProducers.test.ts` parses the tree with the
162
+ TypeScript compiler (a `PropertyAssignment` of `role: 'user'`, so type members
163
+ and comments quoting the string are not counted) and requires every site to be
164
+ classified as an authored frame, a person's own words, or never-in-history, each
165
+ with a written reason. **Thirty-five** sites are classified today: six authored
166
+ frames, seven person, twenty-two never-in-history. Sites are keyed by file with
167
+ the per-file COUNT asserted, so a new producer inside an already-listed file
168
+ fails as loudly as one in a new file. One producer the parser cannot see — the
169
+ message an injection delivers, whose role is copied off the `Injection` — is
170
+ named in the header and pinned by its `injectedBy` marker instead.
171
+
172
+ - **The model-facing checker judges SHAPE, not just remembered wordings.** Four
173
+ new rules: a present-tense copula with a capability noun, deictic-present
174
+ adverbs, second-person effect verbs, and a standing imperative at a clause
175
+ start. Fifteen plausible forward-looking sentences were written out and put
176
+ to the rules: "You are currently in 'alpha'", "Calling read_skill switches you
177
+ to beta", "The following tools are available to you: …", "Nothing is live in
178
+ this scope at the moment". All fifteen are caught by the rules as they stand,
179
+ and the suite asserts exactly that. **Thirteen** of them passed against the
180
+ rule list AS IT STOOD BEFORE THIS RELEASE — the number that motivated the
181
+ work, measured once against a list this tree no longer contains, so it is a
182
+ record of why the rules changed rather than something a run here can
183
+ reproduce. `exemptBecause` is now structurally
184
+ required: `BannedClause` is a discriminated union, and because the root
185
+ `tsconfig.json` excludes `test/`, that is proven where it can actually be
186
+ compiled — `test/type-regressions/`.
187
+
188
+ - **A WALK over every sentence-shaped literal in `src/`.** The registry's own
189
+ header used to say the gap it could not close was "a scan of `src/` … and this
190
+ is not that". `test/modelFacingScan.test.ts` is that: it parses every `.ts` file
191
+ under `src/` with the TypeScript compiler, folds `+` chains and template holes,
192
+ runs each literal through the rules at the persistent lifetime, and fails with
193
+ `file:line` unless the file's flagged literals are accounted for in a ledger of
194
+ **eighty-four files / one hundred and sixty-three literals**, every entry naming
195
+ where the string is delivered and how many literals it covers. Per-file counts
196
+ are the guard again. Four things it cannot see are stated in its header rather
197
+ than left to be found: a sentence assembled across statements, text that lives
198
+ in data rather than in `src/`, literals under twenty-five characters, and any
199
+ falsehood that avoids all the shapes.
200
+
201
+ Its ledger carries an `unrepaired` bucket of **thirty-three** literals across
202
+ thirteen entries that are model-facing, persistent and correctly caught, and
203
+ that were left alone because each needs its own tests. They are named with their
204
+ delivery site, so the bucket is a work list rather than a pardon. The bucket's
205
+ arithmetic is asserted by the suite itself — the counts above come from a run,
206
+ not from a report, which is the failure this whole entry is about.
207
+
208
+ - **Five live producers are registered and read.** The `read_skill` refusal
209
+ composer (every arm), `unknownToolResult`, the trace toolpack's inspection
210
+ results, and — closing the gap 9.85.0's registry named — the wrap-up and
211
+ stepped-skill frames at a shared `INJECTED_TURN` surface.
212
+
213
+ - **The offer/dispatch cross iterates its source list whole.** `frameworkCases()`
214
+ re-derived a source list inside the walk —
215
+ `CLAIMANTS.filter((c) => ['static', 'provider', 'skill-active'].includes(c.id))`
216
+ — so a second hand-written list of sources existed with nothing keeping it in
217
+ sync with the first, and 9.85.0's "crosses every source" was false. That mattered
218
+ because the framework's four auto-attach reservations each read a DIFFERENT
219
+ build-time list, so which source holds a contested name is precisely what decides
220
+ whether a reservation can see it. The walk goes from **sixty configurations to
221
+ seventy-six** and from **thirty-six divergence rows to forty-six**; all ten new
222
+ rows carry a hand-written, checked `tolerated`. Three new tests own what was
223
+ previously true only because somebody had typed it: that every claimant is
224
+ crossed against every auto-attach name, that the header's arithmetic equals the
225
+ recorded case count, and that a placeholder `tolerated` is refused (empty,
226
+ `todo`/`tbd`/`fixme`/`xxx` on a word boundary in any case, or under forty
227
+ characters — a floor on effort, not a measure of truth).
228
+
229
+ Eight of the ten are already-recorded seams reached through a source that had
230
+ never been crossed, and say so. Two are defects nobody had recorded and are
231
+ written up as entries 4 and 5 of `docs/design/2026-09-recorded-not-built.md`
232
+ rather than papered over: `.selfExplain()` reserves its trace-tool names against
233
+ `this.registry` and never `this.injectionList`, making it the one auto-attach
234
+ family with no net at all against a skill's `tools: []`; and the misattributed
235
+ shadow report can now name a `skill-scoped:self-explain` provider — one the
236
+ consumer did not write and cannot open — as the file to go look at.
237
+
238
+ - **`report-misattributed` rows carry their attribution in the row id.** A shadow
239
+ event's meaning lives in its `schemaFromId`/`dispatchToId`, and the row was keyed
240
+ on case + tool + epoch, so two reports naming different sources in one epoch — a
241
+ strictly worse fact than one wrong report — collapsed into one `Map` entry and
242
+ vanished.
243
+
244
+ - **`SkillRejectedPayload.allowed` is what the model was actually told.** Role-
245
+ filtered rather than the graph's raw set. Shape unchanged; only agents with a
246
+ `PermissionChecker` governing `'skill_read'` see any difference. The field's own
247
+ JSDoc says so at the call site, which is the doc a consumer actually reads.
248
+
249
+ - **`ToolRegistryArtifacts.toolDeclaringSkills`** — tool name → the ids of the
250
+ skills whose `inject.tools` carry it, recorded on the walk `buildToolRegistry`
251
+ was already doing and thrown away. Empty for an agent whose skills carry no
252
+ tools. Its one consumer is the unknown-tool roster's role filter; it exists so
253
+ that consumer does not walk `Agent.injections` a second time to re-derive what
254
+ this file already knew.
255
+
256
+ - **`ToolEffectPayload.stay?: true`** on `agentfootprint.tools.effect` — a
257
+ `propose-transition` naming the cursor's own skill is accepted as a no-op.
258
+ Deliberately not a fourth `outcome`, so an exhaustive consumer switch keeps
259
+ compiling.
260
+
261
+ - **`AgentState.hiddenSkillIds?: readonly string[]`** — the per-iteration
262
+ role-hidden set, written by the tools slot and read by the `read_skill` gate.
263
+
264
+ - **`ReadSkillOffer.treeRouted?: boolean`** — declares the mounted graph a decision
265
+ tree, which is what lets the descriptor withhold the offer.
266
+
267
+ ### Two decisions worth stating plainly
268
+
269
+ - **A self-call at a MOUNTED cursor is answered BEFORE the permission gate**, because
270
+ it exercises no capability. `read_skill` naming the cursor's own skill activates
271
+ nothing and moves nothing, so there is no grant for a `PermissionChecker` to make or
272
+ withhold; asking it produced a denial about the one skill whose body was already in
273
+ that call's system prompt. The skip stops at a PARKED cursor, and deliberately: a
274
+ park suppresses a map's contribution without moving the cursor, so the gate below
275
+ reads the same id as a RE-ENGAGEMENT and puts the body and its tools back on the
276
+ wire — which is a capability, and the policy's question to answer. One predicate,
277
+ `atMountedCursor`, is what both gates ask. Every other id still goes to the policy.
278
+ The refusal BUDGET is
279
+ unchanged and still counts the self-call, including the `surfaceMode: 'both'`
280
+ re-read that returns the body — the 9.84.0 argument stands, and it is about the
281
+ loop rather than about the wording: a model that keeps asking the graph where it
282
+ stands instead of working is exactly the stuck run escalation exists for.
283
+
284
+ - **A `propose-transition` naming the cursor's own skill is a STAY**, accepted as a
285
+ no-op with `stay: true` on the event and no refusal on the result. The tool asked
286
+ for a state the run is already in; there is nothing to move and nothing to refuse.
287
+
288
+ ### Deliberately not changed
289
+
290
+ - **The three `STATED:` prose pins** in `src/core/agent/buildToolRegistry.ts` are
291
+ untouched, word for word. `test/core/agent/epoch-laws.test.ts` and
292
+ `test/core/agent/toolDivergenceWalk.test.ts` both read them.
293
+ - **The escalation budget still counts `'both'`-mode self-call re-reads**, per the
294
+ argument above.
295
+ - **The grounding gate** — item 5 of the "Offer, Not Dispatch" review — is a new
296
+ DIAL, not a fix for anything here, and is not in this release.
297
+ - **The flat default is not narrowed.** `scopeTools` stays `false` until 10.0.0.
298
+ - **`isLibraryAuthoredTurn`** (the evidence gate's exempt corpus) is deliberately
299
+ narrower than `isSaidByPerson` and was not widened to the two new frames. It
300
+ decides who SUPPLIED a value, not who wrote a turn; widening it would change which
301
+ values the evidence gate exempts, with no finding behind it.
302
+
303
+ ### Changelog corrections
304
+
305
+ A reader auditing this project by its changelog has to be able to trust the older
306
+ entries, so six sentences in 9.84.0 and 9.85.0 are corrected in place, each marked
307
+ where it stands:
308
+
309
+ - **9.84.0** — _"Five classes of `role: 'user'` message"_: seven kinds are
310
+ library-authored; the wrap-up instruction and the stepped-skill nudge went
311
+ unregistered until this release.
312
+ - **9.84.0** — _"The window's own refusal engine has always applied that rule"_: it
313
+ applied a three-class version, and 9.84.0 widened it to five.
314
+ - **9.84.0** — _"a step or park hold-out says the tools were withheld rather than
315
+ naming them"_: the withheld arm names the declared tools, and a parked cursor
316
+ never reaches the notice at all.
317
+ - **9.85.0** — the fifth _"model-facing sentence"_ bullet credited 9.85.0 with a
318
+ `read_skill` description fix that shipped in 9.84.0, and quoted a sentence that
319
+ existed only in a source comment. Removed, with the reason left in its place; the
320
+ count above it is now four.
321
+ - **9.85.0** — _"drives a real run per configuration. Sixty configurations,
322
+ thirty-six divergences"_: forty of seventy-six are driven, twenty-six are refused
323
+ at build and ten are not constructible; the enumeration it replaced was a
324
+ development draft, never a shipped list.
325
+ - **9.85.0** — law 1 was restated unscoped. It is scoped to the tools
326
+ `buildToolRegistry` routes, with the shadow seam and the walk as its recorded
327
+ exceptions.
328
+
329
+ ## [9.85.0] - 2026-09-04
330
+
331
+ A sentence composed once and read many times is not a fact — it is a prediction.
332
+
333
+ 9.84.0 fixed one such sentence and shipped a checker for the class. The checker
334
+ covered two surfaces. Five more sentences matching its own existing rule were
335
+ live elsewhere in the tree, unread by it, because coverage was decided by which
336
+ suite happened to import the helper. That is the same defect one level up: a
337
+ guard asserting a boundary it cannot verify.
338
+
339
+ ### Fixed
340
+
341
+ - **Four model-facing sentences that outlive the moment they were true.** Each is
342
+ now anchored to one named call, in the past tense, after tracing it to its
343
+ delivery point to confirm it really is re-read:
344
+
345
+ - `artifacts/present.ts` and `artifacts/wants.ts` — _"Nothing is live in this
346
+ run's scope right now"_ and its sibling inventory, _"Live refs in scope: …"_.
347
+ A census goes wrong in BOTH directions on re-read: entries sweep, new ones
348
+ appear.
349
+ - `core/codeRunnerTool.ts` — _"staged into this session"_. The anchor resolves,
350
+ and goes on resolving; the defect is that it resolves to a scope holding many
351
+ calls, so a per-call report cannot say which call it describes.
352
+ - `maps/engagement/parkCard.ts` — _"Its instructions and its tools are not being
353
+ sent right now"_, on a card that rides every call while a map is parked. Its
354
+ falsifier is compose order, not staleness: the card is written in the
355
+ injection-engine pass and the tools slot that acts on the park runs after it.
356
+
357
+ _Corrected in 9.86.0._ A fifth bullet stood here, crediting 9.85.0 with the
358
+ `read_skill` description fix and quoting _"You do not need read_skill to go on
359
+ using it"_ as a wording it had replaced. `skillToolDescriptors.ts` has no
360
+ non-comment change between `v9.84.0` and `v9.85.0`: that fix shipped in 9.84.0,
361
+ where it is also recorded, and the quoted sentence lived only inside a source
362
+ comment — no release ever put it on the wire. What 9.85.0 added to that file is
363
+ the LENS LAW block above `describeOffer`, which is a Documentation change.
364
+
365
+ ### Added
366
+
367
+ - **Surfaces carry `channel` and `lifetime` separately.** Where a string is
368
+ delivered and how long it lives do not correlate: system text is rebuilt every
369
+ request, so a present-tense clause in it is a fact; a tool result persists, so
370
+ the same clause is a forecast. The rules judge lifetime. Both existing
371
+ exemptions turned out to be lifetime claims wearing channel clothes and are now
372
+ derivable rather than asserted.
373
+
374
+ - **A producer registry that fails when a surface is not exercised.** Coverage
375
+ decided by which suite imports a helper is a habit, not a guarantee. Its header
376
+ states what a green run does not prove: hand-maintained rows cannot see a
377
+ producer nobody registered.
378
+
379
+ - **The offer/dispatch divergence list is walked, not written.**
380
+ `test/core/agent/toolDivergenceWalk.test.ts` crosses every source that can put
381
+ a name on the wire or answer to one — static, provider, MCP, always-on skill,
382
+ active skill, inactive skill, stepped skill — against six narrowing states and
383
+ the framework's auto-attach names. _Corrected in 9.86.0:_ at 9.85.0 the
384
+ auto-attach cross did NOT reach every source — it filtered `CLAIMANTS` down to
385
+ three of the seven — and the walk does not drive a real run per configuration.
386
+ Both are true of the walk as it stands after 9.86.0 widened it, with these
387
+ counts. Of its **seventy-six** configurations, **forty** are driven
388
+ as real runs (thirty-six divergent, four clean), **twenty-six** are refused at
389
+ build — which is the walk exercising a refusal, and its `because` records the
390
+ refusal's first line — and **ten** are not constructible at all, so no run is
391
+ attempted. **Forty-six** divergence rows come out of the forty driven, each
392
+ with a mechanically derived cause and a stated reason it is tolerated. New
393
+ fails. Disappeared fails. Vacuous fails, and is unbaselineable.
394
+
395
+ It replaced a hand-written enumeration that claimed completeness and was
396
+ falsified three rounds running — _corrected in 9.86.0:_ that enumeration was
397
+ drafted and falsified during this work, and no released version ever carried
398
+ it, so the walk shipped in place of a draft rather than of a shipped list.
399
+
400
+ It then found three classes nobody seeded: a
401
+ provider tool whose name a registry holder already owns is dead in both
402
+ directions and the shadow report cannot see it; the auto-attach names disagree
403
+ about what they refuse; and `selfExplain` is a fourth family whose reservation
404
+ reads only the static registry.
405
+
406
+ ### Documentation
407
+
408
+ - **Three laws stated where the code lives**, epoch-scoped, after two earlier
409
+ phrasings were false in shipped configurations. Law 1, as the source states it
410
+ and _corrected here in 9.86.0_, is SCOPED: **among the tools `buildToolRegistry`
411
+ routes**, every offered capability resolves to a dispatchable implementation
412
+ with stable identity for that epoch — same-epoch offer implies same-epoch
413
+ dispatch. It is not a claim about the whole wire, and the source names its
414
+ recorded exceptions rather than implying there are none: the SHADOW SEAM (the
415
+ wire list is merged one layer out in `buildToolsSlot` and carries provider
416
+ schemas these maps never hold), with the full enumeration delegated to
417
+ `test/core/agent/toolDivergenceWalk.test.ts`. The second clause is unscoped and
418
+ unchanged: attention may alter the offer, but omission from the offer must not
419
+ be presented as proof of permanent capability loss. Only static skill-registry
420
+ tools are known to remain dispatchable after leaving the offer.
421
+
422
+ - **`docs/design/2026-09-recorded-not-built.md`** — three real defects with
423
+ reproductions, deliberately not fixed: an inactive skill's tool shadows in
424
+ silence, the shadow report names the wrong source, and `skip_step` is
425
+ claimable by a provider. Each names what deciding to fix it would cost.
426
+
10
427
  ## [9.84.0] - 2026-09-03
11
428
 
12
429
  ### Fixed
@@ -30,9 +447,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
30
447
  stands and which tools it could call, taken from the merged wire list the LLM
31
448
  stage actually sent, intersected with the skill's own declared tools — never
32
449
  from the declaration alone. Every configuration that would make that false has
33
- its own wording: a skill declaring no tools says so, a step or park hold-out
34
- says the tools were withheld rather than naming them, and a call whose wire
35
- cannot be established says nothing about tools at all. Mechanically it is still
450
+ its own wording: a skill declaring no tools says so, a hold-out names the
451
+ declared tools and states that they were withheld — _corrected in 9.86.0:_ this
452
+ read "a step or park hold-out says the tools were withheld rather than naming
453
+ them", and the withheld arm does name them; a PARK never reaches the notice at
454
+ all, because a self-call at a parked map member is a re-engagement request
455
+ (9.59.0) answered on an earlier arm — and a call whose wire cannot be
456
+ established says nothing about tools at all. Mechanically it is still
36
457
  a rejection — no activation, no cursor move, and the refusal budget still
37
458
  counts it, because a self-call _loop_ is exactly the stuck model that budget
38
459
  exists to escalate.
@@ -81,12 +502,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
81
502
  ### Added
82
503
 
83
504
  - **`saidByPerson(ctx)` / `isSaidByPerson(msg)` — telling what a person said from
84
- what the library wrote.** Five classes of `role: 'user'` message are authored
85
- by this library, not by a person: the compaction frame, the drop notice (whose
505
+ what the library wrote.** _Corrected in 9.86.0:_ this said "five classes", and
506
+ **seven** kinds of `role: 'user'` message are authored by this library, not by a
507
+ person. Five are registered here: the compaction frame, the drop notice (whose
86
508
  text names tools), the schema-check and evidence-check corrections, and any
87
- injection-delivered message. The window's own refusal engine has always applied
88
- that rule; a `when` predicate could not, because `InjectionContext.history`
89
- exposes only `{ role, content, toolName? }`. An author writing an entry rule
509
+ injection-delivered message. The out-of-budget wrap-up instruction and the
510
+ stepped-skill nudge were library-authored the whole time and went unregistered
511
+ until 9.86.0. _Also corrected:_ the window's own refusal engine had not "always
512
+ applied that rule" — it applied a THREE-class version (drop notice, compaction
513
+ frame, injection-delivered), and 9.84.0 widened it to the five registered here,
514
+ so a schema-check or evidence-check frame can no longer become the protected
515
+ anchor. That widening changes the anchor only when the run's own message text is
516
+ absent from the window, because the anchor is matched by content first and only
517
+ falls back to the last thing a person said. A `when` predicate could apply no
518
+ version of it, because `InjectionContext.history` exposes only
519
+ `{ role, content, toolName? }`. An author writing an entry rule
90
520
  that reads history was silently matching on our own bookkeeping. One
91
521
  implementation, reused by both — the rule cannot drift between routing and the
92
522
  window.
@@ -67,10 +67,28 @@ async function presentArtifact(store, scope, args) {
67
67
  const meta = await store.head(scope, ref);
68
68
  if (meta === null) {
69
69
  const page = await store.list(scope, { limit: PRESENT_LIST_LIMIT });
70
+ // ANCHORED TO THE CALL, NOT TO THE MOMENT — BOTH ARMS. This refusal is a
71
+ // TOOL RESULT: it is written into `history` and re-read on every later call
72
+ // of the turn, including calls made after the model has stored something.
73
+ // "Nothing is live … right now" was therefore a forecast — true when
74
+ // composed, false the moment the run had an artifact — and a model
75
+ // re-reading it is being told its own stored data does not exist. The
76
+ // opening clause names the call (`present('<ref>')`), so the listing binds
77
+ // to that call and stays true wherever it is read.
78
+ //
79
+ // The STOCKED arm needed the same repair for the mirror-image reason, and
80
+ // did not get it until the sentence had a rule to fail: a bare "Live refs
81
+ // in scope: …" is a census, and a census goes wrong in both directions —
82
+ // a ref it names can be swept before the model re-reads it, and a ref
83
+ // minted since will be missing from it. Neither error is visible to the
84
+ // model, which reads a list and believes it is looking at the scope. Past
85
+ // tense plus the call it was taken for is the whole fix: an inventory of a
86
+ // finished moment cannot go stale.
70
87
  const listing = page.artifacts.length === 0
71
- ? `Nothing is live in this run's scope right now — store the data first, then present ` +
72
- `its ref.`
73
- : `Live refs in scope: ${page.artifacts.map(describeRef).join(', ')}.`;
88
+ ? `Nothing was live in this run's scope when you made that call — store the data ` +
89
+ `first, then present its ref.`
90
+ : `These were live in this run's scope when you made that call: ` +
91
+ `${page.artifacts.map(describeRef).join(', ')}.`;
74
92
  return {
75
93
  ok: false,
76
94
  missedRef: ref,
@@ -1 +1 @@
1
- {"version":3,"file":"present.js","sourceRoot":"","sources":["../../src/artifacts/present.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;;;AAIH;;;;GAIG;AACU,QAAA,iBAAiB,GAAG,SAAS,CAAC;AAyC3C,wEAAwE;AACxE,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAE9B,4EAA4E;AAC5E,SAAS,WAAW,CAAC,IAAkB;IACrC,OAAO,GAAG,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,KAAK,SAC9C,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EACpD,GAAG,CAAC;AACN,CAAC;AAED;;;;GAIG;AACI,KAAK,UAAU,eAAe,CACnC,KAAoB,EACpB,KAAoB,EACpB,IAAuC;IAEvC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;IACrB,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;IACnB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EACL,kFAAkF;gBAClF,qFAAqF;gBACrF,UAAU;SACb,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EACL,kFAAkF;gBAClF,IAAI,GAAG,2EAA2E;gBAClF,eAAe;SAClB,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC1C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACpE,MAAM,OAAO,GACX,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;YACzB,CAAC,CAAC,qFAAqF;gBACrF,UAAU;YACZ,CAAC,CAAC,uBAAuB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QAC3E,OAAO;YACL,EAAE,EAAE,KAAK;YACT,SAAS,EAAE,GAAG;YACd,OAAO,EACL,YAAY,GAAG,iEAAiE;gBAChF,uDAAuD,OAAO,EAAE;SACnE,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GACT,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IAC3F,OAAO;QACL,EAAE,EAAE,IAAI;QACR,MAAM,EAAE;YACN,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,EAAE;YACF,QAAQ,EAAE;gBACR,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,CAAC;aACtC;SACF;KACF,CAAC;AACJ,CAAC;AAzDD,0CAyDC"}
1
+ {"version":3,"file":"present.js","sourceRoot":"","sources":["../../src/artifacts/present.ts"],"names":[],"mappings":"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"}
@@ -136,13 +136,28 @@ function describeSpokenValue(spoken) {
136
136
  return 'an empty string';
137
137
  return `a ${typeof spoken}`;
138
138
  }
139
- /** The correcting clause: what CAN resolve, or the honest "nothing can". */
139
+ /** The correcting clause: what CAN resolve, or the honest "nothing can".
140
+ *
141
+ * BOTH arms are PAST TENSE and bound to the refused call, because this clause
142
+ * rides a TOOL RESULT — `resolveToolWants`'s combined refusal, which opens
143
+ * "Tool 'X' was not executed" and is then re-read on every later call of the
144
+ * turn. "No live artifacts exist … right now" was a forecast: the model mints
145
+ * one two calls later and re-reads a sentence saying its data is not there. A
146
+ * fact about the moment that call was refused cannot go stale.
147
+ *
148
+ * The LISTING arm carries the same defect pointing the other way, and kept it
149
+ * three lines from the fix until the checker grew a rule for a census: "Live
150
+ * '<kind>' refs in scope: …" is read as the scope, and by the time it is
151
+ * re-read a ref it names may have been swept and a ref minted since is
152
+ * missing from it. The model cannot see either error — a list looks like a
153
+ * list. So the list says WHEN it was taken, and "Pass one of these" stays
154
+ * useful because a swept ref refuses again with a fresher list. */
140
155
  function liveRefsClause(kind, live) {
141
156
  if (live.length === 0) {
142
- return (`No live '${kind}' artifacts exist in this run's scope right now — produce one first ` +
143
- `(a tool that stores '${kind}', or re-run the step that minted it).`);
157
+ return (`No live '${kind}' artifacts were in this run's scope when that call was refused — ` +
158
+ `produce one first (a tool that stores '${kind}', or re-run the step that minted it).`);
144
159
  }
145
- return `Live '${kind}' refs in scope: ${live
160
+ return `These '${kind}' refs were live in this run's scope when that call was refused: ${live
146
161
  .map(describeLiveRef)
147
162
  .join(', ')}. Pass one of these.`;
148
163
  }
@@ -1 +1 @@
1
- {"version":3,"file":"wants.js","sourceRoot":"","sources":["../../src/artifacts/wants.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wants.js","sourceRoot":"","sources":["../../src/artifacts/wants.ts"],"names":[],"mappings":"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"}
@@ -2039,12 +2039,17 @@ class Agent extends RunnerBase_js_1.RunnerBase {
2039
2039
  }
2040
2040
  const open = this.openSkillIds();
2041
2041
  const reachable = graphMenu;
2042
+ // A decision `tree()` keeps no cursor, so every routing pick is refused by
2043
+ // construction (9.86.0). The descriptor withholds the tool entirely when
2044
+ // nothing is left to open, and explains the tree when something is.
2045
+ const treeRouted = reachable !== undefined && this.skillGraphIsTree;
2042
2046
  return (args) => {
2043
2047
  const grantable = reachable
2044
2048
  ? [...new Set([...reachable(args.currentSkillId), ...open])]
2045
2049
  : undefined;
2046
- // Non-null: `skills` is non-empty, so the builder always returns a tool.
2047
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
2050
+ // `undefined` when the offer is WITHHELD — the tools slot then drops the
2051
+ // schema from the request. (`skills` is non-empty, so an empty catalog is
2052
+ // not one of the ways this can be undefined.)
2048
2053
  return (0, skillTools_js_1.buildReadSkillTool)(skills, {
2049
2054
  ...(grantable !== undefined && { grantable }),
2050
2055
  ...(args.hiddenSkillIds !== undefined && { hiddenIds: args.hiddenSkillIds }),
@@ -2054,7 +2059,8 @@ class Agent extends RunnerBase_js_1.RunnerBase {
2054
2059
  // The turn-start menu (SG-C) — the tools slot passes it only while the
2055
2060
  // verdict is outstanding; describeOffer leads with it.
2056
2061
  ...(args.menu !== undefined && { menu: args.menu }),
2057
- }).schema;
2062
+ ...(treeRouted && { treeRouted: true }),
2063
+ })?.schema;
2058
2064
  };
2059
2065
  }
2060
2066
  /**
@@ -2945,7 +2951,7 @@ class Agent extends RunnerBase_js_1.RunnerBase {
2945
2951
  // auto-attached `present` tool when a store is attached, 9.22.0) +
2946
2952
  // skill-supplied tools (with autoActivate scoping); validates
2947
2953
  // name uniqueness; produces the dispatch map.
2948
- const { registryByName, toolSchemas } = (0, buildToolRegistry_js_1.buildToolRegistry)(registry, this.injections, {
2954
+ const { registryByName, toolSchemas, toolDeclaringSkills } = (0, buildToolRegistry_js_1.buildToolRegistry)(registry, this.injections, {
2949
2955
  hasArtifactStore: artifactStore !== undefined,
2950
2956
  });
2951
2957
  // A statically registered tool that declares `wants` on an agent with no
@@ -3313,6 +3319,11 @@ class Agent extends RunnerBase_js_1.RunnerBase {
3313
3319
  // toolCallsHandler extracted to ./agent/stages/toolCalls.ts (v2.11.2).
3314
3320
  const toolCallsHandler = (0, toolCalls_js_1.buildToolCallsHandler)({
3315
3321
  registryByName,
3322
+ // WHICH SKILLS DECLARE EACH TOOL NAME (9.86.0) — read by the unknown-tool
3323
+ // roster so a role that may not see a skill is not told the names of the
3324
+ // tools that skill brought. Value-conditional: an agent whose skills carry
3325
+ // no tools hands the handler exactly the deps object it always did.
3326
+ ...(toolDeclaringSkills.size > 0 && { toolDeclaringSkills }),
3316
3327
  // The claim ledger accumulates only for an agent that declared a
3317
3328
  // contract to read it (9.61.0) — value-conditional, so every other
3318
3329
  // agent commits exactly what it always did.