@sema-agent/core 7.42.0 → 7.43.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 (89) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/dist/agents/send-message-tool.js +1 -0
  3. package/dist/agents/subagent.d.ts +1 -0
  4. package/dist/agents/subagent.js +5 -3
  5. package/dist/agents/teacher.js +1 -1
  6. package/dist/agents/verify.js +2 -0
  7. package/dist/core/allow-entry.d.ts +50 -31
  8. package/dist/core/allow-entry.js +100 -37
  9. package/dist/core/ask-origin.d.ts +16 -5
  10. package/dist/core/ask-origin.js +11 -3
  11. package/dist/core/ask-unresolvable-notice.d.ts +3 -2
  12. package/dist/core/ask-unresolvable-notice.js +1 -1
  13. package/dist/core/auto-mode.d.ts +5 -4
  14. package/dist/core/auto-mode.js +3 -1
  15. package/dist/core/checkpoint-store.d.ts +19 -8
  16. package/dist/core/checkpoint-store.js +8 -4
  17. package/dist/core/child-clamp-seats.d.ts +15 -1
  18. package/dist/core/child-clamp-seats.js +6 -2
  19. package/dist/core/classifier-unavailable-arm.d.ts +42 -23
  20. package/dist/core/classifier-unavailable-arm.js +14 -3
  21. package/dist/core/decision-receipt.js +2 -0
  22. package/dist/core/gate-lanes.js +37 -29
  23. package/dist/core/hooks.d.ts +6 -1
  24. package/dist/core/hooks.js +3 -0
  25. package/dist/core/mode-policy.d.ts +5 -4
  26. package/dist/core/mode-policy.js +4 -0
  27. package/dist/core/permission-rule-consent.d.ts +3 -2
  28. package/dist/core/permission-rule-consent.js +25 -20
  29. package/dist/core/permission-rule-model.d.ts +47 -7
  30. package/dist/core/permission-rule-model.js +80 -6
  31. package/dist/core/permission-rules.d.ts +8 -2
  32. package/dist/core/permission-rules.js +26 -9
  33. package/dist/core/runner/classifier-ladder.d.ts +10 -8
  34. package/dist/core/runner/classifier-ladder.js +3 -1
  35. package/dist/core/runner/denial-limit-arms.d.ts +25 -8
  36. package/dist/core/runner/denial-limit-arms.js +24 -10
  37. package/dist/core/runner/gate-exit.js +2 -1
  38. package/dist/core/runner/permission-rule-lanes.d.ts +2 -2
  39. package/dist/core/runner/permission-rule-lanes.js +8 -2
  40. package/dist/core/runner/prepare-ask-lane.d.ts +3 -0
  41. package/dist/core/runner/prepare-ask-lane.js +2 -1
  42. package/dist/core/runner/prepare-caps-and-workflow.d.ts +2 -3
  43. package/dist/core/runner/prepare-caps-and-workflow.js +3 -2
  44. package/dist/core/runner/prepare-config-doors.d.ts +3 -0
  45. package/dist/core/runner/prepare-config-doors.js +6 -5
  46. package/dist/core/runner/prepare-gate-stations.js +1 -1
  47. package/dist/core/runner/prepare-inherited-gate.d.ts +7 -5
  48. package/dist/core/runner/prepare-inherited-gate.js +5 -3
  49. package/dist/core/runner/prepare-park-ask.d.ts +4 -4
  50. package/dist/core/runner/prepare-park-ask.js +2 -4
  51. package/dist/core/runner/prepare-policy-chain.d.ts +7 -1
  52. package/dist/core/runner/prepare-policy-chain.js +59 -38
  53. package/dist/core/runner/prepare-project-context.js +6 -2
  54. package/dist/core/runner/prepare-task.js +6 -6
  55. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -5
  56. package/dist/core/runner/prepare-wiring-manifest.js +8 -9
  57. package/dist/core/runner/resume-checkpoint-screen.js +1 -1
  58. package/dist/core/runner/steer-admission.js +2 -1
  59. package/dist/core/runner/stream-steer-verb.js +2 -2
  60. package/dist/core/runner/synthetic-tools.d.ts +3 -2
  61. package/dist/core/runner/synthetic-tools.js +1 -1
  62. package/dist/core/session-policy-store.d.ts +3 -3
  63. package/dist/core/session-policy-store.js +18 -4
  64. package/dist/core/skill-grant-binding.d.ts +44 -0
  65. package/dist/core/skill-grant-binding.js +22 -0
  66. package/dist/core/skill-grant.d.ts +59 -28
  67. package/dist/core/skill-grant.js +96 -23
  68. package/dist/core/task-notification.d.ts +6 -0
  69. package/dist/core/task-notification.js +3 -0
  70. package/dist/core/task-spec.d.ts +14 -1
  71. package/dist/core/tighten-task-spec.d.ts +2 -0
  72. package/dist/core/tighten-task-spec.js +3 -0
  73. package/dist/core/tool-name-aliases.d.ts +35 -5
  74. package/dist/core/tool-name-aliases.js +29 -4
  75. package/dist/core/tool-policy.d.ts +10 -0
  76. package/dist/core/tool-policy.js +9 -2
  77. package/dist/core/tool-spec.d.ts +7 -0
  78. package/dist/core/wiring-manifest.d.ts +56 -14
  79. package/dist/core/wiring-manifest.js +29 -4
  80. package/dist/index.d.ts +4 -3
  81. package/dist/index.js +3 -3
  82. package/dist/orchestration/run-workflow-tool.d.ts +4 -0
  83. package/dist/orchestration/run-workflow-tool.js +1 -1
  84. package/dist/orchestration/workflow-primitives.d.ts +3 -1
  85. package/dist/orchestration/workflow-primitives.js +6 -6
  86. package/package.json +1 -1
  87. package/test/export-surface.snapshot.json +13 -1
  88. package/wire-changes/core@7.42.1.json +56 -0
  89. package/wire-changes/core@7.43.0.json +985 -0
@@ -12,7 +12,7 @@ import { resolveSkillListingBudget } from "../skill-listing-budget.js";
12
12
  import { describeRejectedValue } from "../tool-search-setting.js";
13
13
  import { applyToolModelGate, assertRestoreGatedToolsValue, modelIdTail } from "../tool-model-gate.js";
14
14
  import { resolveUsageWindows } from "../usage-window-store.js";
15
- import { deriveAskEffective, resolveAskSeamForm, resolveQuestionSeam } from "../wiring-manifest.js";
15
+ import { deriveAskEffective, resolveAskSeat, resolveQuestionSeam } from "../wiring-manifest.js";
16
16
  import { assertPeerPresenceValue } from "../../agents/peer-directory.js";
17
17
  import { TOTAL_TOKENS_REMINDER_MODES } from "./turn-attachments.js";
18
18
  const TASK_LIMIT_KEY_DICT = {
@@ -286,6 +286,7 @@ export function prepareConfigDoors(input) {
286
286
  ],
287
287
  });
288
288
  const resolvedInteractionPosture = spec.interactionPosture ?? internals?.parentInteractionPosture ?? deps.interactionPosture;
