@sema-agent/core 7.52.0 → 7.54.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 +470 -0
- package/LICENSE +3 -1
- package/README.md +3 -1
- package/dist/agents/cross-session-envelope.d.ts +8 -0
- package/dist/agents/cross-session-envelope.js +6 -0
- package/dist/agents/cross-session-judge.d.ts +21 -1
- package/dist/agents/cross-session-judge.js +8 -0
- package/dist/agents/cross-session-ref.d.ts +5 -0
- package/dist/agents/cross-session-ref.js +1 -0
- package/dist/agents/org-delivery-gate.d.ts +122 -0
- package/dist/agents/org-delivery-gate.js +69 -0
- package/dist/agents/peer-held-queue.d.ts +9 -4
- package/dist/agents/peer-held-queue.js +6 -5
- package/dist/agents/peer-session-drain.d.ts +35 -6
- package/dist/agents/peer-session-drain.js +271 -182
- package/dist/agents/read-inbox-tool.d.ts +7 -0
- package/dist/agents/read-inbox-tool.js +5 -1
- package/dist/agents/send-message-tool.js +3 -4
- package/dist/agents/subagent.d.ts +6 -5
- package/dist/agents/subagent.js +117 -83
- package/dist/agents/tool-filter.d.ts +25 -4
- package/dist/agents/tool-filter.js +13 -3
- package/dist/brain/anthropic.d.ts +6 -1
- package/dist/brain/anthropic.js +4 -4
- package/dist/brain/model-presets.js +2 -1
- package/dist/brain/route-adjudicator.d.ts +6 -0
- package/dist/brain/routing.d.ts +24 -1
- package/dist/brain/routing.js +54 -19
- package/dist/brain/timeout.js +5 -4
- package/dist/core/a2a.d.ts +5 -2
- package/dist/core/a2a.js +33 -14
- package/dist/core/allow-entry.d.ts +3 -1
- package/dist/core/allow-entry.js +3 -2
- package/dist/core/approval-object.d.ts +87 -0
- package/dist/core/approval-object.js +85 -0
- package/dist/core/arg-summary.d.ts +3 -2
- package/dist/core/arg-summary.js +17 -11
- package/dist/core/ask-origin.d.ts +43 -27
- package/dist/core/ask-origin.js +20 -11
- package/dist/core/ask-question.d.ts +0 -1
- package/dist/core/ask-question.js +4 -67
- package/dist/core/ask-unresolvable-notice.d.ts +3 -2
- package/dist/core/auto-compaction.d.ts +106 -50
- package/dist/core/auto-compaction.js +69 -53
- package/dist/core/auto-mode-prompt.d.ts +4 -2
- package/dist/core/auto-mode-prompt.js +4 -3
- package/dist/core/canonical-json.d.ts +69 -0
- package/dist/core/canonical-json.js +130 -8
- package/dist/core/checkpoint-requirements.d.ts +13 -7
- package/dist/core/checkpoint-requirements.js +4 -1
- package/dist/core/checkpoint-store.d.ts +60 -36
- package/dist/core/checkpoint-store.js +7 -6
- package/dist/core/child-clamp-seats.d.ts +45 -6
- package/dist/core/child-clamp-seats.js +56 -4
- package/dist/core/compliance.js +3 -1
- package/dist/core/consolidate-scope.d.ts +1 -1
- package/dist/core/cross-boundary-taint.d.ts +213 -0
- package/dist/core/cross-boundary-taint.js +196 -0
- package/dist/core/decision-receipt.d.ts +44 -1
- package/dist/core/decision-receipt.js +16 -0
- package/dist/core/effective-path-target.d.ts +28 -6
- package/dist/core/effective-path-target.js +28 -2
- package/dist/core/engine-notice.d.ts +47 -4
- package/dist/core/engine-notice.js +17 -1
- package/dist/core/engine-storage-backend.d.ts +73 -0
- package/dist/core/engine-storage-backend.js +1 -0
- package/dist/core/file-history-store.d.ts +6 -2
- package/dist/core/file-history-store.js +1 -0
- package/dist/core/gate-fold.js +13 -4
- package/dist/core/gate-lanes.js +41 -34
- package/dist/core/gate-outcome.d.ts +18 -9
- package/dist/core/governance-codes.d.ts +9 -2
- package/dist/core/governance-codes.js +9 -0
- package/dist/core/hands-band-screen.d.ts +7 -0
- package/dist/core/hands-band-screen.js +32 -0
- package/dist/core/hooks.d.ts +21 -19
- package/dist/core/hooks.js +6 -5
- package/dist/core/locked-config.d.ts +110 -31
- package/dist/core/locked-config.js +155 -42
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/mcp-probe.js +1 -1
- package/dist/core/mcp-server-spec.d.ts +152 -17
- package/dist/core/mcp-server-spec.js +223 -40
- package/dist/core/mcp.d.ts +21 -14
- package/dist/core/mcp.js +59 -54
- package/dist/core/memory-engine/engine.d.ts +14 -19
- package/dist/core/memory-engine/engine.js +9 -6
- package/dist/core/memory-engine/export-bundle.d.ts +1 -1
- package/dist/core/memory-engine/export-bundle.js +1 -1
- package/dist/core/memory-engine/file-backend.d.ts +2 -6
- package/dist/core/memory-engine/file-backend.js +1 -12
- package/dist/core/memory.d.ts +3 -3
- package/dist/core/mode-policy.d.ts +16 -26
- package/dist/core/mode-policy.js +5 -18
- package/dist/core/mods/kernel/dispatch.js +13 -15
- package/dist/core/mods/kernel/events.d.ts +9 -6
- package/dist/core/mods/kernel/events.js +2 -2
- package/dist/core/mods/kernel/receive.d.ts +41 -11
- package/dist/core/mods/kernel/receive.js +124 -54
- package/dist/core/mods/kernel/site-rules.d.ts +80 -15
- package/dist/core/mods/kernel/site-rules.js +232 -40
- package/dist/core/mods/stations.d.ts +0 -6
- package/dist/core/mods/stations.js +0 -7
- package/dist/core/mounted-mcp.d.ts +57 -0
- package/dist/core/mounted-mcp.js +71 -2
- package/dist/core/own-property-receipt.d.ts +13 -0
- package/dist/core/own-property-receipt.js +3 -1
- package/dist/core/parent-spec-seat.d.ts +12 -15
- package/dist/core/parent-spec-seat.js +14 -6
- package/dist/core/pause-registry.d.ts +35 -1
- package/dist/core/pause-registry.js +10 -0
- package/dist/core/permission-rule-consent.d.ts +18 -5
- package/dist/core/permission-rule-consent.js +13 -8
- package/dist/core/permission-rule-model.d.ts +87 -15
- package/dist/core/permission-rule-model.js +87 -8
- package/dist/core/permission-rule-org.d.ts +200 -33
- package/dist/core/permission-rule-org.js +217 -91
- package/dist/core/permission-rule-session.js +2 -2
- package/dist/core/permission-rule-store.d.ts +8 -0
- package/dist/core/permission-rule-store.js +1 -0
- package/dist/core/permission-rule-sync.js +3 -2
- package/dist/core/permission-rules.d.ts +7 -1
- package/dist/core/permission-rules.js +37 -8
- package/dist/core/read-only-shell.d.ts +1 -1
- package/dist/core/read-only-shell.js +30 -9
- package/dist/core/remote-env.d.ts +41 -1
- package/dist/core/remote-env.js +18 -0
- package/dist/core/resume-startup-cause.d.ts +18 -0
- package/dist/core/resume-startup-cause.js +12 -0
- package/dist/core/retention.js +7 -2
- package/dist/core/retired-keys.d.ts +8 -2
- package/dist/core/retired-keys.js +12 -1
- package/dist/core/roles.js +60 -10
- package/dist/core/rule-lane-reads.js +1 -1
- package/dist/core/runner/approval-feedback.d.ts +46 -0
- package/dist/core/runner/approval-feedback.js +41 -0
- package/dist/core/runner/compaction-call-options.d.ts +3 -3
- package/dist/core/runner/compaction-call-options.js +2 -2
- package/dist/core/runner/contracts.d.ts +34 -41
- package/dist/core/runner/cross-boundary-lane.d.ts +87 -0
- package/dist/core/runner/cross-boundary-lane.js +190 -0
- package/dist/core/runner/decide-continuation.d.ts +4 -4
- package/dist/core/runner/decide-continuation.js +3 -1
- package/dist/core/runner/gate-exit.d.ts +32 -12
- package/dist/core/runner/gate-exit.js +77 -34
- package/dist/core/runner/inherited-ask-grants.js +2 -2
- package/dist/core/runner/mcp-redial.d.ts +52 -10
- package/dist/core/runner/mcp-redial.js +38 -9
- package/dist/core/runner/permission-rule-lanes.d.ts +5 -2
- package/dist/core/runner/permission-rule-lanes.js +22 -10
- package/dist/core/runner/person-path-rows.d.ts +5 -3
- package/dist/core/runner/person-path-rows.js +2 -2
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -4
- package/dist/core/runner/prepare-acquire-reconcile.js +3 -3
- package/dist/core/runner/prepare-ask-lane.js +3 -3
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +6 -5
- package/dist/core/runner/prepare-caps-and-workflow.js +3 -3
- package/dist/core/runner/prepare-config-doors.d.ts +58 -15
- package/dist/core/runner/prepare-config-doors.js +167 -146
- package/dist/core/runner/prepare-context-lane.js +6 -3
- package/dist/core/runner/prepare-defer-classify.js +4 -7
- package/dist/core/runner/prepare-delegation-surface.d.ts +5 -4
- package/dist/core/runner/prepare-delegation-surface.js +8 -7
- package/dist/core/runner/prepare-execution-env.d.ts +1 -2
- package/dist/core/runner/prepare-execution-env.js +2 -1
- package/dist/core/runner/prepare-gate-stations.d.ts +2 -0
- package/dist/core/runner/prepare-gate-stations.js +4 -3
- package/dist/core/runner/prepare-hands-readface.d.ts +3 -3
- package/dist/core/runner/prepare-hands-readface.js +3 -2
- package/dist/core/runner/prepare-inherited-gate.d.ts +2 -0
- package/dist/core/runner/prepare-inherited-gate.js +3 -2
- package/dist/core/runner/prepare-listings.d.ts +1 -1
- package/dist/core/runner/prepare-listings.js +4 -2
- package/dist/core/runner/prepare-memory-engine-session.d.ts +0 -6
- package/dist/core/runner/prepare-memory-engine-session.js +19 -6
- package/dist/core/runner/prepare-memory.d.ts +3 -2
- package/dist/core/runner/prepare-memory.js +6 -2
- package/dist/core/runner/prepare-offload-wrappers.d.ts +4 -4
- package/dist/core/runner/prepare-offload-wrappers.js +2 -1
- package/dist/core/runner/prepare-park-ask.d.ts +1 -1
- package/dist/core/runner/prepare-park-ask.js +9 -3
- package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
- package/dist/core/runner/prepare-policy-chain.js +14 -19
- package/dist/core/runner/prepare-project-context.d.ts +1 -1
- package/dist/core/runner/prepare-project-context.js +6 -4
- package/dist/core/runner/prepare-prompt-assembly.d.ts +1 -1
- package/dist/core/runner/prepare-prompt-assembly.js +20 -16
- package/dist/core/runner/prepare-prompt-inputs.d.ts +12 -6
- package/dist/core/runner/prepare-prompt-inputs.js +6 -3
- package/dist/core/runner/prepare-protocol-tools.d.ts +7 -5
- package/dist/core/runner/prepare-protocol-tools.js +19 -12
- package/dist/core/runner/prepare-question-face.d.ts +4 -2
- package/dist/core/runner/prepare-question-face.js +4 -3
- package/dist/core/runner/prepare-safety-scan.d.ts +7 -2
- package/dist/core/runner/prepare-safety-scan.js +34 -27
- package/dist/core/runner/prepare-suspend-saga.d.ts +2 -2
- package/dist/core/runner/prepare-suspend-saga.js +6 -2
- package/dist/core/runner/prepare-task.js +22 -19
- package/dist/core/runner/prepare-turn-wiring.d.ts +10 -5
- package/dist/core/runner/prepare-turn-wiring.js +14 -49
- package/dist/core/runner/prepare-wiring-manifest.d.ts +10 -5
- package/dist/core/runner/prepare-wiring-manifest.js +9 -6
- package/dist/core/runner/prepare-workspace-restore.js +2 -2
- package/dist/core/runner/resume-admission.d.ts +4 -1
- package/dist/core/runner/resume-admission.js +16 -14
- package/dist/core/runner/resume-apply.js +4 -4
- package/dist/core/runner/resume-internals-and-config.d.ts +3 -3
- package/dist/core/runner/resume-internals-and-config.js +3 -8
- package/dist/core/runner/resume-policy-outcome.d.ts +2 -2
- package/dist/core/runner/resume-policy-outcome.js +18 -15
- package/dist/core/runner/resume-preflight.js +2 -2
- package/dist/core/runner/resume-review-outcome.js +3 -3
- package/dist/core/runner/retired-runner-deps.d.ts +5 -6
- package/dist/core/runner/retired-runner-deps.js +1 -4
- package/dist/core/runner/run-leg.js +97 -43
- package/dist/core/runner/run-recovery-lanes.js +5 -3
- package/dist/core/runner/run-settle-and-teardown.js +2 -0
- package/dist/core/runner/run-terminal-adoption.js +21 -9
- package/dist/core/runner/run-turn-boundary.js +9 -3
- package/dist/core/runner/runtask.js +1 -1
- package/dist/core/runner/session-file-state-replay.d.ts +5 -2
- package/dist/core/runner/session-file-state-replay.js +3 -2
- package/dist/core/runner/skills-seat.d.ts +15 -0
- package/dist/core/runner/skills-seat.js +57 -0
- package/dist/core/runner/stream-steer-verb.js +2 -2
- package/dist/core/runner/sub-agent-deny-lists.d.ts +13 -11
- package/dist/core/runner/sub-agent-deny-lists.js +7 -5
- package/dist/core/runner/synthetic-tools.d.ts +5 -2
- package/dist/core/runner/synthetic-tools.js +2 -12
- package/dist/core/runner/tool-face-overlay.d.ts +24 -6
- package/dist/core/runner/tool-face-overlay.js +24 -15
- package/dist/core/runner-deps.d.ts +37 -22
- package/dist/core/session-policy-store.d.ts +19 -0
- package/dist/core/session-policy-store.js +22 -2
- package/dist/core/session-store.d.ts +35 -16
- package/dist/core/session-store.js +20 -12
- package/dist/core/{shell-lexer.d.ts → shell-run-candidates.d.ts} +36 -12
- package/dist/core/{shell-lexer.js → shell-run-candidates.js} +145 -225
- package/dist/core/shell-wrapper-table.d.ts +5 -3
- package/dist/core/shell-wrapper-table.js +1 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +2 -2
- package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +49 -0
- package/dist/core/store-contracts/session-store-contract.js +639 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +12 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.js +5 -2
- package/dist/core/task-event.d.ts +44 -6
- package/dist/core/task-notification.js +2 -2
- package/dist/core/task-registry-agent.js +1 -0
- package/dist/core/task-registry-shared.d.ts +5 -0
- package/dist/core/task-registry.d.ts +7 -0
- package/dist/core/task-registry.js +17 -0
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +7 -7
- package/dist/core/tighten-task-spec.d.ts +6 -4
- package/dist/core/tighten-task-spec.js +2 -2
- package/dist/core/tool-catalog-entries.d.ts +1 -1
- package/dist/core/tool-catalog-entries.js +52 -52
- package/dist/core/tool-face-reader.d.ts +49 -0
- package/dist/core/tool-face-reader.js +94 -0
- package/dist/core/tool-face.d.ts +17 -8
- package/dist/core/tool-face.js +1 -0
- package/dist/core/tool-policy.d.ts +67 -23
- package/dist/core/tool-policy.js +72 -60
- package/dist/core/tool-roster.d.ts +46 -28
- package/dist/core/tool-roster.js +91 -14
- package/dist/core/tool-spec-members.js +2 -2
- package/dist/core/tool-spec.d.ts +20 -4
- package/dist/core/tools.js +2 -0
- package/dist/core/trace.d.ts +24 -2
- package/dist/core/types.d.ts +3 -3
- package/dist/core/types.js +1 -1
- package/dist/core/untrusted-text.d.ts +23 -0
- package/dist/core/untrusted-text.js +10 -10
- package/dist/core/user-attachment.d.ts +56 -2
- package/dist/core/user-attachment.js +139 -56
- package/dist/core/wiring-manifest.d.ts +4 -2
- package/dist/engine/compaction/compaction.d.ts +2 -2
- package/dist/engine/compaction/utils.d.ts +2 -2
- package/dist/engine/harness/agent-harness.js +2 -1
- package/dist/engine/harness/types.d.ts +10 -4
- package/dist/engine/llm/types.d.ts +7 -2
- package/dist/engine/llm/types.js +2 -1
- package/dist/engine/loop/agent-loop.d.ts +12 -1
- package/dist/engine/loop/agent-loop.js +17 -5
- package/dist/engine/loop/types.d.ts +7 -1
- package/dist/engine/session/repo-utils.d.ts +5 -0
- package/dist/engine/session/repo-utils.js +9 -0
- package/dist/engine/session/storage-base.js +2 -2
- package/dist/index.d.ts +37 -17
- package/dist/index.js +31 -14
- package/dist/internal/harness.d.ts +1 -0
- package/dist/internal/harness.js +1 -0
- package/dist/internal/llm.d.ts +1 -1
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/goal.d.ts +24 -1
- package/dist/orchestration/goal.js +3 -2
- package/dist/orchestration/run-workflow-tool.d.ts +3 -0
- package/dist/orchestration/run-workflow-tool.js +1 -0
- package/dist/orchestration/workflow-governance.d.ts +1 -1
- package/dist/orchestration/workflow.d.ts +3 -0
- package/dist/orchestration/workflow.js +2 -1
- package/dist/prompt-assembly/artifact-store.d.ts +44 -9
- package/dist/prompt-assembly/artifact-store.js +38 -12
- package/dist/prompt-assembly/artifact.d.ts +12 -11
- package/dist/prompt-assembly/artifact.js +52 -21
- package/dist/prompt-assembly/assemble.d.ts +2 -0
- package/dist/prompt-assembly/assemble.js +2 -1
- package/dist/prompt-assembly/catalog/index.js +2 -1
- package/dist/prompt-assembly/catalog/memory.d.ts +13 -0
- package/dist/prompt-assembly/catalog/memory.js +6 -0
- package/dist/prompt-assembly/catalog/schema.d.ts +19 -2
- package/dist/prompt-assembly/catalog/schema.js +3 -0
- package/dist/prompt-assembly/composer.d.ts +2 -0
- package/dist/prompt-assembly/composer.js +1 -1
- package/dist/prompt-assembly/overlay.d.ts +21 -11
- package/dist/prompt-assembly/overlay.js +57 -19
- package/dist/prompt-assembly/select.d.ts +21 -6
- package/dist/prompt-assembly/select.js +41 -4
- package/dist/prompts/default.d.ts +1 -12
- package/dist/prompts/default.js +0 -3
- package/dist/shell/lex.d.ts +87 -8
- package/dist/shell/lex.js +283 -49
- package/dist/stores/file/index.d.ts +8 -6
- package/dist/stores/file/permission-rule-store.d.ts +1 -1
- package/dist/stores/file/permission-rule-store.js +2 -1
- package/dist/tools/artifact/artifact-tool.js +14 -3
- package/dist/tools/fs/bash-program-position.d.ts +3 -15
- package/dist/tools/fs/bash-program-position.js +3 -10
- package/dist/tools/fs/bash-readonly-classifier.js +2 -0
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-bash.js +72 -101
- package/dist/tools/fs/fs-read.d.ts +12 -0
- package/dist/tools/fs/fs-read.js +10 -9
- package/dist/tools/fs/fs-shared.d.ts +27 -31
- package/dist/tools/fs/fs-shared.js +12 -15
- package/dist/tools/fs/fs-write.js +1 -1
- package/dist/tools/fs/index.js +2 -2
- package/dist/tools/fs/read-deny-home.d.ts +1 -1
- package/dist/tools/fs/read-deny-home.js +5 -4
- package/dist/tools/fs/read-deny.d.ts +16 -3
- package/dist/tools/fs/read-deny.js +12 -9
- package/dist/tools/fs/safety.d.ts +7 -6
- package/dist/tools/fs/shell-read-bindings.d.ts +5 -3
- package/dist/tools/fs/shell-read-bindings.js +15 -16
- package/dist/tools/fs/shell-read-device.js +1 -1
- package/dist/tools/fs/shell-read-plan.js +36 -47
- package/dist/tools/fs/shell-read-word.d.ts +1 -6
- package/dist/tools/fs/shell-read-word.js +2 -20
- package/dist/tools/fs/shell-reentry-text.js +1 -1
- package/dist/tools/web.d.ts +2 -2
- package/package.json +4 -1
- package/test/export-surface.snapshot.json +5651 -5457
- package/wire-changes/core@7.53.0.json +1968 -0
- package/wire-changes/core@7.54.0.json +2870 -0
- package/dist/core/shell-scan.d.ts +0 -60
- package/dist/core/shell-scan.js +0 -183
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AssertAllKeysHandled } from "./ask-origin.js";
|
|
2
|
+
import type { DecisionMember, PermissionResult } from "./tool-policy.js";
|
|
2
3
|
export declare const refusedOutOfContract: (message: string) => PermissionResult;
|
|
3
4
|
/** Is `d` a refusal the engine itself minted (by object identity — a look-alike `deny` a caller built is not one)? The receipt's
|
|
4
5
|
* answer is one of two things (the engine's refusal or its detached copy), and this tells them apart. */
|
|
@@ -12,6 +13,48 @@ export declare const isEngineRefusal: (d: unknown) => boolean;
|
|
|
12
13
|
* two entry-list members) — one word per author, so "who said this needs no asking" is read off the decision. */
|
|
13
14
|
declare const DECISION_REASONS: readonly ["rule", "mode", "hook", "safety", "classifier", "persisted_rule", "sandbox", "org_rule", "org_unavailable", "read_only", "skill", "deployment_rule", "request_rule"];
|
|
14
15
|
export type DecisionReason = (typeof DECISION_REASONS)[number];
|
|
16
|
+
/** The arms of the decision union that declare member `M`. */
|
|
17
|
+
type ArmOf<M extends DecisionMember> = PermissionResult extends infer U ? (U extends {
|
|
18
|
+
action: infer A;
|
|
19
|
+
} ? (M extends keyof U ? A : never) : never) : never;
|
|
20
|
+
/**
|
|
21
|
+
* Every member of the decision union with the ARMS that declare it — the one table the receipt's member list is read off
|
|
22
|
+
* (`DECISION_MEMBERS`), fenced to the union both ways: `satisfies` admits no member and no arm the union lacks, and
|
|
23
|
+
* {@link DecisionMemberArmsCoverTheUnion} no arm the union has and a row lacks. A present member on an arm outside its row is
|
|
24
|
+
* out of contract like a word outside a closed set ({@link screenContractValues}): an ask's mark on an allow or a deny is a
|
|
25
|
+
* decision that contradicts itself, and a consumer branching on the member would read the other arm's meaning.
|
|
26
|
+
*/
|
|
27
|
+
export declare const DECISION_MEMBER_ARMS: Readonly<{
|
|
28
|
+
readonly action: readonly ["allow", "ask", "deny"];
|
|
29
|
+
readonly updatedInput: readonly ["allow", "ask", "deny"];
|
|
30
|
+
readonly message: readonly ["allow", "ask", "deny"];
|
|
31
|
+
readonly decisionReason: readonly ["allow", "ask", "deny"];
|
|
32
|
+
readonly attestation: readonly ["allow", "ask", "deny"];
|
|
33
|
+
readonly requiresRealApproval: readonly ["ask"];
|
|
34
|
+
readonly denialLimitFallback: readonly ["ask"];
|
|
35
|
+
readonly classifierNoRuling: readonly ["ask"];
|
|
36
|
+
readonly allowRuleShadowed: readonly ["ask"];
|
|
37
|
+
readonly probeReason: readonly ["ask"];
|
|
38
|
+
readonly probeCause: readonly ["ask"];
|
|
39
|
+
readonly probeMandated: readonly ["ask"];
|
|
40
|
+
readonly crossBoundaryMandated: readonly ["ask"];
|
|
41
|
+
readonly mandated: readonly ["ask"];
|
|
42
|
+
readonly mandate: readonly ["ask"];
|
|
43
|
+
readonly probeReadRootCandidate: readonly ["ask"];
|
|
44
|
+
readonly matchedAskRule: readonly ["ask"];
|
|
45
|
+
readonly ruleEvidence: readonly ["ask"];
|
|
46
|
+
readonly segmentCoverage: readonly ["ask"];
|
|
47
|
+
readonly origin: readonly ["ask"];
|
|
48
|
+
readonly askClass: readonly ["ask"];
|
|
49
|
+
readonly classes: readonly ["ask"];
|
|
50
|
+
readonly guards: readonly ["ask"];
|
|
51
|
+
readonly ruleUnreadable: readonly ["ask"];
|
|
52
|
+
readonly authoredBy: readonly ["ask"];
|
|
53
|
+
readonly foldedAskClasses: readonly ["ask"];
|
|
54
|
+
}>;
|
|
55
|
+
export type DecisionMemberArmsCoverTheUnion = AssertAllKeysHandled<{
|
|
56
|
+
[M in DecisionMember]: Exclude<ArmOf<M>, (typeof DECISION_MEMBER_ARMS)[M][number]>;
|
|
57
|
+
}[DecisionMember]>;
|
|
15
58
|
export declare const RETIRED_WINDOW_MEMBER_DENY_MESSAGE: string;
|
|
16
59
|
export declare const carriesRetiredWindow: (fallback: unknown) => boolean;
|
|
17
60
|
/**
|
|
@@ -32,8 +32,17 @@ const CLOSED_MEMBERS = [
|
|
|
32
32
|
{ member: "classifierNoRuling", words: AUTO_MODE_FALLBACK_CAUSES, has: isAutoModeFallbackCause },
|
|
33
33
|
{ member: "requiresRealApproval", words: [true, false], has: (v) => v === true || v === false },
|
|
34
34
|
{ member: "probeMandated", words: [true], has: (v) => v === true },
|
|
35
|
+
{ member: "crossBoundaryMandated", words: [true], has: (v) => v === true },
|
|
35
36
|
{ member: "mandated", words: [true], has: (v) => v === true },
|
|
36
37
|
];
|
|
38
|
+
const EVERY_ARM = ["allow", "ask", "deny"];
|
|
39
|
+
const ASK = ["ask"];
|
|
40
|
+
export const DECISION_MEMBER_ARMS = Object.freeze({
|
|
41
|
+
action: EVERY_ARM, updatedInput: EVERY_ARM, message: EVERY_ARM, decisionReason: EVERY_ARM, attestation: EVERY_ARM,
|
|
42
|
+
requiresRealApproval: ASK, denialLimitFallback: ASK, classifierNoRuling: ASK, allowRuleShadowed: ASK, probeReason: ASK, probeCause: ASK,
|
|
43
|
+
probeMandated: ASK, crossBoundaryMandated: ASK, mandated: ASK, mandate: ASK, probeReadRootCandidate: ASK, matchedAskRule: ASK, ruleEvidence: ASK,
|
|
44
|
+
segmentCoverage: ASK, origin: ASK, askClass: ASK, classes: ASK, guards: ASK, ruleUnreadable: ASK, authoredBy: ASK, foldedAskClasses: ASK,
|
|
45
|
+
});
|
|
37
46
|
const RETIRED_WINDOW_MEMBER = "autoDenyAfterMs";
|
|
38
47
|
export const RETIRED_WINDOW_MEMBER_DENY_MESSAGE = `a permission decision's "denialLimitFallback" carries "${RETIRED_WINDOW_MEMBER}" — the decision names the counts only; ` +
|
|
39
48
|
`the auto-deny window is decided by the ask's route (a live approver arms it, every other route runs none) and cannot be ` +
|
|
@@ -91,6 +100,13 @@ export function screenContractValues(contract, opts) {
|
|
|
91
100
|
continue;
|
|
92
101
|
return unrecognized(member, v, words);
|
|
93
102
|
}
|
|
103
|
+
const arm = contract.action;
|
|
104
|
+
for (const [member, arms] of Object.entries(DECISION_MEMBER_ARMS)) {
|
|
105
|
+
if (contract[member] === undefined || (arm === undefined ? EVERY_ARM.every((a) => arms.includes(a)) : arms.includes(arm)))
|
|
106
|
+
continue;
|
|
107
|
+
return refusedOutOfContract(`a permission decision carries "${member}" on ${arm === undefined ? "a result with no action (no opinion)" : `its "${arm}" arm`} — the member belongs to ` +
|
|
108
|
+
`the ${arms.join("/")} arm only; denied fail-closed rather than letting consumers branch on a member its arm does not hold`);
|
|
109
|
+
}
|
|
94
110
|
if (carriesRetiredWindow(contract.denialLimitFallback))
|
|
95
111
|
return refusedOutOfContract(RETIRED_WINDOW_MEMBER_DENY_MESSAGE);
|
|
96
112
|
return undefined;
|
|
@@ -245,17 +245,39 @@ export declare function readCallTarget(env: ExecutionEnv | undefined, call: Tool
|
|
|
245
245
|
readonly root?: string | undefined;
|
|
246
246
|
readonly cwd?: string | undefined;
|
|
247
247
|
}, signal?: AbortSignal, leads?: ReadonlyMap<string, string | undefined>): Promise<CallTargetReading>;
|
|
248
|
+
/** The gate's entry records the loop's reading of this call's arguments against the face it stamps on the call. */
|
|
249
|
+
export declare function stampArgsReading(face: object, read: (args: unknown) => unknown): void;
|
|
248
250
|
/**
|
|
249
|
-
* `
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
251
|
+
* `args` as the called tool will run them — its argument preparation and schema coercions, the reading the loop gave the
|
|
252
|
+
* model's call — for the call `req` belongs to; `args` itself when nothing was stamped (a bare request outside a Runner:
|
|
253
|
+
* a host judging a call reads it the tool's way first). Every seat that adopts a rewrite (a hook's, a policy's, a
|
|
254
|
+
* person's edit) takes it through here before anything judges it, so what is judged is what runs. A value the reading
|
|
255
|
+
* leaves as it is comes back as ITSELF (the same object: a target reading taken for it still describes it).
|
|
256
|
+
*/
|
|
257
|
+
export declare function argsAsTheToolReads(req: {
|
|
258
|
+
readonly face?: object | undefined;
|
|
259
|
+
}, args: unknown): unknown;
|
|
260
|
+
/** `args` through one call's reading `read` (the face-less seat: the resumed call reads through its live tool): ITSELF when the
|
|
261
|
+
* reading leaves its bytes as they are, else the reading's value, recorded as read from `args`. */
|
|
262
|
+
export declare function argsReadBy(read: (args: unknown) => unknown, args: unknown): unknown;
|
|
263
|
+
/** The value `args` was read from, when a reading moved it; otherwise `args` itself. */
|
|
264
|
+
export declare function argsReadFrom(args: unknown): unknown;
|
|
265
|
+
/** `copy` is a detached copy of `original` (the decision receipt's): the same bytes, so read from what `original` was read
|
|
266
|
+
* from — the recorded step survives the copy instead of being lost to the copy's new identity. */
|
|
267
|
+
export declare function carryArgsReadFrom(original: unknown, copy: unknown): void;
|
|
268
|
+
/**
|
|
269
|
+
* `req` with its arguments replaced by `args` AS THE TOOL READS THEM ({@link argsAsTheToolReads}) and — when `req` carries
|
|
270
|
+
* a reading of its own target — a reading of the NEW args taken the same way (same environment, same root / cwd, same
|
|
271
|
+
* face). Every seat that rewrites a request's arguments and hands it on (a composition's rewrite cascade, a re-judgment of
|
|
272
|
+
* the final or an edited form) goes through here, so the next layer never judges a request its reading does not describe
|
|
273
|
+
* nor arguments the tool would run differently. `signal` is the CURRENT call's: a reading never carries one call's
|
|
274
|
+
* cancellation into another's.
|
|
254
275
|
*/
|
|
255
276
|
export declare function withArgsReading<R extends {
|
|
256
277
|
readonly args: unknown;
|
|
257
278
|
readonly targetReading?: CallTargetReading | undefined;
|
|
258
|
-
|
|
279
|
+
readonly face?: object | undefined;
|
|
280
|
+
}>(req: R, args: unknown, signal: AbortSignal | undefined): Promise<R>;
|
|
259
281
|
/** The request's target reading, when it describes the request's own `args` (the object it was taken for); otherwise
|
|
260
282
|
* nothing — a rule lane then judges the lexical view it always judged. Every rule lane reads the reading through here. */
|
|
261
283
|
export declare function callTargetReadingOf(req: {
|
|
@@ -3,6 +3,7 @@ import { declaredPathTargetOf, pathTargetValue, protectivePathTargetOf } from ".
|
|
|
3
3
|
import { symlinkChainHops } from "./path-identity.js";
|
|
4
4
|
import { DEFAULT_GATE_AWAIT_TIMEOUT_MS, withGateTimeout } from "./gate-bounded-await.js";
|
|
5
5
|
import { thrownText } from "./thrown-value.js";
|
|
6
|
+
import { canonicalize } from "./canonical-json.js";
|
|
6
7
|
export function pathTargetBaseOf(pt, bases) {
|
|
7
8
|
return (pt?.base ?? "cwd") === "root" ? bases.root : (bases.cwd ?? bases.root);
|
|
8
9
|
}
|
|
@@ -146,10 +147,35 @@ export async function readCallTarget(env, call, signal, leads) {
|
|
|
146
147
|
REREAD.set(reading, (args, rereadSignal) => readCallTarget(env, { ...call, args }, rereadSignal, leads));
|
|
147
148
|
return reading;
|
|
148
149
|
}
|
|
149
|
-
|
|
150
|
+
const ARGS_READING = new WeakMap();
|
|
151
|
+
export function stampArgsReading(face, read) {
|
|
152
|
+
ARGS_READING.set(face, read);
|
|
153
|
+
}
|
|
154
|
+
export function argsAsTheToolReads(req, args) {
|
|
155
|
+
const read = req.face === undefined ? undefined : ARGS_READING.get(req.face);
|
|
156
|
+
return read === undefined ? args : argsReadBy(read, args);
|
|
157
|
+
}
|
|
158
|
+
export function argsReadBy(read, args) {
|
|
159
|
+
const out = read(args);
|
|
160
|
+
if (out === args || canonicalize(out) === canonicalize(args))
|
|
161
|
+
return args;
|
|
162
|
+
if (typeof out === "object" && out !== null)
|
|
163
|
+
READ_FROM.set(out, args);
|
|
164
|
+
return out;
|
|
165
|
+
}
|
|
166
|
+
const READ_FROM = new WeakMap();
|
|
167
|
+
export function argsReadFrom(args) {
|
|
168
|
+
return typeof args === "object" && args !== null && READ_FROM.has(args) ? READ_FROM.get(args) : args;
|
|
169
|
+
}
|
|
170
|
+
export function carryArgsReadFrom(original, copy) {
|
|
171
|
+
if (typeof original === "object" && original !== null && READ_FROM.has(original) && typeof copy === "object" && copy !== null)
|
|
172
|
+
READ_FROM.set(copy, READ_FROM.get(original));
|
|
173
|
+
}
|
|
174
|
+
export async function withArgsReading(req, args, signal) {
|
|
175
|
+
const read = argsAsTheToolReads(req, args);
|
|
150
176
|
const reading = callTargetReadingOf(req);
|
|
151
177
|
const reread = reading === undefined ? undefined : REREAD.get(reading);
|
|
152
|
-
return reread === undefined ?
|
|
178
|
+
return reread === undefined ? { ...req, args: read } : { ...req, args: read, targetReading: await reread(read, signal) };
|
|
153
179
|
}
|
|
154
180
|
function viewFrom(v) {
|
|
155
181
|
if (v.lexical === undefined)
|
|
@@ -68,7 +68,7 @@ export interface EngineNotice {
|
|
|
68
68
|
* as usual. Audience `user`; once per prepared task for the skill and request lists (`detail.sessionId` present), once
|
|
69
69
|
* per Runner for the deployment's (at construction, no session). `detail: { sessionId?, entries: [{ source, entry,
|
|
70
70
|
* reason, skill?, list? }] }` (`source` ∈ `skill` / `request` / `deployment`; `skill` and `list` only on a skill's;
|
|
71
|
-
* `reason` ∈ {@link import("./allow-entry.js").ALLOW_ENTRY_INERT_REASONS}).
|
|
71
|
+
* `reason` ∈ {@link import("./allow-entry.js").ALLOW_ENTRY_INERT_REASONS}; `entry` is the entry as written — the message spells it — when it is at most `NOTICE_RULE_TEXT_MAX` (1 024) code points; a longer one is cut to 1 024 plus the truncation mark, 1 025 in all).
|
|
72
72
|
* - `"mods.registration_refused"` — an extension registration was not mounted: a registration admitted before it
|
|
73
73
|
* answered `{ refuse }` on `plugin.register`, or failed while judging it (fail-closed). The run goes on without it.
|
|
74
74
|
* Audience `user` (the seat is in `detail`). Once per refused registration per run. `detail: { name, seat, tier,
|
|
@@ -399,6 +399,16 @@ export interface EngineNotice {
|
|
|
399
399
|
* ({@link import("./secret-env.js").holdOwnCredentialValues}); `detail: { reason }` — the kind, never the value. Delivered
|
|
400
400
|
* to `RunnerDeps.onNotice` from the `new Runner` receipt; the intakes with no structured seat (a brain's construction,
|
|
401
401
|
* a request's route reading, a peer's dial, a directly built distiller seat) print its line on `console.warn`.
|
|
402
|
+
* - `"config.cross_boundary_posture_undeclared"` — a run whose tree executes on a target device (armed) on a deployment that
|
|
403
|
+
* configured no `RunnerDeps.crossBoundaryPosture`: the permissive `"single_user"` reading is in force. Once per run;
|
|
404
|
+
* `detail: { sessionId, runId, taint }` — `taint` lists the tree's taint bits
|
|
405
|
+
* ({@link import("./cross-boundary-taint.js").CROSS_BOUNDARY_TAINT_BITS}). Minted by
|
|
406
|
+
* {@link import("./cross-boundary-taint.js").crossBoundaryPostureUndeclaredNotice}. Audience `operator`.
|
|
407
|
+
* - `"config.cross_boundary_record_unwritten"` — a session's cross-boundary record the engine owed could not be written (the
|
|
408
|
+
* store threw, or answered with no entry id) and refused nothing: on a tree that is not governed no judgment reads the record;
|
|
409
|
+
* at a governed leg's prepare or settle the next leg reads the content after the newest record as off-target. Per failed write;
|
|
410
|
+
* `detail: { sessionId, runId, phase, governed, cause }` (`phase`: `prepare` / `exit` / `suspend` / `settle`). Minted by
|
|
411
|
+
* {@link import("./cross-boundary-taint.js").crossBoundaryRecordUnwrittenNotice}. Audience `operator`.
|
|
402
412
|
* - `"config.permission_mode_unavailable"` — the permission mode a task requested is not the mode the leg runs
|
|
403
413
|
* under: the deployment denies it (`by: "operator_deny"` — `RuntimeCaps.bypassPermissions` / `autoMode` is
|
|
404
414
|
* `false`), a requested `auto` has no classifier face (`by: "face_absent"` — neither the leg's deps nor its chain carry
|
|
@@ -439,7 +449,18 @@ export interface EngineNotice {
|
|
|
439
449
|
* complete absolute path (only a foreign writer or a hand edit makes one; every engine write face refuses it): they
|
|
440
450
|
* take no part in this run's checks — a deny or ask row among them protects nothing — until they are rewritten or
|
|
441
451
|
* removed. Once per run, by whichever read met them first. `detail: { rows, count, sessionId, runId }` — `rows`
|
|
442
|
-
* the first eight `{ rule, scopeRoot }
|
|
452
|
+
* the first eight `{ rule, scopeRoot }`, `count` all of them; `rule` is the rule text as the store served it, through the same reading
|
|
453
|
+
* as `permission.allowed_tool_not_granted`'s `entries[].entry` (the original, not a spelling of it, when it is at most 1 024 code points;
|
|
454
|
+
* a longer one is cut to 1 024 plus the truncation mark, 1 025 in all), `scopeRoot` neutralized and bounded. Audience `user`.
|
|
455
|
+
* - `"config.session_rules_earlier_grammar"` — a session's stored permission rules (`RunnerDeps.sessionPolicyStore`) hold
|
|
456
|
+
* entries the rule grammar they were written in reads as nothing: an allow entry admits nothing, and a `toolDeny` entry
|
|
457
|
+
* this engine's grammar reads as no rule makes those rules refuse every call until they are rewritten. The message names
|
|
458
|
+
* the session, the bucket, the entries (the first five, the rest counted), the reader's word and the way out. Audience
|
|
459
|
+
* `user`. Once per distinct entry set per bucket per rule layer (the run's own rules, each ancestor's inherited ones).
|
|
460
|
+
* `detail: { bucket, storedGrammar, entries: [{ entry, reader }], rewrite: { by, stampsGrammar }, rulesSessionId,
|
|
461
|
+
* sessionId }` — `entries` every one, `entry` through the same reading as `permission.allowed_tool_not_granted`'s;
|
|
462
|
+
* `reader` ∈ `no_rule` / `named_no_tool`; `rewrite.by` = `operator_write_without_rev`; `rulesSessionId` the session
|
|
463
|
+
* whose rules they are (an ancestor's on a delegated child), `sessionId` the run that read them.
|
|
443
464
|
* - `"config.durable_gate_unavailable"` — a durable-approval MANDATE is in force on a leg with NO
|
|
444
465
|
* checkpoint store: the per-principal `forceDurableGate` entitlement, or the task's own
|
|
445
466
|
* `durableApproval` opt-in with no live approver seat (`durableMandateSourceOf`, the predicate the
|
|
@@ -466,7 +487,13 @@ export interface EngineNotice {
|
|
|
466
487
|
* frame's two count keys). They are NOT redelivered (a steer aimed at a finished run must not
|
|
467
488
|
* fire at the next one — unlike ENGINE notes, which pend per session); the loud half of the
|
|
468
489
|
* #257 contract's "accepted = enqueued, not consumed" sentence;
|
|
469
|
-
*
|
|
490
|
+
* The words a person wrote on an approval card (a durable `policy_ask` allow's `feedback`) that did not reach the
|
|
491
|
+
* model are counted in the SAME account under the steer code — one more row of that family, `detail.kind:
|
|
492
|
+
* "approval_feedback"` (absent on every other row) — when the message carrying them never committed and the row did not come back
|
|
493
|
+
* (a returned row does not carry them: its next decide is fresh); when the pause tried to carry them forward and the parked-steer
|
|
494
|
+
* carrier refused, the row also names the store's refusal as `detail.carry` (`steering.invalid_content` | `steering.queue_full`) and
|
|
495
|
+
* its sentence says so (`cause` stays `leg_end`: the leg ended with them owed — the closed set has no carrier words);
|
|
496
|
+
* `detail: { <countKey>, cause, kind?, carry?, taskId?, sessionId?, runId? }` (the `code` and the `countKey` of each family are the
|
|
470
497
|
* table {@link USER_INPUT_UNDRAINED_FAMILIES}, keyed by the lane the input was queued on — `injectionLaneOf` — and the
|
|
471
498
|
* minter writes exactly those; `cause` on both rows, closed `USER_INPUT_UNDRAINED_CAUSES`: `"leg_end"` — this engine's arm, the
|
|
472
499
|
* leg ended with it still owed; `"crashed"` — minted by the SERVING LAYER, not this engine, before the
|
|
@@ -863,7 +890,8 @@ export interface EngineNotice {
|
|
|
863
890
|
* toolCallId, cause, parkLaneExisted, remedy? }` — `parkLaneExisted` says whether a park lane was armed and
|
|
864
891
|
* declined/failed (`true`) or none existed (`false`, the usual shape); `remedy` (the two causes that say nobody
|
|
865
892
|
* could be asked — `approver_unavailable` and `no_approver_wired`; never `mandate_unreconstructible`)
|
|
866
|
-
* is the one sentence naming the caller-side change that would have let the call run, as the tool text carries it
|
|
893
|
+
* is the one sentence naming the caller-side change that would have let the call run, as the tool text carries it (for arguments
|
|
894
|
+
* no approval can be bound to, the binding's own sentence: the remedy's approver half would not let them run). Audience `"user"`: the refused
|
|
867
895
|
* work is the session user's own; the operator hears it through the sink like every code.
|
|
868
896
|
*
|
|
869
897
|
* - `"memory.consolidation_recommended"` (design/339 §2.2/§6.2) — the engine-minted per-scope
|
|
@@ -1004,6 +1032,16 @@ export interface OwedUserInputAccount {
|
|
|
1004
1032
|
seq?: number;
|
|
1005
1033
|
}>;
|
|
1006
1034
|
carried: number;
|
|
1035
|
+
/** The approving person's words (a `policy_ask` allow's `feedback`), counted APART from `frames`: owed, and how many the migration carried.
|
|
1036
|
+
* They are on no row of their own, and a returned row (the compensation reopened it) does not carry them either — its next decide is a
|
|
1037
|
+
* fresh one the host may re-supply them on — so, unlike the caller's own frames, they are not announced when the row came back (the row is
|
|
1038
|
+
* pending again and the person is asked again). `refusal`: the code the parked-steer carrier answered when the pause tried to carry them
|
|
1039
|
+
* (`steering.invalid_content` — over its bound; `steering.queue_full`), the store's own words; absent when no carry was refused. */
|
|
1040
|
+
approval?: {
|
|
1041
|
+
owed: number;
|
|
1042
|
+
carried: number;
|
|
1043
|
+
refusal?: ApprovalCarryRefusal;
|
|
1044
|
+
};
|
|
1007
1045
|
};
|
|
1008
1046
|
}
|
|
1009
1047
|
/**
|
|
@@ -1058,6 +1096,9 @@ export declare function settleOwedUserInput(account: OwedUserInputAccount, rowRe
|
|
|
1058
1096
|
*/
|
|
1059
1097
|
export declare const USER_INPUT_UNDRAINED_CAUSES: readonly ["leg_end", "crashed"];
|
|
1060
1098
|
export type UserInputUndrainedCause = (typeof USER_INPUT_UNDRAINED_CAUSES)[number];
|
|
1099
|
+
/** What the parked-steer carrier answered (the checkpoint store's own refusal codes, not a set of this notice) when a pause tried to carry an
|
|
1100
|
+
* approving person's words: refused as content / over its bound, or its queue was full. `detail.carry` of the approval row, absent otherwise. */
|
|
1101
|
+
export type ApprovalCarryRefusal = "steering.invalid_content" | "steering.queue_full";
|
|
1061
1102
|
/**
|
|
1062
1103
|
* The two families of the stranded-input account, keyed by the lane the input was queued on (`injectionLaneOf` maps a steer's
|
|
1063
1104
|
* tier to it): the notice `code` the family is announced under, and the `detail` key that carries its count
|
|
@@ -1102,5 +1143,7 @@ export declare function parentLegIds(internals: {
|
|
|
1102
1143
|
export declare function undrainedUserInputNotices(counts: {
|
|
1103
1144
|
steer: number;
|
|
1104
1145
|
followUp: number;
|
|
1146
|
+
approvalFeedback?: number;
|
|
1147
|
+
approvalCarry?: ApprovalCarryRefusal;
|
|
1105
1148
|
}, taskId?: string, sessionId?: string, runId?: string, parent?: ParentLegIds): EngineNotice[];
|
|
1106
1149
|
export {};
|
|
@@ -44,7 +44,10 @@ export function settleOwedUserInput(account, rowReturned, ids, onNotice) {
|
|
|
44
44
|
SETTLED_OWED_ACCOUNTS.add(account);
|
|
45
45
|
try {
|
|
46
46
|
const owed = owedUserInputCounts(account.held, account.migrated, { ...account.continuation, rowReturned });
|
|
47
|
-
|
|
47
|
+
const approval = account.continuation.approval;
|
|
48
|
+
const approvalFeedback = approval === undefined || rowReturned ? 0 : Math.max(0, approval.owed - approval.carried);
|
|
49
|
+
const approvalCarry = approvalFeedback > 0 ? approval?.refusal : undefined;
|
|
50
|
+
for (const notice of undrainedUserInputNotices({ ...owed, ...(approvalFeedback > 0 ? { approvalFeedback } : {}), ...(approvalCarry !== undefined ? { approvalCarry } : {}) }, ids.taskId, ids.sessionId, ids.runId, ids.parent))
|
|
48
51
|
deliverEngineNotice(onNotice, notice);
|
|
49
52
|
}
|
|
50
53
|
catch {
|
|
@@ -84,6 +87,19 @@ export function undrainedUserInputNotices(counts, taskId, sessionId, runId, pare
|
|
|
84
87
|
if (toParent)
|
|
85
88
|
copies.push({ code: STEER_UNDRAINED, message: `${message}${copyTail}`, detail: { ...count, ...ptid, sessionId: parentSession, childSessionId: sessionId } });
|
|
86
89
|
}
|
|
90
|
+
const approvalFeedback = counts.approvalFeedback ?? 0;
|
|
91
|
+
if (approvalFeedback > 0) {
|
|
92
|
+
const why = counts.approvalCarry === "steering.invalid_content"
|
|
93
|
+
? "the leg paused with them still owed and the parked-steer carrier refused them (longer than a parked steer may be)"
|
|
94
|
+
: counts.approvalCarry === "steering.queue_full"
|
|
95
|
+
? "the leg paused with them still owed and the parked-steer carrier refused them (its queue was full)"
|
|
96
|
+
: "the leg ended before the message carrying them was committed";
|
|
97
|
+
const message = `${approvalFeedback} approval-card feedback(s) (the words a person wrote when approving a tool call) never reached the model — ${why}. They are NOT redelivered; re-send if still wanted.`;
|
|
98
|
+
const count = { [USER_INPUT_UNDRAINED_FAMILIES.steer.countKey]: approvalFeedback, cause, kind: "approval_feedback", ...(counts.approvalCarry !== undefined ? { carry: counts.approvalCarry } : {}) };
|
|
99
|
+
own.push({ code: STEER_UNDRAINED, message, detail: { ...count, ...tid, ...sid, ...rid } });
|
|
100
|
+
if (toParent)
|
|
101
|
+
copies.push({ code: STEER_UNDRAINED, message: `${message}${copyTail}`, detail: { ...count, ...ptid, sessionId: parentSession, childSessionId: sessionId } });
|
|
102
|
+
}
|
|
87
103
|
if (counts.followUp > 0) {
|
|
88
104
|
const message = `${counts.followUp} user follow-up(s) ${tail}`;
|
|
89
105
|
const count = { [USER_INPUT_UNDRAINED_FAMILIES.followUp.countKey]: counts.followUp, cause };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The engine's storage seats as ONE backend contract.
|
|
3
|
+
*
|
|
4
|
+
* A backend is the thing a deployment constructs over one storage — a data root, a database — and whose
|
|
5
|
+
* members it wires into {@link import("./runner-deps.js").RunnerDeps}. Before this contract the shape of
|
|
6
|
+
* "a backend" was whatever the file family's aggregate class happened to carry, so a second backend had
|
|
7
|
+
* nothing to implement and a host composing several had nothing to type its engine half against. The
|
|
8
|
+
* shape now lives here, once: the bundled file backend implements it, and so does any other.
|
|
9
|
+
*
|
|
10
|
+
* Membership rule: a member is an engine seat whose durable store lives in the backend's storage and that
|
|
11
|
+
* every backend supplies, the bundled file backend included — `retention` is the one optional member,
|
|
12
|
+
* and a seat the file backend does not supply is not a member. Each member's NAME is its `RunnerDeps` seat and its TYPE is
|
|
13
|
+
* that seat's store type, so each member wires into its seat as it is (name the seats; a backend object may carry
|
|
14
|
+
* members that are not seats, so it is not spread). The member-to-seat correspondence is pinned in both directions
|
|
15
|
+
* by the test suite, together with the classification of the store-shaped seats that are not members. One reading per member:
|
|
16
|
+
* - `fileHistoryStore` is the store only. The seat also accepts the word `"disabled"`; that word is the
|
|
17
|
+
* deployment's wiring decision, not something a storage supplies.
|
|
18
|
+
*
|
|
19
|
+
* A host's own product stores do not belong here: a host that keeps more stores beside these composes
|
|
20
|
+
* an `EngineStorageBackend` with its own, rather than widening this contract.
|
|
21
|
+
*/
|
|
22
|
+
import type { SessionStore } from "./session.js";
|
|
23
|
+
import type { CheckpointStore } from "./checkpoint-store.js";
|
|
24
|
+
import type { ToolResultStore } from "./tool-result-store.js";
|
|
25
|
+
import type { SessionPolicyStore } from "./session-policy-store.js";
|
|
26
|
+
import type { WorkflowJournalStore } from "./workflow-journal-store.js";
|
|
27
|
+
import type { UsageWindowStore } from "./usage-window-store.js";
|
|
28
|
+
import type { BackgroundAgentStore } from "./background-agent-store.js";
|
|
29
|
+
import type { MailboxStore } from "./mailbox-store.js";
|
|
30
|
+
import type { FileHistoryStore } from "./file-history-store.js";
|
|
31
|
+
import type { ManagedRetentionCapability } from "./retention.js";
|
|
32
|
+
import type { RosterStore } from "../agents/roster-store.js";
|
|
33
|
+
export interface EngineStorageBackend {
|
|
34
|
+
/** `RunnerDeps.sessionStore`. */
|
|
35
|
+
readonly sessionStore: SessionStore;
|
|
36
|
+
/** `RunnerDeps.checkpointStore`. */
|
|
37
|
+
readonly checkpointStore: CheckpointStore;
|
|
38
|
+
/** `RunnerDeps.toolResultStore`. */
|
|
39
|
+
readonly toolResultStore: ToolResultStore;
|
|
40
|
+
/** `RunnerDeps.sessionPolicyStore`. */
|
|
41
|
+
readonly sessionPolicyStore: SessionPolicyStore;
|
|
42
|
+
/** `RunnerDeps.workflowJournalStore`. */
|
|
43
|
+
readonly workflowJournalStore: WorkflowJournalStore;
|
|
44
|
+
/** `RunnerDeps.usageWindowStore`. */
|
|
45
|
+
readonly usageWindowStore: UsageWindowStore;
|
|
46
|
+
/** `RunnerDeps.backgroundAgentStore` — and the same instance wherever a deployment-composed Agent tool
|
|
47
|
+
* takes its agent store (the seat's pairing rule). */
|
|
48
|
+
readonly backgroundAgentStore: BackgroundAgentStore;
|
|
49
|
+
/** `RunnerDeps.mailboxStore` (same single-instance pairing as `backgroundAgentStore`). */
|
|
50
|
+
readonly mailboxStore: MailboxStore;
|
|
51
|
+
/** `RunnerDeps.rosterStore`. */
|
|
52
|
+
readonly rosterStore: RosterStore;
|
|
53
|
+
/** `RunnerDeps.fileHistoryStore` — the store; the seat's `"disabled"` word is not a backend's to give. */
|
|
54
|
+
readonly fileHistoryStore: FileHistoryStore;
|
|
55
|
+
/**
|
|
56
|
+
* The backend-level managed-retention executor, when this backend has one.
|
|
57
|
+
*
|
|
58
|
+
* Retention execution belongs to the backend, not to each store: the capability's session deletion
|
|
59
|
+
* re-checks live references inside the deletion transaction, and those references are held by several
|
|
60
|
+
* stores at once (pending checkpoints, background-agent rows, workflow runs), so only a party that
|
|
61
|
+
* spans them can honor it. Absent ⇒ this backend executes no managed retention — the bundled file
|
|
62
|
+
* backend is one such backend.
|
|
63
|
+
*
|
|
64
|
+
* Not the same field as a store's `retention`: on a store that member is the declaration WORD
|
|
65
|
+
* ({@link import("./retention.js").RetentionDeclaring}, `"managed" | "none"`); here it is the
|
|
66
|
+
* executor OBJECT. A backend is not a store: handed to `assertRetentionCapability` as one, a backend
|
|
67
|
+
* that carries this member is refused as an unparseable declaration.
|
|
68
|
+
*/
|
|
69
|
+
readonly retention?: ManagedRetentionCapability;
|
|
70
|
+
/** Release everything the backend holds (handles, locks) so a successor over the same storage can open
|
|
71
|
+
* it. Call it at shutdown. */
|
|
72
|
+
dispose(): Promise<void>;
|
|
73
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -75,6 +75,10 @@ export declare function trackKeyOf(root: string, absPath: string): string;
|
|
|
75
75
|
* before; pass it and a foreign-family record is refused by name instead of coerced.
|
|
76
76
|
*/
|
|
77
77
|
export declare function resolveTrackKey(root: string, key: string, minted?: FileHistoryTrackKeyDescriptor): FileHistoryTrackKeyResolution;
|
|
78
|
+
/** The file-history failure codes, spelled once: {@link FileHistoryError}'s `code` is derived from this tuple (each
|
|
79
|
+
* word is documented there). A host that recognizes a code in failure text, or keeps a code in a store, reads this
|
|
80
|
+
* value rather than keeping its own list. */
|
|
81
|
+
export declare const FILE_HISTORY_ERROR_CODES: readonly ["track_failed", "snapshot_failed", "restore_failed", "adopt_failed", "not_found", "aborted", "unsupported_format", "conflict"];
|
|
78
82
|
export interface FileHistoryError {
|
|
79
83
|
/** `not_found` = no boundary for that (scope, entryId); `aborted` = the signal fired (or the
|
|
80
84
|
* fencing discarded a timed-out attempt); `conflict` = a non-destructive-target law refused
|
|
@@ -89,7 +93,7 @@ export interface FileHistoryError {
|
|
|
89
93
|
* work its shape drove; a fault in the PUBLISH step itself — the disk refusing a good graph —
|
|
90
94
|
* answers `adopt_failed`); `unsupported_format`
|
|
91
95
|
* = a foreign-epoch or wrong-version envelope; the rest name the verb that failed. */
|
|
92
|
-
code:
|
|
96
|
+
code: (typeof FILE_HISTORY_ERROR_CODES)[number];
|
|
93
97
|
message: string;
|
|
94
98
|
}
|
|
95
99
|
export type FileHistoryResult = {
|
|
@@ -291,7 +295,7 @@ export interface FileHistoryStore {
|
|
|
291
295
|
* discarding that baseline would be the fake-pristine hole DV-14 exists to weld shut.
|
|
292
296
|
*
|
|
293
297
|
* `verify` is the EVIDENCE arm (adversarial round 2). A caller whose write failed with a code the
|
|
294
|
-
* FileSystem contract defines as "nothing was written" (`already_exists`, `precondition_failed`)
|
|
298
|
+
* FileSystem contract defines as "nothing was written" (`already_exists`, `precondition_failed`, `target_unavailable`)
|
|
295
299
|
* has proof and passes nothing. Every other failure — a plain write is not contractually atomic,
|
|
296
300
|
* so ENOSPC, a dying transport or a thrown backend may have TRUNCATED the file before reporting —
|
|
297
301
|
* must hand an `env` here: the store then re-reads the path ONCE and retracts only if the world
|
|
@@ -66,6 +66,7 @@ export function resolveTrackKey(root, key, minted) {
|
|
|
66
66
|
return { ok: false, reason: `unsafe recorded key escapes root: ${key}` };
|
|
67
67
|
return { ok: true, abs: joinUnder(root, keyN) };
|
|
68
68
|
}
|
|
69
|
+
export const FILE_HISTORY_ERROR_CODES = Object.freeze(["track_failed", "snapshot_failed", "restore_failed", "adopt_failed", "not_found", "aborted", "unsupported_format", "conflict"]);
|
|
69
70
|
export const FILE_HISTORY_DIFF_LINE_BUDGET = 2000;
|
|
70
71
|
export function countRestoreLineDiff(current, target) {
|
|
71
72
|
const isBinary = (b) => b !== undefined && b.includes(0);
|
package/dist/core/gate-fold.js
CHANGED
|
@@ -8,6 +8,7 @@ import { createGateDeadline, awaitWriteProtectionJudgment, gateWaitFailureOf, wi
|
|
|
8
8
|
import { shellReadFaceWords } from "../tools/fs/shell-read-face.js";
|
|
9
9
|
import { failedJudgmentDeny } from "./runner/policy-throw.js";
|
|
10
10
|
import { thrownText } from "./thrown-value.js";
|
|
11
|
+
import { argsAsTheToolReads } from "./effective-path-target.js";
|
|
11
12
|
import { foldHookAsk, refuseOutOfContractDecision } from "./tool-policy.js";
|
|
12
13
|
import { applyUnansweredSilence, readStationAnswer, silencedBy } from "./shell-read-silence.js";
|
|
13
14
|
import { asksUnstated, permissionSeatAt, unstatedAskMessage } from "./mode-policy.js";
|
|
@@ -37,10 +38,10 @@ export async function runGateFold(pass) {
|
|
|
37
38
|
pass.classifierRound = attributed;
|
|
38
39
|
}
|
|
39
40
|
if ((pass.decision.action === "allow" || pass.decision.action === "ask") && pass.decision.updatedInput !== undefined) {
|
|
40
|
-
pass.policyRewrite = pass.decision.updatedInput;
|
|
41
|
+
pass.policyRewrite = argsAsTheToolReads(pass.req, pass.decision.updatedInput);
|
|
41
42
|
}
|
|
42
43
|
else if (pass.hookAsk?.updatedInput !== undefined) {
|
|
43
|
-
pass.policyRewrite = pass.hookAsk.updatedInput;
|
|
44
|
+
pass.policyRewrite = argsAsTheToolReads(pass.req, pass.hookAsk.updatedInput);
|
|
44
45
|
}
|
|
45
46
|
if (pass.hookAsk !== undefined && pass.decision.action !== "deny") {
|
|
46
47
|
pass.decision = foldHookAsk(pass.decision, pass.hookAsk);
|
|
@@ -164,8 +165,16 @@ export async function runGateFold(pass) {
|
|
|
164
165
|
pass.deniedBy = "write_protection";
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
|
-
if (
|
|
168
|
-
|
|
168
|
+
if (pass.decision.action !== "deny" && input.crossBoundaryCheck?.obligation({ toolName, args: pass.policyRewrite !== undefined ? pass.policyRewrite : pass.currentInput, toolCallId }).mandate === true) {
|
|
169
|
+
const marks = { requiresRealApproval: true, crossBoundaryMandated: true };
|
|
170
|
+
if (pass.decision.action === "ask")
|
|
171
|
+
pass.decision = { ...pass.decision, ...marks };
|
|
172
|
+
else
|
|
173
|
+
[pass.decision, pass.tightenedBy] = [{ action: "ask", message: `tool "${toolName}" crosses the device boundary of a run that executes on a target device — a person must confirm it`, decisionReason: "safety", ...marks }, "safety"];
|
|
174
|
+
}
|
|
175
|
+
const unstatedRuns = pass.policyRewrite !== undefined ? pass.policyRewrite : pass.currentInput;
|
|
176
|
+
if (asksUnstated(pass.decision, pass.req, unstatedRuns, permissionSeatAt(input, unstatedRuns)?.seat, input.permissionMode?.())) {
|
|
177
|
+
pass.decision = { action: "ask", message: permissionSeatAt(input, unstatedRuns)?.question ?? unstatedAskMessage(toolName), ...(pass.policyRewrite !== undefined ? { updatedInput: pass.policyRewrite } : {}) };
|
|
169
178
|
pass.tightenedBy = "unstated";
|
|
170
179
|
}
|
|
171
180
|
return await pass.afterFold(pass);
|