@sema-agent/core 7.51.2 → 7.52.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 +504 -2
- package/dist/agents/agent-transcript-tool.d.ts +1 -1
- package/dist/agents/cascade.js +4 -0
- package/dist/agents/cumulative-stats.d.ts +3 -0
- package/dist/agents/cumulative-stats.js +3 -0
- package/dist/agents/list-agents-tool.d.ts +1 -1
- package/dist/agents/read-inbox-tool.d.ts +1 -1
- package/dist/agents/repair-loop.js +4 -0
- package/dist/agents/send-message-tool.d.ts +11 -16
- package/dist/agents/send-message-tool.js +11 -13
- package/dist/agents/subagent.js +6 -4
- package/dist/agents/tool-filter.d.ts +40 -13
- package/dist/agents/tool-filter.js +28 -14
- package/dist/bench/metrics.d.ts +1 -0
- package/dist/brain/anthropic.js +16 -12
- package/dist/brain/model-presets.d.ts +4 -5
- package/dist/brain/model-presets.js +4 -4
- package/dist/brain/open-responses.js +16 -12
- package/dist/brain/openai.js +16 -12
- package/dist/brain/request-params.d.ts +12 -33
- package/dist/brain/request-params.js +5 -2
- package/dist/brain/request-route.d.ts +9 -8
- package/dist/brain/request-route.js +1 -0
- package/dist/brain/route-adjudicator.d.ts +117 -47
- package/dist/brain/route-adjudicator.js +171 -42
- package/dist/brain/route-conformance.js +2 -2
- package/dist/brain/status-sink.d.ts +18 -0
- package/dist/brain/status-sink.js +7 -0
- package/dist/core/allow-entry.d.ts +40 -8
- package/dist/core/allow-entry.js +23 -16
- package/dist/core/auto-compaction.d.ts +23 -20
- package/dist/core/auto-compaction.js +37 -16
- package/dist/core/auto-promote.d.ts +2 -1
- package/dist/core/auto-promote.js +2 -2
- package/dist/core/caller-tool-name.d.ts +9 -0
- package/dist/core/caller-tool-name.js +13 -0
- package/dist/core/checkpoint-requirements.d.ts +7 -1
- package/dist/core/checkpoint-requirements.js +2 -0
- package/dist/core/checkpoint-store.d.ts +36 -12
- package/dist/core/checkpoint-store.js +1 -1
- package/dist/core/child-clamp-seats.d.ts +6 -0
- package/dist/core/child-clamp-seats.js +2 -1
- package/dist/core/credential-vocabulary.d.ts +33 -8
- package/dist/core/credential-vocabulary.js +32 -7
- package/dist/core/decision-receipt.d.ts +2 -2
- package/dist/core/delegation-frames.d.ts +9 -2
- package/dist/core/delegation-name.d.ts +18 -0
- package/dist/core/delegation-name.js +47 -0
- package/dist/core/engine-capabilities.d.ts +8 -1
- package/dist/core/engine-capabilities.js +1 -1
- package/dist/core/engine-notice.d.ts +36 -19
- package/dist/core/frontmatter-fence.d.ts +10 -0
- package/dist/core/frontmatter-fence.js +6 -0
- package/dist/core/gate-fold.js +5 -23
- package/dist/core/gate-lanes.js +356 -270
- package/dist/core/governance-codes.d.ts +9 -4
- package/dist/core/governance-codes.js +9 -3
- package/dist/core/hooks.d.ts +276 -734
- package/dist/core/hooks.js +97 -192
- package/dist/{tools/fs → core}/image-admission.d.ts +21 -3
- package/dist/{tools/fs → core}/image-admission.js +24 -6
- package/dist/core/mcp-connection-pool.d.ts +4 -1
- package/dist/core/mcp-connection-pool.js +7 -2
- package/dist/core/mcp-probe.d.ts +12 -9
- package/dist/core/mcp-probe.js +2 -2
- package/dist/core/mcp-server-spec.d.ts +16 -0
- package/dist/core/mcp.d.ts +11 -7
- package/dist/core/mcp.js +11 -5
- package/dist/core/memory-engine/data-plane.js +5 -1
- package/dist/core/memory-engine/distiller.js +16 -2
- package/dist/core/memory-engine/engine.d.ts +8 -11
- package/dist/core/memory-engine/engine.js +9 -5
- package/dist/core/memory-engine/frontmatter.d.ts +6 -0
- package/dist/core/memory-engine/frontmatter.js +19 -16
- package/dist/core/memory.d.ts +2 -2
- package/dist/core/mode-policy.d.ts +4 -0
- package/dist/core/mode-policy.js +7 -5
- package/dist/core/model-seat.d.ts +4 -1
- package/dist/core/mods/dollar.d.ts +109 -0
- package/dist/core/mods/dollar.js +154 -0
- package/dist/core/mods/host.d.ts +23 -0
- package/dist/core/mods/host.js +21 -0
- package/dist/core/mods/kernel/budget.d.ts +43 -0
- package/dist/core/mods/kernel/budget.js +83 -0
- package/dist/core/mods/kernel/dispatch.d.ts +100 -0
- package/dist/core/mods/kernel/dispatch.js +701 -0
- package/dist/core/mods/kernel/events.d.ts +242 -0
- package/dist/core/mods/kernel/events.js +210 -0
- package/dist/core/mods/kernel/index.d.ts +6 -0
- package/dist/core/mods/kernel/index.js +5 -0
- package/dist/core/mods/kernel/receive.d.ts +65 -0
- package/dist/core/mods/kernel/receive.js +123 -0
- package/dist/core/mods/kernel/registration.d.ts +131 -0
- package/dist/core/mods/kernel/registration.js +102 -0
- package/dist/core/mods/kernel/site-rules.d.ts +84 -0
- package/dist/core/mods/kernel/site-rules.js +104 -0
- package/dist/core/mods/stations.d.ts +350 -0
- package/dist/core/mods/stations.js +444 -0
- package/dist/core/own-property-receipt.js +11 -23
- package/dist/core/parent-spec-seat.d.ts +18 -7
- package/dist/core/parent-spec-seat.js +6 -2
- package/dist/core/path-identity.js +2 -1
- package/dist/core/permission-rule-syntax.d.ts +15 -0
- package/dist/core/permission-rule-syntax.js +24 -16
- package/dist/core/permission-rules.d.ts +7 -1
- package/dist/core/permission-rules.js +26 -15
- package/dist/core/prompt-section-seat.d.ts +15 -27
- package/dist/core/prompt-section-seat.js +73 -40
- package/dist/core/protocol-http-auth.d.ts +3 -1
- package/dist/core/protocol-http-auth.js +2 -0
- package/dist/core/reminder-mint.d.ts +2 -2
- package/dist/core/remote-env.d.ts +24 -12
- package/dist/core/remote-env.js +1 -0
- package/dist/core/resume-startup-cause.d.ts +16 -1
- package/dist/core/resume-startup-cause.js +4 -1
- package/dist/core/retired-keys.d.ts +4 -0
- package/dist/core/retired-keys.js +3 -0
- package/dist/core/runner/announce-once-ledger.d.ts +31 -1
- package/dist/core/runner/announce-once-ledger.js +22 -0
- package/dist/core/runner/assemble-result.d.ts +9 -0
- package/dist/core/runner/assemble-result.js +3 -1
- package/dist/core/runner/call-hook-stations.d.ts +23 -27
- package/dist/core/runner/call-hook-stations.js +58 -42
- package/dist/core/runner/caller-stop-gate.d.ts +25 -0
- package/dist/core/runner/caller-stop-gate.js +7 -0
- package/dist/core/runner/compaction-seams.d.ts +8 -22
- package/dist/core/runner/compaction-seams.js +28 -53
- package/dist/core/runner/construction-doors.js +11 -1
- package/dist/core/runner/contracts.d.ts +85 -83
- package/dist/core/runner/credential-origin-seat.d.ts +2 -0
- package/dist/core/runner/credential-origin-seat.js +19 -0
- package/dist/core/runner/extra-body-dropped-seat.d.ts +2 -6
- package/dist/core/runner/gate-exit.d.ts +47 -36
- package/dist/core/runner/gate-exit.js +8 -2
- package/dist/core/runner/image.js +1 -2
- package/dist/core/runner/inline-image.js +1 -1
- package/dist/core/runner/notice-seat-input.d.ts +11 -0
- package/dist/core/runner/notice-seat-input.js +1 -0
- package/dist/core/runner/person-path-rows.js +1 -0
- package/dist/core/runner/prepare-acquire-reconcile.js +5 -1
- package/dist/core/runner/prepare-ask-lane.d.ts +5 -7
- package/dist/core/runner/prepare-ask-lane.js +6 -15
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
- package/dist/core/runner/prepare-caps-and-workflow.js +25 -8
- package/dist/core/runner/prepare-config-doors.d.ts +5 -0
- package/dist/core/runner/prepare-config-doors.js +9 -0
- package/dist/core/runner/prepare-defer-classify.js +3 -4
- package/dist/core/runner/prepare-gate-stations.d.ts +8 -11
- package/dist/core/runner/prepare-gate-stations.js +11 -10
- package/dist/core/runner/prepare-inherited-gate.d.ts +8 -12
- package/dist/core/runner/prepare-inherited-gate.js +8 -21
- package/dist/core/runner/prepare-memory-engine-session.js +1 -1
- package/dist/core/runner/prepare-park-ask.js +10 -14
- package/dist/core/runner/prepare-policy-chain.d.ts +17 -15
- package/dist/core/runner/prepare-policy-chain.js +95 -100
- package/dist/core/runner/prepare-project-context.js +7 -10
- package/dist/core/runner/prepare-prompt-assembly.d.ts +45 -40
- package/dist/core/runner/prepare-prompt-assembly.js +134 -101
- package/dist/core/runner/prepare-prompt-inputs.d.ts +18 -19
- package/dist/core/runner/prepare-prompt-inputs.js +5 -7
- package/dist/core/runner/prepare-protocol-tools.d.ts +6 -4
- package/dist/core/runner/prepare-protocol-tools.js +2 -2
- package/dist/core/runner/prepare-safety-scan.js +6 -10
- package/dist/core/runner/prepare-suspend-saga.d.ts +6 -0
- package/dist/core/runner/prepare-suspend-saga.js +7 -5
- package/dist/core/runner/prepare-task.js +33 -15
- package/dist/core/runner/prepare-turn-wiring.d.ts +13 -15
- package/dist/core/runner/prepare-turn-wiring.js +29 -27
- package/dist/core/runner/prepare-wiring-manifest.d.ts +5 -6
- package/dist/core/runner/prepare-wiring-manifest.js +7 -7
- package/dist/core/runner/resume-apply.d.ts +5 -2
- package/dist/core/runner/resume-apply.js +24 -42
- package/dist/core/runner/resume-checkpoint-screen.d.ts +1 -0
- package/dist/core/runner/resume-checkpoint-screen.js +9 -1
- package/dist/core/runner/resume-preflight.js +38 -16
- package/dist/core/runner/retired-runner-deps.js +3 -1
- package/dist/core/runner/run-brain-sinks.d.ts +3 -2
- package/dist/core/runner/run-brain-sinks.js +5 -1
- package/dist/core/runner/run-compaction-machinery.d.ts +7 -1
- package/dist/core/runner/run-compaction-machinery.js +7 -33
- package/dist/core/runner/run-harness-handlers.js +4 -2
- package/dist/core/runner/run-identity-wiring.d.ts +3 -1
- package/dist/core/runner/run-identity-wiring.js +3 -2
- package/dist/core/runner/run-leg.js +62 -84
- package/dist/core/runner/run-notification-lane.js +1 -0
- package/dist/core/runner/run-recovery-lanes.d.ts +3 -0
- package/dist/core/runner/run-recovery-lanes.js +11 -10
- package/dist/core/runner/run-settle-and-teardown.js +9 -28
- package/dist/core/runner/run-stop-and-final-verify.js +18 -25
- package/dist/core/runner/run-terminal-adoption.d.ts +3 -0
- package/dist/core/runner/run-terminal-adoption.js +33 -22
- package/dist/core/runner/run-tool-mount-facts.js +5 -3
- package/dist/core/runner/run-turn-boundary.js +23 -34
- package/dist/core/runner/runtask.d.ts +6 -7
- package/dist/core/runner/runtask.js +14 -72
- package/dist/core/runner/session-rule-policy.d.ts +5 -5
- package/dist/core/runner/session-rule-policy.js +13 -8
- package/dist/core/runner/side-call-account.d.ts +68 -0
- package/dist/core/runner/side-call-account.js +61 -0
- package/dist/core/runner/stream-halt-verbs.js +12 -17
- package/dist/core/runner/stream-lifecycle-verbs.js +8 -5
- package/dist/core/runner/stream-steer-verb.d.ts +1 -1
- package/dist/core/runner/stream-steer-verb.js +20 -38
- package/dist/core/runner/sub-agent-deny-lists.d.ts +121 -22
- package/dist/core/runner/sub-agent-deny-lists.js +228 -71
- package/dist/core/runner/tool-end-body.d.ts +5 -6
- package/dist/core/runner/tool-end-body.js +6 -4
- package/dist/core/runner/tool-not-executed.d.ts +15 -0
- package/dist/core/runner/tool-not-executed.js +30 -0
- package/dist/core/runner/tool-occurrence.d.ts +8 -7
- package/dist/core/runner/tool-occurrence.js +5 -5
- package/dist/core/runner/tool-result-media-seat.d.ts +1 -1
- package/dist/core/runner-deps.d.ts +20 -28
- package/dist/core/safety-merge-corpus.js +18 -2
- package/dist/core/secret-env.d.ts +88 -20
- package/dist/core/secret-env.js +192 -38
- package/dist/core/session-policy-store.d.ts +52 -16
- package/dist/core/session-policy-store.js +118 -28
- package/dist/core/session-reconcile.d.ts +4 -0
- package/dist/core/session-reconcile.js +2 -1
- package/dist/core/shell-read-silence.js +3 -32
- package/dist/core/side-query.d.ts +5 -3
- package/dist/core/skill-grant.d.ts +3 -2
- package/dist/core/skill-grant.js +17 -9
- package/dist/core/skills-directory.d.ts +31 -11
- package/dist/core/skills-directory.js +655 -104
- package/dist/core/task-event.d.ts +13 -3
- package/dist/core/task-result.d.ts +8 -0
- package/dist/core/task-spec.d.ts +20 -19
- package/dist/core/task-stream.d.ts +14 -4
- package/dist/core/tighten-task-spec.d.ts +4 -3
- package/dist/core/tighten-task-spec.js +2 -4
- package/dist/core/tool-check-reading.d.ts +74 -0
- package/dist/core/tool-check-reading.js +80 -0
- package/dist/core/tool-policy.d.ts +59 -18
- package/dist/core/tool-policy.js +77 -12
- package/dist/core/tool-registry.d.ts +20 -0
- package/dist/core/tool-registry.js +4 -0
- package/dist/core/tool-spec.d.ts +10 -6
- package/dist/core/tools.js +2 -0
- package/dist/core/trace.d.ts +51 -32
- package/dist/core/unc-spelling.d.ts +10 -0
- package/dist/core/unc-spelling.js +3 -0
- package/dist/core/untrusted-egress.d.ts +8 -0
- package/dist/core/untrusted-egress.js +4 -1
- package/dist/core/user-attachment.d.ts +12 -2
- package/dist/core/user-attachment.js +17 -2
- package/dist/core/wiring-manifest.d.ts +14 -13
- package/dist/core/wiring-manifest.js +2 -2
- package/dist/engine/compaction/utils.js +1 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +4 -3
- package/dist/engine/execution-env/symlink-chain.js +1 -1
- package/dist/engine/harness/agent-harness.d.ts +1 -1
- package/dist/engine/harness/agent-harness.js +3 -3
- package/dist/engine/harness/types.d.ts +17 -16
- package/dist/engine/harness/types.js +7 -1
- package/dist/engine/llm/types.d.ts +12 -7
- package/dist/engine/loop/agent-loop.js +1 -1
- package/dist/engine/loop/types.d.ts +1 -1
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/import-validate.js +3 -10
- package/dist/engine/session/session.d.ts +4 -4
- package/dist/engine/session/session.js +4 -4
- package/dist/index.d.ts +20 -16
- package/dist/index.js +13 -11
- package/dist/internal/harness.d.ts +1 -1
- package/dist/internal/harness.js +1 -1
- package/dist/orchestration/run-spec.d.ts +4 -6
- package/dist/orchestration/run-spec.js +39 -63
- package/dist/orchestration/run-workflow-tool.js +1 -2
- package/dist/orchestration/workflow.d.ts +11 -3
- package/dist/orchestration/workflow.js +11 -2
- package/dist/prompt-assembly/artifact-store.d.ts +37 -56
- package/dist/prompt-assembly/artifact-store.js +31 -49
- package/dist/prompt-assembly/artifact.d.ts +89 -76
- package/dist/prompt-assembly/artifact.js +167 -146
- package/dist/prompt-assembly/assemble.d.ts +34 -29
- package/dist/prompt-assembly/assemble.js +33 -220
- package/dist/prompt-assembly/bands.d.ts +20 -0
- package/dist/prompt-assembly/bands.js +18 -0
- package/dist/prompt-assembly/catalog/constitution.d.ts +23 -0
- package/dist/prompt-assembly/catalog/constitution.js +69 -0
- package/dist/prompt-assembly/catalog/core-behavior.d.ts +9 -0
- package/dist/prompt-assembly/catalog/core-behavior.js +85 -0
- package/dist/prompt-assembly/catalog/index.d.ts +11 -0
- package/dist/prompt-assembly/catalog/index.js +59 -0
- package/dist/prompt-assembly/catalog/modes.d.ts +15 -0
- package/dist/prompt-assembly/catalog/modes.js +137 -0
- package/dist/prompt-assembly/catalog/role.d.ts +10 -0
- package/dist/prompt-assembly/catalog/role.js +157 -0
- package/dist/prompt-assembly/catalog/schema.d.ts +124 -0
- package/dist/prompt-assembly/catalog/schema.js +25 -0
- package/dist/prompt-assembly/catalog/sections.d.ts +9 -0
- package/dist/prompt-assembly/catalog/sections.js +98 -0
- package/dist/prompt-assembly/catalog/team.d.ts +4 -0
- package/dist/prompt-assembly/catalog/team.js +258 -0
- package/dist/prompt-assembly/composer.d.ts +24 -28
- package/dist/prompt-assembly/composer.js +124 -46
- package/dist/prompt-assembly/epoch.d.ts +89 -79
- package/dist/prompt-assembly/epoch.js +115 -142
- package/dist/prompt-assembly/explain.d.ts +58 -34
- package/dist/prompt-assembly/explain.js +21 -24
- package/dist/prompt-assembly/overlay.d.ts +127 -0
- package/dist/prompt-assembly/overlay.js +301 -0
- package/dist/prompt-assembly/renderers.d.ts +21 -0
- package/dist/prompt-assembly/renderers.js +39 -0
- package/dist/prompt-assembly/section-usage.d.ts +3 -3
- package/dist/prompt-assembly/section-usage.js +1 -1
- package/dist/prompt-assembly/select.d.ts +56 -0
- package/dist/prompt-assembly/select.js +69 -0
- package/dist/prompt-assembly/sugar.d.ts +31 -0
- package/dist/prompt-assembly/sugar.js +20 -0
- package/dist/prompt-assembly/turn-snapshot.d.ts +3 -2
- package/dist/prompt-assembly/types.d.ts +45 -148
- package/dist/prompts/coordinator.d.ts +2 -21
- package/dist/prompts/coordinator.js +3 -255
- package/dist/prompts/cowork.d.ts +27 -16
- package/dist/prompts/cowork.js +2 -23
- package/dist/prompts/default.d.ts +38 -500
- package/dist/prompts/default.js +20 -285
- package/dist/prompts/supervisor.d.ts +6 -71
- package/dist/prompts/supervisor.js +6 -117
- package/dist/tools/fs/bash-readonly-classifier.d.ts +6 -5
- package/dist/tools/fs/dir-entries.d.ts +4 -2
- package/dist/tools/fs/dir-entries.js +16 -4
- package/dist/tools/fs/fs-bash.d.ts +1 -1
- package/dist/tools/fs/fs-bash.js +22 -11
- package/dist/tools/fs/fs-pdf.js +17 -13
- package/dist/tools/fs/fs-read.js +4 -3
- package/dist/tools/fs/fs-shared.d.ts +1 -10
- package/dist/tools/fs/fs-shared.js +3 -4
- package/dist/tools/fs/fs-write.js +2 -1
- package/dist/tools/fs/notebook.js +1 -1
- package/dist/tools/fs/pdf.d.ts +20 -10
- package/dist/tools/fs/pdf.js +19 -10
- package/dist/tools/fs/program-read-model.d.ts +68 -8
- package/dist/tools/fs/program-read-model.js +112 -33
- package/dist/tools/fs/program-read-model.rows.js +30 -10
- package/dist/tools/fs/read-deny-home.d.ts +25 -9
- package/dist/tools/fs/read-deny-home.js +28 -27
- package/dist/tools/fs/read-deny.d.ts +41 -11
- package/dist/tools/fs/read-deny.js +51 -5
- package/dist/tools/fs/safety.d.ts +4 -26
- package/dist/tools/fs/safety.js +10 -32
- package/dist/tools/fs/search.js +15 -10
- package/dist/tools/fs/shell-read-argv.d.ts +3 -2
- package/dist/tools/fs/shell-read-argv.js +118 -38
- package/dist/tools/fs/shell-read-establish.d.ts +5 -5
- package/dist/tools/fs/shell-read-establish.js +11 -61
- package/dist/tools/fs/shell-read-identity.js +6 -3
- package/dist/tools/fs/shell-read-judge.d.ts +13 -15
- package/dist/tools/fs/shell-read-judge.js +18 -4
- package/dist/tools/fs/shell-read-plan.d.ts +2 -2
- package/dist/tools/web.js +1 -1
- package/package.json +13 -1
- package/test/export-surface.snapshot.json +242 -99
- package/wire-changes/core@7.52.0.json +5859 -0
- package/dist/core/hook-seats.d.ts +0 -66
- package/dist/core/hook-seats.js +0 -37
- package/dist/prompt-assembly/packs/sema-default.d.ts +0 -2
- package/dist/prompt-assembly/packs/sema-default.js +0 -147
- package/dist/prompts/simple-sections.d.ts +0 -58
- package/dist/prompts/simple-sections.js +0 -43
package/dist/core/gate-lanes.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { withArgsReading } from "./effective-path-target.js";
|
|
2
|
-
import { attest, attestationOf, decisionText, refuseOutOfContractDecision } from "./tool-policy.js";
|
|
3
|
-
import { arbitrateByMode, classifyAsk, fileCommandOptionsSentence, persistedRuleMandateOf, ruleClearanceOf, safetyAxisOf, stampAskOrigin } from "./ask-origin.js";
|
|
2
|
+
import { attest, attestationOf, decisionText, foldHookAsk, ownArgs, refusalOf, refuseOutOfContractDecision } from "./tool-policy.js";
|
|
3
|
+
import { arbitrateByMode, classifyAsk, decisionAskClassesOf, fileCommandOptionsSentence, persistedRuleMandateOf, ruleClearanceOf, safetyAxisOf, stampAskOrigin } from "./ask-origin.js";
|
|
4
4
|
import { classifierParseFailureDenyMessage, denialLimitFallbackMessage, rungDidNotRule, unarmedWindow } from "./auto-mode.js";
|
|
5
5
|
import { classifierNoRulingArm, settleNoRulingAsk } from "./classifier-unavailable-arm.js";
|
|
6
6
|
import { SETTLEMENT_NOBODY_JUDGED } from "./gate-outcome.js";
|
|
@@ -17,11 +17,13 @@ import { callFaceSeat } from "./tool-roster.js";
|
|
|
17
17
|
import { heldBy, wireOf } from "./tool-name-readings.js";
|
|
18
18
|
import { asksUnstated, modeAcceptsFileCommand, permissionSeatAt, unstatedAskMessage } from "./mode-policy.js";
|
|
19
19
|
import { ORG_RULE_DECISION_REASON, ORG_UNAVAILABLE_DECISION_REASON } from "./permission-rule-org.js";
|
|
20
|
-
import { exitGate, passAskFace } from "./runner/gate-exit.js";
|
|
20
|
+
import { exitGate, passAskFace, unownedArgsMessage } from "./runner/gate-exit.js";
|
|
21
21
|
import { readOrgRuleLane, readPersistedRuleLane } from "./rule-lane-reads.js";
|
|
22
22
|
import { traceHookCrash } from "./gate-crash-trace.js";
|
|
23
23
|
import { createGateDeadline, awaitWriteProtectionJudgment, withGateTimeout } from "./gate-bounded-await.js";
|
|
24
24
|
import { readStationAnswer } from "./shell-read-silence.js";
|
|
25
|
+
import { agentIdOf, judgedInputOf, raiseToolCheck } from "./mods/stations.js";
|
|
26
|
+
import { readToolChecks } from "./tool-check-reading.js";
|
|
25
27
|
import { policyThrowLine, reportPolicyThrow } from "./runner/policy-throw.js";
|
|
26
28
|
const QUESTION_TOOL_NAMES = new Set([ASK_USER_QUESTION_TOOL_NAME]);
|
|
27
29
|
function parkWith(suspendAsk, parkArgs, carry) {
|
|
@@ -34,6 +36,38 @@ export async function runGateLanes(pass) {
|
|
|
34
36
|
const boundedAwaitDeadlineMs = createGateDeadline(input, notifier);
|
|
35
37
|
let orgRealApprovalRequired = false;
|
|
36
38
|
let markedThisRound;
|
|
39
|
+
let approvedWithArgs = false;
|
|
40
|
+
let carriedOwnAsk;
|
|
41
|
+
const takeApprovedEdit = (read) => {
|
|
42
|
+
carriedOwnAsk = read.outstanding ?? (pass.decision.action === "ask" ? pass.decision : undefined);
|
|
43
|
+
pass.decision = read.allow;
|
|
44
|
+
approvedWithArgs = true;
|
|
45
|
+
};
|
|
46
|
+
const safetyOf = (d) => safetyAxisOf({ egress: input.egress, shellGated: input.shellGated, irreversibility: input.irreversibility, probeMandated: d.action === "ask" && d.probeMandated === true, probeUnanswered: pass.probeUnanswered === true, tightened: pass.tightenedBy });
|
|
47
|
+
const realApprovalOf = (d, org) => {
|
|
48
|
+
if (d.action !== "ask" || d.requiresRealApproval !== true)
|
|
49
|
+
return undefined;
|
|
50
|
+
if (d.origin === undefined)
|
|
51
|
+
throw new Error(`a real-approval ask for "${toolName}" reached a park site with no origin word — the origin stamp precedes every park`);
|
|
52
|
+
return { origin: d.origin, ...(org !== undefined ? { org } : {}) };
|
|
53
|
+
};
|
|
54
|
+
const carryOf = (d) => ({
|
|
55
|
+
...(callSignal !== undefined ? { signal: callSignal } : {}),
|
|
56
|
+
...(d.action === "ask" && d.denialLimitFallback !== undefined ? { denialLimitFallback: unarmedWindow(d.denialLimitFallback) } : {}),
|
|
57
|
+
...(d.action === "ask" && d.classifierNoRuling !== undefined ? { classifierNoRuling: d.classifierNoRuling } : {}),
|
|
58
|
+
...(d.action === "ask" && d.origin !== undefined ? { origin: d.origin } : {}),
|
|
59
|
+
...(d.action === "ask" && d.askClass !== undefined && d.classes !== undefined ? { askClass: d.askClass, classes: d.classes } : {}),
|
|
60
|
+
...(d.action === "ask" && d.mandated === true ? { mandated: true, ...(d.mandate !== undefined ? { mandate: d.mandate } : {}) } : {}),
|
|
61
|
+
...(d.action === "ask" && d.authoredBy === "deployment" ? { authoredBy: "deployment" } : {}),
|
|
62
|
+
});
|
|
63
|
+
const parkAsk = async (d, req, args, safety, liveFaceUnavailable, org) => {
|
|
64
|
+
if (suspendAsk === undefined || d.action !== "ask")
|
|
65
|
+
return undefined;
|
|
66
|
+
const suspended = await parkWith(suspendAsk, [req, args, safety, liveFaceUnavailable, realApprovalOf(d, org), d.allowRuleShadowed, d.decisionReason, d.probeReason, d.probeCause, d.segmentCoverage, d.matchedAskRule, d.probeMandated], carryOf(d));
|
|
67
|
+
if (suspended && "parkFailed" in suspended)
|
|
68
|
+
pass.parkFailed = suspended.parkFailed;
|
|
69
|
+
return suspended && !("parkFailed" in suspended) ? { suspend: suspended, preToolContext: pass.preToolContext } : undefined;
|
|
70
|
+
};
|
|
37
71
|
const markedUnresolvable = () => (markedThisRound ??= input.isMarkedUnresolvable?.(input.event.toolCallId) === true);
|
|
38
72
|
const mandateMarksNow = () => ({
|
|
39
73
|
egress: input.egress,
|
|
@@ -75,7 +109,7 @@ export async function runGateLanes(pass) {
|
|
|
75
109
|
if (wireOf("lanes.orgContentAskExemption", pass.req) === ASK_USER_QUESTION_TOOL_NAME && input.orgRules.contentAskToolMounted === true)
|
|
76
110
|
return { decision: current, org: undefined };
|
|
77
111
|
let decided = current;
|
|
78
|
-
const answer = await readOrgRuleLane(input.orgRules, { toolName, args, toolCallId, ...callFaceSeat(pass.req.face) }, input.abortSignal);
|
|
112
|
+
const answer = await readOrgRuleLane(input.orgRules, Object.freeze({ toolName, args, toolCallId, ...callFaceSeat(pass.req.face) }), input.abortSignal);
|
|
79
113
|
if (answer.status === "unavailable") {
|
|
80
114
|
orgEvidence = { revisionAbsent: "unavailable", ruleAbsent: "unavailable" };
|
|
81
115
|
orgRealApprovalRequired = true;
|
|
@@ -103,7 +137,7 @@ export async function runGateLanes(pass) {
|
|
|
103
137
|
orgTightenCount += 1;
|
|
104
138
|
pass.deniedBy = "org";
|
|
105
139
|
pass.denyCause = undefined;
|
|
106
|
-
return { decision: { action: "deny", message: `an organization policy rule (${rule}) denies this call`, decisionReason: ORG_RULE_DECISION_REASON }, org: undefined };
|
|
140
|
+
return { decision: refusalOf({ action: "deny", message: `an organization policy rule (${rule}) denies this call`, decisionReason: ORG_RULE_DECISION_REASON }, args), org: undefined };
|
|
107
141
|
}
|
|
108
142
|
if (decided.action === "deny")
|
|
109
143
|
return { decision: decided, org: undefined };
|
|
@@ -120,33 +154,75 @@ export async function runGateLanes(pass) {
|
|
|
120
154
|
org: "rule",
|
|
121
155
|
};
|
|
122
156
|
};
|
|
123
|
-
const
|
|
157
|
+
const finalArgs = pass.policyRewrite !== undefined ? pass.policyRewrite : pass.currentInput;
|
|
158
|
+
if (pass.decision.action === "deny")
|
|
159
|
+
pass.decision = refusalOf(pass.decision, finalArgs);
|
|
160
|
+
const orgAnswer = await applyOrgLayer(pass.decision, finalArgs);
|
|
124
161
|
pass.decision = orgAnswer.decision;
|
|
125
162
|
const readPersistedRules = (req) => readPersistedRuleLane(input.persistedRules, req, input.abortSignal);
|
|
126
163
|
const reread = pass.policyRewrite !== undefined ? withArgsReading(pass.req, pass.policyRewrite, pass.callSignal ?? input.abortSignal) : undefined;
|
|
127
|
-
const laneReq = reread !== undefined ? await reread : { ...pass.req, ...(pass.policyRewrite !== undefined ? { args: pass.policyRewrite } : {}) };
|
|
164
|
+
const laneReq = Object.freeze(reread !== undefined ? await reread : { ...pass.req, ...(pass.policyRewrite !== undefined ? { args: pass.policyRewrite } : {}) });
|
|
128
165
|
const laneAnswer = input.persistedRules !== undefined && wireOf("lanes.persistedLaneSkip", pass.req) !== ASK_USER_QUESTION_TOOL_NAME ? await readPersistedRules(laneReq) : undefined;
|
|
129
166
|
{
|
|
130
167
|
const tightened = applyPersistedTightening(pass.decision, laneAnswer, laneReq);
|
|
131
|
-
pass.decision = tightened.decision;
|
|
168
|
+
pass.decision = tightened.tightened === "deny" ? refusalOf(tightened.decision, laneReq.args) : tightened.decision;
|
|
132
169
|
if (tightened.tightened === "deny")
|
|
133
170
|
pass.deniedBy = "persisted_rule";
|
|
134
171
|
if (tightened.tightened === "deny")
|
|
135
172
|
pass.denyCause = undefined;
|
|
136
173
|
const skillRefusal = pass.decision.action === "deny" ? undefined : skillRowRefusal(input.skillGrants, laneReq);
|
|
137
174
|
if (skillRefusal !== undefined) {
|
|
138
|
-
pass.decision = skillRefusal;
|
|
175
|
+
pass.decision = refusalOf(skillRefusal, laneReq.args);
|
|
139
176
|
pass.deniedBy = "policy";
|
|
140
177
|
pass.denyCause = undefined;
|
|
141
178
|
}
|
|
142
179
|
}
|
|
180
|
+
let settledRefusal;
|
|
181
|
+
const checkTool = async (standing, args, org, rewrite, mayClear) => {
|
|
182
|
+
const agentId = agentIdOf(input.identity);
|
|
183
|
+
const ceiling = org !== undefined ? { ceiling: "ask" } : {};
|
|
184
|
+
const e = { tool: toolName, input: judgedInputOf(args), tool_use_id: toolCallId, ...(agentId !== undefined ? { agentId } : {}), ...ceiling };
|
|
185
|
+
const signal = callSignal ?? input.abortSignal;
|
|
186
|
+
const own = input.modBus;
|
|
187
|
+
settledRefusal = undefined;
|
|
188
|
+
const settleThroughLedger = (settle) => async (ask, call, sig) => {
|
|
189
|
+
const read = ledger.fromDecision(await settle(ask, call, sig));
|
|
190
|
+
if (read.decision.action === "deny")
|
|
191
|
+
settledRefusal = { deniedBy: read.deniedBy ?? "policy", cause: ledger.causeOf(read.decision) };
|
|
192
|
+
return read.decision;
|
|
193
|
+
};
|
|
194
|
+
const chains = [
|
|
195
|
+
...(own !== undefined ? [{ raise: (p) => raiseToolCheck(own, { ...e }, p, signal), ...(mayClear !== undefined ? { mayClear } : {}) }] : []),
|
|
196
|
+
...(input.inheritedToolChecks ?? []).map((c) => ({ raise: (p) => raiseToolCheck(c.bus, { ...e }, p, signal, c.judges), settle: settleThroughLedger(c.settle) })),
|
|
197
|
+
];
|
|
198
|
+
const project = (current, clears) => {
|
|
199
|
+
const reason = decisionText(current);
|
|
200
|
+
const said = reason !== undefined ? { reason } : {};
|
|
201
|
+
return current.action === "ask" ? { decision: "ask", ...said, classes: [...(current.classes ?? [])], mandated: clears?.() !== true, ...ceiling } : { decision: "allow", ...said, ...ceiling };
|
|
202
|
+
};
|
|
203
|
+
return await readToolChecks(chains, standing, { toolName, judged: args, rewrite, request: Object.freeze({ ...pass.req, args }), signal }, project);
|
|
204
|
+
};
|
|
205
|
+
const refuseByExtension = (deny) => {
|
|
206
|
+
pass.decision = deny;
|
|
207
|
+
pass.deniedBy = settledRefusal?.deniedBy ?? "hook";
|
|
208
|
+
pass.denyCause = settledRefusal?.cause;
|
|
209
|
+
};
|
|
210
|
+
if (pass.decision.action === "allow") {
|
|
211
|
+
const read = await checkTool(pass.decision, finalArgs, orgAnswer.org, pass.policyRewrite);
|
|
212
|
+
if (read !== undefined)
|
|
213
|
+
pass.toolCheckRaised = true;
|
|
214
|
+
if (read?.kind === "denied")
|
|
215
|
+
refuseByExtension(read.deny);
|
|
216
|
+
else if (read?.kind === "asked")
|
|
217
|
+
pass.decision = read.ask;
|
|
218
|
+
else if (read?.kind === "approved")
|
|
219
|
+
takeApprovedEdit(read);
|
|
220
|
+
}
|
|
143
221
|
if (pass.decision.action === "ask") {
|
|
144
222
|
pass.decision = { ...pass.decision };
|
|
145
223
|
if (pass.policyRewrite !== undefined) {
|
|
146
224
|
pass.currentInput = pass.policyRewrite;
|
|
147
|
-
pass.req
|
|
148
|
-
if (laneReq.targetReading !== undefined)
|
|
149
|
-
pass.req.targetReading = laneReq.targetReading;
|
|
225
|
+
pass.req = Object.freeze({ ...pass.req, args: pass.policyRewrite, ...(laneReq.targetReading !== undefined ? { targetReading: laneReq.targetReading } : {}) });
|
|
150
226
|
}
|
|
151
227
|
const ruleMayClear = () => ruleClearanceOf(pass.decision.action === "ask" ? pass.decision : undefined, mandateMarksNow()).ruleMayClear;
|
|
152
228
|
const classMayClear = () => pass.decision.action === "ask" && classifyAsk(pass.decision, askOriginFacts(orgAnswer.org, laneAnswer)).row.ruleMayClear;
|
|
@@ -194,7 +270,7 @@ export async function runGateLanes(pass) {
|
|
|
194
270
|
});
|
|
195
271
|
const storedAllows = laneAnswer?.hit?.behavior === "allow" ? laneAnswer.hit.rules : undefined;
|
|
196
272
|
const members = [
|
|
197
|
-
["hook", () => (pass.
|
|
273
|
+
["hook", () => (pass.hookAllowedBy !== undefined && pass.policyRewrite === undefined ? { entries: pass.hookAllowedBy, clear: () => ({ action: "allow", message: "a PreToolUse hook allowed this call", decisionReason: "hook" }), afterClear: async () => undefined } : undefined)],
|
|
198
274
|
["deployment", () => {
|
|
199
275
|
const hit = input.deploymentAllows?.allowing(pass.req, mode);
|
|
200
276
|
return hit && { entries: hit.entries, clear: () => listAllow("deployment_rule", "the deployment's", hit.entries), afterClear: () => notifier.notifyAsync(() => input.deploymentAllows?.onAllowed?.({ toolName: pass.req.toolName, toolCallId, entries: hit.entries }), "toolGate.allowedToolsResolved") };
|
|
@@ -268,6 +344,24 @@ export async function runGateLanes(pass) {
|
|
|
268
344
|
pass.decision = { ...pass.decision, message: CD_GIT_COMPOUND_SENTENCE };
|
|
269
345
|
}
|
|
270
346
|
}
|
|
347
|
+
if (pass.toolCheckRaised !== true && pass.decision.action !== "deny") {
|
|
348
|
+
const read = await checkTool(pass.decision, pass.currentInput, orgAnswer.org, pass.policyRewrite, () => allowLayerMayClear() && ruleMayClear() && classMayClear());
|
|
349
|
+
if (read?.kind === "denied")
|
|
350
|
+
refuseByExtension(read.deny);
|
|
351
|
+
else if (read?.kind === "cleared")
|
|
352
|
+
pass.decision = read.allow;
|
|
353
|
+
else if (read?.kind === "asked") {
|
|
354
|
+
const asked = read.minted ? { ...read.ask, ruleEvidence: mintRuleEvidence(personalEvidence) } : read.ask;
|
|
355
|
+
if (read.marked === true)
|
|
356
|
+
markedThisRound = undefined;
|
|
357
|
+
const facts = read.marked === true ? askOriginFacts(orgAnswer.org, laneAnswer) : originFacts;
|
|
358
|
+
pass.decision = stampAskOrigin(asked, facts, classifyStanding(asked, facts));
|
|
359
|
+
}
|
|
360
|
+
else if (read?.kind === "shadowed" && pass.decision.action === "ask")
|
|
361
|
+
pass.decision = { ...pass.decision, allowRuleShadowed: [...(pass.decision.allowRuleShadowed ?? []), ...read.shadows] };
|
|
362
|
+
else if (read?.kind === "approved")
|
|
363
|
+
takeApprovedEdit(read);
|
|
364
|
+
}
|
|
271
365
|
if (pass.decision.action === "ask")
|
|
272
366
|
ledger.supersede();
|
|
273
367
|
if (input.autoMode && pass.decision.action === "ask" && pass.decision.origin !== undefined && pass.askClassification?.row.classifierEligible === true && (input.permissionMode === undefined || input.permissionMode() === "auto")) {
|
|
@@ -296,7 +390,7 @@ export async function runGateLanes(pass) {
|
|
|
296
390
|
pass.classifierRound = undefined;
|
|
297
391
|
}
|
|
298
392
|
else if (arm?.kind === "denied")
|
|
299
|
-
pass.decision = arm.deny;
|
|
393
|
+
pass.decision = refusalOf(arm.deny, finalArgs);
|
|
300
394
|
else {
|
|
301
395
|
const reason = verdict.kind === "block" ? (verdict.reason ? inlineUntrusted(verdict.reason) : "") : classifierParseFailureDenyMessage(verdict.classifier);
|
|
302
396
|
const category = verdict.kind === "block" && verdict.category ? inlineUntrusted(verdict.category) : "";
|
|
@@ -310,7 +404,7 @@ export async function runGateLanes(pass) {
|
|
|
310
404
|
message: verdict.kind === "block" ? `auto-mode classifier blocked this call${reason ? `: ${reason}` : category ? `: [${category}]` : ""}` : reason,
|
|
311
405
|
decisionReason: "classifier",
|
|
312
406
|
};
|
|
313
|
-
pass.decision = verdict.kind === "parse_error" ? attest(denied, pass.req, { classifierCause: "parse_error" }) : denied;
|
|
407
|
+
pass.decision = refusalOf(verdict.kind === "parse_error" ? attest(denied, pass.req, { classifierCause: "parse_error" }) : denied, finalArgs);
|
|
314
408
|
}
|
|
315
409
|
}
|
|
316
410
|
}
|
|
@@ -373,86 +467,46 @@ export async function runGateLanes(pass) {
|
|
|
373
467
|
pass.arbitration = verdict;
|
|
374
468
|
pass.deniedBy = "mode";
|
|
375
469
|
pass.denyCause = undefined;
|
|
376
|
-
pass.decision = {
|
|
470
|
+
pass.decision = refusalOf({
|
|
377
471
|
action: "deny",
|
|
378
472
|
message: verdict.mode === "dontAsk"
|
|
379
473
|
? `refused by the dontAsk permission mode: this call needed approval (${verdict.askClass}) and the mode answers no ask; run under a mode with an approver, or change the call`
|
|
380
474
|
: `refused by the bypassPermissions permission mode: the write-protection judge could not resolve this write's target, and with nobody to ask the mode refuses rather than releases it`,
|
|
381
475
|
decisionReason: "mode",
|
|
382
|
-
};
|
|
476
|
+
}, finalArgs);
|
|
383
477
|
}
|
|
384
478
|
}
|
|
385
|
-
const safety =
|
|
386
|
-
egress: input.egress,
|
|
387
|
-
shellGated: input.shellGated,
|
|
388
|
-
irreversibility: input.irreversibility,
|
|
389
|
-
probeMandated: pass.decision.action === "ask" && pass.decision.probeMandated === true,
|
|
390
|
-
probeUnanswered: pass.probeUnanswered === true,
|
|
391
|
-
tightened: pass.tightenedBy,
|
|
392
|
-
});
|
|
393
|
-
const realApprovalOf = (d) => {
|
|
394
|
-
if (d.action !== "ask" || d.requiresRealApproval !== true)
|
|
395
|
-
return undefined;
|
|
396
|
-
if (d.origin === undefined)
|
|
397
|
-
throw new Error(`a real-approval ask for "${toolName}" reached a park site with no origin word — the origin stamp precedes every park`);
|
|
398
|
-
return { origin: d.origin, ...(originFacts.org !== undefined ? { org: originFacts.org } : {}) };
|
|
399
|
-
};
|
|
400
|
-
const carryOf = (d) => ({
|
|
401
|
-
...(callSignal !== undefined ? { signal: callSignal } : {}),
|
|
402
|
-
...(d.action === "ask" && d.denialLimitFallback !== undefined ? { denialLimitFallback: unarmedWindow(d.denialLimitFallback) } : {}),
|
|
403
|
-
...(d.action === "ask" && d.classifierNoRuling !== undefined ? { classifierNoRuling: d.classifierNoRuling } : {}),
|
|
404
|
-
...(d.action === "ask" && d.origin !== undefined ? { origin: d.origin } : {}),
|
|
405
|
-
...(d.action === "ask" && d.askClass !== undefined && d.classes !== undefined ? { askClass: d.askClass, classes: d.classes } : {}),
|
|
406
|
-
...(d.action === "ask" && d.mandated === true ? { mandated: true, ...(d.mandate !== undefined ? { mandate: d.mandate } : {}) } : {}),
|
|
407
|
-
...(d.action === "ask" && d.authoredBy === "deployment" ? { authoredBy: "deployment" } : {}),
|
|
408
|
-
});
|
|
479
|
+
const safety = safetyOf(pass.decision);
|
|
409
480
|
if (suspendAsk && pass.decision.action === "ask") {
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
if ("parkFailed" in suspended)
|
|
414
|
-
pass.parkFailed = suspended.parkFailed;
|
|
415
|
-
else
|
|
416
|
-
return { suspend: suspended, preToolContext: pass.preToolContext };
|
|
417
|
-
}
|
|
481
|
+
const parked = await parkAsk(pass.decision, pass.req, pass.currentInput, safety, undefined, originFacts.org);
|
|
482
|
+
if (parked)
|
|
483
|
+
return parked;
|
|
418
484
|
}
|
|
419
485
|
if (pass.decision.action === "ask" && wireOf("lanes.contentAskRoute", pass.req) === ASK_USER_QUESTION_TOOL_NAME) {
|
|
420
486
|
const outcome = input.resolveContentAsk !== undefined ? await (callSignal !== undefined ? input.resolveContentAsk(pass.req, callSignal) : input.resolveContentAsk(pass.req)) : { kind: "unavailable", parkDeclined: false };
|
|
421
487
|
if (outcome.kind === "answered") {
|
|
422
|
-
pass.decision = { action: "allow"
|
|
488
|
+
pass.decision = { action: "allow" };
|
|
423
489
|
}
|
|
424
490
|
else if (outcome.kind === "unavailable") {
|
|
425
|
-
if (outcome.presentedInput !== undefined) {
|
|
426
|
-
pass.currentInput = outcome.presentedInput;
|
|
427
|
-
pass.req.args = outcome.presentedInput;
|
|
428
|
-
}
|
|
429
491
|
if (suspendAsk && outcome.parkDeclined && pass.parkFailed === undefined) {
|
|
430
|
-
const
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
if ("parkFailed" in suspended)
|
|
434
|
-
pass.parkFailed = suspended.parkFailed;
|
|
435
|
-
else
|
|
436
|
-
return { suspend: suspended, preToolContext: pass.preToolContext };
|
|
437
|
-
}
|
|
492
|
+
const parked = await parkAsk(pass.decision, pass.req, pass.currentInput, safety, true, originFacts.org);
|
|
493
|
+
if (parked)
|
|
494
|
+
return parked;
|
|
438
495
|
}
|
|
439
496
|
if (pass.decision.origin === undefined)
|
|
440
497
|
throw new Error(`the content ask for "${toolName}" reached its refusal without an origin word`);
|
|
441
498
|
ledger.set({ settlement: { kind: input.resolveContentAsk !== undefined ? "approver_unavailable" : "no_approver", who: { party: "none" }, when: Date.now() }, origin: pass.decision.origin });
|
|
442
499
|
pass.deniedBy = "ask_resolution";
|
|
443
|
-
pass.decision = {
|
|
500
|
+
pass.decision = refusalOf({
|
|
444
501
|
action: "deny",
|
|
445
502
|
message: "AskUserQuestion could not be parked for a durable human answer on this path (no checkpoint " +
|
|
446
503
|
"facility, or the suspend failed) and a synchronous permission approver cannot carry an answer — " +
|
|
447
504
|
"the question was NOT shown to anyone. Proceed with your best judgment and state the assumption " +
|
|
448
505
|
"you made.",
|
|
449
|
-
};
|
|
506
|
+
}, finalArgs);
|
|
450
507
|
}
|
|
451
508
|
else {
|
|
452
|
-
|
|
453
|
-
pass.decision = { action: "allow", updatedInput: outcome.presentedInput };
|
|
454
|
-
else
|
|
455
|
-
pass.decision = { action: "allow" };
|
|
509
|
+
pass.decision = { action: "allow" };
|
|
456
510
|
}
|
|
457
511
|
}
|
|
458
512
|
if (pass.decision.action === "ask") {
|
|
@@ -467,16 +521,11 @@ export async function runGateLanes(pass) {
|
|
|
467
521
|
resolved = ledger.fromResolved(resolved, askBeforeResolve, pass.req);
|
|
468
522
|
if (resolved.action === "deny")
|
|
469
523
|
pass.deniedBy = "ask_resolution";
|
|
470
|
-
pass.decision = resolved;
|
|
524
|
+
pass.decision = resolved.action === "deny" ? refusalOf(resolved, finalArgs) : resolved;
|
|
471
525
|
if (resolved.action === "deny" && resolved.approverUnavailable === true && suspendAsk && pass.parkFailed === undefined) {
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
if ("parkFailed" in suspended)
|
|
476
|
-
pass.parkFailed = suspended.parkFailed;
|
|
477
|
-
else
|
|
478
|
-
return { suspend: suspended, preToolContext: pass.preToolContext };
|
|
479
|
-
}
|
|
526
|
+
const parked = await parkAsk(askBeforeResolve, pass.req, pass.currentInput, safety, true, originFacts.org);
|
|
527
|
+
if (parked)
|
|
528
|
+
return parked;
|
|
480
529
|
}
|
|
481
530
|
if (askBeforeResolve.action === "ask" && askBeforeResolve.denialLimitFallback !== undefined) {
|
|
482
531
|
if (pass.decision.action === "allow") {
|
|
@@ -493,211 +542,248 @@ export async function runGateLanes(pass) {
|
|
|
493
542
|
}
|
|
494
543
|
}
|
|
495
544
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
break;
|
|
537
|
-
}
|
|
538
|
-
if (hr.action === "ask") {
|
|
539
|
-
editDenied = {
|
|
540
|
-
action: "deny",
|
|
541
|
-
message: `the approved edit for "${toolName}" raises a new PreToolUse approval requirement the original approval does not cover — denied fail-closed; re-submit the edited action directly`,
|
|
542
|
-
};
|
|
543
|
-
pass.deniedBy = "hook";
|
|
544
|
-
break;
|
|
545
|
-
}
|
|
546
|
-
if (hr.updatedInput !== undefined) {
|
|
547
|
-
editArgs = hr.updatedInput;
|
|
548
|
-
editRewrittenSinceHuman = true;
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
let recheck = { action: "allow" };
|
|
553
|
-
if (adjudicate) {
|
|
554
|
-
try {
|
|
555
|
-
const editReq = { toolName, args: editArgs, toolCallId, ...(pass.req.face !== undefined ? { face: pass.req.face } : {}) };
|
|
556
|
-
recheck = refuseOutOfContractDecision(await (callSignal !== undefined ? adjudicate(editReq, callSignal) : adjudicate(editReq)));
|
|
557
|
-
}
|
|
558
|
-
catch (err) {
|
|
559
|
-
reportPolicyThrow((e) => traceHookCrash(input, e, notifier), "the tool policy's re-check of the approved edit", { toolName, toolCallId }, err, callSignal ?? input.abortSignal);
|
|
560
|
-
recheck = {
|
|
561
|
-
action: "deny",
|
|
562
|
-
message: `policy re-check of the approved edit for "${toolName}" errored: ${policyThrowLine(err)}`,
|
|
563
|
-
};
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
{
|
|
567
|
-
const attributed = ledger.classifierRoundOf(recheck);
|
|
568
|
-
if (attributed !== undefined)
|
|
569
|
-
pass.classifierRound = attributed;
|
|
570
|
-
const read = ledger.fromDecision(recheck);
|
|
571
|
-
recheck = read.decision;
|
|
572
|
-
if (recheck.action === "deny" && read.deniedBy !== undefined) {
|
|
573
|
-
editDenied = recheck;
|
|
574
|
-
pass.deniedBy = read.deniedBy;
|
|
575
|
-
pass.denyCause = ledger.causeOf(recheck);
|
|
576
|
-
break;
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
if (recheck.updatedInput !== undefined) {
|
|
580
|
-
editArgs = recheck.updatedInput;
|
|
581
|
-
editRewrittenSinceHuman = true;
|
|
582
|
-
}
|
|
583
|
-
const editOrg = await applyOrgLayer(recheck, editArgs);
|
|
584
|
-
recheck = editOrg.decision;
|
|
585
|
-
if (recheck.action === "deny") {
|
|
586
|
-
editDenied = recheck;
|
|
587
|
-
break;
|
|
588
|
-
}
|
|
589
|
-
let editLane;
|
|
590
|
-
const editReread = withArgsReading(pass.req, editArgs, callSignal ?? input.abortSignal);
|
|
591
|
-
const editLaneReq = editReread !== undefined ? await editReread : { toolName, args: editArgs, toolCallId, ...(pass.req.face !== undefined ? { face: pass.req.face } : {}) };
|
|
592
|
-
if (input.persistedRules !== undefined && wireOf("lanes.persistedEditSkip", pass.req) !== ASK_USER_QUESTION_TOOL_NAME) {
|
|
593
|
-
editLane = await readPersistedRules(editLaneReq);
|
|
594
|
-
const editTightened = applyPersistedTightening(recheck, editLane, editLaneReq);
|
|
595
|
-
recheck = editTightened.decision;
|
|
596
|
-
if (editTightened.tightened === "deny")
|
|
597
|
-
pass.deniedBy = "persisted_rule";
|
|
598
|
-
if (recheck.action === "deny") {
|
|
599
|
-
editDenied = recheck;
|
|
600
|
-
break;
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
const editSkillRefusal = skillRowRefusal(input.skillGrants, editLaneReq);
|
|
604
|
-
if (editSkillRefusal !== undefined) {
|
|
605
|
-
editDenied = editSkillRefusal;
|
|
606
|
-
pass.deniedBy = "policy";
|
|
545
|
+
approvedWithArgs = pass.decision.action === "allow" && pass.decision.updatedInput !== undefined;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
if (approvedWithArgs && pass.decision.action === "allow" && pass.decision.updatedInput !== undefined) {
|
|
549
|
+
let editArgs = pass.decision.updatedInput;
|
|
550
|
+
let editDenied;
|
|
551
|
+
let editRewrittenSinceHuman = false;
|
|
552
|
+
let unanswered;
|
|
553
|
+
const refusedAtResolution = (d) => { editDenied = d; pass.deniedBy = "ask_resolution"; };
|
|
554
|
+
for (let round = 0;; round++) {
|
|
555
|
+
const taken = ownArgs(editArgs);
|
|
556
|
+
if (!taken.ok) {
|
|
557
|
+
editDenied = { action: "deny", message: unownedArgsMessage(`the approved edit for "${toolName}"`, taken.reason) };
|
|
558
|
+
pass.deniedBy = "policy";
|
|
559
|
+
break;
|
|
560
|
+
}
|
|
561
|
+
editArgs = taken.value;
|
|
562
|
+
if (round >= 3) {
|
|
563
|
+
editDenied = {
|
|
564
|
+
action: "deny",
|
|
565
|
+
message: `the approval-edit chain for "${toolName}" exceeded the re-approval cap — denied fail-closed; re-submit the edited action directly`,
|
|
566
|
+
};
|
|
567
|
+
pass.deniedBy = "policy";
|
|
568
|
+
break;
|
|
569
|
+
}
|
|
570
|
+
let editHookAsk;
|
|
571
|
+
if (screening !== undefined) {
|
|
572
|
+
const screened = await screening.screen(editArgs, `the approved edit for "${toolName}"`);
|
|
573
|
+
if (screened.kind === "refused") {
|
|
574
|
+
editDenied = { action: "deny", message: screened.reason };
|
|
575
|
+
pass.deniedBy = "hook";
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
578
|
+
const hr = screened.answer;
|
|
579
|
+
if (hr) {
|
|
580
|
+
if (hr.additionalContext)
|
|
581
|
+
pass.preToolContext.push(hr.additionalContext);
|
|
582
|
+
if (hr.action === "deny") {
|
|
583
|
+
editDenied = { action: "deny", message: decisionText(hr) ?? `the approved edit for "${toolName}" was blocked by a PreToolUse hook` };
|
|
584
|
+
pass.deniedBy = "hook";
|
|
607
585
|
break;
|
|
608
586
|
}
|
|
609
|
-
if (
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
editRewrittenSinceHuman = true;
|
|
613
|
-
}
|
|
614
|
-
if (!editRewrittenSinceHuman || !asksUnstated(recheck, permissionSeatAt(input, editArgs)?.seat, input.permissionMode?.()))
|
|
615
|
-
break;
|
|
616
|
-
recheck = { action: "ask", message: permissionSeatAt(input, editArgs)?.question ?? unstatedAskMessage(toolName) };
|
|
617
|
-
pass.tightenedBy = "unstated";
|
|
587
|
+
if (hr.action === "ask") {
|
|
588
|
+
const { updatedInput: _adopted, ...ask } = hr;
|
|
589
|
+
editHookAsk = ask;
|
|
618
590
|
}
|
|
619
|
-
if (
|
|
620
|
-
editArgs =
|
|
591
|
+
if (hr.updatedInput !== undefined) {
|
|
592
|
+
editArgs = hr.updatedInput;
|
|
621
593
|
editRewrittenSinceHuman = true;
|
|
622
594
|
}
|
|
623
|
-
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
let recheck = { action: "allow" };
|
|
598
|
+
if (adjudicate) {
|
|
599
|
+
try {
|
|
600
|
+
const editReq = Object.freeze({ toolName, args: editArgs, toolCallId, ...(pass.req.face !== undefined ? { face: pass.req.face } : {}) });
|
|
601
|
+
recheck = refuseOutOfContractDecision(await (callSignal !== undefined ? adjudicate(editReq, callSignal) : adjudicate(editReq)));
|
|
602
|
+
}
|
|
603
|
+
catch (err) {
|
|
604
|
+
reportPolicyThrow((e) => traceHookCrash(input, e, notifier), "the tool policy's re-check of the approved edit", { toolName, toolCallId }, err, callSignal ?? input.abortSignal);
|
|
605
|
+
recheck = {
|
|
606
|
+
action: "deny",
|
|
607
|
+
message: `policy re-check of the approved edit for "${toolName}" errored: ${policyThrowLine(err)}`,
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
{
|
|
612
|
+
const attributed = ledger.classifierRoundOf(recheck);
|
|
613
|
+
if (attributed !== undefined)
|
|
614
|
+
pass.classifierRound = attributed;
|
|
615
|
+
const read = ledger.fromDecision(recheck);
|
|
616
|
+
recheck = read.decision;
|
|
617
|
+
if (recheck.action === "deny" && read.deniedBy !== undefined) {
|
|
618
|
+
editDenied = recheck;
|
|
619
|
+
pass.deniedBy = read.deniedBy;
|
|
620
|
+
pass.denyCause = ledger.causeOf(recheck);
|
|
621
|
+
break;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
if (recheck.updatedInput !== undefined) {
|
|
625
|
+
editArgs = recheck.updatedInput;
|
|
626
|
+
editRewrittenSinceHuman = true;
|
|
627
|
+
}
|
|
628
|
+
const editOrg = await applyOrgLayer(recheck, editArgs);
|
|
629
|
+
recheck = editOrg.decision;
|
|
630
|
+
if (recheck.action === "deny") {
|
|
631
|
+
editDenied = recheck;
|
|
632
|
+
break;
|
|
633
|
+
}
|
|
634
|
+
let editLane;
|
|
635
|
+
const editReread = withArgsReading(pass.req, editArgs, callSignal ?? input.abortSignal);
|
|
636
|
+
const editLaneReq = Object.freeze(editReread !== undefined ? await editReread : { toolName, args: editArgs, toolCallId, ...(pass.req.face !== undefined ? { face: pass.req.face } : {}) });
|
|
637
|
+
if (input.persistedRules !== undefined && wireOf("lanes.persistedEditSkip", pass.req) !== ASK_USER_QUESTION_TOOL_NAME) {
|
|
638
|
+
editLane = await readPersistedRules(editLaneReq);
|
|
639
|
+
const editTightened = applyPersistedTightening(recheck, editLane, editLaneReq);
|
|
640
|
+
recheck = editTightened.decision;
|
|
641
|
+
if (editTightened.tightened === "deny")
|
|
642
|
+
pass.deniedBy = "persisted_rule";
|
|
643
|
+
if (recheck.action === "deny") {
|
|
644
|
+
editDenied = recheck;
|
|
645
|
+
break;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
const editSkillRefusal = skillRowRefusal(input.skillGrants, editLaneReq);
|
|
649
|
+
if (editSkillRefusal !== undefined) {
|
|
650
|
+
editDenied = editSkillRefusal;
|
|
651
|
+
pass.deniedBy = "policy";
|
|
652
|
+
break;
|
|
653
|
+
}
|
|
654
|
+
if (recheck.action === "allow") {
|
|
655
|
+
if (recheck.updatedInput !== undefined) {
|
|
656
|
+
editArgs = recheck.updatedInput;
|
|
657
|
+
editRewrittenSinceHuman = true;
|
|
658
|
+
}
|
|
659
|
+
if (editRewrittenSinceHuman && asksUnstated(recheck, permissionSeatAt(input, editArgs)?.seat, input.permissionMode?.())) {
|
|
660
|
+
recheck = { action: "ask", message: permissionSeatAt(input, editArgs)?.question ?? unstatedAskMessage(toolName) };
|
|
661
|
+
pass.tightenedBy = "unstated";
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
if (recheck.updatedInput !== undefined) {
|
|
665
|
+
editArgs = recheck.updatedInput;
|
|
666
|
+
editRewrittenSinceHuman = true;
|
|
667
|
+
}
|
|
668
|
+
let editFacts;
|
|
669
|
+
const stampEditAsk = (ask) => {
|
|
670
|
+
const editAskSnapshot = { ...ask, ruleEvidence: mintRuleEvidence({ dotsAbsent: "not_adjudicated" }) };
|
|
671
|
+
if (editFacts === undefined) {
|
|
624
672
|
markedThisRound = undefined;
|
|
625
|
-
|
|
626
|
-
const editAskDecision = stampAskOrigin(editAskSnapshot, editFacts, classifyStanding(editAskSnapshot, editFacts));
|
|
627
|
-
if (input.permissionMode !== undefined && pass.askClassification !== undefined) {
|
|
628
|
-
const editVerdict = arbitrateByMode(input.permissionMode(), pass.askClassification, { ...(editAskDecision.origin !== undefined ? { origin: editAskDecision.origin } : {}), ...(editAskDecision.mandate !== undefined ? { mandate: editAskDecision.mandate } : {}) });
|
|
629
|
-
if (editVerdict.kind === "released") {
|
|
630
|
-
ledger.supersede();
|
|
631
|
-
pass.arbitration = editVerdict;
|
|
632
|
-
await notifier.notifyAsync(() => input.onModeReleased?.({ toolName, toolCallId, release: { mode: editVerdict.mode, askClass: editVerdict.askClass, classes: editVerdict.classes, ...(editVerdict.origin !== undefined ? { origin: editVerdict.origin } : {}), ...(editVerdict.mandate !== undefined ? { mandate: editVerdict.mandate } : {}), ...(editVerdict.reason !== undefined ? { reason: editVerdict.reason } : {}) }, ...(pass.shellReadUnestablished === true ? { readUnestablished: true } : {}) }), "toolGate.onModeReleased");
|
|
633
|
-
break;
|
|
634
|
-
}
|
|
635
|
-
if (editVerdict.kind === "denied_by_mode") {
|
|
636
|
-
ledger.supersede();
|
|
637
|
-
pass.arbitration = editVerdict;
|
|
638
|
-
editDenied = { action: "deny", message: `the approved edit for "${toolName}" raised a new approval requirement that the ${editVerdict.mode} permission mode refuses`, decisionReason: "mode" };
|
|
639
|
-
pass.deniedBy = "mode";
|
|
640
|
-
break;
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
const editAskReq = { toolName, args: editArgs, toolCallId, ...(pass.req.face !== undefined ? { face: pass.req.face } : {}) };
|
|
644
|
-
const rr = ledger.fromResolved(await (callSignal !== undefined ? resolveAsk(editAskDecision, editAskReq, callSignal) : resolveAsk(editAskDecision, editAskReq)), editAskDecision, editAskReq);
|
|
645
|
-
if (rr.action !== "allow") {
|
|
646
|
-
editDenied = rr;
|
|
647
|
-
pass.deniedBy = "ask_resolution";
|
|
648
|
-
break;
|
|
649
|
-
}
|
|
650
|
-
if (rr.updatedInput === undefined) {
|
|
651
|
-
if (rr.presentedInput !== undefined)
|
|
652
|
-
editArgs = rr.presentedInput;
|
|
653
|
-
editRewrittenSinceHuman = false;
|
|
654
|
-
break;
|
|
655
|
-
}
|
|
656
|
-
editArgs = rr.updatedInput;
|
|
657
|
-
editRewrittenSinceHuman = false;
|
|
673
|
+
editFacts = askOriginFacts(editOrg.org, editLane);
|
|
658
674
|
}
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
675
|
+
return stampAskOrigin(editAskSnapshot, editFacts, classifyStanding(editAskSnapshot, editFacts));
|
|
676
|
+
};
|
|
677
|
+
if (editHookAsk !== undefined)
|
|
678
|
+
recheck = foldHookAsk(recheck, editHookAsk);
|
|
679
|
+
let editDecision = recheck.action === "ask" ? stampEditAsk(recheck) : recheck;
|
|
680
|
+
if (carriedOwnAsk !== undefined) {
|
|
681
|
+
const { updatedInput: _theOriginalBytes, ...carried } = carriedOwnAsk;
|
|
682
|
+
const rra = carried.requiresRealApproval === true ? { requiresRealApproval: true } : {};
|
|
683
|
+
editDecision = stampEditAsk(editDecision.action === "ask" ? { ...editDecision, foldedAskClasses: [...(editDecision.foldedAskClasses ?? []), ...decisionAskClassesOf(carried), ...(carried.classes ?? [])], ...rra } : carried);
|
|
684
|
+
carriedOwnAsk = undefined;
|
|
685
|
+
}
|
|
686
|
+
const editRead = await checkTool(editDecision, editArgs, editOrg.org, undefined);
|
|
687
|
+
if (editRead?.kind === "denied") {
|
|
688
|
+
refuseByExtension(editRead.deny);
|
|
689
|
+
editDenied = editRead.deny;
|
|
690
|
+
break;
|
|
691
|
+
}
|
|
692
|
+
if (editRead?.kind === "approved") {
|
|
693
|
+
carriedOwnAsk = editRead.outstanding ?? (editDecision.action === "ask" ? editDecision : undefined);
|
|
694
|
+
editArgs = editRead.allow.updatedInput;
|
|
695
|
+
editRewrittenSinceHuman = false;
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
if (editRead?.kind === "asked" && editRead.marked === true)
|
|
699
|
+
editFacts = undefined;
|
|
700
|
+
if (editRead?.kind === "asked")
|
|
701
|
+
editDecision = stampEditAsk(editRead.ask);
|
|
702
|
+
else if (editRead?.kind === "shadowed" && editDecision.action === "ask")
|
|
703
|
+
editDecision = { ...editDecision, allowRuleShadowed: [...(editDecision.allowRuleShadowed ?? []), ...editRead.shadows] };
|
|
704
|
+
if (editDecision.action !== "ask")
|
|
705
|
+
break;
|
|
706
|
+
const editAskDecision = editDecision;
|
|
707
|
+
if (input.permissionMode !== undefined && pass.askClassification !== undefined) {
|
|
708
|
+
const editVerdict = arbitrateByMode(input.permissionMode(), pass.askClassification, { ...(editAskDecision.origin !== undefined ? { origin: editAskDecision.origin } : {}), ...(editAskDecision.mandate !== undefined ? { mandate: editAskDecision.mandate } : {}) });
|
|
709
|
+
if (editVerdict.kind === "released") {
|
|
710
|
+
ledger.supersede();
|
|
711
|
+
pass.arbitration = editVerdict;
|
|
712
|
+
await notifier.notifyAsync(() => input.onModeReleased?.({ toolName, toolCallId, release: { mode: editVerdict.mode, askClass: editVerdict.askClass, classes: editVerdict.classes, ...(editVerdict.origin !== undefined ? { origin: editVerdict.origin } : {}), ...(editVerdict.mandate !== undefined ? { mandate: editVerdict.mandate } : {}), ...(editVerdict.reason !== undefined ? { reason: editVerdict.reason } : {}) }, ...(pass.shellReadUnestablished === true ? { readUnestablished: true } : {}) }), "toolGate.onModeReleased");
|
|
713
|
+
break;
|
|
671
714
|
}
|
|
672
|
-
if (
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
verdict = await withGateTimeout(judged, boundedAwaitDeadlineMs(), callSignal ?? input.abortSignal, "shellReadStation");
|
|
679
|
-
}
|
|
680
|
-
catch {
|
|
681
|
-
verdict = station.unanswered(pass.req, "the read station could not answer");
|
|
682
|
-
}
|
|
683
|
-
const reading = readStationAnswer(verdict, { toolName, toolCallId, report: (e) => traceHookCrash(input, e, notifier) });
|
|
684
|
-
if (reading.kind !== "vouch") {
|
|
685
|
-
editDenied = {
|
|
686
|
-
action: "deny",
|
|
687
|
-
message: reading.verdict.sentence ?? `the approved edit for "${toolName}" reads where the read boundary does not vouch — denied fail-closed; re-submit the command as a fresh call and answer its card`,
|
|
688
|
-
};
|
|
689
|
-
pass.deniedBy = "read_boundary";
|
|
690
|
-
if (reading.verdict.details !== undefined)
|
|
691
|
-
pass.denyDetails = reading.verdict.details;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
715
|
+
if (editVerdict.kind === "denied_by_mode") {
|
|
716
|
+
ledger.supersede();
|
|
717
|
+
pass.arbitration = editVerdict;
|
|
718
|
+
editDenied = { action: "deny", message: `the approved edit for "${toolName}" raised a new approval requirement that the ${editVerdict.mode} permission mode refuses`, decisionReason: "mode" };
|
|
719
|
+
pass.deniedBy = "mode";
|
|
720
|
+
break;
|
|
694
721
|
}
|
|
695
|
-
pass.decision = editDenied ?? { ...pass.decision, updatedInput: editArgs };
|
|
696
722
|
}
|
|
697
|
-
|
|
698
|
-
|
|
723
|
+
const editAskReq = Object.freeze({ toolName, args: editArgs, toolCallId, ...(pass.req.face !== undefined ? { face: pass.req.face } : {}) });
|
|
724
|
+
if (suspendAsk !== undefined && markedUnresolvable()) {
|
|
725
|
+
unanswered = { ask: editAskDecision, req: editAskReq, org: editOrg.org };
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
const rr = ledger.fromResolved(await (callSignal !== undefined ? resolveAsk(editAskDecision, editAskReq, callSignal) : resolveAsk(editAskDecision, editAskReq)), editAskDecision, editAskReq);
|
|
729
|
+
if (rr.action !== "allow") {
|
|
730
|
+
refusedAtResolution(rr);
|
|
731
|
+
if (rr.approverUnavailable === true)
|
|
732
|
+
unanswered = { ask: editAskDecision, req: editAskReq, org: editOrg.org, deny: rr };
|
|
733
|
+
break;
|
|
699
734
|
}
|
|
735
|
+
if (rr.updatedInput === undefined) {
|
|
736
|
+
editRewrittenSinceHuman = false;
|
|
737
|
+
break;
|
|
738
|
+
}
|
|
739
|
+
editArgs = rr.updatedInput;
|
|
740
|
+
editRewrittenSinceHuman = false;
|
|
741
|
+
}
|
|
742
|
+
const rejudged = () => editDenied === undefined || editDenied === unanswered?.deny;
|
|
743
|
+
if (rejudged() && editRewrittenSinceHuman && input.writeProtectionCheck !== undefined) {
|
|
744
|
+
const check = input.writeProtectionCheck;
|
|
745
|
+
const verdict = await awaitWriteProtectionJudgment((deadline) => check(toolName, editArgs, pass.req.face, input.trackedCwd?.(), deadline), boundedAwaitDeadlineMs, callSignal ?? input.abortSignal);
|
|
746
|
+
if (verdict !== undefined && verdict.kind !== "clear") {
|
|
747
|
+
editDenied = {
|
|
748
|
+
action: "deny",
|
|
749
|
+
message: verdict.kind === "hit"
|
|
750
|
+
? `the approved edit for "${toolName}" was rewritten by the restriction chain onto a write-protected path (table entry "${verdict.hit.name}") that no approval covers — denied fail-closed; re-submit the edited action directly`
|
|
751
|
+
: `the approved edit for "${toolName}" was rewritten by the restriction chain onto a target whose destination could not be determined (target_unresolved: ${verdict.cause}) — denied fail-closed; re-submit the edited action directly`,
|
|
752
|
+
};
|
|
753
|
+
pass.deniedBy = "write_protection";
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
if (rejudged() && input.shellReadCheck !== undefined) {
|
|
757
|
+
const station = input.shellReadCheck;
|
|
758
|
+
const judged = station.judge(pass.req, editArgs, input.trackedCwd?.(), callSignal ?? input.abortSignal, { seat: "rejudge", toolCallId });
|
|
759
|
+
if (judged !== null) {
|
|
760
|
+
let verdict;
|
|
761
|
+
try {
|
|
762
|
+
verdict = await withGateTimeout(judged, boundedAwaitDeadlineMs(), callSignal ?? input.abortSignal, "shellReadStation");
|
|
763
|
+
}
|
|
764
|
+
catch {
|
|
765
|
+
verdict = station.unanswered(pass.req, "the read station could not answer");
|
|
766
|
+
}
|
|
767
|
+
const reading = readStationAnswer(verdict, { toolName, toolCallId, report: (e) => traceHookCrash(input, e, notifier) });
|
|
768
|
+
if (reading.kind !== "vouch") {
|
|
769
|
+
editDenied = {
|
|
770
|
+
action: "deny",
|
|
771
|
+
message: reading.verdict.sentence ?? `the approved edit for "${toolName}" reads where the read boundary does not vouch — denied fail-closed; re-submit the command as a fresh call and answer its card`,
|
|
772
|
+
};
|
|
773
|
+
pass.deniedBy = "read_boundary";
|
|
774
|
+
if (reading.verdict.details !== undefined)
|
|
775
|
+
pass.denyDetails = reading.verdict.details;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
if (unanswered !== undefined && editDenied === unanswered.deny && pass.parkFailed === undefined) {
|
|
780
|
+
const parked = await parkAsk(unanswered.ask, unanswered.req, editArgs, safetyOf(unanswered.ask), unanswered.deny !== undefined || undefined, unanswered.org);
|
|
781
|
+
if (parked)
|
|
782
|
+
return parked;
|
|
700
783
|
}
|
|
784
|
+
if (unanswered !== undefined && unanswered.deny === undefined && editDenied === undefined)
|
|
785
|
+
refusedAtResolution(ledger.fromResolved(await (callSignal !== undefined ? resolveAsk(unanswered.ask, unanswered.req, callSignal) : resolveAsk(unanswered.ask, unanswered.req)), unanswered.ask, unanswered.req));
|
|
786
|
+
pass.decision = editDenied !== undefined ? refusalOf(editDenied, editArgs) : { ...pass.decision, updatedInput: editArgs };
|
|
701
787
|
}
|
|
702
788
|
return await exitGate(pass);
|
|
703
789
|
}
|