@sema-agent/core 7.8.0 → 7.9.1

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 (103) hide show
  1. package/CHANGELOG.md +75 -1
  2. package/dist/agents/subagent.d.ts +1 -1
  3. package/dist/core/ask-origin.d.ts +16 -1
  4. package/dist/core/ask-origin.js +5 -1
  5. package/dist/core/checkpoint-store.d.ts +36 -35
  6. package/dist/core/effective-path-target.d.ts +43 -0
  7. package/dist/core/effective-path-target.js +56 -0
  8. package/dist/core/engine-notice.d.ts +8 -0
  9. package/dist/core/fs-write-gate-policy.js +2 -1
  10. package/dist/core/gate-lanes.d.ts +1 -0
  11. package/dist/core/gate-lanes.js +60 -28
  12. package/dist/core/gate-outcome.d.ts +8 -4
  13. package/dist/core/gate-outcome.js +2 -1
  14. package/dist/core/governance-codes.d.ts +1 -1
  15. package/dist/core/governance-codes.js +2 -0
  16. package/dist/core/hooks.d.ts +66 -32
  17. package/dist/core/mcp-injection-drop.d.ts +74 -0
  18. package/dist/core/mcp-injection-drop.js +27 -0
  19. package/dist/core/permission-rule-consent.d.ts +29 -36
  20. package/dist/core/permission-rule-consent.js +110 -60
  21. package/dist/core/permission-rule-model.d.ts +311 -96
  22. package/dist/core/permission-rule-model.js +309 -50
  23. package/dist/core/permission-rule-org.d.ts +19 -12
  24. package/dist/core/permission-rule-org.js +13 -16
  25. package/dist/core/permission-rule-provider.d.ts +10 -6
  26. package/dist/core/permission-rule-provider.js +12 -8
  27. package/dist/core/permission-rule-session.d.ts +7 -6
  28. package/dist/core/permission-rule-session.js +29 -10
  29. package/dist/core/permission-rule-store.d.ts +40 -18
  30. package/dist/core/permission-rule-store.js +68 -42
  31. package/dist/core/permission-rule-sync.d.ts +9 -3
  32. package/dist/core/permission-rule-sync.js +29 -25
  33. package/dist/core/permission-rule-syntax.d.ts +30 -0
  34. package/dist/core/permission-rule-syntax.js +44 -0
  35. package/dist/core/permission-rules.d.ts +56 -33
  36. package/dist/core/permission-rules.js +88 -55
  37. package/dist/core/persisted-rule-arms.d.ts +61 -0
  38. package/dist/core/persisted-rule-arms.js +50 -0
  39. package/dist/core/runner/active-skill-scope.js +2 -1
  40. package/dist/core/runner/contracts.d.ts +21 -2
  41. package/dist/core/runner/permission-rule-lanes.d.ts +42 -27
  42. package/dist/core/runner/permission-rule-lanes.js +25 -21
  43. package/dist/core/runner/prepare-gate-stations.js +1 -1
  44. package/dist/core/runner/prepare-safety-scan.js +8 -2
  45. package/dist/core/runner/prepare-task.js +1 -1
  46. package/dist/core/runner/resume-admission.d.ts +53 -0
  47. package/dist/core/runner/resume-admission.js +83 -0
  48. package/dist/core/runner/resume-apply.d.ts +50 -0
  49. package/dist/core/runner/resume-apply.js +184 -0
  50. package/dist/core/runner/resume-checkpoint-screen.d.ts +18 -0
  51. package/dist/core/runner/resume-checkpoint-screen.js +108 -0
  52. package/dist/core/runner/resume-claim.d.ts +32 -0
  53. package/dist/core/runner/resume-claim.js +27 -0
  54. package/dist/core/runner/resume-internals-and-config.d.ts +33 -0
  55. package/dist/core/runner/resume-internals-and-config.js +50 -0
  56. package/dist/core/runner/resume-policy-outcome.d.ts +31 -0
  57. package/dist/core/runner/resume-policy-outcome.js +127 -0
  58. package/dist/core/runner/resume-preflight.d.ts +40 -0
  59. package/dist/core/runner/resume-preflight.js +122 -0
  60. package/dist/core/runner/resume-review-outcome.d.ts +30 -0
  61. package/dist/core/runner/resume-review-outcome.js +88 -0
  62. package/dist/core/runner/run-harness-handlers.js +1 -1
  63. package/dist/core/runner/runtask.d.ts +20 -0
  64. package/dist/core/runner/runtask.js +85 -734
  65. package/dist/core/runner/session-rule-policy.js +2 -1
  66. package/dist/core/runner/tool-end-body.d.ts +12 -5
  67. package/dist/core/runner/tool-end-body.js +5 -5
  68. package/dist/core/runner/tool-face-overlay.js +22 -3
  69. package/dist/core/runner/tool-output-projection.d.ts +9 -6
  70. package/dist/core/runner/tool-output-projection.js +1 -18
  71. package/dist/core/runner/turn-attachments.d.ts +2 -2
  72. package/dist/core/sensitive-path-policy.js +5 -3
  73. package/dist/core/shell-lexer.d.ts +47 -0
  74. package/dist/core/shell-lexer.js +478 -0
  75. package/dist/core/shell-scan.d.ts +60 -0
  76. package/dist/core/shell-scan.js +183 -0
  77. package/dist/core/shell-wrapper-table.d.ts +297 -0
  78. package/dist/core/shell-wrapper-table.js +58 -0
  79. package/dist/core/store-contracts/permission-rule-sync-contract.js +29 -10
  80. package/dist/core/tool-catalog-entries.js +6 -6
  81. package/dist/core/tool-face.d.ts +80 -4
  82. package/dist/core/tool-face.js +10 -0
  83. package/dist/core/tool-policy.d.ts +1 -6
  84. package/dist/core/tool-registry.d.ts +8 -11
  85. package/dist/core/tool-registry.js +5 -2
  86. package/dist/core/tool-roster.d.ts +20 -2
  87. package/dist/core/tool-roster.js +36 -8
  88. package/dist/index.d.ts +7 -4
  89. package/dist/index.js +6 -3
  90. package/dist/stores/file/checkpoint-store.js +1 -1
  91. package/dist/stores/file/permission-rule-store.d.ts +28 -23
  92. package/dist/stores/file/permission-rule-store.js +64 -16
  93. package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
  94. package/dist/tools/fs/fs-pdf.d.ts +1 -1
  95. package/dist/tools/fs/fs-search-tools.d.ts +3 -2
  96. package/dist/tools/fs/fs-search-tools.js +17 -9
  97. package/dist/tools/fs/index.js +1 -1
  98. package/dist/tools/fs/notebook.d.ts +1 -1
  99. package/dist/tools/fs/safety.d.ts +1 -1
  100. package/dist/tools/fs/search.d.ts +0 -8
  101. package/dist/tools/fs/search.js +0 -23
  102. package/package.json +1 -1
  103. package/test/export-surface.snapshot.json +99 -11
