@sema-agent/core 7.48.0 → 7.49.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +457 -0
- package/README.md +2 -2
- package/dist/agents/cascade.d.ts +2 -5
- package/dist/agents/child-failure.d.ts +20 -0
- package/dist/agents/child-failure.js +28 -0
- package/dist/agents/cross-session-ref.d.ts +11 -3
- package/dist/agents/cross-session-ref.js +6 -0
- package/dist/agents/cumulative-stats.d.ts +12 -15
- package/dist/agents/cumulative-stats.js +1 -1
- package/dist/agents/extra-tool-names.js +1 -1
- package/dist/agents/inherited-tool-pool.d.ts +17 -13
- package/dist/agents/inherited-tool-pool.js +4 -3
- package/dist/agents/peer-session-drain.d.ts +3 -2
- package/dist/agents/peer-session-drain.js +5 -4
- package/dist/agents/send-message-tool.js +2 -9
- package/dist/agents/subagent.d.ts +10 -29
- package/dist/agents/subagent.js +65 -53
- package/dist/agents/suspend-guard.d.ts +1 -1
- package/dist/agents/tool-filter.d.ts +76 -65
- package/dist/agents/tool-filter.js +122 -92
- package/dist/agents/verify.d.ts +4 -7
- package/dist/agents/verify.js +6 -7
- package/dist/bench/metrics.d.ts +1 -2
- package/dist/brain/anthropic.js +133 -79
- package/dist/brain/errors.d.ts +53 -6
- package/dist/brain/errors.js +22 -2
- package/dist/brain/input-too-long.d.ts +40 -19
- package/dist/brain/input-too-long.js +3 -16
- package/dist/brain/open-responses.js +19 -10
- package/dist/brain/openai.js +123 -32
- package/dist/brain/provider-dialect.d.ts +214 -0
- package/dist/brain/provider-dialect.js +186 -0
- package/dist/brain/request-params.d.ts +27 -8
- package/dist/brain/request-params.js +7 -12
- package/dist/brain/request-route.d.ts +84 -0
- package/dist/brain/request-route.js +41 -0
- package/dist/brain/retry.d.ts +8 -0
- package/dist/brain/retry.js +10 -4
- package/dist/brain/route-adjudicator.d.ts +7 -0
- package/dist/brain/route-adjudicator.js +5 -1
- package/dist/brain/status-sink.d.ts +20 -0
- package/dist/brain/status-sink.js +11 -0
- package/dist/brain/stream-engine.d.ts +52 -1
- package/dist/brain/stream-engine.js +81 -24
- package/dist/brain/stream-shared.d.ts +57 -11
- package/dist/brain/stream-shared.js +28 -2
- package/dist/core/a2a.d.ts +1 -0
- package/dist/core/agent-config-dir.js +3 -2
- package/dist/core/allow-entry.d.ts +21 -12
- package/dist/core/allow-entry.js +38 -31
- package/dist/core/arg-summary.d.ts +21 -28
- package/dist/core/arg-summary.js +235 -88
- package/dist/core/ask-origin.d.ts +42 -24
- package/dist/core/ask-origin.js +18 -13
- package/dist/core/auto-mode-prompt-assets.d.ts +2 -2
- package/dist/core/auto-mode-prompt-assets.js +1 -1
- package/dist/core/auto-mode-prompt.d.ts +11 -1
- package/dist/core/auto-mode-prompt.js +13 -10
- package/dist/core/auto-mode-rebuild.d.ts +7 -0
- package/dist/core/auto-mode-rebuild.js +4 -1
- package/dist/core/canonical-json.d.ts +3 -0
- package/dist/core/canonical-json.js +2 -1
- package/dist/core/checkpoint-requirements.d.ts +892 -0
- package/dist/core/checkpoint-requirements.js +333 -0
- package/dist/core/checkpoint-store.d.ts +94 -65
- package/dist/core/checkpoint-store.js +14 -26
- package/dist/core/child-clamp-seats.d.ts +228 -69
- package/dist/core/child-clamp-seats.js +211 -17
- package/dist/core/classifier-unavailable-arm.d.ts +5 -1
- package/dist/core/classifier-unavailable-arm.js +3 -3
- package/dist/core/compliance.d.ts +3 -0
- package/dist/core/compliance.js +9 -4
- package/dist/core/credential-vocabulary.d.ts +140 -0
- package/dist/core/credential-vocabulary.js +131 -0
- package/dist/core/decision-receipt.js +1 -1
- package/dist/core/effective-path-target.d.ts +73 -16
- package/dist/core/effective-path-target.js +63 -33
- package/dist/core/engine-notice.d.ts +43 -11
- package/dist/core/file-history-store.js +2 -2
- package/dist/core/fs-write-gate-policy.d.ts +4 -0
- package/dist/core/fs-write-gate-policy.js +22 -5
- package/dist/core/gate-bounded-await.d.ts +28 -13
- package/dist/core/gate-bounded-await.js +41 -4
- package/dist/core/gate-fold.d.ts +1 -1
- package/dist/core/gate-fold.js +24 -25
- package/dist/core/gate-lanes.js +16 -15
- package/dist/core/gate-outcome.d.ts +20 -5
- package/dist/core/gate-outcome.js +5 -0
- package/dist/core/governance-codes.d.ts +11 -4
- package/dist/core/governance-codes.js +14 -3
- package/dist/core/hooks.d.ts +21 -0
- package/dist/core/locked-config.d.ts +8 -0
- package/dist/core/locked-config.js +14 -2
- package/dist/core/lsp.js +3 -5
- package/dist/core/mailbox-store.d.ts +3 -4
- package/dist/core/mcp-connection-pool.d.ts +75 -0
- package/dist/core/mcp-connection-pool.js +128 -0
- package/dist/core/mcp-failure.d.ts +2 -1
- package/dist/core/mcp-failure.js +13 -2
- package/dist/core/mcp.d.ts +4 -0
- package/dist/core/mcp.js +70 -43
- package/dist/core/memory-engine/content-origin.js +2 -14
- package/dist/core/memory-engine/engine.d.ts +32 -22
- package/dist/core/memory-engine/engine.js +103 -55
- package/dist/core/memory-engine/file-backend.d.ts +13 -30
- package/dist/core/memory-engine/file-backend.js +37 -252
- package/dist/core/memory-engine/index.d.ts +1 -1
- package/dist/core/memory-engine/index.js +1 -1
- package/dist/core/memory-engine/layout.d.ts +139 -9
- package/dist/core/memory-engine/layout.js +350 -7
- package/dist/core/memory-engine/scope-contract.d.ts +10 -0
- package/dist/core/memory-engine/scope-contract.js +8 -0
- package/dist/core/memory-engine/session-incarnation.d.ts +14 -4
- package/dist/core/memory-engine/session-incarnation.js +5 -2
- package/dist/core/memory-engine/types.d.ts +10 -1
- package/dist/core/memory.js +5 -17
- package/dist/core/model-seat.d.ts +4 -4
- package/dist/core/model-seat.js +1 -1
- package/dist/core/mounted-mcp.d.ts +57 -0
- package/dist/core/mounted-mcp.js +19 -0
- package/dist/core/namespaced-rule-name.d.ts +29 -0
- package/dist/core/namespaced-rule-name.js +52 -0
- package/dist/core/park-selfcheck.d.ts +1 -1
- package/dist/core/park-selfcheck.js +16 -6
- package/dist/core/path-guard-rows.d.ts +99 -0
- package/dist/core/path-guard-rows.js +45 -0
- package/dist/core/path-identity.d.ts +22 -16
- package/dist/core/path-identity.js +10 -10
- package/dist/core/path-rule-binding.d.ts +2 -1
- package/dist/core/path-rule-binding.js +3 -1
- package/dist/core/pause-registry.d.ts +16 -2
- package/dist/core/pause-registry.js +6 -0
- package/dist/core/permission-rule-consent.js +0 -7
- package/dist/core/permission-rule-model.d.ts +68 -24
- package/dist/core/permission-rule-model.js +105 -24
- package/dist/core/permission-rule-store.js +2 -2
- package/dist/core/permission-rules.d.ts +3 -30
- package/dist/core/permission-rules.js +4 -54
- package/dist/core/read-root-candidate.d.ts +1 -3
- package/dist/core/read-root-candidate.js +4 -15
- package/dist/core/real-approval.d.ts +4 -3
- package/dist/core/retired-keys.d.ts +13 -0
- package/dist/core/retired-keys.js +14 -0
- package/dist/core/roles.d.ts +2 -3
- package/dist/core/roles.js +15 -6
- package/dist/core/runner/assemble-result.d.ts +0 -7
- package/dist/core/runner/assemble-result.js +19 -31
- package/dist/core/runner/caller-roster.d.ts +78 -0
- package/dist/core/runner/caller-roster.js +219 -0
- package/dist/core/runner/checkpoint-scope.d.ts +16 -16
- package/dist/core/runner/checkpoint-scope.js +2 -2
- package/dist/core/runner/child-tree.js +2 -2
- package/dist/core/runner/contracts.d.ts +68 -35
- package/dist/core/runner/decide-continuation.d.ts +51 -3
- package/dist/core/runner/decide-continuation.js +76 -21
- package/dist/core/runner/denial-limit-arms.d.ts +17 -5
- package/dist/core/runner/denial-limit-arms.js +11 -9
- package/dist/core/runner/extra-body-dropped-seat.d.ts +8 -0
- package/dist/core/runner/extra-body-dropped-seat.js +22 -0
- package/dist/core/runner/finish-reason-seat.d.ts +9 -0
- package/dist/core/runner/finish-reason-seat.js +40 -0
- package/dist/core/runner/gate-exit.d.ts +44 -32
- package/dist/core/runner/gate-exit.js +112 -25
- package/dist/core/runner/inherited-ask-grants.js +6 -4
- package/dist/core/runner/mcp-redial.d.ts +3 -3
- package/dist/core/runner/mcp-redial.js +3 -4
- package/dist/core/runner/permission-rule-lanes.d.ts +1 -2
- package/dist/core/runner/permission-rule-lanes.js +5 -4
- package/dist/core/runner/prepare-artifact.d.ts +4 -0
- package/dist/core/runner/prepare-artifact.js +2 -1
- package/dist/core/runner/prepare-ask-lane.d.ts +2 -0
- package/dist/core/runner/prepare-ask-lane.js +12 -6
- package/dist/core/runner/prepare-boundary-parks.d.ts +5 -8
- package/dist/core/runner/prepare-boundary-parks.js +4 -7
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +11 -15
- package/dist/core/runner/prepare-caps-and-workflow.js +19 -27
- package/dist/core/runner/prepare-config-doors.d.ts +9 -9
- package/dist/core/runner/prepare-config-doors.js +10 -5
- package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
- package/dist/core/runner/prepare-defer-classify.js +5 -3
- package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
- package/dist/core/runner/prepare-delegation-surface.js +3 -3
- package/dist/core/runner/prepare-gate-stations.d.ts +4 -4
- package/dist/core/runner/prepare-gate-stations.js +9 -7
- package/dist/core/runner/prepare-hands-readface.d.ts +7 -7
- package/dist/core/runner/prepare-hands-readface.js +7 -7
- package/dist/core/runner/prepare-inherited-gate.d.ts +7 -6
- package/dist/core/runner/prepare-inherited-gate.js +14 -15
- package/dist/core/runner/prepare-listings.d.ts +7 -24
- package/dist/core/runner/prepare-listings.js +4 -5
- package/dist/core/runner/prepare-memory-engine-session.d.ts +2 -0
- package/dist/core/runner/prepare-memory-engine-session.js +4 -3
- package/dist/core/runner/prepare-memory.d.ts +6 -0
- package/dist/core/runner/prepare-memory.js +13 -13
- package/dist/core/runner/prepare-offload-wrappers.d.ts +5 -0
- package/dist/core/runner/prepare-offload-wrappers.js +3 -3
- package/dist/core/runner/prepare-park-ask.d.ts +7 -8
- package/dist/core/runner/prepare-park-ask.js +17 -10
- package/dist/core/runner/prepare-policy-chain.js +24 -44
- package/dist/core/runner/prepare-project-context.d.ts +1 -1
- package/dist/core/runner/prepare-project-context.js +3 -4
- package/dist/core/runner/prepare-protocol-tools.d.ts +9 -3
- package/dist/core/runner/prepare-protocol-tools.js +3 -4
- package/dist/core/runner/prepare-run-refs.d.ts +3 -0
- package/dist/core/runner/prepare-run-refs.js +2 -1
- package/dist/core/runner/prepare-safety-scan.d.ts +4 -8
- package/dist/core/runner/prepare-safety-scan.js +1 -2
- package/dist/core/runner/prepare-suspend-saga.d.ts +7 -1
- package/dist/core/runner/prepare-suspend-saga.js +28 -12
- package/dist/core/runner/prepare-task.d.ts +1 -1
- package/dist/core/runner/prepare-task.js +67 -56
- package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -10
- package/dist/core/runner/prepare-wiring-manifest.js +5 -8
- package/dist/core/runner/resume-apply.js +7 -14
- package/dist/core/runner/resume-checkpoint-screen.js +11 -4
- package/dist/core/runner/resume-internals-and-config.js +2 -2
- package/dist/core/runner/resume-policy-outcome.js +5 -32
- package/dist/core/runner/resume-review-outcome.js +4 -1
- package/dist/core/runner/retired-runner-deps.d.ts +6 -0
- package/dist/core/runner/retired-runner-deps.js +10 -1
- package/dist/core/runner/run-brain-sinks.d.ts +4 -0
- package/dist/core/runner/run-brain-sinks.js +5 -2
- package/dist/core/runner/run-harness-handlers.js +29 -36
- package/dist/core/runner/run-leg.d.ts +0 -2
- package/dist/core/runner/run-leg.js +32 -33
- package/dist/core/runner/run-terminal-adoption.js +4 -3
- package/dist/core/runner/runtask.js +8 -8
- package/dist/core/runner/session-rule-policy.js +5 -5
- package/dist/core/runner/stream-settle-backstop.js +7 -4
- package/dist/core/runner/sub-agent-deny-lists.d.ts +51 -12
- package/dist/core/runner/sub-agent-deny-lists.js +111 -80
- package/dist/core/runner/terminal-account.d.ts +48 -0
- package/dist/core/runner/terminal-account.js +186 -0
- package/dist/core/runner/tool-end-body.d.ts +54 -17
- package/dist/core/runner/tool-end-body.js +27 -2
- package/dist/core/runner/tool-face-overlay.d.ts +3 -1
- package/dist/core/runner/tool-face-overlay.js +6 -4
- package/dist/core/runner/tool-occurrence.d.ts +106 -0
- package/dist/core/runner/tool-occurrence.js +123 -0
- package/dist/core/runner/tool-progress-lane.d.ts +16 -8
- package/dist/core/runner/tool-progress-lane.js +25 -34
- package/dist/core/runner/tool-turn-repair-seat.d.ts +28 -4
- package/dist/core/runner/tool-turn-repair-seat.js +36 -13
- package/dist/core/runner/turn-attachments.d.ts +1 -1
- package/dist/core/runner/write-protection-station.d.ts +21 -9
- package/dist/core/runner/write-protection-station.js +20 -17
- package/dist/core/runner-deps.d.ts +12 -22
- package/dist/core/secret-env.d.ts +16 -5
- package/dist/core/secret-env.js +23 -63
- package/dist/core/sensitive-path-policy.d.ts +19 -18
- package/dist/core/sensitive-path-policy.js +73 -49
- package/dist/core/session-reconcile.d.ts +3 -0
- package/dist/core/session-reconcile.js +5 -4
- package/dist/core/session-store.d.ts +5 -0
- package/dist/core/session-store.js +12 -0
- package/dist/core/session.d.ts +13 -0
- package/dist/core/shared-memory/normalize.d.ts +17 -4
- package/dist/core/shared-memory/normalize.js +7 -7
- package/dist/core/shell-lexer.js +5 -4
- package/dist/core/shell-wrapper-projection.js +1 -1
- package/dist/core/skill-grant.js +1 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +13 -0
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +7 -14
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +27 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.js +92 -0
- package/dist/core/stub-env.d.ts +2 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/synthetic-read-verdict.js +2 -2
- package/dist/core/task-event.d.ts +59 -5
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +42 -9
- package/dist/core/terminal-cause.d.ts +94 -11
- package/dist/core/tighten-task-spec.d.ts +5 -4
- package/dist/core/tighten-task-spec.js +20 -25
- package/dist/core/tool-catalog-entries.d.ts +5 -7
- package/dist/core/tool-catalog-entries.js +14 -15
- package/dist/core/tool-face.d.ts +47 -0
- package/dist/core/tool-face.js +5 -0
- package/dist/core/tool-model-gate.d.ts +5 -5
- package/dist/core/tool-name-aliases.d.ts +26 -2
- package/dist/core/tool-name-aliases.js +13 -0
- package/dist/core/tool-name-list.d.ts +30 -0
- package/dist/core/tool-name-list.js +55 -0
- package/dist/core/tool-name-readings.d.ts +1 -9
- package/dist/core/tool-name-readings.js +1 -3
- package/dist/core/tool-policy.d.ts +195 -85
- package/dist/core/tool-policy.js +165 -380
- package/dist/core/tool-registry.d.ts +44 -1
- package/dist/core/tool-registry.js +26 -0
- package/dist/core/tool-roster.d.ts +19 -1
- package/dist/core/tool-roster.js +21 -2
- package/dist/core/tool-spec-members.d.ts +45 -0
- package/dist/core/tool-spec-members.js +169 -0
- package/dist/core/tool-spec.d.ts +46 -8
- package/dist/core/tools.d.ts +6 -2
- package/dist/core/tools.js +8 -4
- package/dist/core/untrusted-egress.js +29 -26
- package/dist/core/untrusted-text.d.ts +13 -10
- package/dist/core/untrusted-text.js +6 -44
- package/dist/core/workflow-journal-store.d.ts +4 -1
- package/dist/core/write-protect.d.ts +65 -29
- package/dist/core/write-protect.js +235 -177
- package/dist/engine/compaction/compaction.d.ts +2 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +5 -23
- package/dist/engine/execution-env/node-execution-env.js +16 -38
- package/dist/engine/execution-env/symlink-chain.d.ts +23 -0
- package/dist/engine/execution-env/symlink-chain.js +32 -0
- package/dist/engine/harness/types.d.ts +7 -0
- package/dist/engine/llm/tool-turns.d.ts +3 -0
- package/dist/engine/llm/tool-turns.js +1 -0
- package/dist/engine/llm/types.d.ts +59 -23
- package/dist/engine/loop/agent-loop.js +16 -2
- package/dist/engine/session/memory-repo.js +11 -3
- package/dist/engine/session/repo-utils.d.ts +8 -0
- package/dist/engine/session/repo-utils.js +13 -0
- package/dist/index.d.ts +20 -23
- package/dist/index.js +17 -20
- package/dist/internal/harness.d.ts +1 -1
- package/dist/internal/harness.js +1 -1
- package/dist/internal/llm.d.ts +2 -2
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/governance-baseline-validity.js +1 -1
- package/dist/orchestration/run-spec.js +3 -3
- package/dist/orchestration/run-workflow-tool.d.ts +16 -35
- package/dist/orchestration/run-workflow-tool.js +38 -78
- package/dist/orchestration/workflow-governance.d.ts +21 -25
- package/dist/orchestration/workflow-governance.js +38 -78
- package/dist/orchestration/workflow-primitives.d.ts +7 -22
- package/dist/orchestration/workflow-primitives.js +5 -12
- package/dist/orchestration/workflow-types.d.ts +1 -1
- package/dist/orchestration/workflow.d.ts +61 -11
- package/dist/orchestration/workflow.js +189 -117
- package/dist/scenarios/full-body.d.ts +1 -1
- package/dist/shell/lex.d.ts +0 -21
- package/dist/shell/lex.js +250 -68
- package/dist/shell/shell-words.d.ts +35 -0
- package/dist/shell/shell-words.js +65 -0
- package/dist/stores/file/checkpoint-store.d.ts +5 -5
- package/dist/stores/file/checkpoint-store.js +5 -2
- package/dist/stores/file/index.d.ts +0 -8
- package/dist/stores/file/index.js +0 -12
- package/dist/stores/file/session-store.d.ts +3 -0
- package/dist/stores/file/session-store.js +44 -19
- package/dist/tools/artifact/artifact-tool.js +2 -0
- package/dist/tools/fs/bash-program-position.d.ts +12 -4
- package/dist/tools/fs/bash-program-position.js +32 -9
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/bash-readonly-classifier.js +8 -7
- package/dist/tools/fs/containment-face.d.ts +4 -0
- package/dist/tools/fs/containment-face.js +3 -0
- package/dist/tools/fs/fs-shared.d.ts +10 -0
- package/dist/tools/fs/fs-shared.js +18 -0
- package/dist/tools/fs/fs-write.js +4 -2
- package/dist/tools/fs/index.d.ts +1 -1
- package/dist/tools/fs/program-read-model.d.ts +46 -20
- package/dist/tools/fs/program-read-model.js +50 -20
- package/dist/tools/fs/program-read-model.rows.d.ts +0 -14
- package/dist/tools/fs/program-read-model.rows.js +16 -15
- package/dist/tools/fs/read-deny-home.d.ts +33 -47
- package/dist/tools/fs/read-deny-home.js +35 -49
- package/dist/tools/fs/read-deny.d.ts +23 -22
- package/dist/tools/fs/read-deny.js +114 -89
- package/dist/tools/fs/removal-targets.d.ts +56 -23
- package/dist/tools/fs/removal-targets.js +65 -87
- package/dist/tools/fs/safety.d.ts +29 -22
- package/dist/tools/fs/safety.js +17 -11
- package/dist/tools/fs/search.js +10 -8
- package/dist/tools/fs/shell-read-argv.js +1 -1
- package/dist/tools/fs/shell-read-bindings.d.ts +169 -37
- package/dist/tools/fs/shell-read-bindings.js +324 -86
- package/dist/tools/fs/shell-read-builtins.d.ts +35 -0
- package/dist/tools/fs/shell-read-builtins.js +43 -0
- package/dist/tools/fs/shell-read-check.d.ts +15 -1
- package/dist/tools/fs/shell-read-check.js +67 -43
- package/dist/tools/fs/shell-read-establish.js +6 -6
- package/dist/tools/fs/shell-read-functions.d.ts +22 -0
- package/dist/tools/fs/shell-read-functions.js +29 -0
- package/dist/tools/fs/shell-read-judge.d.ts +51 -18
- package/dist/tools/fs/shell-read-judge.js +40 -4
- package/dist/tools/fs/shell-read-plan.d.ts +12 -6
- package/dist/tools/fs/shell-read-plan.js +118 -113
- package/dist/tools/fs/shell-read-start.d.ts +29 -6
- package/dist/tools/fs/shell-read-start.js +16 -9
- package/dist/tools/fs/shell-read-word.js +4 -0
- package/dist/tools/fs/shell-read-workdir.d.ts +156 -0
- package/dist/tools/fs/shell-read-workdir.js +281 -0
- package/dist/tools/fs/shell-read-write-targets.d.ts +5 -2
- package/dist/tools/fs/shell-read-write-targets.js +14 -5
- package/dist/tools/fs/shell-reentry-text.d.ts +4 -6
- package/dist/tools/fs/shell-reentry-text.js +3 -11
- package/dist/tools/task-list.d.ts +1 -2
- package/dist/tools/web.js +1 -1
- package/package.json +4 -1
- package/test/export-surface.snapshot.json +107 -143
- package/wire-changes/core@7.49.0.json +4765 -0
- package/dist/agents/teacher.d.ts +0 -159
- package/dist/agents/teacher.js +0 -577
- package/dist/agents/team.d.ts +0 -226
- package/dist/agents/team.js +0 -257
- package/dist/core/strategy-store.d.ts +0 -238
- package/dist/core/strategy-store.js +0 -253
- package/dist/orchestration/builtin-workflows.d.ts +0 -133
- package/dist/orchestration/builtin-workflows.js +0 -159
- package/dist/scenarios/env.d.ts +0 -40
- package/dist/scenarios/env.js +0 -39
- package/dist/scenarios/scenario-registry.d.ts +0 -110
- package/dist/scenarios/scenario-registry.js +0 -140
- package/dist/scenarios/teacher-quickstart.d.ts +0 -40
- package/dist/scenarios/teacher-quickstart.js +0 -12
- package/dist/stores/cc/lockfile.d.ts +0 -10
- package/dist/stores/cc/lockfile.js +0 -98
- package/dist/stores/cc/mailbox-store.d.ts +0 -20
- package/dist/stores/cc/mailbox-store.js +0 -255
- package/dist/stores/cc/roster-adapter.d.ts +0 -12
- package/dist/stores/cc/roster-adapter.js +0 -117
- package/dist/stores/cc/sidecar-transcript.d.ts +0 -97
- package/dist/stores/cc/sidecar-transcript.js +0 -264
- package/dist/stores/cc/task-list-store.d.ts +0 -2
- package/dist/stores/cc/task-list-store.js +0 -125
- package/dist/stores/file/strategy-store.d.ts +0 -97
- package/dist/stores/file/strategy-store.js +0 -341
package/dist/core/shell-lexer.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { shellWordsOf } from "../shell/shell-words.js";
|
|
1
2
|
import { evaluatesOperand, SHELL_WRAPPER_TABLE } from "./shell-wrapper-table.js";
|
|
2
3
|
import { arithmeticHidesRun, carriesSubstitution, freshWord, matchOp, readDoubleQuoted, readExpansion, skipBalanced, skipHeredocBodies } from "./shell-scan.js";
|
|
3
4
|
export { SHELL_WRAPPER_TABLE } from "./shell-wrapper-table.js";
|
|
4
5
|
const WRAPPERS = new Map(Object.entries(SHELL_WRAPPER_TABLE));
|
|
5
|
-
const PREFIX_KEYWORDS =
|
|
6
|
-
const CLOSING_KEYWORDS =
|
|
7
|
-
const OPAQUE_KEYWORDS =
|
|
6
|
+
const PREFIX_KEYWORDS = shellWordsOf("stripped_prefix");
|
|
7
|
+
const CLOSING_KEYWORDS = shellWordsOf("stripped_standalone");
|
|
8
|
+
const OPAQUE_KEYWORDS = shellWordsOf("opaque");
|
|
8
9
|
const ASSIGNMENT_RE = /^[A-Za-z_][A-Za-z0-9_]*(?:\[[^\]]*\])?\+?=/;
|
|
9
10
|
const DURATION_RE = /^\d+(?:\.\d+)?[smhd]?$/;
|
|
10
11
|
const REDIRECT_OPS = ["<<<", "<<-", "<<", "<>", "<&", "<", ">>", ">|", ">&", "&>>", "&>", ">"];
|
|
@@ -222,7 +223,7 @@ export function readShellCommand(source) {
|
|
|
222
223
|
i = end;
|
|
223
224
|
continue;
|
|
224
225
|
}
|
|
225
|
-
if (ch === "(" && source[i + 1] === "(" && (!word.started || word.raw === "!") && pendingRedirect === undefined && seg.words.every((w) => w.expands === false && (
|
|
226
|
+
if (ch === "(" && source[i + 1] === "(" && (!word.started || word.raw === "!") && pendingRedirect === undefined && seg.words.every((w) => w.expands === false && (shellWordsOf("control_prefix").has(w.text) || CLOSING_KEYWORDS.has(w.text) || w.text === "-p"))) {
|
|
226
227
|
endWord();
|
|
227
228
|
const end = skipBalanced(source, i, "(", ")");
|
|
228
229
|
if (end === undefined) {
|
|
@@ -38,7 +38,7 @@ function projectRow(row) {
|
|
|
38
38
|
return executes.length > 0 ? { valueFlags: [], flags: [], commandString: [], executes } : undefined;
|
|
39
39
|
}
|
|
40
40
|
const commandString = sorted(all.filter((o) => o.spec.value?.kind === "shell-text").map((o) => o.spelling));
|
|
41
|
-
const values = all.filter((o) => o.spec.value?.kind !== "shell-text");
|
|
41
|
+
const values = all.filter((o) => o.spec.value?.kind !== "shell-text" && o.spec.mode !== "queries");
|
|
42
42
|
const attached = sorted(values.filter((o) => o.arity === "attached" && !o.spelling.startsWith("--")).map((o) => o.spelling));
|
|
43
43
|
const required = row.launcher.requiredOperands ?? 0;
|
|
44
44
|
const duration = required > 0 && row.launcher.requiredOperandSpelling === DURATION_SPELLING;
|
package/dist/core/skill-grant.js
CHANGED
|
@@ -3,7 +3,7 @@ import { parsePermissionRule } from "./permission-rules.js";
|
|
|
3
3
|
import { mountedToolPermissionSeat } from "./mode-policy.js";
|
|
4
4
|
import { inlineUntrusted } from "./untrusted-text.js";
|
|
5
5
|
import { boundInputHashOf } from "./canonical-json.js";
|
|
6
|
-
import { readToolNameList } from "
|
|
6
|
+
import { readToolNameList } from "./tool-name-list.js";
|
|
7
7
|
import { allowingRows, autoStripped, compileAllowEntry, compileAllowList, inertEntryPhrase, judgeAllowEntries, nonListValueLabel, nonStringMemberLabel, renderListEntry } from "./allow-entry.js";
|
|
8
8
|
export const SKILL_GRANT_ORIGINS = Object.freeze(["model", "user", "inherited"]);
|
|
9
9
|
const FROZEN_SKILL_GRANT_ORIGINS = new Set(["model", "inherited"]);
|
|
@@ -405,6 +405,19 @@ export async function checkpointStoreContract(make, runAssertion) {
|
|
|
405
405
|
assert.equal("askClass" in bare, false, "an absent askClass must stay OMITTED on the row");
|
|
406
406
|
assert.equal("classes" in bare, false, "an absent classes must stay OMITTED on the row");
|
|
407
407
|
});
|
|
408
|
+
run("#1320 requirement list: a v10 row's `requires` survives the round-trip verbatim (the whole array, in its order) beside its version; a row without one stays without", async () => {
|
|
409
|
+
const store = make();
|
|
410
|
+
const listed = createCheckpointFixture({ token: mintCheckpointToken(), sessionId: "rq-list", version: 10, requires: ["binding", "hands_coordinates", "requirements_digest"], requirementsDigest: "a".repeat(64) });
|
|
411
|
+
const bare = createCheckpointFixture({ token: mintCheckpointToken(), sessionId: "rq-none" });
|
|
412
|
+
for (const cp of [listed, bare])
|
|
413
|
+
await store.put(cp.token, cp);
|
|
414
|
+
const back = (await store.get(listed.token));
|
|
415
|
+
assert.equal(back.version, 10, "the frozen stamp must survive the round-trip");
|
|
416
|
+
assert.deepEqual(back.requires, ["binding", "hands_coordinates", "requirements_digest"], "the requirement list must survive the round-trip as the same array, in the same order");
|
|
417
|
+
assert.equal(back.requirementsDigest, "a".repeat(64), "the row digest must survive the round-trip verbatim");
|
|
418
|
+
const bareBack = (await store.get(bare.token));
|
|
419
|
+
assert.equal("requires" in bareBack || "requirementsDigest" in bareBack, false, "a row without a list or digest must stay without (never [] / null / \"\")");
|
|
420
|
+
});
|
|
408
421
|
run("decider pair: a policy-decided allow resolves like a person's — its `policy_allowed` record (party `policy`, the attribution) round-trips verbatim on the resolved winner and as the execution record; the same record is already_recorded, a person's record for that row conflicts", async () => {
|
|
409
422
|
const store = make();
|
|
410
423
|
const cp = createCheckpointFixture();
|
|
@@ -6,22 +6,16 @@ import { type ContractAssertionRunner } from "./contract-harness.js";
|
|
|
6
6
|
* `contract-harness.ts` for the runner seam and `contract-kit-version.ts` for version lockstep).
|
|
7
7
|
*
|
|
8
8
|
* 为什么这个家族有契约(结构性复发机制,两次实证):契约 harness 此前只喂 InMemory + File 两个
|
|
9
|
-
* 后端,于是没进 harness
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* - MB1:CC 后端的 `ack` 根本不查 lease 表,注释自陈 "worse than the other two
|
|
13
|
-
* backends' pre-fix bug"。
|
|
14
|
-
* 两次漏的都是同一个后端。修法不是再补一次点,而是把契约本身变成全后端共跑的资产 —— design/159
|
|
15
|
-
* 再进一步:第三方后端也拿得到同一份资产。
|
|
9
|
+
* 后端,于是没进 harness 的第三个后端(已退役的 CC inbox 适配器)反复独立漂移 —— RB-86 空箱
|
|
10
|
+
* claimLease 不返回 null 还装上幽灵租约;MB1 `ack` 根本不查 lease 表。修法不是再补一次点,而是
|
|
11
|
+
* 把契约本身变成全后端共跑的资产 —— design/159 再进一步:第三方后端也拿得到同一份资产。
|
|
16
12
|
*
|
|
17
13
|
* 分层(与 test/mailbox-contract.ts 的挂载对应):
|
|
18
14
|
* - T1 核心不变量层 = {@link mailboxStoreContract} + {@link mailboxAckOwnershipContract}:每个后端
|
|
19
15
|
* 都必须过。任何后端在这一层变红 = 该后端违约,**不许通过放宽契约让它变绿**。核心层一律用
|
|
20
|
-
* `scope: "default"`({@link MAILBOX_CONTRACT_SCOPE})
|
|
21
|
-
* 也跑同一段代码。
|
|
16
|
+
* `scope: "default"`({@link MAILBOX_CONTRACT_SCOPE}),这样租户轴受限的第三方后端也跑同一段代码。
|
|
22
17
|
* - T2 可选能力层 = {@link mailboxBundledOnlyContract}:多租户隔离 + 键注入性,只挂具备租户轴/
|
|
23
|
-
* 自有键空间的后端(core
|
|
24
|
-
* `src/stores/cc/mailbox-store.ts` 模块头)。
|
|
18
|
+
* 自有键空间的后端(core 的两个捆绑后端)。
|
|
25
19
|
*
|
|
26
20
|
* `make()` must return a FRESH, empty store each call. Stores a contract case creates are closed
|
|
27
21
|
* (`close?.()`) when the case ends — the file backend's append fd is refcounted, so a harness that
|
|
@@ -41,9 +35,8 @@ export declare function mailboxStoreContract(mk: () => MailboxStore, runAssertio
|
|
|
41
35
|
*/
|
|
42
36
|
export declare function mailboxAckOwnershipContract(mk: () => MailboxStore, runAssertion?: ContractAssertionRunner): Promise<void>;
|
|
43
37
|
/**
|
|
44
|
-
* T2 可选能力层 —— 只挂具备租户轴 + 自有键空间的后端(core 的两个捆绑后端)
|
|
45
|
-
*
|
|
46
|
-
* 放宽」:核心层没有一条为了任何后端而弱化。第三方后端若有租户轴,应当也挂这一层。
|
|
38
|
+
* T2 可选能力层 —— 只挂具备租户轴 + 自有键空间的后端(core 的两个捆绑后端)。核心层没有一条
|
|
39
|
+
* 为了任何后端而弱化。第三方后端若有租户轴,应当也挂这一层。
|
|
47
40
|
*/
|
|
48
41
|
export declare function mailboxBundledOnlyContract(mk: () => MailboxStore, runAssertion?: ContractAssertionRunner): Promise<void>;
|
|
49
42
|
export interface MailboxCrossProcessContractHooks {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type SessionStore } from "../session.js";
|
|
2
|
+
import { type ContractAssertionRunner } from "./contract-harness.js";
|
|
3
|
+
/**
|
|
4
|
+
* The cross-backend contract for the SESSION INCARNATION face ({@link SessionStore.incarnationOf}):
|
|
5
|
+
* the token naming WHICH occupant holds a session id. vitest-free (see `contract-harness.ts`); mount it
|
|
6
|
+
* on every store that implements `incarnationOf` — the face is optional on the interface, so this kit
|
|
7
|
+
* is a separate opt-in kit rather than a skipped case inside another one (a skipped case is how an
|
|
8
|
+
* unimplemented face reads green). A store WITHOUT the face fails every case loudly.
|
|
9
|
+
*
|
|
10
|
+
* The law the cases pin: the token is a cell of the session ROW, minted once when the row comes into
|
|
11
|
+
* existence and answered unchanged by every later read of that row — a cache forgetting the session or
|
|
12
|
+
* a second store over the same rows does not change it, deleting the row and handing the id out again
|
|
13
|
+
* does, a fork is a new occupant. A `SessionRepo` author runs it through the bundled cache layer
|
|
14
|
+
* (`make: () => new TtlSessionStore({ repo })`, `reopen: () => new TtlSessionStore({ repo })`).
|
|
15
|
+
*
|
|
16
|
+
* `make()` must return a FRESH, empty store each call; each case disposes the store it built.
|
|
17
|
+
*/
|
|
18
|
+
export interface SessionStoreIncarnationContractHooks {
|
|
19
|
+
/** Delete `sessionId`'s session ROW through the backend's own deletion path (history and all), so
|
|
20
|
+
* that a later `acquire(sessionId)` creates a new session under the same id. */
|
|
21
|
+
deleteSession: (store: SessionStore, sessionId: string) => Promise<void>;
|
|
22
|
+
/** A SECOND, independent store instance over the same rows as `store` — what a restarted process or
|
|
23
|
+
* another replica constructs. The kit disposes it. */
|
|
24
|
+
reopen: (store: SessionStore) => SessionStore;
|
|
25
|
+
runAssertion?: ContractAssertionRunner;
|
|
26
|
+
}
|
|
27
|
+
export declare function sessionStoreIncarnationContract(make: () => SessionStore, hooks: SessionStoreIncarnationContractHooks): Promise<void>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { strict as assert } from "node:assert";
|
|
2
|
+
import { hasSessionFork } from "../session.js";
|
|
3
|
+
import { beginContract } from "./contract-harness.js";
|
|
4
|
+
const ID_A = "0198fa00-0000-7000-8000-0000000014a1";
|
|
5
|
+
const ID_B = "0198fa00-0000-7000-8000-0000000014b2";
|
|
6
|
+
const ID_NONE = "0198fa00-0000-7000-8000-0000000014ff";
|
|
7
|
+
async function tokenOf(store, sessionId) {
|
|
8
|
+
assert.equal(typeof store.incarnationOf, "function", "this kit is for stores that implement SessionStore.incarnationOf");
|
|
9
|
+
return store.incarnationOf(sessionId);
|
|
10
|
+
}
|
|
11
|
+
function assertToken(token, what) {
|
|
12
|
+
assert.equal(typeof token, "string", `${what}: a session row created through this store must carry an incarnation`);
|
|
13
|
+
assert.notEqual(token, "", `${what}: an empty token names nobody`);
|
|
14
|
+
}
|
|
15
|
+
export async function sessionStoreIncarnationContract(make, hooks) {
|
|
16
|
+
const { run: runRaw, settle } = beginContract(hooks.runAssertion);
|
|
17
|
+
const run = (name, fn) => runRaw(name, async () => {
|
|
18
|
+
const store = make();
|
|
19
|
+
try {
|
|
20
|
+
await fn(store);
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
await store.dispose();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
run("a session created through acquire carries a token, and every later read of the row answers the same one", async (store) => {
|
|
27
|
+
await store.acquire(ID_A);
|
|
28
|
+
const first = await tokenOf(store, ID_A);
|
|
29
|
+
assertToken(first, "after acquire");
|
|
30
|
+
await store.acquire(ID_A);
|
|
31
|
+
assert.equal(await tokenOf(store, ID_A), first, "a re-acquire reopens the same occupant");
|
|
32
|
+
await store.forget?.(ID_A);
|
|
33
|
+
assert.equal(await tokenOf(store, ID_A), first, "the token is the row's, not the cache's: forgetting the cached view must not change it");
|
|
34
|
+
await store.acquire(ID_A, { requireExisting: true });
|
|
35
|
+
assert.equal(await tokenOf(store, ID_A), first, "a require-existing reopen after the cache forgot it is still the same occupant");
|
|
36
|
+
});
|
|
37
|
+
run("the session acquire hands back carries the token incarnationOf answers — a run's memory seat reads the former", async (store) => {
|
|
38
|
+
const acquired = await store.acquire(ID_A);
|
|
39
|
+
const byId = await tokenOf(store, ID_A);
|
|
40
|
+
assertToken(byId, "by-id read");
|
|
41
|
+
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");
|
|
42
|
+
});
|
|
43
|
+
run("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", async (store) => {
|
|
44
|
+
await store.acquire(ID_A);
|
|
45
|
+
const first = await tokenOf(store, ID_A);
|
|
46
|
+
assertToken(first, "first instance");
|
|
47
|
+
const second = hooks.reopen(store);
|
|
48
|
+
try {
|
|
49
|
+
assert.equal(await tokenOf(second, ID_A), first, "an instance-local token would name a different occupant after every restart");
|
|
50
|
+
await second.acquire(ID_A, { requireExisting: true });
|
|
51
|
+
assert.equal(await tokenOf(second, ID_A), first, "reopening the session on the second instance is still the same occupant");
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
await second.dispose();
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
run("two sessions never share a token, and an id with no session answers undefined (unknown — not an error, not a token)", async (store) => {
|
|
58
|
+
await store.acquire(ID_A);
|
|
59
|
+
const generated = await store.acquire();
|
|
60
|
+
const a = await tokenOf(store, ID_A);
|
|
61
|
+
const g = await tokenOf(store, generated.sessionId);
|
|
62
|
+
assertToken(a, "explicit id");
|
|
63
|
+
assertToken(g, "generated id");
|
|
64
|
+
assert.notEqual(a, g, "two sessions are two occupants");
|
|
65
|
+
assert.equal(await tokenOf(store, ID_NONE), undefined, "no row ⇒ unknown");
|
|
66
|
+
});
|
|
67
|
+
run("a deleted id handed out again is a NEW occupant: a fresh token, never the previous occupant's", async (store) => {
|
|
68
|
+
await store.acquire(ID_A);
|
|
69
|
+
const before = await tokenOf(store, ID_A);
|
|
70
|
+
assertToken(before, "first occupant");
|
|
71
|
+
await hooks.deleteSession(store, ID_A);
|
|
72
|
+
assert.equal(await tokenOf(store, ID_A), undefined, "a deleted row has no occupant");
|
|
73
|
+
await store.acquire(ID_A);
|
|
74
|
+
const after = await tokenOf(store, ID_A);
|
|
75
|
+
assertToken(after, "second occupant");
|
|
76
|
+
assert.notEqual(after, before, "the id was recycled — the previous occupant's records must not bind this one");
|
|
77
|
+
});
|
|
78
|
+
run("a fork is a new occupant: a fresh token, and the source keeps its own", async (store) => {
|
|
79
|
+
if (!hasSessionFork(store))
|
|
80
|
+
return;
|
|
81
|
+
await store.acquire(ID_B);
|
|
82
|
+
const source = await tokenOf(store, ID_B);
|
|
83
|
+
assertToken(source, "fork source");
|
|
84
|
+
const forkedId = await store.fork(ID_B);
|
|
85
|
+
assert.ok(forkedId !== null, "forking an existing session returns the fork's id");
|
|
86
|
+
const forked = await tokenOf(store, forkedId);
|
|
87
|
+
assertToken(forked, "fork");
|
|
88
|
+
assert.notEqual(forked, source, "a fork copies the history, never the occupant");
|
|
89
|
+
assert.equal(await tokenOf(store, ID_B), source, "forking does not touch the source's occupant");
|
|
90
|
+
});
|
|
91
|
+
await settle();
|
|
92
|
+
}
|
package/dist/core/stub-env.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export declare class StubExecutionEnv implements ExecutionEnv {
|
|
|
12
12
|
* member off a `ExecutionEnv | StubExecutionEnv` union; the no-I/O stub produces no target
|
|
13
13
|
* content, so it never declares (always `undefined` — the trusted-side default). */
|
|
14
14
|
readonly externalContentTarget?: boolean;
|
|
15
|
+
/** `ExecutionEnv.cdPath`: the stub runs no shell, so no shell receives a `CDPATH`. */
|
|
16
|
+
readonly cdPath: readonly string[];
|
|
15
17
|
constructor(cwd?: string);
|
|
16
18
|
private fsErr;
|
|
17
19
|
absolutePath(path: string): Promise<Result<string, FileError>>;
|
package/dist/core/stub-env.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { attestationOf, describeThrown, refuseOutOfContractDecision } from "./tool-policy.js";
|
|
2
2
|
import { skillRowRefusal } from "./skill-grant.js";
|
|
3
3
|
import { applyPersistedTightening } from "./persisted-rule-arms.js";
|
|
4
4
|
import { readOrgRuleLane, readPersistedRuleLane } from "./rule-lane-reads.js";
|
|
@@ -62,7 +62,7 @@ export function createSyntheticReadJudge(layers) {
|
|
|
62
62
|
}
|
|
63
63
|
if (read.action !== "deny")
|
|
64
64
|
return undefined;
|
|
65
|
-
if (
|
|
65
|
+
if (attestationOf(read, req)?.settlement !== undefined) {
|
|
66
66
|
cannot(layer, "approval_seat", "the policy would ask an approver, who is never consulted for a visibility probe");
|
|
67
67
|
return undefined;
|
|
68
68
|
}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import type { ActorAssertion } from "../internal/llm.js";
|
|
10
10
|
import type { TaskResult } from "./task-result.js";
|
|
11
11
|
import type { TaskNotificationPayload } from "./task-notification.js";
|
|
12
|
+
import type { ProviderCondition, ProviderConditionSource } from "../brain/provider-dialect.js";
|
|
12
13
|
/**
|
|
13
14
|
* Identity fields carried by every CONTENT event of a task stream (design/99 §E2 — lightweight message
|
|
14
15
|
* identity). Both are OPTIONAL and ADDITIVE; a consumer that ignores them is unchanged.
|
|
@@ -198,6 +199,25 @@ export interface BrainStatus {
|
|
|
198
199
|
* `control_request_progress` frame, where CC itself makes the key optional.
|
|
199
200
|
*/
|
|
200
201
|
errorStatus?: number;
|
|
202
|
+
/**
|
|
203
|
+
* What the provider said about the account or its capacity on the response being retried — one word of
|
|
204
|
+
* `PROVIDER_CONDITIONS`, judged off the provider dialect table keyed by where the request went
|
|
205
|
+
* (`brain/provider-dialect.ts`). Fills the gap {@link errorStatus} states: {@link errClass} `rate_limit`
|
|
206
|
+
* buckets a 429 that clears on its own with one the provider pinned on the account. Only the RETRYABLE words
|
|
207
|
+
* ride a retry frame (`throttled` / `overloaded` / `unknown`): a response judged `quota_exhausted` or
|
|
208
|
+
* `stop_other` is not retried — its word rides the terminal (`terminal.detail.providerCondition`) — unless
|
|
209
|
+
* the provider's own `x-should-retry: true` sent it back into the ladder, in which case the frame states the
|
|
210
|
+
* word the response was judged by.
|
|
211
|
+
*
|
|
212
|
+
* PRESENCE — exactly the connect-ladder backoff frames that carry {@link errorStatus}: a response named the
|
|
213
|
+
* failure. ABSENT on a transport failure, a stall, a mid-stream tear, the output-cap re-send (a re-shaped
|
|
214
|
+
* request, not a provider condition), `circuit_open`, and the terminal `recovered` / `gave_up` frames. A
|
|
215
|
+
* consumer reads absence as "not judged" — the same reading as `unknown`: back off, do not claim a quota.
|
|
216
|
+
*/
|
|
217
|
+
providerCondition?: ProviderCondition;
|
|
218
|
+
/** Which evidence {@link providerCondition} rests on (`unified_header` / `provider_code` / `status`). Present
|
|
219
|
+
* exactly when it is. */
|
|
220
|
+
providerConditionSource?: ProviderConditionSource;
|
|
201
221
|
}
|
|
202
222
|
/**
|
|
203
223
|
* design/97 CORE-8 (③): one lightweight TOOL-ACTIVITY beat surfaced from a running task, for a per-agent live
|
|
@@ -282,9 +302,19 @@ export type TaskEvent = ({
|
|
|
282
302
|
} & TaskEventIdentity) | ({
|
|
283
303
|
type: "tool_start";
|
|
284
304
|
toolCallId: string;
|
|
285
|
-
toolName: string;
|
|
305
|
+
toolName: string;
|
|
306
|
+
/** {@link ToolSpec.label} when distinct from `toolName`; omitted otherwise. */
|
|
286
307
|
label?: string;
|
|
287
308
|
args: unknown;
|
|
309
|
+
/**
|
|
310
|
+
* @contract tool_start.recovered — `true` on a start frame the engine minted at the moment it CLOSED a call
|
|
311
|
+
* whose start never went out on this stream: an interrupted run's reconcile closing a call the loop never
|
|
312
|
+
* reached, or a resumed process closing a call a dead process had announced. Every `tool_end` is preceded by
|
|
313
|
+
* a `tool_start` with the same id on the same stream — this frame is how that holds for those closes. `args`
|
|
314
|
+
* is the call's input as the transcript recorded it. It asserts NOTHING about execution (whether the call
|
|
315
|
+
* ran is the paired `tool_end.notExecuted`); absent on every start the loop announced itself.
|
|
316
|
+
*/
|
|
317
|
+
recovered?: true;
|
|
288
318
|
} & TaskEventIdentity) | ({
|
|
289
319
|
/**
|
|
290
320
|
* A LIVENESS TICK for a tool call that is still running. Emitted on the run's own queue between this
|
|
@@ -477,17 +507,41 @@ export type TaskEvent = ({
|
|
|
477
507
|
* denied by which LAYER), `settlement` (how the ask this pass consumed ENDED — a person's yes or
|
|
478
508
|
* no with the channel's attribution and, on a bare "no", no note; a window that elapsed and whose;
|
|
479
509
|
* nobody reachable; the wait aborted…) and `origin` (who ASKED). It is the SAME object the
|
|
480
|
-
* `permissionDenied` observer received and the
|
|
510
|
+
* `permissionDenied` observer received and the call's occurrence record holds — one mint, three
|
|
481
511
|
* faces — so a renderer never branches on prose to tell "a person refused" from "the window closed".
|
|
482
512
|
*
|
|
483
513
|
* WHERE IT COMES FROM — never inferred here: the gate mints it at its exit, the decide lane mints it
|
|
484
514
|
* from the host's decision facts joined with the row's persisted origin.
|
|
485
515
|
*
|
|
486
|
-
*
|
|
487
|
-
* re-
|
|
488
|
-
*
|
|
516
|
+
* THE LATEST RECORD: a station that refuses the call AFTER its gate exit (the shell read admission that
|
|
517
|
+
* re-establishes what the gate judged and finds it moved, a resumed leg's re-checks) adds one more
|
|
518
|
+
* record, minted as a veto — the refusing layer is the disposition, an approval already given stays on
|
|
519
|
+
* the settlement — and this member is that record. A call refused after its gate allowed it therefore
|
|
520
|
+
* reads `denied`, never `allowed` beside an error, and {@link isError} is `true` whatever the tool's own
|
|
521
|
+
* result said.
|
|
522
|
+
*
|
|
523
|
+
* ABSENT on every frame of a call no gate exit on this stream saw (a tool call on an unarmed gate, a
|
|
524
|
+
* deferred re-issue, a call a reconcile closed that never reached a gate here). A gated call's frame
|
|
525
|
+
* ALWAYS carries it — an absence is not a fact about the call, and a consumer must not read one out of it.
|
|
489
526
|
*/
|
|
490
527
|
gate?: import("./gate-outcome.js").GateOutcome;
|
|
528
|
+
/**
|
|
529
|
+
* @contract tool_end.wireName — on a REFUSED call's frame only (`gate.disposition.kind === "denied"`): the name of
|
|
530
|
+
* the tool the call dispatched to on the live roster — the name the gate judged and the deny observer's `toolName`
|
|
531
|
+
* — where {@link toolName} is the model's spelling (an alias, a retired name the roster still answers to). A
|
|
532
|
+
* refusals list keyed on the tool reads this member; absent on every other frame, and on a refused frame whose
|
|
533
|
+
* station did not know the roster name.
|
|
534
|
+
*/
|
|
535
|
+
wireName?: string;
|
|
536
|
+
/**
|
|
537
|
+
* @contract tool_end.notExecuted — `true` when the engine has POSITIVE evidence this call never executed:
|
|
538
|
+
* the loop closed it without running it (a sibling settled by a halted batch, a call a turn interrupt
|
|
539
|
+
* reached before it started) or an interrupted run's reconcile closed a call this run never started.
|
|
540
|
+
* ABSENT means only that no such evidence exists — never "it ran": a call closed with its outcome unknown
|
|
541
|
+
* (a reconcile at the next process start, a call interrupted mid-execution) carries no mark, because
|
|
542
|
+
* telling a consumer it did not run could invite a replay of a write that already took effect.
|
|
543
|
+
*/
|
|
544
|
+
notExecuted?: true;
|
|
491
545
|
/**
|
|
492
546
|
* design/99 §E1 — `true` when {@link output} was SIZE-bounded by core (the full body exceeded the cap and
|
|
493
547
|
* was degraded to a truncated string). Lets a consumer detect truncation programmatically instead of
|
|
@@ -11,7 +11,7 @@ import type { NestedUsage } from "./tool-spec.js";
|
|
|
11
11
|
* `"suspended"` (design/45) is a **non-terminal** outcome: the task hit a durable tool-policy gate
|
|
12
12
|
* (`ask` with a `CheckpointStore` wired) and persisted a checkpoint instead of finishing — resume it
|
|
13
13
|
* with `runner.resume(checkpointToken, outcome)`. v1 contract: it is only safe at the **top-level
|
|
14
|
-
* `runTask` boundary**; the orchestrators (cascade/
|
|
14
|
+
* `runTask` boundary**; the orchestrators (cascade/verify/repair-loop) map an unexpected `suspended`
|
|
15
15
|
* to `failed` + `errorCode:"unexpected.suspended"` and pass the token up (§11 Q6, hard boundary).
|
|
16
16
|
*
|
|
17
17
|
* `"needs_review"` (design/76 §2.5, dry-run / shadow; design/80 D-B, plan-gate) is also a **non-terminal,
|
package/dist/core/task-spec.d.ts
CHANGED
|
@@ -426,15 +426,34 @@ export interface TaskSpec {
|
|
|
426
426
|
*/
|
|
427
427
|
tools?: ToolSpec[];
|
|
428
428
|
/**
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
436
|
-
*
|
|
437
|
-
*
|
|
429
|
+
* The run's tool ALLOWLIST — the availability selector (true unmount, NOT a permission gate): when set, the run may use only the
|
|
430
|
+
* tools it names, out of everything the engine would otherwise mount for it (the caller's tools, the hands, the engine's own
|
|
431
|
+
* tools, MCP and A2A tools, scenario and leg tools); the rest never reach `tools[]`. Omitted ⇒ the default set (a delegated
|
|
432
|
+
* child: whatever its parent could use). `[]` ⇒ no tools. An entry `"*"` ⇒ no allowlist on this layer (still bounded by the
|
|
433
|
+
* ceiling a spawning run handed down — a child's `"*"` never widens its parent).
|
|
434
|
+
*
|
|
435
|
+
* Entries are read like {@link excludeTools}: a wire name or an alias it declares, `mcp__srv` / `mcp__srv__*` for every tool
|
|
436
|
+
* of a server (including tools it lists later), a glob over the tool segment. The engine resolves the list against its OWN
|
|
437
|
+
* roster at prepare — a host passes the names it was given and never computes a complement. A name no tool answers to, a
|
|
438
|
+
* protocol-wide `mcp__*`, or an entry that is not a string is REFUSED at prepare (`config.tool_face_control`). The same
|
|
439
|
+
* compiled selector is applied on every later roster change (an MCP refresh or re-dial, the deferred-search lane): an exact name
|
|
440
|
+
* admits no new tool. Deferral is reached through ToolSearch, so a list that leaves it out defers nothing.
|
|
441
|
+
*
|
|
442
|
+
* A tool a leg relies on (a delegated child's ReportBlocked, a teammate's SendMessage, a goal iteration's DeclareDone, an
|
|
443
|
+
* observer's report tool — the catalog's protocol column) is not an allowlist's to name; a denylist that reaches one on such a
|
|
444
|
+
* leg is refused at prepare.
|
|
445
|
+
*/
|
|
446
|
+
allowTools?: string[];
|
|
447
|
+
/**
|
|
448
|
+
* per-scenario tool ROSTER removal (true unmount, NOT a permission gate): the tools this list names are removed from the
|
|
449
|
+
* mounted tool set AFTER assembly — their schemas never reach `tools[]` (unlike a policy deny, which gates calls but still
|
|
450
|
+
* ships the schema bytes every request — measured at zero token savings). The DENY half of the run's tool selector, read
|
|
451
|
+
* exactly as a sub-agent's denied tools are: a wire name or an alias it declares; `Tool(content)` names the whole `Tool`;
|
|
452
|
+
* `mcp__srv` / `mcp__srv__*` / a glob over the tool segment for a server's tools, `mcp__*` for every MCP tool (including tools
|
|
453
|
+
* a server lists later). A name no tool answers to, `"*"`, or an entry that is not a string is REFUSED at prepare
|
|
454
|
+
* (`config.tool_face_control`) — a misspelt exclusion guards nothing. A deny wins over {@link allowTools}.
|
|
455
|
+
* ⚠️ A list that reaches a tool this kind of leg relies on (see {@link allowTools}) is refused; excluding a host-requested
|
|
456
|
+
* structural tool (the structured-output tool) can still strand the task — the caller owns that risk.
|
|
438
457
|
*/
|
|
439
458
|
excludeTools?: string[];
|
|
440
459
|
/**
|
|
@@ -854,6 +873,20 @@ export interface TaskSpec {
|
|
|
854
873
|
* (#123). The write faces are untouched.
|
|
855
874
|
*/
|
|
856
875
|
readDenyPatterns?: readonly import("../tools/fs/read-deny.js").ReadDenyEntry[];
|
|
876
|
+
/**
|
|
877
|
+
* TASK-layer rows ADDED to the write-protection table ({@link readDenyPatterns}' law): the run's table is the deployment's
|
|
878
|
+
* ({@link RunnerDeps.writeProtectedPaths}) UNION these; `[]` ≡ absent; no task-layer value removes a deployment row. A
|
|
879
|
+
* covered write is the judge's mandated ask (`write_protection`), as for a deployment row. Bad shapes refuse at prepare
|
|
880
|
+
* (`config.invalid_argument`); rides every engine-built child spec add-only.
|
|
881
|
+
*/
|
|
882
|
+
writeProtectedAdditions?: readonly import("./write-protect.js").WriteProtectedEntry[];
|
|
883
|
+
/**
|
|
884
|
+
* TASK-layer denies ADDED to the compliance posture ({@link readDenyPatterns}' law): the run's deny set is the deployment's
|
|
885
|
+
* ({@link RunnerDeps.compliancePostureResolver}) UNION these; `[]` ≡ absent; nothing here removes a deployment deny. A hit
|
|
886
|
+
* is refused exactly as a deployment deny is. Members outside the closed capability set refuse at prepare
|
|
887
|
+
* (`config.invalid_argument`) — never a silently dropped deny; rides every engine-built child spec add-only.
|
|
888
|
+
*/
|
|
889
|
+
complianceAdditionalDenies?: readonly import("./compliance.js").ComplianceCapability[];
|
|
857
890
|
/**
|
|
858
891
|
* design/199 件A — the TASK layer's read-face containment declaration
|
|
859
892
|
* ({@link import("../tools/fs/containment-face.js").ContainmentFace}). "roots" pins this task (and, via the
|
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
* `runner/terminal-projection.ts` — the one cause→plane derivation.
|
|
10
10
|
*/
|
|
11
11
|
import type { AssertAllKeysHandled } from "./ask-origin.js";
|
|
12
|
+
import type { ProviderCondition, ProviderConditionSource } from "../brain/provider-dialect.js";
|
|
13
|
+
import type { RequestRoute } from "../brain/request-route.js";
|
|
14
|
+
import type { ModelOutputInvalidCause, OutputLimit } from "../internal/llm.js";
|
|
12
15
|
/**
|
|
13
16
|
* WHY a run ended — ONE tagged cause, and the ONLY terminal record a {@link TaskResult} carries. The run
|
|
14
17
|
* loop's terminal arbitration used to decide a `status` word plus seven optional plane fields one by one
|
|
@@ -32,6 +35,14 @@ import type { AssertAllKeysHandled } from "./ask-origin.js";
|
|
|
32
35
|
*/
|
|
33
36
|
export type TerminalCause = {
|
|
34
37
|
kind: "completed";
|
|
38
|
+
/**
|
|
39
|
+
* A machine-readable account beside a completion, for the one shape that completes yet may be short:
|
|
40
|
+
* `finish_reason_unknown` — the final turn's provider ended it with a stream-end word the brain does not read
|
|
41
|
+
* (`AssistantMessage.finishReasonUnknown`); the turn was kept as the model left it, and the run announced the
|
|
42
|
+
* word (`route.finish_reason_unknown`). PRESENCE: only when the final assistant message carried that seat and the
|
|
43
|
+
* run completed on it; every other completion leaves it absent.
|
|
44
|
+
*/
|
|
45
|
+
detail?: TerminalCompletedDetail;
|
|
35
46
|
} | {
|
|
36
47
|
kind: "failed";
|
|
37
48
|
/**
|
|
@@ -69,14 +80,16 @@ export type TerminalCause = {
|
|
|
69
80
|
/** Human-readable failure text. */
|
|
70
81
|
message?: string;
|
|
71
82
|
/**
|
|
72
|
-
* A machine-readable account of the failure beside `code
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* `
|
|
76
|
-
*
|
|
77
|
-
* connect / stream failure
|
|
78
|
-
* A 401 / 403 (credentials) and a 429 (rate limit) are refusals too: branch on `status
|
|
79
|
-
*
|
|
83
|
+
* A machine-readable account of the failure beside `code` — the fact the failure's mint point stated, projected
|
|
84
|
+
* once ({@link TerminalFailureDetail}; branch on `detail.kind`, never on `message`):
|
|
85
|
+
* - `provider_rejected` — the provider REFUSED the request as sent (a 4xx answer) and that refusal named this
|
|
86
|
+
* result. `status` is the refusal's HTTP status (`TaskResult.apiFailure.status`, the same value); `code` the
|
|
87
|
+
* provider's own word (`AssistantMessage.apiErrorCode`); `route` the request's route. A run whose
|
|
88
|
+
* higher-ranked cause named the result, a 5xx, a connect / stream failure and an in-band error inside a 200
|
|
89
|
+
* carry none. A 401 / 403 (credentials) and a 429 (rate limit) are refusals too: branch on `status`.
|
|
90
|
+
* - `coded` — the run threw a coded error (this `code`) whose throw site stated a structured `detail`.
|
|
91
|
+
* - `model_output_invalid` — the model's final turn failed because its tool calls could not be executed.
|
|
92
|
+
* PRESENCE: only when the arm that named this result has such a fact to project; absent otherwise.
|
|
80
93
|
*/
|
|
81
94
|
detail?: TerminalFailureDetail;
|
|
82
95
|
/**
|
|
@@ -144,14 +157,84 @@ export type TerminalCause = {
|
|
|
144
157
|
*/
|
|
145
158
|
restoreMode?: "snapshot" | "park_only";
|
|
146
159
|
};
|
|
147
|
-
/** The machine-readable account a `
|
|
148
|
-
export interface
|
|
160
|
+
/** The machine-readable account a `completed` cause may carry ({@link TerminalCause}). `kind` is closed; one member. */
|
|
161
|
+
export interface TerminalCompletedDetail {
|
|
162
|
+
kind: "finish_reason_unknown";
|
|
163
|
+
/** The provider's stream-end word, in the provider echo shape (`?` when it had bytes outside it). */
|
|
164
|
+
finishReasonUnknown: string;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* The machine-readable account a `failed` cause may carry ({@link TerminalCause}) — the ONE projection of a fact the
|
|
168
|
+
* failure's mint point already stated, carried as it was stated (a missing fact stays missing; nothing is re-derived
|
|
169
|
+
* from the message). `kind` is closed:
|
|
170
|
+
* - `provider_rejected` — the provider REFUSED the request as sent (a 4xx answer) and that refusal named the result:
|
|
171
|
+
* the terminal message's refusal account (`apiErrorStatus` / `apiErrorCode` / the provider-condition verdict / the
|
|
172
|
+
* request's `apiErrorRoute`).
|
|
173
|
+
* - `coded` — a failure THROWN with a machine code whose throw site stated a structured `detail` beside it (e.g. a
|
|
174
|
+
* `CheckpointError`'s `{ reason }` on `resume.parent_constraint_mismatch`): that detail, as a JSON-plain snapshot.
|
|
175
|
+
* `terminal.code` is the same error's code.
|
|
176
|
+
* - `model_output_invalid` — the model's turn failed because its tool calls could not be executed: the terminal
|
|
177
|
+
* message's `modelOutputInvalid` account.
|
|
178
|
+
* New members join with a minor; a consumer that branches on `kind` keeps a default arm.
|
|
179
|
+
*/
|
|
180
|
+
export type TerminalFailureDetail = {
|
|
149
181
|
kind: "provider_rejected";
|
|
150
182
|
/** The refusal's HTTP status, 400–499. */
|
|
151
183
|
status: number;
|
|
152
184
|
/** The provider's own word for the refusal (its error envelope's `error.code`, else `error.type`), when stated. */
|
|
153
185
|
code?: string;
|
|
154
|
-
|
|
186
|
+
/**
|
|
187
|
+
* What the refusal says about the account — the engine's closed word for it (`PROVIDER_CONDITIONS`), judged off
|
|
188
|
+
* the provider dialect table by where the request went: `quota_exhausted` (stop; someone must act or a window
|
|
189
|
+
* must reset), `throttled` / `overloaded` / `unknown` (a retryable condition the retry budget ran out on, or the
|
|
190
|
+
* provider's own `x-should-retry: false` stopped), `stop_other` (credentials, model access, the request itself).
|
|
191
|
+
* The terminal's reading of the same verdict the call's retry frames carried. Present whenever the terminal
|
|
192
|
+
* message states one (`AssistantMessage.providerCondition`); a host-minted message that did not judge leaves it
|
|
193
|
+
* absent.
|
|
194
|
+
*/
|
|
195
|
+
providerCondition?: ProviderCondition;
|
|
196
|
+
/** Which evidence {@link providerCondition} rests on. Present exactly when it is. */
|
|
197
|
+
providerConditionSource?: ProviderConditionSource;
|
|
198
|
+
/** The terminal message's `providerResetAtMs`, carried beside a `quota_exhausted` condition. */
|
|
199
|
+
providerResetAtMs?: number;
|
|
200
|
+
/**
|
|
201
|
+
* The route the refused request took (`AssistantMessage.apiErrorRoute`): where its credential came from, how it
|
|
202
|
+
* rode, which knob named its root — the knob words of `ROUTE_CREDENTIAL_PAIRING`, never a key value or a URL.
|
|
203
|
+
* Present whenever the terminal message states one (the first-party brains always do); a host-minted message that
|
|
204
|
+
* states none leaves it absent.
|
|
205
|
+
*/
|
|
206
|
+
route?: RequestRoute;
|
|
207
|
+
} | {
|
|
208
|
+
kind: "coded";
|
|
209
|
+
/**
|
|
210
|
+
* The thrown error's own `detail`, as its throw site stated it — a snapshot of its JSON-plain members (strings,
|
|
211
|
+
* finite numbers, booleans, null, and arrays / plain objects of those, bounded; a member of any other kind is left
|
|
212
|
+
* out; bytes — an `ArrayBuffer` view, an index-keyed object — are never a record). A member under a credential
|
|
213
|
+
* name (the env-credential judge's names: `password`, `apiKey`, `token` …) stands as `"[redacted]"`, unread; every
|
|
214
|
+
* other string leaf passes the secret-tier redaction (credential shapes masked; a path is kept — it rides this
|
|
215
|
+
* structured seat, never `message`); a member whose key is not JSON-safe (visible ASCII 1–128, nothing the
|
|
216
|
+
* redaction would mask) is left out. Read off the same link of the error's `cause` chain whose `code` became
|
|
217
|
+
* `terminal.code`. PRESENCE: only when that link carried a plain-object `detail` with at least one such member — a
|
|
218
|
+
* code thrown without one (or a higher-ranked terminal that named the result) leaves the whole account absent.
|
|
219
|
+
*/
|
|
220
|
+
detail: CodedFailureDetail;
|
|
221
|
+
} | {
|
|
222
|
+
kind: "model_output_invalid";
|
|
223
|
+
/** Which drop cause failed the turn (`MODEL_OUTPUT_INVALID_CAUSES`: `truncated` — arguments cut before they
|
|
224
|
+
* parsed; `unnamed` — a call with no tool name). The same words `task.tool_turn_incomplete` announces. */
|
|
225
|
+
cause: ModelOutputInvalidCause;
|
|
226
|
+
/** With `truncated`: the output-cap facts the stream reported (the cap stop, the counted output, the request's
|
|
227
|
+
* cap) — what the brain's sentence words as its cap clause. */
|
|
228
|
+
outputLimit?: OutputLimit;
|
|
229
|
+
};
|
|
230
|
+
/** A JSON-plain value as a `coded` account carries it. */
|
|
231
|
+
export type CodedFailureDetailValue = string | number | boolean | null | readonly CodedFailureDetailValue[] | {
|
|
232
|
+
readonly [key: string]: CodedFailureDetailValue;
|
|
233
|
+
};
|
|
234
|
+
/** The `coded` account's body: the thrown error's `detail` members ({@link TerminalFailureDetail}). */
|
|
235
|
+
export type CodedFailureDetail = {
|
|
236
|
+
readonly [key: string]: CodedFailureDetailValue;
|
|
237
|
+
};
|
|
155
238
|
/**
|
|
156
239
|
* The endings of a `userPromptSubmit` hook that keep a prompt from being submitted — the closed set of
|
|
157
240
|
* {@link TerminalBlockedDetail.cause} words:
|
|
@@ -11,10 +11,11 @@ export declare class TaskSpecTightenError extends Error {
|
|
|
11
11
|
* - **`toolPolicy`** — both set ⇒ `combinePolicies(base, override)` (deny-wins; the base's denials survive,
|
|
12
12
|
* the override can only ADD denials/asks). Either alone ⇒ that one. This is the central fix: a blind spread
|
|
13
13
|
* would drop the base policy entirely.
|
|
14
|
-
* -
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
* - **every row of the clamp table** (`CLAMP_SET`: `handsReadOnly`, `interactiveTools`, `approvalReach`, the two
|
|
15
|
+
* containment faces, `readDenyPatterns`, `oneShot`, `memoryPersistenceCapable`, `fileHistory`) — a base carrying the
|
|
16
|
+
* row's restricting value meeting an override that states a different one ⇒ **throw** (loosening); otherwise the
|
|
17
|
+
* restricting value wins if either side carries it, an add-only list unions, and an override writing `undefined`
|
|
18
|
+
* erases nothing.
|
|
18
19
|
* - **`shellGate`** — one value (`"always"`, the operator floor). Either side set ⇒ the floor stands; it cannot
|
|
19
20
|
* be loosened because absence is the only other state and an override cannot unset a base value.
|
|
20
21
|
* - **`onAsk`** — no safe automatic merge (the approver and the policy must be coordinated). Both set to
|