@sema-agent/core 7.21.1 → 7.22.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 (79) hide show
  1. package/CHANGELOG.md +123 -1
  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 +2 -1
  5. package/dist/core/ask-origin.d.ts +1 -0
  6. package/dist/core/ask-origin.js +3 -2
  7. package/dist/core/auto-mode-rebuild.js +6 -2
  8. package/dist/core/auto-mode.d.ts +40 -18
  9. package/dist/core/auto-mode.js +63 -45
  10. package/dist/core/checkpoint-store.d.ts +8 -8
  11. package/dist/core/engine-notice.d.ts +49 -1
  12. package/dist/core/engine-notice.js +14 -1
  13. package/dist/core/governance-codes.d.ts +1 -1
  14. package/dist/core/governance-codes.js +4 -0
  15. package/dist/core/mcp.d.ts +65 -0
  16. package/dist/core/mcp.js +190 -41
  17. package/dist/core/memory-engine/consolidation.d.ts +5 -0
  18. package/dist/core/memory-engine/consolidation.js +7 -3
  19. package/dist/core/memory-engine/engine.d.ts +8 -0
  20. package/dist/core/memory-engine/engine.js +25 -19
  21. package/dist/core/memory-engine/layout.d.ts +47 -9
  22. package/dist/core/memory-engine/layout.js +157 -57
  23. package/dist/core/memory-engine/session-incarnation.d.ts +27 -0
  24. package/dist/core/memory-engine/session-incarnation.js +63 -0
  25. package/dist/core/parent-spec-seat.d.ts +15 -3
  26. package/dist/core/parent-spec-seat.js +5 -0
  27. package/dist/core/permission-rule-model.d.ts +1 -2
  28. package/dist/core/retention.d.ts +8 -1
  29. package/dist/core/retention.js +2 -0
  30. package/dist/core/runner/classifier-ladder.js +1 -0
  31. package/dist/core/runner/contracts.d.ts +11 -0
  32. package/dist/core/runner/mcp-redial.d.ts +109 -0
  33. package/dist/core/runner/mcp-redial.js +60 -0
  34. package/dist/core/runner/memory-consolidation-driver.d.ts +2 -0
  35. package/dist/core/runner/prepare-caps-and-workflow.js +9 -12
  36. package/dist/core/runner/prepare-hands-readface.d.ts +3 -0
  37. package/dist/core/runner/prepare-hands-readface.js +13 -3
  38. package/dist/core/runner/prepare-memory.js +3 -3
  39. package/dist/core/runner/prepare-protocol-tools.d.ts +6 -1
  40. package/dist/core/runner/prepare-protocol-tools.js +20 -38
  41. package/dist/core/runner/prepare-task.js +3 -3
  42. package/dist/core/runner/prepare-wiring-manifest.d.ts +4 -0
  43. package/dist/core/runner/prepare-wiring-manifest.js +2 -1
  44. package/dist/core/runner/run-identity-wiring.d.ts +3 -1
  45. package/dist/core/runner/run-identity-wiring.js +4 -1
  46. package/dist/core/runner/run-settle-and-teardown.d.ts +3 -1
  47. package/dist/core/runner/run-settle-and-teardown.js +6 -2
  48. package/dist/core/runner/run-terminal-adoption.d.ts +4 -1
  49. package/dist/core/runner/run-terminal-adoption.js +2 -6
  50. package/dist/core/runner/runtask.js +8 -5
  51. package/dist/core/runner/stream-lifecycle-verbs.d.ts +5 -1
  52. package/dist/core/runner/stream-lifecycle-verbs.js +23 -2
  53. package/dist/core/runner-deps.d.ts +16 -7
  54. package/dist/core/skill-listing-budget.d.ts +5 -4
  55. package/dist/core/task-result.d.ts +3 -2
  56. package/dist/core/task-spec.d.ts +2 -1
  57. package/dist/core/task-stream.d.ts +26 -0
  58. package/dist/core/tool-spec.d.ts +5 -1
  59. package/dist/core/trace.d.ts +5 -0
  60. package/dist/core/types.d.ts +2 -2
  61. package/dist/core/types.js +1 -1
  62. package/dist/core/wiring-manifest.d.ts +23 -0
  63. package/dist/core/wiring-manifest.js +3 -0
  64. package/dist/index.d.ts +4 -3
  65. package/dist/index.js +2 -2
  66. package/dist/orchestration/workflow-governance.js +1 -1
  67. package/dist/orchestration/workflow-primitives.d.ts +2 -2
  68. package/dist/tools/fs/bash-program-position.d.ts +26 -5
  69. package/dist/tools/fs/bash-program-position.js +63 -16
  70. package/dist/tools/fs/bash-readonly-classifier.d.ts +27 -17
  71. package/dist/tools/fs/bash-readonly-classifier.js +134 -55
  72. package/dist/tools/fs/fs-bash.js +43 -18
  73. package/dist/tools/fs/index.d.ts +4 -2
  74. package/dist/tools/fs/read-deny.d.ts +25 -11
  75. package/dist/tools/fs/read-deny.js +5 -1
  76. package/dist/tools/fs/safety.d.ts +1 -4
  77. package/package.json +1 -1
  78. package/test/export-surface.snapshot.json +9 -1
  79. package/wire-changes/core@7.22.0.json +637 -0
@@ -9,7 +9,7 @@ import { hasDestroy, isIsolated } from "../remote-env.js";
9
9
  import { resolveTaskModel } from "../roles.js";
10
10
  import { defaultTaskRegistry } from "../task-registry.js";
11
11
  import { emitTrace } from "../trace.js";
12
- import { deliverEngineNotice } from "../types.js";
12
+ import { deliverEngineNotice, settleOwedUserInput } from "../types.js";
13
13
  import { assembleResult } from "./assemble-result.js";
14
14
  import { discloseUnconsumedHalt } from "./halt-attribution.js";
15
15
  import { forwardSafely } from "./forward-sink.js";
@@ -21,7 +21,7 @@ import { settleTeardownLeg } from "./teardown-bounded.js";
21
21
  import { autoRunConsolidationFromRecommendation, autoRunOnRecommendationEffective, scopeHasUnconsumedRecommendation } from "./memory-consolidation-driver.js";
22
22
  import { amendTerminal, terminalProjection } from "./terminal-projection.js";
