@sema-agent/core 7.7.0 → 7.9.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 (186) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/dist/agents/agent-transcript-tool.js +2 -2
  3. package/dist/agents/list-agents-tool.js +2 -3
  4. package/dist/agents/observer.js +2 -2
  5. package/dist/agents/send-message-tool.js +2 -1
  6. package/dist/agents/subagent-steps.js +5 -4
  7. package/dist/agents/subagent.d.ts +1 -1
  8. package/dist/agents/subagent.js +2 -3
  9. package/dist/core/ask-origin.d.ts +12 -1
  10. package/dist/core/ask-origin.js +5 -1
  11. package/dist/core/ask-question.js +2 -2
  12. package/dist/core/checkpoint-store.d.ts +64 -24
  13. package/dist/core/context-edit.d.ts +0 -22
  14. package/dist/core/context-edit.js +2 -11
  15. package/dist/core/engine-notice.d.ts +6 -0
  16. package/dist/core/fs-write-gate-policy.d.ts +7 -1
  17. package/dist/core/fs-write-gate-policy.js +7 -7
  18. package/dist/core/gate-fold.js +2 -2
  19. package/dist/core/gate-lanes.js +53 -26
  20. package/dist/core/gate-outcome.d.ts +8 -4
  21. package/dist/core/gate-outcome.js +2 -1
  22. package/dist/core/governance-codes.d.ts +1 -1
  23. package/dist/core/governance-codes.js +6 -0
  24. package/dist/core/hooks.d.ts +64 -33
  25. package/dist/core/hooks.js +1 -1
  26. package/dist/core/lsp.js +2 -2
  27. package/dist/core/mcp-server-spec.d.ts +17 -0
  28. package/dist/core/mcp.js +3 -1
  29. package/dist/core/memory-engine/tools.js +4 -12
  30. package/dist/core/permission-rule-consent.d.ts +29 -36
  31. package/dist/core/permission-rule-consent.js +110 -60
  32. package/dist/core/permission-rule-model.d.ts +254 -55
  33. package/dist/core/permission-rule-model.js +323 -43
  34. package/dist/core/permission-rule-org.d.ts +9 -8
  35. package/dist/core/permission-rule-org.js +6 -15
  36. package/dist/core/permission-rule-provider.d.ts +10 -6
  37. package/dist/core/permission-rule-provider.js +12 -8
  38. package/dist/core/permission-rule-session.d.ts +7 -6
  39. package/dist/core/permission-rule-session.js +29 -10
  40. package/dist/core/permission-rule-store.d.ts +40 -18
  41. package/dist/core/permission-rule-store.js +68 -42
  42. package/dist/core/permission-rule-sync.d.ts +9 -3
  43. package/dist/core/permission-rule-sync.js +29 -25
  44. package/dist/core/permission-rule-syntax.d.ts +30 -0
  45. package/dist/core/permission-rule-syntax.js +44 -0
  46. package/dist/core/permission-rules.d.ts +85 -33
  47. package/dist/core/permission-rules.js +104 -88
  48. package/dist/core/persisted-rule-arms.d.ts +56 -0
  49. package/dist/core/persisted-rule-arms.js +48 -0
  50. package/dist/core/present-plan-tool.js +3 -4
  51. package/dist/core/runner/active-skill-scope.js +7 -4
  52. package/dist/core/runner/compaction-call-options.d.ts +1 -1
  53. package/dist/core/runner/contracts.d.ts +46 -3
  54. package/dist/core/runner/permission-rule-lanes.d.ts +33 -26
  55. package/dist/core/runner/permission-rule-lanes.js +27 -21
  56. package/dist/core/runner/prepare-ask-lane.d.ts +1 -1
  57. package/dist/core/runner/prepare-caps-and-workflow.d.ts +5 -4
  58. package/dist/core/runner/prepare-caps-and-workflow.js +16 -11
  59. package/dist/core/runner/prepare-defer-classify.d.ts +5 -26
  60. package/dist/core/runner/prepare-defer-classify.js +10 -10
  61. package/dist/core/runner/prepare-delegation-surface.d.ts +5 -4
  62. package/dist/core/runner/prepare-delegation-surface.js +15 -17
  63. package/dist/core/runner/prepare-gate-stations.d.ts +4 -1
  64. package/dist/core/runner/prepare-gate-stations.js +4 -2
  65. package/dist/core/runner/prepare-hands-readface.d.ts +3 -2
  66. package/dist/core/runner/prepare-hands-readface.js +3 -2
  67. package/dist/core/runner/prepare-inherited-gate.d.ts +1 -1
  68. package/dist/core/runner/prepare-inherited-gate.js +1 -0
  69. package/dist/core/runner/prepare-lsp.d.ts +4 -3
  70. package/dist/core/runner/prepare-lsp.js +3 -2
  71. package/dist/core/runner/prepare-memory-engine-session.d.ts +4 -4
  72. package/dist/core/runner/prepare-memory-engine-session.js +4 -2
  73. package/dist/core/runner/prepare-offload-wrappers.js +7 -5
  74. package/dist/core/runner/prepare-park-ask.d.ts +4 -0
  75. package/dist/core/runner/prepare-park-ask.js +4 -1
  76. package/dist/core/runner/prepare-project-context.d.ts +5 -23
  77. package/dist/core/runner/prepare-project-context.js +7 -5
  78. package/dist/core/runner/prepare-prompt-assembly.d.ts +1 -1
  79. package/dist/core/runner/prepare-protocol-tools.d.ts +5 -1
  80. package/dist/core/runner/prepare-protocol-tools.js +38 -21
  81. package/dist/core/runner/prepare-question-face.d.ts +4 -3
  82. package/dist/core/runner/prepare-question-face.js +5 -3
  83. package/dist/core/runner/prepare-run-refs.d.ts +16 -0
  84. package/dist/core/runner/prepare-run-refs.js +6 -0
  85. package/dist/core/runner/prepare-safety-scan.js +48 -2
  86. package/dist/core/runner/prepare-task.js +37 -19
  87. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +5 -2
  88. package/dist/core/runner/prepare-tool-disclosure-mount.js +3 -1
  89. package/dist/core/runner/prepare-wiring-manifest.d.ts +4 -0
  90. package/dist/core/runner/prepare-wiring-manifest.js +3 -8
  91. package/dist/core/runner/resume-admission.d.ts +53 -0
  92. package/dist/core/runner/resume-admission.js +83 -0
  93. package/dist/core/runner/resume-apply.d.ts +50 -0
  94. package/dist/core/runner/resume-apply.js +184 -0
  95. package/dist/core/runner/resume-checkpoint-screen.d.ts +18 -0
  96. package/dist/core/runner/resume-checkpoint-screen.js +108 -0
  97. package/dist/core/runner/resume-claim.d.ts +32 -0
  98. package/dist/core/runner/resume-claim.js +27 -0
  99. package/dist/core/runner/resume-internals-and-config.d.ts +33 -0
  100. package/dist/core/runner/resume-internals-and-config.js +50 -0
  101. package/dist/core/runner/resume-policy-outcome.d.ts +31 -0
  102. package/dist/core/runner/resume-policy-outcome.js +127 -0
  103. package/dist/core/runner/resume-preflight.d.ts +40 -0
  104. package/dist/core/runner/resume-preflight.js +122 -0
  105. package/dist/core/runner/resume-review-outcome.d.ts +30 -0
  106. package/dist/core/runner/resume-review-outcome.js +88 -0
  107. package/dist/core/runner/run-harness-handlers.d.ts +46 -0
  108. package/dist/core/runner/run-harness-handlers.js +345 -0
  109. package/dist/core/runner/run-turn-boundary.d.ts +69 -0
  110. package/dist/core/runner/run-turn-boundary.js +694 -0
  111. package/dist/core/runner/runtask.d.ts +20 -0
  112. package/dist/core/runner/runtask.js +129 -1774
  113. package/dist/core/runner/session-rule-policy.js +9 -4
  114. package/dist/core/runner/synthetic-tools.js +5 -8
  115. package/dist/core/runner/tool-disclosure.d.ts +4 -0
  116. package/dist/core/runner/tool-disclosure.js +9 -5
  117. package/dist/core/runner/tool-end-body.d.ts +12 -5
  118. package/dist/core/runner/tool-end-body.js +8 -7
  119. package/dist/core/runner/tool-face-overlay.d.ts +40 -0
  120. package/dist/core/runner/tool-face-overlay.js +125 -0
  121. package/dist/core/runner/tool-output-projection.d.ts +14 -1
  122. package/dist/core/runner/tool-output-projection.js +24 -18
  123. package/dist/core/runner/turn-attachments.d.ts +2 -2
  124. package/dist/core/sensitive-path-policy.d.ts +3 -0
  125. package/dist/core/sensitive-path-policy.js +6 -5
  126. package/dist/core/shared-memory/tools.js +3 -6
  127. package/dist/core/store-contracts/checkpoint-store-contract.js +23 -0
  128. package/dist/core/store-contracts/permission-rule-sync-contract.js +29 -10
  129. package/dist/core/task-event.d.ts +10 -0
  130. package/dist/core/task-registry.js +4 -5
  131. package/dist/core/task-spec.d.ts +8 -0
  132. package/dist/core/tool-catalog-entries.d.ts +48 -0
  133. package/dist/core/tool-catalog-entries.js +174 -0
  134. package/dist/core/tool-conformance.d.ts +22 -0
  135. package/dist/core/tool-conformance.js +37 -0
  136. package/dist/core/tool-face.d.ts +171 -0
  137. package/dist/core/tool-face.js +25 -0
  138. package/dist/core/tool-policy.d.ts +24 -0
  139. package/dist/core/tool-policy.js +4 -2
  140. package/dist/core/tool-registry.d.ts +114 -0
  141. package/dist/core/tool-registry.js +114 -0
  142. package/dist/core/tool-result-budget.d.ts +0 -3
  143. package/dist/core/tool-result-budget.js +4 -3
  144. package/dist/core/tool-result-store.d.ts +0 -18
  145. package/dist/core/tool-result-store.js +2 -18
  146. package/dist/core/tool-roster.d.ts +459 -0
  147. package/dist/core/tool-roster.js +507 -0
  148. package/dist/core/tool-spec.d.ts +54 -3
  149. package/dist/core/tools.js +7 -0
  150. package/dist/core/wiring-manifest.d.ts +13 -0
  151. package/dist/core/wiring-manifest.js +2 -1
  152. package/dist/core/write-protect.d.ts +2 -1
  153. package/dist/core/write-protect.js +5 -4
  154. package/dist/engine/compaction/utils.d.ts +6 -0
  155. package/dist/engine/compaction/utils.js +19 -19
  156. package/dist/engine/loop/types.d.ts +6 -0
  157. package/dist/index.d.ts +17 -6
  158. package/dist/index.js +17 -6
  159. package/dist/orchestration/goal.js +2 -1
  160. package/dist/orchestration/run-spec.js +3 -5
  161. package/dist/orchestration/run-workflow-tool.js +2 -2
  162. package/dist/prompt-assembly/event-registry.js +3 -3
  163. package/dist/prompt-assembly/tool-catalog.d.ts +2 -2
  164. package/dist/stores/file/checkpoint-store.js +1 -1
  165. package/dist/stores/file/permission-rule-store.d.ts +28 -23
  166. package/dist/stores/file/permission-rule-store.js +64 -16
  167. package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
  168. package/dist/tools/fs/fs-bash.d.ts +1 -1
  169. package/dist/tools/fs/fs-bash.js +7 -11
  170. package/dist/tools/fs/fs-pdf.d.ts +1 -1
  171. package/dist/tools/fs/fs-read.js +2 -2
  172. package/dist/tools/fs/fs-search-tools.d.ts +0 -7
  173. package/dist/tools/fs/fs-search-tools.js +3 -16
  174. package/dist/tools/fs/fs-write.js +4 -6
  175. package/dist/tools/fs/notebook.d.ts +1 -1
  176. package/dist/tools/fs/repo-map.js +2 -2
  177. package/dist/tools/fs/safety.d.ts +3 -2
  178. package/dist/tools/fs/safety.js +6 -5
  179. package/dist/tools/monitor.js +2 -2
  180. package/dist/tools/scheduler-tools.js +5 -8
  181. package/dist/tools/task-list.js +5 -8
  182. package/dist/tools/todo.js +2 -2
  183. package/dist/tools/web.js +3 -6
  184. package/dist/tools/worktree.js +3 -4
  185. package/package.json +4 -1
  186. package/test/export-surface.snapshot.json +189 -17
