agentfootprint 9.16.0 → 9.17.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 (183) hide show
  1. package/AGENTS.md +1 -1
  2. package/CLAUDE.md +1 -1
  3. package/README.md +2 -0
  4. package/ai-instructions/claude-code/SKILL.md +1 -1
  5. package/dist/core/Agent.js +92 -4
  6. package/dist/core/Agent.js.map +1 -1
  7. package/dist/core/agent/AgentBuilder.js +85 -3
  8. package/dist/core/agent/AgentBuilder.js.map +1 -1
  9. package/dist/core/agent/buildAgentChart.js +14 -5
  10. package/dist/core/agent/buildAgentChart.js.map +1 -1
  11. package/dist/core/agent/buildDynamicAgentChart.js +17 -4
  12. package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
  13. package/dist/core/agent/stages/routeTurn.js +308 -0
  14. package/dist/core/agent/stages/routeTurn.js.map +1 -0
  15. package/dist/core/agent/stages/seed.js +9 -0
  16. package/dist/core/agent/stages/seed.js.map +1 -1
  17. package/dist/core/agent/stages/toolCalls.js +53 -0
  18. package/dist/core/agent/stages/toolCalls.js.map +1 -1
  19. package/dist/core/runCheckpoint.js +18 -1
  20. package/dist/core/runCheckpoint.js.map +1 -1
  21. package/dist/core/slots/buildToolsSlot.js +19 -0
  22. package/dist/core/slots/buildToolsSlot.js.map +1 -1
  23. package/dist/esm/core/Agent.d.ts +33 -2
  24. package/dist/esm/core/Agent.js +92 -4
  25. package/dist/esm/core/Agent.js.map +1 -1
  26. package/dist/esm/core/agent/AgentBuilder.d.ts +68 -6
  27. package/dist/esm/core/agent/AgentBuilder.js +85 -3
  28. package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
  29. package/dist/esm/core/agent/buildAgentChart.d.ts +9 -0
  30. package/dist/esm/core/agent/buildAgentChart.js +14 -5
  31. package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
  32. package/dist/esm/core/agent/buildDynamicAgentChart.js +17 -4
  33. package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
  34. package/dist/esm/core/agent/stages/routeTurn.d.ts +73 -0
  35. package/dist/esm/core/agent/stages/routeTurn.js +304 -0
  36. package/dist/esm/core/agent/stages/routeTurn.js.map +1 -0
  37. package/dist/esm/core/agent/stages/seed.d.ts +14 -0
  38. package/dist/esm/core/agent/stages/seed.js +9 -0
  39. package/dist/esm/core/agent/stages/seed.js.map +1 -1
  40. package/dist/esm/core/agent/stages/toolCalls.d.ts +16 -0
  41. package/dist/esm/core/agent/stages/toolCalls.js +53 -0
  42. package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
  43. package/dist/esm/core/agent/types.d.ts +6 -0
  44. package/dist/esm/core/runCheckpoint.d.ts +29 -1
  45. package/dist/esm/core/runCheckpoint.js +18 -1
  46. package/dist/esm/core/runCheckpoint.js.map +1 -1
  47. package/dist/esm/core/slots/buildToolsSlot.d.ts +10 -0
  48. package/dist/esm/core/slots/buildToolsSlot.js +19 -0
  49. package/dist/esm/core/slots/buildToolsSlot.js.map +1 -1
  50. package/dist/esm/events/payloads.d.ts +81 -1
  51. package/dist/esm/events/registry.d.ts +3 -1
  52. package/dist/esm/events/registry.js +2 -0
  53. package/dist/esm/events/registry.js.map +1 -1
  54. package/dist/esm/index.d.ts +1 -1
  55. package/dist/esm/index.js.map +1 -1
  56. package/dist/esm/lib/injection-engine/buildInjectionEngineSubflow.js +20 -0
  57. package/dist/esm/lib/injection-engine/buildInjectionEngineSubflow.js.map +1 -1
  58. package/dist/esm/lib/injection-engine/entryScorer.d.ts +20 -2
  59. package/dist/esm/lib/injection-engine/entryScorer.js +60 -22
  60. package/dist/esm/lib/injection-engine/entryScorer.js.map +1 -1
  61. package/dist/esm/lib/injection-engine/factories/defineMenuHint.d.ts +39 -0
  62. package/dist/esm/lib/injection-engine/factories/defineMenuHint.js +53 -0
  63. package/dist/esm/lib/injection-engine/factories/defineMenuHint.js.map +1 -0
  64. package/dist/esm/lib/injection-engine/index.d.ts +5 -0
  65. package/dist/esm/lib/injection-engine/index.js +8 -0
  66. package/dist/esm/lib/injection-engine/index.js.map +1 -1
  67. package/dist/esm/lib/injection-engine/intentScorer.d.ts +78 -0
  68. package/dist/esm/lib/injection-engine/intentScorer.js +56 -0
  69. package/dist/esm/lib/injection-engine/intentScorer.js.map +1 -0
  70. package/dist/esm/lib/injection-engine/llmClassifier.d.ts +36 -0
  71. package/dist/esm/lib/injection-engine/llmClassifier.js +140 -0
  72. package/dist/esm/lib/injection-engine/llmClassifier.js.map +1 -0
  73. package/dist/esm/lib/injection-engine/routingPolicy.d.ts +154 -0
  74. package/dist/esm/lib/injection-engine/routingPolicy.js +128 -0
  75. package/dist/esm/lib/injection-engine/routingPolicy.js.map +1 -0
  76. package/dist/esm/lib/injection-engine/skillGraph.d.ts +76 -2
  77. package/dist/esm/lib/injection-engine/skillGraph.js +135 -14
  78. package/dist/esm/lib/injection-engine/skillGraph.js.map +1 -1
  79. package/dist/esm/lib/injection-engine/skillGraphCheckup.d.ts +11 -1
  80. package/dist/esm/lib/injection-engine/skillGraphCheckup.js +28 -2
  81. package/dist/esm/lib/injection-engine/skillGraphCheckup.js.map +1 -1
  82. package/dist/esm/lib/injection-engine/skillIntent.d.ts +88 -0
  83. package/dist/esm/lib/injection-engine/skillIntent.js +192 -0
  84. package/dist/esm/lib/injection-engine/skillIntent.js.map +1 -0
  85. package/dist/esm/lib/injection-engine/skillMatch.d.ts +28 -6
  86. package/dist/esm/lib/injection-engine/skillMatch.js +47 -12
  87. package/dist/esm/lib/injection-engine/skillMatch.js.map +1 -1
  88. package/dist/esm/lib/injection-engine/skillTools.d.ts +24 -0
  89. package/dist/esm/lib/injection-engine/skillTools.js +24 -4
  90. package/dist/esm/lib/injection-engine/skillTools.js.map +1 -1
  91. package/dist/esm/lib/injection-engine/types.d.ts +10 -0
  92. package/dist/esm/lib/injection-engine/types.js.map +1 -1
  93. package/dist/esm/recorders/observability/RouteRecorder.d.ts +6 -1
  94. package/dist/esm/recorders/observability/RouteRecorder.js +9 -0
  95. package/dist/esm/recorders/observability/RouteRecorder.js.map +1 -1
  96. package/dist/esm/recorders/observability/commentary/commentaryTemplates.js +44 -0
  97. package/dist/esm/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
  98. package/dist/events/registry.js +2 -0
  99. package/dist/events/registry.js.map +1 -1
  100. package/dist/index.js.map +1 -1
  101. package/dist/lib/injection-engine/buildInjectionEngineSubflow.js +20 -0
  102. package/dist/lib/injection-engine/buildInjectionEngineSubflow.js.map +1 -1
  103. package/dist/lib/injection-engine/entryScorer.js +60 -22
  104. package/dist/lib/injection-engine/entryScorer.js.map +1 -1
  105. package/dist/lib/injection-engine/factories/defineMenuHint.js +57 -0
  106. package/dist/lib/injection-engine/factories/defineMenuHint.js.map +1 -0
  107. package/dist/lib/injection-engine/index.js +18 -1
  108. package/dist/lib/injection-engine/index.js.map +1 -1
  109. package/dist/lib/injection-engine/intentScorer.js +60 -0
  110. package/dist/lib/injection-engine/intentScorer.js.map +1 -0
  111. package/dist/lib/injection-engine/llmClassifier.js +144 -0
  112. package/dist/lib/injection-engine/llmClassifier.js.map +1 -0
  113. package/dist/lib/injection-engine/routingPolicy.js +134 -0
  114. package/dist/lib/injection-engine/routingPolicy.js.map +1 -0
  115. package/dist/lib/injection-engine/skillGraph.js +134 -13
  116. package/dist/lib/injection-engine/skillGraph.js.map +1 -1
  117. package/dist/lib/injection-engine/skillGraphCheckup.js +28 -2
  118. package/dist/lib/injection-engine/skillGraphCheckup.js.map +1 -1
  119. package/dist/lib/injection-engine/skillIntent.js +199 -0
  120. package/dist/lib/injection-engine/skillIntent.js.map +1 -0
  121. package/dist/lib/injection-engine/skillMatch.js +47 -12
  122. package/dist/lib/injection-engine/skillMatch.js.map +1 -1
  123. package/dist/lib/injection-engine/skillTools.js +24 -4
  124. package/dist/lib/injection-engine/skillTools.js.map +1 -1
  125. package/dist/lib/injection-engine/types.js.map +1 -1
  126. package/dist/recorders/observability/RouteRecorder.js +9 -0
  127. package/dist/recorders/observability/RouteRecorder.js.map +1 -1
  128. package/dist/recorders/observability/commentary/commentaryTemplates.js +44 -0
  129. package/dist/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
  130. package/dist/types/core/Agent.d.ts +33 -2
  131. package/dist/types/core/Agent.d.ts.map +1 -1
  132. package/dist/types/core/agent/AgentBuilder.d.ts +68 -6
  133. package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
  134. package/dist/types/core/agent/buildAgentChart.d.ts +9 -0
  135. package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
  136. package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
  137. package/dist/types/core/agent/stages/routeTurn.d.ts +74 -0
  138. package/dist/types/core/agent/stages/routeTurn.d.ts.map +1 -0
  139. package/dist/types/core/agent/stages/seed.d.ts +14 -0
  140. package/dist/types/core/agent/stages/seed.d.ts.map +1 -1
  141. package/dist/types/core/agent/stages/toolCalls.d.ts +16 -0
  142. package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
  143. package/dist/types/core/agent/types.d.ts +6 -0
  144. package/dist/types/core/agent/types.d.ts.map +1 -1
  145. package/dist/types/core/runCheckpoint.d.ts +29 -1
  146. package/dist/types/core/runCheckpoint.d.ts.map +1 -1
  147. package/dist/types/core/slots/buildToolsSlot.d.ts +10 -0
  148. package/dist/types/core/slots/buildToolsSlot.d.ts.map +1 -1
  149. package/dist/types/events/payloads.d.ts +81 -1
  150. package/dist/types/events/payloads.d.ts.map +1 -1
  151. package/dist/types/events/registry.d.ts +3 -1
  152. package/dist/types/events/registry.d.ts.map +1 -1
  153. package/dist/types/index.d.ts +1 -1
  154. package/dist/types/index.d.ts.map +1 -1
  155. package/dist/types/lib/injection-engine/buildInjectionEngineSubflow.d.ts.map +1 -1
  156. package/dist/types/lib/injection-engine/entryScorer.d.ts +20 -2
  157. package/dist/types/lib/injection-engine/entryScorer.d.ts.map +1 -1
  158. package/dist/types/lib/injection-engine/factories/defineMenuHint.d.ts +40 -0
  159. package/dist/types/lib/injection-engine/factories/defineMenuHint.d.ts.map +1 -0
  160. package/dist/types/lib/injection-engine/index.d.ts +5 -0
  161. package/dist/types/lib/injection-engine/index.d.ts.map +1 -1
  162. package/dist/types/lib/injection-engine/intentScorer.d.ts +79 -0
  163. package/dist/types/lib/injection-engine/intentScorer.d.ts.map +1 -0
  164. package/dist/types/lib/injection-engine/llmClassifier.d.ts +37 -0
  165. package/dist/types/lib/injection-engine/llmClassifier.d.ts.map +1 -0
  166. package/dist/types/lib/injection-engine/routingPolicy.d.ts +155 -0
  167. package/dist/types/lib/injection-engine/routingPolicy.d.ts.map +1 -0
  168. package/dist/types/lib/injection-engine/skillGraph.d.ts +76 -2
  169. package/dist/types/lib/injection-engine/skillGraph.d.ts.map +1 -1
  170. package/dist/types/lib/injection-engine/skillGraphCheckup.d.ts +11 -1
  171. package/dist/types/lib/injection-engine/skillGraphCheckup.d.ts.map +1 -1
  172. package/dist/types/lib/injection-engine/skillIntent.d.ts +89 -0
  173. package/dist/types/lib/injection-engine/skillIntent.d.ts.map +1 -0
  174. package/dist/types/lib/injection-engine/skillMatch.d.ts +28 -6
  175. package/dist/types/lib/injection-engine/skillMatch.d.ts.map +1 -1
  176. package/dist/types/lib/injection-engine/skillTools.d.ts +24 -0
  177. package/dist/types/lib/injection-engine/skillTools.d.ts.map +1 -1
  178. package/dist/types/lib/injection-engine/types.d.ts +10 -0
  179. package/dist/types/lib/injection-engine/types.d.ts.map +1 -1
  180. package/dist/types/recorders/observability/RouteRecorder.d.ts +6 -1
  181. package/dist/types/recorders/observability/RouteRecorder.d.ts.map +1 -1
  182. package/dist/types/recorders/observability/commentary/commentaryTemplates.d.ts.map +1 -1
  183. package/package.json +1 -1