23
23
  export async function runSettleAndTeardown(input) {
24
- const { spec, queue, prepared, resume, internals, rs, stats, ident, parentToolCallId, subagentName, loopLatch, timeout, ownCommittedTailRef, emitDelegationLifecycle, taskIdRef, manualCompactRef, drainManualCompact, final, threw, abortedLive, userInterruptedLive, answerSettled, strandedHumanAnswers, reasoningResolution, comp, setResult, onSuggestions, onSuspend, runner, sessions } = input;
24
+ const { spec, queue, prepared, resume, internals, rs, stats, ident, parentToolCallId, subagentName, loopLatch, timeout, ownCommittedTailRef, emitDelegationLifecycle, taskIdRef, manualCompactRef, drainManualCompact, final, threw, abortedLive, userInterruptedLive, answerSettled, strandedHumanAnswers, reasoningResolution, comp, owedUserInput, setResult, onSuggestions, onSuspend, runner, sessions } = input;
25
25
  try {
26
26
  if (comp?.compacted) {
27
27
  queue.push({
@@ -141,6 +141,7 @@ export async function runSettleAndTeardown(input) {
141
141
  });
142
142
  }
143
143
  discloseUnconsumedHalt({ accepted: loopLatch.userHalted, consumption: prepared.harness.haltConsumption(), onNotice: runner.deps.onNotice, sessionId: prepared.sessionId, runId: rs.telemetry.runId, taskId: spec.taskId });
144
+ let rowReturned = false;
144
145
  if (resume !== undefined &&
145
146
  resume.pendingActionStarted !== true &&
146
147
  result.terminal.kind !== "completed" &&
@@ -149,12 +150,14 @@ export async function runSettleAndTeardown(input) {
149
150
  resume.onEnvRestoreFailed !== undefined) {
150
151
  try {
151
152
  await resume.onEnvRestoreFailed("env_failed");
153
+ rowReturned = true;
152
154
  amendTerminal(result, "resume.reopened_unstarted", (m) => `${m ?? "the resume leg did not complete"} — the approved action never started, so the checkpoint was REOPENED (pending): the same approval can be resumed again, do not ask for a fresh one`);
153
155
  }
154
156
  catch {
155
157
  amendTerminal(result, "resume.reopen_failed_unstarted", (m) => `${m ?? "the resume leg did not complete"} — the approved action never started, and reopening the checkpoint FAILED: its state is unprovable from here. Re-read it before deciding; do NOT issue a fresh approval on the assumption the old one is dead`);
156
158
  }
157
159
  }
160
+ settleOwedUserInput(owedUserInput, rowReturned, { taskId: spec.taskId ?? prepared.sessionId, sessionId: prepared.sessionId, runId: prepared.runId }, runner.deps.onNotice);
158
161
  prepared.sealReadStateSeat?.(ownCommittedTailRef.current);
159
162
  {
160
163
  const wss = prepared.workspaceStateSettle;
@@ -299,6 +302,7 @@ export async function runSettleAndTeardown(input) {
299
302
  }
300
303
  }
301
304
  finally {
305
+ settleOwedUserInput(owedUserInput, !prepared.suspendProgressRef.executedApproved, { taskId: spec.taskId ?? prepared.sessionId, sessionId: prepared.sessionId, runId: prepared.runId }, runner.deps.onNotice);
302
306
  const ownedEnvDying = prepared.ownedEnv !== undefined &&
303
307
  hasDestroy(prepared.ownedEnv) &&
304
308
  isIsolated(prepared.ownedEnv) &&
@@ -19,7 +19,7 @@ import type { Model } from "../../internal/llm.js";
19
19
  import { type MaybeCompactOptions } from "../auto-compaction.js";
20
20
  import type { SessionStore } from "../session.js";
21
21
  import type { PushQueue } from "../push-queue.js";
22
- import { type Brain, type TaskEvent, type TaskSpec } from "../types.js";
22
+ import type { Brain, OwedUserInputAccount, TaskEvent, TaskSpec } from "../types.js";
23
23
  import { type Stats } from "./assemble-result.js";
24
24
  import type { EndOfTaskCompaction, Prepared, RunnerDepsSeat, RunState } from "./contracts.js";
25
25
  export interface RunTerminalAdoptionInput<R> {
@@ -95,5 +95,8 @@ export interface RunTerminalAdoptionResult {
95
95
  /** This lane's ONE evaluation of {@link answerSettled}: a clean `"stop"` final with no queued continuation lost. The
96
96
  * settle lane hands it to the arbitration (`ResultFlags.answerSettled`), the teardown attribution and the notice. */
97
97
  answerSettled: boolean;
98
+ /** The undrained-input account, UNSETTLED: this lane knows every fact but one — whether this leg's consumed
99
+ * checkpoint row comes back — and that one is the next lane's compensation to perform, not to predict. */
100
+ owedUserInput: OwedUserInputAccount;
98
101
  }
99
102
  export declare function runTerminalAdoption<R>(input: RunTerminalAdoptionInput<R>): Promise<R>;
@@ -3,7 +3,6 @@ import { DEFAULT_COMPACTION_SETTINGS } from "../../internal/harness.js";
3
3
  import { eventDefaultOn } from "../../prompt-assembly/event-registry.js";
4
4
  import { appendInterruptionMarker, reconcileInterruptedSession } from "../session-reconcile.js";
5
5
  import { emitTrace } from "../trace.js";
6
- import { deliverEngineNotice, owedUserInputCounts, undrainedUserInputNotices } from "../types.js";
7
6
  import { answerSettled, errorCodeOf } from "./assemble-result.js";
8
7
  import { awaitChargeWithSlowDisclosure, discloseUnevaluableWindow } from "./clock-and-limits.js";
9
8
  import { buildWorkingFileAttachments, centerAdoptionOption, contextInstructionFilesOption, emitInputTruncated, forkContextOption } from "./compaction-call-options.js";
@@ -109,10 +108,7 @@ export async function runTerminalAdoption(input) {
109
108
  }
110
109
  migratedParked = prepared.harness.dropParkedUserInputs(carried);
111
110
  }
112
- const owed = owedUserInputCounts(undrainedUserAtEnd.current, migratedParked, { frames: prepared.undeliveredContinuationRef.current.parkedSteers, carried: carriedContinuation, rowMayReturn: committedPause === undefined && !prepared.suspendProgressRef.executedApproved });
113
- for (const notice of undrainedUserInputNotices(owed, spec.taskId ?? prepared.sessionId, prepared.sessionId, prepared.runId)) {
114
- deliverEngineNotice(runner.deps.onNotice, notice);
115
- }
111
+ const owedUserInput = { held: undrainedUserAtEnd.current, migrated: migratedParked, continuation: { frames: prepared.undeliveredContinuationRef.current.parkedSteers, carried: carriedContinuation } };
116
112
  if (rs.attach.attachState?.postCompactPending === true && (rs.attach.attachmentsCfg?.backgroundTasks ?? eventDefaultOn("background_tasks")) === true) {
117
113
  emitTrace(rs.telemetry.tracer, () => ({ kind: "compaction.announce_dropped", version: 1, taskId: rs.telemetry.taskId, ts: Date.now() }));
118
114
  }
@@ -125,7 +121,7 @@ export async function runTerminalAdoption(input) {
125
121
  onCompactionFailed: (reason) => queue.push({ type: "compaction_outcome", outcome: "failed", trigger: "auto", reason, ...ident() }),
126
122
  cancelled: abortedLive,
127
123
  }, runner, sessions);
128
- return await next({ threw, comp, answerSettled: settled });
124
+ return await next({ threw, comp, answerSettled: settled, owedUserInput });
129
125
  }
130
126
  async function finish(spec, prepared, opts, runner, sessions) {
131
127
  let comp;
@@ -296,6 +296,7 @@ export class Runner {
296
296
  const acceptedSteerInputs = new Map();
297
297
  const notifyRef = {};
298
298
  const captureOptOutRef = {};
299
+ const mcpRedialRef = {};
299
300
  const manualCompactRef = { requested: false, waiters: [] };
300
301
  const drainManualCompactWaiters = (outcome) => {
301
302
  manualCompactRef.requested = false;
@@ -348,6 +349,7 @@ export class Runner {
348
349
  internals: { ...(internals ?? {}), detachHub, forwardScope: createForwardSinkScope(this.deps.onNotice) },
349
350
  notifyRef,
350
351
  captureOptOutRef,
352
+ mcpRedialRef,
351
353
  entryActor,
352
354
  entryTracer,
353
355
  });
@@ -383,7 +385,7 @@ export class Runner {
383
385
  locallyClaimedTokens: this.locallyClaimedTokens, parentConstraintRegistry: this.parentConstraintRegistry, suspendedEnvReaps: this.suspendedEnvReaps,
384
386
  });
385
387
  const { steer } = streamSteerVerb({ spec, internals, queue, acceptedSteerInputs, live, ready, orTimeout, readyTimeoutMs: READY_TIMEOUT_MS, steeringError, runner: this.depsSeat });
386
- const { notify, optOutMemoryCapture, compact, detach, interrupt } = streamLifecycleVerbs({ live, ready, orTimeout, steeringError, notifyRef, captureOptOutRef, manualCompactRef, detachHub });
388
+ const { notify, optOutMemoryCapture, reconnectMcpServer, compact, detach, interrupt } = streamLifecycleVerbs({ live, ready, orTimeout, steeringError, notifyRef, captureOptOutRef, mcpRedialRef, manualCompactRef, detachHub });
387
389
  const { halt, destroy } = streamHaltVerbs({ spec, live, ready, orTimeout, readyTimeoutMs: READY_TIMEOUT_MS, run, reapSuspended, runner: this.depsSeat });
388
390
  return {
389
391
  [Symbol.asyncIterator]: () => queue[Symbol.asyncIterator](),
@@ -398,6 +400,7 @@ export class Runner {
398
400
  steer,
399
401
  notify,
400
402
  optOutMemoryCapture,
403
+ reconnectMcpServer,
401
404
  compact,
402
405
  detach,
403
406
  interrupt,
@@ -406,14 +409,14 @@ export class Runner {
406
409
  };
407
410
  }
408
411
  runLocked(input) {
409
- const { spec, queue, setResult, onSuggestions, onReady, onSuspend, manualCompactRef, taskIdRef, resume, internals, notifyRef, captureOptOutRef, entryActor, entryTracer } = input;
412
+ const { spec, queue, setResult, onSuggestions, onReady, onSuspend, manualCompactRef, taskIdRef, resume, internals, notifyRef, captureOptOutRef, mcpRedialRef, entryActor, entryTracer } = input;
410
413
  return runNotificationLane({
411
414
  spec, queue, resume, internals, taskIdRef,
412
415
  runner: this.depsSeat, self: this, sessions: this.sessions, sessionReadStates: this.sessionReadStates, pendingSessionNotifications: this.pendingSessionNotifications,
413
416
  prepareTask,
414
417
  next: ({ prepared, injectTaskNotification, deliveredAtTurnOpen, peerInboundChainRef, modelCatalog, notificationLane, unsubscribeTaskNotifications }) => {
415
418
  const { runSourceTaskId, parentToolCallId, ident, emitDelegationLifecycle, loopLatch, stats, undrainedUserAtEnd, userInputLostAtEnd } = runIdentityWiring({
416
- spec, queue, prepared, internals, taskIdRef, onReady, manualCompactRef, notifyRef, captureOptOutRef, injectTaskNotification, deliveredAtTurnOpen, peerInboundChainRef,
419
+ spec, queue, prepared, internals, taskIdRef, onReady, manualCompactRef, notifyRef, captureOptOutRef, mcpRedialRef, injectTaskNotification, deliveredAtTurnOpen, peerInboundChainRef,
417
420
  notificationLane, pendingSessionNotifications: this.pendingSessionNotifications, runner: this.depsSeat,
418
421
  });
419
422
  const rs = createRunState();
@@ -472,9 +475,9 @@ export class Runner {
472
475
  next: ({ final, threw, abortedLive, userInterruptedLive, strandedHumanAnswers }) => runTerminalAdoption({
473
476
  spec, queue, prepared, rs, stats, ident, emitCommitted, startedToolCallIds, toolLabels, timeout, compactionBrain, compactionBreaker, windowSafetyOptions,
474
477
  undrainedUserAtEnd, userInputLostAtEnd, final, threw, abortedLive, userInterruptedLive, runner: this.depsSeat, sessions: this.sessions,
475
- next: ({ threw, comp, answerSettled }) => runSettleAndTeardown({
478
+ next: ({ threw, comp, answerSettled, owedUserInput }) => runSettleAndTeardown({
476
479
  spec, queue, prepared, resume, internals, rs, stats, ident, parentToolCallId, subagentName, loopLatch, timeout, ownCommittedTailRef,
477
- emitDelegationLifecycle, taskIdRef, manualCompactRef, drainManualCompact, final, threw, abortedLive, userInterruptedLive, answerSettled, strandedHumanAnswers, reasoningResolution, comp,
480
+ emitDelegationLifecycle, taskIdRef, manualCompactRef, drainManualCompact, final, threw, abortedLive, userInterruptedLive, answerSettled, strandedHumanAnswers, reasoningResolution, comp, owedUserInput,
478
481
  setResult, onSuggestions, onSuspend, runner: this.depsSeat, sessions: this.sessions,
479
482
  }),
480
483
  }),
@@ -1,6 +1,6 @@
1
1
  import type { ToolDetachHub } from "../tool-detach.js";
2
2
  import type { TaskStream } from "../types.js";
3
- import type { CaptureOptOutRef, LiveHandle, ManualCompactRef, NotifyRef, TaskStreamLiveSeat } from "./contracts.js";
3
+ import type { CaptureOptOutRef, LiveHandle, ManualCompactRef, McpRedialRef, NotifyRef, TaskStreamLiveSeat } from "./contracts.js";
4
4
  export interface StreamLifecycleVerbsInput {
5
5
  /** borrowed-readonly — the stream's live state: `resultValue` (the finished-task refusals) and `handle`, read at each call. */
6
6
  live: TaskStreamLiveSeat;
@@ -14,6 +14,8 @@ export interface StreamLifecycleVerbsInput {
14
14
  notifyRef: NotifyRef;
15
15
  /** borrowed-readonly — the capture opt-out bridge; `flip` is bound by the run body when a memory session mounted. */
16
16
  captureOptOutRef: CaptureOptOutRef;
17
+ /** borrowed-readonly — the MCP re-dial bridge; `redial` is bound by the run body when the leg declared MCP servers. */
18
+ mcpRedialRef: McpRedialRef;
17
19
  /** borrowed-mutable — the manual-compaction request seat: the compact verb arms it and parks its waiter here. */
18
20
  manualCompactRef: ManualCompactRef;
19
21
  /** borrowed-readonly — the run-local detach hub the detach verb requests through. */
@@ -24,6 +26,8 @@ export interface StreamLifecycleVerbsResult {
24
26
  notify: TaskStream["notify"];
25
27
  /** The stream's `optOutMemoryCapture` verb. */
26
28
  optOutMemoryCapture: TaskStream["optOutMemoryCapture"];
29
+ /** The stream's `reconnectMcpServer` verb. */
30
+ reconnectMcpServer: TaskStream["reconnectMcpServer"];
27
31
  /** The stream's `compact` verb. */
28
32
  compact: TaskStream["compact"];
29
33
  /** The stream's `detach` verb. */
@@ -1,6 +1,6 @@
1
1
  import { isSystemInjectionPriority, SYSTEM_INJECTION_PRIORITIES } from "../task-notification.js";
2
2
  export function streamLifecycleVerbs(input) {
3
- const { live, ready, orTimeout, steeringError, notifyRef, captureOptOutRef, manualCompactRef, detachHub } = input;
3
+ const { live, ready, orTimeout, steeringError, notifyRef, captureOptOutRef, mcpRedialRef, manualCompactRef, detachHub } = input;
4
4
  const notify = async (input, opts) => {
5
5
  const notifyError = (msg, code) => {
6
6
  const e = new Error(`cannot notify: ${msg}`);
@@ -69,6 +69,27 @@ export function streamLifecycleVerbs(input) {
69
69
  }
70
70
  return captureOptOutRef.flip(reason);
71
71
  };
72
+ const reconnectMcpServer = async (server) => {
73
+ const serverIn = server;
74
+ if (typeof serverIn !== "string" || serverIn.length === 0) {
75
+ const e = new Error(`cannot reconnect an MCP server: \`server\` must be a non-empty server name`);
76
+ e.code = "steering.invalid_content";
77
+ throw e;
78
+ }
79
+ if (live.resultValue)
80
+ throw steeringError("the task has already finished");
81
+ const h = live.handle ?? (await orTimeout(ready));
82
+ if (!h)
83
+ throw steeringError("the task is not running");
84
+ if (live.resultValue !== undefined || h.loop.ended)
85
+ throw steeringError("the task is no longer running");
86
+ if (mcpRedialRef.redial === undefined) {
87
+ const e = new Error(`cannot reconnect an MCP server: this run declared no MCP servers — there is nothing to re-dial`);
88
+ e.code = "mcp.reconnect_unavailable";
89
+ throw e;
90
+ }
91
+ return mcpRedialRef.redial(serverIn);
92
+ };
72
93
  const compact = async (opts) => {
73
94
  if (live.resultValue)
74
95
  throw steeringError("the task has already finished");
@@ -131,5 +152,5 @@ export function streamLifecycleVerbs(input) {
131
152
  h.abortController.abort();
132
153
  void h.harness.abort();
133
154
  };
134
- return { notify, optOutMemoryCapture, compact, detach, interrupt };
155
+ return { notify, optOutMemoryCapture, reconnectMcpServer, compact, detach, interrupt };
135
156
  }
@@ -179,20 +179,21 @@ export interface RunnerDeps {
179
179
  /**
180
180
  * design/199 件B — DEPLOYMENT-layer ADDITIONS to the built-in sensitive-path READ deny set
181
181
  * ({@link import("../tools/fs/read-deny.js").READ_FACE_DEFAULT_DENY_ENTRIES}); see
182
- * {@link TaskSpec.readDenyPatterns} for the judged surfaces. Add-only on THIS seat: unions with
183
- * the active built-ins and any task-layer additions, and `[]` ≡ absent — narrowing the built-in
182
+ * {@link TaskSpec.readDenyPatterns} for the judged surfaces. INDEPENDENT of the built-in switch. Add-only on
183
+ * THIS seat: unions with the active built-ins and any task-layer additions, and `[]` ≡ absent — narrowing the built-in
184
184
  * set is the sibling knobs' job ({@link readDenyBuiltinTiers} / {@link readDenyBuiltinExclude},
185
185
  * #245 revision of D-4), not a replacement escape hatch here. Bad entry shapes refuse loudly at
186
186
  * prepare (#123).
187
187
  */
188
188
  readDenyPatterns?: readonly import("../tools/fs/read-deny.js").ReadDenyEntry[];
189
189
  /**
190
- * The deployment's built-in deny-table TIER selection:
191
- * EXACTLY the listed tiers of
190
+ * The deployment's built-in deny-table TIER selection — the ON/OFF switch for the whole built-in
191
+ * table, OFF unless this seat says otherwise. EXACTLY the listed tiers of
192
192
  * {@link import("../tools/fs/read-deny.js").READ_FACE_BUILTIN_DENY_TABLE} are active (`[]` = none —
193
- * explicit and legal); absent = the default selection
194
- * ({@link import("../tools/fs/read-deny.js").READ_DENY_DEFAULT_TIERS}: every tier except
195
- * `shell-history`, which is unrestricted by default). Composes with
193
+ * explicit and legal); ABSENT = {@link import("../tools/fs/read-deny.js").READ_DENY_DEFAULT_TIERS},
194
+ * which is EMPTY: an unconfigured deployment activates no built-in row, so nothing from that table
195
+ * refuses a read or demotes a shell one. A leg's active tiers are REPORTED on its wiring manifest
196
+ * ({@link import("./wiring-manifest.js").WiringManifest.readDeny}). Composes with
196
197
  * {@link readDenyBuiltinExclude} (tiers first, then row removal); never touches the additions
197
198
  * seats or the write faces. Unknown tier names refuse loudly at prepare (#123). DEPLOYMENT seat
198
199
  * ONLY: deliberately not a TaskSpec key and not in the governed workflow whitelist — a task or
@@ -324,6 +325,14 @@ export interface RunnerDeps {
324
325
  memoryCaptureRecordStore?: (plane: {
325
326
  controlDir: string;
326
327
  }) => import("./memory-engine/layout.js").SessionCaptureRecordStore;
328
+ /** which occupant of a session id is running now (a purge may delete a session tree and the
329
+ * id be handed out again; without this seat a standing opt-out or pollution record binds the NEXT
330
+ * occupant too). An opaque token, STABLE for one occupant's life, DIFFERENT for the next, only
331
+ * ever compared ({@link import("./memory-engine/layout.js").sessionRecordBindsIncarnation}).
332
+ * ABSENT ⇒ records bind by id (the pre-incarnation bytes); an empty or throwing answer reads the same. */
333
+ memorySessionIncarnation?: (session: {
334
+ sessionId: string;
335
+ }) => string | undefined;
327
336
  /**
328
337
  * design/339 §6.1 — the v3 memory-consolidation switch, threaded verbatim to the engine seat
329
338
  * ({@link import("../core/memory-engine/engine.js").MemoryEngineOptions.consolidation} — same
@@ -65,10 +65,11 @@ export interface ResolvedSkillListingBudget {
65
65
  * (`200 000 × 4 × 0.01` = 8 000 bytes).
66
66
  *
67
67
  * The window is `contextTokens ?? contextWindow`, the same physical coordinate the deferral gate
68
- * measures against. A window that is absent OR unusable (non-finite, non-positive) reads as
69
- * {@link SKILL_LISTING_DEFAULT_CONTEXT_TOKENS}: one rule, not a case per bad shape — a model's own
70
- * declaration is judged by the model doors, and this seat must still produce a number a renderer can
71
- * compare against.
68
+ * measures against. `contextTokens: 0` (or any other non-finite/non-positive declared value) does
69
+ * NOT fall through `??` to `contextWindow` — `0` is not nullish — so it lands here as a
70
+ * declared-but-unusable window, and this seat folds it to {@link SKILL_LISTING_DEFAULT_CONTEXT_TOKENS}
71
+ * the same as a genuinely absent window: one rule, not a case per bad shape, because this seat's
72
+ * job is to always hand a renderer a usable number.
72
73
  */
73
74
  export declare function resolveSkillListingBudget(opts: {
74
75
  fraction?: unknown;
@@ -562,8 +562,9 @@ export interface TaskResult {
562
562
  * duplicates, so re-supplying deployment-shared entries is idempotent) — that is how the frozen
563
563
  * posture rides every leg that continues this work, not just the delegation subtree.
564
564
  *
565
- * **In-presence condition:** present iff non-empty. Built-in entries are never listed (they are in
566
- * force on every run and re-compile locally). Same terminal coverage as
565
+ * **In-presence condition:** present iff non-empty. Built-in entries are never listed — they are the
566
+ * DEPLOYMENT's own selection (off by default), re-compiled per leg and reported on its wiring
567
+ * manifest ({@link import("./wiring-manifest.js").WiringManifest.readDeny}). Same terminal coverage as
567
568
  * {@link effectiveReadFace}: rides any terminal of a leg that ran; absent on prepare failures.
568
569
  *
569
570
  * On a DURABLE-PAUSE hand-back these seats are additionally the RE-SUPPLY hint: a checkpoint
@@ -789,7 +789,8 @@ export interface TaskSpec {
789
789
  * {@link RunnerDeps.readDenyPatterns}; `[]` ≡ absent (union identity); NOTHING at the task layer
790
790
  * can remove a built-in — the one removal channel is the DEPLOYMENT's built-in configuration
791
791
  * ({@link RunnerDeps.readDenyBuiltinTiers} / {@link RunnerDeps.readDenyBuiltinExclude}, #245
792
- * revision of D-4), which no TaskSpec key reaches. Bad entry shapes refuse loudly at prepare
792
+ * revision of D-4), which no TaskSpec key reaches — and that half is OFF by default, so on an
793
+ * unconfigured deployment the entries here are the WHOLE judged set. Bad entry shapes refuse loudly at prepare
793
794
  * (#123). The write faces are untouched.
794
795
  */
795
796
  readDenyPatterns?: readonly import("../tools/fs/read-deny.js").ReadDenyEntry[];
@@ -275,6 +275,32 @@ export interface TaskStream extends AsyncIterable<TaskEvent> {
275
275
  }): Promise<{
276
276
  outcome: "created" | "existed";
277
277
  }>;
278
+ /**
279
+ * **RE-DIAL one MCP server** on the running task, the action `RefreshMcpTools` deliberately
280
+ * is not (its contract is "never dials or re-dials"). Core holds no MCP connection across task
281
+ * legs, so once a server's transport closes this leg is stuck with it: every one of its tools fails
282
+ * fast and a refresh can only keep reporting `not_connected`. This is the verb a host hangs a
283
+ * "Reconnect" control on. ONE NAMED SERVER, required — CC 2.1.259's control-channel request carries
284
+ * a required `serverName` and has no all-servers form, and an all-servers form would CLOSE HEALTHY
285
+ * connections to re-dial them (the stdio server owning a device or a port — the case this verb
286
+ * exists for — is the one that cannot be re-dialed while its predecessor still holds the device).
287
+ *
288
+ * ⚠️ **A FAILED RE-DIAL LEAVES THE SERVER DOWN.** The old connection is closed BEFORE the new one is
289
+ * dialed (no other order works for a device-owning server), so a dial that fails has spent a
290
+ * working connection: the server stays disconnected, with its tools WITHDRAWN from the roster,
291
+ * until another re-dial or the next leg's materialize — and calls in flight on the replaced
292
+ * connection fail with it. Both are inherent to re-dialing; CC behaves the same way.
293
+ *
294
+ * Resolves {@link import("./mcp.js").McpReconnectResult} — `outcome` is one of three words, so a
295
+ * consumer mapping it onto a three-state control answer needs no table: `reconnected` (the only
296
+ * success), `refused` (the engine declined, or the dial failed — `reason` says which and
297
+ * `status.errorCode` keys the next action), `not_declared` (no server of that name on this leg).
298
+ * Throws, never silently no-ops: `mcp.reconnect_unavailable` when this run declared NO MCP servers
299
+ * (a host maps that to "unsupported", not "refused"), `steering.invalid_content` on a missing or
300
+ * non-string name, and the steer-family `steering.not_running` once the task has finished.
301
+ * LEG-LOCAL: the result rides no checkpoint, and a durable resume takes a fresh first listing.
302
+ */
303
+ reconnectMcpServer(server: string): Promise<import("./mcp.js").McpReconnectResult>;
278
304
  /**
279
305
  * Hard-**interrupt** the running task — a real abort (not a best-effort hint), equivalent to firing the
280
306
  * task's `signal` (design/47). Refused typed (`steering.not_running`, the steer-family liveness code —
@@ -95,8 +95,12 @@ export interface ReversibilityVerdict {
95
95
  * spelled, which is the only one derivable from the text.
96
96
  */
97
97
  export interface ReadRootGrantCandidate {
98
- /** An absolute, lexically folded directory in the boundary's own spelling; never a file or a pattern. */
98
+ /** An absolute, lexically folded path in the boundary's own spelling; never a pattern. A DIRECTORY
99
+ * unless {@link covers} says otherwise. */
99
100
  readonly dir: string;
101
+ /** `"exact"` ⇒ {@link dir} is the path the command NAMED, offered verbatim rather than a directory
102
+ * containing it. A consumer ADDS the string itself: expanding it into a pattern grants nothing. */
103
+ readonly covers?: "exact";
100
104
  /** Always the literal `true` — a shape, not a value, so the seat cannot be widened into a "maybe this
101
105
  * helps" hint without a visible type change. It claims THIS ask: not the deny layer (judged by pattern
102
106
  * rather than by root, and unmoved by any grant), and not another ask the same call may raise. */
@@ -548,6 +548,11 @@ export type TraceEvent = {
548
548
  verdict: "allow" | "block" | "unavailable" | "parse_error";
549
549
  /** Present iff `verdict === "unavailable"`: `error` / `timeout`. */
550
550
  cause?: "error" | "timeout";
551
+ /** Present exactly when NO MODEL WAS ASKED because the question did not assemble: `timeout` = the
552
+ * assembly outran its cap, `failed` = it threw. The verdict reads `unavailable` / `error` either way
553
+ * (nothing was dispatched), and `ms` is then time spent BUILDING, not waiting on a provider — which is
554
+ * what separates "the transcript store is slow" from "the provider is down". */
555
+ notAsked?: "failed" | "timeout";
551
556
  ts: number;
552
557
  } | {
553
558
  /** C1 — the failover brain served this call from a FALLBACK entry (`createFailoverBrain`): the
@@ -27,6 +27,6 @@ export { AUTO_MODE_DENY_SOURCES, isAutoModeDenySource } from "./runtime-caps.js"
27
27
  export type { BackgroundChildEvent, DelegationLifecycleEvent } from "./delegation-frames.js";
28
28
  export { __resetMalformedDelegationSeatAnnouncement, deliverDelegationLifecycle } from "./delegation-frames.js";
29
29
  export type { ProjectMemoryLoad, ResumePreflightInfo, ResumePreflightVerdict, RunnerDeps } from "./runner-deps.js";
30
- export type { EngineNotice } from "./engine-notice.js";
31
- export { __resetMalformedNoticeSeatAnnouncement, deliverEngineNotice, owedUserInputCounts, undrainedUserInputNotices } from "./engine-notice.js";
30
+ export type { EngineNotice, OwedUserInputAccount } from "./engine-notice.js";
31
+ export { __resetMalformedNoticeSeatAnnouncement, deliverEngineNotice, owedUserInputCounts, settleOwedUserInput, undrainedUserInputNotices } from "./engine-notice.js";
32
32
  export type { AgentTool, Model, StreamFn, ThinkingLevel, ToolInputValidationContext, ToolInputVerdict };
@@ -1,3 +1,3 @@
1
1
  export { AUTO_MODE_DENY_SOURCES, isAutoModeDenySource } from "./runtime-caps.js";
2
2
  export { __resetMalformedDelegationSeatAnnouncement, deliverDelegationLifecycle } from "./delegation-frames.js";
3
- export { __resetMalformedNoticeSeatAnnouncement, deliverEngineNotice, owedUserInputCounts, undrainedUserInputNotices } from "./engine-notice.js";
3
+ export { __resetMalformedNoticeSeatAnnouncement, deliverEngineNotice, owedUserInputCounts, settleOwedUserInput, undrainedUserInputNotices } from "./engine-notice.js";
@@ -347,6 +347,26 @@ export interface WiringManifest {
347
347
  writeProtection?: {
348
348
  targetView: WriteProtectionTargetView;
349
349
  };
350
+ /**
351
+ * EFFECTIVE half only; the present-iff law is the contract sentence below. `builtinTiers` names the
352
+ * tiers that MATERIALLY activate rows, in {@link
353
+ * import("../tools/fs/read-deny.js").READ_DENY_BUILTIN_TIERS} order — not the tiers the operator
354
+ * typed: one whose every row `readDenyBuiltinExclude` removed is not named. Deliberately NOT
355
+ * reported: `readDenyPatterns`, deployment-supplied TEXTS rather than an enum, so absence means "no
356
+ * BUILT-IN row judges", never "no read is deny-judged". IN the fingerprint (the
357
+ * {@link WiringManifest.writeProtection} class): the selection follows the deployment seat, so legs
358
+ * of one assembly agree.
359
+ *
360
+ * @contract read_deny.builtin_activation_disclosed — WHETHER the built-in sensitive-path read deny
361
+ * table judges a leg is DISCLOSED, never inferred: the table is a deployment opt-in whose default
362
+ * selection is empty, the leg that compiles the judge relays the tiers its own resolution materially
363
+ * activated, and the manifest carries that section iff at least one built-in row is active (absence
364
+ * = no built-in row judges; an empty array is never emitted — "off" and "on to nothing" are one
365
+ * fact). The disclosure changes no verdict.
366
+ */
367
+ readDeny?: {
368
+ builtinTiers: readonly string[];
369
+ };
350
370
  /**
351
371
  * EFFECTIVE half only. PRESENT IFF auto-consolidation is EFFECTIVELY armed on this
352
372
  * deployment (`autoRunOnRecommendationEffective`: an explicit `true`, or an absent seat under the
@@ -441,6 +461,9 @@ export interface WiringFacts {
441
461
  /** Effective half only — the compiled write-protection judge's OWN target-view word
442
462
  * ({@link WiringManifest.writeProtection}); absent ⇒ this leg compiled no judge (an emptied table). */
443
463
  writeProtectionTargetView?: WriteProtectionTargetView;
464
+ /** Effective half only — the built-in read-deny TIERS this leg's configuration materially activated
465
+ * ({@link WiringManifest.readDeny}); empty and absent derive the same thing (no section). */
466
+ readDenyBuiltinTiersActive?: readonly string[];
444
467
  /** Effective half only — `RunnerDeps.autoRunOnRecommendation === true`
445
468
  * ({@link WiringManifest.autoConsolidation}); false ⇒ no section (byte-identical manifest). */
446
469
  autoConsolidationOnRecommendation?: boolean;
@@ -142,6 +142,9 @@ export function deriveWiringManifest(facts) {
142
142
  ...(facts.half === "effective" && facts.hooks !== undefined && facts.hooks.length > 0 ? { hooks: facts.hooks.map((h) => ({ ...h })) } : {}),
143
143
  ...(facts.half === "effective" && facts.lsp !== undefined ? { lsp: { ...facts.lsp } } : {}),
144
144
  ...(facts.half === "effective" && facts.writeProtectionTargetView !== undefined ? { writeProtection: { targetView: facts.writeProtectionTargetView } } : {}),
145
+ ...(facts.half === "effective" && facts.readDenyBuiltinTiersActive !== undefined && facts.readDenyBuiltinTiersActive.length > 0
146
+ ? { readDeny: { builtinTiers: [...facts.readDenyBuiltinTiersActive] } }
147
+ : {}),
145
148
  ...(facts.half === "effective" && facts.autoConsolidationOnRecommendation === true ? { autoConsolidation: { onRecommendation: true } } : {}),
146
149
  };
147
150
  if (facts.half === "effective") {
package/dist/index.d.ts CHANGED
@@ -57,7 +57,7 @@ export { assertOracleIsolation, type GraderEnv, type OracleIsolationVerdict, typ
57
57
  export { decideAutoPromote, deriveTripwire, FROZEN_DENYLIST_FLOOR, type AutoPromoteTerminal, type AutoPromoteInputs, type PromotedRecord, type TripwireResult, } from "./core/auto-promote.js";
58
58
  export { runCascade, type CascadeRung, type CascadeConfig, type CascadeAttempt, type CascadeRunResult, type GateVerdict, } from "./agents/cascade.js";
59
59
  export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
60
- export { materializeMcpTools, MCP_PREFIX, type MaterializedMcp, type McpServerStatus, type McpRefreshResult } from "./core/mcp.js";
60
+ export { materializeMcpTools, MCP_PREFIX, type MaterializedMcp, type McpServerStatus, type McpRefreshResult, type McpReconnectResult } from "./core/mcp.js";
61
61
  export { MCP_FAILURE_KINDS, MCP_DELIVERY_VERDICTS, classifyMcpFailure, type McpFailure, type McpFailureKind, type McpDelivered } from "./core/mcp-failure.js";
62
62
  export { MCP_INJECTION_DROP_REASONS, MCP_INJECTION_DROP_TEXT, mcpInjectionDroppedNotice, type McpInjectionDropReason, type McpInjectionDropFacts } from "./core/mcp-injection-drop.js";
63
63
  export { askUnresolvableNotice, type AskUnresolvableFacts } from "./core/ask-unresolvable-notice.js";
@@ -70,7 +70,7 @@ export { createSessionRulePolicy } from "./core/runner/session-rule-policy.js";
70
70
  export { LOCKED_KEY_REGISTRY, resolveLockedKeys, type LockedKey, type LockedConfig } from "./core/locked-config.js";
71
71
  export { BUILTIN_COMPLIANCE_DENIES, COMPLIANCE_CAPABILITIES, WEB_FETCH_TOOL_NAME, complianceCallDenial, resolveComplianceDenies, type ComplianceCapability, type CompliancePosture, type ComplianceProfile, } from "./core/compliance.js";
72
72
  export { admitMemoryScopes, foldAdmissionFreeze, type OwnOrgAdmissionVerdict, type MemoryAdmissionInput, type MemoryAdmissionOutcome, type MemoryAdmissionVerdict, type MemoryScopeAdmission, type MemoryScopeOrigin, type MemoryScopeRequest, } from "./core/memory-admission.js";
73
- export { assertRetentionCapability, type ManagedRetentionCapability, type RetentionDeclaration, type RetentionDeclaring, type RetentionPolicy, type RetentionReceipt, } from "./core/retention.js";
73
+ export { assertRetentionCapability, RETENTION_CASCADE_DOMAINS, RETENTION_CASCADE_EXEMPT, type ManagedRetentionCapability, type RetentionDeclaration, type RetentionDeclaring, type RetentionPolicy, type RetentionReceipt, } from "./core/retention.js";
74
74
  export { GOVERNANCE_CODES, governanceRetryClass, type GovernanceCode, type GovernanceRetryClass } from "./core/governance-codes.js";
75
75
  export { NOTICE_AUDIENCE, noticeAudienceOf, ENGINE_NOTICE_CODES, type EngineNoticeCode, type NoticeAudience } from "./core/governance-codes.js";
76
76
  export { TtlSessionStore, type TtlSessionStoreOptions, type EvictPolicy } from "./core/session-store.js";
@@ -225,7 +225,8 @@ export { termSet, jaccardDistance, cosineDistance } from "./core/memory-vector.j
225
225
  export { encodeSurfacedKey, buildManifestText, validateSelectedIds, composeSelectiveBody, formatMemoryAge, resolveLinkedIds, RECALL_CAVEAT, DEFAULT_MAX_SELECTED, DEFAULT_MAX_LINKED, type MemorySelector, type MemorySelectRequest, type SelectiveRecallOptions, type SelectiveRecallResult, type LayeredRecallOptions, type LayeredRecallResult, } from "./core/memory-recall.js";
226
226
  export { runMemoryConsolidation, CONSOLIDATION_SYSTEM_PROMPT, DEFAULT_CONSOLIDATION_BAND, DEFAULT_CONSOLIDATION_SEARCH_LIMIT, DEFAULT_CONSOLIDATION_MAX_NOTES, normalizeForExactMatch, type ConsolidationParams, type ConsolidationStats, type ConsolidationNote, type ConsolidationLLM, } from "./core/runner/memory-consolidation.js";
227
227
  export { consolidateScope, advanceCursorAfterInline, type ConsolidateScopeDeps, type ConsolidateScopeOptions, } from "./core/consolidate-scope.js";
228
- export { resolveMemoryConsolidationDriver, type MemoryConsolidationDriverDeps, } from "./core/runner/memory-consolidation-driver.js";
228
+ export { resolveMemoryConsolidationDriver, autoRunOnRecommendationEffective, // the ONE arming reading (`memory.auto_consolidation.arming_has_one_resolver`) — the seat's absence is not "off"
229
+ type MemoryConsolidationDriverDeps, } from "./core/runner/memory-consolidation-driver.js";
229
230
  export { DEFAULT_COMPACTION_INSTRUCTIONS } from "./core/auto-compaction.js";
230
231
  export { DEFAULT_SYSTEM_PROMPT, CODE_AGENT_PROMPT, SUBAGENT_PROMPT, CODE_SYSTEM_PROMPT, MEMORY_GUIDANCE, MEMORY_SAFETY, MEMORY_HYGIENE, NO_PERSISTENT_MEMORY_NOTICE, OUTPUT_EFFICIENCY, CYBER_RISK, HARNESS_SECTION_ANCHOR, URL_SAFETY, SUMMARIZE_TOOL_RESULTS, EXECUTION_ENVIRONMENT, EXECUTION_ENVIRONMENT_OPEN_READS, executionEnvironmentBlockFor, harnessContext, buildEnvironmentContext, buildGitSnapshot, buildScratchpadSection, GIT_STATUS_MAX_CHARS, formatLocalDate, type EnvironmentFacts, defaultPromptProvider, composeSystemPrompt, composeConstitution, constitutionBlocks, type PromptBlock, analyzePromptCacheFriendliness, assertPromptCacheFriendly, type PromptProvider, type StablePromptContext, type PromptCacheReport, type PromptTextDeclaration, } from "./prompts/default.js";
231
232
  export { SUPERVISOR_PROMPT, ORCHESTRATION_GUIDANCE, ORCHESTRATION_AWARENESS, GOAL_COMPLETION_GUIDANCE } from "./prompts/supervisor.js";
package/dist/index.js CHANGED
@@ -56,7 +56,7 @@ export { createSessionRulePolicy } from "./core/runner/session-rule-policy.js";
56
56
  export { LOCKED_KEY_REGISTRY, resolveLockedKeys } from "./core/locked-config.js";
57
57
  export { BUILTIN_COMPLIANCE_DENIES, COMPLIANCE_CAPABILITIES, WEB_FETCH_TOOL_NAME, complianceCallDenial, resolveComplianceDenies, } from "./core/compliance.js";
58
58
  export { admitMemoryScopes, foldAdmissionFreeze, } from "./core/memory-admission.js";
59
- export { assertRetentionCapability, } from "./core/retention.js";
59
+ export { assertRetentionCapability, RETENTION_CASCADE_DOMAINS, RETENTION_CASCADE_EXEMPT, } from "./core/retention.js";
60
60
  export { GOVERNANCE_CODES, governanceRetryClass } from "./core/governance-codes.js";
61
61
  export { NOTICE_AUDIENCE, noticeAudienceOf, ENGINE_NOTICE_CODES } from "./core/governance-codes.js";
62
62
  export { TtlSessionStore } from "./core/session-store.js";
@@ -183,7 +183,7 @@ export { termSet, jaccardDistance, cosineDistance } from "./core/memory-vector.j
183
183
  export { encodeSurfacedKey, buildManifestText, validateSelectedIds, composeSelectiveBody, formatMemoryAge, resolveLinkedIds, RECALL_CAVEAT, DEFAULT_MAX_SELECTED, DEFAULT_MAX_LINKED, } from "./core/memory-recall.js";
184
184
  export { runMemoryConsolidation, CONSOLIDATION_SYSTEM_PROMPT, DEFAULT_CONSOLIDATION_BAND, DEFAULT_CONSOLIDATION_SEARCH_LIMIT, DEFAULT_CONSOLIDATION_MAX_NOTES, normalizeForExactMatch, } from "./core/runner/memory-consolidation.js";
185
185
  export { consolidateScope, advanceCursorAfterInline, } from "./core/consolidate-scope.js";
186
- export { resolveMemoryConsolidationDriver, } from "./core/runner/memory-consolidation-driver.js";
186
+ export { resolveMemoryConsolidationDriver, autoRunOnRecommendationEffective, } from "./core/runner/memory-consolidation-driver.js";
187
187
  export { DEFAULT_COMPACTION_INSTRUCTIONS } from "./core/auto-compaction.js";
188
188
  export { DEFAULT_SYSTEM_PROMPT, CODE_AGENT_PROMPT, SUBAGENT_PROMPT, CODE_SYSTEM_PROMPT, MEMORY_GUIDANCE, MEMORY_SAFETY, MEMORY_HYGIENE, NO_PERSISTENT_MEMORY_NOTICE, OUTPUT_EFFICIENCY, CYBER_RISK, HARNESS_SECTION_ANCHOR, URL_SAFETY, SUMMARIZE_TOOL_RESULTS, EXECUTION_ENVIRONMENT, EXECUTION_ENVIRONMENT_OPEN_READS, executionEnvironmentBlockFor, harnessContext, buildEnvironmentContext, buildGitSnapshot, buildScratchpadSection, GIT_STATUS_MAX_CHARS, formatLocalDate, defaultPromptProvider, composeSystemPrompt, composeConstitution, constitutionBlocks, analyzePromptCacheFriendliness, assertPromptCacheFriendly, } from "./prompts/default.js";
189
189
  export { SUPERVISOR_PROMPT, ORCHESTRATION_GUIDANCE, ORCHESTRATION_AWARENESS, GOAL_COMPLETION_GUIDANCE } from "./prompts/supervisor.js";
@@ -297,7 +297,7 @@ function pickWhitelist(scriptSpec) {
297
297
  if (!Array.isArray(readDenyPatternsRaw)) {
298
298
  throw new WorkflowScriptError('agent(spec): `readDenyPatterns` must be an array of deny entries (a "/"-separated segment run such as ".ssh", or { pattern, caseSensitive? })');
299
299
  }
300
- const entries = mapUntrustedArray(readDenyPatternsRaw, "agent(spec): `readDenyPatterns`", MAX_SCRIPT_DENY_ENTRIES, "Every entry is judged against every path the child reads, for the child's whole run; the built-in and deployment entries are always in force on top of these.", pickReadDenyEntry);
300
+ const entries = mapUntrustedArray(readDenyPatternsRaw, "agent(spec): `readDenyPatterns`", MAX_SCRIPT_DENY_ENTRIES, "Every entry is judged against every path the child reads, for the child's whole run; the deployment's own entries, and whichever built-in tiers the deployment switched on (none by default), are in force on top of these.", pickReadDenyEntry);
301
301
  try {
302
302
  compileReadDeny(entries, "agent(spec).readDenyPatterns");
303
303
  }
@@ -51,8 +51,8 @@ parentReadFace?: () => TaskSpec["readFace"],
51
51
  /** The WRITE seat's twin of the above — the host run's RESOLVED write-face containment, folded
52
52
  * stricter-wins into every spawned child on its own seat (the two seats never read each other). */
53
53
  parentWriteFace?: () => TaskSpec["writeFace"],
54
- /** Twin of the above for the deny-set additions (built-ins always apply; these are the extra
55
- * entries the host's own deployment/task layers stacked on). */
54
+ /** Twin of the above for the deny-set additions (the extra entries the host's own deployment/task
55
+ * layers stacked on; the built-in rows the DEPLOYMENT switched on — none by default — apply beside them). */
56
56
  parentReadDenyPatterns?: () => TaskSpec["readDenyPatterns"],
57
57
  /** #345 ③ — the HOST task's write-hands clamp is ON (`spec.handsReadOnly === true`). Injected
58
58
  * tighten-only into every spawned child, like the read-face clamp above; see the injection
@@ -47,9 +47,16 @@ export declare const ARGV_REENTRY_PROGRAM_RE: RegExp;
47
47
  export declare const ARGV_REENTRY_DEFAULT_PROGRAM = "echo";
48
48
  /**
49
49
  * What a launcher declares about its OWN options: each exact spelling with its ARITY — `0` for a switch, `1` for an
50
- * option whose value is the next token. A fused `--name=value` and every spelling not in the map fall to the refusal
51
- * (the conservative side, and the verdict those spellings always had); a `1` with no token left to take is not
52
- * readable either.
50
+ * option whose value is the next token. Every spelling not in the map falls to the refusal (the conservative side,
51
+ * and the verdict those spellings always had); a `1` with no token left to take is not readable either.
52
+ *
53
+ * THREE SPELLINGS OF ONE DECLARATION, because getopt has three: an arity-1 entry is honoured separated (`-k 5`),
54
+ * fused to its long name (`--signal=TERM`) and fused to its short letter (`-k5`), and an arity-0 short entry inside
55
+ * a cluster of arity-0 letters (`-pv`). Reading only the exact spelling made one program two.
56
+ *
57
+ * WHAT A ROW MAY NOT GET WRONG: declaring an arity-1 option as arity 0 steps onto its VALUE and reads the value as
58
+ * the program — the one direction that turns a refusal into a wrong answer rather than a lost one. A row carries
59
+ * only options whose arity every supported implementation agrees on; a flag no row declares still refuses.
53
60
  */
54
61
  export interface LauncherRow {
55
62
  /** Consulted ONLY for the launcher the command line itself names — a bare keyword in front of the command
@@ -58,6 +65,19 @@ export interface LauncherRow {
58
65
  * them would turn a whole refusal into an ordinary walked segment — a widening, where every other read of this
59
66
  * table only ever finds MORE program to judge. */
60
67
  readonly optionArity: ReadonlyMap<string, 0 | 1>;
68
+ /** A bare NEGATIVE integer in this launcher's option section is its OWN argument (`nice -5 <cmd>`), not a flag
69
+ * the table cannot read. Per row: elsewhere a dash-leading token is an option, and reading one as a number
70
+ * would step over a flag whose meaning this table does not know. */
71
+ readonly negativeIntegerIsOwnArgument?: true;
72
+ /** Positional operands the launcher takes BEFORE the program, consumed whatever they spell (`timeout DURATION
73
+ * COMMAND`); a spelling-based reading under-accepted, and every spelling it missed became the program word. */
74
+ readonly requiredOperands?: number;
75
+ /** The launcher reads NAME=VALUE operands with ITS OWN name grammar (`env 1=x …`), wider than the shell's. */
76
+ readonly assignmentOperands?: true;
77
+ /** The launcher hands its operands to a SHELL as text (`watch "cat /x"` runs `sh -c`): no program word to read. */
78
+ readonly shellText?: true;
79
+ /** With no program word the launcher runs a SHELL: piped text would reach it, so an empty program position refuses. */
80
+ readonly whenNoProgram?: "shell";
61
81
  }
62
82
  /**
63
83
  * The ONE launcher truth: programs that RUN ANOTHER PROGRAM named in ordinary argv tokens, so a declared reader can
@@ -136,7 +156,8 @@ export interface ProgramPosition {
136
156
  */
137
157
  export declare function readProgramPosition(toks: SegmentTokens): ProgramPosition;
138
158
  /** Does this program position hand a program operands the walk cannot see? True when the chain re-enters through
139
- * stdin AND the program it runs is not declared no-path. ONE reading, shared by every consumer. */
140
- export declare function argvReentryUnjudged(pos: ProgramPosition, noPathPrograms: ReadonlySet<string>): boolean;
159
+ * stdin AND the program it runs is not one the caller accepts as a stream target. ONE reading, shared by every
160
+ * consumer; WHICH targets are accepted is the caller's declaration, not this reader's. */
161
+ export declare function argvReentryUnjudged(pos: ProgramPosition, acceptedTargets: ReadonlySet<string>): boolean;
141
162
  /** ONE sentence per refusal kind, minted here and nowhere else. */
142
163
  export declare function programPositionRefusalSentence(refusal: ProgramPositionRefusal): string;