@@ -1,5 +1,5 @@
1
1
  import { isWinFormPath, writeTargetPath, isUncPath } from "../tools/fs/safety.js";
2
- import { PATH_CONFINABLE_WRITE_TOOLS } from "./runner/session-rule-policy.js";
2
+ import { isProtectedWrite } from "./tool-registry.js";
3
3
  import { dataRootSpellings } from "./sensitive-path-policy.js";
4
4
  const freezeTable = (rows) => Object.freeze(rows.map((r) => Object.freeze(r)));
5
5
  export const WRITE_PROTECTED_DEFAULT_TABLE = freezeTable([
@@ -213,10 +213,11 @@ export function createWriteProtectionCheck(entries, opts) {
213
213
  const matcher = compileWriteProtection(entries, opts);
214
214
  if (matcher === undefined)
215
215
  return undefined;
216
- return (toolName, args) => {
217
- if (!PATH_CONFINABLE_WRITE_TOOLS.has(toolName))
216
+ return (toolName, args, face) => {
217
+ const call = { toolName, args, ...(face !== undefined ? { face } : {}) };
218
+ if (!isProtectedWrite(call))
218
219
  return null;
219
- const path = writeTargetPath(toolName, args);
220
+ const path = writeTargetPath(call);
220
221
  if (typeof path !== "string" || path.length === 0)
221
222
  return null;
222
223
  return matcher.matchPath(path);
@@ -1,5 +1,11 @@
1
1
  import type { Message } from "../llm/index.js";
2
2
  import type { AgentMessage } from "../loop/types.js";
3
+ /**
4
+ * design/388 A-18 — the FROZEN history table: tool names a persisted pre-rename transcript may still carry
5
+ * (the upstream trio and the pre-CC-name core trio), mapped to the path access the live definition declares.
6
+ * Never grows: a new name declares its access on the catalog instead. Registered with the name-table gate.
7
+ */
8
+ export declare const DURABLE_HISTORY_NAMES: ReadonlyMap<string, "read" | "create" | "edit">;
3
9
  /** File paths touched by a session branch or compaction range. */
4
10
  export interface FileOperations {
5
11
  /** Files read but not necessarily modified. */
@@ -2,6 +2,15 @@ import { normalizeLlmMessageContent } from "../harness/messages.js";
2
2
  import { sliceHeadSafe } from "../../core/surrogate-safe-slice.js";
3
3
  import { cutEnginePrefix, cutEngineSegments, flattenableUserText } from "../../core/untrusted-text.js";
4
4
  import { fileArgPath } from "../../tools/fs/safety.js";
5
+ import { fileOpAccessOf } from "../../core/tool-registry.js";
6
+ export const DURABLE_HISTORY_NAMES = new Map([
7
+ ["read", "read"],
8
+ ["write", "create"],
9
+ ["edit", "edit"],
10
+ ["read_file", "read"],
11
+ ["write_file", "create"],
12
+ ["edit_file", "edit"],
13
+ ]);
5
14
  export function createFileOps() {
6
15
  return {
7
16
  read: new Set(),
@@ -35,25 +44,16 @@ export function extractFileOpsFromMessage(message, fileOps) {
35
44
  if (!path) {
36
45
  continue;
37
46
  }
38
- switch (block.name) {
39
- case "read":
40
- case "Read":
41
- case "read_file":
42
- fileOps.read.add(path);
43
- break;
44
- case "write":
45
- case "Write":
46
- case "write_file":
47
- fileOps.written.add(path);
48
- touchModified(fileOps, path);
49
- break;
50
- case "edit":
51
- case "Edit":
52
- case "edit_file":
53
- case "MultiEdit":
54
- fileOps.edited.add(path);
55
- touchModified(fileOps, path);
56
- break;
47
+ const access = fileOpAccessOf(block.name) ?? DURABLE_HISTORY_NAMES.get(block.name);
48
+ if (access === "read")
49
+ fileOps.read.add(path);
50
+ else if (access === "create") {
51
+ fileOps.written.add(path);
52
+ touchModified(fileOps, path);
53
+ }
54
+ else if (access === "edit") {
55
+ fileOps.edited.add(path);
56
+ touchModified(fileOps, path);
57
57
  }
58
58
  }
59
59
  }
@@ -750,6 +750,12 @@ export interface AgentTool<TParameters extends TSchema = TSchema, TDetails = unk
750
750
  * server's own channel for keeping one tool's full schema inlined. Absent on non-MCP tools.
751
751
  */
752
752
  mcpAlwaysLoad?: boolean;
753
+ /**
754
+ * design/388 — the server's RAW tool name this mounted MCP tool was accepted under (byte-exact, the `tools/call`
755
+ * spelling). The `toolFaces` overlay binds to it: two raw names can fold onto one minted wire name, and an overlay
756
+ * keyed by the folded-away spelling must stay inert rather than land on the other tool. Absent on non-MCP tools.
757
+ */
758
+ mcpRemoteName?: string;
753
759
  /**
754
760
  * design/120 P1.5 (CC `isConcurrencySafe(parsedInput)` parity): INPUT-level concurrency refinement
755
761
  * for a tool whose safety depends on its arguments — CC's only real consumer is
package/dist/index.d.ts CHANGED
@@ -24,9 +24,9 @@ export { createTodoWriteTool } from "./tools/todo.js";
24
24
  export { createTaskListTools, createMemoryTaskListStore, assertJsonMetadata, type TaskListItem, type TaskListStore } from "./tools/task-list.js";
25
25
  export { assembleCodeTools, type CodeToolsConfig, CODE_ROLE } from "./scenarios/full-body.js";
26
26
  export { TOOL_MODEL_GATE_CLASSES, isModelGatedForClass, type ToolModelGateRule } from "./core/tool-model-gate.js";
27
- export { capAggregateToolResults, AGGREGATE_TOOL_RESULT_BUDGET_CHARS, DEFAULT_BUDGET_EXEMPT_TOOLS, type AggregateBudgetOptions, } from "./core/tool-result-budget.js";
27
+ export { capAggregateToolResults, AGGREGATE_TOOL_RESULT_BUDGET_CHARS, type AggregateBudgetOptions, } from "./core/tool-result-budget.js";
28
28
  export { capAggregateMediaBytes, AGGREGATE_MEDIA_BUDGET_BYTES, type MediaStripInfo } from "./core/media-byte-cap.js";
29
- export { createAskUserQuestionTool, createDurableQuestionPolicy, QUESTION_AWAITS_RESUME, isQuestionUnavailable, type OnQuestionOutcome, type QuestionUnavailable, type OnQuestion, type AskQuestion, type AskQuestionOption, type AskQuestionRequest, type QuestionAnswer, type QuestionAnswerItem, type AskQuestionCardDetails, type AskUserQuestionToolOptions, type AskAnswerContinuationSource, type SyntheticContinuationReason, } from "./core/ask-question.js";
29
+ export { createAskUserQuestionTool, createDurableQuestionPolicy, QUESTION_AWAITS_RESUME, isQuestionUnavailable, type OnQuestionOutcome, type QuestionUnavailable, type OnQuestion, type AskQuestion, type AskQuestionOption, type AskQuestionRequest, type QuestionAnswer, type QuestionAnswerItem, type AskQuestionCardDetails, type AskUserQuestionToolOptions, type AskAnswerContinuationSource, type SyntheticContinuationReason, ASK_USER_QUESTION_TOOL_NAME, } from "./core/ask-question.js";
30
30
  export { createLspTool, gitCheckIgnoreFilter, LSP_OPERATIONS, LSP_FAILURE_BRAND, brandLspFailure, lspFailureOf, SharedAbortScope, settleOnAbort, type LspNoneReason, type LspOperation, type LspServerManager, type LspSession, type LspResult, type LspLocation, type LspSymbolInfo, type LspRequestParams, type LspToolOptions, type LspTransport, type LspReadText, } from "./core/lsp.js";
31
31
  export { buildRequest, parseResult, callHierarchyMethod, pathToUri } from "./core/lsp-protocol.js";
32
32
  export { TransportLspSession, type SessionWarmup } from "./core/lsp-session.js";
@@ -91,7 +91,7 @@ export { sanitizeUntrustedText, delimitUntrusted, inlineUntrusted } from "./core
91
91
  export { mintReminderMark, isValidReminderMark, openSystemReminder, mintSystemReminder, reminderMarkDeclaration } from "./core/reminder-mint.js";
92
92
  export { deriveInvariants, checkInvariants } from "./core/property-harness.js";
93
93
  export type { InvariantKind, FunctionContract, Invariant, InvariantViolation, CheckResult, } from "./core/property-harness.js";
94
- export { HAND_TOOL_EFFECTS, bashReversibilityProbe, BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName, classifyCompoundReadonly, MAX_EDIT_BYTES } from "./tools/fs/index.js";
94
+ export { bashReversibilityProbe, BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName, classifyCompoundReadonly, MAX_EDIT_BYTES } from "./tools/fs/index.js";
95
95
  export { classifyCompoundReadonlyDetailed, formatOutOfRootReadApprovalOption, type BashReadonlyRootBoundary, type CompoundReadonlyVerdict, } from "./tools/fs/index.js";
96
96
  export { resolveBashTimeoutCaps } from "./tools/fs/index.js";
97
97
  export { READ_FACE_DEFAULT_DENY_ENTRIES, READ_FACE_BUILTIN_DENY_TABLE, READ_DENY_BUILTIN_TIERS, READ_DENY_DEFAULT_TIERS, resolveReadDenyBuiltins, compileReadDeny, type ReadDenyEntry, type ReadDenyMatcher, type NormalizedReadDenyEntry, type ReadDenyBuiltinTier, type ReadDenyBuiltinRow, type ReadDenyBuiltinConfig, } from "./tools/fs/index.js";
@@ -124,6 +124,17 @@ export { createFsWriteGatePolicy, type FsWriteGatePolicyOptions } from "./core/f
124
124
  export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
125
125
  export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
126
126
  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 { 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
+ 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
+ export { type ToolCallFace } from "./core/tool-policy.js";
131
+ export { TOOL_CONFORMANCE_VECTORS, describeToolConformanceVectors, type ToolConformanceVector } from "./core/tool-conformance.js";
132
+ export { applyMcpToolFaces, toolFaceProblem, APPROVAL_CARD_REQUIRED_KEYS, type McpToolFace } from "./core/runner/tool-face-overlay.js";
133
+ export { createStructuredProjector } from "./core/runner/tool-output-projection.js";
134
+ export { parkedToolIdentity } from "./core/tool-roster.js";
135
+ export { type ToolCallIdentity } from "./core/fs-write-gate-policy.js";
136
+ export { type RuleFaceView, catalogRuleFaceView } from "./core/permission-rules.js";
137
+ export { DURABLE_HISTORY_NAMES } from "./engine/compaction/utils.js";
127
138
  export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveSubagentTranscriptTier, type SubagentTranscriptTier, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, AUTO_MODE_ARM_REASONS, type AutoModeArmReason, type WiringManifest, type WiringManifestMcpEntry, type WiringFacts, type WiringLegKind, type AskSeamForm, type AskEffective, type QuestionChannelState, type SeamProvenance, type ParkLaneReason, type ManifestDurability, type StaticWiringDeps, type StaticWiringSpec, } from "./core/wiring-manifest.js";
128
139
  export { probeParkRoundTrip, durableParkGapOf, durableParkGapFor, PARK_SELFCHECK_SCOPE_PREFIX, type ParkSelfCheckResult, type ParkProbeFinding, type ParkProbeFindingCode, } from "./core/park-selfcheck.js";
129
140
  export { type StoreDurability } from "./core/checkpoint-store.js";
@@ -175,8 +186,8 @@ export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRul
175
186
  * and nothing more. Removal is exported without ceremony, because narrowing on a user's behalf is
176
187
  * allowed and widening is not.
177
188
  */
178
- 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";
179
- 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";
189
+ export { RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, RULE_BEHAVIORS_BY_PRECEDENCE, isRuleBehavior, readRowBehavior, adjudicatePersistedRules, adjudicatePersistedPathRules, ruleReachesProgramRun, 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";
190
+ 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";
180
191
  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";
181
192
  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";
182
193
  export { InMemorySessionRulePartition, type SessionRulePartition, type SessionRuleAdd, type SessionRuleApplyResult, } from "./core/permission-rule-session.js";
@@ -280,7 +291,7 @@ export { defineAgent } from "./agents/agent-definition.js";
280
291
  export { builtinAgentDefinitions, BUILTIN_READONLY_DENY_TOOLS, EXPLORE_WHEN_TO_USE, EXPLORE_WHEN_TO_USE_LEAN, PLAN_WHEN_TO_USE, EXPLORE_SYSTEM_PROMPT, PLAN_SYSTEM_PROMPT, } from "./agents/builtin-agents.js";
281
292
  export { runTeamDiscussion, type TeamDiscussionOptions, type TeamMember, type TeamResult, type TeamTurn, type TeamEvent, } from "./agents/team.js";
282
293
  export { createTaskServer, type TaskServerOptions, type TaskRequestBody, } from "./server/http.js";
283
- export { clearStaleToolResults, COMPACTABLE_TOOLS, editBudget, type ContextEditOptions, } from "./core/context-edit.js";
294
+ export { clearStaleToolResults, editBudget, type ContextEditOptions, } from "./core/context-edit.js";
284
295
  export { createOpenAIBrain, type OpenAIBrainConfig } from "./brain/openai.js";
285
296
  export { createAnthropicBrain, type AnthropicBrainConfig } from "./brain/anthropic.js";
286
297
  export { createOpenResponsesBrain, type OpenResponsesBrainConfig } from "./brain/open-responses.js";
package/dist/index.js CHANGED
@@ -12,9 +12,9 @@ export { createTodoWriteTool } from "./tools/todo.js";
12
12
  export { createTaskListTools, createMemoryTaskListStore, assertJsonMetadata } from "./tools/task-list.js";
13
13
  export { assembleCodeTools, CODE_ROLE } from "./scenarios/full-body.js";
14
14
  export { TOOL_MODEL_GATE_CLASSES, isModelGatedForClass } from "./core/tool-model-gate.js";
15
- export { capAggregateToolResults, AGGREGATE_TOOL_RESULT_BUDGET_CHARS, DEFAULT_BUDGET_EXEMPT_TOOLS, } from "./core/tool-result-budget.js";
15
+ export { capAggregateToolResults, AGGREGATE_TOOL_RESULT_BUDGET_CHARS, } from "./core/tool-result-budget.js";
16
16
  export { capAggregateMediaBytes, AGGREGATE_MEDIA_BUDGET_BYTES } from "./core/media-byte-cap.js";
17
- export { createAskUserQuestionTool, createDurableQuestionPolicy, QUESTION_AWAITS_RESUME, isQuestionUnavailable, } from "./core/ask-question.js";
17
+ export { createAskUserQuestionTool, createDurableQuestionPolicy, QUESTION_AWAITS_RESUME, isQuestionUnavailable, ASK_USER_QUESTION_TOOL_NAME, } from "./core/ask-question.js";
18
18
  export { createLspTool, gitCheckIgnoreFilter, LSP_OPERATIONS, LSP_FAILURE_BRAND, brandLspFailure, lspFailureOf, SharedAbortScope, settleOnAbort, } from "./core/lsp.js";
19
19
  export { buildRequest, parseResult, callHierarchyMethod, pathToUri } from "./core/lsp-protocol.js";
20
20
  export { TransportLspSession } from "./core/lsp-session.js";
@@ -70,7 +70,7 @@ export { runExecGate } from "./core/exec-gate.js";
70
70
  export { sanitizeUntrustedText, delimitUntrusted, inlineUntrusted } from "./core/untrusted-text.js";
71
71
  export { mintReminderMark, isValidReminderMark, openSystemReminder, mintSystemReminder, reminderMarkDeclaration } from "./core/reminder-mint.js";
72
72
  export { deriveInvariants, checkInvariants } from "./core/property-harness.js";
73
- export { HAND_TOOL_EFFECTS, bashReversibilityProbe, BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName, classifyCompoundReadonly, MAX_EDIT_BYTES } from "./tools/fs/index.js";
73
+ export { bashReversibilityProbe, BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName, classifyCompoundReadonly, MAX_EDIT_BYTES } from "./tools/fs/index.js";
74
74
  export { classifyCompoundReadonlyDetailed, formatOutOfRootReadApprovalOption, } from "./tools/fs/index.js";
75
75
  export { resolveBashTimeoutCaps } from "./tools/fs/index.js";
76
76
  export { READ_FACE_DEFAULT_DENY_ENTRIES, READ_FACE_BUILTIN_DENY_TABLE, READ_DENY_BUILTIN_TIERS, READ_DENY_DEFAULT_TIERS, resolveReadDenyBuiltins, compileReadDeny, } from "./tools/fs/index.js";
@@ -100,6 +100,17 @@ export { createFsWriteGatePolicy } from "./core/fs-write-gate-policy.js";
100
100
  export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
101
101
  export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
102
102
  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 { 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
+ export { ToolRosterEntry, ToolRoster, ToolRosterDelta, ToolRosterRenderHints, ROSTER_SOURCES, toolIdentityOf, mintCapabilityId, diffToolRoster, judgeParkedToolIdentity, ruleFacesFromRoster, toolCallFaceOf, inputKeysOf, ruleFaceOfInstance, ToolRosterDeltaSeat, } from "./core/tool-roster.js";
106
+ export {} from "./core/tool-policy.js";
107
+ export { TOOL_CONFORMANCE_VECTORS, describeToolConformanceVectors } from "./core/tool-conformance.js";
108
+ export { applyMcpToolFaces, toolFaceProblem, APPROVAL_CARD_REQUIRED_KEYS } from "./core/runner/tool-face-overlay.js";
109
+ export { createStructuredProjector } from "./core/runner/tool-output-projection.js";
110
+ export { parkedToolIdentity } from "./core/tool-roster.js";
111
+ export {} from "./core/fs-write-gate-policy.js";
112
+ export { catalogRuleFaceView } from "./core/permission-rules.js";
113
+ export { DURABLE_HISTORY_NAMES } from "./engine/compaction/utils.js";
103
114
  export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveSubagentTranscriptTier, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, AUTO_MODE_ARM_REASONS, } from "./core/wiring-manifest.js";
104
115
  export { probeParkRoundTrip, durableParkGapOf, durableParkGapFor, PARK_SELFCHECK_SCOPE_PREFIX, } from "./core/park-selfcheck.js";
105
116
  export {} from "./core/checkpoint-store.js";
@@ -134,8 +145,8 @@ export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/au
134
145
  export { AUTO_MODE_ARMING_RECIPE_VERSION, autoModeArmingRecipeOf, sanitizeAutoModeArmingRecipe, foldAutoModeArming, } from "./core/auto-mode-arming.js";
135
146
  export { rebuildAutoModeDecider, } from "./core/auto-mode-rebuild.js";
136
147
  export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRule, wildcardMatch, isNamespacedCoveringRuleName, namespacedRuleNameCovers, } from "./core/permission-rules.js";
137
- 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";
138
- 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";
148
+ export { RULE_BEHAVIORS, RULE_BEHAVIOR_PRECEDENCE, RULE_BEHAVIORS_BY_PRECEDENCE, isRuleBehavior, readRowBehavior, adjudicatePersistedRules, adjudicatePersistedPathRules, ruleReachesProgramRun, 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";
149
+ 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";
139
150
  export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, } from "./core/permission-rule-sync.js";
140
151
  export { createPermissionRuleStoreProvider, effectivePermissionRules, effectiveOrThrow, ruleSourceOf, } from "./core/permission-rule-provider.js";
141
152
  export { InMemorySessionRulePartition, } from "./core/permission-rule-session.js";
@@ -236,7 +247,7 @@ export { defineAgent } from "./agents/agent-definition.js";
236
247
  export { builtinAgentDefinitions, BUILTIN_READONLY_DENY_TOOLS, EXPLORE_WHEN_TO_USE, EXPLORE_WHEN_TO_USE_LEAN, PLAN_WHEN_TO_USE, EXPLORE_SYSTEM_PROMPT, PLAN_SYSTEM_PROMPT, } from "./agents/builtin-agents.js";
237
248
  export { runTeamDiscussion, } from "./agents/team.js";
238
249
  export { createTaskServer, } from "./server/http.js";
239
- export { clearStaleToolResults, COMPACTABLE_TOOLS, editBudget, } from "./core/context-edit.js";
250
+ export { clearStaleToolResults, editBudget, } from "./core/context-edit.js";
240
251
  export { createOpenAIBrain } from "./brain/openai.js";
241
252
  export { createAnthropicBrain } from "./brain/anthropic.js";
242
253
  export { createOpenResponsesBrain } from "./brain/open-responses.js";
@@ -3,16 +3,17 @@ import { Type } from "typebox";
3
3
  import { delimitUntrusted } from "../core/untrusted-text.js";
4
4
  import { OUTPUT_TOOL_NAME } from "../core/runner/synthetic-tools.js";
5
5
  import { isDurablePause, pauseFamily } from "../agents/suspend-guard.js";
6
+ import { toolFace } from "../core/tool-catalog-entries.js";
6
7
  export const DECLARE_DONE_TOOL_NAME = "DeclareDone";
7
8
  function createDeclareDoneTool(ref) {
8
9
  return {
9
10
  name: DECLARE_DONE_TOOL_NAME,
11
+ ...toolFace("declare-done"),
10
12
  description: "Call this ONLY when you believe the goal is FULLY achieved — verified against evidence, not just " +
11
13
  "attempted. Provide a concise summary of what was achieved and how you verified it. Calling this " +
12
14
  "declares completion; a verification check then runs. If it passes, the goal stops and surfaces for " +
13
15
  "human review. If it does NOT pass, you will be asked to keep working with the verification feedback.",
14
16
  parameters: Type.Object({ summary: Type.String() }),
15
- effect: "read",
16
17
  execute: (args) => {
17
18
  ref.declared = true;
18
19
  ref.summary = String(args.summary ?? "").trim();
@@ -7,7 +7,7 @@ import { isDurablePause } from "../agents/suspend-guard.js";
7
7
  import { terminalProjection } from "../core/runner/terminal-projection.js";
8
8
  import { isAbsolutePathForm, writeTargetPath } from "../tools/fs/safety.js";
9
9
  import { captureBaseline, resolveFrozenPaths, restoreFrozenPaths, runOracle, snapshotFrozenPaths, specError, } from "../core/spec-contract.js";
10
- const WRITE_TOOLS = new Set(["Write", "Edit", "NotebookEdit"]);
10
+ import { isProtectedWrite } from "../core/tool-registry.js";
11
11
  const CASE_INSENSITIVE_FS = process.platform === "darwin" || process.platform === "win32";
12
12
  const pathKey = (p) => {
13
13
  let n = p.replace(/\\/g, "/");
@@ -19,11 +19,9 @@ function frozenDenyPolicy(rootDir, frozenResolved) {
19
19
  const frozen = new Set(frozenResolved.map(pathKey));
20
20
  return {
21
21
  check(req) {
22
- const toolName = req.toolName;
23
- if (!WRITE_TOOLS.has(toolName))
22
+ if (!isProtectedWrite(req))
24
23
  return { action: "allow" };
25
- const args = req.args;
26
- const raw = writeTargetPath(toolName, args);
24
+ const raw = writeTargetPath(req);
27
25
  if (typeof raw !== "string" || raw.length === 0)
28
26
  return { action: "allow" };
29
27
  const absForm = isAbsolutePathForm(raw);
@@ -10,6 +10,7 @@ import { parseWorkflowMeta, splitWorkflowMeta, workflowScriptReadsClockOrRandom
10
10
  import { mergeWorkflowArgs, normalizeStringArg } from "./workflow-script-store.js";
11
11
  import { builtinWorkflowListings, canonicalWorkflowName, resolveBuiltinWorkflow, workflowNameProbeOrder } from "./builtin-workflows.js";
12
12
  import { workflowSizeGuidelineSection } from "./workflow-size-guideline.js";
13
+ import { toolFace } from "../core/tool-catalog-entries.js";
13
14
  export const RUN_WORKFLOW_TOOL_NAME = "Workflow";
14
15
  function stripCodeFences(s) {
15
16
  const t = s.trim();
@@ -244,7 +245,7 @@ export async function createRunWorkflowTool(d) {
244
245
  const structuredError = (message) => errorResult(JSON.stringify({ error: message }));
245
246
  return defineTool({
246
247
  name: RUN_WORKFLOW_TOOL_NAME,
247
- contract: { contractId: "core.workflow@1", implementationRevision: "1" },
248
+ ...toolFace("workflow"),
248
249
  approvalPreview: (raw) => {
249
250
  const a = (raw ?? {});
250
251
  if (typeof a.name === "string" && a.name)
@@ -374,7 +375,6 @@ export async function createRunWorkflowTool(d) {
374
375
  "Requires a journal-backed deployment; omit for a fresh run.",
375
376
  })),
376
377
  }),
377
- effect: "write",
378
378
  execute: async (rawArgs, ctx) => {
379
379
  const rawScript = rawArgs.script;
380
380
  const rawName = rawArgs.name;
@@ -6,7 +6,7 @@ export const EVENT_PROMPT_REGISTRY = new Map([
6
6
  { kind: "plan_mode", carrier: "message.user-prefix", trust: "operator", dedupe: "replace-by-key", defaultPolicy: "off", rendererRef: "turn-attachments.ts#PLAN_MODE_FULL_BODY" },
7
7
  { kind: "date_change", carrier: "message.user-prefix", trust: "operator", dedupe: "replace-by-key", defaultPolicy: "always", rendererRef: "turn-attachments.ts#renderDateChange" },
8
8
  { kind: "instructions_change", carrier: "message.user-prefix", trust: "operator", dedupe: "replace-by-key", maxBytes: 512, defaultPolicy: "always", rendererRef: "turn-attachments.ts#collectInstructionsChange" },
9
- { kind: "workflow_size_guideline_change", carrier: "message.user-prefix", trust: "operator", dedupe: "replace-by-key", defaultPolicy: "always", rendererRef: "runtask.ts#workflowSizeGuidelineChangeNotice" },
9
+ { kind: "workflow_size_guideline_change", carrier: "message.user-prefix", trust: "operator", dedupe: "replace-by-key", defaultPolicy: "always", rendererRef: "run-turn-boundary.ts#workflowSizeGuidelineChangeNotice" },
10
10
  { kind: "budget_usd", carrier: "message.user-prefix", trust: "operator", dedupe: "replace-by-key", defaultPolicy: "off", rendererRef: "turn-attachments.ts#renderBudgetUsd" },
11
11
  { kind: "total_tokens_reminder", carrier: "message.user-prefix", trust: "operator", dedupe: "replace-by-key", defaultPolicy: "on", rendererRef: "turn-attachments.ts#renderTotalTokensReminder" },
12
12
  { kind: "background_tasks", carrier: "message.user-prefix", trust: "operator", dedupe: "replace-by-key", defaultPolicy: "on", rendererRef: "turn-attachments.ts#renderBackgroundTasks" },
@@ -16,8 +16,8 @@ export const EVENT_PROMPT_REGISTRY = new Map([
16
16
  { kind: "mcp_instructions", carrier: "message.user-prefix", trust: "external", dedupe: "replace-by-key", defaultPolicy: "off", rendererRef: "turn-attachments.ts#renderMcpInstructionsDelta" },
17
17
  { kind: "mcp_dropped_tools", carrier: "message.user-prefix", trust: "external", dedupe: "replace-by-key", defaultPolicy: "off", rendererRef: "turn-attachments.ts#renderMcpDroppedTools" },
18
18
  { kind: "git_status", carrier: "message.user-prefix", trust: "external", dedupe: "replace-by-key", defaultPolicy: "always", rendererRef: "git-status-frame.ts#renderGitStatusFrameBody" },
19
- { kind: "limit_approach_converge", carrier: "message.user-prefix", trust: "operator", dedupe: "once-per-run", defaultPolicy: "always", rendererRef: "runtask.ts#limitApproachFrames" },
20
- { kind: "limit_approach_deliver", carrier: "message.user-prefix", trust: "operator", dedupe: "once-per-run", defaultPolicy: "always", rendererRef: "runtask.ts#limitApproachFrames" },
19
+ { kind: "limit_approach_converge", carrier: "message.user-prefix", trust: "operator", dedupe: "once-per-run", defaultPolicy: "always", rendererRef: "run-turn-boundary.ts#limitApproachFrames" },
20
+ { kind: "limit_approach_deliver", carrier: "message.user-prefix", trust: "operator", dedupe: "once-per-run", defaultPolicy: "always", rendererRef: "run-turn-boundary.ts#limitApproachFrames" },
21
21
  { kind: "final_verification", carrier: "message.user-prefix", trust: "operator", dedupe: "once-per-run", defaultPolicy: "always", rendererRef: "runtask.ts#final-verification" },
22
22
  ].map((e) => [e.kind, e]));
23
23
  export function eventDefaultOn(kind) {
@@ -61,7 +61,7 @@ export declare function attachToolContract(tool: AgentTool, input: AttachContrac
61
61
  export declare function getToolContract(tool: AgentTool, fallbackOrigin?: ToolOrigin): ToolContractDescriptor;
62
62
  export declare function hasToolContract(tool: AgentTool): boolean;
63
63
  /** Manifest projection for the final mounted tool set (manifest v2 `tools`, protocol §5.4). */
64
- export declare function projectToolManifest(tools: AgentTool[], originOf?: (tool: AgentTool) => ToolOrigin): ToolManifestRow[];
64
+ export declare function projectToolManifest(tools: readonly AgentTool[], originOf?: (tool: AgentTool) => ToolOrigin): ToolManifestRow[];
65
65
  /**
66
66
  * RB-15: wire-identity collision audit over the FINAL mounted tool set.
67
67
  * Rules (plan §6.2 tool row):
@@ -71,7 +71,7 @@ export declare function projectToolManifest(tools: AgentTool[], originOf?: (tool
71
71
  * a built-in; the harness Map keeps the later mount) — NOT fatal, but returned as an explicit
72
72
  * exemption record so the mount site can surface it (observable, never silent).
73
73
  */
74
- export declare function auditToolCollisions(tools: AgentTool[]): {
74
+ export declare function auditToolCollisions(tools: readonly AgentTool[]): {
75
75
  yields: Array<{
76
76
  name: string;
77
77
  }>;
@@ -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);
@@ -2,17 +2,21 @@
2
2
  * design/179 §5/§8 / design/389 — the file backend of the permission-rule store's DURABLE partition (one
3
3
  * bucket file per owner), plus the file home of the ORG partition's durable state (`org.json`).
4
4
  *
5
- * ## Schema 3 and the one-time migration
5
+ * ## Schema 4 and the one-time migration
6
6
  *
7
7
  * Pre-389 files (schema 1/2) kept the org last-known-good snapshot as an `org` block INSIDE each
8
- * principal's bucket file — deployment-wide policy stored per person. Schema 3 drops that block; the org
9
- * state lives in one `org.json` beside the buckets. `FileDurableRulePartitionProvider` migrates every
10
- * legacy bucket file ONCE at construction (under the writer lock: the migration is a write, and a live
11
- * older writer over the same directory is refused rather than raced), folding each file's `org` block
12
- * into `org.json` by the anti-rollback rule (the highest high-water wins; an equal revision with
13
- * different content keeps what is already installed and discloses). After that the reader accepts
14
- * schema 3 ONLY a 1/2/4 file is refused whole, loudly (zero rules + disclosure). There is no second
15
- * read path for the old shapes: the migrator is the only code that reads them, and it runs once.
8
+ * principal's bucket file — deployment-wide policy stored per person. Schema 3 dropped that block; the org
9
+ * state lives in one `org.json` beside the buckets. Schema 4 adds the `behavior` member to every rule row,
10
+ * tombstone and quarantine row (the rule identity is the (behavior, text, scope) triple): a schema-3 row has
11
+ * none, and every row a schema-3 engine wrote was an allow, so the migration stamps `"allow"` on each — the
12
+ * ONE reading of the pre-field row (`readRowBehavior`), applied once, here, never at a read face.
13
+ * `FileDurableRulePartitionProvider` migrates every legacy bucket file (1, 2 or 3) ONCE at construction
14
+ * (under the writer lock: the migration is a write, and a live older writer over the same directory is
15
+ * refused rather than raced), folding a 1/2 file's `org` block into `org.json` by the anti-rollback rule
16
+ * (the highest high-water wins; an equal revision with different content keeps what is already installed
17
+ * and discloses). After that the reader accepts schema 4 ONLY — a 1/2/3/5 file is refused whole, loudly
18
+ * (zero rules + disclosure). There is no second read path for the old shapes: the migrator is the only
19
+ * code that reads them, and it runs once.
16
20
  *
17
21
  * ## Why this store builds its own symlink refusal
18
22
  *
@@ -55,23 +59,23 @@
55
59
  * and is not: it detects corruption, and it does not detect an editor, because an editor recomputes it.
56
60
  * For this backend the trust is host = user, exactly as for the settings file it mirrors.
57
61
  */
58
- import type { PersistedAllowRule, RuleTombstone } from "../../core/permission-rule-model.js";
59
- import type { DurableRulePartition, DurableRulePartitionProvider, PermissionRuleWriter, QuarantinedRuleAdd, RuleOwner, RuleSyncFrontier, StoredAllowRules, WritableDurableRulePartition } from "../../core/permission-rule-store.js";
62
+ import type { PersistedRule, RuleTombstone } from "../../core/permission-rule-model.js";
63
+ import type { DurableRulePartition, DurableRulePartitionProvider, PermissionRuleWriter, QuarantinedRuleAdd, RuleOwner, RuleSyncFrontier, StoredRules, WritableDurableRulePartition } from "../../core/permission-rule-store.js";
60
64
  import { PERMISSION_RULE_WRITER } from "../../core/permission-rule-store.js";
61
65
  import type { OrgRuleStatePersistence, PersistedOrgRuleState } from "../../core/permission-rule-org.js";
62
66
  import type { StoreDurability, StoreFidelity } from "../../core/checkpoint-store.js";
63
67
  /**
64
68
  * The on-disk shape of one bucket. `schemaVersion` is the only field a future reader may rely on before
65
- * validating. Schema 3 (design/389): the five core fields plus the OPTIONAL `sync` block (observation
66
- * vector + round timestamp) and `quarantined` area (rows moved out of the live view, bytes preserved).
67
- * The org state is NOT here — see {@link OrgStateFile}.
69
+ * validating. Schema 4: the five core fields plus the OPTIONAL `sync` block (observation vector + round
70
+ * timestamp) and `quarantined` area (rows moved out of the live view, bytes preserved); every rule,
71
+ * tombstone and quarantine row carries its `behavior`. The org state is NOT here — see {@link OrgStateFile}.
68
72
  */
69
73
  interface RuleFile {
70
- schemaVersion: 3;
74
+ schemaVersion: 4;
71
75
  actor: string;
72
76
  counter: number;
73
77
  rev: number;
74
- rules: PersistedAllowRule[];
78
+ rules: PersistedRule[];
75
79
  tombstones: RuleTombstone[];
76
80
  sync?: {
77
81
  observedVector?: RuleSyncFrontier;
@@ -88,10 +92,10 @@ interface OrgStateFile {
88
92
  }
89
93
  /** The org partition's durable home in a rule directory. */
90
94
  export declare const ORG_STATE_FILE = "org.json";
91
- /** Written once the directory is known to hold only schema-3 buckets. Its presence ends the legacy
92
- * scan for good: a schema 1/2 bucket that appears AFTERWARDS (an older engine writing after the
95
+ /** Written once the directory is known to hold only schema-4 buckets. Its presence ends the legacy
96
+ * scan for good: a schema 1/2/3 bucket that appears AFTERWARDS (an older engine writing after the
93
97
  * cutover) is refused by the reader on every later construction too, never re-admitted by a restart. */
94
- export declare const SCHEMA3_MARKER_FILE = ".rule-schema-3";
98
+ export declare const SCHEMA_MARKER_FILE = ".rule-schema-4";
95
99
  /** The anti-rollback contract's DESIGNED refusal (a lower high-water mark, or different content under
96
100
  * the same revision) — distinguished by class from every other install failure, because the two are
97
101
  * handled in opposite directions by the migration: a refusal means the block is superseded and may be
@@ -148,7 +152,7 @@ declare class FileDurableRulePartition implements WritableDurableRulePartition {
148
152
  */
149
153
  private screenDurableRows;
150
154
  private write;
151
- list(): Promise<StoredAllowRules>;
155
+ list(): Promise<StoredRules>;
152
156
  /** The quarantine area (design/182 §5.2/§8.3): introspection only — never part of `list()`. */
153
157
  quarantined(): Promise<QuarantinedRuleAdd[]>;
154
158
  /**
@@ -209,7 +213,8 @@ export declare class FileDurableRulePartitionProvider implements DurableRulePart
209
213
  dataRoot?: string;
210
214
  });
211
215
  /**
212
- * Fold every legacy bucket file in `dir` into schema 3 and its `org` block into `org.json`. A no-op on a
216
+ * Fold every legacy bucket file in `dir` into schema 4 (stamping `behavior: "allow"` on every pre-field
217
+ * row — the one pre-field reading) and a 1/2 file's `org` block into `org.json`. A no-op on a
213
218
  * directory with no legacy file (zero writes, the lock untouched — the second construction over a
214
219
  * migrated directory is byte-silent). A legacy file whose checksum or shape does not hold is NOT
215
220
  * migrated: its bytes stay where they are for a person to look at, and the reader keeps refusing it
@@ -220,10 +225,10 @@ export declare class FileDurableRulePartitionProvider implements DurableRulePart
220
225
  * shape — the old engine's buckets are refused whole until they are migrated.
221
226
  */
222
227
  private migrateLegacyBuckets;
223
- /** Publish the schema-3 completion marker (idempotent, atomic, no lock: its content never changes and
228
+ /** Publish the schema-4 completion marker (idempotent, atomic, no lock: its content never changes and
224
229
  * a concurrent writer of the same bytes is harmless). A failure to write it is disclosed, not thrown —
225
230
  * the next construction simply scans again, which is the safe direction. */
226
- private writeSchema3Marker;
231
+ private writeSchemaMarker;
227
232
  /** The org partition's durable home in this directory (design/182 §7.4 contract; `org.json`). Shares
228
233
  * this provider's writer lock — an install is a write. */
229
234
  orgStatePersistence(): OrgRuleStatePersistence;