@@ -0,0 +1,304 @@
1
+ /**
2
+ * RouteTurn — the turn-start routing cascade stage (SG-C).
3
+ *
4
+ * Runs ONCE per turn, BEFORE the ReAct loop, in the slot PickEntry has always
5
+ * occupied (`STAGE_IDS.PICK_ENTRY` — recorded structures stay stable), so
6
+ * anything async (a classifier, an embedder, one model call) is paid off the
7
+ * hot loop and `nextSkill` stays synchronous. It decides where the turn
8
+ * STARTS and writes the verdict to `scope.turnRoute`; the graph's cursor
9
+ * resolver consumes it on iteration 1 — the exact mechanism
10
+ * `entryScores`/`pendingSkillPick` already use. Iterations 2..N keep today's
11
+ * law byte-for-byte (`userMessage` is fixed for a run).
12
+ *
13
+ * The cascade:
14
+ * tier 1 — declared start rules (regex / keywords / `when`), declaration
15
+ * order, binary and decisive;
16
+ * tier 2 — the configured scorer: the intent classifier (`classify`) over
17
+ * declared intents, or the entry scorer (`entryBy*`) over
18
+ * descriptions — judged by `decideTier2` (floor + pairwise
19
+ * near-tie margin; near-ties FALL THROUGH, never argmax);
20
+ * tier 3 — a menu through the model's own `read_skill` description (plus
21
+ * the advisory menu hint), STAY first-class mid-conversation.
22
+ *
23
+ * Mounted only on graphs that run the cascade — `classify` configured, or
24
+ * `continuity: 'conversation'` declared. A 9.16-style graph (scorer or not)
25
+ * keeps its exact prior stage and events: scorer-only graphs keep PickEntry
26
+ * byte-for-byte, and the cascade fires no `turn_routed` there.
27
+ *
28
+ * Mid-conversation (an inherited cursor from `continuity: 'conversation'`):
29
+ * sticky default — the incumbent is scored AS A CANDIDATE, beaten only by a
30
+ * decisive tier-1/tier-2 verdict; ambiguity = stay; genuinely-new-but-
31
+ * unmatched opens the full menu with STAY first-class. An inherited id the
32
+ * mounted graph does not know is DROPPED (cold start), dev-warned, and
33
+ * recorded as `turn_routed.droppedResume` — never silently parked on a node
34
+ * that does not exist.
35
+ *
36
+ * Every verdict lands on `agentfootprint.skill.turn_routed` with the losers
37
+ * (`scores`, ranked), the pairwise runner-up gap, and the policy numbers that
38
+ * judged it. A throwing/misbehaving scorer never aborts the run: cold start
39
+ * falls through to the FULL menu (recorded — never the declaration-order
40
+ * walk), mid-conversation stays put (`by: 'continuity'`), both dev-warned.
41
+ *
42
+ * `strictness: 'rails'` and menus: the model is not allowed to route, so a
43
+ * menu verdict proceeds on the base prompt — recorded as `by: 'none'` WITH
44
+ * the offered set on the EVENT (what happened), while `scope.turnRoute`
45
+ * carries no `offered` (what the loop may act on): no envelope is composed,
46
+ * and no entry loads. That is the honest cost of rails without a resolver,
47
+ * and the README names it.
48
+ */
49
+ import { isDevMode } from 'footprintjs';
50
+ import { validateIntentScores } from '../../../lib/injection-engine/intentScorer.js';
51
+ import { decideTier2, } from '../../../lib/injection-engine/routingPolicy.js';
52
+ import { typedEmit } from '../../../recorders/core/typedEmit.js';
53
+ export function makeRouteTurnStage(deps) {
54
+ const plan = deps.turnRouting;
55
+ return async (scope) => {
56
+ const env = scope.$getEnv();
57
+ let inherited = scope.currentSkillId;
58
+ // Deploy honesty: an inherited id that is not a node of the CURRENTLY
59
+ // mounted graph is dropped (cold start), never silently parked on a node
60
+ // that does not exist.
61
+ let droppedResume;
62
+ if (inherited !== undefined && !deps.isNode(inherited)) {
63
+ droppedResume = { id: inherited, reason: 'unknown-skill' };
64
+ scope.currentSkillId = undefined;
65
+ if (isDevMode()) {
66
+ // eslint-disable-next-line no-console
67
+ console.warn(`agentfootprint RouteTurn: the conversation's stored cursor "${inherited}" is not a ` +
68
+ `node of the currently mounted graph (a deploy changed it?) — starting cold. ` +
69
+ `Recorded as turn_routed.droppedResume.`);
70
+ }
71
+ inherited = undefined;
72
+ }
73
+ const ctx = {
74
+ iteration: scope.iteration ?? 1,
75
+ userMessage: scope.userMessage ?? '',
76
+ history: scope.history ?? [],
77
+ activatedInjectionIds: scope.activatedInjectionIds ?? [],
78
+ ...(inherited !== undefined && { currentSkillId: inherited }),
79
+ };
80
+ const resolved = await resolveHidden(deps.hiddenSkillIds);
81
+ // Fail CLOSED: a throwing resolver hides EVERY graph candidate this turn
82
+ // (the cascade degrades to continuity-stay / base prompt, all recorded)
83
+ // rather than advertising skills a policy may have meant to hide.
84
+ const hidden = resolved === 'resolver-failed' ? new Set(plan.entryIds) : new Set(resolved);
85
+ if (resolved === 'resolver-failed' && isDevMode()) {
86
+ console.warn('agentfootprint: the hidden-skills resolver threw during turn routing — ' +
87
+ 'failing closed (no graph candidates scored or offered this turn). ' +
88
+ 'Fix the resolver passed to hiddenSkillIds.');
89
+ }
90
+ const visibleEntryIds = plan.entryIds.filter((id) => !hidden.has(id));
91
+ const verdict = await runCascade(deps, plan, ctx, inherited, hidden, visibleEntryIds, env.signal);
92
+ if (verdict === undefined && droppedResume === undefined) {
93
+ // Cold start on a continuity graph with no tier 2 at all: the resolver's
94
+ // cold walk decides exactly as it always has — no verdict, no event.
95
+ return;
96
+ }
97
+ // The shipped ranking surface (defineRelevanceHint, the Why-panel) — the
98
+ // tier-2 numbers, whatever scorer produced them.
99
+ if (verdict?.scores !== undefined && verdict.scorer !== undefined) {
100
+ scope.entryScores = verdict.scores;
101
+ scope.entryScorer = verdict.scorer;
102
+ }
103
+ const policy = plan.policy;
104
+ const effectiveFloor = policy.floor ?? plan.scorer?.floor;
105
+ // Rails × menu: the model may not act on it — record the offer, act on none.
106
+ const rails = deps.strictness === 'rails';
107
+ const eventBy = rails && verdict?.by === 'menu' ? 'none' : verdict?.by ?? 'none';
108
+ typedEmit(scope, 'agentfootprint.skill.turn_routed', {
109
+ by: eventBy,
110
+ ...(inherited !== undefined && { from: inherited }),
111
+ ...(verdict?.to !== undefined && { to: verdict.to }),
112
+ ...(verdict?.scorer !== undefined && { scorer: verdict.scorer }),
113
+ ...(verdict?.scores !== undefined && { scores: verdict.scores.map((s) => ({ ...s })) }),
114
+ ...(verdict?.runnerUp !== undefined && { runnerUp: { ...verdict.runnerUp } }),
115
+ ...(verdict?.decisive !== undefined && { decisive: verdict.decisive }),
116
+ ...(verdict?.offered !== undefined && { offered: [...verdict.offered] }),
117
+ ...(verdict?.stayOffered !== undefined && { stayOffered: verdict.stayOffered }),
118
+ policy: {
119
+ nearTieMargin: policy.nearTieMargin,
120
+ menuSize: policy.menuSize,
121
+ ...(effectiveFloor !== undefined && { floor: effectiveFloor }),
122
+ },
123
+ ...(verdict?.window !== undefined && { window: verdict.window }),
124
+ ...(droppedResume !== undefined && { droppedResume }),
125
+ });
126
+ // The POJO the LOOP acts on — the resolver's iteration-1 input, the
127
+ // envelope's source, the guard gate's window. Under rails a menu carries
128
+ // no `offered` here: nothing downstream may offer what nothing may accept.
129
+ // Written ONLY when the cascade DECIDED something: the resolver suppresses
130
+ // its cold-start walk on the POJO's presence (suppression follows the
131
+ // verdict), so a droppedResume with nothing else to say — a TRUE cold
132
+ // start on a graph whose cold walk still decides — must leave scope
133
+ // untouched, or the drop would silently strand the turn on no entry.
134
+ if (verdict === undefined)
135
+ return;
136
+ const turnRoute = {
137
+ by: eventBy,
138
+ ...(inherited !== undefined && { from: inherited }),
139
+ ...(verdict.to !== undefined && { to: verdict.to }),
140
+ ...(!rails && verdict.offered !== undefined && { offered: [...verdict.offered] }),
141
+ ...(!rails && verdict.stayOffered !== undefined && { stayOffered: verdict.stayOffered }),
142
+ ...(!rails &&
143
+ verdict.offered !== undefined &&
144
+ verdict.scores !== undefined && {
145
+ relevance: verdict.scores.map((s) => ({ id: s.id, relevance: s.relevance })),
146
+ }),
147
+ };
148
+ scope.turnRoute = turnRoute;
149
+ };
150
+ }
151
+ /** Resolve the role-hidden set. A throwing resolver returns the sentinel so the
152
+ * caller can fail CLOSED (hide every candidate) — a menu built on a question
153
+ * nobody answered would advertise what policy hides. */
154
+ async function resolveHidden(hiddenSkillIds) {
155
+ if (!hiddenSkillIds)
156
+ return [];
157
+ try {
158
+ const asked = hiddenSkillIds();
159
+ return asked instanceof Promise ? await asked : asked;
160
+ }
161
+ catch {
162
+ return 'resolver-failed';
163
+ }
164
+ }
165
+ /** The cascade proper. Returns undefined when the stage has nothing to decide
166
+ * (cold start, no classifier, no scorer — the resolver's law). */
167
+ async function runCascade(deps, plan, ctx, inherited, hidden, visibleEntryIds, signal) {
168
+ const cold = inherited === undefined;
169
+ // Tier 1 — declared rules, declaration order. Binary: a rule match is
170
+ // decisive by definition, cold or mid-conversation.
171
+ const ruleWin = plan.firstRuleMatch(ctx);
172
+ if (ruleWin !== undefined) {
173
+ return { by: 'entry', to: ruleWin, decisive: true };
174
+ }
175
+ // Tier 2 — the classifier over declared intents…
176
+ if (plan.scorer !== undefined) {
177
+ const scorer = plan.scorer;
178
+ const candidates = [...plan.intentCandidates(hidden)];
179
+ if (!cold && !hidden.has(inherited) && !candidates.some((c) => c.id === inherited)) {
180
+ // The incumbent is judged by the same numbers as its challengers — its
181
+ // intent is its description when it is not an intent entry.
182
+ candidates.push(plan.incumbentCandidate(inherited));
183
+ }
184
+ if (candidates.length === 0) {
185
+ return cold
186
+ ? menuVerdict(visibleEntryIds, false, scorer.name, scorer.window)
187
+ : { by: 'continuity', to: inherited, scorer: scorer.name };
188
+ }
189
+ let scores;
190
+ try {
191
+ const input = {
192
+ message: ctx.userMessage,
193
+ ...(scorer.window !== undefined && {
194
+ recentTurns: recentTurnsOf(ctx.history, scorer.window),
195
+ }),
196
+ };
197
+ const raw = await scorer.score(input, candidates, signal);
198
+ scores = validateIntentScores(scorer.name, candidates, raw);
199
+ }
200
+ catch (err) {
201
+ return scorerFellThrough(err, scorer.name, cold, inherited, visibleEntryIds, scorer.window);
202
+ }
203
+ const v = decideTier2(scores, cold ? undefined : inherited, plan.policy, {
204
+ ...(scorer.floor !== undefined && { floor: scorer.floor }),
205
+ ...(scorer.categorical !== undefined && { categorical: scorer.categorical }),
206
+ });
207
+ return mapTier2(v, scorer.name, cold, inherited, visibleEntryIds, scorer.window);
208
+ }
209
+ // …or the entry scorer over descriptions (entryBy/entryByRelevance graphs
210
+ // that opted into the cascade via continuity).
211
+ if (deps.scoreEntries !== undefined) {
212
+ let scoring;
213
+ try {
214
+ scoring = await deps.scoreEntries(ctx, signal);
215
+ }
216
+ catch (err) {
217
+ return scorerFellThrough(err, 'entry-scorer', cold, inherited, visibleEntryIds, undefined);
218
+ }
219
+ // Role-hidden candidates never appear in scores, menus or the envelope.
220
+ let ranked = scoring.ranked.filter((r) => !hidden.has(r.id));
221
+ if (!cold && !hidden.has(inherited) && !ranked.some((r) => r.id === inherited)) {
222
+ // The incumbent was not a when-passing entry candidate this turn — score
223
+ // floor-less zero so the same verdict function judges it. (An entry
224
+ // scorer declares no floor, so 0 is a rank, not "unmatched".)
225
+ ranked = [...ranked, { id: inherited, score: 0, relevance: 0 }];
226
+ }
227
+ if (ranked.length === 0)
228
+ return cold
229
+ ? menuVerdict(visibleEntryIds, false, scoring.scorer, undefined)
230
+ : { by: 'continuity', to: inherited, scorer: scoring.scorer };
231
+ const v = decideTier2(ranked.map((r) => ({ id: r.id, score: r.score })), cold ? undefined : inherited, plan.policy, {});
232
+ return mapTier2(v, scoring.scorer, cold, inherited, visibleEntryIds, undefined);
233
+ }
234
+ // No tier 2 at all: mid-conversation the inherited cursor holds (sticky,
235
+ // recorded); cold start is the resolver's cold walk — nothing to decide.
236
+ if (!cold)
237
+ return { by: 'continuity', to: inherited };
238
+ return undefined;
239
+ }
240
+ /** Map a `decideTier2` verdict into the stage's recorded shape. */
241
+ function mapTier2(v, scorerName, cold, inherited, visibleEntryIds, window) {
242
+ const numbers = {
243
+ scorer: scorerName,
244
+ scores: v.ranked.map((r) => ({ id: r.id, score: r.score, relevance: r.relevance })),
245
+ ...(v.runnerUp !== undefined && { runnerUp: { ...v.runnerUp } }),
246
+ decisive: v.decisive,
247
+ ...(window !== undefined && { window }),
248
+ };
249
+ switch (v.kind) {
250
+ case 'move':
251
+ return { by: 'intent', to: v.to, ...numbers };
252
+ case 'stay':
253
+ // Incumbent won or near-tie held it — `continuity`, with the numbers.
254
+ return { by: 'continuity', to: inherited, ...numbers };
255
+ case 'menu':
256
+ return { by: 'menu', offered: v.offered, ...(!cold && { stayOffered: true }), ...numbers };
257
+ case 'unmatched':
258
+ // Genuinely new but unmatched: the FULL entry menu, STAY first-class
259
+ // mid-conversation.
260
+ return {
261
+ by: 'menu',
262
+ offered: visibleEntryIds,
263
+ ...(!cold && { stayOffered: true }),
264
+ ...numbers,
265
+ };
266
+ }
267
+ }
268
+ /** The recorded fallback for a throwing/misbehaving scorer: cold → the full
269
+ * menu (never the declaration-order walk); mid → stay. Dev-warned. */
270
+ function scorerFellThrough(err, scorerName, cold, inherited, visibleEntryIds, window) {
271
+ if (isDevMode()) {
272
+ // eslint-disable-next-line no-console
273
+ console.warn(`agentfootprint RouteTurn: the '${scorerName}' scorer failed — ${cold
274
+ ? 'offering the full entry menu (recorded)'
275
+ : 'staying on the inherited cursor (recorded)'}. Scorers are a tier, never a correctness dependency. ${err instanceof Error ? err.message : String(err)}`);
276
+ }
277
+ return cold
278
+ ? menuVerdict(visibleEntryIds, false, scorerName, window)
279
+ : {
280
+ by: 'continuity',
281
+ to: inherited,
282
+ scorer: scorerName,
283
+ ...(window !== undefined && { window }),
284
+ };
285
+ }
286
+ function menuVerdict(offered, stayOffered, scorerName, window) {
287
+ return {
288
+ by: 'menu',
289
+ offered,
290
+ ...(stayOffered && { stayOffered }),
291
+ ...(scorerName !== undefined && { scorer: scorerName }),
292
+ ...(window !== undefined && { window }),
293
+ };
294
+ }
295
+ /** The prior conversational turns a windowed scorer sees — user/assistant
296
+ * roles only, the CURRENT user message excluded, newest last. */
297
+ function recentTurnsOf(history, window) {
298
+ const prior = history.slice(0, Math.max(0, history.length - 1));
299
+ return prior
300
+ .filter((m) => m.role === 'user' || m.role === 'assistant')
301
+ .map((m) => ({ role: m.role, content: m.content }))
302
+ .slice(-window);
303
+ }
304
+ //# sourceMappingURL=routeTurn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routeTurn.js","sourceRoot":"","sources":["../../../../../src/core/agent/stages/routeTurn.ts"],"names":[],"mappings":"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"}
@@ -109,6 +109,20 @@ export interface SeedStageDeps {
109
109
  * commits exactly the keys it always did.
110
110
  */
111
111
  readonly conversationStores?: readonly MemoryStore[];
112
+ /**
113
+ * Read-AND-CLEAR accessor for the CONVERSATION'S skill cursor (SG-C,
114
+ * `continuity: 'conversation'`) — the `skillCursor` a continued checkpoint
115
+ * carried, stashed by `applyContinuation` beside the history. Consumed on
116
+ * every run (the side channel must clear either way); WRITTEN to
117
+ * `scope.currentSkillId` only when `restoreSkillCursor` is true, so a graph
118
+ * under the default `continuity: 'turn'` seeds the exact keys it always
119
+ * did. The RouteTurn stage then judges the inherited cursor against the new
120
+ * message (sticky default, decisively beaten, or dropped when the mounted
121
+ * graph no longer knows the id).
122
+ */
123
+ readonly consumePendingResumeSkillCursor?: () => string | undefined;
124
+ /** The mounted graph declared `continuity: 'conversation'`. */
125
+ readonly restoreSkillCursor?: boolean;
112
126
  }
