@sema-agent/core 7.54.1 → 7.55.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 +437 -0
- package/dist/agents/agent-transcript-tool.js +2 -1
- package/dist/agents/builtin-agents.d.ts +12 -14
- package/dist/agents/cc-peer-directory.d.ts +36 -0
- package/dist/agents/cc-peer-directory.js +138 -0
- package/dist/agents/cc-peer-wire.d.ts +105 -0
- package/dist/agents/cc-peer-wire.js +98 -0
- package/dist/agents/cc-uds-peer-channel.d.ts +40 -0
- package/dist/agents/cc-uds-peer-channel.js +457 -0
- package/dist/agents/cross-session-envelope.d.ts +4 -1
- package/dist/agents/cross-session-envelope.js +8 -1
- package/dist/agents/cross-session-judge.d.ts +2 -2
- package/dist/agents/list-agents-tool.js +2 -1
- package/dist/agents/observer.d.ts +4 -5
- package/dist/agents/observer.js +2 -1
- package/dist/agents/peer-admission.d.ts +6 -0
- package/dist/agents/peer-admission.js +4 -1
- package/dist/agents/peer-directory.d.ts +43 -9
- package/dist/agents/peer-directory.js +66 -23
- package/dist/agents/peer-notices.d.ts +1 -1
- package/dist/agents/peer-session-drain.d.ts +3 -1
- package/dist/agents/peer-session-drain.js +1 -0
- package/dist/agents/read-inbox-tool.js +2 -1
- package/dist/agents/retain-ledger.d.ts +1 -1
- package/dist/agents/roster-store.d.ts +1 -1
- package/dist/agents/send-message-tool.d.ts +10 -0
- package/dist/agents/send-message-tool.js +34 -5
- package/dist/agents/subagent.d.ts +34 -79
- package/dist/agents/subagent.js +45 -46
- package/dist/agents/tool-filter.d.ts +29 -46
- package/dist/agents/tool-filter.js +8 -31
- package/dist/agents/verify.d.ts +3 -3
- package/dist/brain/anthropic.js +14 -9
- package/dist/brain/errors.d.ts +15 -0
- package/dist/brain/errors.js +10 -0
- package/dist/brain/model-presets.d.ts +4 -4
- package/dist/brain/open-responses.js +15 -10
- package/dist/brain/openai.js +17 -12
- package/dist/brain/provider-dialect.d.ts +39 -3
- package/dist/brain/provider-dialect.js +28 -0
- package/dist/brain/reasoning.d.ts +1 -1
- package/dist/brain/request-params.d.ts +55 -5
- package/dist/brain/request-params.js +35 -3
- package/dist/brain/retry.d.ts +1 -1
- package/dist/brain/route-adjudicator.d.ts +15 -0
- package/dist/brain/route-adjudicator.js +15 -0
- package/dist/brain/stream-engine.js +6 -5
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/core/advisor-verdict.d.ts +120 -0
- package/dist/core/advisor-verdict.js +92 -0
- package/dist/core/agent-definition.d.ts +7 -8
- package/dist/core/allow-entry.d.ts +49 -23
- package/dist/core/allow-entry.js +57 -32
- package/dist/core/allow-rule-shadow.d.ts +7 -0
- package/dist/core/approval-object.d.ts +2 -1
- package/dist/core/approval-object.js +6 -6
- package/dist/core/ask-origin.d.ts +63 -11
- package/dist/core/ask-origin.js +27 -5
- package/dist/core/ask-question.js +10 -4
- package/dist/core/auto-compaction.d.ts +11 -8
- package/dist/core/auto-compaction.js +4 -2
- package/dist/core/auto-mode-arming.d.ts +2 -2
- package/dist/core/auto-mode-defaults.d.ts +8 -8
- package/dist/core/auto-mode-prompt-assets.d.ts +3 -3
- package/dist/core/auto-mode-prompt.d.ts +1 -1
- package/dist/core/auto-mode.d.ts +17 -9
- package/dist/core/auto-mode.js +9 -6
- package/dist/core/background-agent-store.d.ts +3 -3
- package/dist/core/canonical-json.d.ts +1 -1
- package/dist/core/canonical-json.js +2 -2
- package/dist/core/checkpoint-requirements.d.ts +6 -3
- package/dist/core/checkpoint-requirements.js +4 -14
- package/dist/core/checkpoint-store.d.ts +80 -51
- package/dist/core/checkpoint-store.js +56 -74
- package/dist/core/child-clamp-seats.d.ts +6 -0
- package/dist/core/child-clamp-seats.js +3 -16
- package/dist/core/compliance.d.ts +2 -2
- package/dist/core/context-edit.d.ts +6 -7
- package/dist/core/cross-boundary-taint.d.ts +9 -3
- package/dist/core/cross-boundary-taint.js +5 -3
- package/dist/core/decision-receipt.js +2 -2
- package/dist/core/effective-path-target.d.ts +1 -1
- package/dist/core/engine-notice.d.ts +19 -5
- package/dist/core/exec-output-tail.d.ts +1 -1
- package/dist/core/file-history-retention.d.ts +1 -1
- package/dist/core/file-history-store.d.ts +59 -9
- package/dist/core/file-history-store.js +35 -17
- package/dist/core/gate-fold.js +3 -2
- package/dist/core/gate-lanes.js +12 -8
- package/dist/core/gate-outcome.d.ts +17 -4
- package/dist/core/gate-outcome.js +30 -0
- package/dist/core/governance-codes.d.ts +13 -3
- package/dist/core/governance-codes.js +10 -0
- package/dist/core/hands-band.d.ts +1 -1
- package/dist/core/hooks.d.ts +4 -4
- package/dist/core/host-target.d.ts +49 -0
- package/dist/core/host-target.js +59 -0
- package/dist/core/image-downsample.d.ts +1 -1
- package/dist/core/lsp-diagnostics.d.ts +4 -4
- package/dist/core/lsp.d.ts +3 -3
- package/dist/core/mailbox-store.d.ts +4 -0
- package/dist/core/mcp-connection-pool.d.ts +18 -2
- package/dist/core/mcp-connection-pool.js +53 -6
- package/dist/core/mcp-failure.d.ts +23 -4
- package/dist/core/mcp-failure.js +26 -11
- package/dist/core/mcp-listing-drift.d.ts +10 -0
- package/dist/core/mcp-listing-drift.js +6 -0
- package/dist/core/mcp-server-link.d.ts +173 -0
- package/dist/core/mcp-server-link.js +127 -0
- package/dist/core/mcp-server-spec.d.ts +4 -2
- package/dist/core/mcp-session-end.d.ts +26 -0
- package/dist/core/mcp-session-end.js +29 -0
- package/dist/core/mcp-startup-request.d.ts +17 -0
- package/dist/core/mcp-startup-request.js +17 -0
- package/dist/core/mcp.d.ts +13 -13
- package/dist/core/mcp.js +187 -162
- package/dist/core/media-byte-cap.d.ts +1 -1
- package/dist/core/memory-engine/engine.d.ts +9 -9
- package/dist/core/memory-engine/provenance-wording.d.ts +1 -1
- package/dist/core/memory-engine/tools.js +4 -1
- package/dist/core/mode-policy.d.ts +1 -1
- package/dist/core/namespaced-rule-name.d.ts +33 -7
- package/dist/core/namespaced-rule-name.js +39 -25
- package/dist/core/output-style.d.ts +1 -1
- package/dist/core/param-rule-reach.d.ts +15 -0
- package/dist/core/param-rule-reach.js +30 -0
- package/dist/core/parent-spec-seat.d.ts +8 -1
- package/dist/core/parent-spec-seat.js +4 -0
- package/dist/core/pause-registry.d.ts +16 -5
- package/dist/core/pause-registry.js +6 -2
- package/dist/core/peer-channel.d.ts +70 -0
- package/dist/core/peer-channel.js +1 -0
- package/dist/core/permission-rule-consent.d.ts +11 -5
- package/dist/core/permission-rule-consent.js +37 -30
- package/dist/core/permission-rule-model.d.ts +233 -64
- package/dist/core/permission-rule-model.js +384 -85
- package/dist/core/permission-rule-provider.d.ts +2 -1
- package/dist/core/permission-rule-store.d.ts +20 -25
- package/dist/core/permission-rule-store.js +1 -4
- package/dist/core/permission-rule-sync.d.ts +11 -2
- package/dist/core/permission-rule-sync.js +8 -1
- package/dist/core/permission-rules.d.ts +49 -11
- package/dist/core/permission-rules.js +123 -89
- package/dist/core/persisted-rule-arms.d.ts +4 -2
- package/dist/core/present-plan-tool.js +3 -1
- package/dist/core/protocol-naming.d.ts +2 -2
- package/dist/core/read-only-shell-table.d.ts +1 -1
- package/dist/core/read-only-shell.d.ts +1 -1
- package/dist/core/roles.d.ts +6 -2
- package/dist/core/roles.js +45 -44
- package/dist/core/rule-offer-read.d.ts +53 -0
- package/dist/core/rule-offer-read.js +146 -0
- package/dist/core/rule-owner.d.ts +46 -0
- package/dist/core/rule-owner.js +28 -0
- package/dist/core/runner/advisor-instructions.d.ts +70 -0
- package/dist/core/runner/advisor-instructions.js +61 -0
- package/dist/core/runner/advisor-tool.d.ts +33 -0
- package/dist/core/runner/advisor-tool.js +112 -0
- package/dist/core/runner/announce-once-ledger.d.ts +4 -26
- package/dist/core/runner/announce-once-ledger.js +14 -46
- package/dist/core/runner/approval-feedback.js +6 -3
- package/dist/core/runner/assemble-result.d.ts +1 -1
- package/dist/core/runner/caller-roster.d.ts +7 -0
- package/dist/core/runner/caller-roster.js +11 -0
- package/dist/core/runner/classifier-ladder.d.ts +27 -5
- package/dist/core/runner/classifier-ladder.js +12 -11
- package/dist/core/runner/compaction-restate.d.ts +10 -6
- package/dist/core/runner/compaction-restate.js +9 -3
- package/dist/core/runner/contracts.d.ts +13 -9
- package/dist/core/runner/conversation-segment.d.ts +28 -0
- package/dist/core/runner/conversation-segment.js +42 -0
- package/dist/core/runner/cross-boundary-lane.d.ts +6 -5
- package/dist/core/runner/cross-boundary-lane.js +26 -15
- package/dist/core/runner/decide-continuation.d.ts +7 -4
- package/dist/core/runner/decide-continuation.js +2 -2
- package/dist/core/runner/denial-limit-arms.d.ts +2 -2
- package/dist/core/runner/derived-route-fallback.d.ts +24 -24
- package/dist/core/runner/derived-route-fallback.js +9 -7
- package/dist/core/runner/gate-exit.d.ts +6 -0
- package/dist/core/runner/gate-exit.js +7 -2
- package/dist/core/runner/initial-run-state.js +1 -1
- package/dist/core/runner/permission-rule-lanes.d.ts +2 -2
- package/dist/core/runner/permission-rule-lanes.js +14 -7
- package/dist/core/runner/person-path-rows.js +1 -1
- package/dist/core/runner/prepare-advisor.d.ts +63 -0
- package/dist/core/runner/prepare-advisor.js +77 -0
- package/dist/core/runner/prepare-caps-and-workflow.js +1 -1
- package/dist/core/runner/prepare-config-doors.d.ts +6 -4
- package/dist/core/runner/prepare-config-doors.js +18 -12
- package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
- package/dist/core/runner/prepare-delegation-surface.js +1 -1
- package/dist/core/runner/prepare-file-history.js +39 -39
- package/dist/core/runner/prepare-gate-stations.d.ts +1 -4
- package/dist/core/runner/prepare-gate-stations.js +2 -7
- package/dist/core/runner/prepare-inherited-gate.d.ts +5 -4
- package/dist/core/runner/prepare-inherited-gate.js +3 -3
- package/dist/core/runner/prepare-park-ask.js +7 -7
- package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
- package/dist/core/runner/prepare-policy-chain.js +4 -10
- package/dist/core/runner/prepare-project-context.d.ts +5 -2
- package/dist/core/runner/prepare-project-context.js +6 -3
- package/dist/core/runner/prepare-prompt-inputs.js +1 -1
- package/dist/core/runner/prepare-protocol-tools.d.ts +2 -2
- package/dist/core/runner/prepare-protocol-tools.js +3 -2
- package/dist/core/runner/prepare-safety-scan.d.ts +9 -12
- package/dist/core/runner/prepare-safety-scan.js +8 -6
- package/dist/core/runner/prepare-task.js +15 -18
- package/dist/core/runner/prepare-tool-disclosure-mount.js +6 -4
- package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -3
- package/dist/core/runner/prepare-wiring-manifest.js +2 -2
- package/dist/core/runner/resume-policy-outcome.js +1 -1
- package/dist/core/runner/retired-runner-deps.js +1 -1
- package/dist/core/runner/run-attachment-seats.js +0 -1
- package/dist/core/runner/run-compaction-machinery.d.ts +1 -1
- package/dist/core/runner/run-compaction-machinery.js +2 -12
- package/dist/core/runner/run-git-lane.d.ts +1 -0
- package/dist/core/runner/run-harness-handlers.js +2 -3
- package/dist/core/runner/run-leg.js +13 -0
- package/dist/core/runner/run-settle-and-teardown.js +1 -1
- package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
- package/dist/core/runner/run-turn-boundary.d.ts +1 -0
- package/dist/core/runner/run-turn-boundary.js +14 -12
- package/dist/core/runner/session-rule-policy.d.ts +22 -21
- package/dist/core/runner/session-rule-policy.js +13 -28
- package/dist/core/runner/side-call-account.d.ts +32 -8
- package/dist/core/runner/side-call-account.js +23 -1
- package/dist/core/runner/strict-output-schema.d.ts +1 -1
- package/dist/core/runner/sub-agent-deny-lists.js +4 -3
- package/dist/core/runner/synthetic-tools.d.ts +10 -13
- package/dist/core/runner/synthetic-tools.js +4 -2
- package/dist/core/runner/tool-disclosure.js +2 -1
- package/dist/core/runner/tool-face-overlay.d.ts +2 -1
- package/dist/core/runner/tool-face-overlay.js +17 -1
- package/dist/core/runner/tool-progress-lane.d.ts +2 -2
- package/dist/core/runner/tool-turn-repair-seat.d.ts +3 -2
- package/dist/core/runner/turn-attachments.d.ts +60 -67
- package/dist/core/runner-deps.d.ts +37 -37
- package/dist/core/runtime-caps.d.ts +4 -4
- package/dist/core/safety-merge-corpus.js +17 -1
- package/dist/core/same-plain-value.d.ts +40 -0
- package/dist/core/same-plain-value.js +49 -0
- package/dist/core/scheduler.d.ts +1 -1
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/sensitive-path-policy.js +1 -1
- package/dist/core/session-policy-store.d.ts +77 -22
- package/dist/core/session-policy-store.js +56 -14
- package/dist/core/session-reconcile.d.ts +2 -2
- package/dist/core/session-store.d.ts +80 -30
- package/dist/core/session-store.js +118 -76
- package/dist/core/session.d.ts +24 -46
- package/dist/core/shared-memory/tools.js +3 -1
- package/dist/core/shared-memory/types.d.ts +1 -1
- package/dist/core/side-query.d.ts +10 -0
- package/dist/core/side-query.js +5 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +29 -2
- package/dist/core/store-contracts/file-history-store-contract.js +43 -3
- package/dist/core/store-contracts/session-policy-store-contract.d.ts +7 -0
- package/dist/core/store-contracts/session-policy-store-contract.js +130 -0
- package/dist/core/store-contracts/session-repo-contract.js +125 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +4 -7
- package/dist/core/store-contracts/session-store-contract.js +215 -41
- package/dist/core/store-contracts/workflow-journal-store-contract.js +26 -1
- package/dist/core/surrogate-safe-slice.d.ts +3 -3
- package/dist/core/task-event.d.ts +10 -4
- package/dist/core/task-notification.d.ts +3 -3
- package/dist/core/task-registry-agent.d.ts +4 -4
- package/dist/core/task-registry-shared.d.ts +4 -4
- package/dist/core/task-registry-shared.js +1 -0
- package/dist/core/task-registry.d.ts +4 -4
- package/dist/core/task-registry.js +3 -1
- package/dist/core/task-result.d.ts +3 -3
- package/dist/core/task-spec.d.ts +52 -52
- package/dist/core/task-stream.d.ts +6 -6
- package/dist/core/task-tool-shape.d.ts +4 -4
- package/dist/core/tighten-task-spec.d.ts +1 -1
- package/dist/core/tool-catalog-entries.d.ts +19 -2
- package/dist/core/tool-catalog-entries.js +57 -42
- package/dist/core/tool-conformance.js +1 -0
- package/dist/core/tool-errors.d.ts +2 -2
- package/dist/core/tool-face-reader.js +5 -3
- package/dist/core/tool-face.d.ts +21 -2
- package/dist/core/tool-face.js +1 -1
- package/dist/core/tool-model-gate.d.ts +3 -3
- package/dist/core/tool-name-aliases.d.ts +29 -8
- package/dist/core/tool-name-aliases.js +27 -3
- package/dist/core/tool-name-readings.d.ts +5 -8
- package/dist/core/tool-name-readings.js +1 -2
- package/dist/core/tool-policy.d.ts +24 -5
- package/dist/core/tool-policy.js +34 -10
- package/dist/core/tool-registry.d.ts +14 -7
- package/dist/core/tool-registry.js +17 -7
- package/dist/core/tool-result-store.js +2 -1
- package/dist/core/tool-roster.d.ts +47 -18
- package/dist/core/tool-roster.js +53 -32
- package/dist/core/tool-spec-members.js +1 -1
- package/dist/core/tool-spec.d.ts +35 -21
- package/dist/core/tools.js +3 -2
- package/dist/core/trace.d.ts +4 -0
- package/dist/core/untrusted-egress.d.ts +1 -1
- package/dist/core/untrusted-text.d.ts +1 -1
- package/dist/core/warm-resume.d.ts +1 -1
- package/dist/core/wiring-manifest.d.ts +49 -0
- package/dist/core/wiring-manifest.js +13 -5
- package/dist/core/workflow-journal-store.d.ts +62 -0
- package/dist/core/workflow-journal-store.js +77 -1
- package/dist/core/workflow-run-store.d.ts +6 -0
- package/dist/core/workflow-run-store.js +2 -0
- package/dist/engine/compaction/compaction.d.ts +9 -9
- package/dist/engine/execution-env/node-execution-env.d.ts +19 -5
- package/dist/engine/execution-env/node-execution-env.js +43 -22
- package/dist/engine/harness/agent-harness.d.ts +14 -8
- package/dist/engine/harness/agent-harness.js +33 -26
- package/dist/engine/harness/types.d.ts +29 -7
- package/dist/engine/harness/types.js +12 -1
- package/dist/engine/llm/types.d.ts +9 -9
- package/dist/engine/llm/validation.d.ts +4 -1
- package/dist/engine/llm/validation.js +13 -1
- package/dist/engine/loop/agent-loop.d.ts +1 -1
- package/dist/engine/loop/agent-loop.js +10 -8
- package/dist/engine/loop/types.d.ts +15 -13
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/memory-repo.d.ts +10 -11
- package/dist/engine/session/memory-repo.js +13 -8
- package/dist/engine/session/parent-chain-guard.d.ts +3 -2
- package/dist/engine/session/parent-chain-guard.js +1 -1
- package/dist/engine/session/repo-utils.d.ts +31 -3
- package/dist/engine/session/repo-utils.js +42 -5
- package/dist/index.d.ts +27 -15
- package/dist/index.js +21 -11
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/harness.d.ts +3 -3
- package/dist/internal/harness.js +2 -2
- package/dist/internal/llm.d.ts +1 -1
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/goal.js +2 -2
- package/dist/orchestration/run-workflow-tool.d.ts +2 -2
- package/dist/orchestration/run-workflow-tool.js +5 -3
- package/dist/orchestration/workflow-size-guideline.d.ts +4 -4
- package/dist/orchestration/workflow-types.d.ts +18 -0
- package/dist/orchestration/workflow-types.js +6 -0
- package/dist/orchestration/workflow.d.ts +2 -13
- package/dist/orchestration/workflow.js +21 -31
- package/dist/prompt-assembly/event-registry.js +1 -0
- package/dist/prompt-assembly/tool-catalog.d.ts +3 -0
- package/dist/prompt-assembly/tool-catalog.js +3 -0
- package/dist/prompts/default.d.ts +14 -14
- package/dist/scenarios/full-body.d.ts +4 -4
- package/dist/stores/file/adoption/adopt.d.ts +4 -3
- package/dist/stores/file/adoption/adopt.js +24 -31
- package/dist/stores/file/adoption/marker.d.ts +6 -13
- package/dist/stores/file/adoption/marker.js +6 -15
- package/dist/stores/file/checkpoint-store.d.ts +3 -0
- package/dist/stores/file/checkpoint-store.js +9 -3
- package/dist/stores/file/file-history-store.d.ts +20 -19
- package/dist/stores/file/file-history-store.js +152 -135
- package/dist/stores/file/fs-atomic.d.ts +15 -0
- package/dist/stores/file/fs-atomic.js +89 -14
- package/dist/stores/file/index.d.ts +1 -1
- package/dist/stores/file/mailbox-store.d.ts +3 -0
- package/dist/stores/file/mailbox-store.js +3 -1
- package/dist/stores/file/permission-rule-adopt.d.ts +1 -1
- package/dist/stores/file/permission-rule-adopt.js +15 -16
- package/dist/stores/file/permission-rule-store.d.ts +18 -2
- package/dist/stores/file/permission-rule-store.js +21 -14
- package/dist/stores/file/session-policy-store.d.ts +3 -3
- package/dist/stores/file/session-store.d.ts +26 -11
- package/dist/stores/file/session-store.js +77 -40
- package/dist/stores/file/workflow-journal-store.d.ts +10 -4
- package/dist/stores/file/workflow-journal-store.js +28 -13
- package/dist/tools/artifact/artifact-text.d.ts +1 -1
- package/dist/tools/artifact/artifact-tool.js +2 -1
- package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -3
- package/dist/tools/fs/fs-bash.d.ts +2 -2
- package/dist/tools/fs/fs-bash.js +3 -1
- package/dist/tools/fs/fs-shared.d.ts +8 -8
- package/dist/tools/fs/gh-rate-limit.d.ts +1 -1
- package/dist/tools/fs/notebook.d.ts +2 -2
- package/dist/tools/fs/read-deny.d.ts +29 -7
- package/dist/tools/fs/read-deny.js +63 -22
- package/dist/tools/fs/removal-targets.d.ts +1 -1
- package/dist/tools/fs/safety.d.ts +9 -9
- package/dist/tools/fs/search.d.ts +6 -6
- package/dist/tools/fs/shell-read-check.js +6 -1
- package/dist/tools/fs/shell-read-judge.d.ts +4 -0
- package/dist/tools/fs/shell-read-judge.js +5 -2
- package/dist/tools/loop-tick.d.ts +2 -2
- package/dist/tools/scheduler-tools.js +5 -1
- package/dist/tools/task-list.d.ts +7 -7
- package/dist/tools/task-list.js +5 -1
- package/dist/tools/todo.js +2 -1
- package/dist/tools/web.d.ts +1 -1
- package/dist/tools/web.js +40 -37
- package/dist/tools/worktree.d.ts +3 -3
- package/dist/tools/worktree.js +3 -1
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +5756 -5638
- package/wire-changes/core@7.55.0.json +3318 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +0 -39
- package/dist/core/store-contracts/session-store-incarnation-contract.js +0 -95
|
@@ -4,7 +4,6 @@ import { hasSessionFork, isSessionConflict } from "../session.js";
|
|
|
4
4
|
import { readMember } from "../thrown-value.js";
|
|
5
5
|
import { receiptRefusal, receiveOwnProperties } from "../own-property-receipt.js";
|
|
6
6
|
import { beginContract } from "./contract-harness.js";
|
|
7
|
-
import { registerSessionIncarnationCases } from "./session-store-incarnation-contract.js";
|
|
8
7
|
const AT = "2026-10-18T00:00:00.000Z";
|
|
9
8
|
const AT_MS = Date.parse(AT);
|
|
10
9
|
const STAMP = { api: "openai-completions", provider: "contract-kit", model: "contract-kit-model" };
|
|
@@ -12,9 +11,9 @@ const ZERO_USAGE = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalToke
|
|
|
12
11
|
function userEntry(id, parentId, text = `t-${id}`) {
|
|
13
12
|
return { id, parentId, type: "message", timestamp: AT, message: { role: "user", content: [{ type: "text", text }], timestamp: AT_MS } };
|
|
14
13
|
}
|
|
15
|
-
function assistantEntry(id, parentId,
|
|
16
|
-
const content =
|
|
17
|
-
return { id, parentId, type: "message", timestamp: AT, message: { role: "assistant", content, ...STAMP, usage: ZERO_USAGE, stopReason:
|
|
14
|
+
function assistantEntry(id, parentId, ...toolCalls) {
|
|
15
|
+
const content = toolCalls.length > 0 ? toolCalls.map((call) => ({ type: "toolCall", id: call, name: "Read", arguments: { file_path: "/kit/x" } })) : [{ type: "text", text: `a-${id}` }];
|
|
16
|
+
return { id, parentId, type: "message", timestamp: AT, message: { role: "assistant", content, ...STAMP, usage: ZERO_USAGE, stopReason: toolCalls.length > 0 ? "toolUse" : "stop", timestamp: AT_MS } };
|
|
18
17
|
}
|
|
19
18
|
function toolResultEntry(id, parentId, toolCallId) {
|
|
20
19
|
return { id, parentId, type: "message", timestamp: AT, message: { role: "toolResult", toolCallId, toolName: "Read", content: [{ type: "text", text: "ok" }], isError: false, timestamp: AT_MS } };
|
|
@@ -89,8 +88,22 @@ function assertNewestFirst(rows) {
|
|
|
89
88
|
function registerUntyped(store, sessionId, owner) {
|
|
90
89
|
return Reflect.apply(store.register, store, [sessionId, owner]);
|
|
91
90
|
}
|
|
92
|
-
const
|
|
91
|
+
const hasHead = (s) => typeof s.headOf === "function";
|
|
92
|
+
const hasOwnership = (s) => hasHead(s) && typeof s.register === "function";
|
|
93
93
|
const declaresPlacements = (s) => s.placements?.subagent !== undefined;
|
|
94
|
+
const headOf = (store, sessionId) => store.headOf(sessionId);
|
|
95
|
+
async function ownerOf(store, sessionId, what) {
|
|
96
|
+
const head = await headOf(store, sessionId);
|
|
97
|
+
assert.ok(head !== undefined, `${what}: the row exists, so headOf must answer it`);
|
|
98
|
+
return head.owner;
|
|
99
|
+
}
|
|
100
|
+
async function tokenOf(store, sessionId, what) {
|
|
101
|
+
const head = await headOf(store, sessionId);
|
|
102
|
+
assert.ok(head !== undefined, `${what}: the row exists, so headOf must answer it`);
|
|
103
|
+
assert.equal(typeof head.incarnation, "string", `${what}: a session row created through this store must carry an incarnation`);
|
|
104
|
+
assert.notEqual(head.incarnation, "", `${what}: an empty token names nobody`);
|
|
105
|
+
return head.incarnation;
|
|
106
|
+
}
|
|
94
107
|
async function honorsRequireExisting(store) {
|
|
95
108
|
const probe = freshId();
|
|
96
109
|
await store.acquire(probe);
|
|
@@ -165,8 +178,8 @@ async function runSessionStoreContract(make, hooks) {
|
|
|
165
178
|
noteTaskRun: (s) => typeof s.noteTaskRun === "function",
|
|
166
179
|
listPlaced: (s) => declaresPlacements(s) && typeof s.listPlaced === "function",
|
|
167
180
|
placements: declaresPlacements,
|
|
181
|
+
headOf: hasHead,
|
|
168
182
|
ownership: hasOwnership,
|
|
169
|
-
incarnationOf: (s) => typeof s.incarnationOf === "function",
|
|
170
183
|
replica: () => hooks.replica !== undefined,
|
|
171
184
|
};
|
|
172
185
|
const faceRun = (name, needs, fn) => run(name, async (store, open) => {
|
|
@@ -214,8 +227,8 @@ async function runSessionStoreContract(make, hooks) {
|
|
|
214
227
|
}
|
|
215
228
|
if (typeof store.list === "function")
|
|
216
229
|
assert.equal(rowOf(await store.list(), id), undefined, "the refused acquire must not surface on the session list");
|
|
217
|
-
if (
|
|
218
|
-
assert.equal(await store
|
|
230
|
+
if (hasHead(store))
|
|
231
|
+
assert.equal(await headOf(store, id), undefined, "nor have a row");
|
|
219
232
|
report("requireExisting", honored ? "verified" : "absent");
|
|
220
233
|
});
|
|
221
234
|
run("[acquire] two concurrent acquires of one id are one session: one log, and the second write on the same parent loses the CAS", async (store) => {
|
|
@@ -438,10 +451,10 @@ async function runSessionStoreContract(make, hooks) {
|
|
|
438
451
|
assert.equal(await store.fork(missing), null);
|
|
439
452
|
if (await honorsRequireExisting(store))
|
|
440
453
|
await rejectsWithCode(() => store.acquire(missing, { requireExisting: true }), "not_found", "a fork of a missing source must not create it");
|
|
441
|
-
if (
|
|
442
|
-
assert.equal(await store
|
|
454
|
+
if (hasHead(store))
|
|
455
|
+
assert.equal(await headOf(store, missing), undefined, "a fork of a missing source must not create it");
|
|
443
456
|
});
|
|
444
|
-
faceRun("[fork] a fork never inherits an in-flight assistant turn: a
|
|
457
|
+
faceRun("[fork] a fork never inherits an in-flight assistant turn: a turn with a tool call no result answers yet (with or without sibling results already in) is left out; a turn every call of which is answered is kept", ["fork"], async (store) => {
|
|
445
458
|
const parallel = freshId();
|
|
446
459
|
const p = (await store.acquire(parallel)).session;
|
|
447
460
|
await append(p, userEntry("u1", null));
|
|
@@ -451,10 +464,18 @@ async function runSessionStoreContract(make, hooks) {
|
|
|
451
464
|
const sequential = freshId();
|
|
452
465
|
const q = (await store.acquire(sequential)).session;
|
|
453
466
|
await append(q, userEntry("u1", null));
|
|
454
|
-
await append(q, assistantEntry("a1", "u1", "call-1"));
|
|
467
|
+
await append(q, assistantEntry("a1", "u1", "call-1", "call-2"));
|
|
455
468
|
await append(q, toolResultEntry("r1", "a1", "call-1"));
|
|
456
469
|
const qf = await store.fork(sequential);
|
|
457
|
-
assert.deepEqual(await pathIds((await readBack(store, qf))), ["u1"], "a sibling call's committed result does not settle the turn");
|
|
470
|
+
assert.deepEqual(await pathIds((await readBack(store, qf))), ["u1"], "a sibling call's committed result does not settle the turn: call-2 has none");
|
|
471
|
+
const answered = freshId();
|
|
472
|
+
const t = (await store.acquire(answered)).session;
|
|
473
|
+
await append(t, userEntry("u1", null));
|
|
474
|
+
await append(t, assistantEntry("a1", "u1", "call-1", "call-2"));
|
|
475
|
+
await append(t, toolResultEntry("r1", "a1", "call-2"));
|
|
476
|
+
await append(t, toolResultEntry("r2", "r1", "call-1"));
|
|
477
|
+
const tf = await store.fork(answered);
|
|
478
|
+
assert.deepEqual(await pathIds((await readBack(store, tf))), ["u1", "a1", "r1", "r2"], "a tool turn every call of which has its result is settled: a fork keeps it");
|
|
458
479
|
const settled = freshId();
|
|
459
480
|
const s = (await store.acquire(settled)).session;
|
|
460
481
|
await append(s, userEntry("u1", null));
|
|
@@ -620,64 +641,217 @@ async function runSessionStoreContract(make, hooks) {
|
|
|
620
641
|
assert.ok(scoped.includes(complete) && scoped.includes(incomplete) && !scoped.includes(elsewhere), "scope narrows to one tenant");
|
|
621
642
|
assert.ok(!(await store.listPlaced("subagent", { olderThanMs: 60 * 60 * 1000 })).some((r) => r.sessionId === complete), "a session placed just now is not an hour old");
|
|
622
643
|
});
|
|
623
|
-
faceRun("[
|
|
624
|
-
const
|
|
625
|
-
assert.equal(await store
|
|
644
|
+
faceRun("[head] headOf answers undefined for an id with no row; for a row, its owner, its occupant and its active leaf — the leaf follows appends and a branch switch", ["headOf"], async (store) => {
|
|
645
|
+
const id = freshId();
|
|
646
|
+
assert.equal(await headOf(store, id), undefined, "no row ⇒ undefined");
|
|
647
|
+
const { session } = await store.acquire(id);
|
|
648
|
+
assert.deepEqual(await headOf(store, id), { owner: null, incarnation: (await session.getMetadata()).incarnation, leafId: null }, "a row acquire created: no owner, its occupant, no leaf");
|
|
649
|
+
await append(session, userEntry("e1", null));
|
|
650
|
+
await append(session, assistantEntry("e2", "e1"));
|
|
651
|
+
assert.equal((await headOf(store, id))?.leafId, "e2", "an append moves the head's leaf");
|
|
652
|
+
await session.getStorage().setLeafId("e1");
|
|
653
|
+
assert.equal((await headOf(store, id))?.leafId, "e1", "a branch switch moves it back");
|
|
654
|
+
await session.getStorage().setLeafId(null);
|
|
655
|
+
assert.equal((await headOf(store, id))?.leafId, null);
|
|
656
|
+
});
|
|
657
|
+
faceRun("[head] the head lives in the row: a store reopened over the same rows (a restart) answers the same owner, occupant and leaf", ["headOf"], async (store, open) => {
|
|
658
|
+
const id = freshId();
|
|
659
|
+
const { session } = await store.acquire(id);
|
|
660
|
+
await append(session, userEntry("e1", null));
|
|
661
|
+
await append(session, assistantEntry("e2", "e1"));
|
|
662
|
+
await session.getStorage().setLeafId("e1");
|
|
663
|
+
const before = await headOf(store, id);
|
|
664
|
+
const second = await open(hooks.reopen(store));
|
|
665
|
+
assert.deepEqual(await headOf(second, id), before, "a head an instance kept for itself would answer differently after every restart");
|
|
666
|
+
});
|
|
667
|
+
faceRun("[head] one read, one generation: while an id is deleted and created again under other owners, no head pairs one generation's owner with another's occupant", ["ownership"], async (store) => {
|
|
668
|
+
const id = freshId();
|
|
669
|
+
const generations = [];
|
|
670
|
+
const reads = [];
|
|
671
|
+
const probe = () => {
|
|
672
|
+
for (let k = 0; k < 3; k++)
|
|
673
|
+
reads.push(headOf(store, id));
|
|
674
|
+
};
|
|
675
|
+
for (let i = 0; i < 12; i++) {
|
|
676
|
+
if (i > 0) {
|
|
677
|
+
probe();
|
|
678
|
+
await hooks.deleteSession(store, id);
|
|
679
|
+
}
|
|
680
|
+
probe();
|
|
681
|
+
await store.register(id, `kit-gen-${i}`);
|
|
682
|
+
probe();
|
|
683
|
+
await store.acquire(id);
|
|
684
|
+
generations.push((await headOf(store, id)));
|
|
685
|
+
}
|
|
686
|
+
const whole = new Set(generations.map((g) => `${g.owner}|${g.incarnation}`));
|
|
687
|
+
assert.equal(whole.size, generations.length, "each generation is its own owner and occupant");
|
|
688
|
+
for (const head of await Promise.all(reads)) {
|
|
689
|
+
if (head === undefined)
|
|
690
|
+
continue;
|
|
691
|
+
assert.ok(whole.has(`${head.owner}|${head.incarnation}`), `a head read ${head.owner} with occupant ${head.incarnation}, a pair no generation of the row ever held`);
|
|
692
|
+
}
|
|
693
|
+
});
|
|
694
|
+
faceRun("[ownership] register on an id with no row creates its row recording the owner — a string, or null for anonymous; a row acquire created records null", ["ownership"], async (store) => {
|
|
695
|
+
const [owned, anonymous, acquired] = [freshId(), freshId(), freshId()];
|
|
626
696
|
await store.register(owned, "kit-alice");
|
|
627
697
|
await store.register(anonymous, null);
|
|
628
|
-
|
|
629
|
-
assert.equal(await
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
const
|
|
698
|
+
await store.acquire(acquired);
|
|
699
|
+
assert.equal(await ownerOf(store, owned, "a registered id"), "kit-alice");
|
|
700
|
+
assert.equal(await ownerOf(store, anonymous, "an anonymous registration"), null);
|
|
701
|
+
assert.equal(await ownerOf(store, acquired, "a row acquire created"), null, "acquire names no owner");
|
|
702
|
+
const token = await tokenOf(store, owned, "a registered row");
|
|
703
|
+
assert.equal((await (await readBack(store, owned)).getMetadata()).incarnation, token, "the registered row is the session acquire then hands out");
|
|
704
|
+
});
|
|
705
|
+
faceRun("[ownership] register on a row that exists does nothing, whatever it carries — an owned row, an anonymous row, a row acquire created, a placed row", ["ownership"], async (store) => {
|
|
706
|
+
const [owned, anonymous, acquired] = [freshId(), freshId(), freshId()];
|
|
633
707
|
await store.register(owned, "kit-alice");
|
|
634
708
|
await store.register(owned, "kit-bob");
|
|
635
709
|
await store.register(owned, null);
|
|
636
710
|
await registerUntyped(store, owned, undefined);
|
|
637
|
-
assert.equal(await
|
|
711
|
+
assert.equal(await ownerOf(store, owned, "an owned row"), "kit-alice");
|
|
638
712
|
await store.register(anonymous, null);
|
|
639
713
|
await store.register(anonymous, "kit-bob");
|
|
640
|
-
assert.equal(await
|
|
714
|
+
assert.equal(await ownerOf(store, anonymous, "an anonymous row"), null, "an anonymous row is not claimable by a later register");
|
|
715
|
+
await store.acquire(acquired);
|
|
716
|
+
await store.register(acquired, "kit-carol");
|
|
717
|
+
assert.equal(await ownerOf(store, acquired, "a row acquire created"), null, "there is no claiming of a row that exists");
|
|
718
|
+
if (declaresPlacements(store)) {
|
|
719
|
+
const placed = freshId();
|
|
720
|
+
await store.acquire(placed, { placement: placementFor() });
|
|
721
|
+
await store.register(placed, "kit-dave");
|
|
722
|
+
assert.equal(await ownerOf(store, placed, "a placed row"), null, "a placed row records no owner");
|
|
723
|
+
}
|
|
641
724
|
});
|
|
642
725
|
faceRun("[ownership] a FIRST register whose owner is neither a string nor null is refused loudly and leaves no row behind", ["ownership"], async (store) => {
|
|
643
726
|
const id = freshId();
|
|
644
727
|
await thrownBy(() => registerUntyped(store, id, undefined), "a first register with owner undefined");
|
|
645
728
|
await thrownBy(() => registerUntyped(store, id, 42), "a first register with a numeric owner");
|
|
646
|
-
assert.equal(await store
|
|
729
|
+
assert.equal(await headOf(store, id), undefined, "the refused writes stored nothing");
|
|
647
730
|
await store.register(id, "kit-carol");
|
|
648
|
-
assert.equal(await
|
|
731
|
+
assert.equal(await ownerOf(store, id, "the first well-formed register"), "kit-carol", "the id is still ownable");
|
|
649
732
|
});
|
|
650
733
|
faceRun("[ownership] two concurrent first registers: each caller's own re-read sees the same winner, one of the two", ["ownership"], async (store) => {
|
|
651
734
|
const id = freshId();
|
|
652
735
|
const caller = async (owner) => {
|
|
653
736
|
await store.register(id, owner);
|
|
654
|
-
return
|
|
737
|
+
return ownerOf(store, id, "after a register");
|
|
655
738
|
};
|
|
656
739
|
const [x, y] = await Promise.all([caller("kit-x"), caller("kit-y")]);
|
|
657
740
|
assert.equal(x, y, "the loser must see the winner on its own re-read, or both callers attach to one session");
|
|
658
741
|
assert.ok(x === "kit-x" || x === "kit-y");
|
|
659
|
-
assert.equal(await
|
|
742
|
+
assert.equal(await ownerOf(store, id, "the settled row"), x, "and the row keeps that winner");
|
|
660
743
|
});
|
|
661
|
-
faceRun("[ownership] the
|
|
662
|
-
const
|
|
663
|
-
await store.register(
|
|
664
|
-
await append((await store.acquire(
|
|
665
|
-
await store.
|
|
666
|
-
|
|
744
|
+
faceRun("[ownership] the owner is a cell of the row: it reads back after the cached view is dropped and on a store reopened over the same rows (a restart)", ["ownership"], async (store, open) => {
|
|
745
|
+
const [owned, acquired] = [freshId(), freshId()];
|
|
746
|
+
await store.register(owned, "kit-alice");
|
|
747
|
+
await append((await store.acquire(owned)).session, userEntry("e1", null));
|
|
748
|
+
await store.acquire(acquired);
|
|
749
|
+
if (typeof store.forget === "function") {
|
|
750
|
+
await store.forget(owned);
|
|
751
|
+
assert.equal(await ownerOf(store, owned, "a forgotten session"), "kit-alice", "a live session must never lose its owner with the cached view");
|
|
752
|
+
}
|
|
753
|
+
const second = await open(hooks.reopen(store));
|
|
754
|
+
assert.equal(await ownerOf(second, owned, "after a restart"), "kit-alice", "an owner an instance kept for itself is lost on every restart, and the session is then anyone's");
|
|
755
|
+
assert.equal(await ownerOf(second, acquired, "after a restart"), null);
|
|
756
|
+
await second.register(owned, "kit-bob");
|
|
757
|
+
assert.equal(await ownerOf(second, owned, "a register after a restart"), "kit-alice", "a restart opens no claiming window");
|
|
667
758
|
});
|
|
668
|
-
faceRun("[ownership] a fork
|
|
759
|
+
faceRun("[ownership] a fork records its owner in its own row: no owner or null ⇒ the source's (an owned copy is never downgraded), an explicit owner ⇒ that owner, an anonymous source ⇒ anonymous", ["ownership", "fork"], async (store) => {
|
|
669
760
|
const owned = freshId();
|
|
670
761
|
await store.register(owned, "kit-alice");
|
|
671
762
|
await append((await store.acquire(owned)).session, userEntry("e1", null));
|
|
672
|
-
assert.equal(await
|
|
673
|
-
assert.equal(await
|
|
674
|
-
assert.equal(await
|
|
763
|
+
assert.equal(await ownerOf(store, (await store.fork(owned)), "a fork"), "kit-alice", "no owner argument ⇒ the source's owner");
|
|
764
|
+
assert.equal(await ownerOf(store, (await store.fork(owned, null)), "a fork"), "kit-alice", "an explicit null never downgrades a copy of an owned history to anonymous");
|
|
765
|
+
assert.equal(await ownerOf(store, (await store.fork(owned, "kit-bob")), "a fork"), "kit-bob", "an explicit owner scopes the fork");
|
|
675
766
|
const anonymous = freshId();
|
|
676
|
-
await store.register(anonymous, null);
|
|
677
767
|
await append((await store.acquire(anonymous)).session, userEntry("e1", null));
|
|
678
|
-
assert.equal(await
|
|
679
|
-
assert.equal(await
|
|
768
|
+
assert.equal(await ownerOf(store, (await store.fork(anonymous)), "a fork"), null);
|
|
769
|
+
assert.equal(await ownerOf(store, (await store.fork(anonymous, null)), "a fork"), null);
|
|
770
|
+
});
|
|
771
|
+
faceRun("[ownership] an id registered first is an ordinary row: a placement-carrying acquire of it is refused placement_refused", ["ownership", "placements"], async (store) => {
|
|
772
|
+
const id = freshId();
|
|
773
|
+
await store.register(id, "kit-alice");
|
|
774
|
+
await rejectsWithCode(() => store.acquire(id, { placement: placementFor() }), "placement_refused", "a placed creation onto an id a register already created");
|
|
775
|
+
assert.equal(await ownerOf(store, id, "the registered row"), "kit-alice", "the refused acquire rewrote nothing");
|
|
776
|
+
});
|
|
777
|
+
faceRun("[ownership] acquire serves only the occupant the row holds: after another instance deleted the row and registered the id to another owner, this instance's next acquire serves the new occupant, never its cached view of the old one", ["ownership", "replica"], async (store, open) => {
|
|
778
|
+
const id = freshId();
|
|
779
|
+
const other = await open(hooks.replica(store));
|
|
780
|
+
await store.register(id, "kit-alice");
|
|
781
|
+
await append((await store.acquire(id)).session, userEntry("alice-only", null));
|
|
782
|
+
await other.acquire(id);
|
|
783
|
+
await hooks.deleteSession(other, id);
|
|
784
|
+
await other.register(id, "kit-bob");
|
|
785
|
+
const head = await headOf(store, id);
|
|
786
|
+
assert.equal(head?.owner, "kit-bob", "this instance's head reads the row");
|
|
787
|
+
const served = (await store.acquire(id)).session;
|
|
788
|
+
assert.equal((await served.getMetadata()).incarnation, head?.incarnation, "the session handed out is the row the owner was read from");
|
|
789
|
+
assert.deepEqual(await entryIds(served), [], "the previous occupant's transcript is not served under the new owner");
|
|
790
|
+
});
|
|
791
|
+
faceRun("[ownership] the metadata a session hands out is not the row: writing to it changes no owner or occupant the head answers", ["ownership"], async (store) => {
|
|
792
|
+
const id = freshId();
|
|
793
|
+
await store.register(id, "kit-alice");
|
|
794
|
+
const before = await headOf(store, id);
|
|
795
|
+
try {
|
|
796
|
+
Object.assign(await (await store.acquire(id)).session.getMetadata(), { owner: null, incarnation: "kit-forged" });
|
|
797
|
+
}
|
|
798
|
+
catch {
|
|
799
|
+
}
|
|
800
|
+
assert.deepEqual(await headOf(store, id), before, "admission changes only through a write of the row");
|
|
801
|
+
});
|
|
802
|
+
faceRun("[incarnation] a session created through acquire carries a token, and every later read of the row answers the same one", ["headOf", "requireExisting"], async (store) => {
|
|
803
|
+
const id = freshId();
|
|
804
|
+
await store.acquire(id);
|
|
805
|
+
const first = await tokenOf(store, id, "after acquire");
|
|
806
|
+
await store.acquire(id);
|
|
807
|
+
assert.equal(await tokenOf(store, id, "a re-acquire"), first, "a re-acquire reopens the same occupant");
|
|
808
|
+
await store.forget?.(id);
|
|
809
|
+
assert.equal(await tokenOf(store, id, "after forget"), first, "the token is the row's, not the cache's: forgetting the cached view must not change it");
|
|
810
|
+
await store.acquire(id, { requireExisting: true });
|
|
811
|
+
assert.equal(await tokenOf(store, id, "a require-existing reopen"), first, "a require-existing reopen after the cache forgot it is still the same occupant");
|
|
812
|
+
});
|
|
813
|
+
faceRun("[incarnation] the session acquire hands back carries the token headOf answers — a run's memory seat reads the former", ["headOf", "requireExisting"], async (store) => {
|
|
814
|
+
const id = freshId();
|
|
815
|
+
const acquired = await store.acquire(id);
|
|
816
|
+
const byId = await tokenOf(store, id, "by-id read");
|
|
817
|
+
assert.equal((await acquired.session.getMetadata()).incarnation, byId, "two faces of one row cell must agree, or the seat and the by-id read name two occupants");
|
|
818
|
+
});
|
|
819
|
+
faceRun("[incarnation] a second store over the same rows (a restart, a replica) answers the same token — the token lives in the row, not in an instance", ["headOf", "requireExisting"], async (store, open) => {
|
|
820
|
+
const id = freshId();
|
|
821
|
+
await store.acquire(id);
|
|
822
|
+
const first = await tokenOf(store, id, "first instance");
|
|
823
|
+
const second = await open(hooks.reopen(store));
|
|
824
|
+
assert.equal(await tokenOf(second, id, "second instance"), first, "an instance-local token would name a different occupant after every restart");
|
|
825
|
+
await second.acquire(id, { requireExisting: true });
|
|
826
|
+
assert.equal(await tokenOf(second, id, "reopened on the second instance"), first, "reopening the session on the second instance is still the same occupant");
|
|
827
|
+
});
|
|
828
|
+
faceRun("[incarnation] two sessions never share a token, and an id with no session has no head (unknown — not an error, not a token)", ["headOf", "requireExisting"], async (store) => {
|
|
829
|
+
const id = freshId();
|
|
830
|
+
await store.acquire(id);
|
|
831
|
+
const generated = await store.acquire();
|
|
832
|
+
const a = await tokenOf(store, id, "explicit id");
|
|
833
|
+
const g = await tokenOf(store, generated.sessionId, "generated id");
|
|
834
|
+
assert.notEqual(a, g, "two sessions are two occupants");
|
|
835
|
+
assert.equal(await headOf(store, freshId()), undefined, "no row ⇒ unknown");
|
|
836
|
+
});
|
|
837
|
+
faceRun("[incarnation] a deleted id handed out again is a NEW occupant: a fresh token, never the previous occupant's", ["headOf", "requireExisting"], async (store) => {
|
|
838
|
+
const id = freshId();
|
|
839
|
+
await store.acquire(id);
|
|
840
|
+
const before = await tokenOf(store, id, "first occupant");
|
|
841
|
+
await hooks.deleteSession(store, id);
|
|
842
|
+
assert.equal(await headOf(store, id), undefined, "a deleted row has no occupant");
|
|
843
|
+
await store.acquire(id);
|
|
844
|
+
const after = await tokenOf(store, id, "second occupant");
|
|
845
|
+
assert.notEqual(after, before, "the id was recycled — the previous occupant's records must not bind this one");
|
|
846
|
+
});
|
|
847
|
+
faceRun("[incarnation] a fork is a new occupant: a fresh token, and the source keeps its own", ["headOf", "requireExisting", "fork"], async (store) => {
|
|
848
|
+
const src = freshId();
|
|
849
|
+
await store.acquire(src);
|
|
850
|
+
const source = await tokenOf(store, src, "fork source");
|
|
851
|
+
const forkedId = await store.fork(src);
|
|
852
|
+
assert.ok(forkedId !== null, "forking an existing session returns the fork's id");
|
|
853
|
+
assert.notEqual(await tokenOf(store, forkedId, "fork"), source, "a fork copies the history, never the occupant");
|
|
854
|
+
assert.equal(await tokenOf(store, src, "fork source after"), source, "forking does not touch the source's occupant");
|
|
680
855
|
});
|
|
681
|
-
registerSessionIncarnationCases((name, fn) => faceRun(`[incarnation] ${name}`, ["incarnationOf", "requireExisting"], (store) => fn(store)), hooks);
|
|
682
856
|
await settle();
|
|
683
857
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { strict as assert } from "node:assert";
|
|
2
|
-
import { JOURNAL_OVERSIZE_ERROR_CODE, MAX_JOURNAL_RESULT_BYTES, } from "../workflow-journal-store.js";
|
|
2
|
+
import { JOURNAL_INCOMPATIBLE_ERROR_CODE, JOURNAL_OVERSIZE_ERROR_CODE, MAX_JOURNAL_RESULT_BYTES, } from "../workflow-journal-store.js";
|
|
3
3
|
import { beginContract } from "./contract-harness.js";
|
|
4
4
|
const key = (ordinal) => `${ordinal}:h`;
|
|
5
5
|
const completed = (ordinal, over = {}) => ({
|
|
@@ -22,6 +22,7 @@ const parked = (ordinal, over = {}) => ({
|
|
|
22
22
|
});
|
|
23
23
|
const OVER_CAP = "x".repeat(MAX_JOURNAL_RESULT_BYTES + 1024);
|
|
24
24
|
const isOversizeRefusal = (e) => e instanceof Error && e.code === JOURNAL_OVERSIZE_ERROR_CODE;
|
|
25
|
+
const isIncompatibleRefusal = (e) => e instanceof Error && e.code === JOURNAL_INCOMPATIBLE_ERROR_CODE;
|
|
25
26
|
export async function workflowJournalStoreContract(make, runAssertion) {
|
|
26
27
|
const { run, settle } = beginContract(runAssertion);
|
|
27
28
|
run("append → load returns entries ASCENDING by ordinal, both arms verbatim; a re-append per ordinal OVERWRITES", async () => {
|
|
@@ -64,6 +65,30 @@ export async function workflowJournalStoreContract(make, runAssertion) {
|
|
|
64
65
|
await store.append("run-1", "tenant-a", { callKey: key(1), parked: parked(1) });
|
|
65
66
|
assert.equal((await store.load("run-1", "tenant-a"))[1].parked?.terminal.kind, "paused");
|
|
66
67
|
});
|
|
68
|
+
run("a PARKED row whose payload is not a paused result is refused — at append, or by the whole load — never read back as an entry, never dropped", async () => {
|
|
69
|
+
const bad = [
|
|
70
|
+
["terminal completed", { ...parked(1), terminal: { kind: "completed" } }],
|
|
71
|
+
["paused terminal without a checkpoint token", { ...parked(1), terminal: { kind: "paused", gate: { kind: "human", reason: "approve", toolName: "Write" } } }],
|
|
72
|
+
["parked arm a string", "paused"],
|
|
73
|
+
];
|
|
74
|
+
for (const [what, payload] of bad) {
|
|
75
|
+
const store = make();
|
|
76
|
+
await store.append("run-1", "tenant-a", { callKey: key(0), result: completed(0) });
|
|
77
|
+
let appended = true;
|
|
78
|
+
try {
|
|
79
|
+
await store.append("run-1", "tenant-a", { callKey: key(1), parked: payload });
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
appended = false;
|
|
83
|
+
}
|
|
84
|
+
if (appended) {
|
|
85
|
+
await assert.rejects(store.load("run-1", "tenant-a"), isIncompatibleRefusal, `${what}: the row was journaled, so the load must refuse — with code "${JOURNAL_INCOMPATIBLE_ERROR_CODE}" — rather than answer around it`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
assert.deepEqual((await store.load("run-1", "tenant-a")).map((e) => e.callKey), [key(0)], `${what}: an append that refused must have journaled nothing`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
67
92
|
run("the cap is inclusive: a payload of EXACTLY the cap's byte count is accepted on both arms", async () => {
|
|
68
93
|
const store = make();
|
|
69
94
|
const fit = (payload) => {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* same defect has been found and fixed one site at a time (RB-122 in `clipWithFilePointer`, then
|
|
10
10
|
* `truncateError`, then the three siblings above), which is exactly the shape a shared primitive prevents.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* Head / tail helpers: drop the straddling code point WHOLE
|
|
13
13
|
* rather than emit half of it. Zero imports, so any module in the repo may depend on it without risking an
|
|
14
14
|
* import cycle.
|
|
15
15
|
*
|
|
@@ -25,7 +25,7 @@ export declare const isHighSurrogate: (c: number) => boolean;
|
|
|
25
25
|
export declare const isLowSurrogate: (c: number) => boolean;
|
|
26
26
|
/**
|
|
27
27
|
* Head-keep of at most `keep` code UNITS that never ends on a lone high surrogate — a code point straddling
|
|
28
|
-
* the cut is dropped whole
|
|
28
|
+
* the cut is dropped whole.
|
|
29
29
|
*
|
|
30
30
|
* Callers must derive any "how much was dropped" count from the RETURNED length, never from `keep`: when
|
|
31
31
|
* the rollback fires the result is one unit SHORTER than the budget, and a count computed from `keep`
|
|
@@ -33,7 +33,7 @@ export declare const isLowSurrogate: (c: number) => boolean;
|
|
|
33
33
|
*/
|
|
34
34
|
export declare function sliceHeadSafe(s: string, keep: number): string;
|
|
35
35
|
/**
|
|
36
|
-
* Tail-keep counterpart: at most `keep` code units, never STARTING on a lone low surrogate (
|
|
36
|
+
* Tail-keep counterpart: at most `keep` code units, never STARTING on a lone low surrogate (the reference's
|
|
37
37
|
* `_W`). Same rule for the caller's dropped-count arithmetic — read it off the returned length.
|
|
38
38
|
*/
|
|
39
39
|
export declare function sliceTailSafe(s: string, keep: number): string;
|
|
@@ -322,7 +322,7 @@ export type TaskEvent = ({
|
|
|
322
322
|
* forwarded to a parent's display sink under the SAME opt-in as those two
|
|
323
323
|
* (`TaskSpec.forwardSubagentEvents`).
|
|
324
324
|
*
|
|
325
|
-
* ONE FRAME, not two:
|
|
325
|
+
* ONE FRAME, not two: the reference splits this into a per-tool `tool_heartbeat` plus Bash's own
|
|
326
326
|
* `bash_progress`; this engine mints the single shape and lets the OUTPUT KEYS be what is conditional.
|
|
327
327
|
* Registered divergence.
|
|
328
328
|
*
|
|
@@ -413,7 +413,7 @@ export type TaskEvent = ({
|
|
|
413
413
|
* document/worktree/todo/task/task-list/task-output/task-stop/agent/fork/workflow-run/web-fetch/
|
|
414
414
|
* web-search/cron-create/cron-delete/cron-list/tool-search/repo-map/monitor-start/
|
|
415
415
|
* enter-plan-mode/exit-plan-mode/report-findings/schedule-wakeup/send-message/agent-transcript/
|
|
416
|
-
* a2a/path_not_in_root/readonly_out_of_root/read_unestablished), surfaced on the live wire so a CC-faithful shell
|
|
416
|
+
* a2a/path_not_in_root/readonly_out_of_root/read_unestablished/advisor), surfaced on the live wire so a CC-faithful shell
|
|
417
417
|
* renders rich cards (red/green diff, stdout panes, file cards) without re-parsing the
|
|
418
418
|
* model-facing string. Absent when the tool carries no card shape or when the serialized card
|
|
419
419
|
* exceeds the size bound (omitted whole; a consumer falls back to `output`).
|
|
@@ -427,13 +427,19 @@ export type TaskEvent = ({
|
|
|
427
427
|
* memory-saved / memory-recall, three words with no producer anywhere in core (a batch MultiEdit
|
|
428
428
|
* replay mints `type:"edit"` with an `edits[]` array; core mounts no memory tool at all).
|
|
429
429
|
*
|
|
430
|
+
* The **advisor** card (`type:"advisor"`, the advisor tool's every call) carries closed words, numbers and catalog ids
|
|
431
|
+
* only — `outcome` (`reviewed` / `declined` / `unavailable`, and `isError` ⇔ `unavailable`), `model`, `servedModel?`,
|
|
432
|
+
* `stopReason?`, `code?` / `errorKind?` (the failure's own words), `hold?: true` (this failure's cause switches the
|
|
433
|
+
* advisor off for the conversation until it is compacted — a classification, not a promise: the transcript says so once
|
|
434
|
+
* the result is recorded) and `usage?`. The guidance, a refusal's reason and an error's message ride {@link output}.
|
|
435
|
+
*
|
|
430
436
|
* **Leak boundary**: the allowlist gates by `type`, so what rides is whatever the minting tool put
|
|
431
437
|
* in the object — which makes each mint site responsible for its own field set. The Agent family's
|
|
432
438
|
* completed card is therefore built from an EXPLICIT whitelist rather than a child-`TaskResult`
|
|
433
439
|
* spread: a `TaskResult` can carry `checkpointToken` (the resume CAPABILITY) on the
|
|
434
440
|
* `unexpected.suspended` terminal, and that field, with `checkpointGate`, never leaves the process.
|
|
435
441
|
*
|
|
436
|
-
* **双面契约(
|
|
442
|
+
* **双面契约(`tool_use_result` describe;P2-3)** — a tool
|
|
437
443
|
* result has TWO faces that never substitute for each other:
|
|
438
444
|
* - **模型面** = {@link output} / the tool_result text: the string the MODEL reads. It may carry
|
|
439
445
|
* model-directed framing — e.g. a delegation tool's trailer (agentId / usage lines the model uses to
|
|
@@ -841,7 +847,7 @@ export type TaskEvent = ({
|
|
|
841
847
|
preview: string;
|
|
842
848
|
} & TaskEventIdentity) | ({
|
|
843
849
|
/**
|
|
844
|
-
* design/121 (
|
|
850
|
+
* design/121 (`<new-diagnostics>`): NEW LSP diagnostics that appeared after the
|
|
845
851
|
* agent's edits, drained at a turn boundary. The SAME data was injected into the model as a
|
|
846
852
|
* `<new-diagnostics>` context message; this frame is the shell's render source (CC's collapsed
|
|
847
853
|
* `Found N new diagnostic issues in M files (ctrl+o to expand)` row). UNTRUSTED RAW (language-
|
|
@@ -26,7 +26,7 @@ export declare function isNotificationInjectionOutcome(value: unknown): value is
|
|
|
26
26
|
export type NotificationDisposition = Exclude<NotificationInjectionOutcome, "dropped_duplicate">;
|
|
27
27
|
/** The closed value set of {@link SystemInjectionPriority}, as data — the wire-facing entries validate
|
|
28
28
|
* against THIS rather than against three inline string literals, so widening the type widens the guard.
|
|
29
|
-
* (Names taken
|
|
29
|
+
* (Names taken from the reference; see the semantics note on
|
|
30
30
|
* {@link SystemInjection.priority} for which of CC's behaviors this engine implements.) */
|
|
31
31
|
export declare const SYSTEM_INJECTION_PRIORITIES: readonly SystemInjectionPriority[];
|
|
32
32
|
/** backlog #389 伴生 (D-3, bad-value loudness) — is this a priority this engine knows at all? A value
|
|
@@ -327,8 +327,8 @@ export interface ExternalNotificationInput {
|
|
|
327
327
|
export interface SystemInjection<TPayload = unknown> {
|
|
328
328
|
kind: "task_notification";
|
|
329
329
|
/**
|
|
330
|
-
* design/373 — the injection ladder is LIVE (all three values carry delivery semantics, the
|
|
331
|
-
*
|
|
330
|
+
* design/373 — the injection ladder is LIVE (all three values carry delivery semantics, the reference's
|
|
331
|
+
* form; the flat "every priority delivers at the next boundary" era ended with this
|
|
332
332
|
* design — its H-1 anchor-correction note is preserved in the design archive, and the ruled
|
|
333
333
|
* changes it named are exactly what landed here):
|
|
334
334
|
*
|
|
@@ -282,12 +282,12 @@ export declare function abortBackgroundAgentsForOwnerLane(core: DurableAgentCore
|
|
|
282
282
|
skipSessionScoped?: boolean;
|
|
283
283
|
sessionScopedOnly?: boolean;
|
|
284
284
|
}): number;
|
|
285
|
-
/**
|
|
286
|
-
*
|
|
285
|
+
/** Name resolution over the caller-visible background_agent rows
|
|
286
|
+
* (sema's single-lane subset: no teammate/name-registry branches).
|
|
287
287
|
*
|
|
288
288
|
* [c209-D] PUBLIC + explicit-name layer 0: the single resolver both TaskStop (:1839 leg) and
|
|
289
289
|
* SendMessage consume, so the two verbs can never drift. Ladder:
|
|
290
|
-
* 0a.
|
|
290
|
+
* 0a. exact `handle.name` match — LATEST-WINS (the reference's SendMessage doc: "a newer agent took the name
|
|
291
291
|
* (latest wins)"; older rows stay task_id-addressable), any status (names keep working after
|
|
292
292
|
* completion — the resume face is the CC "resumes it from its transcript" counterpart).
|
|
293
293
|
* **Latest-wins is RESOLUTION, not permission to redirect a conversation**: CC pairs the same
|
|
@@ -446,7 +446,7 @@ export declare function deliverToRunningAgentLane(core: DurableAgentCore, id: st
|
|
|
446
446
|
* very rows a retry needs. The task faces' split lives in `runningAgentFooterLane` (RB-332). */
|
|
447
447
|
export declare function runningBackgroundAgentLabelsLane(core: DurableAgentCore, access: TaskAccess): string[];
|
|
448
448
|
/**
|
|
449
|
-
* The not-found FOOTER's two rows, split the way
|
|
449
|
+
* The not-found FOOTER's two rows, split the way the reference assembles them:
|
|
450
450
|
* - `named` = CC `uG_` (220:467941-467953): the agentNameRegistry's KEYS whose task is a running local
|
|
451
451
|
* agent, listed as BARE NAMES — the string a retry should pass verbatim. sema's counterpart
|
|
452
452
|
* of "has a registry entry" is the handle carrying an explicit `name` (spawn-time label),
|
|
@@ -590,10 +590,10 @@ export declare const MONITOR_DEFAULT_TIMEOUT_MS = 300000;
|
|
|
590
590
|
export declare const MONITOR_MAX_TIMEOUT_MS = 3600000;
|
|
591
591
|
export declare const MONITOR_MAX_BATCHES_PER_MINUTE = 50;
|
|
592
592
|
/** Burst capacity of the storm token bucket — how many batches may fire
|
|
593
|
-
* back-to-back before the SUPPRESSION level engages.
|
|
593
|
+
* back-to-back before the SUPPRESSION level engages. Adopted from the reference. */
|
|
594
594
|
export declare const MONITOR_STORM_BURST = 10;
|
|
595
595
|
/** How long a monitor must stay CONTINUOUSLY over budget before the
|
|
596
|
-
* second level (kill) fires.
|
|
596
|
+
* second level (kill) fires. Adopted from the reference. */
|
|
597
597
|
export declare const MONITOR_STORM_KILL_AFTER_MS = 30000;
|
|
598
598
|
/** The partial-line accumulator bound. sema's `lineBuf` had NO bound —
|
|
599
599
|
* a monitored process emitting megabytes without a single newline grew it without limit (the spool's
|
|
@@ -789,7 +789,7 @@ export declare function firstDropNote(spool: {
|
|
|
789
789
|
/** ONE wording for "you stopped nothing" across every already-terminal stop face —
|
|
790
790
|
* the in-process bash/monitor/agent arms and the durable-row fallback previously split: the durable
|
|
791
791
|
* arm answered honestly while the in-process arms claimed `Terminated <id>.` over work that finished
|
|
792
|
-
* (or was killed) on its own.
|
|
792
|
+
* (or was killed) on its own. The reference refuses the call outright (`Task X is not running (status: …)`,
|
|
793
793
|
* 220:468231-468236); sema keeps the idempotent no-op posture (stopWorkflow / durable-arm precedent,
|
|
794
794
|
* no isError) but the receipt must tell the truth. */
|
|
795
795
|
export declare function alreadyTerminalStopNote(id: string, status: string): string;
|
|
@@ -840,7 +840,7 @@ export declare const DURABLE_AGENT_HANDLE_RE: RegExp;
|
|
|
840
840
|
* real child error — settleBackgroundAgent never stores it (status "killed" + stoppedBy already say
|
|
841
841
|
* it); exported so the subagent call sites and the registry agree on the exact sentinel. */
|
|
842
842
|
export declare const BG_AGENT_REAP_STOP_ERROR = "stopped (parent task ended or TaskStop)";
|
|
843
|
-
/**
|
|
843
|
+
/** TaskStop name addressing: NFKC-normalize, strip
|
|
844
844
|
* control/format chars (whitespace-class ones survive), trim, lowercase, whitespace runs → hyphens. Both
|
|
845
845
|
* the query and the candidate label go through this, so "Fix Tests" addresses "fix tests".
|
|
846
846
|
* [c209-D]: EXPORTED — SendMessage's "main" reserved lane must use the SAME canonicalization
|
|
@@ -217,6 +217,7 @@ export function formatWorkflowRun(run) {
|
|
|
217
217
|
runId: run.id,
|
|
218
218
|
type: "workflow",
|
|
219
219
|
status: run.status,
|
|
220
|
+
...(summary.parked ? { parked: true } : {}),
|
|
220
221
|
...(summary.name ? { name: summary.name } : {}),
|
|
221
222
|
...(summary.currentPhase ? { currentPhase: summary.currentPhase } : {}),
|
|
222
223
|
agents: { done, total: run.agents.length, failed },
|
|
@@ -33,7 +33,7 @@ export interface RegisterBackgroundBashInput extends TaskAccess {
|
|
|
33
33
|
* rolling bound) and fires ONE completion task-notification at the terminal state — the background-bash
|
|
34
34
|
* half of CC's LocalShellTask completion notify. Also flips TaskOutput to re-readable spool reads. */
|
|
35
35
|
onTerminal?: (notification: TaskNotificationPayload) => void;
|
|
36
|
-
/**
|
|
36
|
+
/** The task's OUTPUT FILE — the launch receipt advertises it and the watcher
|
|
37
37
|
* mirrors every polled increment into it (append-only, unbounded — unlike the rolling in-memory
|
|
38
38
|
* spool), so "Read the output file path" is a real alternative to TaskOutput. Terminal
|
|
39
39
|
* task-notifications carry the same path (`output_file`). Primarily meaningful with `onTerminal`
|
|
@@ -66,9 +66,9 @@ export interface TaskPollOptions {
|
|
|
66
66
|
filter?: string;
|
|
67
67
|
/** design/116 W3 (CC TaskOutput `block`): wait until the task reaches a terminal state (or `timeoutMs`)
|
|
68
68
|
* instead of returning the instantaneous snapshot — saves the model blind re-poll turns. The TOOL layer
|
|
69
|
-
* defaults this to TRUE (
|
|
69
|
+
* defaults this to TRUE (裁定 2026-07-02); registry callers pass it explicitly. */
|
|
70
70
|
block?: boolean;
|
|
71
|
-
/** Max wait for `block` (ms). Default 30s, capped at 600s
|
|
71
|
+
/** Max wait for `block` (ms). Default 30s, capped at 600s. */
|
|
72
72
|
timeoutMs?: number;
|
|
73
73
|
/** Abort signal — a blocked wait must stop when the tool call is cancelled. */
|
|
74
74
|
signal?: AbortSignal;
|
|
@@ -101,7 +101,7 @@ export interface TaskToolOptions extends TaskAccess {
|
|
|
101
101
|
* foreground clamp (design/130 P2b). When present, a BLOCKING TaskOutput wait is clamped so it
|
|
102
102
|
* cannot eat the write-out window: the model gets an honest, visible clamp note instead of a
|
|
103
103
|
* silent 10-minute blind wait into the finalize wall (TB rs**: 9.1min poll = the exact tax).
|
|
104
|
-
* CC posture note
|
|
104
|
+
* CC posture note: CC classifies WIND-DOWN waits, and its
|
|
105
105
|
* block cap rides per-query budgets — a deadline-aware wait is the sema equivalent on the tool face. */
|
|
106
106
|
deadlineMs?: () => number | undefined;
|
|
107
107
|
/** design/157 B17 S2 (fable 终判 D4) — whether a terminal <task-notification> is actually wired for
|
|
@@ -12,7 +12,7 @@ import { mintCompletionId, canAccessWorkflowRun, formatWorkflowRun, clipTaskOutp
|
|
|
12
12
|
export { normalizeAgentName, DURABLE_AGENT_HEARTBEAT_MS, DURABLE_AGENT_HANDLE_RE, BG_AGENT_REAP_STOP_ERROR } from "./task-registry-shared.js";
|
|
13
13
|
import { TASK_OUTPUT_TOOL_NAME, TASK_STOP_TOOL_NAME, TASK_OUTPUT_MISSING_ID_MESSAGE, TASK_STOP_MISSING_ID_MESSAGE, TASK_STOP_PARAMS, resolveTaskIdArg, REGISTRY_TASK_TOOL_CAPS, composeTaskOutputDescription, composeTaskOutputParams, composeTaskStopDescription, } from "./task-tool-shape.js";
|
|
14
14
|
import { durableAgentArmedLane, durableAgentRowProbeLane, beginDurableClaimLane, endDurableClaimLane, reapDurableAgentsLane, noteBackgroundAgentActivityLane, reapStaleSessionBackgroundAgentsLane, releaseDurableTranscriptAnchorLane, bindBackgroundAgentSessionLane, registerBackgroundAgentLane, recordBackgroundAgentOrgAdmissionLane, parkBackgroundAgentLane, reconcileParkedAgentsLane, claimParkedAgentLane, rollbackParkedClaimLane, consumeParkedFlipLane, finalizeParkedResumeLane, settleBackgroundAgentLane, abortBackgroundAgentsForOwnerLane, serveDurableAgentRowLane, resolveBackgroundAgentByNameLane, backgroundAgentCycleSeqLane, activeDelegationHandlesLane, markRetainedContinuationLane, reviveBackgroundAgentLane, settleRevivedAgentLane, unmarkRetainedContinuationLane, attachAgentNotifyLane, deliverToRunningAgentLane, runningBackgroundAgentLabelsLane, runningAgentFooterLane, notFoundRunningAgentsTail, pollBackgroundAgentLane, stopBackgroundAgentLane, } from "./task-registry-agent.js";
|
|
15
|
-
import { toolFace } from "./tool-catalog-entries.js";
|
|
15
|
+
import { mountRuleFace, toolFace } from "./tool-catalog-entries.js";
|
|
16
16
|
import { thrownText } from "./thrown-value.js";
|
|
17
17
|
import { agentStateSourceOfHandle, agentStateSourceOfRecord, agentStateSummary, readAgentState } from "./agent-state.js";
|
|
18
18
|
export { canAccessWorkflowRun, clipTaskOutput, MONITOR_BATCH_WINDOW_MS, MONITOR_DEFAULT_TIMEOUT_MS, MONITOR_MAX_TIMEOUT_MS, MONITOR_MAX_BATCHES_PER_MINUTE };
|
|
@@ -1307,6 +1307,7 @@ export function createTaskOutputTool(opts) {
|
|
|
1307
1307
|
return defineTool({
|
|
1308
1308
|
name: TASK_OUTPUT_TOOL_NAME,
|
|
1309
1309
|
...toolFace("task-output"),
|
|
1310
|
+
ruleFace: mountRuleFace("task-output"),
|
|
1310
1311
|
description: composeTaskOutputDescription(caps),
|
|
1311
1312
|
parameters: composeTaskOutputParams(caps),
|
|
1312
1313
|
boundaryLegsFor: (rawArgs, at) => {
|
|
@@ -1360,6 +1361,7 @@ export function createTaskStopTool(opts) {
|
|
|
1360
1361
|
return defineTool({
|
|
1361
1362
|
name: TASK_STOP_TOOL_NAME,
|
|
1362
1363
|
...toolFace("task-stop"),
|
|
1364
|
+
ruleFace: mountRuleFace("task-stop"),
|
|
1363
1365
|
description: composeTaskStopDescription(REGISTRY_TASK_TOOL_CAPS),
|
|
1364
1366
|
parameters: TASK_STOP_PARAMS,
|
|
1365
1367
|
boundaryLegsFor: (rawArgs, at) => {
|