@sema-agent/core 5.20.0 → 5.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/agents/agent-definition.d.ts +7 -0
- package/dist/agents/agent-transcript-tool.d.ts +30 -0
- package/dist/agents/builtin-agents.d.ts +60 -0
- package/dist/agents/cascade.d.ts +107 -0
- package/dist/agents/cumulative-stats.d.ts +56 -0
- package/dist/agents/observer.d.ts +162 -0
- package/dist/agents/peer-admission.d.ts +95 -0
- package/dist/agents/repair-loop.d.ts +226 -0
- package/dist/agents/retain-ledger.d.ts +141 -0
- package/dist/agents/roster-store.d.ts +105 -0
- package/dist/agents/send-message-tool.d.ts +92 -0
- package/dist/agents/session-util.d.ts +5 -0
- package/dist/agents/subagent-steps.d.ts +66 -0
- package/dist/agents/subagent.d.ts +600 -0
- package/dist/agents/suspend-guard.d.ts +29 -0
- package/dist/agents/teacher.d.ts +75 -0
- package/dist/agents/team.d.ts +120 -1
- package/dist/agents/tool-filter.d.ts +34 -0
- package/dist/agents/verify.d.ts +198 -0
- package/dist/bench/metrics.d.ts +455 -0
- package/dist/brain/anthropic.d.ts +30 -0
- package/dist/brain/circuit-breaker.d.ts +33 -0
- package/dist/brain/context-overflow.d.ts +60 -3
- package/dist/brain/degrading.d.ts +67 -0
- package/dist/brain/errors.d.ts +42 -0
- package/dist/brain/failover.d.ts +15 -0
- package/dist/brain/media-degrade.d.ts +39 -0
- package/dist/brain/model-presets.d.ts +31 -0
- package/dist/brain/open-responses.d.ts +19 -0
- package/dist/brain/openai.d.ts +46 -0
- package/dist/brain/reasoning.d.ts +106 -1
- package/dist/brain/repetition.d.ts +83 -0
- package/dist/brain/request-params.d.ts +56 -0
- package/dist/brain/retry.d.ts +46 -0
- package/dist/brain/routing.d.ts +12 -0
- package/dist/brain/status-sink.d.ts +30 -1
- package/dist/brain/stream-engine.d.ts +147 -0
- package/dist/brain/stream-shared.d.ts +34 -0
- package/dist/brain/terminal-cause.d.ts +31 -0
- package/dist/brain/timeout.d.ts +107 -0
- package/dist/brain/tool-call-id.d.ts +20 -0
- package/dist/brain/tool-call-repair.d.ts +13 -0
- package/dist/config/catalog.d.ts +47 -0
- package/dist/config/defaults.d.ts +33 -0
- package/dist/core/a2a-task-state.d.ts +53 -0
- package/dist/core/a2a.d.ts +51 -0
- package/dist/core/arg-summary.d.ts +62 -0
- package/dist/core/ask-question.d.ts +272 -2
- package/dist/core/auto-compaction.d.ts +467 -0
- package/dist/core/auto-compaction.js +20 -6
- package/dist/core/auto-mode-prompt-assets.d.ts +8 -0
- package/dist/core/auto-mode-prompt.d.ts +27 -0
- package/dist/core/auto-mode.d.ts +54 -3
- package/dist/core/auto-promote.d.ts +100 -0
- package/dist/core/background-agent-store.d.ts +292 -0
- package/dist/core/background-shell.d.ts +110 -0
- package/dist/core/cache-break-detector.d.ts +34 -0
- package/dist/core/canonical-json.d.ts +57 -0
- package/dist/core/checkpoint-store.d.ts +1574 -16
- package/dist/core/compliance.d.ts +30 -0
- package/dist/core/consolidate-scope.d.ts +75 -0
- package/dist/core/context-edit.d.ts +99 -0
- package/dist/core/context-guard.d.ts +46 -0
- package/dist/core/exec-gate.d.ts +44 -0
- package/dist/core/exec-output-tail.d.ts +61 -0
- package/dist/core/file-snapshot-store.d.ts +104 -0
- package/dist/core/fs-write-gate-policy.d.ts +36 -0
- package/dist/core/git-worktree-env.d.ts +31 -0
- package/dist/core/governance-codes.d.ts +19 -0
- package/dist/core/hooks.d.ts +608 -1
- package/dist/core/human-input-projection.d.ts +37 -0
- package/dist/core/human-input-projection.js +13 -0
- package/dist/core/image-downsample.d.ts +74 -0
- package/dist/core/locked-config.d.ts +37 -0
- package/dist/core/lsp-diagnostics.d.ts +77 -0
- package/dist/core/lsp-protocol.d.ts +29 -0
- package/dist/core/lsp-session.d.ts +60 -1
- package/dist/core/lsp.d.ts +150 -1
- package/dist/core/mailbox-store.d.ts +57 -0
- package/dist/core/mcp.d.ts +381 -0
- package/dist/core/media-byte-cap.d.ts +21 -0
- package/dist/core/memory-admission.d.ts +71 -0
- package/dist/core/memory-engine/content-origin.d.ts +64 -0
- package/dist/core/memory-engine/data-plane.d.ts +43 -0
- package/dist/core/memory-engine/dual-root.d.ts +24 -0
- package/dist/core/memory-engine/engine.d.ts +230 -0
- package/dist/core/memory-engine/engine.js +103 -35
- package/dist/core/memory-engine/file-backend.d.ts +155 -0
- package/dist/core/memory-engine/frontmatter.d.ts +16 -0
- package/dist/core/memory-engine/layout.d.ts +217 -0
- package/dist/core/memory-engine/memory-backend-contract.d.ts +12 -0
- package/dist/core/memory-engine/migrate.d.ts +9 -0
- package/dist/core/memory-engine/scan.d.ts +12 -0
- package/dist/core/memory-engine/scope-contract.d.ts +61 -1
- package/dist/core/memory-engine/sync-client.d.ts +87 -0
- package/dist/core/memory-engine/sync.d.ts +60 -0
- package/dist/core/memory-engine/tools.d.ts +41 -0
- package/dist/core/memory-engine/types.d.ts +188 -0
- package/dist/core/memory-recall.d.ts +141 -0
- package/dist/core/memory-vector.d.ts +20 -0
- package/dist/core/memory.d.ts +458 -0
- package/dist/core/message-utils.d.ts +6 -0
- package/dist/core/oracle-isolation.d.ts +69 -0
- package/dist/core/permission-rule-consent.d.ts +138 -0
- package/dist/core/permission-rule-model.d.ts +122 -0
- package/dist/core/permission-rule-store.d.ts +119 -3
- package/dist/core/permission-rules.d.ts +87 -1
- package/dist/core/present-plan-tool.d.ts +20 -0
- package/dist/core/pricing.d.ts +26 -0
- package/dist/core/property-harness.d.ts +86 -0
- package/dist/core/protocol-naming.d.ts +38 -0
- package/dist/core/protocol-table.d.ts +61 -0
- package/dist/core/push-queue.d.ts +1 -0
- package/dist/core/remote-env.d.ts +383 -1
- package/dist/core/retention-policy.d.ts +33 -0
- package/dist/core/retention.d.ts +51 -0
- package/dist/core/roles.d.ts +59 -0
- package/dist/core/runner/active-skill-scope.d.ts +34 -0
- package/dist/core/runner/assemble-result.d.ts +134 -0
- package/dist/core/runner/compaction-call-options.d.ts +97 -1
- package/dist/core/runner/grounding-signal.d.ts +10 -0
- package/dist/core/runner/image.d.ts +17 -0
- package/dist/core/runner/image.js +29 -15
- package/dist/core/runner/memory-consolidation.d.ts +60 -0
- package/dist/core/runner/prepare-memory.d.ts +59 -0
- package/dist/core/runner/prepare-task.d.ts +1011 -2
- package/dist/core/runner/prepare-task.js +12 -11
- package/dist/core/runner/prompt-suggestions.d.ts +7 -0
- package/dist/core/runner/runtask.d.ts +304 -3
- package/dist/core/runner/session-file-state-replay.d.ts +49 -0
- package/dist/core/runner/session-rule-policy.d.ts +58 -0
- package/dist/core/runner/strict-output-schema.d.ts +18 -3
- package/dist/core/runner/synthetic-tools.d.ts +113 -0
- package/dist/core/runner/teardown-bounded.d.ts +34 -0
- package/dist/core/runner/tool-disclosure.d.ts +227 -0
- package/dist/core/runner/tool-output-projection.d.ts +6 -0
- package/dist/core/runner/turn-attachments.d.ts +634 -0
- package/dist/core/runner/usage-accounting.d.ts +32 -0
- package/dist/core/runtime.d.ts +9 -0
- package/dist/core/safe-notify.d.ts +64 -0
- package/dist/core/safety-axis-vocab.d.ts +23 -0
- package/dist/core/safety-merge-corpus.d.ts +37 -0
- package/dist/core/scheduler.d.ts +121 -0
- package/dist/core/secret-env.d.ts +32 -0
- package/dist/core/select-model.d.ts +15 -0
- package/dist/core/sensitive-path-policy.d.ts +42 -0
- package/dist/core/session-policy-store.d.ts +94 -0
- package/dist/core/session-reconcile.d.ts +80 -0
- package/dist/core/session-store.d.ts +85 -0
- package/dist/core/session.d.ts +153 -0
- package/dist/core/shared-memory/contract.d.ts +22 -0
- package/dist/core/shared-memory/normalize.d.ts +123 -2
- package/dist/core/shared-memory/tools.d.ts +14 -0
- package/dist/core/shared-memory/types.d.ts +105 -0
- package/dist/core/shutdown-debug.d.ts +6 -0
- package/dist/core/side-query.d.ts +38 -0
- package/dist/core/side-query.js +6 -1
- package/dist/core/skill-tool-specifier.d.ts +72 -0
- package/dist/core/skills-directory.d.ts +100 -1
- package/dist/core/spec-contract.d.ts +89 -0
- package/dist/core/store-contracts/background-agent-store-contract.d.ts +31 -0
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +26 -0
- package/dist/core/store-contracts/contract-harness.d.ts +20 -0
- package/dist/core/store-contracts/contract-kit-version.d.ts +27 -0
- package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +8 -0
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +42 -0
- package/dist/core/store-contracts/tool-result-store-contract.d.ts +13 -0
- package/dist/core/strategy-store.d.ts +37 -0
- package/dist/core/stub-env.d.ts +7 -0
- package/dist/core/surrogate-safe-slice.d.ts +35 -0
- package/dist/core/task-notification.d.ts +202 -0
- package/dist/core/task-outcome.d.ts +53 -0
- package/dist/core/task-registry-agent.d.ts +337 -1
- package/dist/core/task-registry-monitor.d.ts +12 -0
- package/dist/core/task-registry-shared.d.ts +540 -0
- package/dist/core/task-registry.d.ts +343 -0
- package/dist/core/task-registry.js +13 -2
- package/dist/core/task-tool-shape.d.ts +44 -0
- package/dist/core/tighten-task-spec.d.ts +21 -0
- package/dist/core/tool-detach.d.ts +21 -0
- package/dist/core/tool-errors.d.ts +131 -0
- package/dist/core/tool-errors.js +4 -0
- package/dist/core/tool-name-aliases.d.ts +27 -0
- package/dist/core/tool-policy.d.ts +555 -0
- package/dist/core/tool-result-budget.d.ts +32 -0
- package/dist/core/tool-result-store.d.ts +174 -1
- package/dist/core/tools.d.ts +45 -0
- package/dist/core/trace.d.ts +323 -0
- package/dist/core/types.d.ts +3859 -2
- package/dist/core/untrusted-egress.d.ts +8 -0
- package/dist/core/untrusted-text.d.ts +156 -0
- package/dist/core/usage-window-store.d.ts +95 -0
- package/dist/core/version.d.ts +1 -0
- package/dist/core/warm-resume.d.ts +17 -0
- package/dist/core/wiring-manifest.d.ts +169 -0
- package/dist/core/with-retry.d.ts +24 -0
- package/dist/core/workflow-journal-store.d.ts +160 -0
- package/dist/core/workflow-run-store-contract.d.ts +25 -0
- package/dist/core/workflow-run-store.d.ts +119 -0
- package/dist/engine/compaction/compaction.d.ts +256 -1
- package/dist/engine/compaction/utils.d.ts +94 -0
- package/dist/engine/execution-env/kill-tree.d.ts +29 -0
- package/dist/engine/execution-env/node-execution-env.d.ts +94 -0
- package/dist/engine/harness/agent-harness.d.ts +116 -0
- package/dist/engine/harness/agent-harness.js +3 -14
- package/dist/engine/harness/messages.d.ts +15 -0
- package/dist/engine/harness/types.d.ts +464 -2
- package/dist/engine/llm/diagnostics.d.ts +4 -0
- package/dist/engine/llm/event-stream.d.ts +3 -0
- package/dist/engine/llm/index.d.ts +7 -0
- package/dist/engine/llm/types.d.ts +500 -3
- package/dist/engine/llm/validation.d.ts +3 -0
- package/dist/engine/loop/agent-loop.d.ts +87 -2
- package/dist/engine/loop/runtime-deps.d.ts +7 -0
- package/dist/engine/loop/types.d.ts +424 -0
- package/dist/engine/lsp/frame-decoder.d.ts +13 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts +107 -0
- package/dist/engine/lsp/stdio-lsp-transport.d.ts +7 -0
- package/dist/engine/session/import-validate.d.ts +27 -0
- package/dist/engine/session/log-digest.d.ts +93 -0
- package/dist/engine/session/memory-repo.d.ts +6 -0
- package/dist/engine/session/memory-storage.d.ts +2 -0
- package/dist/engine/session/session.d.ts +75 -0
- package/dist/engine/session/storage-base.d.ts +8 -0
- package/dist/fixtures/index.d.ts +36 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.js +0 -1
- package/dist/internal/harness-types.d.ts +6 -0
- package/dist/internal/harness.d.ts +11 -0
- package/dist/internal/llm.d.ts +6 -0
- package/dist/orchestration/builtin-workflows.d.ts +53 -0
- package/dist/orchestration/dev-vm-script-runner.d.ts +19 -0
- package/dist/orchestration/goal.d.ts +57 -0
- package/dist/orchestration/goal.js +3 -0
- package/dist/orchestration/run-spec.d.ts +42 -0
- package/dist/orchestration/run-workflow-tool.d.ts +169 -0
- package/dist/orchestration/workflow-governance.d.ts +61 -0
- package/dist/orchestration/workflow-meta.d.ts +28 -0
- package/dist/orchestration/workflow-observe.d.ts +60 -0
- package/dist/orchestration/workflow-primitives.d.ts +23 -1
- package/dist/orchestration/workflow-sandbox-conformance.d.ts +38 -0
- package/dist/orchestration/workflow-script-runner.d.ts +88 -0
- package/dist/orchestration/workflow-script-store.d.ts +98 -0
- package/dist/orchestration/workflow-size-guideline.d.ts +67 -0
- package/dist/orchestration/workflow-types.d.ts +169 -2
- package/dist/orchestration/workflow.d.ts +358 -0
- package/dist/prompt-assembly/artifact-store.d.ts +33 -0
- package/dist/prompt-assembly/artifact.d.ts +25 -0
- package/dist/prompt-assembly/assemble.d.ts +20 -0
- package/dist/prompt-assembly/composer.d.ts +29 -0
- package/dist/prompt-assembly/epoch.d.ts +55 -1
- package/dist/prompt-assembly/event-registry.d.ts +35 -0
- package/dist/prompt-assembly/explain.d.ts +12 -0
- package/dist/prompt-assembly/tool-catalog.d.ts +38 -0
- package/dist/prompt-assembly/turn-snapshot.d.ts +40 -0
- package/dist/prompt-assembly/types.d.ts +115 -0
- package/dist/prompts/coordinator.d.ts +27 -0
- package/dist/prompts/default.d.ts +539 -0
- package/dist/prompts/simple-sections.d.ts +45 -0
- package/dist/prompts/supervisor.d.ts +66 -0
- package/dist/scenarios/env.d.ts +28 -0
- package/dist/scenarios/full-body.d.ts +50 -0
- package/dist/scenarios/scenario-registry.d.ts +60 -0
- package/dist/scenarios/teacher-quickstart.d.ts +27 -0
- package/dist/server/http.d.ts +17 -0
- package/dist/stores/cc/lockfile.d.ts +6 -0
- package/dist/stores/cc/mailbox-store.d.ts +8 -0
- package/dist/stores/cc/roster-adapter.d.ts +4 -0
- package/dist/stores/cc/sidecar-transcript.d.ts +66 -0
- package/dist/stores/file/background-agent-store.d.ts +24 -0
- package/dist/stores/file/checkpoint-store.d.ts +38 -0
- package/dist/stores/file/file-snapshot-store.d.ts +25 -0
- package/dist/stores/file/fs-atomic.d.ts +155 -0
- package/dist/stores/file/index.d.ts +89 -0
- package/dist/stores/file/mailbox-store.d.ts +36 -0
- package/dist/stores/file/memory-store.d.ts +82 -0
- package/dist/stores/file/permission-rule-store.d.ts +79 -0
- package/dist/stores/file/session-policy-store.d.ts +28 -0
- package/dist/stores/file/session-store.d.ts +40 -0
- package/dist/stores/file/shared-ledger.d.ts +83 -0
- package/dist/stores/file/tool-result-store.d.ts +11 -0
- package/dist/stores/file/usage-window-store.d.ts +18 -0
- package/dist/stores/file/workflow-journal-store.d.ts +100 -0
- package/dist/stores/file/workflow-run-store.d.ts +11 -0
- package/dist/tools/fs/bash-readonly-classifier.d.ts +282 -0
- package/dist/tools/fs/encoding.d.ts +60 -0
- package/dist/tools/fs/fs-bash.d.ts +133 -0
- package/dist/tools/fs/fs-pdf.d.ts +28 -0
- package/dist/tools/fs/fs-search-tools.d.ts +5 -0
- package/dist/tools/fs/fs-search-tools.js +0 -1
- package/dist/tools/fs/fs-shared.d.ts +360 -0
- package/dist/tools/fs/fs-write.d.ts +16 -0
- package/dist/tools/fs/gh-rate-limit.d.ts +22 -0
- package/dist/tools/fs/index.d.ts +79 -0
- package/dist/tools/fs/notebook.d.ts +56 -0
- package/dist/tools/fs/pdf.d.ts +70 -0
- package/dist/tools/fs/pdf.js +8 -2
- package/dist/tools/fs/repo-map.d.ts +10 -0
- package/dist/tools/fs/safety.d.ts +376 -0
- package/dist/tools/fs/search.d.ts +131 -0
- package/dist/tools/loop-tick.d.ts +24 -0
- package/dist/tools/monitor.d.ts +55 -0
- package/dist/tools/scheduler-tools.d.ts +51 -0
- package/dist/tools/sql-adapters.d.ts +18 -0
- package/dist/tools/sql.d.ts +25 -0
- package/dist/tools/task-list.d.ts +77 -0
- package/dist/tools/todo.d.ts +8 -0
- package/dist/tools/web.d.ts +184 -0
- package/dist/tools/worktree.d.ts +81 -0
- package/package.json +2 -2
- package/dist/tools/gitea-issue.d.ts +0 -13
- package/dist/tools/gitea-issue.js +0 -75
|
@@ -22,33 +22,90 @@ export interface RegisterBackgroundBashInput extends TaskAccess {
|
|
|
22
22
|
toolUseId?: string;
|
|
23
23
|
id?: string;
|
|
24
24
|
now?: number;
|
|
25
|
+
/** (design/129 discipline): session-resident background bash — `owner` MUST be the
|
|
26
|
+
* sessionId (a later turn's fresh per-turn owner reaches it via `access.sessionId`). Survives the
|
|
27
|
+
* run teardown (settle/evict skip + dispose except-list); terminal anchor = `reapSessionBackground`. */
|
|
25
28
|
sessionScoped?: true;
|
|
29
|
+
/** design/116 §7 G2b: when set, the registry WATCHES the process (1s poll, increments spooled with a
|
|
30
|
+
* rolling bound) and fires ONE completion task-notification at the terminal state — the background-bash
|
|
31
|
+
* half of CC's LocalShellTask completion notify. Also flips TaskOutput to re-readable spool reads. */
|
|
26
32
|
onTerminal?: (notification: TaskNotificationPayload) => void;
|
|
33
|
+
/** CC 2.1.209 对齐批A A5: the task's OUTPUT FILE — the launch receipt advertises it and the watcher
|
|
34
|
+
* mirrors every polled increment into it (append-only, unbounded — unlike the rolling in-memory
|
|
35
|
+
* spool), so "Read the output file path" is a real alternative to TaskOutput. Terminal
|
|
36
|
+
* task-notifications carry the same path (`output_file`). Only meaningful with `onTerminal` (the
|
|
37
|
+
* watcher is the writer); callers create the file (empty) before registering. */
|
|
27
38
|
outputFile?: string;
|
|
28
39
|
}
|
|
29
40
|
export interface TaskPollOptions {
|
|
30
41
|
workflowStore?: WorkflowRunStore;
|
|
42
|
+
/** design/151 S1a: the durable agent ledger — a live-registry miss on an `a*` id falls back to it
|
|
43
|
+
* (terminal snapshot / honest cross-instance "running elsewhere"), behind {@link canAccessAgentRecord}. */
|
|
31
44
|
agentStore?: BackgroundAgentStore;
|
|
32
45
|
filter?: string;
|
|
46
|
+
/** design/116 W3 (CC TaskOutput `block`): wait until the task reaches a terminal state (or `timeoutMs`)
|
|
47
|
+
* instead of returning the instantaneous snapshot — saves the model blind re-poll turns. The TOOL layer
|
|
48
|
+
* defaults this to TRUE (CC 187 `block: default(!0)`, clay 拍 2026-07-02); registry callers pass it explicitly. */
|
|
33
49
|
block?: boolean;
|
|
50
|
+
/** Max wait for `block` (ms). Default 30s, capped at 600s (CC 187). */
|
|
34
51
|
timeoutMs?: number;
|
|
52
|
+
/** Abort signal — a blocked wait must stop when the tool call is cancelled. */
|
|
35
53
|
signal?: AbortSignal;
|
|
54
|
+
/** RB-220 — mirrors {@link import("./types.js").TaskSpec.oneShot} (see {@link TaskToolOptions.oneShot}
|
|
55
|
+
* for the full contract): forwarded to the background_agent lane's still-running poll body so it
|
|
56
|
+
* does not teach "you will be notified" when this run has no later turn to receive one. */
|
|
36
57
|
oneShot?: boolean;
|
|
58
|
+
/** design/158 S1 (RB-205-B 半): the offload store a CLIPPED background_agent result's full text
|
|
59
|
+
* spills to — the disclosure gains a `ReadToolResult` ref instead of the middle staying gone for
|
|
60
|
+
* good (see {@link import("./task-registry-agent.js").spillClippedAgentResult}). Absent (a
|
|
61
|
+
* deployment that never wired a tool-result store) ⇒ legal degrade, byte-identical to pre-S1 output. */
|
|
37
62
|
toolResultStore?: ToolResultStore;
|
|
38
63
|
}
|
|
39
64
|
export interface TaskStopOptions {
|
|
40
65
|
workflowStore?: WorkflowRunStore;
|
|
66
|
+
/** design/151 S1a: durable-ledger fallback for the stop face (an off-process row reads `not_local` —
|
|
67
|
+
* workflow-fallback parity — instead of a misleading not-found). */
|
|
41
68
|
agentStore?: BackgroundAgentStore;
|
|
42
69
|
}
|
|
43
70
|
export interface TaskToolOptions extends TaskAccess {
|
|
44
71
|
registry: TaskRegistry;
|
|
45
72
|
workflowStore?: WorkflowRunStore;
|
|
73
|
+
/** design/151 S1a: durable agent ledger — threads into pollTask/stopTask fallback reads. */
|
|
46
74
|
agentStore?: BackgroundAgentStore;
|
|
75
|
+
/** [1076]③d — the task's soft wall-clock deadline (absolute ms epoch), same source as the Bash
|
|
76
|
+
* foreground clamp (design/130 P2b). When present, a BLOCKING TaskOutput wait is clamped so it
|
|
77
|
+
* cannot eat the write-out window: the model gets an honest, visible clamp note instead of a
|
|
78
|
+
* silent 10-minute blind wait into the finalize wall (TB rs**: 9.1min poll = the exact tax).
|
|
79
|
+
* CC posture note (anchors/2.1.212/print-mode-drain.md): CC classifies WIND-DOWN waits, and its
|
|
80
|
+
* block cap rides per-query budgets — a deadline-aware wait is the sema equivalent on the tool face. */
|
|
47
81
|
deadlineMs?: () => number | undefined;
|
|
82
|
+
/** design/157 B17 S2 (fable 终判 D4) — whether a terminal <task-notification> is actually wired for
|
|
83
|
+
* this mount. Drives the composed description's notification sentence: the pre-S2 literal advertised
|
|
84
|
+
* the notification unconditionally, which was a false promise on deployments that never wired
|
|
85
|
+
* `taskNotification` (B17 方案查出的既有假广告). Default true (a direct public-API consumer keeps the
|
|
86
|
+
* historical wording); prepare-task passes the real wiring state. */
|
|
48
87
|
notificationWired?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* RB-220 — mirrors {@link import("./types.js").TaskSpec.oneShot}: this run has no later turn for an
|
|
90
|
+
* async background notification to land in (a headless `-p` process exits once the turn ends).
|
|
91
|
+
* Threaded into the background_agent lane's non-blocking/blocked-timeout "still running" poll body
|
|
92
|
+
* (see {@link import("./task-registry-agent.js").pollBackgroundAgentLane}), which otherwise taught
|
|
93
|
+
* "you will be notified when it completes" — the same failure form `run_workflow`'s launch note was
|
|
94
|
+
* fixed for (RB-215/run-workflow-tool.ts). Default undefined ⇒ byte-compat (pre-RB-220 wording).
|
|
95
|
+
*/
|
|
49
96
|
oneShot?: boolean;
|
|
97
|
+
/** design/158 S1 (RB-205-B 半): the offload store a CLIPPED background_agent result's full text
|
|
98
|
+
* spills to — see {@link TaskPollOptions.toolResultStore} (forwarded verbatim into `pollTask`).
|
|
99
|
+
* Absent ⇒ legal degrade, byte-identical to pre-S1 output. */
|
|
50
100
|
toolResultStore?: ToolResultStore;
|
|
51
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* RB-49 B-3 (2026-07-25): the row-metadata projection `getAccessibleTask` returns. Was spelled out as a
|
|
104
|
+
* hand-written literal in THREE places (this signature, the internal cast below, and the SendMessage
|
|
105
|
+
* consumer in agents/subagent.ts) with an identical field list — adding a row field meant editing three
|
|
106
|
+
* spots with zero compiler enforcement (the server [1622] / core [1640] projection-antipattern family).
|
|
107
|
+
* One exported name, three consumers, drift becomes a type error.
|
|
108
|
+
*/
|
|
52
109
|
export interface AccessibleTaskRow {
|
|
53
110
|
task_id: string;
|
|
54
111
|
type: SemaTaskHandle["type"];
|
|
@@ -63,17 +120,43 @@ export interface AccessibleTaskRow {
|
|
|
63
120
|
parentTaskId?: string;
|
|
64
121
|
parentSessionId?: string;
|
|
65
122
|
rootSessionId?: string;
|
|
123
|
+
/** RB-478 — the row's registration instant (the original spawn time for a first-cycle row): the
|
|
124
|
+
* revive projection needs it so a revive frame's `startedAt` anchors the ROW, not the wake call. */
|
|
66
125
|
createdAt?: number;
|
|
67
126
|
}
|
|
68
127
|
export declare class TaskRegistry {
|
|
69
128
|
private handles;
|
|
129
|
+
/** codex 终审 1.255 F1: observers of the design/129 session terminal anchor — `reapSessionBackground`
|
|
130
|
+
* fires each hook (swallow-guarded) AFTER reaping, so session-anchored side state (the session-scoped
|
|
131
|
+
* subagent retain ledger) releases on the SAME deployment call. Registered idempotently per consumer. */
|
|
70
132
|
private sessionReapHooks;
|
|
133
|
+
/** design/144 §1.2 (child gate): one-shot quiescence watchers keyed by OWNER — each set fires (and is
|
|
134
|
+
* removed) when that owner's running background-task count reaches zero. Populated by
|
|
135
|
+
* {@link onBackgroundQuiescence}; poked from every terminal transition / running-row eviction site.
|
|
136
|
+
* 1.284 C3: callbacks carry a REASON — "quiescent" (the count really reached zero) vs "evicted"
|
|
137
|
+
* (cap overflow dropped the watcher; the owner's tasks may still be running — the subscriber must
|
|
138
|
+
* NOT treat this as quiescence). */
|
|
71
139
|
private bgQuiescenceWatchers;
|
|
140
|
+
/** RB-463 — one host-callback isolation scope for this registry's five notification seams (reap terminal
|
|
141
|
+
* notifier, session-reap hooks, quiescence fire + cap-overflow eviction, terminal-once send). Same swallow
|
|
142
|
+
* as the five hand-written try/catches it replaced, now counted per site and readable for diagnostics. */
|
|
72
143
|
private readonly notifier;
|
|
144
|
+
/** RB-473 — the read face for this registry's CONTAINED host-callback failures (site → count).
|
|
145
|
+
* The registry has no deployment error sink of its own to disclose to (it is process-global,
|
|
146
|
+
* constructed before any RunnerDeps exists), so readability IS its disclosure grade: a deployment
|
|
147
|
+
* that suspects a broken observer polls this instead of grepping for silence. Empty on the
|
|
148
|
+
* healthy path. */
|
|
73
149
|
notifierFailureCounts(): ReadonlyArray<{
|
|
74
150
|
site: string;
|
|
75
151
|
count: number;
|
|
76
152
|
}>;
|
|
153
|
+
/** design/157 B13 一期(#coreView 解法,B13 档「私有成员解法」定稿): the MON+WF lane free functions'
|
|
154
|
+
* only seam back into the class — exactly the 5 `RegistryCore` members those two lanes' `this.*`
|
|
155
|
+
* calls actually reached (grep-verified, see task-registry-shared.ts's own doc comment). Declared
|
|
156
|
+
* AFTER `handles` (its `handles` field below is captured eagerly at construction, so `this.handles`
|
|
157
|
+
* must already be assigned); the 4 method arrows close over `this` lazily and don't share that
|
|
158
|
+
* ordering constraint. Two-期 extends this to `DurableAgentCore` (durable-agent 车道, per the B13
|
|
159
|
+
* 「私有成员解法」 note) without touching this shape. */
|
|
77
160
|
private readonly core;
|
|
78
161
|
durableAgentArmed(id: string): boolean;
|
|
79
162
|
durableAgentRowProbe(id: string): (() => Promise<boolean>) | undefined;
|
|
@@ -85,6 +168,10 @@ export declare class TaskRegistry {
|
|
|
85
168
|
unpin?(sessionId: string): unknown;
|
|
86
169
|
release(sessionId: string): Promise<void> | void;
|
|
87
170
|
};
|
|
171
|
+
/** design/151 §7.7 (F-13) — the row's mailbox dies with the row: a WINNING delete also drops
|
|
172
|
+
* the (scope, handle) mailbox (advisory — a mailbox fault never blocks the reap; an orphaned
|
|
173
|
+
* box is bounded by the mailbox's own `reap` policy). Structural face (drop only), so the
|
|
174
|
+
* deployment passes its `RunnerDeps.mailboxStore` directly. */
|
|
88
175
|
mailbox?: {
|
|
89
176
|
drop(scope: string, handle: string): Promise<void>;
|
|
90
177
|
};
|
|
@@ -101,6 +188,8 @@ export declare class TaskRegistry {
|
|
|
101
188
|
releaseDurableTranscriptAnchor(id: string): void;
|
|
102
189
|
bindBackgroundAgentSession(id: string, sessionId: string): void;
|
|
103
190
|
registerBackgroundAgent(input: RegisterBackgroundAgentInput): string;
|
|
191
|
+
/** #22 — persist this leg's org-memory admission verdict on the durable row (the cross-process
|
|
192
|
+
* revival's only carrier). See {@link recordBackgroundAgentOrgAdmissionLane}. */
|
|
104
193
|
recordBackgroundAgentOrgAdmission(id: string, verdict: import("./memory-admission.js").OwnOrgAdmissionVerdict): void;
|
|
105
194
|
parkBackgroundAgent(id: string, park: {
|
|
106
195
|
checkpointToken: string;
|
|
@@ -134,6 +223,10 @@ export declare class TaskRegistry {
|
|
|
134
223
|
agentStore: import("./background-agent-store.js").BackgroundAgentStore;
|
|
135
224
|
}, ticket: ParkedClaimTicket): Promise<boolean>;
|
|
136
225
|
finalizeParkedResume(id: string): void;
|
|
226
|
+
/** RB-425: `outcome.cycle` names the revive cycle this settle speaks for (absent = 0 = the original
|
|
227
|
+
* spawn cycle). A spawn leg never passes it; a caller that settles by LIFECYCLE AUTHORITY (reap /
|
|
228
|
+
* session release — "whatever is running under this row dies") passes the row's current cycle. See
|
|
229
|
+
* {@link settleBackgroundAgentLane} for why a stale stamp must be a no-op. */
|
|
137
230
|
settleBackgroundAgent(id: string, outcome: {
|
|
138
231
|
status: "completed" | "failed" | "killed";
|
|
139
232
|
result?: string;
|
|
@@ -147,7 +240,12 @@ export declare class TaskRegistry {
|
|
|
147
240
|
seq?: number;
|
|
148
241
|
cycle?: number;
|
|
149
242
|
}): "completed" | "failed" | "killed" | undefined;
|
|
243
|
+
/** design/164 — record one tool-lifecycle beat on a running background-agent row; see
|
|
244
|
+
* {@link noteBackgroundAgentActivityLane} for why the in-memory row needed a stall signal at all. */
|
|
150
245
|
noteBackgroundAgentActivity(id: string, now?: number): void;
|
|
246
|
+
/** design/164 — collect SESSION-SCOPED background agents that have gone silent for `staleMs`, the
|
|
247
|
+
* stall-based replacement for the retired wall-clock ceiling on that lane. Caller-supplied policy
|
|
248
|
+
* like every other retention knob here; see {@link reapStaleSessionBackgroundAgentsLane}. */
|
|
151
249
|
reapStaleSessionBackgroundAgents(staleMs: number, now?: number): number;
|
|
152
250
|
abortBackgroundAgentsForOwner(access: TaskAccess, opts?: {
|
|
153
251
|
skipSessionScoped?: boolean;
|
|
@@ -167,6 +265,9 @@ export declare class TaskRegistry {
|
|
|
167
265
|
suggestion?: string;
|
|
168
266
|
};
|
|
169
267
|
markRetainedContinuation(id: string): void;
|
|
268
|
+
/** ASYNC (revive arbitration) — the durable half is a guarded ownership claim on the row (awaited before the
|
|
269
|
+
* in-memory flip), so this leg and a cross-process claim arbitrate in one domain instead of both
|
|
270
|
+
* believing they own the cycle. See {@link reviveBackgroundAgentLane}. */
|
|
170
271
|
reviveBackgroundAgent(id: string, access: TaskAccess, abort?: AbortController): Promise<{
|
|
171
272
|
ok: true;
|
|
172
273
|
cycle: number;
|
|
@@ -186,7 +287,15 @@ export declare class TaskRegistry {
|
|
|
186
287
|
}): "completed" | "failed" | "killed" | undefined;
|
|
187
288
|
unmarkRetainedContinuation(id: string): void;
|
|
188
289
|
attachAgentNotify(id: string, notify: NonNullable<BackgroundAgentTaskHandle["notify"]>, cycle?: number): void;
|
|
290
|
+
/** RB-375 A1 — hang the reap-time terminal notifier on a live background-agent row (see
|
|
291
|
+
* {@link BackgroundAgentTaskHandle.onReapTerminal}). No-op on unknown/terminal rows: a row that
|
|
292
|
+
* already settled has its unwind (or the settle itself) owning the terminal story. */
|
|
189
293
|
attachAgentTerminalNotifier(id: string, fn: () => void): void;
|
|
294
|
+
/** RB-375 A1 — the child-unwind side of the terminal-notification once-latch: returns `true` when
|
|
295
|
+
* the CALLER now owns sending the terminal faces (and claims the latch), `false` when the reap
|
|
296
|
+
* sweep already sent them (the caller must stay silent — the registry row still takes the settle's
|
|
297
|
+
* payload/backfill either way; only the announcement is deduplicated). Unknown/GC'd row ⇒ `true`
|
|
298
|
+
* (no latch survives eviction; the L1-1 late-report posture is unchanged). */
|
|
190
299
|
claimAgentTerminalNotify(id: string): boolean;
|
|
191
300
|
deliverToRunningAgent(id: string, access: TaskAccess, notification: import("./task-notification.js").TaskNotificationPayload, opts?: {
|
|
192
301
|
priority?: import("./task-notification.js").SystemInjectionPriority;
|
|
@@ -200,59 +309,291 @@ export declare class TaskRegistry {
|
|
|
200
309
|
runningBackgroundAgentLabels(access: TaskAccess): string[];
|
|
201
310
|
private pollBackgroundAgent;
|
|
202
311
|
private stopBackgroundAgent;
|
|
312
|
+
/** design/151 §3.1d (HIGH-3): this process instance's durable-row writer identity (random per
|
|
313
|
+
* registry instance). A fallback read of a `running` row written by a DIFFERENT instance must
|
|
314
|
+
* never claim liveness — it serves the honest "outcome unknown here" instead. */
|
|
203
315
|
readonly writerId: string;
|
|
316
|
+
/** codex S1a F2 — the writer-liveness LEASE: while any armed durable row is running, one lazy
|
|
317
|
+
* unref'd interval bumps their `updatedAt` (an empty patch), so row age measures SILENCE, not
|
|
318
|
+
* run length. A `staleRunningMaxAgeMs` reap policy must therefore be ≫ this period (the store
|
|
319
|
+
* contract recommends ≥10min) — and even a premature flip self-heals: the real settle's
|
|
320
|
+
* read-back adopts the bumped rev and re-CASes the truth over the reaper's guess. */
|
|
321
|
+
/** codex 增量 R-1 — handles a reap sweep is CURRENTLY adjudicating (between its live-handle check
|
|
322
|
+
* and the delete/release outcome). A revive admitted inside that await window would race the
|
|
323
|
+
* conditional delete with its own durable transition still unflushed (old rev ⇒ the delete wins,
|
|
324
|
+
* the session is released under an ADMITTED resume, and the revive's queued write poisons on
|
|
325
|
+
* "gone"). Membership is synchronous on both sides, with three readers (the `claimingHandles` twin
|
|
326
|
+
* below carries the same fence set): reap marks BEFORE its terminal check, a revival lane refuses
|
|
327
|
+
* while marked (the row is being recycled — not_found is the honest answer), and the terminal-handle
|
|
328
|
+
* GC skips a marked id instead of evicting it. */
|
|
204
329
|
private reapingHandles;
|
|
330
|
+
/** design/151 §7.3 (F-8) — handles a revival lane is CURRENTLY claiming (between the claim-CAS
|
|
331
|
+
* decision and the revive registration/rollback). BOTH lanes are writers: the tier-3 SendMessage
|
|
332
|
+
* claim, and (since the retained revive started claiming its own row) the in-process retained-revive
|
|
333
|
+
* path, which holds the mark across its store round trip. Synchronous membership on both sides, the
|
|
334
|
+
* `reapingHandles` twin, with three readers: the reap sweep skips a mid-claim row (its rev is about
|
|
335
|
+
* to move), the sibling revival lane refuses one (`reviveBackgroundAgent` not_found), and the
|
|
336
|
+
* terminal-handle GC skips it — so the revival lanes, the reaper and the GC can never adjudicate the
|
|
337
|
+
* same handle concurrently in-process. */
|
|
205
338
|
private claimingHandles;
|
|
206
339
|
private durableHeartbeatTimer;
|
|
207
340
|
mintTaskId(type: SemaTaskType): string;
|
|
208
341
|
registerBackgroundBash(input: RegisterBackgroundBashInput): string;
|
|
342
|
+
/** Background output-file read exemption: true iff `canonicalPath` is EXACTLY the registered output
|
|
343
|
+
* file of a background bash row that (a) the caller can access (same owner/scope/session visibility as
|
|
344
|
+
* a TaskOutput poll — {@link canAccess}) and (b) was registered on the caller's OWN execution env —
|
|
345
|
+
* `env` identity is part of the match, same discipline as {@link retainedShellIds} /
|
|
346
|
+
* {@link sessionResidentShellIds}. A canonical path only names a file within ONE env's filesystem
|
|
347
|
+
* namespace: on a shared registry, a row minted on env A must never exempt a same-named outside-root
|
|
348
|
+
* file in env B's namespace (same session or not), so instance equality — never a string proxy — is
|
|
349
|
+
* required. The output file is minted by the ENGINE itself (createTempFile
|
|
350
|
+
* at spawn/adopt) in the OS temp dir — structurally outside the hands containment root — and its path
|
|
351
|
+
* is handed to the model in the launch receipt and the completion notification; Read consults this so
|
|
352
|
+
* it can honor that instruction without widening the root fence (exact registered file only, no
|
|
353
|
+
* directory/prefix admission). Membership dies with the row (per-run evict / session reap / terminal
|
|
354
|
+
* GC), so the exemption never outlives the task's addressability. Exact string compare: both sides are
|
|
355
|
+
* `canonicalPath` outputs for the same env, so a symlinked temp dir cannot cause a miss or a false hit. */
|
|
209
356
|
isBackgroundOutputFile(canonicalPath: string, access: TaskAccess, env: unknown): boolean;
|
|
357
|
+
/** [c209-D] codex R1: display-cap-free EXACT id lookup with the same access guard as a poll — identity
|
|
358
|
+
* resolution must NEVER ride the display-capped `list()` (with >LIMIT visible rows the cap can evict
|
|
359
|
+
* the addressed id, and a name-layer fallback then MISROUTES the message to a同名 row instead of an
|
|
360
|
+
* honest not-found). Unknown and out-of-scope ids read identically (info-hiding, undefined both). */
|
|
210
361
|
getAccessibleTask(taskId: string, access: TaskAccess): AccessibleTaskRow | undefined;
|
|
362
|
+
/** design/134 §3.3 (R3 single-source): record WHO is about to kill `id`, at the initiation site,
|
|
363
|
+
* BEFORE the abort()/status flip — the ordering is load-bearing: the guard below refuses markers on a
|
|
364
|
+
* non-running handle, so a caller that flips first loses its claim and attribution falls back to
|
|
365
|
+
* "system". First-marker-wins: an earlier marker (e.g. a service-wire "user") is never overwritten.
|
|
366
|
+
* Applies to background_agent AND background_bash (same class); workflow cancellation is out of scope. */
|
|
211
367
|
markStopSource(id: string, source: StopSource): void;
|
|
368
|
+
/**
|
|
369
|
+
* [1712] / RB-164 — attribute an ENV-LEVEL blanket sweep before it runs.
|
|
370
|
+
*
|
|
371
|
+
* The incident: a user's `run_in_background` Bash died mid-run reporting `stopped-by:"system"` with a
|
|
372
|
+
* zero-byte output file, and diagnosing it took a cross-repo investigation with a timeline argument.
|
|
373
|
+
* `"system"` is not a cause — it is the DEFAULT, i.e. the signature of a kill that never passed through
|
|
374
|
+
* this registry. Every kill that does pass through records who did it; `disposeBackgroundShells` lives in
|
|
375
|
+
* the execution-env layer, cannot reach the registry, and so left the one class of kill a user actually
|
|
376
|
+
* notices as the only one with no attribution at all.
|
|
377
|
+
*
|
|
378
|
+
* This marks every background_bash row on `env` that the sweep is about to take, so the row the user
|
|
379
|
+
* reads says what happened to it. `except` mirrors the sweep's own keep-list exactly — a spared shell
|
|
380
|
+
* must not be marked, or the next reader would be told a live process had been killed.
|
|
381
|
+
*
|
|
382
|
+
* Attribution only: it never kills anything. The caller has already demonstrated kill capability on the
|
|
383
|
+
* env, which is why there is no access guard (same reasoning as {@link markStopSourceByShellId}).
|
|
384
|
+
*/
|
|
212
385
|
markStopSourceForEnvSweep(env: unknown, source: StopSource, except?: readonly string[]): string[];
|
|
386
|
+
/** design/134 KNOWN-ISSUES close-out (env-direct TaskStop): the stop-source annotation face
|
|
387
|
+
* addressed by the ENV-level shellId — for a kill initiator that holds only the env handle (the
|
|
388
|
+
* registry-less TaskStop band) and is about to `env.killBackground` directly, i.e. without going
|
|
389
|
+
* through {@link stopTask}. Resolves the shellId → unified task id and delegates to
|
|
390
|
+
* {@link markStopSource}, so the running-only + first-marker-wins guards hold unchanged.
|
|
391
|
+
* ⚠️ `env` is REQUIRED for any effect (RB-479-A②, 5.0.0): a shellId without its env is ambiguous
|
|
392
|
+
* by construction on a shared registry, so an env-less call is a NO-OP — this marker is
|
|
393
|
+
* best-effort attribution, not data. No access guard — attribution only (never kills); the
|
|
394
|
+
* caller already demonstrated kill capability on the env. */
|
|
213
395
|
markStopSourceByShellId(shellId: string, source: StopSource, env?: unknown): void;
|
|
396
|
+
/** Withdraw a pending stop-source marker after the kill it announced FAILED (小优化批 2026-07-13):
|
|
397
|
+
* a marker left by a failed env-direct kill would win first-marker-wins against the NEXT, real stopper
|
|
398
|
+
* (e.g. a later user TaskStop reads "parent"). Clears ONLY the exact still-pending marker the caller
|
|
399
|
+
* minted — same (shellId, env) resolution as {@link markStopSourceByShellId}; a row already settled,
|
|
400
|
+
* or carrying a different source, is left alone. */
|
|
214
401
|
clearPendingStopSourceByShellId(shellId: string, source: StopSource, env?: unknown): void;
|
|
402
|
+
/** design/134 §3.3: narrow terminal read for consumers (subagent sinkEmit/notify) — only a KILLED row
|
|
403
|
+
* has an attribution; "system" is the defensive floor for a row that went killed without a landed
|
|
404
|
+
* stoppedBy (e.g. env-direct flips). Returns undefined for running/completed/failed/evicted rows. */
|
|
215
405
|
getStopAttribution(id: string): StopSource | undefined;
|
|
406
|
+
/** P1-3 — the fill-once completion correlation id (see {@link UnifiedTaskOutput.completionId}), for a
|
|
407
|
+
* notification-construction call site that already has the task's `id` and needs to attach it to the
|
|
408
|
+
* payload it is building. Deliberately NOT restricted to a subset of task types (unlike
|
|
409
|
+
* {@link getStopAttribution}) — `completionId` lives on the shared {@link SemaTaskHandle} base and
|
|
410
|
+
* every registered task kind, workflow included, carries it the same way. Undefined until the task's
|
|
411
|
+
* own settle point has run ({@link mintCompletionId}), or for an id this registry never held. */
|
|
216
412
|
getCompletionId(id: string): string | undefined;
|
|
413
|
+
/** Bulk stop-source attribution for one owner — the registry-side primitive that
|
|
414
|
+
* replaces the service's `list()+markStopSource` per-row loop, which had TWO holes: ① `list()` didn't
|
|
415
|
+
* expose `sessionScoped`, so on the resume leg (canonical taskId==sessionId, rebuilt taskConfig without
|
|
416
|
+
* spec.taskId) task-scoped and session-scoped children share the same owner KEY VALUE and can't be told
|
|
417
|
+
* apart; ② `list()`'s 500-row display cap silently skipped rows on >500-children runs.
|
|
418
|
+
* Same owner-filter semantics as {@link abortBackgroundAgentsForOwner}: {@link canAccess} + the EXPLICIT
|
|
419
|
+
* `sessionScoped` flag (design/129 — never inferred from key values), over a DIRECT handle-map walk
|
|
420
|
+
* (no list() cap in the path). Covers every markable kind ({@link markStopSource}'s own set:
|
|
421
|
+
* background_agent / background_bash / monitor); each row is delegated to `markStopSource`, so the
|
|
422
|
+
* running-only + first-marker-wins guards hold unchanged — an existing claim is never overwritten.
|
|
423
|
+
* Returns how many rows NEWLY took the marker (already-marked / non-running rows don't count). */
|
|
217
424
|
markStopSourceForOwner(access: TaskAccess, source: StopSource, opts?: {
|
|
218
425
|
skipSessionScoped?: boolean;
|
|
219
426
|
}): number;
|
|
427
|
+
/** The run-teardown KILLED-receipt producer for the SHELL lanes (background_bash + per-run
|
|
428
|
+
* monitor). The runner teardown disposes the processes (`disposeBackgroundShells`) and evicts the rows
|
|
429
|
+
* (`clearBackgroundForOwner`) — after which NO producer can ever mint the killed notification: the bash
|
|
430
|
+
* watcher's next poll sees a vanished shell ("nothing to notify about") or its evicted handle and just
|
|
431
|
+
* stops. So a mid-turn abort (or a normal turn end) silently swallowed children the model had been
|
|
432
|
+
* promised notifications for ("You will be notified when it completes — do not poll"). The AGENT lane
|
|
433
|
+
* already has its producer (the child promise's settle → notify); this is the same receipt for
|
|
434
|
+
* the shell lanes — call it BEFORE dispose/evict so the sink chain (onTerminal/onEvent → the run's
|
|
435
|
+
* notification wrapper, whose lane is already down at teardown) PARKS the receipt on the per-session
|
|
436
|
+
* pending store and the session's next run drains it (the pending lane, one shape for all producers).
|
|
437
|
+
*
|
|
438
|
+
* Attribution (design/134 §3.3): `markStopSource(source)` first — first-marker-wins, so a deployment's
|
|
439
|
+
* earlier explicit mark (e.g. a service-wire "user" on abort) is never overwritten; `stoppedBy` then
|
|
440
|
+
* lands from the marker. Rows without a sink still settle (registry truth), they just have no receipt
|
|
441
|
+
* to send. Session-scoped rows are skipped under `skipSessionScoped` (they outlive the turn; their
|
|
442
|
+
* terminal anchor is `reapSessionBackground`). KNOWN small race, recorded: a child that exited within
|
|
443
|
+
* the last watcher-poll interval (~1s) but whose exit the watcher hasn't observed yet still reads
|
|
444
|
+
* "running" here and is settled `killed` — the receipt is at worst one status coarser, never silent.
|
|
445
|
+
*
|
|
446
|
+
* codex 1.257.3 review (HIGH): the settle EXECUTES the kill itself (await `killBackground`, Result-typed)
|
|
447
|
+
* before minting the receipt — previously the receipt claimed "killed" while the actual kill was left to
|
|
448
|
+
* the later `disposeBackgroundShells`, whose failure was swallowed (process alive + registry cleared =
|
|
449
|
+
* the receipt lied). A failed kill now mints an HONEST receipt naming the failure (the env dispose is
|
|
450
|
+
* still the idempotent backstop). Returns how many rows were settled. */
|
|
220
451
|
settleKilledForOwner(access: TaskAccess, opts?: {
|
|
221
452
|
source?: StopSource;
|
|
222
453
|
skipSessionScoped?: boolean;
|
|
223
454
|
envDying?: boolean;
|
|
455
|
+
/** Spec-level retain (`TaskSpec.retainBackgroundProcesses`): treat every shell-lane row as if its
|
|
456
|
+
* env had declared retain — skip entirely (no kill, no killed receipt: nothing died, a receipt
|
|
457
|
+
* would lie). Same `envDying` exception as the env-capability gate: retain on a dying owned env
|
|
458
|
+
* is illusory, so those rows still settle with the honest killed receipt. */
|
|
224
459
|
retainProcesses?: boolean;
|
|
225
460
|
}): Promise<number>;
|
|
461
|
+
/** A-005.4/5: the best-effort kill `reapSessionBackground`'s monitor/background_bash arms fire is
|
|
462
|
+
* fire-and-forget by DESIGN (the reap is synchronous and settles the row regardless of the kill
|
|
463
|
+
* outcome — see the callers) but was fire-and-FORGET-the-evidence-too: a resolved `{ok:false}` was
|
|
464
|
+
* never read, and even a promise rejection landed on `.catch(() => undefined)`. Reads the Result,
|
|
465
|
+
* drops the benign `not_found` case (already dead — same filter the awaited TaskStop kill path uses,
|
|
466
|
+
* see `killFailed` above), and routes anything else through `shutdownDebug` — the SAME kill-path
|
|
467
|
+
* forensics channel the row-scoped calls right above these call sites already use for this reap, so
|
|
468
|
+
* a `SEMA_DEBUG_SHUTDOWN=1` "who killed my process" hunt no longer dead-ends at a silently-swallowed
|
|
469
|
+
* reap-time failure. Never throws (a forensics call must not fault the reap it is reporting on). */
|
|
470
|
+
private reportSessionReapKillFailure;
|
|
471
|
+
/** design/129: the session-scoped children's TERMINAL anchor — call from your session release/sweep.
|
|
472
|
+
* Aborts every running session-scoped background child registered under `sessionId` and settles it
|
|
473
|
+
* `killed` (the child's own catch/then would also classify the abort as killed; this makes the registry
|
|
474
|
+
* state immediate rather than waiting on the child's promise). Idempotent.
|
|
475
|
+
* RETAINED shell-lane rows are EXEMPT: under the deliver-a-living-service contract a retained daemon
|
|
476
|
+
* outlives the session release — its only terminals are explicit TaskStop, its own process exit (the
|
|
477
|
+
* watcher mints that receipt), and env destruction (the multi-tenant leak backstop). The engine-exit
|
|
478
|
+
* reap ({@link reapAllSessionBackground}) delegates here, so it inherits the same exemption.
|
|
479
|
+
* RB-375 A3 — RETURN-VALUE semantics: the count covers DIRECT hits of this sweep only (rows whose
|
|
480
|
+
* own arm above matched). Children the reaped agents themselves spawned (`sessionScoped:false`
|
|
481
|
+
* grandchildren) die COLLATERALLY, via each reaped agent's own teardown
|
|
482
|
+
* (`abortBackgroundAgentsForOwner` in the child's unwind) — this function never sees those rows,
|
|
483
|
+
* so they are NOT counted here.
|
|
484
|
+
* RB-375 A1 — a directly reaped `background_agent` row's terminal notification is sent
|
|
485
|
+
* SYNCHRONOUSLY by this sweep (through the spawn-lane-hung {@link BackgroundAgentTaskHandle.onReapTerminal},
|
|
486
|
+
* once-latched against the child's own unwind), so consumers observe the terminal immediately
|
|
487
|
+
* instead of after the in-flight tool honors the abort (unbounded). */
|
|
226
488
|
reapSessionBackground(sessionId: string, scope?: string): number;
|
|
489
|
+
/** The FULL-registry reap for the ENGINE's own exit path. TOC form:
|
|
490
|
+
* the engine process IS the session terminal (the shell has no line to call — live evidence:
|
|
491
|
+
* detached bg children reparent to PID 1 and outlive the engine), so the engine's SIGHUP/SIGTERM/
|
|
492
|
+
* normal-exit terminus calls THIS. Enumerates every running session-scoped row's (sessionId, scope)
|
|
493
|
+
* pair — `owner` = the sessionId by design/129 discipline for background_bash/monitor/background_agent
|
|
494
|
+
* (RB-215 note: NOT for workflow, whose `owner` is the launching LEG's taskId; its session anchor is
|
|
495
|
+
* `originatingSessionId` — see {@link reapSessionBackground}'s own workflow arm for why) — and runs
|
|
496
|
+
* the per-session reap on each pair; retain-declared envs keep their processes (rows settle only),
|
|
497
|
+
* exactly like the per-session anchor. Timing discipline: call at the hardShutdown TERMINUS, never at
|
|
498
|
+
* drain start — an in-flight turn may still be TaskOutput-following a bg process. Returns total rows
|
|
499
|
+
* reaped. */
|
|
227
500
|
reapAllSessionBackground(): number;
|
|
501
|
+
/** codex 终审 1.255 F1 — subscribe to `reapSessionBackground` (the design/129 session terminal anchor).
|
|
502
|
+
* Returns an unsubscribe. Hooks are best-effort observers; a throwing hook is swallowed. */
|
|
228
503
|
onSessionReap(hook: (sessionId: string, scope?: string) => void): () => void;
|
|
504
|
+
/** design/144 §1.2 — the child gate's liveness read: how many BACKGROUND tasks (bg bash / monitor /
|
|
505
|
+
* bg agent) registered under EXACTLY this owner key are still running. Deliberately an owner-equality
|
|
506
|
+
* walk, NOT {@link canAccess}: an owner-less handle is world-*readable* but attributable to nobody —
|
|
507
|
+
* counting it against every owner would park every parent's completion frame behind a stranger's task.
|
|
508
|
+
* Workflow rows are out of the gate's task class by design (§1.2 names bg bash/monitor/grandchild
|
|
509
|
+
* agents; a workflow's terminal already notifies on its own lane). */
|
|
229
510
|
countRunningBackgroundForOwner(owner: string): number;
|
|
511
|
+
/** design/144 §1.2 — hard cap on concurrently watched owners (each parked parent notification holds
|
|
512
|
+
* exactly one watcher; the retain-ledger caps bound this in practice — the cap is a defensive floor).
|
|
513
|
+
* 1.284 C3: overflow notifies the OLDEST owner's watchers with reason "evicted" (CANCELLATION
|
|
514
|
+
* semantics, not a fake quiescence — the pre-fix synchronous no-arg fire read as "count reached
|
|
515
|
+
* zero" while the owner's tasks were still running, an early FALSE completion). The subscriber
|
|
516
|
+
* decides its own degradation (the child gate delivers its parked frame immediately, undecorated —
|
|
517
|
+
* 宁发勿丢); a silently leaked/never-fired watcher would lose the frame forever. */
|
|
230
518
|
private static readonly BG_QUIESCENCE_WATCHERS_MAX;
|
|
519
|
+
/** design/144 §1.2 (child gate, 补发钩子) — subscribe a ONE-SHOT callback fired when `owner`'s running
|
|
520
|
+
* background-task count reaches zero (reason "quiescent"). Exactly-once discipline for the N-children
|
|
521
|
+
* race: every terminal transition pokes, only the poke that OBSERVES count==0 fires, and firing removes
|
|
522
|
+
* the whole owner set first (count-zero judgement + once latch). NEVER fires synchronously from this
|
|
523
|
+
* call — the caller checks the count itself in the same synchronous block (count > 0 → subscribe; no
|
|
524
|
+
* await between, so no missed-settle window). 1.284 C3: a cap-overflow eviction fires the victims with
|
|
525
|
+
* reason "evicted" instead, and ASYNCHRONOUSLY (queueMicrotask) — the new watcher is installed before
|
|
526
|
+
* any victim runs, closing the re-entrant window where a victim's callback observed a half-updated map.
|
|
527
|
+
* Returns an unsubscribe. Callbacks are swallow-guarded observers. */
|
|
231
528
|
onBackgroundQuiescence(owner: string, cb: (reason: "quiescent" | "evicted") => void): () => void;
|
|
529
|
+
/** design/144 §1.2 — poke the quiescence watchers of `owner` after a terminal transition (or a
|
|
530
|
+
* running-row eviction). Cheap no-op without watchers; fires + removes the owner's whole set only
|
|
531
|
+
* when the running count is zero (the LAST settling task's poke wins — count-zero judgement). */
|
|
232
532
|
private pokeBgQuiescence;
|
|
533
|
+
/** fidelity R1-3: the terminal-notification once-latch. Checks-and-sets BEFORE sending (single-threaded,
|
|
534
|
+
* no await between check and set — atomic), so a racing producer pair (a teardown settle vs an in-flight
|
|
535
|
+
* watcher tick that passed its status gate before the settle landed) emits exactly ONE terminal notice.
|
|
536
|
+
* The latch stays set even if the sink throws — a faulty sink must not re-arm it. */
|
|
233
537
|
private notifyTerminalOnce;
|
|
538
|
+
/** G2b watcher (design/116 §7): 1s poll loop that spools increments (rolling bound) and fires ONE
|
|
539
|
+
* completion notification at the terminal state. `unref()`d — a watcher never keeps the process alive.
|
|
540
|
+
* Stops itself on terminal, on a vanished shell (env disposed), or when the handle is evicted. */
|
|
234
541
|
private startBashWatcher;
|
|
542
|
+
/** design/135 G2: register a spawned background process as a MONITOR — the watcher polls at the batch
|
|
543
|
+
* window (200ms), turns each completed stdout line into an event, batches lines within one tick into
|
|
544
|
+
* ONE notification, enforces the non-persistent timeout, auto-stops an event storm, and fires exactly
|
|
545
|
+
* one terminal notification (exit code / timeout / auto-stop / env-side kill). */
|
|
546
|
+
/** The shells a run teardown must LEAVE ALIVE: running SESSION-scoped monitors of this
|
|
547
|
+
* session on THIS env (their whole point is outliving the turn; the env-wide dispose would otherwise
|
|
548
|
+
* orphan the watch — handle alive, process dead, watcher reporting a bogus env-death terminal). Env
|
|
549
|
+
* identity is part of the match so a shared registry never exempts another env's ids. */
|
|
235
550
|
sessionResidentShellIds(sessionId: string, env: unknown): BackgroundShellId[];
|
|
551
|
+
/** The OTHER shells a run teardown must leave alive: NON-persistent monitors still inside
|
|
552
|
+
* their timeout window, on THIS env. CC semantics: Monitor(persistent:false) lives to timeout_ms — the
|
|
553
|
+
* parent run ending is not an exit (timeout / process exit / TaskStop are). Deliberately NO owner
|
|
554
|
+
* filter: on a shared env an earlier run's (or another session's) in-window watch must survive this
|
|
555
|
+
* run's env-wide dispose too. Env identity stays part of the match, same as
|
|
556
|
+
* {@link sessionResidentShellIds} (a shared registry never exempts another env's ids). */
|
|
236
557
|
timeoutResidentShellIds(env: unknown): BackgroundShellId[];
|
|
558
|
+
/** The THIRD dispose except-list lane: RETAINED shells (the settle sweep's deliver-a-living-service
|
|
559
|
+
* mark) still running on THIS env. Deliberately NO owner filter, same as
|
|
560
|
+
* {@link timeoutResidentShellIds}: on a shared static env a LATER task's env-wide teardown dispose
|
|
561
|
+
* must not reap an EARLIER task's delivered daemon (that task's own teardown skipped the dispose;
|
|
562
|
+
* the next run's sweep was the remaining kill path). Env identity stays part of the match
|
|
563
|
+
* (a shared registry never exempts another env's ids). */
|
|
237
564
|
retainedShellIds(env: unknown): BackgroundShellId[];
|
|
238
565
|
registerMonitor(input: RegisterMonitorInput): string;
|
|
239
566
|
registerWorkflow(input: RegisterWorkflowInput): string;
|
|
240
567
|
pollTask(id: string, access: TaskAccess, opts?: TaskPollOptions): Promise<UnifiedTaskResult>;
|
|
241
568
|
stopTask(id: string, access: TaskAccess, opts?: TaskStopOptions): Promise<UnifiedTaskResult>;
|
|
569
|
+
/** S2b codex R8 — bounded delivery-confirmation wait (see deliverToRunningAgent). Test-tunable. */
|
|
242
570
|
deliverConfirmTimeoutMs: number;
|
|
243
571
|
private lastGcAt;
|
|
572
|
+
/**
|
|
573
|
+
* 预清(飞轮 /tasks + footer pill 的数据源正道): list the caller's OWN tasks as a bounded DISPLAY
|
|
574
|
+
* projection — never the internal handles (no shellId/env/abort). Same owner/scope guard as poll/stop;
|
|
575
|
+
* a caller only ever sees its own tasks. Sorted newest-first, capped at `limit` (default 50).
|
|
576
|
+
* CC parity note: CC's /tasks is a UI/SDK surface, NOT an LLM tool — expose this via SDK/service,
|
|
577
|
+
* do not mount it as a model tool by default.
|
|
578
|
+
*/
|
|
244
579
|
list(access: TaskAccess, opts?: {
|
|
245
580
|
limit?: number;
|
|
246
581
|
}): Array<{
|
|
247
582
|
task_id: string;
|
|
248
583
|
type: SemaTaskType;
|
|
249
584
|
status: SemaTaskStatus;
|
|
585
|
+
/** design/129 lifetime flag, surfaced for observability — on resume-leg deployments the
|
|
586
|
+
* canonical taskId==sessionId, so task- and session-scoped rows share an owner KEY VALUE and only this
|
|
587
|
+
* explicit flag tells them apart. Bulk attribution should use {@link markStopSourceForOwner}, not a
|
|
588
|
+
* list()-driven loop (the 500-row cap). */
|
|
250
589
|
sessionScoped: boolean;
|
|
251
590
|
description?: string;
|
|
252
591
|
toolUseId?: string;
|
|
253
592
|
createdAt: number;
|
|
254
593
|
updatedAt: number;
|
|
255
594
|
}>;
|
|
595
|
+
/** Throttled {@link gc} for hot-path callers (design/115 review B5): prepare-task runs once per task,
|
|
596
|
+
* and a full-map sweep per prepare is pure overhead — sweep at most once per minute. */
|
|
256
597
|
maybeGc(now?: number): number;
|
|
257
598
|
gc(now?: number, terminalTtlMs?: number): number;
|
|
258
599
|
clearBackgroundForOwner(access: TaskAccess): number;
|
|
@@ -260,6 +601,8 @@ export declare class TaskRegistry {
|
|
|
260
601
|
private pollBackgroundBash;
|
|
261
602
|
private pollWorkflow;
|
|
262
603
|
private stopBackgroundBash;
|
|
604
|
+
/** design/135 G2: TaskOutput over a monitor — a RE-READABLE spool snapshot (the watcher owns the env
|
|
605
|
+
* cursor, exactly the bash G2b spool posture): repeated polls return the same accumulated output. */
|
|
263
606
|
private pollMonitor;
|
|
264
607
|
private stopMonitor;
|
|
265
608
|
private stopWorkflow;
|
|
@@ -480,6 +480,17 @@ export class TaskRegistry {
|
|
|
480
480
|
}
|
|
481
481
|
return settled;
|
|
482
482
|
}
|
|
483
|
+
async reportSessionReapKillFailure(kind, handle) {
|
|
484
|
+
try {
|
|
485
|
+
const kill = await handle.env.killBackground(handle.shellId);
|
|
486
|
+
if (!kill.ok && kill.error.code !== "not_found") {
|
|
487
|
+
shutdownDebug("session reap: kill failed", { kind, id: handle.id, shellId: handle.shellId, code: kill.error.code });
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
catch (err) {
|
|
491
|
+
shutdownDebug("session reap: kill threw", { kind, id: handle.id, shellId: handle.shellId, error: err instanceof Error ? err.message : String(err) });
|
|
492
|
+
}
|
|
493
|
+
}
|
|
483
494
|
reapSessionBackground(sessionId, scope) {
|
|
484
495
|
const access = { owner: sessionId, sessionId, ...(scope !== undefined ? { scope } : {}) };
|
|
485
496
|
let reaped = 0;
|
|
@@ -494,7 +505,7 @@ export class TaskRegistry {
|
|
|
494
505
|
handle.watcher = undefined;
|
|
495
506
|
}
|
|
496
507
|
if (handle.env.backgroundCapabilities.retainBackgroundProcesses !== true) {
|
|
497
|
-
void
|
|
508
|
+
void this.reportSessionReapKillFailure("monitor", handle);
|
|
498
509
|
}
|
|
499
510
|
handle.status = "killed";
|
|
500
511
|
handle.stoppedBy = handle.stopSource ?? "system";
|
|
@@ -511,7 +522,7 @@ export class TaskRegistry {
|
|
|
511
522
|
handle.watcher = undefined;
|
|
512
523
|
}
|
|
513
524
|
if (handle.env.backgroundCapabilities.retainBackgroundProcesses !== true) {
|
|
514
|
-
void
|
|
525
|
+
void this.reportSessionReapKillFailure("background_bash", handle);
|
|
515
526
|
}
|
|
516
527
|
handle.status = "killed";
|
|
517
528
|
handle.stoppedBy = handle.stopSource ?? "system";
|
|
@@ -15,16 +15,60 @@ export declare const TASK_STOP_PARAMS: Type.TObject<{
|
|
|
15
15
|
task_id: Type.TOptional<Type.TString>;
|
|
16
16
|
shell_id: Type.TOptional<Type.TString>;
|
|
17
17
|
}>;
|
|
18
|
+
/**
|
|
19
|
+
* Trims and skips blank/whitespace-only candidates, returning the first non-blank string among `values`.
|
|
20
|
+
* RB-479-A①: callers pass ONLY the tool's declared id parameters (TaskOutput: task_id; TaskStop:
|
|
21
|
+
* task_id, shell_id) — an id smuggled under any other key falls to the loud missing-parameter refusal.
|
|
22
|
+
* The trim/skip-blank behavior stays (a whitespace-only id reports the same missing-parameter text as an
|
|
23
|
+
* absent one, instead of falling through to a not-found lookup on the literal " ").
|
|
24
|
+
*/
|
|
18
25
|
export declare function resolveTaskIdArg(...values: unknown[]): string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* design/157 B17 (S2) — the declaration face is a FUNCTION OF CAPABILITY (fable 终判 D3/D4/D6): what the
|
|
28
|
+
* tool advertises to the model must match what the mount can actually do. A flag is true only when the
|
|
29
|
+
* deployment really delivers that behavior; every composed sentence below is gated on the flag it
|
|
30
|
+
* describes, so no mount ever advertises a file path that is never written, a notification that never
|
|
31
|
+
* fires, a wait that never blocks, or name addressing that never resolves.
|
|
32
|
+
*/
|
|
19
33
|
export interface TaskToolCapabilities {
|
|
34
|
+
/** The unified registry face: workflow-task support + own-scope fencing (registry mounts only). */
|
|
20
35
|
lanes: boolean;
|
|
36
|
+
/** Bash(run_in_background)'s launch receipt carries the output file path (registry mounts only). */
|
|
21
37
|
outputFile: boolean;
|
|
38
|
+
/** A terminal <task-notification> fires when the task completes — true only when the deployment
|
|
39
|
+
* actually wired `taskNotification` (B17 方案查出的既有假广告: the registry mount used to advertise
|
|
40
|
+
* this unconditionally; prepare-task now passes the real wiring state). */
|
|
22
41
|
notification: boolean;
|
|
42
|
+
/** TaskOutput block/timeout wait semantics (registry pollTask; the env-direct poll is instantaneous). */
|
|
23
43
|
blockWait: boolean;
|
|
44
|
+
/** TaskStop accepts a background agent's spawn NAME as task_id (registry name resolution only). */
|
|
24
45
|
nameAddressing: boolean;
|
|
25
46
|
}
|
|
47
|
+
/** Full-capability profile = the registry-backed mount with notifications wired (CC-209 verbatim form). */
|
|
26
48
|
export declare const REGISTRY_TASK_TOOL_CAPS: TaskToolCapabilities;
|
|
49
|
+
/** The env-direct thin-shell profile: cursor polling over a background shell, nothing else. */
|
|
27
50
|
export declare const ENV_DIRECT_TASK_TOOL_CAPS: TaskToolCapabilities;
|
|
51
|
+
/**
|
|
52
|
+
* TaskOutput description, composed per capability. With every flag true this reproduces the registry's
|
|
53
|
+
* pre-S2 literal byte-for-byte — the first two sentences are the CC 2.1.209 A5 deprecated form
|
|
54
|
+
* (209-verbatim except the task-type names, mapped to sema's lanes; divergence-logged; the anchor
|
|
55
|
+
* commentary lives at the registry factory). With `notification` false the <task-notification> half is
|
|
56
|
+
* honestly omitted and the cursor-polling guidance (the env side's long-standing wording) is composed in
|
|
57
|
+
* instead — completion must then be detected by status, and SAYING so is the capability-honest guidance.
|
|
58
|
+
*/
|
|
28
59
|
export declare function composeTaskOutputDescription(caps: TaskToolCapabilities): string;
|
|
60
|
+
/**
|
|
61
|
+
* TaskStop description, composed per capability. All-true reproduces the registry literal (CC206-B 欠账:
|
|
62
|
+
* the named-agent bullet is CC-verbatim; CC's teammate bullet stays honestly omitted — sema's team face is
|
|
63
|
+
* in-process, not registry-addressable); `nameAddressing:false` drops exactly that bullet (the env shell
|
|
64
|
+
* has no agent-name resolution), which reproduces the env-direct literal.
|
|
65
|
+
*/
|
|
29
66
|
export declare function composeTaskStopDescription(caps: TaskToolCapabilities): string;
|
|
67
|
+
/**
|
|
68
|
+
* TaskOutput params, composed per capability (fable 终判 D3 — an advertised parameter the execute body
|
|
69
|
+
* ignores is a lie): block/timeout enter the schema only where the poll can actually wait
|
|
70
|
+
* (design/116 W3 — CC TaskOutput block/timeout; sema block default documented as true, CC-parity).
|
|
71
|
+
* Canonical surface stays design/115 review S-3: task_id + sema-delta filter — and (RB-479-A①) the
|
|
72
|
+
* declared surface is also the RESOLVED surface; no undeclared id key is read.
|
|
73
|
+
*/
|
|
30
74
|
export declare function composeTaskOutputParams(caps: Pick<TaskToolCapabilities, "blockWait" | "lanes">): ReturnType<typeof Type.Object>;
|
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
import type { TaskSpec } from "./types.js";
|
|
2
|
+
/** Thrown when `overrides` would LOOSEN a safety field `base` already set (a tighten-only violation). */
|
|
2
3
|
export declare class TaskSpecTightenError extends Error {
|
|
3
4
|
constructor(message: string);
|
|
4
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Merge `overrides` onto `base` with TIGHTEN-ONLY semantics for the safety-bearing fields. Non-safety fields
|
|
8
|
+
* follow plain last-wins object spread (`overrides` value wins when present, else `base`). The safety fields
|
|
9
|
+
* get explicit rules:
|
|
10
|
+
*
|
|
11
|
+
* - **`toolPolicy`** — both set ⇒ `combinePolicies(base, override)` (deny-wins; the base's denials survive,
|
|
12
|
+
* the override can only ADD denials/asks). Either alone ⇒ that one. This is the central fix: a blind spread
|
|
13
|
+
* would drop the base policy entirely.
|
|
14
|
+
* - **`handsReadOnly`** — `true` is stricter. `base:true` + `override:false` ⇒ **throw** (loosening). Otherwise
|
|
15
|
+
* the stricter (`true` if either is true) wins.
|
|
16
|
+
* - **`shellGate`** — `off < classify < always`. `override` may only equal-or-raise the rank; lowering it ⇒
|
|
17
|
+
* **throw**. The stricter of the two wins.
|
|
18
|
+
* - **`onAsk`** — no safe automatic merge (the approver and the policy must be coordinated). Both set to
|
|
19
|
+
* DIFFERENT values ⇒ **throw**; equal ⇒ keep; one set ⇒ that one.
|
|
20
|
+
* - **`hooks`** — no standard composition (stacking hook results is caller-specific). Both set ⇒ **throw**;
|
|
21
|
+
* one set ⇒ that one.
|
|
22
|
+
*
|
|
23
|
+
* @throws {TaskSpecTightenError} when an override would loosen a stricter base safety field, or when two
|
|
24
|
+
* incompatible safety values are both set and cannot be merged automatically.
|
|
25
|
+
*/
|
|
5
26
|
export declare function tightenTaskSpec(base: TaskSpec, overrides: Partial<TaskSpec>): TaskSpec;
|