113
127
  /**
114
128
  * Build the seed stage function for an Agent instance. Captures both
@@ -240,6 +240,15 @@ function seedFrom(scope, message, deps) {
240
240
  // graph through the entry router (cold start). The Injection Engine advances
241
241
  // it each iteration; undefined for agents without a skillGraph().
242
242
  scope.currentSkillId = undefined;
243
+ // …unless the graph declared `continuity: 'conversation'` and this run
244
+ // continues a stored conversation (SG-C): the SAME key, one clause earlier —
245
+ // no second cursor, no new time axis. Consumed unconditionally (the side
246
+ // channel clears whether or not it is honored); written only under the
247
+ // option, so `continuity: 'turn'` commits exactly the keys it always did.
248
+ const inheritedCursor = deps.consumePendingResumeSkillCursor?.();
249
+ if (deps.restoreSkillCursor === true && inheritedCursor !== undefined) {
250
+ scope.currentSkillId = inheritedCursor;
251
+ }
243
252
  // The model's `read_skill` pick — nothing picked yet on a fresh turn.
244
253
  scope.pendingSkillPick = undefined;
245
254
  // `.configure()` — resolved ONCE here (seed runs exactly once per run)
@@ -1 +1 @@
1
- {"version":3,"file":"seed.js","sourceRoot":"","sources":["../../../../../src/core/agent/stages/seed.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"seed.js","sourceRoot":"","sources":["../../../../../src/core/agent/stages/seed.ts"],"names":[],"mappings":"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"}
@@ -120,6 +120,22 @@ export interface ToolCallsHandlerDeps {
120
120
  * why the graph cannot be jumped at all, so the model stops asking and answers.
121
121
  */