@@ -15,7 +15,7 @@ export const TOOL_CATALOG_ENTRIES = [
15
15
  cards: ["text", "notebook", "file_unchanged", "image", "document"],
16
16
  face: {
17
17
  family: "file-read", effect: "read", contract: c("core.read@1"),
18
- pathTarget: { param: "file_path", aliases: ["path"], access: "read" },
18
+ pathTarget: { param: "file_path", aliases: ["path"], access: "read", base: "cwd", absent: "none" },
19
19
  ruleFace: { params: ["file_path", "path", "offset", "limit", "pages"] },
20
20
  renderHints: { summaryParams: ["file_path"] },
21
21
  offload: false, compactable: true, budgetExempt: true,
@@ -26,7 +26,7 @@ export const TOOL_CATALOG_ENTRIES = [
26
26
  cards: ["edit"],
27
27
  face: {
28
28
  family: "file-write", effect: "write", contract: c("core.edit@1"),
29
- pathTarget: { param: "file_path", aliases: ["path"], access: "edit", skillScopeEligible: true },
29
+ pathTarget: { param: "file_path", aliases: ["path"], access: "edit", skillScopeEligible: true, base: "cwd", absent: "none" },
30
30
  ruleFace: { params: ["file_path", "path", "old_string", "new_string", "replace_all"] },
31
31
  renderHints: { summaryParams: ["file_path"], approvalCard: "file-edit" },
32
32
  compactable: true,
@@ -37,7 +37,7 @@ export const TOOL_CATALOG_ENTRIES = [
37
37
  cards: ["create", "update"],
38
38
  face: {
39
39
  family: "file-write", effect: "write", contract: c("core.write@1"),
40
- pathTarget: { param: "file_path", aliases: ["path"], access: "create", skillScopeEligible: true },
40
+ pathTarget: { param: "file_path", aliases: ["path"], access: "create", skillScopeEligible: true, base: "cwd", absent: "none" },
41
41
  ruleFace: { params: ["file_path", "path", "content"] },
42
42
  renderHints: { summaryParams: ["file_path"], approvalCard: "file-write" },
43
43
  offload: false, compactable: true,
@@ -48,7 +48,7 @@ export const TOOL_CATALOG_ENTRIES = [
48
48
  cards: ["notebook-edit"],
49
49
  face: {
50
50
  family: "file-write", effect: "write", contract: c("core.notebook_edit@1"),
51
- pathTarget: { param: "notebook_path", aliases: ["path"], access: "edit" },
51
+ pathTarget: { param: "notebook_path", aliases: ["path"], access: "edit", base: "cwd", absent: "none" },
52
52
  ruleFace: { params: ["notebook_path", "path", "cell_id", "cell_type", "edit_mode", "new_source"] },
53
53
  renderHints: { userFacingName: "Edit Notebook", summaryParams: ["notebook_path"], approvalCard: "notebook-edit" },
54
54
  },
@@ -78,7 +78,7 @@ export const TOOL_CATALOG_ENTRIES = [
78
78
  cards: ["grep"],
79
79
  face: {
80
80
  family: "search", effect: "read", contract: c("core.grep@1"),
81
- pathTarget: { param: "path", access: "read" },
81
+ pathTarget: { param: "path", access: "read", base: "root", absent: "base" },
82
82
  ruleFace: { params: ["pattern", "path", "glob", "type", "output_mode", "head_limit", "offset", "multiline", "context", "ignore_case", "-i", "-n", "-o", "-A", "-B", "-C"] },
83
83
  renderHints: { userFacingName: "Search", summaryParams: ["pattern", "path"] },
84
84
  offloadThresholdChars: 20_000, compactable: true,
@@ -89,7 +89,7 @@ export const TOOL_CATALOG_ENTRIES = [
89
89
  cards: ["glob"],
90
90
  face: {
91
91
  family: "search", effect: "read", contract: c("core.glob@1"),
92
- pathTarget: { param: "path", access: "read" },
92
+ pathTarget: { param: "path", access: "read", base: "root", absent: "base", patternParam: "pattern" },
93
93
  ruleFace: { params: ["pattern", "path", "max_results"] },
94
94
  renderHints: { userFacingName: "Search", summaryParams: ["pattern", "path"] },
95
95
  compactable: true,
@@ -46,18 +46,94 @@ export type ToolApprovalCard = (typeof TOOL_APPROVAL_CARDS)[number];
46
46
  export declare const TOOL_PATH_ACCESSES: readonly ["read", "create", "edit"];
47
47
  export type ToolPathAccess = (typeof TOOL_PATH_ACCESSES)[number];
48
48
  /**
49
- * The parameter that names this tool's filesystem target, and how the target is touched. Present the
50
- * tool can be confirmed BY PATH (write confinement, sensitive-path guards, edited-file tracking, the
51
- * transcript-directory gate). `param` outranks every alias (NotebookEdit's `notebook_path` beats a decoy
49
+ * The BASE a RELATIVE spelling in the target slot resolves against the tool's OWN resolution base,
50
+ * DECLARED so every fence resolves the very path the tool will open instead of guessing one:
51
+ *
52
+ * - `cwd` — the live tracked working directory, falling back to the task root when no tracker moved
53
+ * (Read / Edit / Write / NotebookEdit: each hands `cwdRef.current` to `canonicalizeTarget` as its base);
54
+ * - `root` — the task root, always (Grep / Glob: their `path` describes say "relative to root", and the
55
+ * tools hand `rootCanonical` to the same resolver whatever the shell's `cd` did).
56
+ *
57
+ * Absent ⇒ `cwd`: the pre-declaration reading every fence took, kept as the floor for a face (a caller's,
58
+ * an MCP server's) that declares no base. This one word is the whole difference the fences had to model,
59
+ * and getting it wrong is SILENT — a rule about the path the tool really opens simply never fires.
60
+ */
61
+ export declare const TOOL_PATH_BASES: readonly ["cwd", "root"];
62
+ export type ToolPathBase = (typeof TOOL_PATH_BASES)[number];
63
+ /**
64
+ * What the call targets when the target slot carries NO usable spelling:
65
+ *
66
+ * - `none` — nothing. A file tool with no path names no file, so no path rule speaks about the call;
67
+ * - `base` — the resolution base ITSELF. A search tool with no `path` searches the WHOLE base, so a rule
68
+ * naming the base (or anything containing it) does reach the call.
69
+ *
70
+ * Absent ⇒ `none` (the pre-declaration reading: an absent slot was "no resolvable path" for every tool).
71
+ */
72
+ export declare const TOOL_PATH_ABSENCES: readonly ["none", "base"];
73
+ export type ToolPathAbsence = (typeof TOOL_PATH_ABSENCES)[number];
74
+ /**
75
+ * The parameter that names a tool's filesystem target, how the target is touched, and how a spelling in that
76
+ * slot RESOLVES — as a READER sees it, whichever side it came from. Present ⇔ the tool can be confirmed BY
77
+ * PATH (write confinement, sensitive-path guards, edited-file tracking, the transcript-directory gate, the
78
+ * permission-rule path family). `param` outranks every alias (NotebookEdit's `notebook_path` beats a decoy
52
79
  * `file_path`). `skillScopeEligible` (default false) is the SEPARATE authorization domain of the
53
80
  * active-skill `allowPaths` face — a confinable write tool is not automatically eligible there.
81
+ *
82
+ * ONE shape, two spellings: a DECLARATION ({@link ToolPathTarget}, what a catalog row / a `ToolSpec` / an
83
+ * MCP overlay writes) and the roster row's NORMALIZED form (`aliases` always an array, `skillScopeEligible`
84
+ * always a boolean) that the wire carries and the gate stamps on a call. Both are readable through this
85
+ * type, which is what every fence reads — the shape used to be re-declared at each of them, and a member
86
+ * added to one spelling silently never reached the others.
87
+ *
88
+ * The three RESOLUTION members are read by one function (`effectivePathTargetOf`, effective-path-target.ts)
89
+ * that every fence and the tools themselves go through: the declaration is the single source, so a fence
90
+ * and the tool it fences cannot resolve one call to two different files.
54
91
  */
55
- export interface ToolPathTarget {
92
+ export interface ToolCallPathTarget {
56
93
  param: string;
57
94
  aliases?: readonly string[];
58
95
  access: ToolPathAccess;
96
+ skillScopeEligible?: boolean;
97
+ /** How a RELATIVE spelling in `param` (or an alias) resolves. Absent ⇒ `cwd`. */
98
+ base?: ToolPathBase;
99
+ /** What the call targets when the slot is absent. Absent ⇒ `none`. */
100
+ absent?: ToolPathAbsence;
101
+ /**
102
+ * A top-level parameter whose ABSOLUTE glob pattern carries its own base directory (Glob's `pattern`:
103
+ * `/proj/secret/**` searches `/proj/secret` with no `path` at all). Consulted ONLY when the target slot
104
+ * is absent and `absent` is `base` — the tool's own precedence, in which an explicit `path` wins and a
105
+ * relative pattern leaves the base alone.
106
+ */
107
+ patternParam?: string;
108
+ }
109
+ /** The DECLARATION spelling of {@link ToolCallPathTarget}: what a catalog row, a `ToolSpec` or an MCP
110
+ * overlay writes. `skillScopeEligible` is narrowed to `true` — a declaration says "eligible" or says
111
+ * nothing; "eligible: false" is the absence, and spelling it would be a second way to say one thing. */
112
+ export interface ToolPathTarget extends ToolCallPathTarget {
59
113
  skillScopeEligible?: true;
60
114
  }
115
+ /**
116
+ * The NORMALIZED spelling of {@link ToolCallPathTarget}: what the roster MINTS, what the wire carries, and
117
+ * what the gate stamps on a call. `aliases` and `skillScopeEligible` are always present because the mint
118
+ * fills them — a guarantee a consumer reading a stamped face has always had, and one the shared reader type
119
+ * deliberately does not weaken (an optional member here would break `face.pathTarget.aliases.includes(…)`
120
+ * at compile time for every downstream that already reads it).
121
+ */
122
+ export interface ToolRosterPathTarget extends ToolCallPathTarget {
123
+ aliases: readonly string[];
124
+ skillScopeEligible: boolean;
125
+ }
126
+ /**
127
+ * The SLOT half of a target — which argument names the path — with the RESOLUTION half (`base` / `absent` /
128
+ * `patternParam`) dropped, so the reader falls back to the documented defaults.
129
+ *
130
+ * #635, from the adversarial round: the protective floor (design/388 B6 — a face that declares no target of
131
+ * its own is judged against the CATALOG's declaration for the name) rests on "naming a slot can only TIGHTEN
132
+ * a deny". Naming a slot does. Claiming how a FOREIGN tool of the same name RESOLVES that slot does not: a
133
+ * wrong claim moves the judged path to a different file, and the deny the floor exists to keep then misses.
134
+ * So the floor hands over the slot and keeps its mouth shut about the resolution.
135
+ */
136
+ export declare function pathTargetSlotOnly(pt: ToolCallPathTarget): ToolCallPathTarget;
61
137
  /**
62
138
  * The parameter vocabulary a permission rule (`Tool(param:pattern)`) may name. DERIVED by default from
63
139
  * the tool's schema: the SCALAR top-level parameters (string/number/integer/boolean and their enum/const/
@@ -2,6 +2,16 @@ export const TOOL_FAMILIES = ["shell", "file-read", "file-write", "search", "web
2
2
  export const TOOL_MOUNT_TAGS = ["hands", "backgroundTasks", "workflow", "delegation", "hostInternals", "peerLane", "scheduler", "memory", "scenario", "always", "optional"];
3
3
  export const TOOL_APPROVAL_CARDS = ["file-edit", "file-write", "notebook-edit", "shell", "fetch", "plan", "question", "generic"];
4
4
  export const TOOL_PATH_ACCESSES = ["read", "create", "edit"];
5
+ export const TOOL_PATH_BASES = ["cwd", "root"];
6
+ export const TOOL_PATH_ABSENCES = ["none", "base"];
7
+ export function pathTargetSlotOnly(pt) {
8
+ return {
9
+ param: pt.param,
10
+ access: pt.access,
11
+ ...(pt.aliases !== undefined ? { aliases: pt.aliases } : {}),
12
+ ...(pt.skillScopeEligible !== undefined ? { skillScopeEligible: pt.skillScopeEligible } : {}),
13
+ };
14
+ }
5
15
  export const TOOL_WIRE_NAME_MAX_CHARS = 128;
6
16
  export const TOOL_CONTRACT_MAX_CHARS = 64;
7
17
  export const TOOL_KEY_MAX_CHARS = 256;
@@ -4,12 +4,7 @@ import type { Settlement } from "./gate-outcome.js";
4
4
  /** design/388 B6 — the per-call face (see {@link ToolCallRequest.face}). */
5
5
  export interface ToolCallFace {
6
6
  family: import("./tool-face.js").ToolFamily;
7
- pathTarget?: {
8
- param: string;
9
- aliases: readonly string[];
10
- access: "read" | "create" | "edit";
11
- skillScopeEligible: boolean;
12
- };
7
+ pathTarget?: import("./tool-face.js").ToolRosterPathTarget;
13
8
  capabilityId: string;
14
9
  contractId: string;
15
10
  shapeDigest: string;
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * Layer-0 vocabulary: depends on the leaf catalog and the face vocabulary only.
12
12
  */
13
- import { type ToolCatalogEntry, type ToolMountTag, type ToolPathAccess } from "./tool-face.js";
13
+ import { type ToolCallPathTarget, type ToolCatalogEntry, type ToolMountTag, type ToolPathAccess } from "./tool-face.js";
14
14
  /** The whole static catalog, one frozen row per definition (design/388 §2.1 `describeToolCatalog()`).
15
15
  * Replaces the retired name-keyed exports `HAND_TOOL_EFFECTS` / `DEFAULT_BUDGET_EXEMPT_TOOLS` /
16
16
  * `COMPACTABLE_TOOLS`: filter this instead (`e.mountedBy.includes("hands")`, `e.face.budgetExempt`,
@@ -45,24 +45,21 @@ export interface ToolCallLike {
45
45
  toolName: string;
46
46
  args: unknown;
47
47
  face?: {
48
- pathTarget?: {
49
- param: string;
50
- aliases?: readonly string[];
51
- access: ToolPathAccess;
52
- };
48
+ pathTarget?: ToolCallPathTarget;
53
49
  } | undefined;
54
50
  }
55
- type CallPathTarget = {
56
- param: string;
57
- aliases?: readonly string[];
58
- access: ToolPathAccess;
59
- };
51
+ type CallPathTarget = ToolCallPathTarget;
60
52
  /**
61
53
  * design/388 B6/B17 — the path target a PROTECTIVE fence reads (a deny-list judging a write's target: sensitive paths,
62
54
  * frozen paths, write protection, the transcript gate; edit tracking): the object face's own declaration first, the
63
55
  * catalog's declaration for the NAME as the FLOOR — for a bare request (a policy invoked outside a Runner) and for a
64
56
  * face that declares none. Reading the catalog for an undeclared same-name tool can only TIGHTEN a deny-list (it adds
65
57
  * a slot to judge — the pre-388 posture, never wider), which is exactly why this floor is wrong for a grant.
58
+ *
59
+ * #635: "can only tighten" is true of the SLOT and false of the RESOLUTION, so the floor hands over the first and
60
+ * defaults the second (`pathTargetSlotOnly`). Telling a fence that a FOREIGN tool of the same name resolves its slot
61
+ * against the project root is a claim about someone else's implementation: get it wrong and the judged path moves to
62
+ * a different file, and the deny this floor exists to preserve simply misses.
66
63
  */
67
64
  export declare function protectivePathTargetOf(call: ToolCallLike): CallPathTarget | undefined;
68
65
  /**
@@ -1,4 +1,4 @@
1
- import { TOOL_MOUNT_TAGS } from "./tool-face.js";
1
+ import { TOOL_MOUNT_TAGS, pathTargetSlotOnly } from "./tool-face.js";
2
2
  import { ENGINE_CARDS, TOOL_CATALOG_ENTRIES } from "./tool-catalog-entries.js";
3
3
  export function describeToolCatalog() {
4
4
  return TOOL_CATALOG_ENTRIES;
@@ -49,7 +49,10 @@ export function pathTargetValue(args, pt) {
49
49
  return undefined;
50
50
  }
51
51
  export function protectivePathTargetOf(call) {
52
- return call.face?.pathTarget ?? pathTargetOf(call.toolName);
52
+ if (call.face?.pathTarget !== undefined)
53
+ return call.face.pathTarget;
54
+ const floor = pathTargetOf(call.toolName);
55
+ return floor === undefined || call.face === undefined ? floor : pathTargetSlotOnly(floor);
53
56
  }
54
57
  export function declaredPathTargetOf(call) {
55
58
  return call.face !== undefined ? call.face.pathTarget : pathTargetOf(call.toolName);
@@ -1,6 +1,6 @@
1
1
  import { Type, type Static, type TSchema } from "typebox";
2
2
  import type { AgentTool } from "../internal/harness-types.js";
3
- import { type ToolFamily, type ToolMountTag, type ToolPathTarget, type ToolRenderHints, type ToolRuleFace } from "./tool-face.js";
3
+ import { type ToolFamily, type ToolRosterPathTarget, type ToolMountTag, type ToolPathTarget, type ToolRenderHints, type ToolRuleFace } from "./tool-face.js";
4
4
  import type { ToolContentOrigin, ToolEffect } from "./tool-spec.js";
5
5
  export declare const ROSTER_SOURCES: readonly ["builtin", "caller", "host", "mcp", "a2a", "external", "synthetic"];
6
6
  export type RosterSource = (typeof ROSTER_SOURCES)[number];
@@ -55,6 +55,9 @@ export declare const ToolRosterEntry: Type.TObject<{
55
55
  aliases: Type.TArray<Type.TString>;
56
56
  access: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"create">, Type.TLiteral<"edit">]>;
57
57
  skillScopeEligible: Type.TBoolean;
58
+ base: Type.TOptional<Type.TUnion<[Type.TLiteral<"cwd">, Type.TLiteral<"root">]>>;
59
+ absent: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"base">]>>;
60
+ patternParam: Type.TOptional<Type.TString>;
58
61
  }>>;
59
62
  ruleFace: Type.TObject<{
60
63
  primaryParams: Type.TArray<Type.TString>;
@@ -126,6 +129,9 @@ export declare const ToolRoster: Type.TObject<{
126
129
  aliases: Type.TArray<Type.TString>;
127
130
  access: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"create">, Type.TLiteral<"edit">]>;
128
131
  skillScopeEligible: Type.TBoolean;
132
+ base: Type.TOptional<Type.TUnion<[Type.TLiteral<"cwd">, Type.TLiteral<"root">]>>;
133
+ absent: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"base">]>>;
134
+ patternParam: Type.TOptional<Type.TString>;
129
135
  }>>;
130
136
  ruleFace: Type.TObject<{
131
137
  primaryParams: Type.TArray<Type.TString>;
@@ -205,6 +211,9 @@ export declare const ToolRosterDelta: Type.TObject<{
205
211
  aliases: Type.TArray<Type.TString>;
206
212
  access: Type.TUnion<[Type.TLiteral<"read">, Type.TLiteral<"create">, Type.TLiteral<"edit">]>;
207
213
  skillScopeEligible: Type.TBoolean;
214
+ base: Type.TOptional<Type.TUnion<[Type.TLiteral<"cwd">, Type.TLiteral<"root">]>>;
215
+ absent: Type.TOptional<Type.TUnion<[Type.TLiteral<"none">, Type.TLiteral<"base">]>>;
216
+ patternParam: Type.TOptional<Type.TString>;
208
217
  }>>;
209
218
  ruleFace: Type.TObject<{
210
219
  primaryParams: Type.TArray<Type.TString>;
@@ -265,7 +274,7 @@ export declare function parkedToolFace(roster: ToolRoster | undefined, toolName:
265
274
  * partial face). This is the face every recheck of the row judges under, roster or no roster. */
266
275
  export declare function parkedCallFaceOf(pending: {
267
276
  family?: ToolFamily;
268
- pathTarget?: ToolRosterEntry["pathTarget"];
277
+ pathTarget?: ToolRosterPathTarget;
269
278
  capabilityId?: string;
270
279
  contractId?: string;
271
280
  shapeDigest?: string;
@@ -396,6 +405,13 @@ export declare class RosterBuilder {
396
405
  /** Which source a `TaskSpec.tools` entry mounts as: a definition carrying a CORE contract is a built-in the host chose
397
406
  * to mount; anything else is the caller's own tool. Identity follows the object, never the name. */
398
407
  export declare function callerMountSource(tool: AgentTool): RosterSource;
408
+ /** The card namespace a roster row owns (design/388 §2.2 ④) — ONE mint, read by the row and by the prepare door that
409
+ * judges a caller's `renderHints.resultCards` against it: `builtin:<name>` for engine-owned definitions,
410
+ * `<mcp|a2a>:<peer>/<tool>` for protocol tools, `<caller|external>:<contractId>` for everything the caller mounts. */
411
+ export declare function rosterCardId(source: RosterSource, toolName: string, peer: string | null, protocolTool: string, contractId: string): string;
412
+ /** The card namespace a `TaskSpec.tools` entry will own once mounted — the same mint the row makes, so the prepare
413
+ * door and the roster row cannot disagree about which namespace a caller card must live under. */
414
+ export declare function callerCardIdOf(tool: Pick<AgentTool, "name" | "parameters">): string;
399
415
  /** One row (design/388 §2.5). Every axis is read off the instance or the leg facts; nothing off a name table. */
400
416
  export declare function mintRosterEntry(tool: AgentTool, meta: RosterMountMeta, facts: RosterSnapshotFacts): ToolRosterEntry;
401
417
  /**
@@ -414,6 +430,8 @@ export declare class ToolRosterDeltaSeat {
414
430
  republish(): ToolRosterDelta | undefined;
415
431
  /** Install the stream sink; anything published before is flushed in order. */
416
432
  subscribe(sink: (delta: ToolRosterDelta) => void): void;
433
+ /** The leg ended: drop the sink so a late republish never reaches a closed stream (it buffers, bounded, unread). */
434
+ unsubscribe(): void;
417
435
  /** Take the buffered deltas (a consumer that polls instead of subscribing). */
418
436
  drain(): ToolRosterDelta[];
419
437
  }
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import { Type } from "typebox";
3
3
  import { getToolContract } from "../prompt-assembly/tool-catalog.js";
4
4
  import { protocolOf } from "./protocol-table.js";
5
- import { RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_CHARS, RENDER_HINT_MAX_LIST, TOOL_APPROVAL_CARDS, TOOL_FAMILIES, TOOL_KEYS_MAX, TOOL_KEY_MAX_CHARS, TOOL_MOUNT_TAGS, } from "./tool-face.js";
5
+ import { RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_CHARS, RENDER_HINT_MAX_LIST, TOOL_APPROVAL_CARDS, TOOL_FAMILIES, TOOL_KEYS_MAX, TOOL_KEY_MAX_CHARS, TOOL_MOUNT_TAGS, TOOL_PATH_ABSENCES, TOOL_PATH_BASES, } from "./tool-face.js";
6
6
  function lit(values) {
7
7
  return Type.Union(values.map((v) => Type.Literal(v)));
8
8
  }
@@ -42,7 +42,15 @@ export const ToolRosterEntry = Type.Object({
42
42
  contentOrigin: lit(["local", "execution", "external"]),
43
43
  contentOriginProvenance: lit(["declared", "server", "exempted", "default"]),
44
44
  family: lit(TOOL_FAMILIES),
45
- pathTarget: Type.Optional(Type.Object({ param: Key, aliases: Type.Array(Key), access: lit(["read", "create", "edit"]), skillScopeEligible: Type.Boolean() }, { additionalProperties: false })),
45
+ pathTarget: Type.Optional(Type.Object({
46
+ param: Key,
47
+ aliases: Type.Array(Key),
48
+ access: lit(["read", "create", "edit"]),
49
+ skillScopeEligible: Type.Boolean(),
50
+ base: Type.Optional(lit(TOOL_PATH_BASES)),
51
+ absent: Type.Optional(lit(TOOL_PATH_ABSENCES)),
52
+ patternParam: Type.Optional(Key),
53
+ }, { additionalProperties: false })),
46
54
  ruleFace: Type.Object({ primaryParams: Type.Array(Key), params: Type.Array(Key) }, { additionalProperties: false }),
47
55
  approvalPreview: Type.Boolean(),
48
56
  validateInput: Type.Boolean(),
@@ -335,17 +343,24 @@ export class RosterBuilder {
335
343
  export function callerMountSource(tool) {
336
344
  return getToolContract(tool, "caller").origin === "core" ? "builtin" : "caller";
337
345
  }
346
+ export function rosterCardId(source, toolName, peer, protocolTool, contractId) {
347
+ return source === "builtin" || source === "synthetic"
348
+ ? `builtin:${toolName}`
349
+ : source === "mcp" || source === "a2a"
350
+ ? `${source}:${peer}/${protocolTool}`
351
+ : `${source === "external" ? "external" : "caller"}:${contractId}`;
352
+ }
353
+ export function callerCardIdOf(tool) {
354
+ const t = tool;
355
+ return rosterCardId(callerMountSource(t), t.name, null, t.name, getToolContract(t, "caller").contractId);
356
+ }
338
357
  export function mintRosterEntry(tool, meta, facts) {
339
358
  const face = faceOf(tool);
340
359
  const fallbackOrigin = meta.source === "builtin" ? "core" : meta.source === "synthetic" ? "synthetic" : meta.source === "mcp" || meta.source === "a2a" ? meta.source : "caller";
341
360
  const d = getToolContract(tool, fallbackOrigin);
342
361
  const peer = meta.origin?.peer ?? null;
343
362
  const protocolTool = peer !== null ? protocolOf(tool.name)?.parse(tool.name)?.tool ?? tool.name : tool.name;
344
- const cardId = meta.source === "builtin" || meta.source === "synthetic"
345
- ? `builtin:${tool.name}`
346
- : meta.source === "mcp" || meta.source === "a2a"
347
- ? `${meta.source}:${peer}/${protocolTool}`
348
- : `${meta.source === "external" ? "external" : "caller"}:${d.contractId}`;
363
+ const cardId = rosterCardId(meta.source, tool.name, peer, protocolTool, d.contractId);
349
364
  const { keys: inputKeys } = inputKeysOf(tool.parameters);
350
365
  const declaredEffect = face.effect;
351
366
  const foldedEffect = facts.effects.get(tool.name);
@@ -385,7 +400,17 @@ export function mintRosterEntry(tool, meta, facts) {
385
400
  contentOriginProvenance,
386
401
  family: face.family !== undefined && TOOL_FAMILIES.includes(face.family) ? face.family : "other",
387
402
  ...(pathTarget !== undefined
388
- ? { pathTarget: { param: pathTarget.param, aliases: [...(pathTarget.aliases ?? [])], access: pathTarget.access, skillScopeEligible: pathTarget.skillScopeEligible === true } }
403
+ ? {
404
+ pathTarget: {
405
+ param: pathTarget.param,
406
+ aliases: [...(pathTarget.aliases ?? [])],
407
+ access: pathTarget.access,
408
+ skillScopeEligible: pathTarget.skillScopeEligible === true,
409
+ ...(pathTarget.base !== undefined ? { base: pathTarget.base } : {}),
410
+ ...(pathTarget.absent !== undefined ? { absent: pathTarget.absent } : {}),
411
+ ...(pathTarget.patternParam !== undefined ? { patternParam: pathTarget.patternParam } : {}),
412
+ },
413
+ }
389
414
  : {}),
390
415
  ruleFace: rf,
391
416
  approvalPreview: typeof tool.approvalPreview === "function",
@@ -431,6 +456,9 @@ export class ToolRosterDeltaSeat {
431
456
  for (const d of pending)
432
457
  sink(d);
433
458
  }
459
+ unsubscribe() {
460
+ this.#sink = undefined;
461
+ }
434
462
  drain() {
435
463
  const pending = this.#pending;
436
464
  this.#pending = [];
package/dist/index.d.ts CHANGED
@@ -53,6 +53,7 @@ export { runCascade, type CascadeRung, type CascadeConfig, type CascadeAttempt,
53
53
  export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
54
54
  export { materializeMcpTools, MCP_PREFIX, type MaterializedMcp, type McpServerStatus, type McpRefreshResult } from "./core/mcp.js";
55
55
  export { MCP_FAILURE_KINDS, MCP_DELIVERY_VERDICTS, classifyMcpFailure, type McpFailure, type McpFailureKind, type McpDelivered } from "./core/mcp-failure.js";
56
+ export { MCP_INJECTION_DROP_REASONS, MCP_INJECTION_DROP_TEXT, mcpInjectionDroppedNotice, type McpInjectionDropReason, type McpInjectionDropFacts } from "./core/mcp-injection-drop.js";
56
57
  export { materializeA2aTools, A2aRpcError, type MaterializedA2a, type A2aPeerStatus, type A2aRefreshResult, type A2aToolAxis } from "./core/a2a.js";
57
58
  export { PROTOCOL_TABLE, MCP_NAMESPACE, A2A_NAMESPACE, protocolOf, type ProtocolNamespace, type ProtocolId } from "./core/protocol-table.js";
58
59
  export { InMemorySessionPolicyStore, SessionPolicyError, loosenReasons, normalizeRules, stripRev, type SessionPolicyStore, type SessionPermissionRules, type StoredSessionRules, type SessionRulesRecord, type PutRulesOptions, } from "./core/session-policy-store.js";
@@ -124,10 +125,11 @@ export { createFsWriteGatePolicy, type FsWriteGatePolicyOptions } from "./core/f
124
125
  export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
125
126
  export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
126
127
  export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, type TaskNotificationPayload, type TaskNotificationStatus, type ExternalNotificationInput, type SystemInjection, type SystemInjectionPriority, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, AGENT_MESSAGE_TAG, renderAgentMessageFrame, type SemaProvenance, } from "./core/task-notification.js";
127
- export { TOOL_FAMILIES, TOOL_MOUNT_TAGS, TOOL_APPROVAL_CARDS, TOOL_PATH_ACCESSES, TOOL_WIRE_NAME_MAX_CHARS, TOOL_CONTRACT_MAX_CHARS, TOOL_KEY_MAX_CHARS, TOOL_KEYS_MAX, RENDER_HINT_MAX_CHARS, RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_LIST, type ToolFamily, type ToolMountTag, type ToolApprovalCard, type ToolPathAccess, type ToolPathTarget, type ToolRuleFace, type ToolRenderHints, type ToolFaceDeclaration, type ToolCatalogEntry, } from "./core/tool-face.js";
128
+ export { TOOL_FAMILIES, TOOL_MOUNT_TAGS, TOOL_APPROVAL_CARDS, TOOL_PATH_ACCESSES, TOOL_PATH_BASES, TOOL_PATH_ABSENCES, TOOL_WIRE_NAME_MAX_CHARS, TOOL_CONTRACT_MAX_CHARS, TOOL_KEY_MAX_CHARS, TOOL_KEYS_MAX, RENDER_HINT_MAX_CHARS, RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_LIST, type ToolFamily, type ToolMountTag, type ToolApprovalCard, type ToolPathAccess, type ToolPathBase, type ToolPathAbsence, type ToolPathTarget, type ToolCallPathTarget, type ToolRosterPathTarget, pathTargetSlotOnly, type ToolRuleFace, type ToolRenderHints, type ToolFaceDeclaration, type ToolCatalogEntry, } from "./core/tool-face.js";
128
129
  export { describeToolCatalog, catalogEntriesNamed, catalogToolNames, catalogRuleFaceOf, pathTargetOf, pathTargetValue, protectivePathTargetOf, declaredPathTargetOf, isProtectedWrite, isDeclaredWrite, fileOpAccessOf, type ToolCallLike, pathConfinableWriteToolNames, skillScopeWriteToolNames, pathTargetingToolNames, compactableToolNames, budgetExemptToolNames, handBandEffects, engineCardTypes, predictMountedToolNames, HANDS_BAND_TAGS, MOUNT_TAG_IN_HANDS_BAND, } from "./core/tool-registry.js";
129
130
  export { ToolRosterEntry, ToolRoster, ToolRosterDelta, ToolRosterRenderHints, ROSTER_SOURCES, type RosterSource, type ToolIdentity, toolIdentityOf, mintCapabilityId, diffToolRoster, judgeParkedToolIdentity, ruleFacesFromRoster, toolCallFaceOf, inputKeysOf, ruleFaceOfInstance, ToolRosterDeltaSeat, } from "./core/tool-roster.js";
130
131
  export { type ToolCallFace } from "./core/tool-policy.js";
132
+ export { effectivePathTargetOf, pathTargetBaseOf, type ToolPathBases } from "./core/effective-path-target.js";
131
133
  export { TOOL_CONFORMANCE_VECTORS, describeToolConformanceVectors, type ToolConformanceVector } from "./core/tool-conformance.js";
132
134
  export { applyMcpToolFaces, toolFaceProblem, APPROVAL_CARD_REQUIRED_KEYS, type McpToolFace } from "./core/runner/tool-face-overlay.js";
133
135
  export { createStructuredProjector } from "./core/runner/tool-output-projection.js";
@@ -186,12 +188,13 @@ export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRul
186
188
  * and nothing more. Removal is exported without ceremony, because narrowing on a user's behalf is
187
189
  * allowed and widening is not.
188
190
  */
189
- export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, type UncoveredSegmentDetail, type EditedRuleBreadthWarning, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, type PersistedAllowRule, type RuleTombstone, type RuleScope, type RuleDot, type RuleAdd, type RuleAddOrigin, type RuleOffer, type RuleOfferBatchMember, type SegmentRuleSuggestion, type SegmentCoverage, type RuleReject, type RuleRejectCode, type ParsedAllowRule, type PersistedRuleTool, type PersistedRuleMatch, } from "./core/permission-rule-model.js";
190
- export { removePersistedRule, applyTombstones, sameScope, isValidConsentScope, isValidDurableScope, InMemoryDurableRulePartition, EMPTY_DURABLE_RULE_PARTITION, type DurableRulePartition, type DurableRulePartitionProvider, type RuleWriteOutcome, type StoredAllowRules, type RemoveResult, type PutResult, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, type RuleSyncState, type RuleSyncFrontier, type RuleSyncDrop, type RuleSyncLandingReport, type RuleOwner, type QuarantinedRuleAdd, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, type PermissionRuleWriter, type WritableDurableRulePartition, type RuleWriteDelta, type RuleAddDelta, type RuleDeleteDelta, type RuleSyncJoinDelta, type RawRuleSyncState, type RedemptionAuthorization, } from "./core/permission-rule-store.js";
191
+ export { RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, RULE_BEHAVIORS_BY_PRECEDENCE, isRuleBehavior, readRowBehavior, adjudicatePersistedRules, adjudicatePersistedPathRules, ruleReachesProgramRun, programRunReachOf, PROGRAM_RUN_REACHES, type ProgramRunReach, type ProgramRunReachOutcome, pathRuleReaches, ruleToolGrammarOf, COMMAND_RULE_TOOL, READ_RULE_TOOL, type PathRuleBases, type RuleBehavior, type PersistedRuleVerdict, parseRuleText, formatRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, type UncoveredSegmentDetail, type EditedRuleBreadthWarning, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, type PersistedRule, type RuleTombstone, type RuleScope, type RuleDot, type RuleAdd, type RuleAddOrigin, type RuleOffer, type RuleOfferBatchMember, type SegmentRuleSuggestion, type SegmentCoverage, type RuleReject, type RuleRejectCode, type ParsedRule, type PersistedRuleTool, type PersistedRuleMatch, } from "./core/permission-rule-model.js";
192
+ export { removePersistedRule, applyTombstones, sameScope, sameRuleIdentity, isValidConsentScope, isValidDurableScope, InMemoryDurableRulePartition, EMPTY_DURABLE_RULE_PARTITION, type DurableRulePartition, type DurableRulePartitionProvider, type RuleWriteOutcome, type StoredRules, type RemoveResult, type PutResult, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, type RuleSyncState, type RuleSyncFrontier, type RuleSyncDrop, type RuleSyncLandingReport, type RuleOwner, type QuarantinedRuleAdd, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, type PermissionRuleWriter, type WritableDurableRulePartition, type RuleWriteDelta, type RuleAddDelta, type RuleDeleteDelta, type RuleSyncJoinDelta, type RawRuleSyncState, type RedemptionAuthorization, } from "./core/permission-rule-store.js";
191
193
  export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, type PermissionRuleSyncTransport, type PermissionRuleSyncResult, type RuleSyncRequestBody, type RuleSyncResponseBody, } from "./core/permission-rule-sync.js";
192
194
  export { createPermissionRuleStoreProvider, effectivePermissionRules, effectiveOrThrow, ruleSourceOf, type PermissionRuleStore, type PermissionRuleStoreProvider, type PermissionRuleStoreConfig, type EffectivePermissionRules, type EffectivePermissionRule, type RemovedPermissionRule, type RuleSource, } from "./core/permission-rule-provider.js";
193
195
  export { InMemorySessionRulePartition, type SessionRulePartition, type SessionRuleAdd, type SessionRuleApplyResult, } from "./core/permission-rule-session.js";
194
- export { orgRuleVerdictFor, orgRuleShadows, unenforceableOrgRules, ORG_UNAVAILABLE_DECISION_REASON, ORG_RULE_DECISION_REASON, ORG_ADJUDICATION_TIMEOUT_MS, type OrgPermissionRule, type OrgRuleSnapshot, type OrgRuleSnapshotProvider, type OrgRuleStatePersistence, type PersistedOrgRuleState, type OrgRulePartitionConfig, type OrgRuleResolution, type OrgRuleStatus, } from "./core/permission-rule-org.js";
196
+ export { readShellCommand, isFullyReadable, MAX_SHELL_READ_CHARS, SHELL_WRAPPER_TABLE, type ShellCommandShape, type ShellSegment, type ShellWord, type ShellWrapperName, } from "./core/shell-lexer.js";
197
+ export { orgRuleVerdictFor, type OrgRuleVerdict, orgRuleShadows, unenforceableOrgRules, ORG_UNAVAILABLE_DECISION_REASON, ORG_RULE_DECISION_REASON, ORG_ADJUDICATION_TIMEOUT_MS, type OrgPermissionRule, type OrgRuleSnapshot, type OrgRuleSnapshotProvider, type OrgRuleStatePersistence, type PersistedOrgRuleState, type OrgRulePartitionConfig, type OrgRuleResolution, type OrgRuleStatus, } from "./core/permission-rule-org.js";
195
198
  export { RULE_SYNC_DROP_CODES, type RuleSyncDropReason, type RuleQuarantineReason } from "./core/governance-codes.js";
196
199
  export { prepareCardApproval, confirmRuleApproval, type ConfirmResult, type ConfirmRefusalReason, precheckEditedRuleText, type EditedRuleTextPrecheck, redeemRuleTicket, redeemRuleBatch, prepareCcImport, prepareStarterBatch, mintRuleTicket, STARTER_RULES, InMemoryRuleApprovalRecordStore, ruleOffersOfRecord, type RuleTicket, type RuleCandidate, type RuleApprovalKind, type RuleApprovalRecord, type RuleApprovalRecordStore, type RuleOffer2, type StaleRuleApprovalRecord, type RuleConsentDeps, type RedeemResult, type RedeemedBatchMember, type CcImportLayer, type ImportedSettingsLayer, type ImportPreview, } from "./core/permission-rule-consent.js";
197
200
  export { FileDurableRulePartitionProvider, ORG_STATE_FILE } from "./stores/file/permission-rule-store.js";
package/dist/index.js CHANGED
@@ -40,6 +40,7 @@ export { runCascade, } from "./agents/cascade.js";
40
40
  export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
41
41
  export { materializeMcpTools, MCP_PREFIX } from "./core/mcp.js";
42
42
  export { MCP_FAILURE_KINDS, MCP_DELIVERY_VERDICTS, classifyMcpFailure } from "./core/mcp-failure.js";
43
+ export { MCP_INJECTION_DROP_REASONS, MCP_INJECTION_DROP_TEXT, mcpInjectionDroppedNotice } from "./core/mcp-injection-drop.js";
43
44
  export { materializeA2aTools, A2aRpcError } from "./core/a2a.js";
44
45
  export { PROTOCOL_TABLE, MCP_NAMESPACE, A2A_NAMESPACE, protocolOf } from "./core/protocol-table.js";
45
46
  export { InMemorySessionPolicyStore, SessionPolicyError, loosenReasons, normalizeRules, stripRev, } from "./core/session-policy-store.js";
@@ -100,10 +101,11 @@ export { createFsWriteGatePolicy } from "./core/fs-write-gate-policy.js";
100
101
  export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
101
102
  export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
102
103
  export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, AGENT_MESSAGE_TAG, renderAgentMessageFrame, } from "./core/task-notification.js";
103
- export { TOOL_FAMILIES, TOOL_MOUNT_TAGS, TOOL_APPROVAL_CARDS, TOOL_PATH_ACCESSES, TOOL_WIRE_NAME_MAX_CHARS, TOOL_CONTRACT_MAX_CHARS, TOOL_KEY_MAX_CHARS, TOOL_KEYS_MAX, RENDER_HINT_MAX_CHARS, RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_LIST, } from "./core/tool-face.js";
104
+ export { TOOL_FAMILIES, TOOL_MOUNT_TAGS, TOOL_APPROVAL_CARDS, TOOL_PATH_ACCESSES, TOOL_PATH_BASES, TOOL_PATH_ABSENCES, TOOL_WIRE_NAME_MAX_CHARS, TOOL_CONTRACT_MAX_CHARS, TOOL_KEY_MAX_CHARS, TOOL_KEYS_MAX, RENDER_HINT_MAX_CHARS, RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_LIST, pathTargetSlotOnly, } from "./core/tool-face.js";
104
105
  export { describeToolCatalog, catalogEntriesNamed, catalogToolNames, catalogRuleFaceOf, pathTargetOf, pathTargetValue, protectivePathTargetOf, declaredPathTargetOf, isProtectedWrite, isDeclaredWrite, fileOpAccessOf, pathConfinableWriteToolNames, skillScopeWriteToolNames, pathTargetingToolNames, compactableToolNames, budgetExemptToolNames, handBandEffects, engineCardTypes, predictMountedToolNames, HANDS_BAND_TAGS, MOUNT_TAG_IN_HANDS_BAND, } from "./core/tool-registry.js";
105
106
  export { ToolRosterEntry, ToolRoster, ToolRosterDelta, ToolRosterRenderHints, ROSTER_SOURCES, toolIdentityOf, mintCapabilityId, diffToolRoster, judgeParkedToolIdentity, ruleFacesFromRoster, toolCallFaceOf, inputKeysOf, ruleFaceOfInstance, ToolRosterDeltaSeat, } from "./core/tool-roster.js";
106
107
  export {} from "./core/tool-policy.js";
108
+ export { effectivePathTargetOf, pathTargetBaseOf } from "./core/effective-path-target.js";
107
109
  export { TOOL_CONFORMANCE_VECTORS, describeToolConformanceVectors } from "./core/tool-conformance.js";
108
110
  export { applyMcpToolFaces, toolFaceProblem, APPROVAL_CARD_REQUIRED_KEYS } from "./core/runner/tool-face-overlay.js";
109
111
  export { createStructuredProjector } from "./core/runner/tool-output-projection.js";
@@ -145,11 +147,12 @@ export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/au
145
147
  export { AUTO_MODE_ARMING_RECIPE_VERSION, autoModeArmingRecipeOf, sanitizeAutoModeArmingRecipe, foldAutoModeArming, } from "./core/auto-mode-arming.js";
146
148
  export { rebuildAutoModeDecider, } from "./core/auto-mode-rebuild.js";
147
149
  export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRule, wildcardMatch, isNamespacedCoveringRuleName, namespacedRuleNameCovers, } from "./core/permission-rules.js";
148
- export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, } from "./core/permission-rule-model.js";
149
- export { removePersistedRule, applyTombstones, sameScope, isValidConsentScope, isValidDurableScope, InMemoryDurableRulePartition, EMPTY_DURABLE_RULE_PARTITION, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, } from "./core/permission-rule-store.js";
150
+ export { RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, RULE_BEHAVIORS_BY_PRECEDENCE, isRuleBehavior, readRowBehavior, adjudicatePersistedRules, adjudicatePersistedPathRules, ruleReachesProgramRun, programRunReachOf, PROGRAM_RUN_REACHES, pathRuleReaches, ruleToolGrammarOf, COMMAND_RULE_TOOL, READ_RULE_TOOL, parseRuleText, formatRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, } from "./core/permission-rule-model.js";
151
+ export { removePersistedRule, applyTombstones, sameScope, sameRuleIdentity, isValidConsentScope, isValidDurableScope, InMemoryDurableRulePartition, EMPTY_DURABLE_RULE_PARTITION, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, } from "./core/permission-rule-store.js";
150
152
  export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, } from "./core/permission-rule-sync.js";
151
153
  export { createPermissionRuleStoreProvider, effectivePermissionRules, effectiveOrThrow, ruleSourceOf, } from "./core/permission-rule-provider.js";
152
154
  export { InMemorySessionRulePartition, } from "./core/permission-rule-session.js";
155
+ export { readShellCommand, isFullyReadable, MAX_SHELL_READ_CHARS, SHELL_WRAPPER_TABLE, } from "./core/shell-lexer.js";
153
156
  export { orgRuleVerdictFor, orgRuleShadows, unenforceableOrgRules, ORG_UNAVAILABLE_DECISION_REASON, ORG_RULE_DECISION_REASON, ORG_ADJUDICATION_TIMEOUT_MS, } from "./core/permission-rule-org.js";
154
157
  export { RULE_SYNC_DROP_CODES } from "./core/governance-codes.js";
155
158
  export { prepareCardApproval, confirmRuleApproval, precheckEditedRuleText, redeemRuleTicket, redeemRuleBatch, prepareCcImport, prepareStarterBatch, mintRuleTicket, STARTER_RULES, InMemoryRuleApprovalRecordStore, ruleOffersOfRecord, } from "./core/permission-rule-consent.js";
@@ -16,7 +16,7 @@ const KNOWN_CHECKPOINT_LEDGER_EVENTS = new Set(Object.keys(CHECKPOINT_LEDGER_EVE
16
16
  function applyCheckpointEvent(cps, ev) {
17
17
  if (!KNOWN_CHECKPOINT_LEDGER_EVENTS.has(ev.t)) {
18
18
  throw new CheckpointError("checkpoint.unsupported_version", `file checkpoint ledger: unrecognised event kind "${String(ev.t)}" — ` +
19
- `it was written by a newer worker; refusing the replay rather than serving an incomplete authority`);
19
+ `it was written by a newer worker; refusing the replay rather than serving an incomplete authority`, { reason: "ledger_event_unknown" });
20
20
  }
21
21
  if (ev.t === "put") {
22
22
  cps.set(ev.token, ev.cp);