@sema-agent/core 7.55.0 → 7.56.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 +513 -0
- package/dist/agents/cascade.js +1 -1
- package/dist/agents/cc-peer-directory.js +1 -0
- package/dist/agents/child-model-seat.d.ts +0 -11
- package/dist/agents/child-model-seat.js +0 -3
- package/dist/agents/list-agents-tool.d.ts +3 -1
- package/dist/agents/list-agents-tool.js +7 -7
- package/dist/agents/peer-directory.d.ts +22 -4
- package/dist/agents/peer-directory.js +24 -2
- package/dist/agents/peer-session-drain.js +2 -2
- package/dist/agents/repair-loop.js +2 -2
- package/dist/agents/send-message-tool.js +4 -4
- package/dist/agents/subagent.d.ts +6 -4
- package/dist/agents/subagent.js +64 -60
- package/dist/agents/tool-filter.d.ts +7 -5
- package/dist/agents/tool-filter.js +12 -9
- package/dist/agents/verify.d.ts +3 -2
- package/dist/agents/verify.js +3 -3
- package/dist/brain/anthropic.js +30 -73
- package/dist/brain/media-degrade.d.ts +18 -7
- package/dist/brain/media-degrade.js +13 -2
- package/dist/brain/model-capability.d.ts +37 -0
- package/dist/brain/model-capability.js +34 -0
- package/dist/brain/model-presets.d.ts +2 -8
- package/dist/brain/model-presets.js +1 -6
- package/dist/brain/open-responses.js +13 -26
- package/dist/brain/openai.js +14 -87
- package/dist/brain/reasoning-request.d.ts +96 -0
- package/dist/brain/reasoning-request.js +174 -0
- package/dist/brain/reasoning.d.ts +11 -11
- package/dist/brain/reasoning.js +4 -3
- package/dist/brain/request-params.d.ts +7 -4
- package/dist/brain/request-params.js +7 -4
- package/dist/brain/status-sink.d.ts +20 -0
- package/dist/brain/status-sink.js +7 -0
- package/dist/core/a2a.d.ts +2 -1
- package/dist/core/a2a.js +19 -13
- package/dist/core/agent-definition.d.ts +10 -0
- package/dist/core/allow-entry.d.ts +20 -13
- package/dist/core/allow-entry.js +26 -22
- package/dist/core/allow-rule-shadow.d.ts +3 -3
- package/dist/core/ask-origin.d.ts +64 -18
- package/dist/core/ask-origin.js +63 -23
- package/dist/core/ask-question.d.ts +51 -8
- package/dist/core/ask-question.js +3 -4
- package/dist/core/ask-unresolvable-notice.d.ts +8 -3
- package/dist/core/ask-unresolvable-notice.js +16 -2
- package/dist/core/checkpoint-generation.d.ts +53 -0
- package/dist/core/checkpoint-generation.js +35 -0
- package/dist/core/checkpoint-queries.d.ts +180 -0
- package/dist/core/checkpoint-queries.js +272 -0
- package/dist/core/checkpoint-requirements.d.ts +13 -1
- package/dist/core/checkpoint-requirements.js +4 -0
- package/dist/core/checkpoint-store.d.ts +88 -24
- package/dist/core/checkpoint-store.js +24 -9
- package/dist/core/cross-boundary-taint.d.ts +6 -5
- package/dist/core/cross-boundary-taint.js +1 -3
- package/dist/core/decision-receipt.d.ts +37 -3
- package/dist/core/decision-receipt.js +17 -17
- package/dist/core/delegation-not-started.d.ts +6 -0
- package/dist/core/delegation-not-started.js +17 -0
- package/dist/core/engine-attestation.d.ts +93 -0
- package/dist/core/engine-attestation.js +70 -0
- package/dist/core/engine-capabilities.d.ts +4 -1
- package/dist/core/engine-capabilities.js +1 -1
- package/dist/core/engine-notice.d.ts +30 -11
- package/dist/core/file-history-store.d.ts +90 -14
- package/dist/core/file-history-store.js +23 -15
- package/dist/core/gate-fold.d.ts +1 -1
- package/dist/core/gate-fold.js +22 -10
- package/dist/core/gate-lanes.js +73 -64
- package/dist/core/gate-outcome.d.ts +26 -5
- package/dist/core/gate-outcome.js +26 -0
- package/dist/core/governance-codes.d.ts +5 -1
- package/dist/core/governance-codes.js +6 -0
- package/dist/core/hooks.d.ts +17 -16
- package/dist/core/hooks.js +3 -1
- package/dist/core/host-floor.d.ts +128 -0
- package/dist/core/host-floor.js +206 -0
- package/dist/core/host-target.d.ts +38 -3
- package/dist/core/host-target.js +38 -5
- package/dist/core/mcp.d.ts +5 -1
- package/dist/core/mcp.js +67 -41
- package/dist/core/memory-engine/delegation-settlement.js +15 -24
- package/dist/core/memory-engine/engine.js +4 -4
- package/dist/core/memory-engine/layout.d.ts +60 -8
- package/dist/core/memory-engine/layout.js +65 -6
- package/dist/core/model-seat.d.ts +10 -3
- package/dist/core/mods/classic-events.d.ts +67 -0
- package/dist/core/mods/classic-events.js +1 -0
- package/dist/core/mods/dollar.d.ts +13 -0
- package/dist/core/mods/extension-call.d.ts +31 -0
- package/dist/core/mods/extension-call.js +43 -0
- package/dist/core/mods/kernel/dispatch.d.ts +20 -3
- package/dist/core/mods/kernel/dispatch.js +140 -69
- package/dist/core/mods/kernel/events.d.ts +47 -11
- package/dist/core/mods/kernel/events.js +66 -42
- package/dist/core/mods/kernel/index.d.ts +4 -4
- package/dist/core/mods/kernel/index.js +2 -2
- package/dist/core/mods/kernel/receive.d.ts +39 -5
- package/dist/core/mods/kernel/receive.js +290 -17
- package/dist/core/mods/kernel/registration.d.ts +33 -2
- package/dist/core/mods/kernel/registration.js +6 -7
- package/dist/core/mods/kernel/site-rules.d.ts +44 -16
- package/dist/core/mods/kernel/site-rules.js +24 -42
- package/dist/core/mods/spec-seats.d.ts +69 -0
- package/dist/core/mods/spec-seats.js +114 -0
- package/dist/core/mods/stations.d.ts +28 -8
- package/dist/core/mods/stations.js +29 -13
- package/dist/core/mods/tool-call.d.ts +79 -0
- package/dist/core/mods/tool-call.js +152 -0
- package/dist/core/namespaced-rule-name.d.ts +32 -38
- package/dist/core/namespaced-rule-name.js +29 -36
- package/dist/core/parent-spec-seat.d.ts +6 -1
- package/dist/core/parent-spec-seat.js +2 -0
- package/dist/core/park-selfcheck.js +1 -0
- package/dist/core/permission-rule-consent.d.ts +19 -0
- package/dist/core/permission-rule-consent.js +116 -26
- package/dist/core/permission-rule-model.d.ts +14 -3
- package/dist/core/permission-rule-model.js +39 -24
- package/dist/core/permission-rule-org.d.ts +6 -2
- package/dist/core/permission-rule-org.js +7 -3
- package/dist/core/permission-rule-provider.d.ts +5 -2
- package/dist/core/permission-rule-provider.js +41 -11
- package/dist/core/permission-rule-store.d.ts +3 -2
- package/dist/core/permission-rule-store.js +11 -2
- package/dist/core/permission-rule-sync.js +3 -2
- package/dist/core/permission-rule-syntax.d.ts +5 -4
- package/dist/core/permission-rule-syntax.js +2 -2
- package/dist/core/permission-rules.d.ts +4 -4
- package/dist/core/permission-rules.js +11 -20
- package/dist/core/persisted-rule-arms.d.ts +2 -2
- package/dist/core/persisted-rule-arms.js +10 -12
- package/dist/core/principal-name.d.ts +20 -0
- package/dist/core/principal-name.js +22 -0
- package/dist/core/prompt-section-seat.js +4 -6
- package/dist/core/protocol-http-auth.d.ts +26 -5
- package/dist/core/protocol-http-auth.js +137 -4
- package/dist/core/retired-keys.d.ts +16 -0
- package/dist/core/retired-keys.js +16 -4
- package/dist/core/rewrite-rejudge.d.ts +60 -0
- package/dist/core/rewrite-rejudge.js +36 -0
- package/dist/core/roles.d.ts +28 -1
- package/dist/core/roles.js +31 -19
- package/dist/core/rule-lane-reads.d.ts +20 -15
- package/dist/core/rule-lane-reads.js +45 -17
- package/dist/core/rule-owner.d.ts +3 -3
- package/dist/core/rule-owner.js +3 -2
- package/dist/core/runner/announce-once-ledger.d.ts +14 -0
- package/dist/core/runner/announce-once-ledger.js +5 -0
- package/dist/core/runner/assemble-result.d.ts +1 -0
- package/dist/core/runner/assemble-result.js +1 -1
- package/dist/core/runner/call-hook-stations.d.ts +3 -2
- package/dist/core/runner/caller-roster.d.ts +16 -4
- package/dist/core/runner/caller-roster.js +33 -6
- package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
- package/dist/core/runner/capability-withheld-seat.js +24 -0
- package/dist/core/runner/classifier-ladder.d.ts +7 -9
- package/dist/core/runner/classifier-ladder.js +3 -3
- package/dist/core/runner/construction-doors.js +3 -0
- package/dist/core/runner/contracts.d.ts +28 -25
- package/dist/core/runner/cross-boundary-lane.d.ts +17 -13
- package/dist/core/runner/cross-boundary-lane.js +40 -27
- package/dist/core/runner/denial-limit-arms.d.ts +2 -2
- package/dist/core/runner/denial-limit-arms.js +1 -1
- package/dist/core/runner/file-history-request.d.ts +18 -0
- package/dist/core/runner/file-history-request.js +21 -13
- package/dist/core/runner/file-history-restore.d.ts +45 -0
- package/dist/core/runner/file-history-restore.js +46 -0
- package/dist/core/runner/gate-exit.d.ts +3 -3
- package/dist/core/runner/gate-exit.js +4 -3
- package/dist/core/runner/image.d.ts +7 -17
- package/dist/core/runner/image.js +9 -60
- package/dist/core/runner/permission-rule-lanes.d.ts +4 -4
- package/dist/core/runner/permission-rule-lanes.js +26 -10
- package/dist/core/runner/person-path-rows.d.ts +12 -9
- package/dist/core/runner/person-path-rows.js +18 -7
- package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
- package/dist/core/runner/prepare-ask-lane.js +5 -2
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
- package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
- package/dist/core/runner/prepare-config-doors.d.ts +29 -38
- package/dist/core/runner/prepare-config-doors.js +42 -25
- package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
- package/dist/core/runner/prepare-defer-classify.js +7 -8
- package/dist/core/runner/prepare-file-history.d.ts +48 -8
- package/dist/core/runner/prepare-file-history.js +7 -39
- package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
- package/dist/core/runner/prepare-gate-stations.js +10 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
- package/dist/core/runner/prepare-hands-readface.js +15 -14
- package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
- package/dist/core/runner/prepare-inherited-gate.js +5 -3
- package/dist/core/runner/prepare-memory-engine-session.js +1 -1
- package/dist/core/runner/prepare-park-ask.js +5 -5
- package/dist/core/runner/prepare-policy-chain.d.ts +6 -3
- package/dist/core/runner/prepare-policy-chain.js +65 -72
- package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
- package/dist/core/runner/prepare-prompt-assembly.js +10 -8
- package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
- package/dist/core/runner/prepare-prompt-inputs.js +3 -5
- package/dist/core/runner/prepare-protocol-tools.d.ts +2 -0
- package/dist/core/runner/prepare-protocol-tools.js +3 -3
- package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
- package/dist/core/runner/prepare-safety-scan.js +0 -17
- package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
- package/dist/core/runner/prepare-suspend-saga.js +5 -6
- package/dist/core/runner/prepare-task.d.ts +1 -1
- package/dist/core/runner/prepare-task.js +29 -20
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
- package/dist/core/runner/prepare-tool-disclosure-mount.js +20 -16
- package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
- package/dist/core/runner/prepare-turn-wiring.js +2 -7
- package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -2
- package/dist/core/runner/prepare-wiring-manifest.js +3 -3
- package/dist/core/runner/resume-admission.js +1 -1
- package/dist/core/runner/resume-apply.js +11 -12
- package/dist/core/runner/resume-checkpoint-screen.js +3 -0
- package/dist/core/runner/resume-claim.d.ts +4 -2
- package/dist/core/runner/resume-claim.js +15 -8
- package/dist/core/runner/retired-runner-deps.js +1 -0
- package/dist/core/runner/rewind-files.d.ts +15 -0
- package/dist/core/runner/rewind-files.js +132 -0
- package/dist/core/runner/run-attachment-seats.js +2 -1
- package/dist/core/runner/run-brain-sinks.d.ts +4 -1
- package/dist/core/runner/run-brain-sinks.js +4 -2
- package/dist/core/runner/run-harness-handlers.js +12 -4
- package/dist/core/runner/run-leg.d.ts +1 -1
- package/dist/core/runner/run-leg.js +30 -18
- package/dist/core/runner/run-settle-and-teardown.js +2 -1
- package/dist/core/runner/run-turn-boundary.js +1 -10
- package/dist/core/runner/runtask.d.ts +3 -0
- package/dist/core/runner/runtask.js +8 -9
- package/dist/core/runner/session-read-file-states.d.ts +15 -0
- package/dist/core/runner/session-read-file-states.js +28 -0
- package/dist/core/runner/session-rule-policy.js +4 -3
- package/dist/core/runner/shell-env-withheld.d.ts +33 -0
- package/dist/core/runner/shell-env-withheld.js +51 -0
- package/dist/core/runner/skills-seat.js +6 -2
- package/dist/core/runner/stream-settle-backstop.js +1 -1
- package/dist/core/runner/sub-agent-deny-lists.js +4 -7
- package/dist/core/runner/synthetic-tools.d.ts +6 -0
- package/dist/core/runner/synthetic-tools.js +4 -1
- package/dist/core/runner/tool-disclosure.d.ts +10 -12
- package/dist/core/runner/tool-disclosure.js +1 -3
- package/dist/core/runner/tool-end-body.d.ts +1 -1
- package/dist/core/runner/tool-end-body.js +10 -9
- package/dist/core/runner/tool-not-executed.d.ts +5 -0
- package/dist/core/runner/tool-not-executed.js +11 -0
- package/dist/core/runner/tool-occurrence.d.ts +8 -0
- package/dist/core/runner/tool-occurrence.js +7 -0
- package/dist/core/runner/turn-attachments.d.ts +33 -15
- package/dist/core/runner/turn-attachments.js +62 -37
- package/dist/core/runner-deps.d.ts +5 -5
- package/dist/core/safety-axis-vocab.d.ts +6 -4
- package/dist/core/safety-axis-vocab.js +6 -5
- package/dist/core/safety-merge-corpus.js +11 -3
- package/dist/core/secret-env.d.ts +26 -3
- package/dist/core/secret-env.js +44 -8
- package/dist/core/select-model.js +3 -3
- package/dist/core/session-policy-store.d.ts +27 -15
- package/dist/core/session-policy-store.js +156 -36
- package/dist/core/session-store.d.ts +29 -10
- package/dist/core/session-store.js +51 -19
- package/dist/core/session.d.ts +82 -16
- package/dist/core/session.js +53 -0
- package/dist/core/shell-read-silence.d.ts +11 -12
- package/dist/core/shell-read-silence.js +9 -5
- package/dist/core/shell-run-candidates.js +3 -1
- package/dist/core/shell-wrapper-projection.js +1 -1
- package/dist/core/shell-wrapper-table.d.ts +14 -7
- package/dist/core/shell-wrapper-table.js +5 -4
- package/dist/core/side-query.js +10 -1
- package/dist/core/skill-grant.d.ts +7 -2
- package/dist/core/skill-grant.js +5 -0
- package/dist/core/skills-directory.js +6 -2
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +140 -2
- package/dist/core/store-contracts/file-history-store-contract.js +31 -1
- package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
- package/dist/core/store-contracts/peer-directory-contract.js +14 -2
- package/dist/core/store-contracts/session-repo-contract.js +51 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +2 -1
- package/dist/core/store-contracts/session-store-contract.js +150 -14
- package/dist/core/stub-env.d.ts +2 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/synthetic-read-verdict.js +3 -3
- package/dist/core/task-event.d.ts +32 -4
- package/dist/core/task-notification.d.ts +16 -12
- package/dist/core/task-registry.d.ts +9 -0
- package/dist/core/task-registry.js +11 -1
- package/dist/core/task-result.d.ts +18 -0
- package/dist/core/task-spec.d.ts +18 -13
- package/dist/core/tighten-task-spec.js +2 -1
- package/dist/core/tool-catalog-entries.d.ts +17 -0
- package/dist/core/tool-catalog-entries.js +13 -2
- package/dist/core/tool-check-reading.d.ts +11 -0
- package/dist/core/tool-check-reading.js +11 -6
- package/dist/core/tool-model-gate.d.ts +2 -2
- package/dist/core/tool-name-aliases.d.ts +16 -16
- package/dist/core/tool-name-aliases.js +13 -19
- package/dist/core/tool-name-readings.d.ts +5 -35
- package/dist/core/tool-name-readings.js +1 -9
- package/dist/core/tool-policy.d.ts +68 -198
- package/dist/core/tool-policy.js +149 -198
- package/dist/core/tool-result-store.js +3 -0
- package/dist/core/tool-roster.d.ts +14 -19
- package/dist/core/tool-roster.js +11 -44
- package/dist/core/tool-spec-members.js +7 -2
- package/dist/core/tool-spec.d.ts +19 -11
- package/dist/core/tools.js +49 -9
- package/dist/core/trace.d.ts +2 -2
- package/dist/core/types.d.ts +1 -1
- package/dist/core/user-attachment.d.ts +8 -1
- package/dist/core/user-attachment.js +64 -4
- package/dist/core/wiring-manifest.d.ts +9 -0
- package/dist/core/wiring-manifest.js +1 -0
- package/dist/core/workflow-journal-store.js +1 -1
- package/dist/engine/compaction/compaction.js +3 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +7 -3
- package/dist/engine/execution-env/node-execution-env.js +11 -2
- package/dist/engine/harness/agent-harness.d.ts +25 -1
- package/dist/engine/harness/agent-harness.js +54 -7
- package/dist/engine/harness/types.d.ts +29 -2
- package/dist/engine/llm/types.d.ts +28 -11
- package/dist/engine/loop/agent-loop.d.ts +22 -0
- package/dist/engine/loop/agent-loop.js +16 -26
- package/dist/engine/loop/types.d.ts +16 -6
- package/dist/engine/session/memory-repo.d.ts +9 -2
- package/dist/engine/session/memory-repo.js +11 -1
- package/dist/engine/session/repo-utils.d.ts +6 -5
- package/dist/engine/session/repo-utils.js +14 -6
- package/dist/index.d.ts +22 -10
- package/dist/index.js +15 -7
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/llm.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +6 -4
- package/dist/orchestration/run-workflow-tool.js +5 -3
- package/dist/orchestration/workflow.d.ts +3 -0
- package/dist/orchestration/workflow.js +36 -18
- package/dist/prompt-assembly/artifact.d.ts +2 -2
- package/dist/prompt-assembly/artifact.js +5 -3
- package/dist/prompt-assembly/assemble.d.ts +3 -2
- package/dist/prompt-assembly/assemble.js +1 -1
- package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
- package/dist/prompt-assembly/catalog/schema.js +34 -2
- package/dist/prompt-assembly/catalog/sections.js +0 -1
- package/dist/prompt-assembly/composer.d.ts +3 -1
- package/dist/prompt-assembly/composer.js +1 -1
- package/dist/prompt-assembly/event-registry.js +1 -0
- package/dist/prompt-assembly/overlay.js +3 -3
- package/dist/prompt-assembly/renderers.d.ts +1 -1
- package/dist/prompt-assembly/renderers.js +0 -3
- package/dist/prompt-assembly/role-base.d.ts +15 -0
- package/dist/prompt-assembly/role-base.js +9 -0
- package/dist/prompt-assembly/select.d.ts +39 -14
- package/dist/prompt-assembly/select.js +47 -16
- package/dist/prompt-assembly/sugar.d.ts +17 -11
- package/dist/prompt-assembly/sugar.js +8 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +37 -3
- package/dist/prompt-assembly/tool-catalog.js +114 -4
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
- package/dist/prompt-assembly/turn-snapshot.js +0 -3
- package/dist/prompt-assembly/types.d.ts +0 -7
- package/dist/scenarios/full-body.d.ts +11 -11
- package/dist/scenarios/full-body.js +4 -3
- package/dist/shell/lex.js +10 -1
- package/dist/stores/file/adoption/adopt.js +4 -3
- package/dist/stores/file/adoption/marker.js +3 -2
- package/dist/stores/file/checkpoint-store.d.ts +21 -0
- package/dist/stores/file/checkpoint-store.js +38 -6
- package/dist/stores/file/file-history-store.js +6 -7
- package/dist/stores/file/index.js +2 -1
- package/dist/stores/file/permission-rule-adopt.js +4 -3
- package/dist/stores/file/permission-rule-store.js +11 -5
- package/dist/stores/file/session-store.d.ts +29 -6
- package/dist/stores/file/session-store.js +42 -50
- package/dist/tools/artifact/artifact-tool.js +3 -2
- package/dist/tools/fs/bash-program-position.d.ts +19 -2
- package/dist/tools/fs/bash-program-position.js +56 -9
- package/dist/tools/fs/fs-bash.js +5 -5
- package/dist/tools/fs/fs-glob.d.ts +86 -0
- package/dist/tools/fs/fs-glob.js +226 -0
- package/dist/tools/fs/fs-read.js +14 -14
- package/dist/tools/fs/fs-search-tools.js +7 -7
- package/dist/tools/fs/pattern-kill-guard.d.ts +22 -0
- package/dist/tools/fs/pattern-kill-guard.js +397 -0
- package/dist/tools/fs/pdf.d.ts +9 -6
- package/dist/tools/fs/pdf.js +3 -3
- package/dist/tools/fs/program-read-model.d.ts +57 -7
- package/dist/tools/fs/program-read-model.js +11 -1
- package/dist/tools/fs/program-read-model.rows.js +78 -21
- package/dist/tools/fs/read-deny-home.js +3 -2
- package/dist/tools/fs/removal-targets.d.ts +17 -7
- package/dist/tools/fs/removal-targets.js +47 -20
- package/dist/tools/fs/search.d.ts +10 -0
- package/dist/tools/fs/search.js +20 -26
- package/dist/tools/fs/shell-read-argv.js +89 -12
- package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
- package/dist/tools/fs/shell-read-bindings.js +41 -0
- package/dist/tools/fs/shell-read-check.js +6 -19
- package/dist/tools/fs/shell-read-environment.d.ts +5 -1
- package/dist/tools/fs/shell-read-environment.js +3 -2
- package/dist/tools/fs/shell-read-establish.d.ts +15 -0
- package/dist/tools/fs/shell-read-establish.js +19 -20
- package/dist/tools/fs/shell-read-plan.js +24 -16
- package/dist/tools/fs/shell-read-start.d.ts +6 -1
- package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
- package/dist/tools/fs/shell-read-write-targets.js +2 -3
- package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
- package/dist/tools/fs/shell-reentry-text.js +40 -2
- package/dist/tools/todo.js +63 -63
- package/dist/tools/web.d.ts +19 -14
- package/dist/tools/web.js +38 -55
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +143 -5
- package/wire-changes/core@7.56.0.json +3891 -0
- package/wire-changes/mods-kernel@7.56.0.json +303 -0
package/dist/core/tool-policy.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { argsReadFrom, carryArgsReadFrom, withArgsReading } from "./effective-path-target.js";
|
|
4
|
+
import { editRewrittenSentence, readRejudge, rewriteChasedSentence } from "./rewrite-rejudge.js";
|
|
4
5
|
import { brandPolicyAskClass } from "./ask-class.js";
|
|
5
6
|
import { decisionAskClassesOf, headlessDenialMessage } from "./ask-origin.js";
|
|
7
|
+
import { attest, attestationOf, isEngineAttestation, mergeAttestation, mintAttestation, withAttestation } from "./engine-attestation.js";
|
|
6
8
|
import { ownReadRootCandidate, readRootGrantSeat } from "./read-root-grant-screen.js";
|
|
7
9
|
import { decidersNote, settledByDecider } from "./gate-outcome.js";
|
|
8
10
|
import { unjudgedAllowRefused } from "./real-approval.js";
|
|
@@ -19,9 +21,9 @@ import { egressText, egressThrownText } from "./untrusted-egress.js";
|
|
|
19
21
|
import { assertNoRetiredKeys, assertNoRetiredToolPolicyKeys, RETIRED_DECISION_MEMBERS, RETIRED_TOOL_POLICY_KEYS } from "./retired-keys.js";
|
|
20
22
|
import { DECISION_MEMBER_ARMS, isEngineRefusal, nestedRecordsOf, receiveContract, receiveNestedRecords, refusedOutOfContract, screenContractValues } from "./decision-receipt.js";
|
|
21
23
|
export { isEngineRefusal } from "./decision-receipt.js";
|
|
22
|
-
import {
|
|
24
|
+
import { isCoveringRuleName, ruleNameCovers } from "./namespaced-rule-name.js";
|
|
23
25
|
import { ruleContentOf } from "./permission-rule-model.js";
|
|
24
|
-
import {
|
|
26
|
+
import { grantWildcardRefusalOf } from "./tool-name-aliases.js";
|
|
25
27
|
import { ruleSpellingOf } from "./permission-rule-syntax.js";
|
|
26
28
|
import { protocolOf } from "./protocol-table.js";
|
|
27
29
|
import { anchorSpelling, isAbsoluteForFamily, normalizeAbsPathLexically, pathFamilyOf, writeTargetPath } from "../tools/fs/safety.js";
|
|
@@ -37,75 +39,7 @@ export function exemptRootsSeat(exemptRoots) {
|
|
|
37
39
|
function settledByNobody(kind) {
|
|
38
40
|
return { kind, who: { party: "none" }, when: Date.now() };
|
|
39
41
|
}
|
|
40
|
-
|
|
41
|
-
settlement: "answer",
|
|
42
|
-
origin: "answer",
|
|
43
|
-
classes: "answer",
|
|
44
|
-
inputDigest: "answer",
|
|
45
|
-
classifierCause: "classifierCause",
|
|
46
|
-
classifierRound: "classifierRound",
|
|
47
|
-
unresolvableCause: "unresolvableCause",
|
|
48
|
-
foldedClasses: "foldedClasses",
|
|
49
|
-
pathDenial: "pathDenial",
|
|
50
|
-
bindingRefusal: "bindingRefusal",
|
|
51
|
-
};
|
|
52
|
-
const ATTESTATION_MEMBERS = Object.keys(ATTESTATION_GROUP_OF);
|
|
53
|
-
const groupLead = (g) => ATTESTATION_MEMBERS.find((k) => ATTESTATION_GROUP_OF[k] === g);
|
|
54
|
-
const ENGINE_ATTESTATIONS = new WeakSet();
|
|
55
|
-
function detachedMember(v) {
|
|
56
|
-
if (Array.isArray(v))
|
|
57
|
-
return Object.freeze([...v]);
|
|
58
|
-
if (typeof v !== "object" || v === null)
|
|
59
|
-
return v;
|
|
60
|
-
return Object.freeze(Object.fromEntries(Object.entries(v).map(([k, x]) => [k, typeof x === "object" && x !== null ? Object.freeze(Array.isArray(x) ? [...x] : { ...x }) : x])));
|
|
61
|
-
}
|
|
62
|
-
export function mintAttestation(call, members) {
|
|
63
|
-
const record = { toolCallId: call.toolCallId, toolName: call.toolName };
|
|
64
|
-
for (const k of ATTESTATION_MEMBERS)
|
|
65
|
-
if (members[k] !== undefined)
|
|
66
|
-
record[k] = detachedMember(members[k]);
|
|
67
|
-
const minted = Object.freeze(record);
|
|
68
|
-
ENGINE_ATTESTATIONS.add(minted);
|
|
69
|
-
return minted;
|
|
70
|
-
}
|
|
71
|
-
export function isEngineAttestation(v) {
|
|
72
|
-
return typeof v === "object" && v !== null && ENGINE_ATTESTATIONS.has(v);
|
|
73
|
-
}
|
|
74
|
-
const boundTo = (r, call) => isEngineAttestation(r) && r.toolCallId === call.toolCallId && r.toolName === call.toolName ? r : undefined;
|
|
75
|
-
export function attestationOf(d, call) {
|
|
76
|
-
if (typeof d !== "object" || d === null)
|
|
77
|
-
return undefined;
|
|
78
|
-
return boundTo(Object.getOwnPropertyDescriptor(d, "attestation")?.value, call);
|
|
79
|
-
}
|
|
80
|
-
export function mergeAttestation(call, earlier, later, scope = "all") {
|
|
81
|
-
const a = boundTo(earlier, call);
|
|
82
|
-
const b = boundTo(later, call);
|
|
83
|
-
if (a === undefined)
|
|
84
|
-
return b;
|
|
85
|
-
const members = {};
|
|
86
|
-
if (b !== undefined)
|
|
87
|
-
for (const k of ATTESTATION_MEMBERS)
|
|
88
|
-
if (b[k] !== undefined)
|
|
89
|
-
members[k] = b[k];
|
|
90
|
-
let filled = false;
|
|
91
|
-
for (const g of new Set(Object.values(ATTESTATION_GROUP_OF))) {
|
|
92
|
-
if ((scope === "answer" && g !== "answer") || members[groupLead(g)] !== undefined || a[groupLead(g)] === undefined)
|
|
93
|
-
continue;
|
|
94
|
-
for (const k of ATTESTATION_MEMBERS)
|
|
95
|
-
if (ATTESTATION_GROUP_OF[k] === g && a[k] !== undefined)
|
|
96
|
-
members[k] = a[k];
|
|
97
|
-
filled = true;
|
|
98
|
-
}
|
|
99
|
-
if (!filled)
|
|
100
|
-
return b;
|
|
101
|
-
return mintAttestation(call, members);
|
|
102
|
-
}
|
|
103
|
-
export function attest(d, call, members) {
|
|
104
|
-
return withAttestation(d, mergeAttestation(call, attestationOf(d, call), mintAttestation(call, members)));
|
|
105
|
-
}
|
|
106
|
-
export function withAttestation(d, record) {
|
|
107
|
-
return record === undefined ? d : { ...d, attestation: record };
|
|
108
|
-
}
|
|
42
|
+
export { attest, attestationOf, isEngineAttestation, mergeAttestation, mintAttestation, withAttestation } from "./engine-attestation.js";
|
|
109
43
|
const UNASKED_SEAT_SETTLEMENTS = new Set(["task_aborted", "no_approver"]);
|
|
110
44
|
function seatNeverAsked(settlement) {
|
|
111
45
|
return settlement !== undefined && UNASKED_SEAT_SETTLEMENTS.has(settlement.kind);
|
|
@@ -196,21 +130,11 @@ export function toolPolicyWriteGuardRows(policies) {
|
|
|
196
130
|
return undefined;
|
|
197
131
|
return async (at) => (await Promise.all(sources.map((rowsOf) => rowsOf(at)))).flat();
|
|
198
132
|
}
|
|
199
|
-
export function
|
|
200
|
-
return (entries ?? []).filter((entry) =>
|
|
133
|
+
export function coveringRuleEntries(entries, behavior) {
|
|
134
|
+
return (entries ?? []).filter((entry) => isCoveringRuleName(entry, behavior));
|
|
201
135
|
}
|
|
202
|
-
function
|
|
203
|
-
|
|
204
|
-
return undefined;
|
|
205
|
-
const sentence = wildcardPeerRefusalOf(ruleSpellingOf(entry)?.toolName ?? entry, "allow");
|
|
206
|
-
if (sentence === undefined)
|
|
207
|
-
return undefined;
|
|
208
|
-
const e = new Error(`${who}: ${list} entry "${entry}" — ${sentence}`);
|
|
209
|
-
e.code = "config.invalid_tool_name_set";
|
|
210
|
-
return e;
|
|
211
|
-
}
|
|
212
|
-
export function namespacedCoveringHit(covering, call) {
|
|
213
|
-
return covering.length > 0 && nameListHolds({ has: (name) => covering.some((e) => namespacedRuleNameCovers(e, name)) }, call);
|
|
136
|
+
export function coveringRuleHit(covering, call) {
|
|
137
|
+
return covering.length > 0 && nameListHolds({ has: (name) => covering.some((e) => ruleNameCovers(e, name)) }, call);
|
|
214
138
|
}
|
|
215
139
|
export function projectionToolNames(c) {
|
|
216
140
|
return c.kind === "shell_command" ? { member: "tools", list: c.tools } : { member: "names", list: c.names };
|
|
@@ -219,13 +143,13 @@ export function checkToolPolicyProjection(projection, req) {
|
|
|
219
143
|
const listed = (list) => heldBy("policy.projectionReplay", { has: (n) => list.includes(n) }, req);
|
|
220
144
|
for (const c of projection.components) {
|
|
221
145
|
if (c.kind === "tool_deny") {
|
|
222
|
-
if (listed(c.names) ||
|
|
146
|
+
if (listed(c.names) || coveringRuleHit(coveringRuleEntries(c.names, "deny"), req)) {
|
|
223
147
|
return { action: "deny", message: `tool "${req.toolName}" is denied by a frozen inherited policy projection` };
|
|
224
148
|
}
|
|
225
149
|
continue;
|
|
226
150
|
}
|
|
227
151
|
if (c.kind === "tool_allowlist") {
|
|
228
|
-
if (!listed(c.names) && !
|
|
152
|
+
if (!listed(c.names) && !coveringRuleHit(coveringRuleEntries(c.names, "allow"), req)) {
|
|
229
153
|
return { action: "deny", message: `tool "${req.toolName}" is not in a frozen inherited policy projection's allowlist` };
|
|
230
154
|
}
|
|
231
155
|
continue;
|
|
@@ -300,6 +224,12 @@ const HOOK_SEAM_UNREAD = new Set(["decisionReason"]);
|
|
|
300
224
|
const HOOK_SEAM_OPTIONAL = new Set(["action"]);
|
|
301
225
|
const HOOK_RECEIPTS = new WeakSet();
|
|
302
226
|
const ENGINE_RECEIPTS = new WeakSet();
|
|
227
|
+
function askOfAnotherCall(d, call) {
|
|
228
|
+
if (call === undefined || d.action !== "ask" || d.attestation === undefined || attestationOf(d, call) !== undefined)
|
|
229
|
+
return undefined;
|
|
230
|
+
return refusedOutOfContract(`a permission decision asks with the engine's record of another call — what the engine found about that call's question is not this call's; ` +
|
|
231
|
+
`a policy answers the call it is asked about (a cached or relayed ask is asked again); denied fail-closed rather than reading the findings as absent`);
|
|
232
|
+
}
|
|
303
233
|
export function refuseOutOfContractDecision(d, opts) {
|
|
304
234
|
const hookSeam = opts?.reasonIsNonInput === true;
|
|
305
235
|
if (hookSeam && (d === null || d === undefined || Object.is(d, false)))
|
|
@@ -308,7 +238,7 @@ export function refuseOutOfContractDecision(d, opts) {
|
|
|
308
238
|
return refusedOutOfContract(`a permission decision's "action" is absent (the decision is ${d === null || d === undefined ? String(d) : `a ${typeof d}`}, not an object) — the closed set is allow/deny/ask; denied fail-closed rather than reading a word outside it as an allow`);
|
|
309
239
|
}
|
|
310
240
|
if ((hookSeam ? HOOK_RECEIPTS : ENGINE_RECEIPTS).has(d) || isEngineRefusal(d))
|
|
311
|
-
return d;
|
|
241
|
+
return askOfAnotherCall(d, opts?.call) ?? d;
|
|
312
242
|
const decision = receiveContract(d, hookSeam ? HOOK_RESULT_MEMBERS : DECISION_MEMBERS, "", RETIRED_DECISION_MEMBERS);
|
|
313
243
|
if (decision.kind === "refused")
|
|
314
244
|
return decision.refused;
|
|
@@ -323,13 +253,9 @@ export function refuseOutOfContractDecision(d, opts) {
|
|
|
323
253
|
: `a permission decision carries an "attestation" the engine did not mint — the member is an engine record (who settled the call, ` +
|
|
324
254
|
`which question it answered); denied fail-closed rather than reading a caller's value as a settlement`);
|
|
325
255
|
}
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
return refusedOutOfContract(`a permission decision carries "foldedAskClasses" that no policy fold of the engine attested on it — the member is ` +
|
|
330
|
-
`engine-written (combinePolicies records the classes of the asks it collapsed); denied fail-closed rather than letting a ` +
|
|
331
|
-
`class no station judged reach the class derivation`);
|
|
332
|
-
}
|
|
256
|
+
const foreign = askOfAnotherCall({ action: contract.action, attestation }, opts?.call);
|
|
257
|
+
if (foreign !== undefined)
|
|
258
|
+
return foreign;
|
|
333
259
|
if (hookSeam && contract.additionalContext !== undefined && typeof contract.additionalContext !== "string") {
|
|
334
260
|
return refusedOutOfContract(`a PreToolUse hook result's "additionalContext" is not a string — the member is the text appended for the model; denied fail-closed rather than rendering a value this layer cannot classify`);
|
|
335
261
|
}
|
|
@@ -387,86 +313,75 @@ export function toolPolicyNameSets(p) {
|
|
|
387
313
|
const sets = p?.nameSets;
|
|
388
314
|
return Array.isArray(sets) ? sets : [];
|
|
389
315
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const
|
|
400
|
-
if (
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
const malformed = suffix.length === 0 || sep === 0 || (sep > 0 && suffix.length === sep + 2);
|
|
404
|
-
if (malformed) {
|
|
405
|
-
const family = ns.id.toUpperCase();
|
|
406
|
-
const lesson = `a malformed ${family} tool name (empty peer or tool segment) — it can never match any mounted tool. ` +
|
|
407
|
-
`Use \`${ns.prefix}<peer>\` for every tool of a peer, or \`${ns.prefix}<peer>__<tool>\` for one tool.`;
|
|
408
|
-
invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
|
|
409
|
-
continue;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
const spelled = ruleSpellingOf(entry);
|
|
413
|
-
if (spelled === undefined) {
|
|
414
|
-
const lesson = `a spelling no tool name can have — the rule syntax reads no tool name in it, so a name set never names a tool by it. Fix the entry.`;
|
|
316
|
+
function screenToolNameList(entries, list, behavior, invalid) {
|
|
317
|
+
if (entries === undefined)
|
|
318
|
+
return undefined;
|
|
319
|
+
const kept = [];
|
|
320
|
+
const seen = new Set();
|
|
321
|
+
for (const entry of entries) {
|
|
322
|
+
const ns = protocolOf(entry);
|
|
323
|
+
if (ns !== undefined) {
|
|
324
|
+
const suffix = entry.slice(ns.prefix.length);
|
|
325
|
+
const sep = suffix.indexOf("__");
|
|
326
|
+
if (suffix.length === 0 || sep === 0 || (sep > 0 && suffix.length === sep + 2)) {
|
|
327
|
+
const lesson = `a malformed ${ns.id.toUpperCase()} tool name (empty peer or tool segment) — it can never match any mounted tool. ` +
|
|
328
|
+
`Use \`${ns.prefix}<peer>\` for every tool of a peer, or \`${ns.prefix}<peer>__<tool>\` for one tool.`;
|
|
415
329
|
invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
|
|
416
330
|
continue;
|
|
417
331
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if (wild !== undefined) {
|
|
427
|
-
invalid.push({ entry, list, message: `"${entry}": ${wild}`, lesson: wild });
|
|
428
|
-
continue;
|
|
429
|
-
}
|
|
430
|
-
if (!seen.has(spelled.toolName)) {
|
|
431
|
-
seen.add(spelled.toolName);
|
|
432
|
-
kept.push(spelled.toolName);
|
|
433
|
-
}
|
|
434
|
-
continue;
|
|
435
|
-
}
|
|
332
|
+
}
|
|
333
|
+
const spelled = ruleSpellingOf(entry);
|
|
334
|
+
if (spelled === undefined) {
|
|
335
|
+
const lesson = `a spelling no tool name can have — the rule syntax reads no tool name in it, so a name set never names a tool by it. Fix the entry.`;
|
|
336
|
+
invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
if (ruleContentOf(spelled) !== undefined) {
|
|
436
340
|
const lesson = `a rule CONTENT form, not a tool name — a name set matches raw tool names, so this entry ` +
|
|
437
341
|
`can never match any mounted tool (in an allow list it removes the tool entirely). Use the tool NAME here, ` +
|
|
438
342
|
`and route the narrowing through the lane that speaks this grammar: parameter rules via ` +
|
|
439
343
|
`createPermissionRulePolicy, Bash command prefixes via the persisted allow-rule lane.`;
|
|
440
344
|
invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
|
|
345
|
+
continue;
|
|
441
346
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
if (invalid.length > 0) {
|
|
447
|
-
if ((opts.onInvalidName ?? "throw") === "throw") {
|
|
448
|
-
const byLesson = new Map();
|
|
449
|
-
for (const i of invalid) {
|
|
450
|
-
const group = byLesson.get(i.lesson) ?? [];
|
|
451
|
-
group.push({ entry: i.entry, list: i.list });
|
|
452
|
-
byLesson.set(i.lesson, group);
|
|
453
|
-
}
|
|
454
|
-
const e = new Error(`createAllowDenyPolicy: ${invalid.length} entr${invalid.length === 1 ? "y is" : "ies are"} not tool name(s):\n` +
|
|
455
|
-
[...byLesson.entries()]
|
|
456
|
-
.map(([lesson, group]) => ` Each of the following is ${lesson}\n` + group.map((g) => ` [${g.list}] "${g.entry}"`).join("\n"))
|
|
457
|
-
.join("\n"));
|
|
458
|
-
e.code = "config.invalid_tool_name_set";
|
|
459
|
-
e.issues = invalid;
|
|
460
|
-
throw e;
|
|
347
|
+
const wild = behavior === "allow" ? grantWildcardRefusalOf(spelled.toolName) : undefined;
|
|
348
|
+
if (wild !== undefined) {
|
|
349
|
+
invalid.push({ entry, list, message: `"${entry}": ${wild}`, lesson: wild });
|
|
350
|
+
continue;
|
|
461
351
|
}
|
|
352
|
+
if (!seen.has(spelled.toolName)) {
|
|
353
|
+
seen.add(spelled.toolName);
|
|
354
|
+
kept.push(spelled.toolName);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return kept;
|
|
358
|
+
}
|
|
359
|
+
function toolNameSetRefusal(who, invalid) {
|
|
360
|
+
const byLesson = new Map();
|
|
361
|
+
for (const i of invalid)
|
|
362
|
+
byLesson.set(i.lesson, [...(byLesson.get(i.lesson) ?? []), { entry: i.entry, list: i.list }]);
|
|
363
|
+
const e = new Error(`${who}: ${invalid.length} entr${invalid.length === 1 ? "y is" : "ies are"} not tool name(s):\n` +
|
|
364
|
+
[...byLesson.entries()].map(([lesson, group]) => ` Each of the following is ${lesson}\n` + group.map((g) => ` [${g.list}] "${g.entry}"`).join("\n")).join("\n"));
|
|
365
|
+
e.code = "config.invalid_tool_name_set";
|
|
366
|
+
e.issues = invalid;
|
|
367
|
+
return e;
|
|
368
|
+
}
|
|
369
|
+
export function createAllowDenyPolicy(opts) {
|
|
370
|
+
assertNoRetiredKeys(opts, RETIRED_ALLOW_DENY_POLICY_OPTIONS, "createAllowDenyPolicy");
|
|
371
|
+
const invalid = [];
|
|
372
|
+
const screenedAllow = screenToolNameList(opts.allow, "allow", "allow", invalid);
|
|
373
|
+
const screenedDeny = screenToolNameList(opts.deny, "deny", "deny", invalid);
|
|
374
|
+
if (invalid.length > 0) {
|
|
375
|
+
if ((opts.onInvalidName ?? "throw") === "throw")
|
|
376
|
+
throw toolNameSetRefusal("createAllowDenyPolicy", invalid);
|
|
462
377
|
for (const issue of invalid)
|
|
463
378
|
opts.onInvalidNameIssue?.(issue);
|
|
464
379
|
}
|
|
465
380
|
opts = { ...opts, ...(screenedAllow ? { allow: screenedAllow } : {}), ...(screenedDeny ? { deny: screenedDeny } : {}) };
|
|
466
381
|
const allow = opts.allow ? new Set(opts.allow) : undefined;
|
|
467
382
|
const deny = new Set(opts.deny ?? []);
|
|
468
|
-
const denyCovering =
|
|
469
|
-
const allowCovering =
|
|
383
|
+
const denyCovering = coveringRuleEntries(opts.deny, "deny");
|
|
384
|
+
const allowCovering = coveringRuleEntries(opts.allow, "allow");
|
|
470
385
|
return {
|
|
471
386
|
projection: {
|
|
472
387
|
components: [
|
|
@@ -477,10 +392,10 @@ export function createAllowDenyPolicy(opts) {
|
|
|
477
392
|
},
|
|
478
393
|
nameSets: [{ ...(opts.allow ? { allow: [...opts.allow] } : {}), ...(opts.deny ? { deny: [...opts.deny] } : {}) }],
|
|
479
394
|
check(req) {
|
|
480
|
-
if (nameListHolds(deny, req) ||
|
|
395
|
+
if (nameListHolds(deny, req) || coveringRuleHit(denyCovering, req)) {
|
|
481
396
|
return { action: "deny", message: `tool "${req.toolName}" is denied by policy` };
|
|
482
397
|
}
|
|
483
|
-
if (allow && !nameListHolds(allow, req) && !
|
|
398
|
+
if (allow && !nameListHolds(allow, req) && !coveringRuleHit(allowCovering, req)) {
|
|
484
399
|
return { action: "deny", message: `tool "${req.toolName}" is not in the allowlist` };
|
|
485
400
|
}
|
|
486
401
|
return ALLOW;
|
|
@@ -497,19 +412,21 @@ export function createApprovalPolicy(opts) {
|
|
|
497
412
|
if (opts.approvalTimeoutMs !== undefined && opts.approvalTimeoutMs > 2_147_483_647) {
|
|
498
413
|
throw new Error(`createApprovalPolicy: approvalTimeoutMs must not exceed 2147483647ms (~24.8 days) (got ${opts.approvalTimeoutMs}) — a host timer truncates a larger delay and fires immediately, denying every request at once; omit it to wait indefinitely`);
|
|
499
414
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
415
|
+
const invalid = [];
|
|
416
|
+
const requireApproval = screenToolNameList(opts.requireApproval, "requireApproval", "ask", invalid) ?? [];
|
|
417
|
+
const denied = screenToolNameList(opts.deny, "deny", "deny", invalid);
|
|
418
|
+
const autoAllow = screenToolNameList(opts.autoAllow, "autoAllow", "allow", invalid);
|
|
419
|
+
if (opts.denyByDefault === true)
|
|
420
|
+
screenToolNameList(requireApproval, "requireApproval", "allow", invalid);
|
|
421
|
+
if (invalid.length > 0)
|
|
422
|
+
throw toolNameSetRefusal("createApprovalPolicy", invalid);
|
|
423
|
+
opts = { ...opts, requireApproval, ...(denied !== undefined ? { deny: denied } : {}), ...(autoAllow !== undefined ? { autoAllow } : {}) };
|
|
507
424
|
const need = new Set(opts.requireApproval);
|
|
508
425
|
const deny = new Set(opts.deny ?? []);
|
|
509
426
|
const auto = new Set(opts.autoAllow ?? []);
|
|
510
|
-
const needCovering =
|
|
511
|
-
const denyCovering =
|
|
512
|
-
const autoCovering =
|
|
427
|
+
const needCovering = coveringRuleEntries(opts.requireApproval, "ask");
|
|
428
|
+
const denyCovering = coveringRuleEntries(opts.deny, "deny");
|
|
429
|
+
const autoCovering = coveringRuleEntries(opts.autoAllow, "allow");
|
|
513
430
|
return {
|
|
514
431
|
projection: {
|
|
515
432
|
components: [
|
|
@@ -526,10 +443,10 @@ export function createApprovalPolicy(opts) {
|
|
|
526
443
|
},
|
|
527
444
|
],
|
|
528
445
|
async check(req, signal) {
|
|
529
|
-
if (nameListHolds(deny, req) ||
|
|
446
|
+
if (nameListHolds(deny, req) || coveringRuleHit(denyCovering, req)) {
|
|
530
447
|
return { action: "deny", message: `tool "${req.toolName}" is denied by policy` };
|
|
531
448
|
}
|
|
532
|
-
if (nameListHolds(need, req) ||
|
|
449
|
+
if (nameListHolds(need, req) || coveringRuleHit(needCovering, req)) {
|
|
533
450
|
const attestOver = (inputDigest) => (d, settlement, bindingRefusal) => ({ ...d, attestation: mintAttestation(req, { settlement, origin: "policy", ...(inputDigest !== undefined ? { inputDigest } : {}), ...(bindingRefusal !== undefined ? { bindingRefusal } : {}) }) });
|
|
534
451
|
const unasked = unaskedSeatAnswer(req, signal, { aborted: `approval aborted for "${req.toolName}" (run or turn interrupted)`, unreachable: `approval for "${req.toolName}" was not requested: nobody can be asked about this call` }, "policy");
|
|
535
452
|
if (unasked !== undefined)
|
|
@@ -592,7 +509,7 @@ export function createApprovalPolicy(opts) {
|
|
|
592
509
|
}
|
|
593
510
|
return attest({ action: "deny", message: `approval denied for "${req.toolName}"` }, settledByDecider("person", "refused", undefined));
|
|
594
511
|
}
|
|
595
|
-
if (nameListHolds(auto, req) ||
|
|
512
|
+
if (nameListHolds(auto, req) || coveringRuleHit(autoCovering, req))
|
|
596
513
|
return ALLOW;
|
|
597
514
|
if (opts.denyByDefault) {
|
|
598
515
|
return { action: "deny", message: `tool "${req.toolName}" requires explicit allow` };
|
|
@@ -636,7 +553,6 @@ export function combinePolicies(...policies) {
|
|
|
636
553
|
let asked;
|
|
637
554
|
let current = Object.freeze({ ...req });
|
|
638
555
|
let rewrite;
|
|
639
|
-
let records;
|
|
640
556
|
let ruleAskText;
|
|
641
557
|
let probeMandateSeen = false;
|
|
642
558
|
let mandateSeen = false;
|
|
@@ -644,25 +560,64 @@ export function combinePolicies(...policies) {
|
|
|
644
560
|
let noRulingSeen;
|
|
645
561
|
let authoredBySeen = false;
|
|
646
562
|
const contributors = [];
|
|
647
|
-
const
|
|
563
|
+
const decisions = [];
|
|
564
|
+
const recordsExcept = (at) => decisions.reduce((acc, d, j) => (j !== at && d?.action === "allow" && d.attestation !== undefined ? mergeAttestation(req, acc, d.attestation) : acc), undefined);
|
|
565
|
+
const settleDeny = (d, at) => {
|
|
648
566
|
const out = rewrite !== undefined ? refusalOf(d, current.args) : d;
|
|
567
|
+
const records = recordsExcept(at);
|
|
649
568
|
if (records === undefined)
|
|
650
569
|
return out;
|
|
651
570
|
return { ...out, attestation: mergeAttestation(req, records, d.attestation) };
|
|
652
571
|
};
|
|
653
572
|
let seatDeny;
|
|
654
|
-
|
|
655
|
-
|
|
573
|
+
const denied = (d, at) => {
|
|
574
|
+
decisions[at] = undefined;
|
|
575
|
+
if (!seatNeverAsked(attestationOf(d, current)?.settlement))
|
|
576
|
+
return settleDeny(d, at);
|
|
577
|
+
seatDeny ??= settleDeny(d, at);
|
|
578
|
+
return undefined;
|
|
579
|
+
};
|
|
580
|
+
let emitter = -1;
|
|
581
|
+
let personWrote = false;
|
|
582
|
+
for (const [at, p] of policies.entries()) {
|
|
583
|
+
const d = refuseOutOfContractDecision(await p.check(current, signal), { call: req });
|
|
656
584
|
if (d.action === "deny") {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
585
|
+
const ended = denied(d, at);
|
|
586
|
+
if (ended !== undefined)
|
|
587
|
+
return ended;
|
|
660
588
|
continue;
|
|
661
589
|
}
|
|
662
|
-
|
|
590
|
+
decisions[at] = d;
|
|
591
|
+
if (readRejudge(current, current.args, d).kind === "rewritten") {
|
|
592
|
+
if (personWrote)
|
|
593
|
+
return settleDeny({ action: "deny", message: `${editRewrittenSentence(req.toolName)}, which a later policy layer wrote over a person's edit — denied fail-closed` }, at);
|
|
663
594
|
current = Object.freeze(await withArgsReading(current, d.updatedInput, signal));
|
|
664
595
|
rewrite = d;
|
|
596
|
+
emitter = at;
|
|
597
|
+
personWrote = attestationOf(d, current)?.settlement?.who.party === "person" && answeredFor(d, req, current.args);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
for (let at = 0; at < emitter; at++) {
|
|
601
|
+
const p = policies[at];
|
|
602
|
+
const d = refuseOutOfContractDecision(await p.check(current, signal), { call: req });
|
|
603
|
+
if (d.action === "deny") {
|
|
604
|
+
const ended = denied(d, at);
|
|
605
|
+
if (ended !== undefined)
|
|
606
|
+
return ended;
|
|
607
|
+
continue;
|
|
665
608
|
}
|
|
609
|
+
if (readRejudge(current, current.args, d).kind === "rewritten")
|
|
610
|
+
return settleDeny({ action: "deny", message: rewriteChasedSentence(req.toolName) }, at);
|
|
611
|
+
const { updatedInput: _sameBytes, ...asIs } = d;
|
|
612
|
+
const first = decisions[at];
|
|
613
|
+
decisions[at] = asIs.action === "allow" && first?.action === "allow" && first.attestation !== undefined ? withAttestation(asIs, mergeAttestation(req, first.attestation, asIs.attestation)) : asIs;
|
|
614
|
+
}
|
|
615
|
+
if (seatDeny !== undefined)
|
|
616
|
+
return seatDeny;
|
|
617
|
+
let records;
|
|
618
|
+
for (const d of decisions) {
|
|
619
|
+
if (d === undefined)
|
|
620
|
+
continue;
|
|
666
621
|
if (d.action === "allow" && d.attestation !== undefined)
|
|
667
622
|
records = mergeAttestation(req, records, d.attestation);
|
|
668
623
|
if (d.action === "ask" && (asked === undefined || (d.requiresRealApproval === true && asked.requiresRealApproval !== true))) {
|
|
@@ -684,8 +639,6 @@ export function combinePolicies(...policies) {
|
|
|
684
639
|
if (d.action === "ask")
|
|
685
640
|
contributors.push(d);
|
|
686
641
|
}
|
|
687
|
-
if (seatDeny !== undefined)
|
|
688
|
-
return seatDeny;
|
|
689
642
|
if (asked) {
|
|
690
643
|
const merged = rewrite?.updatedInput;
|
|
691
644
|
const withRuleAsk = ruleAskText !== undefined && asked.matchedAskRule === undefined ? { ...asked, matchedAskRule: ruleAskText } : asked;
|
|
@@ -694,16 +647,15 @@ export function combinePolicies(...policies) {
|
|
|
694
647
|
const withFallback = fallbackSeen !== undefined && withMandate.denialLimitFallback === undefined ? { ...withMandate, denialLimitFallback: fallbackSeen, requiresRealApproval: true } : withMandate;
|
|
695
648
|
const withNoRuling = noRulingSeen !== undefined && withFallback.classifierNoRuling === undefined ? { ...withFallback, classifierNoRuling: noRulingSeen, requiresRealApproval: true } : withFallback;
|
|
696
649
|
const withAuthor = authoredBySeen && withNoRuling.authoredBy === undefined ? { ...withNoRuling, authoredBy: "deployment" } : withNoRuling;
|
|
697
|
-
const folded = new Set(
|
|
650
|
+
const folded = new Set(attestationOf(asked, req)?.foldedClasses ?? []);
|
|
698
651
|
for (const c of contributors)
|
|
699
652
|
if (c !== asked)
|
|
700
|
-
for (const k of decisionAskClassesOf(c))
|
|
653
|
+
for (const k of decisionAskClassesOf(c, req))
|
|
701
654
|
folded.add(k);
|
|
702
655
|
if (withNoRuling !== withMandate)
|
|
703
|
-
for (const k of decisionAskClassesOf(asked))
|
|
656
|
+
for (const k of decisionAskClassesOf(asked, req))
|
|
704
657
|
folded.add(k);
|
|
705
|
-
const
|
|
706
|
-
const out = merged !== undefined ? { ...withClasses, updatedInput: merged } : withClasses;
|
|
658
|
+
const out = merged !== undefined ? { ...withAuthor, updatedInput: merged } : withAuthor;
|
|
707
659
|
return folded.size > 0 ? attest(out, req, { foldedClasses: [...folded] }) : out;
|
|
708
660
|
}
|
|
709
661
|
const allowed = rewrite ?? ALLOW;
|
|
@@ -780,17 +732,17 @@ export function createUnverifiableDeletePolicy(opts) {
|
|
|
780
732
|
if (typeof command !== "string")
|
|
781
733
|
return ALLOW;
|
|
782
734
|
const removal = removalReadingOf(command, req, opts?.removalSeat, safeRoots);
|
|
783
|
-
return removal === undefined ? ALLOW : removal.judge(signal).then((found) => (found === undefined ? ALLOW : removalAsk(found.guard, found.text)));
|
|
735
|
+
return removal === undefined ? ALLOW : removal.judge(signal).then((found) => (found === undefined ? ALLOW : removalAsk(req, found.guard, found.text)));
|
|
784
736
|
},
|
|
785
737
|
}, "external_authority");
|
|
786
738
|
}
|
|
787
|
-
function removalAsk(guard, text) {
|
|
739
|
+
function removalAsk(req, guard, text) {
|
|
788
740
|
const messages = {
|
|
789
741
|
dangerous_delete: `Dangerous removal: ${text}. No permission mode, allow rule or classifier clears this — only a person confirming this call does.`,
|
|
790
742
|
unverifiable_delete: `Unverifiable recursive delete (fail-closed unless cleared): ${text}. Re-run the delete with the resolved literal path written into the command itself (or assign the variable a literal path in the same command, e.g. \`DIR=/exact/path; rm -rf "$DIR"\`) so the target can be verified.`,
|
|
791
|
-
unverifiable_shell_text: `Unverifiable shell text (fail-closed unless cleared): ${text}
|
|
743
|
+
unverifiable_shell_text: `Unverifiable shell text (fail-closed unless cleared): ${text}.`,
|
|
792
744
|
};
|
|
793
|
-
return { action: "ask", decisionReason: "safety", requiresRealApproval: true,
|
|
745
|
+
return attest({ action: "ask", decisionReason: "safety", requiresRealApproval: true, message: messages[guard] }, req, { guards: [guard] });
|
|
794
746
|
}
|
|
795
747
|
function pathSegments(p) {
|
|
796
748
|
return p.split(/[\\/]/).filter(Boolean);
|
|
@@ -859,16 +811,15 @@ export function createTranscriptIntegrityPolicy(opts) {
|
|
|
859
811
|
}
|
|
860
812
|
return false;
|
|
861
813
|
};
|
|
862
|
-
const askReason = (what) => ({
|
|
814
|
+
const askReason = (req, what) => attest({
|
|
863
815
|
action: "ask",
|
|
864
816
|
decisionReason: "safety",
|
|
865
817
|
requiresRealApproval: true,
|
|
866
|
-
guards: ["transcript_write"],
|
|
867
818
|
message: `Session-transcript write (fail-closed unless cleared): ${what}. Session transcripts (the .jsonl files ` +
|
|
868
819
|
`under the agent data dir's sessions/ directory) are harness-written session state, not agent working ` +
|
|
869
820
|
`files — modifying or deleting them tampers with the run's own audit trail. Reading them (ls/cat/grep ` +
|
|
870
821
|
`as a single simple command) is fine.`,
|
|
871
|
-
});
|
|
822
|
+
}, req, { guards: ["transcript_write"] });
|
|
872
823
|
return brandPolicyAskClass({
|
|
873
824
|
check(req) {
|
|
874
825
|
if (shellToolsListHolds(shellTools, req)) {
|
|
@@ -882,7 +833,7 @@ export function createTranscriptIntegrityPolicy(opts) {
|
|
|
882
833
|
const parsed = parseLeadingCommandName(command);
|
|
883
834
|
if ("name" in parsed && readAllow.has(parsed.name))
|
|
884
835
|
return ALLOW;
|
|
885
|
-
return askReason("name" in parsed
|
|
836
|
+
return askReason(req, "name" in parsed
|
|
886
837
|
? `\`${parsed.name}\` is not a read-only command${cwdInsideProtected ? " and the shell's working directory is inside the transcript directory" : ""}`
|
|
887
838
|
: cwdInsideProtected
|
|
888
839
|
? "the shell's working directory is inside the transcript directory and this is not a single read-only command (fail-closed)"
|
|
@@ -892,7 +843,7 @@ export function createTranscriptIntegrityPolicy(opts) {
|
|
|
892
843
|
if (writeTarget !== undefined && writeTarget.access !== "read") {
|
|
893
844
|
const p = writeTargetPath(req);
|
|
894
845
|
if (typeof p === "string" && inProtectedDir(p, req.cwd)) {
|
|
895
|
-
return askReason(`"${p}" is inside the session-transcript directory`);
|
|
846
|
+
return askReason(req, `"${p}" is inside the session-transcript directory`);
|
|
896
847
|
}
|
|
897
848
|
}
|
|
898
849
|
return ALLOW;
|
|
@@ -6,6 +6,7 @@ import { deliverEngineNotice } from "./types.js";
|
|
|
6
6
|
import { TOOL_SEARCH_NAME } from "./runner/tool-disclosure.js";
|
|
7
7
|
import { mountRuleFace, toolFace } from "./tool-catalog-entries.js";
|
|
8
8
|
import { thrownText } from "./thrown-value.js";
|
|
9
|
+
import { carryNotStartedReceipt } from "./delegation-not-started.js";
|
|
9
10
|
export const TOOL_RESULT_REF_CONFLICT_CODE = "tool_result.ref_conflict";
|
|
10
11
|
export class ToolResultRefConflictError extends Error {
|
|
11
12
|
ref;
|
|
@@ -239,6 +240,8 @@ export function withToolResultOffload(tool, store, thresholdChars, sessionId, re
|
|
|
239
240
|
const wrappedExecute = async (toolCallId, params, signal, onUpdate) => {
|
|
240
241
|
const res = await tool.execute(toolCallId, params, signal, onUpdate);
|
|
241
242
|
const offloadedDetails = res.details === undefined ? undefined : await offloadOversizedDetailStrings(res.details, store, thresholdChars, sessionId, toolCallId, provenance);
|
|
243
|
+
if (offloadedDetails !== undefined)
|
|
244
|
+
carryNotStartedReceipt(res.details, offloadedDetails.value);
|
|
242
245
|
const withDetails = (r) => offloadedDetails === undefined || offloadedDetails.value === res.details ? r : { ...r, details: offloadedDetails.value };
|
|
243
246
|
if (totalTextChars(res.content) <= thresholdChars)
|
|
244
247
|
return withDetails(res);
|