agentfootprint 9.74.0 → 9.76.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.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +126 -0
- package/CLAUDE.md +24 -19
- package/ai-instructions/claude-code/SKILL.md +1 -1
- package/dist/artifacts/index.js +3 -1
- package/dist/artifacts/index.js.map +1 -1
- package/dist/artifacts/recordingArtifact.js +47 -1
- package/dist/artifacts/recordingArtifact.js.map +1 -1
- package/dist/core/Agent.js +53 -1
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/AgentBuilder.js +12 -0
- package/dist/core/agent/AgentBuilder.js.map +1 -1
- package/dist/core/agent/evidence/gate.js +22 -3
- package/dist/core/agent/evidence/gate.js.map +1 -1
- package/dist/core/agent/stagedRefs.js +161 -0
- package/dist/core/agent/stagedRefs.js.map +1 -0
- package/dist/core/agent/stages/callLLM.js +22 -2
- package/dist/core/agent/stages/callLLM.js.map +1 -1
- package/dist/core/agent/stages/evidenceRecheck.js +21 -2
- package/dist/core/agent/stages/evidenceRecheck.js.map +1 -1
- package/dist/core/agent/stages/toolCalls.js +42 -0
- package/dist/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/core/agent/toolDispatch.js +101 -0
- package/dist/core/agent/toolDispatch.js.map +1 -0
- package/dist/core/flowchartAsTool.js +9 -2
- package/dist/core/flowchartAsTool.js.map +1 -1
- package/dist/core/runbook/coverage.js +162 -0
- package/dist/core/runbook/coverage.js.map +1 -0
- package/dist/core/runbook/dispatch.js +119 -0
- package/dist/core/runbook/dispatch.js.map +1 -0
- package/dist/core/runbook/index.js +24 -0
- package/dist/core/runbook/index.js.map +1 -0
- package/dist/core/runbook/runbookAsTool.js +358 -0
- package/dist/core/runbook/runbookAsTool.js.map +1 -0
- package/dist/core/runbook/types.js +22 -0
- package/dist/core/runbook/types.js.map +1 -0
- package/dist/core/runbook/verdicts.js +156 -0
- package/dist/core/runbook/verdicts.js.map +1 -0
- package/dist/core/runbook/walk.js +115 -0
- package/dist/core/runbook/walk.js.map +1 -0
- package/dist/core/tools.js +55 -1
- package/dist/core/tools.js.map +1 -1
- package/dist/esm/artifacts/index.d.ts +1 -1
- package/dist/esm/artifacts/index.js +1 -1
- package/dist/esm/artifacts/index.js.map +1 -1
- package/dist/esm/artifacts/recordingArtifact.d.ts +36 -0
- package/dist/esm/artifacts/recordingArtifact.js +45 -0
- package/dist/esm/artifacts/recordingArtifact.js.map +1 -1
- package/dist/esm/core/Agent.js +53 -1
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.d.ts +12 -0
- package/dist/esm/core/agent/AgentBuilder.js +12 -0
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
- package/dist/esm/core/agent/evidence/gate.d.ts +11 -1
- package/dist/esm/core/agent/evidence/gate.js +22 -3
- package/dist/esm/core/agent/evidence/gate.js.map +1 -1
- package/dist/esm/core/agent/evidence/types.d.ts +23 -0
- package/dist/esm/core/agent/stagedRefs.d.ts +94 -0
- package/dist/esm/core/agent/stagedRefs.js +154 -0
- package/dist/esm/core/agent/stagedRefs.js.map +1 -0
- package/dist/esm/core/agent/stages/callLLM.d.ts +17 -0
- package/dist/esm/core/agent/stages/callLLM.js +22 -2
- package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
- package/dist/esm/core/agent/stages/evidenceRecheck.d.ts +19 -1
- package/dist/esm/core/agent/stages/evidenceRecheck.js +21 -2
- package/dist/esm/core/agent/stages/evidenceRecheck.js.map +1 -1
- package/dist/esm/core/agent/stages/toolCalls.js +42 -0
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/esm/core/agent/toolDispatch.d.ts +50 -0
- package/dist/esm/core/agent/toolDispatch.js +97 -0
- package/dist/esm/core/agent/toolDispatch.js.map +1 -0
- package/dist/esm/core/flowchartAsTool.d.ts +6 -0
- package/dist/esm/core/flowchartAsTool.js +9 -2
- package/dist/esm/core/flowchartAsTool.js.map +1 -1
- package/dist/esm/core/runbook/coverage.d.ts +69 -0
- package/dist/esm/core/runbook/coverage.js +155 -0
- package/dist/esm/core/runbook/coverage.js.map +1 -0
- package/dist/esm/core/runbook/dispatch.d.ts +69 -0
- package/dist/esm/core/runbook/dispatch.js +112 -0
- package/dist/esm/core/runbook/dispatch.js.map +1 -0
- package/dist/esm/core/runbook/index.d.ts +9 -0
- package/dist/esm/core/runbook/index.js +9 -0
- package/dist/esm/core/runbook/index.js.map +1 -0
- package/dist/esm/core/runbook/runbookAsTool.d.ts +88 -0
- package/dist/esm/core/runbook/runbookAsTool.js +354 -0
- package/dist/esm/core/runbook/runbookAsTool.js.map +1 -0
- package/dist/esm/core/runbook/types.d.ts +196 -0
- package/dist/esm/core/runbook/types.js +21 -0
- package/dist/esm/core/runbook/types.js.map +1 -0
- package/dist/esm/core/runbook/verdicts.d.ts +78 -0
- package/dist/esm/core/runbook/verdicts.js +148 -0
- package/dist/esm/core/runbook/verdicts.js.map +1 -0
- package/dist/esm/core/runbook/walk.d.ts +72 -0
- package/dist/esm/core/runbook/walk.js +110 -0
- package/dist/esm/core/runbook/walk.js.map +1 -0
- package/dist/esm/core/tools.d.ts +112 -0
- package/dist/esm/core/tools.js +52 -0
- package/dist/esm/core/tools.js.map +1 -1
- package/dist/esm/events/payloads.d.ts +39 -0
- package/dist/esm/events/registry.d.ts +3 -1
- package/dist/esm/events/registry.js +2 -0
- package/dist/esm/events/registry.js.map +1 -1
- package/dist/esm/index.d.ts +4 -3
- package/dist/esm/index.js +19 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/mcp/toolExtras.d.ts +8 -0
- package/dist/esm/lib/mcp/toolExtras.js +7 -1
- package/dist/esm/lib/mcp/toolExtras.js.map +1 -1
- package/dist/events/registry.js +2 -0
- package/dist/events/registry.js.map +1 -1
- package/dist/index.js +97 -66
- package/dist/index.js.map +1 -1
- package/dist/lib/mcp/toolExtras.js +6 -0
- package/dist/lib/mcp/toolExtras.js.map +1 -1
- package/dist/types/artifacts/index.d.ts +1 -1
- package/dist/types/artifacts/index.d.ts.map +1 -1
- package/dist/types/artifacts/recordingArtifact.d.ts +36 -0
- package/dist/types/artifacts/recordingArtifact.d.ts.map +1 -1
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts +12 -0
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
- package/dist/types/core/agent/evidence/gate.d.ts +11 -1
- package/dist/types/core/agent/evidence/gate.d.ts.map +1 -1
- package/dist/types/core/agent/evidence/types.d.ts +23 -0
- package/dist/types/core/agent/evidence/types.d.ts.map +1 -1
- package/dist/types/core/agent/stagedRefs.d.ts +95 -0
- package/dist/types/core/agent/stagedRefs.d.ts.map +1 -0
- package/dist/types/core/agent/stages/callLLM.d.ts +17 -0
- package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
- package/dist/types/core/agent/stages/evidenceRecheck.d.ts +19 -1
- package/dist/types/core/agent/stages/evidenceRecheck.d.ts.map +1 -1
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
- package/dist/types/core/agent/toolDispatch.d.ts +51 -0
- package/dist/types/core/agent/toolDispatch.d.ts.map +1 -0
- package/dist/types/core/flowchartAsTool.d.ts +6 -0
- package/dist/types/core/flowchartAsTool.d.ts.map +1 -1
- package/dist/types/core/runbook/coverage.d.ts +70 -0
- package/dist/types/core/runbook/coverage.d.ts.map +1 -0
- package/dist/types/core/runbook/dispatch.d.ts +70 -0
- package/dist/types/core/runbook/dispatch.d.ts.map +1 -0
- package/dist/types/core/runbook/index.d.ts +10 -0
- package/dist/types/core/runbook/index.d.ts.map +1 -0
- package/dist/types/core/runbook/runbookAsTool.d.ts +89 -0
- package/dist/types/core/runbook/runbookAsTool.d.ts.map +1 -0
- package/dist/types/core/runbook/types.d.ts +197 -0
- package/dist/types/core/runbook/types.d.ts.map +1 -0
- package/dist/types/core/runbook/verdicts.d.ts +79 -0
- package/dist/types/core/runbook/verdicts.d.ts.map +1 -0
- package/dist/types/core/runbook/walk.d.ts +73 -0
- package/dist/types/core/runbook/walk.d.ts.map +1 -0
- package/dist/types/core/tools.d.ts +112 -0
- package/dist/types/core/tools.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +39 -0
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/events/registry.d.ts +3 -1
- package/dist/types/events/registry.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/mcp/toolExtras.d.ts +8 -0
- package/dist/types/lib/mcp/toolExtras.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runbook/types — the vocabulary of the runbook bridge.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: one options bag, four concerns (declarations, procedure, evidence
|
|
5
|
+
* policy, walk policy) + one envelope type split into a MANDATORY
|
|
6
|
+
* SPINE and an OPTIONAL projection. Pure data, no behavior.
|
|
7
|
+
* Role: core/ layer. `runbookAsTool.ts` consumes; consumers read the
|
|
8
|
+
* envelope types when they assert on results.
|
|
9
|
+
* Emits: N/A.
|
|
10
|
+
*
|
|
11
|
+
* The SPINE / PROJECTION split is load-bearing honesty, not taste: the spine
|
|
12
|
+
* (coverage, provenance, rule version, the recorded walk) is what EVERY
|
|
13
|
+
* runbook ships whatever its shape, so an answer can never arrive without its
|
|
14
|
+
* boundary; the verdict/rowset projection is one shape of answer (a triage),
|
|
15
|
+
* selected by `resultKind: 'verdict/*'` — an action-taking runbook ships the
|
|
16
|
+
* spine plus its own `report` payload and no rowset. The spine's wire shape
|
|
17
|
+
* is explicitly PROVISIONAL until a second, differently-shaped consumer has
|
|
18
|
+
* shipped through it.
|
|
19
|
+
*/
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/core/runbook/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runbook/verdicts — the OPTIONAL verdict/rowset projection.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: pure selection + rendering over the run's final state, plus one
|
|
5
|
+
* tiny recorder that harvests decide() evidence for generated
|
|
6
|
+
* meanings. Selected by `resultKind: 'verdict/*'`; a runbook of any
|
|
7
|
+
* other kind never sees this module.
|
|
8
|
+
* Role: core/runbook.
|
|
9
|
+
* Emits: N/A.
|
|
10
|
+
*
|
|
11
|
+
* THE ONE-NUMBER LAW: the rendered table and the structured `verdicts` list
|
|
12
|
+
* show the SAME rows under the SAME cap. A rendered table beside a longer
|
|
13
|
+
* structured list is an invitation that gets accepted — rows come back
|
|
14
|
+
* retyped with subtly wrong identifiers.
|
|
15
|
+
*
|
|
16
|
+
* GENERATED MEANINGS, never hand-restated: `verdict_meanings` is composed
|
|
17
|
+
* from (a) the named decider's declared branches in the chart's own structure
|
|
18
|
+
* (branch description, falling back to branch name), overlaid by (b) the rule
|
|
19
|
+
* LABELS this run's decide() evidence carried — the rule speaking for itself.
|
|
20
|
+
* A decider inside a dynamically generated fan-out branch is invisible to (a)
|
|
21
|
+
* by construction (the branch chart does not exist at build time); (b) still
|
|
22
|
+
* covers every verdict an executed rule produced.
|
|
23
|
+
*/
|
|
24
|
+
import type { CombinedRecorder } from 'footprintjs';
|
|
25
|
+
import type { FlowChart } from 'footprintjs';
|
|
26
|
+
import type { VerdictRow } from './types.js';
|
|
27
|
+
/** Default cap on `verdicts` rows and the rendered table. */
|
|
28
|
+
export declare const DEFAULT_MAX_ROWS = 50;
|
|
29
|
+
/** The render law, stated to the model beside every table. */
|
|
30
|
+
export declare const VERDICT_RENDER_NOTE: string;
|
|
31
|
+
/** The reserved verdict word for "no classification was reached" — rows
|
|
32
|
+
* carrying it are counted into the coverage ledger as not-checked ground
|
|
33
|
+
* (the three-outcome honesty: reached, reached-and-clear, DECLINED). */
|
|
34
|
+
export declare const DECLINED_VERDICT = "declined";
|
|
35
|
+
/** Read the rowset off the final state's `verdicts` key — an array of bags
|
|
36
|
+
* each carrying a string `verdict`. Anything else reads as "no rowset". */
|
|
37
|
+
export declare function verdictRowsOf(state: Readonly<Record<string, unknown>>): VerdictRow[];
|
|
38
|
+
/**
|
|
39
|
+
* Render the shown rows as one markdown table. Columns are the FIRST row's
|
|
40
|
+
* own keys in declaration order — the chart writes its rows, so the chart
|
|
41
|
+
* owns the column vocabulary; the bridge only renders it.
|
|
42
|
+
*/
|
|
43
|
+
export declare function renderVerdictTable(rows: readonly VerdictRow[]): string;
|
|
44
|
+
/** The two spellings of the configured decider, once the static walk has
|
|
45
|
+
* (maybe) resolved it — flow events report the decider by name. */
|
|
46
|
+
export interface DeciderIdentity {
|
|
47
|
+
readonly spellings: ReadonlySet<string>;
|
|
48
|
+
/** branch → declared meaning, from the chart's own structure. */
|
|
49
|
+
readonly declared: ReadonlyMap<string, string>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Find the named decider in the chart's static structure (root graph plus
|
|
53
|
+
* statically declared subflows) and read its branches. Loop-ref stubs are
|
|
54
|
+
* skipped FIRST — they deliberately violate node-id uniqueness.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveDecider(chart: FlowChart, decider: string): DeciderIdentity;
|
|
57
|
+
/** The evidence harvest: rule labels observed in this run, branch → label. */
|
|
58
|
+
export interface MeaningsHarvest {
|
|
59
|
+
readonly recorder: CombinedRecorder;
|
|
60
|
+
readonly observed: ReadonlyMap<string, string>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* A tiny flow recorder capturing the named decider's decide() evidence as it
|
|
64
|
+
* fires — collected DURING the traversal, never reconstructed after. Rule
|
|
65
|
+
* labels are harvested for every rule the evidence lists (matched or not):
|
|
66
|
+
* a rule that was evaluated has spoken its label, whichever branch won.
|
|
67
|
+
*
|
|
68
|
+
* A decider inside a subflow (including a generated fan-out branch) reports
|
|
69
|
+
* itself PATH-PREFIXED (`per-subject~0/Protection posture`), so the match is
|
|
70
|
+
* on the LAST `/`-segment — the same last-delimiter reading every upstream
|
|
71
|
+
* parser of these paths uses, which is what keeps the generated-branch
|
|
72
|
+
* marker opaque here.
|
|
73
|
+
*/
|
|
74
|
+
export declare function meaningsRecorder(identity: DeciderIdentity): MeaningsHarvest;
|
|
75
|
+
/** Compose the final meanings: declared branches first, observed rule labels
|
|
76
|
+
* winning where both speak (the rule is the sharper sentence). Undefined
|
|
77
|
+
* when neither source produced anything — absent, never `{}`. */
|
|
78
|
+
export declare function composeMeanings(identity: DeciderIdentity, observed: ReadonlyMap<string, string>): Record<string, string> | undefined;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runbook/verdicts — the OPTIONAL verdict/rowset projection.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: pure selection + rendering over the run's final state, plus one
|
|
5
|
+
* tiny recorder that harvests decide() evidence for generated
|
|
6
|
+
* meanings. Selected by `resultKind: 'verdict/*'`; a runbook of any
|
|
7
|
+
* other kind never sees this module.
|
|
8
|
+
* Role: core/runbook.
|
|
9
|
+
* Emits: N/A.
|
|
10
|
+
*
|
|
11
|
+
* THE ONE-NUMBER LAW: the rendered table and the structured `verdicts` list
|
|
12
|
+
* show the SAME rows under the SAME cap. A rendered table beside a longer
|
|
13
|
+
* structured list is an invitation that gets accepted — rows come back
|
|
14
|
+
* retyped with subtly wrong identifiers.
|
|
15
|
+
*
|
|
16
|
+
* GENERATED MEANINGS, never hand-restated: `verdict_meanings` is composed
|
|
17
|
+
* from (a) the named decider's declared branches in the chart's own structure
|
|
18
|
+
* (branch description, falling back to branch name), overlaid by (b) the rule
|
|
19
|
+
* LABELS this run's decide() evidence carried — the rule speaking for itself.
|
|
20
|
+
* A decider inside a dynamically generated fan-out branch is invisible to (a)
|
|
21
|
+
* by construction (the branch chart does not exist at build time); (b) still
|
|
22
|
+
* covers every verdict an executed rule produced.
|
|
23
|
+
*/
|
|
24
|
+
/** Default cap on `verdicts` rows and the rendered table. */
|
|
25
|
+
export const DEFAULT_MAX_ROWS = 50;
|
|
26
|
+
/** The render law, stated to the model beside every table. */
|
|
27
|
+
export const VERDICT_RENDER_NOTE = 'table is PRE-RENDERED over the same rows as `verdicts` — output it VERBATIM. Never ' +
|
|
28
|
+
'retype an identifier from `verdicts`; a transcribed name that looks right and matches ' +
|
|
29
|
+
'nothing is the failure this note exists to stop.';
|
|
30
|
+
/** The reserved verdict word for "no classification was reached" — rows
|
|
31
|
+
* carrying it are counted into the coverage ledger as not-checked ground
|
|
32
|
+
* (the three-outcome honesty: reached, reached-and-clear, DECLINED). */
|
|
33
|
+
export const DECLINED_VERDICT = 'declined';
|
|
34
|
+
/** Read the rowset off the final state's `verdicts` key — an array of bags
|
|
35
|
+
* each carrying a string `verdict`. Anything else reads as "no rowset". */
|
|
36
|
+
export function verdictRowsOf(state) {
|
|
37
|
+
const raw = state.verdicts;
|
|
38
|
+
if (!Array.isArray(raw))
|
|
39
|
+
return [];
|
|
40
|
+
return raw.filter((row) => row !== null &&
|
|
41
|
+
typeof row === 'object' &&
|
|
42
|
+
!Array.isArray(row) &&
|
|
43
|
+
typeof row.verdict === 'string');
|
|
44
|
+
}
|
|
45
|
+
/** The one place a `—` is written for a value the source did not report — a
|
|
46
|
+
* blank cell reads as a zero; a dash reads as "not reported". */
|
|
47
|
+
function cell(value) {
|
|
48
|
+
if (value === null || value === undefined || value === '')
|
|
49
|
+
return '—';
|
|
50
|
+
if (value === true)
|
|
51
|
+
return 'yes';
|
|
52
|
+
if (value === false)
|
|
53
|
+
return 'no';
|
|
54
|
+
return String(value).replace(/\|/g, '\\|').replace(/\n/g, ' ');
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Render the shown rows as one markdown table. Columns are the FIRST row's
|
|
58
|
+
* own keys in declaration order — the chart writes its rows, so the chart
|
|
59
|
+
* owns the column vocabulary; the bridge only renders it.
|
|
60
|
+
*/
|
|
61
|
+
export function renderVerdictTable(rows) {
|
|
62
|
+
if (rows.length === 0)
|
|
63
|
+
return 'No rows in the projected set.';
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
65
|
+
const columns = Object.keys(rows[0]);
|
|
66
|
+
const head = `| ${columns.join(' | ')} |\n|${columns.map(() => '---').join('|')}|\n`;
|
|
67
|
+
return (head +
|
|
68
|
+
rows.map((row) => `| ${columns.map((column) => cell(row[column])).join(' | ')} |`).join('\n'));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Find the named decider in the chart's static structure (root graph plus
|
|
72
|
+
* statically declared subflows) and read its branches. Loop-ref stubs are
|
|
73
|
+
* skipped FIRST — they deliberately violate node-id uniqueness.
|
|
74
|
+
*/
|
|
75
|
+
export function resolveDecider(chart, decider) {
|
|
76
|
+
const spellings = new Set([decider]);
|
|
77
|
+
const declared = new Map();
|
|
78
|
+
const visited = new Set();
|
|
79
|
+
const walk = (node) => {
|
|
80
|
+
if (node === undefined || node.isLoopRef === true || visited.has(node))
|
|
81
|
+
return;
|
|
82
|
+
visited.add(node);
|
|
83
|
+
if ((node.id === decider || node.name === decider) && (node.children?.length ?? 0) > 0) {
|
|
84
|
+
if (node.id !== undefined)
|
|
85
|
+
spellings.add(node.id);
|
|
86
|
+
if (node.name !== undefined)
|
|
87
|
+
spellings.add(node.name);
|
|
88
|
+
for (const child of node.children ?? []) {
|
|
89
|
+
const branch = child.branchId ?? child.id;
|
|
90
|
+
if (branch === undefined)
|
|
91
|
+
continue;
|
|
92
|
+
const meaning = child.description ?? child.name;
|
|
93
|
+
if (meaning !== undefined && !declared.has(branch))
|
|
94
|
+
declared.set(branch, meaning);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
for (const child of node.children ?? [])
|
|
98
|
+
walk(child);
|
|
99
|
+
walk(node.next);
|
|
100
|
+
};
|
|
101
|
+
walk(chart.root);
|
|
102
|
+
for (const subflow of Object.values(chart.subflows ?? {})) {
|
|
103
|
+
walk(subflow.root);
|
|
104
|
+
}
|
|
105
|
+
return { spellings, declared };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* A tiny flow recorder capturing the named decider's decide() evidence as it
|
|
109
|
+
* fires — collected DURING the traversal, never reconstructed after. Rule
|
|
110
|
+
* labels are harvested for every rule the evidence lists (matched or not):
|
|
111
|
+
* a rule that was evaluated has spoken its label, whichever branch won.
|
|
112
|
+
*
|
|
113
|
+
* A decider inside a subflow (including a generated fan-out branch) reports
|
|
114
|
+
* itself PATH-PREFIXED (`per-subject~0/Protection posture`), so the match is
|
|
115
|
+
* on the LAST `/`-segment — the same last-delimiter reading every upstream
|
|
116
|
+
* parser of these paths uses, which is what keeps the generated-branch
|
|
117
|
+
* marker opaque here.
|
|
118
|
+
*/
|
|
119
|
+
export function meaningsRecorder(identity) {
|
|
120
|
+
const observed = new Map();
|
|
121
|
+
const lastSegment = (path) => path.slice(path.lastIndexOf('/') + 1);
|
|
122
|
+
const recorder = {
|
|
123
|
+
id: 'runbook-verdict-meanings',
|
|
124
|
+
onDecision(event) {
|
|
125
|
+
if (!identity.spellings.has(lastSegment(event.decider)))
|
|
126
|
+
return;
|
|
127
|
+
const evidence = event.evidence;
|
|
128
|
+
for (const rule of evidence?.rules ?? []) {
|
|
129
|
+
if (typeof rule.branch === 'string' && typeof rule.label === 'string') {
|
|
130
|
+
observed.set(rule.branch, rule.label);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
return { recorder, observed };
|
|
136
|
+
}
|
|
137
|
+
/** Compose the final meanings: declared branches first, observed rule labels
|
|
138
|
+
* winning where both speak (the rule is the sharper sentence). Undefined
|
|
139
|
+
* when neither source produced anything — absent, never `{}`. */
|
|
140
|
+
export function composeMeanings(identity, observed) {
|
|
141
|
+
const meanings = {};
|
|
142
|
+
for (const [branch, meaning] of identity.declared)
|
|
143
|
+
meanings[branch] = meaning;
|
|
144
|
+
for (const [branch, label] of observed)
|
|
145
|
+
meanings[branch] = label;
|
|
146
|
+
return Object.keys(meanings).length > 0 ? meanings : undefined;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=verdicts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verdicts.js","sourceRoot":"","sources":["../../../../src/core/runbook/verdicts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runbook/walk — the recorded walk: projection law, counters, mint.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: pure projection (`projectWalk`) + one guarded side effect
|
|
5
|
+
* (`mintWalk`, which files the artifact and NEVER fails the answer).
|
|
6
|
+
* Role: core/runbook. The walk is not a debugging extra — a procedure that
|
|
7
|
+
* cannot show how it reached a verdict is a procedure somebody has
|
|
8
|
+
* to take on trust.
|
|
9
|
+
* Emits: nothing (the artifact capability emits its own `artifacts.*`).
|
|
10
|
+
*
|
|
11
|
+
* THE CAP LAW, and why a head slice is the wrong cap: in a chart walk the
|
|
12
|
+
* per-key reads and writes come FIRST and the decisions come LAST, so a
|
|
13
|
+
* naive head slice over a fleet sweep keeps four hundred writes and drops
|
|
14
|
+
* every decision — a walk with the walking taken out. When the whole thing
|
|
15
|
+
* does not fit, the CONTROL FLOW survives (stages, forks, subflows, and
|
|
16
|
+
* every `condition` entry carrying its decide() evidence) and the projection
|
|
17
|
+
* is DECLARED, so a reader knows which of the two they are holding.
|
|
18
|
+
*/
|
|
19
|
+
import type { ToolExecutionContext } from '../tools.js';
|
|
20
|
+
import type { WalkDescriptor } from './types.js';
|
|
21
|
+
/** The default row cap — a readable artifact, not an archive. The count is
|
|
22
|
+
* always reported, so a truncated walk says it is truncated instead of
|
|
23
|
+
* looking like a short run. */
|
|
24
|
+
export declare const DEFAULT_WALK_CAP = 500;
|
|
25
|
+
/** A narrative entry as this module reads it. `rawValue` is deliberately NOT
|
|
26
|
+
* in the list: it is a LIVE reference into engine memory and has no business
|
|
27
|
+
* in a value checked into an artifact store. */
|
|
28
|
+
export interface NarrativeEntryView {
|
|
29
|
+
readonly type: string;
|
|
30
|
+
readonly text: string;
|
|
31
|
+
readonly depth: number;
|
|
32
|
+
readonly stageName?: string;
|
|
33
|
+
readonly stageId?: string;
|
|
34
|
+
readonly runtimeStageId?: string;
|
|
35
|
+
readonly subflowId?: string;
|
|
36
|
+
}
|
|
37
|
+
/** One walk row — plain data by construction (every field projected). */
|
|
38
|
+
export interface WalkRow {
|
|
39
|
+
readonly step: number;
|
|
40
|
+
readonly type: string;
|
|
41
|
+
readonly depth: number;
|
|
42
|
+
readonly stage: string | null;
|
|
43
|
+
readonly stage_id: string | null;
|
|
44
|
+
readonly runtime_stage_id: string | null;
|
|
45
|
+
readonly subflow: string | null;
|
|
46
|
+
readonly text: string;
|
|
47
|
+
}
|
|
48
|
+
/** The pure projection result — rows plus truthful counters. */
|
|
49
|
+
export interface ProjectedWalk {
|
|
50
|
+
readonly rows: readonly WalkRow[];
|
|
51
|
+
readonly projection: 'full' | 'control-flow';
|
|
52
|
+
readonly shown: number;
|
|
53
|
+
readonly total: number;
|
|
54
|
+
readonly complete: boolean;
|
|
55
|
+
}
|
|
56
|
+
/** Apply the cap law. Counters are about the WHOLE narrative (`total`), so a
|
|
57
|
+
* projected walk cannot read as a short run. */
|
|
58
|
+
export declare function projectWalk(entries: readonly NarrativeEntryView[], cap: number): ProjectedWalk;
|
|
59
|
+
/** What the mint needs from the call. */
|
|
60
|
+
export interface WalkMintFacts {
|
|
61
|
+
readonly toolName: string;
|
|
62
|
+
readonly toolCallId: string;
|
|
63
|
+
readonly runId?: string;
|
|
64
|
+
readonly stepsExecuted: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* File the walk and build the descriptor. THE SPINE ALWAYS GETS A
|
|
68
|
+
* DESCRIPTOR: with no store attached, or when the mint fails, the counters
|
|
69
|
+
* still travel and the note names why there is no ticket — a failed mint
|
|
70
|
+
* costs the TICKET, never the answer and never the counts.
|
|
71
|
+
*/
|
|
72
|
+
export declare function mintWalk(ctx: ToolExecutionContext, projected: ProjectedWalk, facts: WalkMintFacts): Promise<WalkDescriptor>;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runbook/walk — the recorded walk: projection law, counters, mint.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: pure projection (`projectWalk`) + one guarded side effect
|
|
5
|
+
* (`mintWalk`, which files the artifact and NEVER fails the answer).
|
|
6
|
+
* Role: core/runbook. The walk is not a debugging extra — a procedure that
|
|
7
|
+
* cannot show how it reached a verdict is a procedure somebody has
|
|
8
|
+
* to take on trust.
|
|
9
|
+
* Emits: nothing (the artifact capability emits its own `artifacts.*`).
|
|
10
|
+
*
|
|
11
|
+
* THE CAP LAW, and why a head slice is the wrong cap: in a chart walk the
|
|
12
|
+
* per-key reads and writes come FIRST and the decisions come LAST, so a
|
|
13
|
+
* naive head slice over a fleet sweep keeps four hundred writes and drops
|
|
14
|
+
* every decision — a walk with the walking taken out. When the whole thing
|
|
15
|
+
* does not fit, the CONTROL FLOW survives (stages, forks, subflows, and
|
|
16
|
+
* every `condition` entry carrying its decide() evidence) and the projection
|
|
17
|
+
* is DECLARED, so a reader knows which of the two they are holding.
|
|
18
|
+
*/
|
|
19
|
+
import { CHART_WALK_ARTIFACT_KIND, chartWalkPutInput } from '../../artifacts/recordingArtifact.js';
|
|
20
|
+
/** The default row cap — a readable artifact, not an archive. The count is
|
|
21
|
+
* always reported, so a truncated walk says it is truncated instead of
|
|
22
|
+
* looking like a short run. */
|
|
23
|
+
export const DEFAULT_WALK_CAP = 500;
|
|
24
|
+
function toWalkRow(entry, step) {
|
|
25
|
+
return {
|
|
26
|
+
step,
|
|
27
|
+
type: entry.type,
|
|
28
|
+
depth: entry.depth,
|
|
29
|
+
stage: entry.stageName ?? null,
|
|
30
|
+
stage_id: entry.stageId ?? null,
|
|
31
|
+
runtime_stage_id: entry.runtimeStageId ?? null,
|
|
32
|
+
subflow: entry.subflowId ?? null,
|
|
33
|
+
text: entry.text,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Apply the cap law. Counters are about the WHOLE narrative (`total`), so a
|
|
37
|
+
* projected walk cannot read as a short run. */
|
|
38
|
+
export function projectWalk(entries, cap) {
|
|
39
|
+
const full = entries.length <= cap;
|
|
40
|
+
const projection = full ? 'full' : 'control-flow';
|
|
41
|
+
const chosen = full ? entries : entries.filter((entry) => entry.type !== 'step');
|
|
42
|
+
const rows = chosen.slice(0, cap).map(toWalkRow);
|
|
43
|
+
return {
|
|
44
|
+
rows,
|
|
45
|
+
projection,
|
|
46
|
+
shown: rows.length,
|
|
47
|
+
total: entries.length,
|
|
48
|
+
complete: rows.length === entries.length,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** The descriptor's standing sentence, plus the projection clause when the
|
|
52
|
+
* control flow is what survived. */
|
|
53
|
+
function walkNote(projection) {
|
|
54
|
+
return ("The chart's own walk, one row per execution step. The `condition` rows carry the " +
|
|
55
|
+
'rule that matched, the values it compared and the branch it chose — that is where a ' +
|
|
56
|
+
'verdict can be checked rather than taken on trust.' +
|
|
57
|
+
(projection === 'control-flow'
|
|
58
|
+
? ' This one is the CONTROL-FLOW projection: the walk did not fit, so the stages, ' +
|
|
59
|
+
'forks, subflows and decisions are here and the per-key reads and writes are not.'
|
|
60
|
+
: ''));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* File the walk and build the descriptor. THE SPINE ALWAYS GETS A
|
|
64
|
+
* DESCRIPTOR: with no store attached, or when the mint fails, the counters
|
|
65
|
+
* still travel and the note names why there is no ticket — a failed mint
|
|
66
|
+
* costs the TICKET, never the answer and never the counts.
|
|
67
|
+
*/
|
|
68
|
+
export async function mintWalk(ctx, projected, facts) {
|
|
69
|
+
const base = {
|
|
70
|
+
rows: projected.rows.length,
|
|
71
|
+
steps_executed: facts.stepsExecuted,
|
|
72
|
+
projection: projected.projection,
|
|
73
|
+
shown: projected.shown,
|
|
74
|
+
total: projected.total,
|
|
75
|
+
complete: projected.complete,
|
|
76
|
+
walk_segment: 'full',
|
|
77
|
+
};
|
|
78
|
+
if (!ctx.hasArtifacts || projected.rows.length === 0) {
|
|
79
|
+
return {
|
|
80
|
+
...base,
|
|
81
|
+
note: projected.rows.length === 0
|
|
82
|
+
? 'The run produced no narrative entries, so there was no walk to file.'
|
|
83
|
+
: walkNote(projected.projection) +
|
|
84
|
+
' No artifact store is attached to this run, so the walk was recorded but not ' +
|
|
85
|
+
'filed — the counters above are still the truth about it.',
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const meta = await ctx.artifacts.put(chartWalkPutInput([...projected.rows], {
|
|
90
|
+
toolName: facts.toolName,
|
|
91
|
+
toolCallId: facts.toolCallId,
|
|
92
|
+
...(facts.runId !== undefined && { runId: facts.runId }),
|
|
93
|
+
}));
|
|
94
|
+
return {
|
|
95
|
+
ref: meta.ref,
|
|
96
|
+
kind: CHART_WALK_ARTIFACT_KIND,
|
|
97
|
+
...base,
|
|
98
|
+
note: walkNote(projected.projection),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
return {
|
|
103
|
+
...base,
|
|
104
|
+
note: walkNote(projected.projection) +
|
|
105
|
+
` The walk could not be filed (${err instanceof Error ? err.message : String(err)}) — ` +
|
|
106
|
+
'the mint failure cost the ticket, never the answer.',
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=walk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.js","sourceRoot":"","sources":["../../../../src/core/runbook/walk.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/core/tools.d.ts
CHANGED
|
@@ -208,6 +208,41 @@ export interface Tool<TArgs = Record<string, unknown>, TResult = unknown> {
|
|
|
208
208
|
* tool is never that check's subject, byte-identical.
|
|
209
209
|
*/
|
|
210
210
|
readonly argumentsFrom?: readonly string[];
|
|
211
|
+
/**
|
|
212
|
+
* THE NAMED INGREDIENT TOOLS THIS TOOL IS COMPOSED OF (9.76.0) — the
|
|
213
|
+
* registered tools its body calls through the run's own dispatch
|
|
214
|
+
* (`ctx.tools`), declared by the author, never inferred.
|
|
215
|
+
*
|
|
216
|
+
* Consumer-side readers, which is what earns it a place here (the
|
|
217
|
+
* `resultKind` / `argumentsFrom` law — a declaration rails read, nothing
|
|
218
|
+
* that governs execution): the agent-build drift gate asserts every named
|
|
219
|
+
* ingredient is a registered tool, so a runbook whose inventory tool was
|
|
220
|
+
* renamed fails the BUILD by name instead of failing its first run; and it
|
|
221
|
+
* joins the MCP `_meta` declaration list so a composed tool served over the
|
|
222
|
+
* wire says what it is made of.
|
|
223
|
+
*
|
|
224
|
+
* Checked at AGENT BUILD, not at definition — the ingredients need not
|
|
225
|
+
* exist before this tool is defined, and the catalog is only complete once
|
|
226
|
+
* every `.tool()` registration has landed. Tools delivered by a
|
|
227
|
+
* `ToolProvider` are invisible to the check (there is no build-time list);
|
|
228
|
+
* with a provider configured the gate warns instead of refusing.
|
|
229
|
+
* Omitted → nothing is checked, byte-identical.
|
|
230
|
+
*/
|
|
231
|
+
readonly composedOf?: readonly string[];
|
|
232
|
+
/**
|
|
233
|
+
* WHETHER THIS TOOL'S PROCEDURE CAN RAISE AN APPROVAL GATE (9.76.0) — a
|
|
234
|
+
* mid-run pause that asks a human before continuing. Declared, never
|
|
235
|
+
* inferred (the `capabilities` law): the framework cannot see through a
|
|
236
|
+
* tool boundary into an inner chart that gates.
|
|
237
|
+
*
|
|
238
|
+
* Consumer-side readers: composition-time checks that must refuse a gating
|
|
239
|
+
* tool where a pause cannot be resumed (a fan-out branch — the runbook
|
|
240
|
+
* grammar's compiler is the named reader). It does not govern execution;
|
|
241
|
+
* the runtime pause refusal remains the backstop for a tool that omits it.
|
|
242
|
+
* `false` is a declaration too ("this procedure never gates"), distinct
|
|
243
|
+
* from saying nothing. Omitted → byte-identical.
|
|
244
|
+
*/
|
|
245
|
+
readonly gates?: boolean;
|
|
211
246
|
/**
|
|
212
247
|
* FINGERPRINT THE REPEATED-CALL LEDGER ON ARGUMENTS ALONE (9.62.0) —
|
|
213
248
|
* `'arguments'` tells `core/agent/repeatedCall.ts` that this tool's own
|
|
@@ -349,6 +384,67 @@ export declare function assertToolOwner(toolName: string, owner: ToolOwner | und
|
|
|
349
384
|
* on a declaration a remote server sent.
|
|
350
385
|
*/
|
|
351
386
|
export declare function assertArgumentsFrom(toolName: string, argumentsFrom: readonly string[] | undefined): void;
|
|
387
|
+
/**
|
|
388
|
+
* Refuse a `composedOf` list that could never be drift-checked, at definition
|
|
389
|
+
* time — the {@link assertArgumentsFrom} law applied to composition: the
|
|
390
|
+
* agent-build gate joins on these names, and a blank one — or a tool composed
|
|
391
|
+
* of itself — would join the wrong subjects or none. The REGISTRATION check
|
|
392
|
+
* (is every named ingredient actually registered?) deliberately does NOT
|
|
393
|
+
* happen here: the ingredients need not exist before this tool is defined,
|
|
394
|
+
* and only the agent build sees the complete catalog.
|
|
395
|
+
*/
|
|
396
|
+
export declare function assertComposedOf(toolName: string, composedOf: readonly string[] | undefined): void;
|
|
397
|
+
/**
|
|
398
|
+
* Refuse a `gates` declaration that is not a boolean, at definition time.
|
|
399
|
+
* Trivial for anyone the compiler vets; load-bearing at the MCP ingest
|
|
400
|
+
* boundary, where a foreign server can put anything under the key and a
|
|
401
|
+
* truthy string would silently declare a gate nobody wrote.
|
|
402
|
+
*/
|
|
403
|
+
export declare function assertGates(toolName: string, gates: boolean | undefined): void;
|
|
404
|
+
/** Options for one {@link ToolDispatch.call}. */
|
|
405
|
+
export interface ToolDispatchCallOptions {
|
|
406
|
+
/** Abort signal for the inner call. Defaults to the outer call's own. */
|
|
407
|
+
readonly signal?: AbortSignal;
|
|
408
|
+
/**
|
|
409
|
+
* Declare an inner ABSENCE survivable (9.76.0). By default a dispatch
|
|
410
|
+
* consumer that composes answers (runbookAsTool) propagates an inner
|
|
411
|
+
* `absent()` as its own answer — "the inventory found nothing" IS the
|
|
412
|
+
* runbook's result, and pretending to a verdict over it would be the
|
|
413
|
+
* confident-partial-answer failure. Pass `true` when the caller can carry
|
|
414
|
+
* on without this source and will state the gap itself (usually as a
|
|
415
|
+
* coverage entry). The raw dispatch delivered on `ctx.tools` returns every
|
|
416
|
+
* result untouched either way — the propagation policy belongs to the
|
|
417
|
+
* consumer that wraps it.
|
|
418
|
+
*/
|
|
419
|
+
readonly allowAbsent?: boolean;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* The run's own tool dispatch, delivered at execute time as `ctx.tools`
|
|
423
|
+
* (9.76.0) — how one tool's body calls ANOTHER registered tool through the
|
|
424
|
+
* same map the model dispatches by, instead of importing its module and
|
|
425
|
+
* building a second query stack.
|
|
426
|
+
*
|
|
427
|
+
* What it sees: the agent's static catalog (`.tool()` registrations plus
|
|
428
|
+
* skill-carried tools) — the same dispatch map the tool-calls handler uses.
|
|
429
|
+
* Tools delivered by a `ToolProvider` are NOT visible (there is no build-time
|
|
430
|
+
* list), a stated caveat, not an accident.
|
|
431
|
+
*
|
|
432
|
+
* What an inner call gets: the outer call's own facts (credentials, signal,
|
|
433
|
+
* progress) with `hasArtifacts: false` — an inner tool must not mint claim
|
|
434
|
+
* tickets competing with the composed answer's own — and a derived
|
|
435
|
+
* `toolCallId` naming the outer call it belongs to. A declared `needs` is
|
|
436
|
+
* resolved before the inner execute (fail-closed: a service that requires
|
|
437
|
+
* interactive consent refuses by name — an inner call cannot pause).
|
|
438
|
+
*/
|
|
439
|
+
export interface ToolDispatch {
|
|
440
|
+
/** Is this name in the dispatch map? Provider-delivered tools answer false. */
|
|
441
|
+
has(name: string): boolean;
|
|
442
|
+
/**
|
|
443
|
+
* Execute a registered tool and return its result exactly as returned —
|
|
444
|
+
* a coverage envelope arrives as the envelope, an absence as the absence.
|
|
445
|
+
*/
|
|
446
|
+
call(name: string, args: unknown, opts?: ToolDispatchCallOptions): Promise<unknown>;
|
|
447
|
+
}
|
|
352
448
|
/** Runtime context passed to tool.execute(). */
|
|
353
449
|
export interface ToolExecutionContext {
|
|
354
450
|
/** Unique id of THIS tool invocation (matches stream.tool_start.toolCallId). */
|
|
@@ -392,6 +488,15 @@ export interface ToolExecutionContext {
|
|
|
392
488
|
/** The credential resolved for this tool's declared `needs` (declare-and-push).
|
|
393
489
|
* Present only when the tool declared a need and it resolved successfully. */
|
|
394
490
|
readonly credential?: Credential;
|
|
491
|
+
/**
|
|
492
|
+
* The run's own tool dispatch (9.76.0) — see {@link ToolDispatch}. Present
|
|
493
|
+
* on the agent's dispatch paths; ABSENT at doors with no dispatch map
|
|
494
|
+
* (`mcpServe`, the offline trace context, a hand-built context in a test).
|
|
495
|
+
* Absent and empty are different facts: branch on the absence rather than
|
|
496
|
+
* optional-chaining past it, and prefer a fail-closed refusal (the
|
|
497
|
+
* `credentials` law) when your tool cannot work without it.
|
|
498
|
+
*/
|
|
499
|
+
readonly tools?: ToolDispatch;
|
|
395
500
|
/**
|
|
396
501
|
* Report progress from INSIDE a long-running tool — "hop 3 of 12 done", said
|
|
397
502
|
* mid-`execute`, while the call is still running.
|
|
@@ -575,6 +680,13 @@ export interface DefineToolOptions<TArgs, TResult> {
|
|
|
575
680
|
readonly owner?: ToolOwner;
|
|
576
681
|
/** The declared argument grounds — see {@link Tool.argumentsFrom}. */
|
|
577
682
|
readonly argumentsFrom?: readonly string[];
|
|
683
|
+
/** The named ingredient tools this tool calls through `ctx.tools` — see
|
|
684
|
+
* {@link Tool.composedOf}. Drift-checked at agent build, when the catalog
|
|
685
|
+
* is complete. Omitted → nothing checked, byte-identical. */
|
|
686
|
+
readonly composedOf?: readonly string[];
|
|
687
|
+
/** Whether this tool's procedure can raise an approval gate — see
|
|
688
|
+
* {@link Tool.gates}. Omitted → nothing declared, byte-identical. */
|
|
689
|
+
readonly gates?: boolean;
|
|
578
690
|
/** Fingerprint the repeated-call ledger on arguments alone, ignoring this
|
|
579
691
|
* tool's own result — see {@link Tool.repeatedWhen}. Omitted →
|
|
580
692
|
* byte-identical (the ledger keeps comparing results, as always). */
|