122
122
  readonly skillGraphIsTree?: boolean;
123
+ /**
124
+ * The mount's routing POSTURE beyond reachability (SG-C `strictness`).
125
+ * Undefined = `'assist'` = today's gate, byte-for-byte — not one new line
126
+ * runs. Judged AFTER reachability (an unreachable pick keeps its original
127
+ * teaching refusal), and only on HOPS — an OPEN skill (`.selfExplain()`,
128
+ * a `.skill()` beside the graph) is admitted from anywhere under every
129
+ * posture, so debugging never breaks:
130
+ * • `'guard'` — a routing pick is admitted only while the turn's MENU is
131
+ * outstanding AND names an offered id (the framework declared the
132
+ * ambiguity; the model resolves exactly that). Off-menu / no-menu picks
133
+ * get a teaching refusal + `skill.rejected { posture: 'guard' }`.
134
+ * • `'rails'` — routing picks are refused outright: rules/scorer resolve
135
+ * turn starts, declared routes handle transitions.
136
+ * Same graph, same trace: postures change refusal behavior only.
137
+ */
138
+ readonly skillStrictness?: 'guard' | 'rails';
123
139
  /**
124
140
  * Check-in config (evidence-carrying human consent). Resolved from the Agent
125
141
  * builder (`.checkIn({...})`) — defaults to `standard` evidence + the
@@ -46,6 +46,7 @@ import { checkerGoverns } from '../../../adapters/types.js';
46
46
  import { typedEmit } from '../../../recorders/core/typedEmit.js';
47
47
  import { extractSequence } from '../../../security/extractSequence.js';
48
48
  import { skillTarget } from '../../../security/skillTarget.js';
49
+ import { menuOutstanding } from '../../../lib/injection-engine/routingPolicy.js';
49
50
  import { unconfiguredCredentialProvider } from '../../../identity/types.js';
50
51
  import { CONSENT_PAUSE_KEY, consentQuestion, modelRefusal } from '../../../identity/consent.js';
51
52
  import { isPauseRequest, PauseAnswerRequiredError } from '../../pause.js';
@@ -133,6 +134,36 @@ function skillRefusal(requestedId, allowed, isTree) {
133
134
  }
134
135
  return `${head}No skills are reachable from here — answer with the current skill, or finish.`;
135
136
  }
137
+ /**
138
+ * The re-prompt a POSTURE-refused `read_skill` gets back (SG-C `strictness`).
139
+ * The pick was REACHABLE — the graph would have granted it — so the message
140
+ * must teach the posture, not the map: who routes here, and what the model may
141
+ * still do (open skills, staying, finishing).
142
+ */
143
+ function postureRefusal(requestedId, posture, turnRoute, currentSkillId, openIds) {
144
+ const openClause = openIds.length > 0
145
+ ? ` read_skill here reaches only the open skills: ${openIds.join(', ')}.`
146
+ : '';
147
+ if (posture === 'rails') {
148
+ return (`read_skill("${requestedId}") was declined: this graph runs on rails — turn starts ` +
149
+ `resolve by declared rule or scorer and transitions by declared routes; the model ` +
150
+ `does not route itself.${openClause} Continue with the skill you are in` +
151
+ `${currentSkillId !== undefined ? ` ('${currentSkillId}')` : ''}, or finish.`);
152
+ }
153
+ // guard — either no menu is outstanding, or the pick was off it.
154
+ if (turnRoute?.offered !== undefined && menuOutstanding(turnRoute, currentSkillId)) {
155
+ return (`read_skill("${requestedId}") was declined: under this graph's 'guard' posture a ` +
156
+ `routing pick must come from the offered menu — ${turnRoute.offered.join(', ')} — or ` +
157
+ `stay (answer without calling read_skill).${openClause}`);
158
+ }
159
+ const decidedBy = turnRoute?.by === 'intent' || turnRoute?.by === 'entry'
160
+ ? `the turn's start was resolved decisively this turn`
161
+ : `no routing ambiguity is open this turn`;
162
+ return (`read_skill("${requestedId}") was declined: this graph's 'guard' posture admits a ` +
163
+ `routing pick only while the framework has declared ambiguity (an offered menu), and ` +
164
+ `${decidedBy}; declared routes handle transitions.${openClause} Continue with the ` +
165
+ `skill you are in${currentSkillId !== undefined ? ` ('${currentSkillId}')` : ''}, or finish.`);
166
+ }
136
167
  /**
137
168
  * The args a `pauseHere` / `askHuman` call was running with, read back on the
138
169
  * far side of the pause (8.13.0).
@@ -1103,6 +1134,28 @@ export function buildToolCallsHandler(deps) {
1103
1134
  iteration,
1104
1135
  });
1105
1136
  }
1137
+ else if (deps.skillStrictness !== undefined && skillHop) {
1138
+ // ── The POSTURE arm (SG-C) — after reachability, hops only. ──
1139
+ // OPEN skills never reach here (skillHop is false for them), so
1140
+ // `.selfExplain()` and friends stay admitted under every posture.
1141
+ const turnRoute = scope.turnRoute;
1142
+ const onOutstandingMenu = menuOutstanding(turnRoute, currentSkillId) &&
1143
+ turnRoute?.offered?.includes(reqId) === true;
1144
+ const refusedByPosture = deps.skillStrictness === 'rails' ||
1145
+ (deps.skillStrictness === 'guard' && !onOutstandingMenu);
1146
+ if (refusedByPosture) {
1147
+ skillRejected = true;
1148
+ skillHop = false; // a refused pick must not move the cursor below
1149
+ result = postureRefusal(reqId, deps.skillStrictness, turnRoute, currentSkillId, deps.openSkillIds ?? []);
1150
+ typedEmit(scope, 'agentfootprint.skill.rejected', {
1151
+ requestedId: reqId,
1152
+ ...(currentSkillId !== undefined && { currentSkillId }),
1153
+ allowed,
1154
+ iteration,
1155
+ posture: deps.skillStrictness,
1156
+ });
1157
+ }
1158
+ }
1106
1159
  }
1107
1160
  }
1108
1161
  // ── The after-tool moment ────────────────────────────────────────