@sema-agent/core 5.19.0 → 5.21.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.
- package/CHANGELOG.md +102 -4
- 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/roster-store.js +3 -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/circuit-breaker.js +14 -3
- 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 +108 -0
- package/dist/brain/timeout.js +11 -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 +293 -0
- package/dist/core/background-agent-store.js +5 -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 +609 -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/mailbox-store.js +2 -0
- package/dist/core/mcp.d.ts +385 -0
- package/dist/core/mcp.js +58 -11
- 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 +40 -0
- package/dist/core/retention-policy.js +21 -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 +51 -14
- package/dist/core/runner/prompt-suggestions.d.ts +7 -0
- package/dist/core/runner/runtask.d.ts +304 -3
- package/dist/core/runner/runtask.js +17 -2
- 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-agent.js +2 -0
- 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-policy.js +3 -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/core/workflow-run-store.js +2 -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 +17 -2
- package/dist/index.js +1 -2
- 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-spec.js +4 -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/orchestration/workflow.js +13 -2
- 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/background-agent-store.js +2 -1
- 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/mailbox-store.js +2 -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/stores/file/workflow-run-store.js +2 -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-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/web.js +32 -5
- 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
|
@@ -6,24 +6,74 @@ import type { WorkflowHandle, WorkflowRun } from "../orchestration/workflow.js";
|
|
|
6
6
|
import type { TaskNotificationPayload } from "./task-notification.js";
|
|
7
7
|
import type { ToolResultStore } from "./tool-result-store.js";
|
|
8
8
|
export type SemaTaskType = "background_bash" | "workflow" | "background_agent" | "monitor";
|
|
9
|
+
/** design/134 §3.3 (R3): WHO initiated a kill — recorded at the initiation site (first-marker-wins),
|
|
10
|
+
* because the settle-side then/catch context has already lost it. OPEN ENUM on the wire, now in the
|
|
11
|
+
* TYPE too (`(string & {})` keeps literal completion while admitting future values like "timeout"
|
|
12
|
+
* without a breaking change): consumers must tolerate unknown values and fall back to default copy.
|
|
13
|
+
* SINGLE SOURCE of the shape — two wire mirrors are INLINED to avoid import cycles (this module sits
|
|
14
|
+
* above both) and must stay in sync: types.ts `BackgroundChildEvent.stoppedBy` and
|
|
15
|
+
* task-notification.ts `TaskNotificationPayload.stoppedBy`. */
|
|
9
16
|
export type StopSource = "user" | "parent" | "system" | (string & {});
|
|
17
|
+
/** design/153 §7.1: `"parked"` (background agents only today) = durably suspended on a pending
|
|
18
|
+
* approval checkpoint — neither live nor terminal. Every `=== "running"` liveness check treats it
|
|
19
|
+
* as not-running (correct: no process exists); it exits poll waits, refuses settles, and is
|
|
20
|
+
* reap-exempt. Downstream switches over this union gain an arm (announced, [1556]/L1.5). */
|
|
10
21
|
export type SemaTaskStatus = "pending" | "running" | "parked" | "completed" | "failed" | "killed" | "cancelled";
|
|
11
22
|
export type TaskRetrievalStatus = "success" | "not_ready" | "timeout";
|
|
12
23
|
export interface UnifiedTaskOutput {
|
|
13
24
|
task_id: string;
|
|
25
|
+
/** RB-92 (2026-07-25, red probe): `"unknown"` is a DECLARED member here, not a stray literal. A
|
|
26
|
+
* not-found lookup has no task kind to report, and the TaskStop envelope's `task_type` is required by
|
|
27
|
+
* the client schema — so the wrapper was already emitting `"unknown"` while the type said it could
|
|
28
|
+
* only be a `SemaTaskType`. Declaring it keeps the two honest with each other, and keeps `SemaTaskType`
|
|
29
|
+
* itself clean for every consumer that switches over real task kinds. */
|
|
14
30
|
type?: SemaTaskType | "unknown";
|
|
15
31
|
status?: SemaTaskStatus | string;
|
|
16
32
|
retrieval_status: TaskRetrievalStatus;
|
|
17
33
|
content?: string;
|
|
18
34
|
error?: string;
|
|
35
|
+
/** RB-386② ([2090]) — machine-readable failure code on a FAILED background_agent row's poll
|
|
36
|
+
* details (the child's TaskResult.errorCode taxonomy — brain codes / `limit.*` / `budget.*` …).
|
|
37
|
+
* Additive; absent on non-failed rows, on rows whose failure carried no code, and on other lanes. */
|
|
19
38
|
errorCode?: string;
|
|
39
|
+
/** RB-386② — retryability verdict for a FAILED background_agent row, derived at settle time by the
|
|
40
|
+
* same classifier the sync sub-agent report's `error_kind (retryable: …)` line uses. Additive. */
|
|
20
41
|
retryable?: boolean;
|
|
42
|
+
/** design/134 §3.3: only present when `status === "killed"` (open enum — see {@link StopSource}). */
|
|
21
43
|
stoppedBy?: StopSource;
|
|
44
|
+
/** server[1526] ask — the durable row's committed stop-cycle number (1.371 settle mint), served on
|
|
45
|
+
* durable-fallback polls so a tail consumer can key revive cycles without the notify lane.
|
|
46
|
+
* [1532]§三1: ALSO served by the in-process live poll/stop arms (the handle's current cycle
|
|
47
|
+
* projection — spawn = 1, each 1.332/tier-3 revival opens the next), same key, same meaning,
|
|
48
|
+
* so tail meta is complete whichever arm answers. */
|
|
22
49
|
seq?: number;
|
|
50
|
+
/** fidelity-sweep A1: the served result is the child's PARTIAL work — it landed after a kill had
|
|
51
|
+
* already won the terminal race and was backfilled (produced before/while the task was stopped). */
|
|
23
52
|
partial_result?: boolean;
|
|
53
|
+
/** P1-3(黑板 [1870] P1-3, cli/server 商定项 — 黑板 [1920]/[1921]/[1924]/[1925]):a cross-channel
|
|
54
|
+
* correlation key for ONE completion event. The same task's completion fans out across several
|
|
55
|
+
* independent channels today (a live `TaskNotificationPayload` frame, a durable inbox entry, and
|
|
56
|
+
* this poll projection) — a consumer today has to reconstruct "are these the same completion?" from
|
|
57
|
+
* weaker signals (task_id + status + timing). Minted ONCE per completion, fill-once (first writer
|
|
58
|
+
* wins) on the handle/record the completion is settled onto, so every read face — this poll
|
|
59
|
+
* projection, the notification payload, and (for background_agent) the cross-restart durable
|
|
60
|
+
* fallback row — serves the exact same value. Open-shape `string` (a uuidv7 in this implementation,
|
|
61
|
+
* not contractually required to stay one); absent when the underlying task hasn't reached a terminal
|
|
62
|
+
* settle yet, or on a pre-P1-3 core build that never minted one. */
|
|
24
63
|
completionId?: string;
|
|
25
64
|
details?: unknown;
|
|
26
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* E1 (黑板 [1937]) — the shared internal poll/stop result shape every helper below returns
|
|
68
|
+
* (`noTask`/`noTaskForStop`/`formatWorkflowRun`/`serveDurableAgentRow`/`pollTask`/`stopTask` and every
|
|
69
|
+
* per-task-kind poll/stop arm). `UnifiedTaskOutput` (the `details` face) has no isError channel of its
|
|
70
|
+
* own — it is a REQUIRED-field wire shape consumed by callers beyond these two tools too, so isError is
|
|
71
|
+
* carried as a sibling on the WRAPPER instead (trap avoidance per the E1 sweep: never smuggle isError
|
|
72
|
+
* through a narrower helper contract). Optional, absent/false = success — `createTaskOutputTool`/
|
|
73
|
+
* `createTaskStopTool` forward it onto the real `ToolReturn` at the tool boundary. Every internal helper
|
|
74
|
+
* keeps constructing `content`/`details` exactly as before; this only adds a place to say "and this one
|
|
75
|
+
* is a genuine failure" where the failure is actually detected.
|
|
76
|
+
*/
|
|
27
77
|
export type UnifiedTaskResult = {
|
|
28
78
|
content: string;
|
|
29
79
|
details: UnifiedTaskOutput;
|
|
@@ -40,22 +90,59 @@ export interface SemaTaskHandle {
|
|
|
40
90
|
createdAt: number;
|
|
41
91
|
updatedAt: number;
|
|
42
92
|
outputFile?: string;
|
|
93
|
+
/** P1-3 — see {@link UnifiedTaskOutput.completionId}. Minted fill-once at this task's own settle
|
|
94
|
+
* point ({@link mintCompletionId}); absent until the task reaches a terminal status. */
|
|
43
95
|
completionId?: string;
|
|
44
96
|
}
|
|
97
|
+
/** P1-3(黑板 [1920]/[1921]/[1924]/[1925]) — mint a cross-channel completion correlation id ONCE per
|
|
98
|
+
* handle/record, fill-once (first writer wins): every settle/direct-terminal-flip site calls this
|
|
99
|
+
* instead of writing `completionId` directly, so no matter how many terminal-transition sites a lane
|
|
100
|
+
* has (settle / TaskStop bypass / backfill), the value is minted exactly once and every later caller
|
|
101
|
+
* (including an idempotent re-call from a bypass path that already ran) gets back the SAME id. `string`
|
|
102
|
+
* is intentionally loose (any object with an optional `completionId` field) so the same helper serves
|
|
103
|
+
* both a `RegisteredTaskHandle` and a `WorkflowRun` (orchestration/workflow.ts — a different module,
|
|
104
|
+
* no shared base type, same fill-once shape). */
|
|
45
105
|
export declare function mintCompletionId(target: {
|
|
46
106
|
completionId?: string;
|
|
47
107
|
}): string;
|
|
48
108
|
export interface TaskAccess {
|
|
49
109
|
owner?: string;
|
|
50
110
|
scope?: string;
|
|
111
|
+
/** design/129: the caller's SESSION id — matches session-scoped handles across turns (a fresh per-turn
|
|
112
|
+
* spec.taskId changes `owner`, but the session is the stable key a background child outlives turns under). */
|
|
51
113
|
sessionId?: string;
|
|
52
114
|
}
|
|
53
115
|
export interface BackgroundBashTaskHandle extends SemaTaskHandle {
|
|
54
116
|
type: "background_bash";
|
|
55
117
|
env: ExecutionEnv & BackgroundShellCapability;
|
|
56
118
|
shellId: BackgroundShellId;
|
|
119
|
+
/** (design/129 lifetime discipline, CC parity): a background bash spawned inside a SESSION
|
|
120
|
+
* outlives the run — CC's bg shells survive the agent turn (TB live evidence in settleKilledForOwner's
|
|
121
|
+
* T1-1 note) and die at the SESSION terminal. When set, owner MUST be the sessionId: skipped by the
|
|
122
|
+
* run-teardown settle/evict, kept alive through the dispose except-list, reaped by
|
|
123
|
+
* {@link TaskRegistry.reapSessionBackground}. Explicit flag only — never inferred from owner shape. */
|
|
57
124
|
sessionScoped?: true;
|
|
125
|
+
/** Deliver-a-living-service ledger mark: the run-teardown settle sweep skipped this row under the
|
|
126
|
+
* retain gate (spec-level `TaskSpec.retainBackgroundProcesses` OR the env-declared capability). The
|
|
127
|
+
* row is the delivered daemon's ONLY management surface — while the process runs it survives the
|
|
128
|
+
* per-run evict (TaskOutput/TaskStop resolve through this map; the watcher must stay live to mint
|
|
129
|
+
* the natural-exit receipt) and rides every later run's dispose except-list on the same env
|
|
130
|
+
* ({@link TaskRegistry.retainedShellIds}). A terminal row evicts normally. Terminals: explicit
|
|
131
|
+
* TaskStop, the process's own exit (watcher settle), or env destruction (watcher env-death settle)
|
|
132
|
+
* — deliberately NO timed reaper (the deliverable is the living process). A retained SESSION-resident
|
|
133
|
+
* row is likewise exempt from the session-release reap ({@link TaskRegistry.reapSessionBackground}):
|
|
134
|
+
* the delivered daemon outlives its session, with the same three terminals. */
|
|
58
135
|
retained?: true;
|
|
136
|
+
/** design/116 §7 G2b: when a watcher is attached, the registry accumulates the FULL output here (rolling
|
|
137
|
+
* bound) — TaskOutput then serves a RE-READABLE snapshot (CC semantics) instead of a consume-once cursor.
|
|
138
|
+
* `timedOut`/`timeoutSec` record a SELF-INFLICTED background-timeout kill (the env's per-shell budget
|
|
139
|
+
* fired), so later re-readable polls keep rendering it distinguishably from an external stop.
|
|
140
|
+
* `mirrorFailed` records that at least one append to the advertised output FILE failed — the terminal
|
|
141
|
+
* frame then discloses the file as incomplete instead of letting the launch receipt's "full output is
|
|
142
|
+
* appended there" promise stand over a silently partial file. */
|
|
143
|
+
/** RB-238 ([1937] M1): `droppedBytes`/`dropUnknown` account ENV-SIDE tail-buffer eviction disclosed by
|
|
144
|
+
* the poll (`bytesDroppedBeforeCursor`/`truncated`) — a loss upstream of (and distinct from) the
|
|
145
|
+
* registry's own `rolledChars` memory bound. Bytes counted here never reached the spool at all. */
|
|
59
146
|
spool?: {
|
|
60
147
|
stdout: string;
|
|
61
148
|
stderr: string;
|
|
@@ -68,9 +155,18 @@ export interface BackgroundBashTaskHandle extends SemaTaskHandle {
|
|
|
68
155
|
dropUnknown?: true;
|
|
69
156
|
};
|
|
70
157
|
watcher?: ReturnType<typeof setInterval>;
|
|
158
|
+
/** design/134 §3.3 (R3 MED, 修类不修点): same attribution pair as the agent handle — see there. */
|
|
71
159
|
stopSource?: StopSource;
|
|
72
160
|
stoppedBy?: StopSource;
|
|
161
|
+
/** The terminal-notification sink, HELD ON THE HANDLE (not only inside the watcher closure)
|
|
162
|
+
* so the run-teardown killed settle ({@link TaskRegistry.settleKilledForOwner}) can mint the receipt the
|
|
163
|
+
* watcher never will — a disposed shell polls as vanished ("nothing to notify about") and an evicted
|
|
164
|
+
* handle stops the watcher outright. */
|
|
73
165
|
onTerminal?: (notification: TaskNotificationPayload) => void;
|
|
166
|
+
/** Terminal-notification once-latch (fidelity R1-3): set atomically right before the FIRST terminal
|
|
167
|
+
* notice is sent. A teardown settle and an in-flight watcher tick can both reach their emit point
|
|
168
|
+
* (the kill/poll awaits are suspension windows between the status gate and the send) — whichever
|
|
169
|
+
* fires first wins; every later producer stays silent. */
|
|
74
170
|
terminalNotified?: true;
|
|
75
171
|
}
|
|
76
172
|
export interface WorkflowTaskHandle extends SemaTaskHandle {
|
|
@@ -78,37 +174,104 @@ export interface WorkflowTaskHandle extends SemaTaskHandle {
|
|
|
78
174
|
runId: string;
|
|
79
175
|
handle: WorkflowHandle<unknown>;
|
|
80
176
|
store?: WorkflowRunStore;
|
|
177
|
+
/** γ 批 B-1 (live leg) — see {@link RegisterWorkflowInput.originatingSessionId}. */
|
|
81
178
|
originatingSessionId?: string;
|
|
179
|
+
/** RB-215(黑板 [1870] C6,已修): design/129 session-lifetime discipline, extended to workflow — the
|
|
180
|
+
* ONE background kind that never had it (`background_bash`/`monitor`/`background_agent` all do).
|
|
181
|
+
* Unlike those three (task-scoped BY DEFAULT, `sessionScoped` an explicit opt-in via
|
|
182
|
+
* `TaskSpec.backgroundScope`), a workflow is unconditionally session-anchored — `originatingSessionId`
|
|
183
|
+
* is set at every standard mount (`prepare-task.ts`, never gated), and Workflow's whole raison d'être
|
|
184
|
+
* (its own guidance text) is "runs asynchronously, notifies you or is polled LATER" — there is no
|
|
185
|
+
* sensible "dies with this turn" mode for it to opt out into, unlike a background_agent which
|
|
186
|
+
* genuinely has both use cases. Set `true` whenever `originatingSessionId` is present (`registerWorkflow`).
|
|
187
|
+
* Read only by {@link TaskRegistry.reapSessionBackground} — the explicit, deployment-invoked session
|
|
188
|
+
* terminal anchor (core has no session TTL reaper of its own); NEVER by `Runner.runTask()`'s own
|
|
189
|
+
* per-leg teardown, whose finally block runs on every NORMAL leg completion, not just a genuine
|
|
190
|
+
* session end — a would-be regression caught by cross-review before this shipped (see docs/
|
|
191
|
+
* REVIEW-BACKLOG.md's "RB-215 复核" entry for the full incident). */
|
|
82
192
|
sessionScoped?: true;
|
|
193
|
+
/** See {@link RegisterWorkflowInput.onServedTerminal}. Cleared after the single fire. */
|
|
83
194
|
onServedTerminal?: () => void;
|
|
195
|
+
/** 复审 r2 MAJOR: the bounded return value, captured on the done-hook so the STORE-LESS in-memory lane's
|
|
196
|
+
* terminal poll can hand it over too (the launch note promises it; without a store there was no result). */
|
|
84
197
|
result?: string;
|
|
198
|
+
/** T2A-8: the failure reason (bounded + redacted), captured on the done-hook's rejection so a store-less
|
|
199
|
+
* terminal poll can say WHY it failed (the store lane's formatWorkflowRun already carries run.error). */
|
|
85
200
|
error?: string;
|
|
86
201
|
}
|
|
202
|
+
/** design/151 S1a — the per-row durable write lane. The registry is the row's SINGLE writer; writes
|
|
203
|
+
* are serialized on a promise chain (put → bind → settle order preserved), CAS'd with the locally
|
|
204
|
+
* held `record.rev`, and BEST-EFFORT (a store outage degrades durability with a visible warning,
|
|
205
|
+
* never execution). A lost CAS or a put `already_exists` means a FOREIGN row lives under this
|
|
206
|
+
* handle (leftover from a dead process / another writer) — the lane poisons itself loudly instead
|
|
207
|
+
* of clobbering (design/151 MED-8: the writer's own rev is the anti-clobber line). */
|
|
87
208
|
export interface DurableAgentLane {
|
|
88
209
|
store: BackgroundAgentStore;
|
|
210
|
+
/** The writer's authoritative local copy (rev included — bumped only on a confirmed CAS win). */
|
|
89
211
|
record: BackgroundAgentRecord;
|
|
90
212
|
chain: Promise<void>;
|
|
213
|
+
/** True once the initial `put` landed (an outage before that retries put on the next write). */
|
|
91
214
|
written: boolean;
|
|
92
215
|
poisoned: boolean;
|
|
216
|
+
/** codex r3 F2 — true while the LATEST flush exhausted its retries (cleared by the next success).
|
|
217
|
+
* The lifecycle-flip probe requires it false: a row whose bind/settle never persisted must not
|
|
218
|
+
* have its transcript preserved-but-unreachable (the local record accumulates patches, so the
|
|
219
|
+
* next successful write self-heals the missing fields). */
|
|
93
220
|
flushFailed: boolean;
|
|
221
|
+
/** codex 增量 R-4 — consecutive heartbeat re-drives of a settled flush-failed lane (reset on any
|
|
222
|
+
* flush success); past the ceiling the lane is abandoned loudly instead of retrying forever. */
|
|
94
223
|
redrives?: number;
|
|
95
224
|
}
|
|
96
225
|
export interface BackgroundAgentTaskHandle extends SemaTaskHandle {
|
|
97
226
|
type: "background_agent";
|
|
227
|
+
/** design/115 P3: aborting this cancels the child run (TaskStop / parent teardown). */
|
|
98
228
|
abort: AbortController;
|
|
229
|
+
/** RB-236 — lineage axes, declared (registration always spread them into the handle; readers used
|
|
230
|
+
* to cast). `rootSessionId` feeds {@link canAccess}'s root-session arm; the other two stay
|
|
231
|
+
* read-only lineage metadata on the live face (no parentSessionId access arm — see the arm's
|
|
232
|
+
* comment for why). [1344]② clamps `parentTaskId` register-side. */
|
|
99
233
|
parentTaskId?: string;
|
|
100
234
|
parentSessionId?: string;
|
|
101
235
|
rootSessionId?: string;
|
|
236
|
+
/** design/151 S1a — the child's store session id (transcript/resume anchor), bound once the child
|
|
237
|
+
* session is minted ({@link TaskRegistry.bindBackgroundAgentSession}). */
|
|
102
238
|
sessionId?: string;
|
|
239
|
+
/** design/151 S1a — the durable write lane (present iff the registration wired a store). */
|
|
103
240
|
durable?: DurableAgentLane;
|
|
241
|
+
/** design/147 S2a — the RUNNING child run's notification injector (attached once its lane is
|
|
242
|
+
* live, dropped at terminal settle). A parent/sibling SendMessage delivers through this at the
|
|
243
|
+
* child's next turn boundary (CC in-memory pendingMessages pedestal); late calls after the run
|
|
244
|
+
* ends park per session inside the injector itself (the lane-teardown branch). */
|
|
104
245
|
notify?: (notification: import("./task-notification.js").TaskNotificationPayload, opts?: {
|
|
105
246
|
priority?: import("./task-notification.js").SystemInjectionPriority;
|
|
106
247
|
}) => "queued" | "parked" | "dropped_duplicate" | Promise<"queued" | "parked" | "dropped_duplicate">;
|
|
248
|
+
/** design/147 S2a (codex R3 F5) — messages that arrived in the STARTUP window (row already
|
|
249
|
+
* running, lane not yet bound). Bounded; flushed in order by attachAgentNotify. Discarded at
|
|
250
|
+
* terminal settle: a run that failed during prepare never had a lane to park through, and the
|
|
251
|
+
* sender's completion notification (failed) prompts the resend. */
|
|
252
|
+
/** S2b codex F1 — park redeemability (see RegisterBackgroundAgentInput.retainedContinuation). */
|
|
107
253
|
retainedContinuation?: boolean;
|
|
254
|
+
/** S2b RB-27② — revive-cycle stamp (see reviveBackgroundAgent): attach/settle from a resume leg
|
|
255
|
+
* carry it so a stale cycle's late calls no-op instead of clobbering the newer cycle. */
|
|
108
256
|
reviveCycle?: number;
|
|
257
|
+
/** [1532]§三1 — the CURRENT stop-cycle number in settle-generation terms (spawn run = 1; each
|
|
258
|
+
* revival — 1.332 retained or tier-3 seeded — opens the next). Served by the LIVE poll/stop
|
|
259
|
+
* projection under the SAME `seq` key as the durable-fallback arm, so a tail consumer keys
|
|
260
|
+
* revive cycles identically whichever arm answered. Re-aligned to the settle's authoritative
|
|
261
|
+
* `outcome.seq` at settle time (the ledger's cycleSeq is the mint; this is its projection). */
|
|
109
262
|
cycleSeq?: number;
|
|
263
|
+
/** design/153 §7.1 — the approval checkpoint this handle is parked on (`status:"parked"` only). */
|
|
110
264
|
parkedCheckpointToken?: string;
|
|
265
|
+
/** design/153 §7.1 — in-process TaskStop arbitration closure, minted by the parking watcher
|
|
266
|
+
* (captures the checkpoint store + token; the registry itself holds no durable stores — r4 F-06).
|
|
267
|
+
* Resolves `true` iff the STOP won the checkpoint CAS (expire landed; resume can no longer
|
|
268
|
+
* consume it) — only then may the row flip killed. `false` = a resume consumed the token first.
|
|
269
|
+
* Absent (cross-process row, no live park context) ⇒ TaskStop refuses honestly: the durable
|
|
270
|
+
* approval inbox (server /decide) owns that arbitration. */
|
|
111
271
|
resolveParkedStop?: () => Promise<boolean>;
|
|
272
|
+
/** S2b codex R5-F2 — resolvers of DIRECT (post-attach) deliveries currently awaiting the
|
|
273
|
+
* injector; terminal settle/stop sweep these as not_running so a never-settling adapter can
|
|
274
|
+
* never pin the sender's tool call. */
|
|
112
275
|
inFlightDirect?: Set<(r: {
|
|
113
276
|
ok: true;
|
|
114
277
|
disposition: "queued" | "parked";
|
|
@@ -116,6 +279,8 @@ export interface BackgroundAgentTaskHandle extends SemaTaskHandle {
|
|
|
116
279
|
ok: false;
|
|
117
280
|
reason: "not_found" | "not_running" | "no_channel";
|
|
118
281
|
}) => void>;
|
|
282
|
+
/** S2a F7 — channel lifecycle: undefined = unsupported (spawner never declared), "attaching" =
|
|
283
|
+
* declared, lane not yet bound (buffer window), "attached" = live injector present. */
|
|
119
284
|
channelState?: "attaching" | "attached";
|
|
120
285
|
preAttachQueue?: Array<[
|
|
121
286
|
import("./task-notification.js").TaskNotificationPayload,
|
|
@@ -130,32 +295,101 @@ export interface BackgroundAgentTaskHandle extends SemaTaskHandle {
|
|
|
130
295
|
reason: "not_found" | "not_running" | "no_channel";
|
|
131
296
|
}) => void) | undefined)?
|
|
132
297
|
]>;
|
|
298
|
+
/** [c209-D] the EXPLICIT addressing name (CC Agent.name parity, validated at spawn: charset regex +
|
|
299
|
+
* "main" reserved). Distinct from `description` (the display/legacy-matching label): the name layer
|
|
300
|
+
* resolves latest-wins ("a newer agent took the name"), the description layers keep their
|
|
301
|
+
* running-preferred + ambiguous posture. Absent on pre-[c209] rows and unnamed spawns. */
|
|
133
302
|
name?: string;
|
|
303
|
+
/** design/129: this child OUTLIVES its parent turn — owner is the SESSION id; the parent-teardown reap
|
|
304
|
+
* skips it; `reapSessionBackground` is its terminal anchor. Explicit flag, never inferred from key values
|
|
305
|
+
* (hostTaskId===sessionId deployments would otherwise be ambiguous). */
|
|
134
306
|
sessionScoped?: true;
|
|
307
|
+
/** Terminal snapshot (bounded, {@link BG_AGENT_RESULT_MAX} in subagent.ts) — served by TaskOutput
|
|
308
|
+
* once the child finishes. */
|
|
135
309
|
result?: string;
|
|
310
|
+
/** RB-205-B: the FULL result (bounded only by the defensive {@link BG_AGENT_RESULT_FULL_MAX} ceiling
|
|
311
|
+
* in subagent.ts), set ONLY when it differs from `result` — same shape as {@link WorkflowRun.resultFull}
|
|
312
|
+
* (workflow.ts NH-1). Before this field existed, the settle call sites pre-sliced `child.result` to
|
|
313
|
+
* ~2-4K chars with no disclosure — clipTaskOutput's own file-pointer/offload-friendly design at the
|
|
314
|
+
* poll layer was structurally unreachable because `result` itself could never be long enough to need it. */
|
|
136
315
|
resultFull?: string;
|
|
316
|
+
/** design/158 S1 (RB-205-B 半) — the tool-result-store ref `resultFull`'s full text was spilled to,
|
|
317
|
+
* the FIRST time a poll's `clipTaskOutput` actually cut it (lazy write, not at settle time). Cached
|
|
318
|
+
* here so every LATER poll within the SAME cycle reuses the same ref instead of re-writing (the
|
|
319
|
+
* store's own `put` is write-once too, but re-deriving/re-calling it every poll would still cost a
|
|
320
|
+
* redundant round-trip on a durable backend, and a changing ref across polls would be a needless
|
|
321
|
+
* disclosure churn). {@link reviveBackgroundAgentLane} clears this on revive — the cycle's full text
|
|
322
|
+
* is gone, so a stale ref must not be reused across cycles. Ref format ties in `reviveCycle` (see
|
|
323
|
+
* {@link import("./task-registry-agent.js").spillClippedAgentResult}) precisely so a revived cycle's
|
|
324
|
+
* eventual spill lands under a DIFFERENT ref rather than colliding with (and being silently refused
|
|
325
|
+
* by the write-once store under) cycle 1's. */
|
|
137
326
|
spillRef?: string;
|
|
138
327
|
error?: string;
|
|
328
|
+
/** RB-386② ([2090]) — the machine-readable failure code beside `error`, threaded from the settle
|
|
329
|
+
* mint point (subagent.ts computes it ONCE from the child's TaskResult.errorCode taxonomy /
|
|
330
|
+
* extractErrorCode — single source with the sync report's classification). Served on the failed
|
|
331
|
+
* row's poll `details` and the failed terminal notification. Absent when no code was known. */
|
|
139
332
|
errorCode?: string;
|
|
333
|
+
/** RB-386② — retryability verdict for a FAILED row, computed at the settle mint point by the SAME
|
|
334
|
+
* classifier the sync report face uses (`classifySubagentError` — error_kind ∈ rate_limit/
|
|
335
|
+
* overloaded/timeout/network ⇒ true, logic ⇒ false). Stored rather than re-derived so the core
|
|
336
|
+
* poll lane never has to import the agents-domain classifier (no new domain cycle). */
|
|
140
337
|
errorRetryable?: boolean;
|
|
338
|
+
/** RB-405 G3 ([2135]/[2136]) — the coarse classification KIND beside `errorRetryable`
|
|
339
|
+
* (classifySubagentError's error_kind ∈ rate_limit/overloaded/timeout/network/logic), threaded
|
|
340
|
+
* from the same settle mint point and stored for the same no-domain-cycle reason as its sibling.
|
|
341
|
+
* Rendered on the FAILED row's poll TEXT face as the `(error_kind: …, retryable: …)` clause —
|
|
342
|
+
* the same field names the sync report's error_kind line already speaks. */
|
|
141
343
|
errorKind?: string;
|
|
344
|
+
/** Ruled 2026-08-05 (governance kind follow-up): the wait hint paired with a deferred-retryable
|
|
345
|
+
* failure (`usage.*` codes — errorKind `"governance"`), threaded from the same settle mint point
|
|
346
|
+
* as its three siblings. Without it the background faces exposed `retryable:false` with no way to
|
|
347
|
+
* know WHEN the refusal lifts — the sync report card carried `retryAfterMs` while the bg poll/
|
|
348
|
+
* notification faces structurally lost it. */
|
|
142
349
|
errorRetryAfterMs?: number;
|
|
350
|
+
/** fidelity-sweep A1: `result` arrived AFTER a kill won the status race — it is the child's partial
|
|
351
|
+
* work (produced before/while being stopped), backfilled by the refused settle. Poll frames label it. */
|
|
143
352
|
resultIsPartial?: boolean;
|
|
353
|
+
/** design/134 §3.3 (R3): the PENDING attribution marker, written by {@link TaskRegistry.markStopSource}
|
|
354
|
+
* at the kill INITIATION site, strictly BEFORE the abort/status flip (once the handle leaves "running"
|
|
355
|
+
* the marker is refused and attribution falls back to "system"). First-marker-wins. */
|
|
144
356
|
stopSource?: StopSource;
|
|
357
|
+
/** The LANDED attribution — set exactly when the handle goes `killed`, never rewritten afterwards
|
|
358
|
+
* (first-writer-wins, same discipline as the terminal status itself). Absent on natural completion/failure. */
|
|
145
359
|
stoppedBy?: StopSource;
|
|
360
|
+
/** RB-375 A1 — the reap-time terminal notifier, hung by the spawn lanes (subagent.ts) right after
|
|
361
|
+
* registration: composes and sends the SAME terminal faces (observer sink + parent notification)
|
|
362
|
+
* the child's own unwind would, so {@link import("./task-registry.js").TaskRegistry.reapSessionBackground}
|
|
363
|
+
* can emit the terminal news AT REAP TIME instead of waiting on the child's unwind (which blocks on
|
|
364
|
+
* the in-flight tool actually honoring the abort — unbounded). The bash handle's `onTerminal` twin.
|
|
365
|
+
* Cleared at the accepted settle (with `notify`); invoked at most once via {@link terminalNotified}. */
|
|
146
366
|
onReapTerminal?: () => void;
|
|
367
|
+
/** RB-375 A1 — terminal-notification once-latch (the bash/monitor `terminalNotified` twin): claimed
|
|
368
|
+
* by whichever side reaches its emit point first — the session-release reap sweep (synchronous send)
|
|
369
|
+
* or the child's own unwind (`TaskRegistry.claimAgentTerminalNotify`). The loser stays silent, so a
|
|
370
|
+
* reaped child never double-announces. Cleared on revive (a new stop cycle owns its own terminal). */
|
|
147
371
|
terminalNotified?: true;
|
|
148
372
|
}
|
|
373
|
+
/** design/135 G2 (Monitor): injectable timer/clock seam for the monitor watcher — the 200ms batch window
|
|
374
|
+
* and the timeout/storm checks must be drivable by a test without real sleeps (design/87 discipline).
|
|
375
|
+
* `setInterval` receives an ASYNC tick (the default adapter fires it void; a fake can await it). */
|
|
149
376
|
export interface MonitorTimers {
|
|
150
377
|
setInterval: (fn: () => unknown, ms: number) => unknown;
|
|
151
378
|
clearInterval: (handle: unknown) => void;
|
|
152
379
|
now: () => number;
|
|
153
380
|
}
|
|
154
381
|
export declare const defaultMonitorTimers: MonitorTimers;
|
|
382
|
+
/** design/135 G2: Monitor watch — background_bash's near kin, but the watcher streams stdout LINES as
|
|
383
|
+
* batched event notifications instead of firing one terminal notify. Spool stays re-readable (TaskOutput). */
|
|
155
384
|
export interface MonitorTaskHandle extends SemaTaskHandle {
|
|
156
385
|
type: "monitor";
|
|
157
386
|
env: ExecutionEnv & BackgroundShellCapability;
|
|
158
387
|
shellId: BackgroundShellId;
|
|
388
|
+
/** RB-238/RB-239/RB-240 ([1937] M1-M3) spool honesty fields: `droppedBytes`/`dropUnknown` = env-side
|
|
389
|
+
* tail-buffer eviction (see the bash handle's twin); `dropNotified` = the once-latch for the event-stream
|
|
390
|
+
* disclosure (terminal frames disclose unconditionally); `drainFailed` = the stop-time final drain poll
|
|
391
|
+
* failed, so the spool may be missing the last window; `timedOut`/`timeoutSec` = the env's own
|
|
392
|
+
* background time budget killed the process (bash-lane parity — renders distinguishably from a stop). */
|
|
159
393
|
spool: {
|
|
160
394
|
stdout: string;
|
|
161
395
|
stderr: string;
|
|
@@ -168,8 +402,18 @@ export interface MonitorTaskHandle extends SemaTaskHandle {
|
|
|
168
402
|
timedOut?: boolean;
|
|
169
403
|
timeoutSec?: number;
|
|
170
404
|
};
|
|
405
|
+
/** Partial (newline-less) stdout tail awaiting completion — a line becomes an event only once terminated. */
|
|
171
406
|
lineBuf: string;
|
|
407
|
+
/** Per-batch monotonic counter → unique notification dedup keys (see task-notification.ts). */
|
|
172
408
|
seq: number;
|
|
409
|
+
/** RB-334 (CC `PCo`/`TIs` 220:403278-403321): the TWO-LEVEL event-storm control's state.
|
|
410
|
+
* Level 1 = a token bucket (`stormTokens` out of `stormBurst`, refilled one per
|
|
411
|
+
* `stormRefillIntervalMs`): a batch that cannot consume a token is SUPPRESSED (its lines stay in the
|
|
412
|
+
* re-readable spool) and counted in `suppressedBatches`; the next batch that DOES consume one first
|
|
413
|
+
* emits the disclosure frame naming that count. Level 2 = kill, and only for a monitor that stayed
|
|
414
|
+
* continuously over budget since `overloadSince` for MONITOR_STORM_KILL_AFTER_MS.
|
|
415
|
+
* `lastSuppressedAt` clears `overloadSince` once the pressure is old enough (CC's `OCo * 3` rule) —
|
|
416
|
+
* a short burst every few minutes must never accumulate into a kill. */
|
|
173
417
|
stormTokens: number;
|
|
174
418
|
stormBurst: number;
|
|
175
419
|
stormRefillIntervalMs: number;
|
|
@@ -179,24 +423,65 @@ export interface MonitorTaskHandle extends SemaTaskHandle {
|
|
|
179
423
|
lastSuppressedAt?: number;
|
|
180
424
|
batchWindowMs: number;
|
|
181
425
|
maxBatchesPerMinute: number;
|
|
426
|
+
/** Session-level residency (design/129 sessionScoped semantics): reaped by `reapSessionBackground`,
|
|
427
|
+
* skipped by the per-run `clearBackgroundForOwner`, and NEVER timeout-killed by the watcher. */
|
|
182
428
|
persistent?: true;
|
|
183
429
|
sessionScoped?: true;
|
|
430
|
+
/** Deliver-a-living-service ledger mark — same semantics as the bash handle's `retained` (see there). */
|
|
184
431
|
retained?: true;
|
|
432
|
+
/** Non-persistent only: watcher-enforced hard deadline (epoch ms on the injected clock).
|
|
433
|
+
* (CC parity): this deadline — not the parent run — is the watch's lifetime anchor.
|
|
434
|
+
* A monitor's life = min(timeout, process exit, TaskStop); a persistent one is SESSION-anchored.
|
|
435
|
+
* NEITHER is run-anchored: the run teardown leaves an in-window watch alive (settle/evict/dispose
|
|
436
|
+
* all skip it) so between-turns events keep flowing through the pending lane. */
|
|
185
437
|
deadlineAt?: number;
|
|
186
438
|
timeoutMs?: number;
|
|
187
439
|
watcher?: unknown;
|
|
440
|
+
/** RB-239 ([1937] M2): a watcher tick is suspended on its pollBackground await RIGHT NOW. The stop-time
|
|
441
|
+
* final drain must skip its own poll then (that in-flight tick already consumed the env cursor — and a
|
|
442
|
+
* never-resolving adapter must not pin TaskStop). Set/cleared in lockstep with the tick's re-entrancy
|
|
443
|
+
* guard. */
|
|
188
444
|
tickInFlight?: true;
|
|
189
445
|
timers: MonitorTimers;
|
|
190
446
|
onEvent?: (n: TaskNotificationPayload) => void;
|
|
191
447
|
stopSource?: StopSource;
|
|
192
448
|
stoppedBy?: StopSource;
|
|
449
|
+
/** Terminal-notification once-latch — same discipline as the bash handle (fidelity R1-3). Only the
|
|
450
|
+
* TERMINAL frame is latched; "event" frames are unaffected. */
|
|
193
451
|
terminalNotified?: true;
|
|
452
|
+
/** design/158 S2 (RB-364 半) — the offload store a ROLLED-OFF spool middle spills to, captured at
|
|
453
|
+
* REGISTRATION time (RegisterMonitorInput's additive field), not per-poll like the background_agent
|
|
454
|
+
* lane's `TaskPollOptions.toolResultStore` (S1): the roll happens inside the watcher tick — an async
|
|
455
|
+
* timer callback with no per-call "access" to thread a store through — so registration is the only
|
|
456
|
+
* point that has one to hang on the handle. Absent ⇒ legal degrade: `rollSpoolText`'s `onDrop` hook
|
|
457
|
+
* is simply never wired, byte-identical to pre-S2 rolling (design/158 §2.2). */
|
|
194
458
|
toolResultStore?: ToolResultStore;
|
|
459
|
+
/** design/158 S2 — the session id spilled refs are scoped under (same `TaskAccess.sessionId` role as
|
|
460
|
+
* every other `buildToolResultRef` call site); captured at registration for the same reason as
|
|
461
|
+
* `toolResultStore` above. */
|
|
195
462
|
spillSessionId?: string;
|
|
463
|
+
/** design/158 S2 — next segment index to mint for the STDOUT dropped-middle ref chain (0-based;
|
|
464
|
+
* design/158 §3 "方案 a": a ref PER dropped segment, chained by index, rather than one ref with an
|
|
465
|
+
* append primitive — ToolResultStore's contract is write-once with no append). stdout and stderr get
|
|
466
|
+
* INDEPENDENT counters (this field vs `spillErrSegCount`) so each stream's own segments concatenate
|
|
467
|
+
* back in original byte order without interleaving the other stream's drops between them. */
|
|
196
468
|
spillSegCount?: number;
|
|
469
|
+
/** design/158 S2 — the STDERR twin of {@link spillSegCount}. */
|
|
197
470
|
spillErrSegCount?: number;
|
|
471
|
+
/** design/158 S2 — cumulative chars (UTF-16 code units, `string.length`) handed to `store.put`
|
|
472
|
+
* across every segment this handle has spilled so far (both streams combined) — the per-handle
|
|
473
|
+
* disk-cap accounting ({@link import("./task-registry-monitor.js")} reads `MONITOR_SPILL_CAP_CHARS`
|
|
474
|
+
* against this). RB-396-b: the field used to be named `spillBytesUsed` while the ledger counted
|
|
475
|
+
* chars — renamed to the axis it really measures (see the constant's own doc for why chars). */
|
|
198
476
|
spillCharsUsed?: number;
|
|
477
|
+
/** design/158 S2 — the per-handle spill cap (`MONITOR_SPILL_CAP_CHARS`) was reached; further
|
|
478
|
+
* rolled-off middles are no longer spilled (already-written segments stay readable — "earlier
|
|
479
|
+
* segments retained"). One-time latch; the poll disclosure reads it to stop claiming full ref
|
|
480
|
+
* coverage. */
|
|
199
481
|
spillCapped?: true;
|
|
482
|
+
/** design/158 S2 — at least one `store.put` for this handle rejected or threw. One-time latch; the
|
|
483
|
+
* poll disclosure downgrades its wording once this is set (never claims the ref chain is complete —
|
|
484
|
+
* the fire-and-forget write may have silently failed; see task-registry-monitor.ts's spill helper). */
|
|
200
485
|
spillFailed?: true;
|
|
201
486
|
}
|
|
202
487
|
export type RegisteredTaskHandle = BackgroundBashTaskHandle | WorkflowTaskHandle | BackgroundAgentTaskHandle | MonitorTaskHandle;
|
|
@@ -205,15 +490,27 @@ export interface RegisterMonitorInput extends TaskAccess {
|
|
|
205
490
|
env: ExecutionEnv & BackgroundShellCapability;
|
|
206
491
|
description?: string;
|
|
207
492
|
toolUseId?: string;
|
|
493
|
+
/** Session-level residency: no watcher timeout; reaped by session release (design/129 semantics —
|
|
494
|
+
* when set, `owner` MUST be the session id and `sessionScoped` should be set too). */
|
|
208
495
|
persistent?: boolean;
|
|
496
|
+
/** design/129 explicit-flag discipline: session-scoped access matching + session-terminal reap. */
|
|
209
497
|
sessionScoped?: true;
|
|
498
|
+
/** Non-persistent watch deadline (ms). The tool clamps to [1, 3_600_000], default 300_000. */
|
|
210
499
|
timeoutMs?: number;
|
|
500
|
+
/** The event sink — each stdout-line batch AND the single terminal state fires exactly one payload. */
|
|
211
501
|
onEvent?: (n: TaskNotificationPayload) => void;
|
|
502
|
+
/** design/87: injectable timers/clock (tests drive ticks + time manually; default = real timers). */
|
|
212
503
|
timers?: MonitorTimers;
|
|
504
|
+
/** Batch window (ms, default 200): lines arriving within one tick coalesce into one notification. */
|
|
213
505
|
batchWindowMs?: number;
|
|
506
|
+
/** RB-334: the SUSTAINED batch rate the storm bucket refills at (default 50/min). Exceeding it is
|
|
507
|
+
* suppression, not death — see `stormBurst` and MONITOR_STORM_KILL_AFTER_MS. */
|
|
214
508
|
maxBatchesPerMinute?: number;
|
|
509
|
+
/** RB-334: burst capacity of the storm bucket (default MONITOR_STORM_BURST = CC's 10). */
|
|
215
510
|
stormBurst?: number;
|
|
216
511
|
now?: number;
|
|
512
|
+
/** design/158 S2 (RB-364 半) — the offload store a rolled-off spool middle spills to (see
|
|
513
|
+
* {@link MonitorTaskHandle.toolResultStore}). Absent ⇒ legal degrade, byte-identical rolling. */
|
|
217
514
|
toolResultStore?: ToolResultStore;
|
|
218
515
|
}
|
|
219
516
|
export interface RegisterWorkflowInput extends TaskAccess {
|
|
@@ -223,28 +520,109 @@ export interface RegisterWorkflowInput extends TaskAccess {
|
|
|
223
520
|
description?: string;
|
|
224
521
|
toolUseId?: string;
|
|
225
522
|
now?: number;
|
|
523
|
+
/** γ 批 B-1 (live leg): the ORIGINATING session id — anchors the in-process handle to its session
|
|
524
|
+
* so a later turn of the SAME session (fresh per-turn owner) reaches it through `canAccess`'s
|
|
525
|
+
* workflow session arm, mirroring the durable predicate. A workflow is a SESSION-level asset
|
|
526
|
+
* (its completion notification routes to the session) — deliberately unlike a background agent's
|
|
527
|
+
* live handle, whose sibling-turn invisibility is a channel-discipline ruling (§3.1c). */
|
|
226
528
|
originatingSessionId?: string;
|
|
529
|
+
/**
|
|
530
|
+
* Fired AT MOST ONCE when a `pollTask` through THIS registry entry (= the originating
|
|
531
|
+
* session's own lane; cross-session store-fallback polls don't fire it) serves a TERMINAL snapshot.
|
|
532
|
+
* The RunWorkflow tool wires it to {@link import("../orchestration/run-workflow-tool.js").WorkflowCompletionNotifier.ackServed}
|
|
533
|
+
* so the deployment can drop the now-redundant completion-inbox entry. Errors are swallowed.
|
|
534
|
+
*/
|
|
227
535
|
onServedTerminal?: () => void;
|
|
228
536
|
}
|
|
537
|
+
/** T2A-7 (2026-07-05 soak): one blocked-poll step, CLAMPED to the caller's deadline — a small timeoutMs
|
|
538
|
+
* (e.g. 10ms) must not sleep the full 400ms step (~40× overshoot, and the overshoot window even served a
|
|
539
|
+
* late terminal as success). `undefined` deadline keeps the plain step (callers without a deadline). */
|
|
229
540
|
export declare const sleepPollStep: (deadline: number | undefined, signal?: AbortSignal) => Promise<void>;
|
|
230
541
|
export declare const sleepMs: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
542
|
+
/** design/135 G2 Monitor defaults (CC schema: 200ms batch window; timeout default 5min / max 60min).
|
|
543
|
+
* `MONITOR_MAX_BATCHES_PER_MINUTE` = the SUSTAINED batch rate the storm bucket refills at
|
|
544
|
+
* (RB-334: CC `TIs(bIs=10, OCo=2000)` 220:403284/403421-403423 refills 1 token per 2000ms = 30/min;
|
|
545
|
+
* sema keeps its own 50/min figure — the sema batch window is the same 200ms, so the two are the same
|
|
546
|
+
* order of magnitude — and derives the refill interval from it, see `stormRefillIntervalMs`). */
|
|
231
547
|
export declare const MONITOR_BATCH_WINDOW_MS = 200;
|
|
232
548
|
export declare const MONITOR_DEFAULT_TIMEOUT_MS = 300000;
|
|
233
549
|
export declare const MONITOR_MAX_TIMEOUT_MS = 3600000;
|
|
234
550
|
export declare const MONITOR_MAX_BATCHES_PER_MINUTE = 50;
|
|
551
|
+
/** RB-334 (CC `bIs` 220:403421): burst capacity of the storm token bucket — how many batches may fire
|
|
552
|
+
* back-to-back before the SUPPRESSION level engages. CC value, adopted verbatim. */
|
|
235
553
|
export declare const MONITOR_STORM_BURST = 10;
|
|
554
|
+
/** RB-334 (CC `FN_` 220:403423): how long a monitor must stay CONTINUOUSLY over budget before the
|
|
555
|
+
* second level (kill) fires. CC value, adopted verbatim. */
|
|
236
556
|
export declare const MONITOR_STORM_KILL_AFTER_MS = 30000;
|
|
557
|
+
/** RB-334 (CC `bdd` 220:403427): the partial-line accumulator bound. sema's `lineBuf` had NO bound —
|
|
558
|
+
* a monitored process emitting megabytes without a single newline grew it without limit (the spool's
|
|
559
|
+
* own roll never covered it). Keep the TAIL (the newest bytes are the ones a watch is about). */
|
|
237
560
|
export declare const MONITOR_LINE_BUF_CAP = 1048576;
|
|
561
|
+
/** RB-239 ([1937] M2): the monitor event-result clip, shared by the watcher's batch/terminal emits and
|
|
562
|
+
* the stop-time drain emit (one clip, one truncation wording). */
|
|
238
563
|
export declare function clipMonitorEvent(s: string): string;
|
|
564
|
+
/** RB-334 (CC `DCo` leg): per-line clip applied to the `lines[]` a batch carries. Spool untouched. */
|
|
239
565
|
export declare function clipMonitorLine(s: string): string;
|
|
566
|
+
/**
|
|
567
|
+
* RB-335 (CC `rFs` 220:507725-507743, all six branches verbatim): the ONE terminal-notification summary
|
|
568
|
+
* HEAD for a background command / monitor watch. Every terminal frame in the bash and monitor lanes
|
|
569
|
+
* composes its summary as `terminalTaskSummary(...)` plus this lane's own honest detail clause — the
|
|
570
|
+
* pre-RB-335 code had six hand-written phrasings whose comment claimed "no CC sample for those faces"
|
|
571
|
+
* while 220 carries a verbatim sample for every one of them (the `failed` branch was the concrete
|
|
572
|
+
* mismatch: sema said `failed (exit code N)`, CC says `failed with exit code N`).
|
|
573
|
+
*/
|
|
240
574
|
export declare function terminalTaskSummary(kind: "bash" | "monitor", label: string, status: "completed" | "failed" | "killed", exitCode?: number): string;
|
|
241
575
|
export declare const TASK_OUTPUT_MAX_CHARS = 160000;
|
|
576
|
+
/**
|
|
577
|
+
* CC `FHl` shape (pretty.js:458012-458016) when the task has an on-disk output file: TAIL-keep (a
|
|
578
|
+
* background command's latest output is the valuable end) behind a `[Truncated. Full output: <path>]`
|
|
579
|
+
* pointer so the model can Read the full spool. Without a file (workflow/agent results), keep the
|
|
580
|
+
* legacy head+tail middle-omission — there is no path to point at, and the head often carries status.
|
|
581
|
+
* RB-198 F4: the clip arithmetic itself moved to the shared {@link clipWithFilePointer} (a second caller,
|
|
582
|
+
* the foreground Bash tool, needed the SAME already-hardened RB-85/RB-112/RB-122 logic) — this wrapper
|
|
583
|
+
* only supplies the task-output budget.
|
|
584
|
+
*/
|
|
242
585
|
export declare function clipTaskOutput(s: string, fullOutputPath?: string): string;
|
|
243
586
|
export declare function statusFromBackground(status: string, exitCode?: number): SemaTaskStatus;
|
|
587
|
+
/** Rolling middle-drop bound for the bash spool, shared by the watcher's per-tick accumulate and the
|
|
588
|
+
* teardown settle's terminal flush: keep head+tail halves within `cap`, account the dropped middle in
|
|
589
|
+
* `rolledChars` (the honesty counter the poll face reports as permanently-dropped bytes).
|
|
590
|
+
*
|
|
591
|
+
* design/158 S2 (RB-364 半): `onDrop`, when given, is called SYNCHRONOUSLY (before this function
|
|
592
|
+
* returns) with exactly the middle substring being dropped — the ONE place that substring is ever
|
|
593
|
+
* materialized, so a caller wanting to preserve it (the monitor lane's spill-to-offload-store) does not
|
|
594
|
+
* need to re-derive the same slice arithmetic a second time. Every EXISTING caller (the background_bash
|
|
595
|
+
* lane, task-registry.ts) omits the 4th argument, so their behavior — return value AND `rolledChars`
|
|
596
|
+
* accounting — is untouched byte-for-byte; the callback is a pure side-channel hook. */
|
|
244
597
|
export declare function rollSpoolText(spool: {
|
|
245
598
|
rolledChars: number;
|
|
246
599
|
}, s: string, cap: number, onDrop?: (dropped: string) => void): string;
|
|
600
|
+
/** design/158 S2 (RB-364 半) — per-monitor-handle hard cap on cumulative CHARS (UTF-16 code units)
|
|
601
|
+
* spilled to the offload store (design/158 §3's S3 half, pulled forward alongside S2). Once a
|
|
602
|
+
* handle's running total reaches this, further rolled-off middles are simply not spilled —
|
|
603
|
+
* already-written segments stay readable (the poll disclosure says "earlier segments retained"),
|
|
604
|
+
* matching the pre-S2 loss shape for whatever is dropped PAST the cap. Exported so the boundary is a
|
|
605
|
+
* testable contract, not a buried literal.
|
|
606
|
+
*
|
|
607
|
+
* RB-396-b (回溯复查批, [c209-C] R2 C4① char/byte 同名异轴族): the constant used to be named
|
|
608
|
+
* `..._BYTES` while the ledger added `dropped.length` — chars, up to ~3× fewer than UTF-8 bytes on
|
|
609
|
+
* multibyte content. CHARS is the axis kept (name changed, arithmetic untouched) because it is the
|
|
610
|
+
* offload store family's own coordinate (`InMemoryToolResultStore.maxTotalChars` evicts by
|
|
611
|
+
* `content.length`; `ToolResultSlice.totalChars`) and the spool's `rolledChars` axis — one unit
|
|
612
|
+
* end-to-end; a `Buffer.byteLength` ledger here would sit crosswise to the store's own cap. */
|
|
247
613
|
export declare const MONITOR_SPILL_CAP_CHARS: number;
|
|
614
|
+
/** RB-238 ([1937] M1): fold one poll's env-side-loss disclosure into the spool's account. The env's
|
|
615
|
+
* tail buffer evicts its HEAD under pressure (node-execution-env 8MB bound) — those bytes are gone
|
|
616
|
+
* before any watcher ever saw them, which is a different loss than the registry-side `rolledChars`
|
|
617
|
+
* middle-drop. `bytesDroppedBeforeCursor` only counts bytes dropped before an unconsumed cursor, so
|
|
618
|
+
* summing successive polls never double-counts; an env that says only `truncated` (no byte figure)
|
|
619
|
+
* degrades to the unquantified flag. Shared by ALL THREE consumers of a background poll — the monitor
|
|
620
|
+
* watcher, the bash watcher, and the blocking pollBackgroundBash leg (one class, one arithmetic).
|
|
621
|
+
* The blocked-wait leg used to keep its own hand-rolled `dropped += bytesDroppedBeforeCursor ?? 0`
|
|
622
|
+
* accumulator, which ignored `truncated` outright: an env that discloses the loss WITHOUT a byte
|
|
623
|
+
* figure produced ZERO disclosure on that leg. It routes through here now — the header's former
|
|
624
|
+
* "already accounted this on its own" claim was describing exactly the half-accounting that made the
|
|
625
|
+
* degraded shape invisible. */
|
|
248
626
|
export declare function accountDroppedBytes(spool: {
|
|
249
627
|
droppedBytes?: number;
|
|
250
628
|
dropUnknown?: true;
|
|
@@ -252,10 +630,19 @@ export declare function accountDroppedBytes(spool: {
|
|
|
252
630
|
truncated?: boolean;
|
|
253
631
|
bytesDroppedBeforeCursor?: number;
|
|
254
632
|
}): void;
|
|
633
|
+
/** RB-238 ([1937] M1) — the POLL-FACE wording for env-side loss (the terminal/event-frame wording is
|
|
634
|
+
* {@link droppedGapNote}'s; the two faces differ by design and always have). One function so the two
|
|
635
|
+
* quantified/unquantified branches cannot drift between the three legs that render it: the monitor
|
|
636
|
+
* re-readable spool, the bash re-readable spool, and the bash blocked wait. Trailing newline included
|
|
637
|
+
* (it is a banner LINE above the stdout heading); "" when nothing was dropped. */
|
|
255
638
|
export declare function spoolDropNote(acct: {
|
|
256
639
|
droppedBytes?: number;
|
|
257
640
|
dropUnknown?: true;
|
|
258
641
|
}): string;
|
|
642
|
+
/** The re-readable spool fields {@link renderSpoolBody} reads — the intersection of the bash handle's
|
|
643
|
+
* optional `spool` and the monitor handle's mandatory one (both carry supersets: `mirrorFailed` is
|
|
644
|
+
* bash-only, `drainFailed`/`dropNotified` monitor-only). Declared as a named shape, not inlined, so
|
|
645
|
+
* the renderer's contract is one thing both lanes are checked against. */
|
|
259
646
|
export interface RenderableSpool {
|
|
260
647
|
stdout: string;
|
|
261
648
|
stderr: string;
|
|
@@ -266,27 +653,82 @@ export interface RenderableSpool {
|
|
|
266
653
|
droppedBytes?: number;
|
|
267
654
|
dropUnknown?: true;
|
|
268
655
|
}
|
|
656
|
+
/** The per-lane inputs {@link renderSpoolBody} cannot derive from the spool itself.
|
|
657
|
+
* `rolledExtraClause` / `drainNote` are PRE-RENDERED STRINGS, deliberately not booleans or a lane
|
|
658
|
+
* discriminator: the renderer must stay ignorant of which lane called it, otherwise the two monitor-only
|
|
659
|
+
* disclosures (design/158 S2 spill refs; RB-239 stop-time drain failure) come back as in-renderer
|
|
660
|
+
* branches on a kind switch — the exact shape that let the two hand-copied renderers drift in the first
|
|
661
|
+
* place. Both are "" on a lane that has no such disclosure. */
|
|
269
662
|
export interface SpoolBodyOptions {
|
|
663
|
+
/** The handle is still running (drives the "running" display status). */
|
|
270
664
|
running: boolean;
|
|
665
|
+
/** Fallback display status for a non-running handle with no recorded exit code. */
|
|
271
666
|
handleStatus: SemaTaskStatus;
|
|
667
|
+
/** The lane's filter+clip projection, applied to stdout and stderr alike. */
|
|
272
668
|
shape: (text: string) => string;
|
|
669
|
+
/** Appended INSIDE the roll note, before its newline ("" when the lane has no extra clause). */
|
|
273
670
|
rolledExtraClause: string;
|
|
671
|
+
/** A full banner line (own trailing newline) rendered after the drop note, or "". */
|
|
274
672
|
drainNote: string;
|
|
275
673
|
}
|
|
674
|
+
/** RB-238/RB-239/RB-240 ([1937] M1-M3) — the ONE renderer for a re-readable spool's TaskOutput body,
|
|
675
|
+
* shared by the monitor lane (pollMonitorLane) and the bash spool lane (pollBackgroundBash).
|
|
676
|
+
*
|
|
677
|
+
* Both faces were hand-copied twins carrying three real disclosure bugs' worth of wording (env-side
|
|
678
|
+
* eviction vs registry roll are SEPARATE notes, never merged; a self-inflicted background-timeout kill
|
|
679
|
+
* renders distinguishably from an external stop; a spool with a disclosed gap must stop advertising
|
|
680
|
+
* itself as "full") — kept in sync by a comment on each side telling the reader to make the same edit
|
|
681
|
+
* twice. The heading rule is the load-bearing one: any disclosed gap (env-side drop OR a failed
|
|
682
|
+
* stop-time drain) downgrades the heading, so a caller cannot add a gap note and forget the heading.
|
|
683
|
+
*
|
|
684
|
+
* NOT used by the blocked-wait leg: that face is a consume-once "new stdout" increment with its own
|
|
685
|
+
* wording ("accumulated char(s) dropped from the middle during the blocked wait"), an intentional
|
|
686
|
+
* divergence — it shares {@link accountDroppedBytes} + {@link spoolDropNote}, not this. */
|
|
276
687
|
export declare function renderSpoolBody(spool: RenderableSpool, opts: SpoolBodyOptions): string;
|
|
688
|
+
/** RB-238: the honesty suffix for frames over a spool with env-side loss. Empty when nothing dropped. */
|
|
277
689
|
export declare function droppedGapNote(spool: {
|
|
278
690
|
droppedBytes?: number;
|
|
279
691
|
dropUnknown?: true;
|
|
280
692
|
}): string;
|
|
693
|
+
/** RB-238: the event-stream disclosure rides the FIRST batch after a loss is observed (once-latch —
|
|
694
|
+
* a chatty watch must not repeat the note on every batch; terminal frames disclose unconditionally). */
|
|
281
695
|
export declare function firstDropNote(spool: {
|
|
282
696
|
droppedBytes?: number;
|
|
283
697
|
dropUnknown?: true;
|
|
284
698
|
dropNotified?: true;
|
|
285
699
|
}): string;
|
|
700
|
+
/** RB-244 ([1937] T1): ONE wording for "you stopped nothing" across every already-terminal stop face —
|
|
701
|
+
* the in-process bash/monitor/agent arms and the durable-row fallback previously split: the durable
|
|
702
|
+
* arm answered honestly while the in-process arms claimed `Terminated <id>.` over work that finished
|
|
703
|
+
* (or was killed) on its own. CC 220 refuses the call outright (`Task X is not running (status: …)`,
|
|
704
|
+
* 220:468231-468236); sema keeps the idempotent no-op posture (stopWorkflow / durable-arm precedent,
|
|
705
|
+
* no isError) but the receipt must tell the truth. */
|
|
286
706
|
export declare function alreadyTerminalStopNote(id: string, status: string): string;
|
|
707
|
+
/** design/115 review B1 → β 批 A-2: register-side fail-fast, now on BOTH axes — `canAccess` is
|
|
708
|
+
* default-deny, so a handle missing either axis would be unreachable by every caller (a dead row
|
|
709
|
+
* is worse than a loud registration error). The production chain always sets both (hostTaskId +
|
|
710
|
+
* principal-or-"default"); a direct registry caller declares its access domain explicitly
|
|
711
|
+
* (`scope: "default"` is the single-tenant spelling — explicit, never implied). */
|
|
287
712
|
export declare function assertOwnership(input: TaskAccess, site: string): void;
|
|
713
|
+
/** γ 批 B-1 (2026-07-22, [1510] 同窗) — POSITIVE-MATCH form, one polarity with `canAccess`/
|
|
714
|
+
* `canAccessAgentRecord` (β 批 A-2): scope must match, then the caller must HIT an arm — owner
|
|
715
|
+
* (the spawning task) or SESSION (the run's `originatingSessionId`). The session arm is the B-1
|
|
716
|
+
* HIGH fix: the completion notification routes back to the originating SESSION, but per-turn
|
|
717
|
+
* taskIds die with their turn — before this arm, a later turn of the same session could not poll
|
|
718
|
+
* or stop its own workflow (default-deny functional breakage, [1502] R4 sibling). The old form's
|
|
719
|
+
* `access.owner === undefined ⇒ pass` scope-only residue is gone with the same β polarity ruling
|
|
720
|
+
* (design/136 §2.3 S-1 定谳 posture, now positive-match on every arm). Exported: the run-workflow
|
|
721
|
+
* tool's resume-ownership recheck and a deployment's serving layer apply the SAME predicate. */
|
|
288
722
|
export declare function canAccessWorkflowRun(run: Pick<WorkflowRun, "scope" | "sourceTaskId" | "originatingSessionId">, access: TaskAccess): boolean;
|
|
289
723
|
export declare function formatWorkflowRun(run: WorkflowRun): UnifiedTaskResult;
|
|
724
|
+
/** design/157 B13 一期定稿(二期细察补充 §「私有成员解法」)——the kernel-面 seam the MON/WF lane free
|
|
725
|
+
* functions call through instead of `this`: exactly the 5 members `startMonitorWatcher`/`stopMonitor`/
|
|
726
|
+
* `registerMonitor`/`registerWorkflow` actually reach into (`this.*` 耦合 grep 逐方法统计,见 B13 档).
|
|
727
|
+
* Does NOT include `fireServedTerminal` (WF-private helper, only called from within `pollWorkflow`
|
|
728
|
+
* itself — travels with the lane, never crosses the core seam) nor any AGENT-domain member (二期 extends
|
|
729
|
+
* this as `DurableAgentCore` per B13 §「私有成员解法」). The TaskRegistry class satisfies this via a
|
|
730
|
+
* `#coreView`-style cached object (`private readonly core: RegistryCore`), declared AFTER `handles` so
|
|
731
|
+
* the eager `handles` field reference below sees an already-initialized Map. */
|
|
290
732
|
export interface RegistryCore {
|
|
291
733
|
handles: Map<string, RegisteredTaskHandle>;
|
|
292
734
|
mintTaskId(type: SemaTaskType): string;
|
|
@@ -294,20 +736,62 @@ export interface RegistryCore {
|
|
|
294
736
|
notifyTerminalOnce(handle: BackgroundBashTaskHandle | MonitorTaskHandle, send: () => void): void;
|
|
295
737
|
pokeBgQuiescence(owner: string | undefined): void;
|
|
296
738
|
}
|
|
739
|
+
/** codex S1a F2 — writer-lease renewal period for armed durable rows (see ensureDurableHeartbeat).
|
|
740
|
+
* Exported so deployments size `staleRunningMaxAgeMs` against it (recommend ≥10× this). */
|
|
297
741
|
export declare const DURABLE_AGENT_HEARTBEAT_MS = 60000;
|
|
742
|
+
/** design/151 S1a (codex F3): the durable fallback consults the store ONLY for handle-shaped ids —
|
|
743
|
+
* a NAME (the fuzzy stop leg) or a foreign-domain id must not take a store round-trip, and a store
|
|
744
|
+
* outage must never block the local name-resolution ladder. Mint form: `a` + 16 hex; the revive
|
|
745
|
+
* leg re-registers the same form.
|
|
746
|
+
* EXPORTED ([1518] server ask): a serving layer's fallback needs the SAME shape gate before its
|
|
747
|
+
* durable arm (a bare exact-key miss lets padded/legacy/name-shaped ids leak into live branches —
|
|
748
|
+
* the server 1.250 HIGH) — one shared regex kills the drift, roster-normalize precedent. */
|
|
298
749
|
export declare const DURABLE_AGENT_HANDLE_RE: RegExp;
|
|
750
|
+
/** Synthetic settle error the subagent reap path passes after a stop/parent teardown. It is NOT a
|
|
751
|
+
* real child error — settleBackgroundAgent never stores it (status "killed" + stoppedBy already say
|
|
752
|
+
* it); exported so the subagent call sites and the registry agree on the exact sentinel. */
|
|
299
753
|
export declare const BG_AGENT_REAP_STOP_ERROR = "stopped (parent task ended or TaskStop)";
|
|
754
|
+
/** CC206-B 欠账 — TaskStop name addressing, CC `XN` verbatim (206:574955-574962): NFKC-normalize, strip
|
|
755
|
+
* control/format chars (whitespace-class ones survive), trim, lowercase, whitespace runs → hyphens. Both
|
|
756
|
+
* the query and the candidate label go through this, so "Fix Tests" addresses "fix tests".
|
|
757
|
+
* [c209-D] codex R4: EXPORTED — SendMessage's "main" reserved lane must use the SAME canonicalization
|
|
758
|
+
* as this resolver, or an NFKC-equivalent spelling (fullwidth "main") skips the reserved lane and
|
|
759
|
+
* reaches the description layers. One normalizer, every name face. */
|
|
300
760
|
export declare function normalizeAgentName(s: string): string;
|
|
761
|
+
/** CC `gtr` (fable 复审 F1 — 亲核 @16169850: NOT plain Levenshtein but OSA / restricted
|
|
762
|
+
* Damerau-Levenshtein, WITH the adjacent-transposition term `o[i][s]=min(o[i][s], o[i-2][s-2]+1)`
|
|
763
|
+
* when `e[i-1]===t[s-2] && e[i-2]===t[s-1]`). The transposition matters: a typo like "tset"→"test"
|
|
764
|
+
* is distance 1 (CC has a Did-you-mean), plain Levenshtein would call it 2. */
|
|
301
765
|
export declare function editDistance(a: string, b: string): number;
|
|
766
|
+
/** CC `htr` shape (206:519814-519827): candidates within Levenshtein ≤2 (length-diff ≤2 pre-filter),
|
|
767
|
+
* best-first; the single best is the "Did you mean" suggestion (`htr(e, keys, 1)[0]`, 206:575196). */
|
|
302
768
|
export declare function closestName(query: string, candidates: Iterable<string>): string | undefined;
|
|
769
|
+
/** β 批 A-2 (clay 裁定 2026-07-22, 一步到位): DEFAULT-DENY on BOTH axes — the old predicate skipped
|
|
770
|
+
* a missing axis (owner-less handle = readable by everyone in scope; scope-less handle = readable
|
|
771
|
+
* across scopes), splitting polarity with `canAccessAgentRecord` and re-opening the session-axis
|
|
772
|
+
* class cli/server just swept. Registration now REQUIRES both axes ({@link assertOwnership}), so a
|
|
773
|
+
* missing axis here is a broken invariant, answered with denial, never a pass. */
|
|
303
774
|
export declare function canAccess(handle: SemaTaskHandle, access: TaskAccess): boolean;
|
|
775
|
+
/** design/157 B13 二期(B13 档预调研 §4.2/§4.3 定稿)— the durable-agent lane's widened core seam.
|
|
776
|
+
* Extends {@link RegistryCore} with EXACTLY the 5 extra members the AGENT lane's `this.*` census
|
|
777
|
+
* reached (73 处/9 成员,扣车道内互调后落在这 5 个上,见 B13 档「二期细察补充」)。
|
|
778
|
+
* `durableAgentWrite`/`ensureDurableHeartbeat`/`settleBackgroundAgent` are NOT here — they are lane
|
|
779
|
+
* members themselves (车道内直接函数调用;类上只留转发或不留)。The class satisfies this via the
|
|
780
|
+
* same cached-view field, upgraded with lazy getter/setter proxies (an IIFE capturing `this`) so
|
|
781
|
+
* field declaration ORDER no longer constrains it — `writerId`/`reapingHandles` 등 are read at
|
|
782
|
+
* call time, after construction completes. */
|
|
304
783
|
export interface DurableAgentCore extends RegistryCore {
|
|
305
784
|
readonly writerId: string;
|
|
306
785
|
readonly reapingHandles: Set<string>;
|
|
307
786
|
readonly claimingHandles: Set<string>;
|
|
787
|
+
/** get/set proxy — `ensureDurableHeartbeatLane` both reads AND writes the timer slot. */
|
|
308
788
|
durableHeartbeatTimer: ReturnType<typeof setInterval> | undefined;
|
|
309
789
|
readonly deliverConfirmTimeoutMs: number;
|
|
310
790
|
}
|
|
791
|
+
/** design/153 §7.2c (件3b) — the compensable reservation ticket {@link TaskRegistry.claimParkedAgent}
|
|
792
|
+
* returns: everything {@link TaskRegistry.rollbackParkedClaim} and the 件3c consume flip need to
|
|
793
|
+
* proceed or compensate. `row` is the PRE-RESERVATION snapshot (restored verbatim on rollback);
|
|
794
|
+
* `reservedRev` is the row's rev AFTER the reservation CAS (the next guarded write binds to it). */
|
|
311
795
|
export interface ParkedClaimTicket {
|
|
312
796
|
handle: string;
|
|
313
797
|
scope: string;
|
|
@@ -316,29 +800,85 @@ export interface ParkedClaimTicket {
|
|
|
316
800
|
reservedRev: number;
|
|
317
801
|
row: import("./background-agent-store.js").BackgroundAgentRecord;
|
|
318
802
|
}
|
|
803
|
+
/** P1-3 独立复审第三轮(已修) — sibling of {@link mintCompletionId} for a caller that must compute the
|
|
804
|
+
* value BEFORE it is safe to commit (a CAS not yet known to win): fill-once with an EXTERNALLY-chosen
|
|
805
|
+
* value instead of generating a fresh one. Exists because `rollbackParkedClaim`'s original fix minted
|
|
806
|
+
* directly onto the live handle before its durable CAS was confirmed — a losing CAS then left a
|
|
807
|
+
* non-terminal ("parked") handle carrying a completionId nothing ever cleared, which a later legitimate
|
|
808
|
+
* parked→running flip (`consumeParkedFlip`) silently carried into an unrelated real completion via
|
|
809
|
+
* `mintCompletionId`'s own fill-once guard (independently reproduced end-to-end). The fix: compute the
|
|
810
|
+
* candidate once, use it in the durable payload immediately (that write is fine — it only takes effect
|
|
811
|
+
* if its own CAS wins), and commit it to the live handle ONLY from the call that already knows the CAS
|
|
812
|
+
* won. */
|
|
319
813
|
export declare function commitCompletionIdIfEmpty(target: {
|
|
320
814
|
completionId?: string;
|
|
321
815
|
}, value: string): string;
|
|
322
816
|
export interface RegisterBackgroundAgentInput extends TaskAccess {
|
|
817
|
+
/** design/153 §7.2d (件3c) — parked-resume registration shape: the handle is born PARKED (the
|
|
818
|
+
* pre-consume window keeps the live face's checkpoint arbitration; the consume flip
|
|
819
|
+
* {@link TaskRegistry.adoptParkedResume} is the only path to running). Pass the ticket's token
|
|
820
|
+
* and a stop-arbitration closure alongside. Also licenses replacing an in-process PARKED prior
|
|
821
|
+
* handle of the same id (the planned park→resume handoff; lane poisoned like the terminal replace). */
|
|
323
822
|
initialStatus?: "parked";
|
|
823
|
+
/** design/153 §7.2d — the parked checkpoint token this parked-born handle waits on. */
|
|
324
824
|
parkedCheckpointToken?: string;
|
|
825
|
+
/** design/153 §7.2d — the TaskStop arbitration closure for the parked-born handle (expire CAS). */
|
|
325
826
|
resolveParkedStop?: () => Promise<boolean>;
|
|
827
|
+
/** design/147 S2a (codex R5 F7) — declare that the spawner WILL attach a mid-run delivery
|
|
828
|
+
* channel (attachAgentNotify) once the child's lane binds. Only declared-"attaching" rows buffer
|
|
829
|
+
* startup-window messages; an undeclared row refuses `no_channel` IMMEDIATELY — a spawner that
|
|
830
|
+
* never attaches must not collect acknowledged-then-discarded messages (silent loss). */
|
|
326
831
|
deliveryChannel?: "attaching";
|
|
832
|
+
/** S2b RB-27① codex F1 — the spawner DECLARES whether a parked message is redeemable: true when
|
|
833
|
+
* the child's session outlives the run (retain ledger or session-scoped registration), so a
|
|
834
|
+
* continuation can drain the park. A non-retained row must NOT hand out parked acknowledgements
|
|
835
|
+
* (the session is released right after settle — the park would be irrecoverable): its
|
|
836
|
+
* lane-dead race window reads as `not_running` instead, steering the sender to the settled path. */
|
|
327
837
|
retainedContinuation?: boolean;
|
|
328
838
|
description?: string;
|
|
839
|
+
/** [c209-D] explicit addressing name (CC Agent.name parity) — the CALLER validates it (charset +
|
|
840
|
+
* reserved "main") before registration; the registry stores it verbatim. Duplicate names are legal
|
|
841
|
+
* (latest-wins at resolution; older rows stay task_id-addressable). */
|
|
329
842
|
name?: string;
|
|
843
|
+
/** [1358]/[1336]A — the RESOLVED subagent type ("general-purpose"/"fork"/a roster name), persisted
|
|
844
|
+
* so a REVIVE cycle's observer frames can reproduce the row's TYPE column (never the description). */
|
|
330
845
|
agentType?: string;
|
|
846
|
+
/** [1371]② — the spawn frame's parent linkage, persisted so a REVIVE cycle's spawn frame nests the
|
|
847
|
+
* revived row exactly like the first spawn did. The caller passes the SAME values it emitted on the
|
|
848
|
+
* original frame (parentTaskId already [1344]②-clamped there; parentSessionId always-on). */
|
|
331
849
|
parentTaskId?: string;
|
|
332
850
|
parentSessionId?: string;
|
|
851
|
+
/** δ 批 [1498]⑦ — the ROOT host session of the delegation tree (fixed point down the trusted
|
|
852
|
+
* internals chain; equals parentSessionId at depth 1). Persisted on the handle, the durable row
|
|
853
|
+
* and the roster so recovery faces enumerate the whole tree under the root without alias walks. */
|
|
333
854
|
rootSessionId?: string;
|
|
855
|
+
/** design/151 S3b — revival lookup keys (CC meta-sidecar shape): the RESOLVED model id and the
|
|
856
|
+
* team name, persisted on the durable row so a tier-3 revival rebuilds the spec the way a fresh
|
|
857
|
+
* named-teammate spawn would. Lookup keys only, never a serialized spec. */
|
|
334
858
|
model?: string;
|
|
335
859
|
teamName?: string;
|
|
336
860
|
toolUseId?: string;
|
|
337
861
|
abort: AbortController;
|
|
338
862
|
now?: number;
|
|
863
|
+
/** design/129: register as session-scoped (owner MUST be the sessionId; see the handle flag). */
|
|
339
864
|
sessionScoped?: true;
|
|
865
|
+
/** design/151 S1a (LOW-12): caller-supplied handle — the tier-3 revival leg (S3) re-registers the
|
|
866
|
+
* SAME durable handle so the row stays continuous across restarts. Collision with a live in-memory
|
|
867
|
+
* row throws (registerBackgroundBash parity). Absent ⇒ mint. */
|
|
340
868
|
id?: string;
|
|
869
|
+
/** design/151 S1a: the durable execution-row ledger. Present (with BOTH owner and scope — the
|
|
870
|
+
* durable predicate is fail-closed on both axes) ⇒ this registration writes a durable row
|
|
871
|
+
* (put → bind → settle, a serialized best-effort single-writer lane); absent ⇒ the pre-151
|
|
872
|
+
* in-memory-only lifecycle, byte for byte. */
|
|
341
873
|
store?: BackgroundAgentStore;
|
|
874
|
+
/** design/151 §7.2 (X-2/F-7) — tier-3 revival lane seeding: the CLAIMED durable row (identity
|
|
875
|
+
* inherited verbatim, status running, writerId = this instance) and its post-claim rev. Present
|
|
876
|
+
* ⇒ the durable lane starts from this snapshot with `written: true` and SKIPS the initial put
|
|
877
|
+
* (the claim-CAS already committed the row); every later write CASes against `rev`, so the first
|
|
878
|
+
* settle moves the claim forward instead of losing to it. Also authorizes REPLACING a leftover
|
|
879
|
+
* TERMINAL in-memory handle of the same id (the pre-revival cycle's row survives ~1h of terminal
|
|
880
|
+
* GC): its stale lane is silenced first — a queued/re-driven write from it carries the pre-claim
|
|
881
|
+
* rev under this process's own writerId, and the adopt path would clobber the claim. */
|
|
342
882
|
durableSeed?: {
|
|
343
883
|
record: BackgroundAgentRecord;
|
|
344
884
|
rev: number;
|