289
+ const askSeat = resolveAskSeat(spec, deps);
289
290
  {
290
291
  const interactionPosture = resolvedInteractionPosture;
291
292
  const discloseInteractionPostureRefusal = (err) => {
@@ -303,8 +304,7 @@ export function prepareConfigDoors(input) {
303
304
  throw e;
304
305
  }
305
306
  if (interactionPosture === "interactive") {
306
- const askDoor = resolveAskSeamForm(spec, deps);
307
- const humanReachable = deriveAskEffective(askDoor.form, "unresolved") === "human_reachable";
307
+ const humanReachable = deriveAskEffective(askSeat.form, "unresolved") === "human_reachable";
308
308
  const questionDoor = resolveQuestionSeam(spec, deps);
309
309
  const strippedByEngine = internals?.questionFaceStripped === true;
310
310
  if (spec.interactiveTools === false) {
@@ -318,9 +318,9 @@ export function prepareConfigDoors(input) {
318
318
  if (!humanReachable || !(questionDoor.wired || strippedByEngine)) {
319
319
  const missing = [];
320
320
  if (!humanReachable) {
321
- missing.push(askDoor.form === "absent"
321
+ missing.push(askSeat.form === "declared_none" ? 'this run declares approvalReach: "none" — nobody on it can be asked to approve' : askSeat.form === "absent"
322
322
  ? "no onAsk approver is wired (spec.onAsk ?? deps.onAsk is absent — asks would auto-deny or park)"
323
- : `the resolved onAsk seat is the blanket policy "${askDoor.form}" (${askDoor.provenance ?? "?"}) — a policy setting is not a reachable human`);
323
+ : `the resolved onAsk seat is the blanket policy "${askSeat.form}" (${askSeat.provenance ?? "?"}) — a policy setting is not a reachable human`);
324
324
  }
325
325
  if (!questionDoor.wired && !strippedByEngine) {
326
326
  missing.push("no content-question channel (spec.onQuestion ?? deps.onQuestion is absent, and this leg is not an engine-stripped background lane)");
@@ -433,6 +433,7 @@ export function prepareConfigDoors(input) {
433
433
  promptProfile,
434
434
  lockedPreflight,
435
435
  resolvedInteractionPosture,
436
+ askSeat,
436
437
  microCompactKnob,
437
438
  resolvedRole,
438
439
  model,
@@ -137,7 +137,7 @@ export function prepareGateStations(input) {
137
137
  onHookError: notifyHookError,
138
138
  shellGated: tierSeat?.shellGated(shellGatedTools, toolMarkSources) === true,
139
139
  ...(autoModeDecider.current !== undefined ? { autoMode: { decider: autoModeDecider.current, ...(autoModeDenialTracking.current !== undefined ? { denialTracking: autoModeDenialTracking.current } : {}), unavailable: classifierUnavailableSeat({ station: "leg", ...(autoModeDecider.current.timeoutMs !== undefined ? { budgetMs: autoModeDecider.current.timeoutMs } : {}), approvalSeat: askReachesPerson(askRoute), onNotice: deps.onNotice, sessionId, runId }) } } : {}),
140
- permissionMode: () => permissionMode.current,
140
+ permissionMode: () => permissionMode.current, askSeatForm: askRoute.form,
141
141
  ...(markSources.size > 0 ? { toolMarkSources: markSources } : {}),
142
142
  ...seatInputsFor(e.toolName, wireOf("gate.skillActivationSeat", call)),
143
143
  ...(mountedToolRequiresUserInteraction(tools, e.toolName) ? { requiresUserInteraction: true } : {}),
@@ -50,19 +50,21 @@ import { type SkillGrantTable } from "../skill-grant.js";
50
50
  import type { InheritedGate, Prepared, PrepareResume, RunInternals, StopForDenialLimit, ToolFaceSnapshot, WriteFaceSeat } from "./contracts.js";
51
51
  export interface PrepareInheritedGateInput {
52
52
  /** borrowed-readonly — the REBOUND spec. Read: `shellGate` (the own doctrine the chain fold tightens), `durableApproval`
53
- * (the mandate tests + the children's copy), `onAsk`/`onQuestion` (the frozen seats), `handsReadOnly` / `interactiveTools`
53
+ * (the mandate tests + the children's copy), `onQuestion` (the frozen question seat), `handsReadOnly` / `interactiveTools`
54
54
  * / `oneShot` / `clientContext` / `principal` / `additionalDirectories` / `additionalReadDirectories` / `envFacts` /
55
55
  * `memoryPersistenceCapable` / `getApiKeyAndHeaders` / `backgroundScope` / `enablePlanMode` (the ctx enrichment's
56
56
  * trusted seats). Never mutated. */
57
- spec: Pick<TaskSpec, "shellGate" | "durableApproval" | "onAsk" | "onQuestion" | "handsReadOnly" | "interactiveTools" | "oneShot" | "clientContext" | "principal" | "additionalDirectories" | "additionalReadDirectories" | "envFacts" | "memoryPersistenceCapable" | "getApiKeyAndHeaders" | "backgroundScope" | "enablePlanMode" | "excludeAllTools">;
57
+ spec: Pick<TaskSpec, "shellGate" | "durableApproval" | "onQuestion" | "handsReadOnly" | "interactiveTools" | "oneShot" | "clientContext" | "principal" | "additionalDirectories" | "additionalReadDirectories" | "envFacts" | "memoryPersistenceCapable" | "getApiKeyAndHeaders" | "backgroundScope" | "enablePlanMode" | "excludeAllTools">;
58
58
  /** borrowed-readonly — the seat this run hands its children (`checkpointSeatOf`, minted once by the driver after the config doors): the ctx's `checkpointStoreForChildren`, absent when the run has no seat. */
59
59
  checkpointSeat: import("../checkpoint-seat.js").CheckpointSeat | undefined;
60
60
  /** borrowed-readonly — the deployment seats: `autoMode.denialLimit` (the rebuilt trackers' bounds), `memoryScopeAdmission` /
61
61
  * `deploymentMemoryScopes` / `compliancePostureResolver` (the governed-provenance bit), `onError` (the screening-face crash
62
62
  * lane), `onNotice` (the stop seat's notice), `executionEnv` (the hook-env identity predicate), `delegationEntryCaps` (resolved
63
- * and validated once here), `rosterStore` / `onBackgroundChildEvent` (ctx seats), `onAsk` / `onQuestion` (the deps half of the
64
- * frozen seats). */
65
- deps: Pick<RunnerDeps, "autoMode" | "memoryScopeAdmission" | "deploymentMemoryScopes" | "compliancePostureResolver" | "onError" | "onNotice" | "executionEnv" | "delegationEntryCaps" | "rosterStore" | "onBackgroundChildEvent" | "onAsk" | "onQuestion">;
63
+ * and validated once here), `rosterStore` / `onBackgroundChildEvent` (ctx seats), `onQuestion` (the deps half of the
64
+ * frozen question seat). */
65
+ deps: Pick<RunnerDeps, "autoMode" | "memoryScopeAdmission" | "deploymentMemoryScopes" | "compliancePostureResolver" | "onError" | "onNotice" | "executionEnv" | "delegationEntryCaps" | "rosterStore" | "onBackgroundChildEvent" | "onQuestion">;
66
+ /** borrowed-readonly — the run's approval seat as the config doors froze it: the frozen approver, and this leg's chain view. */
67
+ askSeat: import("../wiring-manifest.js").AskSeat;
66
68
  /** borrowed-readonly — the trusted spawn-side channel: `inheritedGate` (the LIVE half of the chain fold), `ownOrgAdmissionRef`
67
69
  * (the same-session continuation's freeze), `delegationProvenance` (the F-012 stamp), and the identity / peer / notification
68
70
  * seats the ctx enrichment forwards. Never mutated. */
@@ -13,7 +13,7 @@ import { frozenSkillGrants } from "../skill-grant.js";
13
13
  import { attachRebuiltDenialTrackers, createDenialLimitStop } from "./denial-limit-arms.js";
14
14
  import { asThrownError } from "../thrown-value.js";
15
15
  export function prepareInheritedGate(input) {
16
- const { spec, deps, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, toolFaceSnapshot, mountsCallerTool, promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun } = input;
16
+ const { spec, deps, askSeat, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, toolFaceSnapshot, mountsCallerTool, promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun } = input;
17
17
  const liveInheritedGate = internals?.inheritedGate;
18
18
  const seedInheritedGate = resume?.seed.inheritedGate;
19
19
  const inheritedAncestorRules = (() => {
@@ -35,7 +35,8 @@ export function prepareInheritedGate(input) {
35
35
  })();
36
36
  const modeSeed = recordedModeSeed(seedInheritedGate);
37
37
  const inheritedShellGate = liveInheritedGate?.shellGate ?? modeSeed.shellGate;
38
- const inheritedParentConstraints = attachRebuiltDenialTrackers(liveInheritedGate?.parentConstraints, deps.autoMode?.denialLimit);
38
+ const chainView = askSeat.reach === "none" ? liveInheritedGate?.parentConstraints?.map((pc) => (typeof pc.onAsk === "function" ? ((({ onAsk: _person, ...rest }) => rest)(pc)) : pc)) : liveInheritedGate?.parentConstraints;
39
+ const inheritedParentConstraints = attachRebuiltDenialTrackers(chainView, deps.autoMode?.denialLimit);
39
40
  const parentSeat = liveInheritedGate?.permissionModeCeiling;
40
41
  const ceiling = parentSeat ?? liveInheritedGate?.permissionMode;
41
42
  const announceModeFold = (receipt) => {
@@ -113,7 +114,7 @@ export function prepareInheritedGate(input) {
113
114
  const f012CheckpointState = () => (inheritedParentConstraints?.length ?? 0) > 0 ||
114
115
  seedInheritedGate?.constraintChain !== undefined ||
115
116
  internals?.delegationProvenance !== undefined;
116
- const frozenOnAsk = spec.onAsk ?? deps.onAsk;
117
+ const frozenOnAsk = askSeat.value;
117
118
  const hookEnvSource = (ownedEnv ?? deps.executionEnv) != null ? executionEnv : undefined;
118
119
  const notifyOwnHookCrash = (err) => {
119
120
  try {
@@ -213,6 +214,7 @@ export function prepareInheritedGate(input) {
213
214
  thinkingLevel: harnessRef.current?.getThinkingLevel(),
214
215
  principal: spec.principal,
215
216
  ...(frozenOnAsk !== undefined ? { onAsk: frozenOnAsk } : {}),
217
+ ...(askSeat.reach !== undefined ? { approvalReach: askSeat.reach } : {}),
216
218
  ...(frozenOnQuestion !== undefined ? { onQuestion: frozenOnQuestion } : {}),
217
219
  ...(spec.handsReadOnly === true ? { handsReadOnly: true } : {}),
218
220
  ...(carrierReadFace() === "roots" ? { readFace: "roots" } : {}),
@@ -22,6 +22,7 @@
22
22
  import type { AgentHarness, AgentMessage, AgentTool, ExecutionEnv } from "../../internal/harness.js";
23
23
  import { type OnQuestion } from "../ask-question.js";
24
24
  import { type CheckpointStore } from "../checkpoint-store.js";
25
+ import type { GrantBindingOf } from "../skill-grant-binding.js";
25
26
  import type { SessionStore } from "../session.js";
26
27
  import { type OnAsk, type ToolCallRequest, type ToolPolicy } from "../tool-policy.js";
27
28
  import { type ToolResultStore } from "../tool-result-store.js";
@@ -32,7 +33,6 @@ import { type ContentAskBinding } from "./content-ask-bindings.js";
32
33
  import type { AskLane, IrreversibilityTier, ParkAsk, Prepared, SuspendSaga } from "./contracts.js";
33
34
  import type { createRuleOffersOf } from "./permission-rule-lanes.js";
34
35
  import { type ToolRosterDeltaSeat } from "../tool-roster.js";
35
- import { type SkillGrantSource } from "../skill-grant.js";
36
36
  export interface PrepareParkAskInput {
37
37
  /** borrowed-readonly — the in-stream ask lane, or undefined when the gate machinery is inactive (then both closures are
38
38
  * absent). Read: `composedCallSignal` (the fence and the delivery race), `approvalPreviewOf` (the row's preview). */
@@ -141,9 +141,9 @@ export interface PrepareParkAskInput {
141
141
  orgAdmissionCheckpointState: () => boolean;
142
142
  /** borrowed-readonly — the policy-chain phase's rule-offer factory (the row's suggestion members). */
143
143
  ruleOffersOf: ReturnType<typeof createRuleOffersOf>;
144
- /** borrowed-readonly — the leg's loaded skills (what its `Skill` tool serves); a parked `Skill` call's row binds the named
145
- * skill — its name and its lists — from them (`boundGrantDigest`). Empty when the leg loads none. */
146
- skillSpecs: readonly SkillGrantSource[];
144
+ /** borrowed-readonly — the policy-chain phase's Skill-card binding factory: a parked `Skill` call's row carries the named skill and
145
+ * its lists (`boundGrants`) and their hash (`boundGrantDigest`) from it, as the live ask does. */
146
+ grantBindingOf: GrantBindingOf;
147
147
  /** borrowed-readonly — the injectable wall clock (the row's `suspendedAt`). */
148
148
  now: () => number;
149
149
  /** borrowed-readonly — the per-task human-review accumulator; snapshotted onto the row (never written here). */
@@ -17,8 +17,6 @@ import { DEFAULT_UNATTENDED_APPROVAL_TTL_MS, publishCommittedSuspend, sanitizedT
17
17
  import { remoteEnvFailureNote } from "./remote-env-retry.js";
18
18
  import { callFaceSeat, parkedToolIdentity, parkedToolFace } from "../tool-roster.js";
19
19
  import { seatOf, wireOf } from "../tool-name-readings.js";
20
- import { skillCallGrantDigest } from "../skill-grant.js";
21
- import { SKILL_TOOL_NAME } from "./synthetic-tools.js";
22
20
  class ParkRefusal extends Error {
23
21
  constructor(message, options) {
24
22
  super(message, options);
@@ -29,7 +27,7 @@ const wordlessDemand = (toolName) => {
29
27
  throw new Error(`a real-approval demand for "${toolName}" reached the park with no origin word — the origin stamp precedes every park`);
30
28
  };
31
29
  export function prepareParkAsk(input) {
32
- const { askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, irreversibilityTier, toolMarkSources, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, skillSpecs, now, humanReviewRef, abortController, harness, pausedRef } = input;
30
+ const { askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, irreversibilityTier, toolMarkSources, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, grantBindingOf, now, humanReviewRef, abortController, harness, pausedRef } = input;
33
31
  if (askLane === undefined || saga === undefined)
34
32
  return { parkAsk: undefined };
35
33
  const { composedCallSignal, approvalPreviewOf } = askLane;
@@ -318,7 +316,7 @@ export function prepareParkAsk(input) {
318
316
  ...askCarryRowMembers(carry),
319
317
  ...ruleOffersOf(req, parkedArgs, clearanceFacts),
320
318
  boundInputHash: boundInputHashOf(parkedArgs),
321
- ...((grantDigest) => (grantDigest !== undefined ? { boundGrantDigest: grantDigest } : {}))(skillCallGrantDigest(req, parkedArgs, skillSpecs, SKILL_TOOL_NAME)),
319
+ ...grantBindingOf(req, parkedArgs),
322
320
  batchToolCallIds,
323
321
  completedCallIds,
324
322
  }),
@@ -30,7 +30,8 @@ import { type OnAsk, type ToolPolicy } from "../tool-policy.js";
30
30
  import type { RunnerDeps, RuntimeCaps, TaskSpec, ToolEffect } from "../types.js";
31
31
  import type { CwdRef } from "../../tools/fs/fs-shared.js";
32
32
  import type { ReadDenyMatcher } from "../../tools/fs/read-deny.js";
33
- import type { SkillGrantLane, SkillGrantTable } from "../skill-grant.js";
33
+ import { type SkillGrantLane, type SkillGrantSource, type SkillGrantTable } from "../skill-grant.js";
34
+ import type { GrantBindingOf } from "../skill-grant-binding.js";
34
35
  import { type AllowEntryLane, type AllowEntryTable } from "../allow-entry.js";
35
36
  import type { InheritedGate, IrreversibilityTier, PrepareResume, RunInternals, StopForDenialLimit } from "./contracts.js";
36
37
  import { type Arbitration } from "../ask-origin.js";
@@ -122,6 +123,8 @@ export interface PreparePolicyChainInput {
122
123
  /** borrowed-readonly — the run's skill grant table; this phase binds its lane to the call facts the person's rule lane
123
124
  * reads (root, session, live cwd, the execution environment's home). Not written here. */
124
125
  skillGrants: SkillGrantTable;
126
+ /** borrowed-readonly — the loaded skills (the table the `Skill` tool activates from); {@link PreparePolicyChainResult.grantBindingOf} reads them. */
127
+ skillSpecs: readonly SkillGrantSource[];
125
128
  /** borrowed-readonly — the request's and the deployment's allow-entry tables (prepare seeded them); this phase binds
126
129
  * their lanes to the same call facts. Not written here. */
127
130
  allowedToolTables: {
@@ -218,6 +221,9 @@ export interface PreparePolicyChainResult {
218
221
  };
219
222
  /** owned — the ONE rule-offer factory for all five ask-mint sites. */
220
223
  ruleOffersOf: ReturnType<typeof createRuleOffersOf>;
224
+ /** owned — the ONE Skill-card binding factory for the same five sites: a call to the engine's `Skill` tool carries the skill and
225
+ * its two lists (`boundGrants`) and their hash (`boundGrantDigest`) on the live ask, an ancestor's and the parked row alike. */
226
+ grantBindingOf: GrantBindingOf;
221
227
  /** owned — the personal permission-rule lane, or undefined. */
222
228
  permissionRuleLane: PermissionRuleLanes["personal"];
223
229
  /** owned — the org permission-rule lane (`Prepared.permissionRuleOrg`), or undefined. */
@@ -7,14 +7,16 @@ import { assertHookSeatsCallable } from "../hook-seats.js";
7
7
  import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "../permission-rules.js";
8
8
  import { isIsolated } from "../remote-env.js";
9
9
  import { askApproverIdentity, carryEngineAttestations, carryPrecedingSettlement, checkToolPolicyProjection, combinePolicies, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, durableParkOptInDeclared, isLiveApproverSeat, refuseOutOfContractDecision, resolveAsk, toolPolicyNameSets, wrapToolPolicy, attestAskUnresolvableCause } from "../tool-policy.js";
10
- import { judgeRuleToolName } from "../tool-name-aliases.js";
10
+ import { judgeRuleToolName, mountedToolNames } from "../tool-name-aliases.js";
11
11
  import { NAMESPACED_NAME_SHAPES } from "../protocol-table.js";
12
12
  import { emitTrace } from "../trace.js";
13
+ import { skillGrantBindingMembers } from "../skill-grant.js";
14
+ import { SKILL_TOOL_NAME } from "./synthetic-tools.js";
13
15
  import { autoStrippedRule, cardDisclosureOf } from "../allow-entry.js";
14
16
  import { arbitrateByMode, askClassMembersOf, askMandateMember } from "../ask-origin.js";
15
17
  import { createModeGatePolicy, mountedToolDeclaresReadOnly } from "../mode-policy.js";
16
18
  const ancestorFacts = (ask) => ({ ...(ask ?? {}), ancestorResolved: true });
17
- import { headlessDenyAtFold, headlessDenyAtRecheck, INHERITED_STATION_FACTS, inheritedAskCarry, inheritedAskFallbackMessage, judgeInheritedClassifier, lateAskSettlementObserver, settleDenialLimitFallback } from "./denial-limit-arms.js";
19
+ import { headlessDenyAtFold, headlessDenyAtRecheck, INHERITED_STATION_FACTS, inheritedAskCarry, inheritedAskFallbackMessage, judgeInheritedClassifier, lateAskSettlementObserver, resolveInheritedAsk, settleDenialLimitFallback } from "./denial-limit-arms.js";
18
20
  import { settleReadRootGrant } from "./read-root-grant.js";
19
21
  import { askGrantShapeOf } from "./inherited-ask-grants.js";
20
22
  import { createPermissionRuleLanes, inheritedAskRuleEvidence, createRuleOffersOf } from "./permission-rule-lanes.js";
@@ -22,7 +24,7 @@ import { createLiveSessionRules, createSessionRulePolicy } from "./session-rule-
22
24
  import { thrownText } from "../thrown-value.js";
23
25
  import { heldBy, heldValues, seatOf, wireOf } from "../tool-name-readings.js";
24
26
  export async function preparePolicyChain(input) {
25
- const { spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, announceRuleStoreSkipped, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider, permissionMode, scratchpadDir, toolRosterDeltas, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef } = input;
27
+ const { spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, announceRuleStoreSkipped, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider, permissionMode, scratchpadDir, toolRosterDeltas, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef } = input;
26
28
  const ancestorArbitrations = new Map();
27
29
  const arbitrateInherited = (ask, toolCallId, judged) => {
28
30
  const verdict = arbitrateByMode(permissionMode.current, judged.classification, { origin: judged.origin, ...askMandateMember(ancestorFacts(judged.ask.action === "ask" ? judged.ask : undefined)) });
@@ -37,7 +39,7 @@ export async function preparePolicyChain(input) {
37
39
  const auditPolicyNames = (auditee) => {
38
40
  const nameGroups = toolPolicyNameSets(auditee);
39
41
  if (nameGroups.length > 0) {
40
- const known = new Set(tools.flatMap((t) => [t.name, ...(t.aliases ?? [])]));
42
+ const known = mountedToolNames(tools);
41
43
  for (const t of harnessTools)
42
44
  known.add(t.name);
43
45
  const unmatched = new Set();
@@ -46,9 +48,24 @@ export async function preparePolicyChain(input) {
46
48
  for (const n of list ?? []) {
47
49
  const verdict = judgeRuleToolName(n, known);
48
50
  if (verdict.kind !== "current") {
49
- const err = new Error(verdict.kind === "retired"
50
- ? `tool policy ${kind}-list entry "${n}" is a RETIRED tool name (${verdict.guidance}) and matches nothing in this run's roster — legacy-name normalization was removed (RB-476-A), so this entry would silently guard nothing. Update the deployment's rule to the current name.`
51
- : `tool policy ${kind}-list entry "${n}" carries the "__" namespace separator but no protocol prefix, and matches nothing in this run's roster — protocol tools are named ${NAMESPACED_NAME_SHAPES}, and legacy-name normalization was removed (RB-476-A), so this entry would silently guard nothing. Prefix the entry with the owning protocol's marker.`);
51
+ const entry = `tool policy ${kind}-list entry "${n}"`;
52
+ let message;
53
+ switch (verdict.kind) {
54
+ case "retired":
55
+ message = `${entry} is a RETIRED tool name (${verdict.guidance}) and matches nothing in this run's roster — legacy-name normalization was removed (RB-476-A), so this entry would silently guard nothing. Update the deployment's rule to the current name.`;
56
+ break;
57
+ case "unprefixed_namespace":
58
+ message = `${entry} carries the "__" namespace separator but no protocol prefix, and matches nothing in this run's roster — protocol tools are named ${NAMESPACED_NAME_SHAPES}, and legacy-name normalization was removed (RB-476-A), so this entry would silently guard nothing. Prefix the entry with the owning protocol's marker.`;
59
+ break;
60
+ case "unmintable_segment":
61
+ message = `${entry} can match no tool, ever (${verdict.guidance}), so it would silently guard nothing.${verdict.currentName !== undefined ? ` Write "${verdict.currentName}".` : ""}`;
62
+ break;
63
+ default: {
64
+ const exhaustive = verdict;
65
+ return exhaustive;
66
+ }
67
+ }
68
+ const err = new Error(message);
52
69
  err.code = "config.legacy_tool_name";
53
70
  throw err;
54
71
  }
@@ -285,6 +302,7 @@ export async function preparePolicyChain(input) {
285
302
  return {};
286
303
  return { riskAxes: { ...(irreversible !== undefined ? { irreversible } : {}), ...(egress !== undefined ? { egress } : {}) } };
287
304
  };
305
+ const grantBindingOf = (call, args) => skillGrantBindingMembers(call, args, skillSpecs, SKILL_TOOL_NAME);
288
306
  const inheritedStationFacts = (call) => {
289
307
  const seat = seatMarksOf(call);
290
308
  return {
@@ -374,7 +392,7 @@ export async function preparePolicyChain(input) {
374
392
  }
375
393
  if (judged.kind === "deny")
376
394
  return vetoed(judged.result);
377
- const { ask: editAsk, fallback: editFallback, mintedHere: editMintedHere } = judged;
395
+ const { ask: editAsk } = judged;
378
396
  re = editAsk;
379
397
  const editArbitrated = arbitrateInherited(re, creq.toolCallId, judged);
380
398
  if (editArbitrated !== undefined) {
@@ -382,21 +400,22 @@ export async function preparePolicyChain(input) {
382
400
  carryPrecedingSettlement(settledBy, out);
383
401
  return out;
384
402
  }
385
- const rr = await resolveAsk({
403
+ const { resolved: rr, judged: settled } = await resolveInheritedAsk(judged, (j) => resolveAsk({
386
404
  toolName: creq.toolName,
387
405
  toolCallId: creq.toolCallId,
388
406
  args: editArgs,
389
- ...ruleOffersOf(creq, editArgs, ancestorFacts(re)),
390
- ...cardDisclosureOf(re, inheritedAskFallbackMessage(creq.toolName)),
407
+ ...ruleOffersOf(creq, editArgs, ancestorFacts(j.ask)),
408
+ ...cardDisclosureOf(j.ask, inheritedAskFallbackMessage(creq.toolName)),
391
409
  ...askSourceIdentity(),
392
410
  ...riskAxesOf(creq),
393
- ...(re.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
394
- ...askMandateMember(ancestorFacts(re)),
395
- ...inheritedAskCarry(judged, isLiveApproverSeat(onAskOf), ancestorTracker),
411
+ ...grantBindingOf(creq, editArgs),
412
+ ...(j.ask.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
413
+ ...askMandateMember(ancestorFacts(j.ask)),
414
+ ...inheritedAskCarry(j, isLiveApproverSeat(onAskOf), ancestorTracker),
396
415
  ruleEvidence: inheritedAskEvidence,
397
- }, onAskOf, csignal ?? abortController.signal, lateAskSettlementObserver({ toolName: creq.toolName, toolCallId: creq.toolCallId, sessionId, runId, ...(spec.taskId !== undefined ? { taskId: spec.taskId } : {}), onNotice: deps.onNotice, onError: deps.onError }));
416
+ }, onAskOf, csignal ?? abortController.signal, lateAskSettlementObserver({ toolName: creq.toolName, toolCallId: creq.toolCallId, sessionId, runId, ...(spec.taskId !== undefined ? { taskId: spec.taskId } : {}), onNotice: deps.onNotice, onError: deps.onError })), ancestorTracker, creq.toolName, inheritedStationFacts(creq));
398
417
  void settleReadRootGrant(rr.readRootGrant, undefined, { toolName: creq.toolName, toolCallId: creq.toolCallId, sessionId, runId, ...(spec.taskId !== undefined ? { taskId: spec.taskId } : {}), onNotice: deps.onNotice });
399
- settleDenialLimitFallback({ fallback: editFallback, mintedHere: editMintedHere, tracker: ancestorTracker, resolved: rr, headless: headlessDenyAtRecheck, stop: stopForDenialLimit, toolName: creq.toolName, toolCallId: creq.toolCallId });
418
+ settleDenialLimitFallback({ fallback: settled.fallback, mintedHere: settled.mintedHere, tracker: ancestorTracker, resolved: rr, headless: headlessDenyAtRecheck, stop: stopForDenialLimit, toolName: creq.toolName, toolCallId: creq.toolCallId });
400
419
  if (rr.action !== "allow")
401
420
  return rr;
402
421
  settledBy = rr;
@@ -451,7 +470,7 @@ export async function preparePolicyChain(input) {
451
470
  return judged.result;
452
471
  if (judged.kind === "deny")
453
472
  return judged.result;
454
- const { ask: inheritedAsk, fallback, mintedHere } = judged;
473
+ const { ask: inheritedAsk, fallback } = judged;
455
474
  if (fallback === undefined && sandboxAdmissionArmed && policyAskClassOf(pc.policy) === "sandbox_local" && !sandboxBoundaryCapable(creq) && judged.classification.row.sandboxAdmission) {
456
475
  recordAncestorSandboxAdmission(creq.toolCallId, creq.toolName);
457
476
  return { action: "allow", decisionReason: "sandbox" };
@@ -461,33 +480,34 @@ export async function preparePolicyChain(input) {
461
480
  return arbitrated;
462
481
  const presentedArgs = creq.args;
463
482
  const askT0 = now();
464
- const resolved = await resolveAsk({
483
+ const { resolved, judged: settled } = await resolveInheritedAsk(judged, (j) => resolveAsk({
465
484
  toolName: creq.toolName,
466
485
  toolCallId: creq.toolCallId,
467
486
  args: presentedArgs,
468
- ...ruleOffersOf(creq, presentedArgs, ancestorFacts(inheritedAsk.action === "ask" ? inheritedAsk : undefined)),
469
- ...cardDisclosureOf(inheritedAsk, inheritedAskFallbackMessage(creq.toolName)),
487
+ ...ruleOffersOf(creq, presentedArgs, ancestorFacts(j.ask.action === "ask" ? j.ask : undefined)),
488
+ ...cardDisclosureOf(j.ask, inheritedAskFallbackMessage(creq.toolName)),
470
489
  ...askSourceIdentity(),
471
490
  ...riskAxesOf(creq),
472
- ...(inheritedAsk.action === "ask" && inheritedAsk.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
473
- ...askMandateMember(ancestorFacts(inheritedAsk.action === "ask" ? inheritedAsk : undefined)),
474
- ...inheritedAskCarry(judged, isLiveApproverSeat(pc.onAsk), pc.autoMode?.denialTracking),
491
+ ...grantBindingOf(creq, presentedArgs),
492
+ ...(j.ask.action === "ask" && j.ask.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
493
+ ...askMandateMember(ancestorFacts(j.ask.action === "ask" ? j.ask : undefined)),
494
+ ...inheritedAskCarry(j, isLiveApproverSeat(pc.onAsk), pc.autoMode?.denialTracking),
475
495
  ruleEvidence: inheritedAskEvidence,
476
- }, pc.onAsk, csignal ?? abortController.signal, lateAskSettlementObserver({ toolName: creq.toolName, toolCallId: creq.toolCallId, sessionId, runId, ...(spec.taskId !== undefined ? { taskId: spec.taskId } : {}), onNotice: deps.onNotice, onError: deps.onError }));
496
+ }, pc.onAsk, csignal ?? abortController.signal, lateAskSettlementObserver({ toolName: creq.toolName, toolCallId: creq.toolCallId, sessionId, runId, ...(spec.taskId !== undefined ? { taskId: spec.taskId } : {}), onNotice: deps.onNotice, onError: deps.onError })), pc.autoMode?.denialTracking, creq.toolName, inheritedStationFacts(creq));
477
497
  void settleReadRootGrant(resolved.readRootGrant, undefined, { toolName: creq.toolName, toolCallId: creq.toolCallId, sessionId, runId, ...(spec.taskId !== undefined ? { taskId: spec.taskId } : {}), onNotice: deps.onNotice });
478
498
  const askWaitMs = Math.max(0, now() - askT0);
479
499
  if (resolved.action === "deny" && resolved.approverUnavailable === true) {
480
500
  if (markInheritedUnavailable(creq.toolCallId))
481
- return inheritedAsk;
501
+ return settled.ask;
482
502
  return markerChannelFullDeny(creq);
483
503
  }
484
- settleDenialLimitFallback({ fallback, mintedHere, tracker: pc.autoMode?.denialTracking, resolved, headless: headlessDenyAtFold, stop: stopForDenialLimit, toolName: creq.toolName, toolCallId: creq.toolCallId });
504
+ settleDenialLimitFallback({ fallback: settled.fallback, mintedHere: settled.mintedHere, tracker: pc.autoMode?.denialTracking, resolved, headless: headlessDenyAtFold, stop: stopForDenialLimit, toolName: creq.toolName, toolCallId: creq.toolCallId });
485
505
  if (resolved.action !== "allow")
486
506
  return resolved;
487
507
  if (resolved.updatedInput !== undefined) {
488
508
  return recheckApprovedEdit(pc.policy, pc.onAsk, creq, resolved.updatedInput, resolved, csignal, pc.autoMode);
489
509
  }
490
- recordInheritedAskGrant(creq.toolCallId, pc.onAsk, resolved.presentedInput, askWaitMs, resolved, askClassMembersOf(judged.classification).classes);
510
+ recordInheritedAskGrant(creq.toolCallId, pc.onAsk, resolved.presentedInput, askWaitMs, resolved, askClassMembersOf(settled.classification).classes);
491
511
  return { action: "allow", decisionReason: "mode" };
492
512
  },
493
513
  }
@@ -524,7 +544,7 @@ export async function preparePolicyChain(input) {
524
544
  return judged.result;
525
545
  if (judged.kind === "deny")
526
546
  return judged.result;
527
- const { ask: inheritedAsk, fallback, mintedHere } = judged;
547
+ const { ask: inheritedAsk, fallback } = judged;
528
548
  if (fallback === undefined && sandboxAdmissionArmed && policyAskClassOf(pc.policy) === "sandbox_local" && !sandboxBoundaryCapable(creq) && judged.classification.row.sandboxAdmission) {
529
549
  recordAncestorSandboxAdmission(creq.toolCallId, creq.toolName);
530
550
  return decision.updatedInput !== undefined ? { action: "allow", updatedInput: decision.updatedInput, decisionReason: "sandbox" } : { action: "allow", decisionReason: "sandbox" };
@@ -533,27 +553,28 @@ export async function preparePolicyChain(input) {
533
553
  if (arbitrated !== undefined)
534
554
  return arbitrated;
535
555
  const askT0 = now();
536
- const resolved = await resolveAsk({
556
+ const { resolved, judged: settled } = await resolveInheritedAsk(judged, (j) => resolveAsk({
537
557
  toolName: creq.toolName,
538
558
  toolCallId: creq.toolCallId,
539
559
  args: presentedArgs,
540
- ...ruleOffersOf(creq, presentedArgs, ancestorFacts(inheritedAsk.action === "ask" ? inheritedAsk : undefined)),
541
- ...cardDisclosureOf(inheritedAsk, inheritedAskFallbackMessage(creq.toolName)),
560
+ ...ruleOffersOf(creq, presentedArgs, ancestorFacts(j.ask.action === "ask" ? j.ask : undefined)),
561
+ ...cardDisclosureOf(j.ask, inheritedAskFallbackMessage(creq.toolName)),
542
562
  ...askSourceIdentity(),
543
563
  ...riskAxesOf(creq),
544
- ...(inheritedAsk.action === "ask" && inheritedAsk.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
545
- ...askMandateMember(ancestorFacts(inheritedAsk.action === "ask" ? inheritedAsk : undefined)),
546
- ...inheritedAskCarry(judged, isLiveApproverSeat(pc.onAsk), pc.autoMode?.denialTracking),
564
+ ...grantBindingOf(creq, presentedArgs),
565
+ ...(j.ask.action === "ask" && j.ask.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
566
+ ...askMandateMember(ancestorFacts(j.ask.action === "ask" ? j.ask : undefined)),
567
+ ...inheritedAskCarry(j, isLiveApproverSeat(pc.onAsk), pc.autoMode?.denialTracking),
547
568
  ruleEvidence: inheritedAskEvidence,
548
- }, pc.onAsk, csignal ?? abortController.signal, lateAskSettlementObserver({ toolName: creq.toolName, toolCallId: creq.toolCallId, sessionId, runId, ...(spec.taskId !== undefined ? { taskId: spec.taskId } : {}), onNotice: deps.onNotice, onError: deps.onError }));
569
+ }, pc.onAsk, csignal ?? abortController.signal, lateAskSettlementObserver({ toolName: creq.toolName, toolCallId: creq.toolCallId, sessionId, runId, ...(spec.taskId !== undefined ? { taskId: spec.taskId } : {}), onNotice: deps.onNotice, onError: deps.onError })), pc.autoMode?.denialTracking, creq.toolName, inheritedStationFacts(creq));
549
570
  void settleReadRootGrant(resolved.readRootGrant, undefined, { toolName: creq.toolName, toolCallId: creq.toolCallId, sessionId, runId, ...(spec.taskId !== undefined ? { taskId: spec.taskId } : {}), onNotice: deps.onNotice });
550
571
  const askWaitMs = Math.max(0, now() - askT0);
551
572
  if (resolved.action === "deny" && resolved.approverUnavailable === true) {
552
573
  if (markInheritedUnavailable(creq.toolCallId))
553
- return inheritedAsk;
574
+ return settled.ask;
554
575
  return markerChannelFullDeny(creq);
555
576
  }
556
- settleDenialLimitFallback({ fallback, mintedHere, tracker: pc.autoMode?.denialTracking, resolved, headless: headlessDenyAtFold, stop: stopForDenialLimit, toolName: creq.toolName, toolCallId: creq.toolCallId });
577
+ settleDenialLimitFallback({ fallback: settled.fallback, mintedHere: settled.mintedHere, tracker: pc.autoMode?.denialTracking, resolved, headless: headlessDenyAtFold, stop: stopForDenialLimit, toolName: creq.toolName, toolCallId: creq.toolCallId });
557
578
  if (resolved.action !== "allow")
558
579
  return resolved;
559
580
  if (resolved.updatedInput !== undefined) {
@@ -667,7 +688,7 @@ export async function preparePolicyChain(input) {
667
688
  return decision;
668
689
  })
669
690
  : foldedPolicy;
670
- return { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations };
691
+ return { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, grantBindingOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations };
671
692
  }
672
693
  const advisedPolicyNames = new WeakMap();
673
694
  const ADVISED_KEYS_CAP = 64;
@@ -11,6 +11,7 @@ import { deliverEngineNotice } from "../engine-notice.js";
11
11
  import { SKILL_CONTENT_MAX_CHARS, SKILL_TOOL_NAME, createSkillTool, normalizeSkills } from "./synthetic-tools.js";
12
12
  import { skillLoadReading } from "./skill-base-dir.js";
13
13
  import { RosterBuilder } from "../tool-roster.js";
14
+ import { mountedToolNames } from "../tool-name-aliases.js";
14
15
  import { asThrownError } from "../thrown-value.js";
15
16
  export async function prepareProjectContext(input) {
16
17
  const { deps, spec, internals, session, sessionId, hostTaskId, taskRootFinal, handsEnabled, delegation, seedContextFiles, memoryBlockFromEngine, skillGrants, allowedTools, allowedToolTables, roster, toolFaceSnapshot, onceLedger, memoryTools, memoryEngineSession, memorySearchToolsPlanned, memoryPairExcludedName, memoryPairOccupiedName, resume, skillListingBudget } = input;
@@ -88,7 +89,10 @@ export async function prepareProjectContext(input) {
88
89
  const frozenSkillGrants = readFrozenSkillGrants(resume?.seed.skillGrants);
89
90
  if (frozenSkillGrants === undefined)
90
91
  throw new Error("the resumed checkpoint's skill-grant section does not read as grant rows — refusing to seed the run without the refusals it carries (the resume screen refuses this row before the claim)");
91
- const inert = seedAllowEntryTables(allowedToolTables, { skillInert: seedSkillGrants(skillGrants, { skills: skillSpecs, userInvokedSkills: spec.userInvokedSkills, inherited: [...(internals?.inheritedSkillGrants ?? []), ...frozenSkillGrants] }), inherited: internals?.inheritedAllowedTools, request: allowedTools, deployment: deps.allowedTools });
92
+ const mounted = () => mountedToolNames(tools);
93
+ skillGrants.bindMountedNames(mounted);
94
+ skillGrants.bindSkills(skillSpecs, SKILL_TOOL_NAME);
95
+ const inert = seedAllowEntryTables(allowedToolTables, { skillInert: seedSkillGrants(skillGrants, { skills: skillSpecs, userInvokedSkills: spec.userInvokedSkills, inherited: [...(internals?.inheritedSkillGrants ?? []), ...frozenSkillGrants] }), inherited: internals?.inheritedAllowedTools, request: allowedTools, deployment: deps.allowedTools }, mounted());
92
96
  if (inert.length > 0)
93
97
  deliverEngineNotice(deps.onNotice, allowedToolsNotGrantedNotice(inert, sessionId));
94
98
  if (skillSpecs.length > 0) {
@@ -99,7 +103,7 @@ export async function prepareProjectContext(input) {
99
103
  }
100
104
  roster.mount(createSkillTool(skillSpecs, skillGrants), { source: "builtin", mountedBy: "optional" });
101
105
  }
102
- const skillSeatOf = skillSeatReader(skillSpecs);
106
+ const skillSeatOf = skillSeatReader(skillSpecs, mounted);
103
107
  const sharedMemoryProvider = deps.sharedMemoryStores;
104
108
  let sharedMemoryPairMounted = false;
105
109
  if (sharedMemoryProvider !== undefined) {
@@ -407,7 +407,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
407
407
  let readDenyAdditionsNormalized = [];
408
408
  let handsLessResolvedFace;
409
409
  let handsLessResolvedWriteFace;
410
- const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, permissionMode, commitModeSeats, endModeCeiling, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, ancestorSessionRulesRef, ancestorRulesNow, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, orgAdmissionCheckpointState, faceCheckpointSection, faceCheckpointState, writeFaceCheckpointSection, skillGrantCheckpointSection, f012CheckpointState, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, frozenOnQuestion, parentSpecSeat, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, carrierWriteFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, checkpointSeat, toolFaceSnapshot, mountsCallerTool, promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, requestAllowedTools: allowedToolTables.request, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, hooks: () => hooks, preToolUseObservational: () => preToolUseObservational, hookTimeoutMs: () => hookTimeoutMs, hookEnvFace: () => hookEnvFace, autoModeDecider: () => autoModeDeciderRef.current, autoModeDenialTracking: () => autoModeDenialTrackingRef.current, autoModeArming: () => autoModeArmingRef.current, agentForkDenial: () => agentForkDenial, observersActive: () => observersActive, resolvedReadFace: () => resolvedReadFace, resolvedWriteFace: () => resolvedWriteFace, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized, handsLessResolvedFace: () => handsLessResolvedFace, handsLessResolvedWriteFace: () => handsLessResolvedWriteFace, centerAdoption: () => centerAdoptionRef.current, memoryEngineSession: () => memoryEngineSession });
410
+ const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, permissionMode, commitModeSeats, endModeCeiling, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, ancestorSessionRulesRef, ancestorRulesNow, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, orgAdmissionCheckpointState, faceCheckpointSection, faceCheckpointState, writeFaceCheckpointSection, skillGrantCheckpointSection, f012CheckpointState, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, frozenOnQuestion, parentSpecSeat, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, carrierWriteFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, askSeat: doors.askSeat, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, checkpointSeat, toolFaceSnapshot, mountsCallerTool, promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, requestAllowedTools: allowedToolTables.request, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, hooks: () => hooks, preToolUseObservational: () => preToolUseObservational, hookTimeoutMs: () => hookTimeoutMs, hookEnvFace: () => hookEnvFace, autoModeDecider: () => autoModeDeciderRef.current, autoModeDenialTracking: () => autoModeDenialTrackingRef.current, autoModeArming: () => autoModeArmingRef.current, agentForkDenial: () => agentForkDenial, observersActive: () => observersActive, resolvedReadFace: () => resolvedReadFace, resolvedWriteFace: () => resolvedWriteFace, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized, handsLessResolvedFace: () => handsLessResolvedFace, handsLessResolvedWriteFace: () => handsLessResolvedWriteFace, centerAdoption: () => centerAdoptionRef.current, memoryEngineSession: () => memoryEngineSession });
411
411
  bindPermissionModeSeat(permissionMode);
412
412
  const announceRuleStoreSkipped = ruleStoreUnreadableNotice(deps.onNotice, { sessionId, runId });
413
413
  const persistedPathRowsRead = persistedPathRowsOfTask({ deps, principal: spec.principal, sessionId, root: taskRootFinal, home: executionEnv.homeDir, taskId: hostTaskId, handsEnabled, signals: [abortController.signal, ...(spec.signal !== undefined ? [spec.signal] : [])], onUnread: announceRuleStoreSkipped });
@@ -415,7 +415,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
415
415
  const effectivePathDenyRules = [...toolPolicyPathDenyRules([lockedPreflight.toolPolicy, ...(inheritedParentConstraints ?? []).map((c) => c.policy)]), ...persistedPathRows.denyRows];
416
416
  const writeProtectionJudgeRef = {};
417
417
  const writeGuards = { protection: () => writeProtectionJudgeRef.current, target: toolPolicyWriteTargetGuard([lockedPreflight.toolPolicy, ...(inheritedParentConstraints ?? []).map((c) => c.policy)]) };
418
- const { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDeciderRef, autoModeDenialTrackingRef, autoModeArmingRef, armAutoMode, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline } = await prepareCapsAndWorkflow({ spec, deps, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, checkpointSeat, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, frozenOnAsk, parentSpecSeat, carrierReadFace, carrierWriteFace, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries: () => ({ entries: readDenyMatcher?.entries ?? [], ruleRows: effectivePathDenyRules }), peerLaneActive, peerSendMessageBuiltIn, runnerSelf, memoryEngineSession: () => memoryEngineSession, centerAdoption: () => centerAdoptionRef.current, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized });
418
+ const { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDeciderRef, autoModeDenialTrackingRef, autoModeArmingRef, armAutoMode, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline } = await prepareCapsAndWorkflow({ spec, deps, askSeat: doors.askSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, checkpointSeat, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, parentSpecSeat, carrierReadFace, carrierWriteFace, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries: () => ({ entries: readDenyMatcher?.entries ?? [], ruleRows: effectivePathDenyRules }), peerLaneActive, peerSendMessageBuiltIn, runnerSelf, memoryEngineSession: () => memoryEngineSession, centerAdoption: () => centerAdoptionRef.current, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized });
419
419
  const tools = roster.tools;
420
420
  const pausedRef = {};
421
421
  const undeliveredContinuationRef = { current: { parkedSteers: [], orphanTasks: [] } };
@@ -733,8 +733,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
733
733
  releaseSignal = () => sig.removeEventListener("abort", onExternalAbort);
734
734
  }
735
735
  }
736
- const { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, announceRuleStoreSkipped, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider: () => autoModeDeciderRef.current, permissionMode, scratchpadDir: spec.envFacts?.scratchpadDir, toolRosterDeltas: rosterSeat, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
737
- const { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtection, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound } = prepareWiringManifest({ spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, shellReadStationArmed: handsReadFace.shellReadStationArmed, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined, fileHistoryFact, sessionBox });
736
+ const { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, grantBindingOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, announceRuleStoreSkipped, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider: () => autoModeDeciderRef.current, permissionMode, scratchpadDir: spec.envFacts?.scratchpadDir, toolRosterDeltas: rosterSeat, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
737
+ const { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtection, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound } = prepareWiringManifest({ spec, deps, askSeat: doors.askSeat, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, shellReadStationArmed: handsReadFace.shellReadStationArmed, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, harness, pausedRef, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined, fileHistoryFact, sessionBox });
738
738
  const writeProtectionCheck = writeProtection?.check;
739
739
  writeProtectionJudgeRef.current = writeProtection?.judgeTarget;
740
740
  if (fileHistoryBoundary !== undefined) {
@@ -743,10 +743,10 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
743
743
  return undefined;
744
744
  });
745
745
  }
746
- const { askLane } = prepareAskLane({ gateMachineryActive, abortController, effectivePolicy, budgetSnapshot, handsCwdRef, advertisedWritableDirs, tools, inheritedUnavailableAsks, inheritedAskGrants, onAsk, humanReviewRef, now, ruleOffersOf, askSourceIdentity, riskAxesOf, autoModeDenialTracking: autoModeDenialTrackingRef, spec, deps, sessionId, runId, hooks, hookTimeoutMs, notifyOwnHookCrash, grantReadRoot: handsReadFace.grantReadRoot });
746
+ const { askLane } = prepareAskLane({ gateMachineryActive, abortController, effectivePolicy, budgetSnapshot, handsCwdRef, advertisedWritableDirs, tools, inheritedUnavailableAsks, inheritedAskGrants, onAsk, humanReviewRef, now, ruleOffersOf, grantBindingOf, askSourceIdentity, riskAxesOf, autoModeDenialTracking: autoModeDenialTrackingRef, spec, deps, sessionId, runId, hooks, hookTimeoutMs, notifyOwnHookCrash, grantReadRoot: handsReadFace.grantReadRoot });
747
747
  const { saga } = prepareSuspendSaga({ gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
748
748
  const { suspendForResource, suspendForPlatformLimit, suspendForReview } = prepareBoundaryParks({ saga, spec, checkpointStore, abortController, harness, session, sessions, sessionId, deps, priorLedger, maxSlices, maxSuspends, resourceTotal, priorSuspendCount, suspendChainBase, humanReviewRef, liveSpendRef, now, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, pausedRef, remoteEnvFailures, resourceSuspendEligible, durableSuspendInfraReady, incompleteSuspendAdapter });
749
- const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, irreversibilityTier, toolMarkSources, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, skillSpecs, now, humanReviewRef, abortController, harness, pausedRef });
749
+ const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, irreversibilityTier, toolMarkSources, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, grantBindingOf, now, humanReviewRef, abortController, harness, pausedRef });
750
750
  const seatInputsFor = skillGateWiring({ tools, skillToolName: SKILL_TOOL_NAME, seatOf: skillSeatOf, mode: () => permissionMode.current, lane: skillGrantLane, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.skill_allowed", version: 1, taskId: hostTaskId, ...info, entries: [...info.entries], ts: Date.now() })), allowEntries: { deploymentAllows: { ...allowEntryLanes.deployment, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.allowed_tools_allowed", version: 1, taskId: hostTaskId, source: "deployment", ...info, entries: [...info.entries], ts: Date.now() })) }, requestAllows: { ...allowEntryLanes.request, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.allowed_tools_allowed", version: 1, taskId: hostTaskId, source: "request", ...info, entries: [...info.entries], ts: Date.now() })) } } });
751
751
  const { approvedCallScreen } = prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, gateOutcomes, batchHaltRef, blockedTracked, hookIdentity, reminderMark, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, readDenyInForce: () => ({ tiers: handsReadFace.readDenyBuiltinTiersActive, rows: [...readDenyAdditionsNormalized.map((e) => e.pattern), ...handsReadFaceInput.pathDenyRules.filter((r) => r.faces.includes("read")).map((r) => r.rule)] }), hookEnvFace, writeProtectionCheck, shellReadCheck, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider: autoModeDeciderRef, autoModeDenialTracking: autoModeDenialTrackingRef, askRoute: { ...wiringManifest.ask, effective: askSeatEffective(wiringManifest) }, permissionMode, toolMarkSources, ...(deps.a2a?.isolatePeers === true ? { a2aIsolatePeers: true } : {}), ancestorArbitrations, runId, stopForDenialLimit, permissionRuleLane, seatInputsFor, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash, frameSettlement });
752
752
  const postureFrameRef = { report: (err) => deps.onError?.(err, { phase: "degraded", sessionId }) };
@@ -36,12 +36,12 @@ import { type AutoModeArmFact, type WiringManifest, type WiringManifestMcpEntry
36
36
  import { type PermissionModeController } from "../mode-policy.js";
37
37
  import type { AnnounceOnceSink, Prepared, PrepareResume, RunInternals, UsageGovernance } from "./contracts.js";
38
38
  export interface PrepareWiringManifestInput {
39
- /** borrowed-readonly — the REBOUND spec. Read: `onAsk` (the own seat), `onQuestion` (the question seam), `handsReadOnly` / `tools` (the ungated scan),
39
+ /** borrowed-readonly — the REBOUND spec. Read: `onQuestion` (the question seam), `handsReadOnly` / `tools` (the ungated scan),
40
40
  * `resourceSuspend` (the task-axis lane), `durableApproval` / `principal` (the synthesis and the notice), `interactiveTools` /
41
41
  * `mcp` / `checkpointStore` (manifest cells and the notice's cause), `enablePlanMode` (the gate-machinery predicate's
42
42
  * plan-mode term). Never mutated. */
43
- spec: Pick<TaskSpec, "onAsk" | "onQuestion" | "handsReadOnly" | "tools" | "resourceSuspend" | "durableApproval" | "principal" | "interactiveTools" | "mcp" | "checkpointStore" | "enablePlanMode" | "hooks" | "peerPresence">;
44
- /** borrowed-readonly — the deployment seats, whole: `onAsk` (the seat's deps half), `onError` (the warning), `executionEnv`
43
+ spec: Pick<TaskSpec, "onQuestion" | "handsReadOnly" | "tools" | "resourceSuspend" | "durableApproval" | "principal" | "interactiveTools" | "mcp" | "checkpointStore" | "enablePlanMode" | "hooks" | "peerPresence">;
44
+ /** borrowed-readonly — the deployment seats, whole: `onError` (the warning), `executionEnv`
45
45
  * (the hook-env predicate), `checkpointStore` (durable infra), the manifest's dozen wiring facts (`backgroundAgentStore`,
46
46
  * `permissionRuleStore`, `permissionRuleSyncWired`, `onBackgroundChildEvent`, `lockedConfig`, `compliancePostureResolver`,
47
47
  * `memoryScopeAdmission`, `retentionPolicy`, `onElicit`), `onNotice`, the write-protection judge's compile seats
@@ -141,8 +141,9 @@ export interface PrepareWiringManifestInput {
141
141
  harness: AgentHarness;
142
142
  /** borrowed-readonly — the durable-suspend holder; the drain's parked predicate reads `token` at run time. Not written here. */
143
143
  pausedRef: Prepared["pausedRef"];
144
- /** borrowed-readonly — the FROZEN approver seat (the notice's liveApprover fact). */
145
- frozenOnAsk: OnAsk | undefined;
144
+ /** borrowed-readonly — the run's approval seat as the config doors froze it: the gate's approver and the notice's facts (its
145
+ * value), the manifest's ask cell (its form and provenance). */
146
+ askSeat: import("../wiring-manifest.js").AskSeat;
146
147
  /** borrowed-readonly — the LIVE half of the inherited chain (the notice reads its content mandates). */
147
148
  liveInheritedGate: RunInternals["inheritedGate"];
148
149
  /** borrowed-readonly — the effective delegation facts (the identity's isDelegatedChild). */