@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/tool-policy.js
CHANGED
|
@@ -19,7 +19,8 @@ import { egressText, egressThrownText } from "./untrusted-egress.js";
|
|
|
19
19
|
import { assertNoRetiredToolPolicyKeys, RETIRED_DECISION_MEMBERS } from "./retired-keys.js";
|
|
20
20
|
import { isEngineRefusal, nestedRecordsOf, receiveContract, receiveNestedRecords, refusedOutOfContract, screenContractValues } from "./decision-receipt.js";
|
|
21
21
|
export { isEngineRefusal } from "./decision-receipt.js";
|
|
22
|
-
import { isNamespacedCoveringRuleName, namespacedRuleNameCovers
|
|
22
|
+
import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "./permission-rules.js";
|
|
23
|
+
import { ruleSpellingOf } from "./permission-rule-syntax.js";
|
|
23
24
|
import { protocolOf } from "./protocol-table.js";
|
|
24
25
|
import { anchorSpelling, isAbsoluteForFamily, normalizeAbsPathLexically, pathFamilyOf, writeTargetPath } from "../tools/fs/safety.js";
|
|
25
26
|
import { KNOWN_SAFE_ROOTS, removalReadingOf } from "../tools/fs/removal-targets.js";
|
|
@@ -176,6 +177,9 @@ export function namespacedCoveringEntries(entries) {
|
|
|
176
177
|
export function namespacedCoveringHit(covering, call) {
|
|
177
178
|
return covering.length > 0 && nameListHolds({ has: (name) => covering.some((e) => namespacedRuleNameCovers(e, name)) }, call);
|
|
178
179
|
}
|
|
180
|
+
export function projectionToolNames(c) {
|
|
181
|
+
return c.kind === "shell_command" ? { member: "tools", list: c.tools } : { member: "names", list: c.names };
|
|
182
|
+
}
|
|
179
183
|
export function checkToolPolicyProjection(projection, req) {
|
|
180
184
|
const listed = (list) => heldBy("policy.projectionReplay", { has: (n) => list.includes(n) }, req);
|
|
181
185
|
for (const c of projection.components) {
|
|
@@ -305,6 +309,12 @@ export function refuseOutOfContractDecision(d, opts) {
|
|
|
305
309
|
return refusedOutOfContract(`a permission decision's members could not be detached from the layer that returned them (${detached.reason}) — ` +
|
|
306
310
|
`the engine keeps its own copy of what it read; denied fail-closed`);
|
|
307
311
|
}
|
|
312
|
+
const rewrite = detached.value.updatedInput;
|
|
313
|
+
const ownedRewrite = rewrite !== undefined ? ownedCopy(rewrite, "updatedInput") : undefined;
|
|
314
|
+
if (ownedRewrite !== undefined && !ownedRewrite.ok) {
|
|
315
|
+
return refusedOutOfContract(`a permission decision's members could not be detached from the layer that returned them (${ownedRewrite.reason}) — ` +
|
|
316
|
+
`the engine keeps its own copy of what it read; denied fail-closed`);
|
|
317
|
+
}
|
|
308
318
|
const receipt = Object.freeze(attestation !== undefined ? { ...detached.value, attestation } : detached.value);
|
|
309
319
|
for (const v of Object.values(receipt))
|
|
310
320
|
if (Array.isArray(v))
|
|
@@ -318,9 +328,6 @@ export function refuseOutOfContractDecision(d, opts) {
|
|
|
318
328
|
(hookSeam ? HOOK_RECEIPTS : ENGINE_RECEIPTS).add(receipt);
|
|
319
329
|
return receipt;
|
|
320
330
|
}
|
|
321
|
-
export function receiveHookResult(result) {
|
|
322
|
-
return refuseOutOfContractDecision(result, { reasonIsNonInput: true });
|
|
323
|
-
}
|
|
324
331
|
const DEADLINE_ELAPSED = Symbol("approval.deadline_elapsed");
|
|
325
332
|
function withTimeout(p, ms, onTimeout) {
|
|
326
333
|
if (ms === undefined) {
|
|
@@ -353,6 +360,7 @@ export function createAllowDenyPolicy(opts) {
|
|
|
353
360
|
if (entries === undefined)
|
|
354
361
|
return undefined;
|
|
355
362
|
const kept = [];
|
|
363
|
+
const seen = new Set();
|
|
356
364
|
for (const entry of entries) {
|
|
357
365
|
const ns = protocolOf(entry);
|
|
358
366
|
if (ns !== undefined) {
|
|
@@ -367,8 +375,23 @@ export function createAllowDenyPolicy(opts) {
|
|
|
367
375
|
continue;
|
|
368
376
|
}
|
|
369
377
|
}
|
|
370
|
-
|
|
371
|
-
|
|
378
|
+
const spelled = ruleSpellingOf(entry);
|
|
379
|
+
if (spelled === undefined) {
|
|
380
|
+
const lesson = `a spelling no tool name can have — the rule syntax reads no tool name in it, so a name set never names a tool by it. Fix the entry.`;
|
|
381
|
+
invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
if (spelled.ruleContent === undefined) {
|
|
385
|
+
if (spelled.toolName === "*" && list === "deny") {
|
|
386
|
+
const lesson = `the wildcard — \`*\` names no tool, and a deny entry reaches the tool it names, so this one would be kept and never match ` +
|
|
387
|
+
`(a deny that reads protective and denies nothing). Name the tools to deny; to leave a run no tools, write an empty allow list.`;
|
|
388
|
+
invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
if (!seen.has(spelled.toolName)) {
|
|
392
|
+
seen.add(spelled.toolName);
|
|
393
|
+
kept.push(spelled.toolName);
|
|
394
|
+
}
|
|
372
395
|
continue;
|
|
373
396
|
}
|
|
374
397
|
const lesson = `a rule CONTENT form, not a tool name — a name set matches raw tool names, so this entry ` +
|
|
@@ -562,7 +585,7 @@ export function combinePolicies(...policies) {
|
|
|
562
585
|
...carriedMembersOf(folded),
|
|
563
586
|
async check(req, signal) {
|
|
564
587
|
let asked;
|
|
565
|
-
let current = req;
|
|
588
|
+
let current = Object.freeze({ ...req });
|
|
566
589
|
let rewrite;
|
|
567
590
|
let stated;
|
|
568
591
|
let records;
|
|
@@ -574,7 +597,7 @@ export function combinePolicies(...policies) {
|
|
|
574
597
|
let authoredBySeen = false;
|
|
575
598
|
const contributors = [];
|
|
576
599
|
const settleDeny = (d) => {
|
|
577
|
-
const out = rewrite
|
|
600
|
+
const out = rewrite !== undefined ? refusalOf(d, current.args) : d;
|
|
578
601
|
if (records === undefined)
|
|
579
602
|
return out;
|
|
580
603
|
return { ...out, attestation: mergeAttestation(req, records, d.attestation) };
|
|
@@ -590,7 +613,7 @@ export function combinePolicies(...policies) {
|
|
|
590
613
|
}
|
|
591
614
|
if (d.updatedInput !== undefined) {
|
|
592
615
|
const reread = withArgsReading(current, d.updatedInput, signal);
|
|
593
|
-
current = reread !== undefined ? await reread : { ...current, args: d.updatedInput };
|
|
616
|
+
current = Object.freeze(reread !== undefined ? await reread : { ...current, args: d.updatedInput });
|
|
594
617
|
rewrite = d;
|
|
595
618
|
stated = d.action === "allow" ? d.decisionReason : undefined;
|
|
596
619
|
}
|
|
@@ -871,6 +894,48 @@ export function tryCloneArgs(v) {
|
|
|
871
894
|
return { ok: false, reason: describeThrown(err), cause: err };
|
|
872
895
|
}
|
|
873
896
|
}
|
|
897
|
+
export function refusalOf(deny, judged) {
|
|
898
|
+
return deny.action !== "deny" || deny.updatedInput !== undefined ? deny : { ...deny, updatedInput: judged };
|
|
899
|
+
}
|
|
900
|
+
export function foldHookAsk(verdict, hookAsk) {
|
|
901
|
+
if (verdict.action === "deny")
|
|
902
|
+
return verdict;
|
|
903
|
+
const mandate = hookAsk.requiresRealApproval === true ? { requiresRealApproval: true } : {};
|
|
904
|
+
if (verdict.action === "allow") {
|
|
905
|
+
return { action: "ask", ...(hookAsk.message !== undefined ? { message: hookAsk.message } : {}), decisionReason: "hook", ...mandate, ...(hookAsk.updatedInput !== undefined ? { updatedInput: hookAsk.updatedInput } : {}) };
|
|
906
|
+
}
|
|
907
|
+
const hookMessage = hookAsk.message;
|
|
908
|
+
const message = hookMessage !== undefined && hookMessage !== verdict.message ? `${verdict.message !== undefined ? `${verdict.message} ` : ""}(a PreToolUse hook also asks: ${hookMessage})` : verdict.message;
|
|
909
|
+
return { ...verdict, decisionReason: "hook", ...(message !== undefined ? { message } : {}), ...mandate };
|
|
910
|
+
}
|
|
911
|
+
const OWNED_ARGS = new WeakSet();
|
|
912
|
+
export function ownArgs(v, root = "args") {
|
|
913
|
+
if (v === null || (typeof v !== "object" && typeof v !== "function") || OWNED_ARGS.has(v))
|
|
914
|
+
return { ok: true, value: v };
|
|
915
|
+
const copy = tryCloneArgs(v);
|
|
916
|
+
return copy.ok ? ownedCopy(copy.value, root) : { ...copy, reason: `unclonable value: ${copy.reason}` };
|
|
917
|
+
}
|
|
918
|
+
function ownedCopy(fresh, root) {
|
|
919
|
+
const pending = [[fresh, root]];
|
|
920
|
+
for (let next = pending.pop(); next !== undefined; next = pending.pop()) {
|
|
921
|
+
const [x, at] = next;
|
|
922
|
+
if (typeof x !== "object" || x === null || Object.isFrozen(x))
|
|
923
|
+
continue;
|
|
924
|
+
const proto = Object.getPrototypeOf(x);
|
|
925
|
+
if (proto !== Object.prototype && proto !== Array.prototype && proto !== null) {
|
|
926
|
+
return { ok: false, reason: `${inlineUntrusted(at, 200)} is a ${Object.prototype.toString.call(x).slice(8, -1)}, whose contents cannot be made immutable — args are plain data` };
|
|
927
|
+
}
|
|
928
|
+
Object.freeze(x);
|
|
929
|
+
for (const key of Reflect.ownKeys(x)) {
|
|
930
|
+
const d = Object.getOwnPropertyDescriptor(x, key);
|
|
931
|
+
if (d !== undefined && "value" in d)
|
|
932
|
+
pending.push([d.value, Array.isArray(x) ? `${at}[${String(key)}]` : `${at}.${String(key)}`]);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
if (typeof fresh === "object" && fresh !== null)
|
|
936
|
+
OWNED_ARGS.add(fresh);
|
|
937
|
+
return { ok: true, value: fresh };
|
|
938
|
+
}
|
|
874
939
|
export function describeThrown(err) {
|
|
875
940
|
const contained = containThrownText(egressThrownText("same-principal", err));
|
|
876
941
|
if (contained !== "")
|
|
@@ -1127,7 +1192,7 @@ function readApproverOutcomeObject(ok, toolName, editLane) {
|
|
|
1127
1192
|
`re-adjudication an approver's edit gets; denied fail-closed (approve or refuse what was shown, and route edits ` +
|
|
1128
1193
|
`through the run's approver seat)`, settledByNobody("approver_contract"));
|
|
1129
1194
|
}
|
|
1130
|
-
const edit =
|
|
1195
|
+
const edit = ownArgs(suppliedEdit);
|
|
1131
1196
|
if (!edit.ok) {
|
|
1132
1197
|
return refused(`the approved edit for "${toolName}" is not safely clonable (${edit.reason}) — denied fail-closed`, settledByNobody("presentation_failed"));
|
|
1133
1198
|
}
|
|
@@ -1150,11 +1215,11 @@ async function resolveAskArms(req, onAsk, signal, onLateSettlement) {
|
|
|
1150
1215
|
if (signal?.aborted) {
|
|
1151
1216
|
return { action: "deny", message: `approval aborted for "${req.toolName}" (run or turn interrupted)`, decisionReason: "mode", settlement: settledByNobody("task_aborted") };
|
|
1152
1217
|
}
|
|
1153
|
-
const presented =
|
|
1218
|
+
const presented = ownArgs(req.args);
|
|
1154
1219
|
if (!presented.ok) {
|
|
1155
1220
|
return {
|
|
1156
1221
|
action: "deny",
|
|
1157
|
-
message: `approval for "${req.toolName}" could not present the args safely (
|
|
1222
|
+
message: `approval for "${req.toolName}" could not present the args safely (${presented.reason}) — denied fail-closed`,
|
|
1158
1223
|
decisionReason: "mode",
|
|
1159
1224
|
settlement: settledByNobody("presentation_failed"),
|
|
1160
1225
|
};
|
|
@@ -88,6 +88,26 @@ export declare function pathTargetValue(args: unknown, pt: {
|
|
|
88
88
|
param: string;
|
|
89
89
|
aliases?: readonly string[];
|
|
90
90
|
}): string | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* CC parity: Read/Edit/Write take the file path as `file_path`. Read the target the same way
|
|
93
|
+
* EVERYWHERE the path is consumed from a tool-call's args — not just the tool body but ALSO every gate that
|
|
94
|
+
* extracts the write target to confine it (sensitive-path, session allowDirs, the fs-write gate). A gate that only
|
|
95
|
+
* read `args.path` would see `undefined` for a `file_path` call and either fail-OPEN (circumvent the guard — a real
|
|
96
|
+
* hole) or fail-closed (deny a legitimate write). Single source.
|
|
97
|
+
*
|
|
98
|
+
* The `path` arm is deliberately BROADER than what Read/Edit/Write accept: their schema requires
|
|
99
|
+
* `file_path` (fs-shared.ts FILE_PATH_PARAMS; Write alone repairs the `path` spelling onto it BEFORE validation,
|
|
100
|
+
* `coerceWriteArguments`, so a gate never sees the alias there), but this reader is
|
|
101
|
+
* shared with gates that judge OTHER tool vocabularies — Glob's real `path` parameter, deployment-authored tools —
|
|
102
|
+
* and a gate must never see LESS than the tool it is confining might act on. So the asymmetry is the design: the
|
|
103
|
+
* schema decides what a caller may send, this decides what gets judged, and this side over-reads on purpose.
|
|
104
|
+
*
|
|
105
|
+
* `file_path` wins; an empty/non-string `file_path` falls back to `path` (NOT an alias for Read/Edit/Write, whose
|
|
106
|
+
* schema requires `file_path`). Empty string ⇒ undefined (treated as "no path") so every caller's `=== undefined`
|
|
107
|
+
* check is sufficient — no separate length-0 guard needed. It lives beside {@link pathTargetValue} and is that
|
|
108
|
+
* reader over the one slot above: the engine's compaction metadata reads it too, and the engine never imports tools/.
|
|
109
|
+
*/
|
|
110
|
+
export declare function fileArgPath(args: unknown): string | undefined;
|
|
91
111
|
/** The path target of a wire name — the FIRST definition's (every definition under one name declares
|
|
92
112
|
* the same target; the conformance test pins that). */
|
|
93
113
|
/** A gated call as every fence sees it: the wire name, the args, and the OBJECT face a prepared leg stamped on the
|
|
@@ -85,6 +85,10 @@ export function pathTargetValue(args, pt) {
|
|
|
85
85
|
}
|
|
86
86
|
return undefined;
|
|
87
87
|
}
|
|
88
|
+
const FILE_ARG_PATH_TARGET = { param: "file_path", aliases: ["path"] };
|
|
89
|
+
export function fileArgPath(args) {
|
|
90
|
+
return pathTargetValue(args, FILE_ARG_PATH_TARGET);
|
|
91
|
+
}
|
|
88
92
|
export function protectivePathTargetOf(call) {
|
|
89
93
|
if (call.face?.pathTarget !== undefined)
|
|
90
94
|
return call.face.pathTarget;
|
package/dist/core/tool-spec.d.ts
CHANGED
|
@@ -121,10 +121,14 @@ export interface ReadRootGrantCandidate {
|
|
|
121
121
|
}
|
|
122
122
|
export interface ToolSpec<TParams extends TSchema = TSchema> {
|
|
123
123
|
/**
|
|
124
|
-
* Model-facing tool name.
|
|
125
|
-
* (`
|
|
126
|
-
*
|
|
127
|
-
*
|
|
124
|
+
* Model-facing tool name. It keeps the caller tool name contract (`caller-tool-name.ts`), judged at prepare-time — a
|
|
125
|
+
* name that breaks it is refused there (`config.tool_name_invalid`) and the run does not start:
|
|
126
|
+
* - it is a name a rule can name: ASCII letters, digits and `_ - . : *`, starting with a letter, a digit or `_`, not
|
|
127
|
+
* ending with `.` or `:`, and not the lone wildcard `*` — so every allow / deny list can name the tool (a leading `-`,
|
|
128
|
+
* a character outside ASCII, a blank or an empty name is refused);
|
|
129
|
+
* - it does not contain `__` — that separator is reserved by the PROTOCOL TABLE (`protocol-table.ts`), the umbrella over
|
|
130
|
+
* every namespaced family the engine speaks: `mcp__<server>__<tool>`, `a2a__<peer>__<skill>`, and whatever a third
|
|
131
|
+
* protocol appends.
|
|
128
132
|
*
|
|
129
133
|
* The live reason (not the retired durable-resume name shim, RB-476-A): every table-driven site — the
|
|
130
134
|
* namespace `parse`, the grouped display key, the permission-rule lanes, the tool-manifest origin
|
|
@@ -136,7 +140,7 @@ export interface ToolSpec<TParams extends TSchema = TSchema> {
|
|
|
136
140
|
/**
|
|
137
141
|
* Backward-compatible model-facing names that should dispatch to this tool. New transcripts and tool rosters
|
|
138
142
|
* should use {@link name}; aliases exist only so old model calls / SDK payloads / resumed sessions don't strand
|
|
139
|
-
* across a canonical rename.
|
|
143
|
+
* across a canonical rename. Each alias keeps the same contract as {@link name} (a rule naming an alias reaches the tool).
|
|
140
144
|
*/
|
|
141
145
|
aliases?: string[];
|
|
142
146
|
description: string;
|
|
@@ -711,7 +715,7 @@ export interface ToolExecuteContext {
|
|
|
711
715
|
* PreToolUse SCREENING entry (issue #33), whose policy the engine mints. Rebuild it with the
|
|
712
716
|
* exported `createPreToolUseConstraintPolicy(hook, env)` — same callback, same installed env —
|
|
713
717
|
* or the chain handed back here will be short and rejected on the count check. A face that only
|
|
714
|
-
* observes should
|
|
718
|
+
* observes should be declared `{ observe: true }` instead, and then never enters the chain
|
|
715
719
|
* at all; a park under a screening entry announces the requirement on `onError`
|
|
716
720
|
* (classification `screening-constraint-in-durable-chain`) at park time.
|
|
717
721
|
*/
|
package/dist/core/tools.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Value } from "typebox/value";
|
|
|
2
2
|
import { formatToolError, formatZodValidationError } from "./tool-errors.js";
|
|
3
3
|
import { readMember } from "./thrown-value.js";
|
|
4
4
|
import { frozenToolSpec } from "./tool-spec-members.js";
|
|
5
|
+
import { carryDelegationName } from "./delegation-name.js";
|
|
5
6
|
import { attachToolContract } from "../prompt-assembly/tool-catalog.js";
|
|
6
7
|
function normalizeContent(ret) {
|
|
7
8
|
if (typeof ret === "string") {
|
|
@@ -135,6 +136,7 @@ function buildProduct(spec, owner, options) {
|
|
|
135
136
|
}
|
|
136
137
|
},
|
|
137
138
|
};
|
|
139
|
+
carryDelegationName(spec.execute, tool.execute);
|
|
138
140
|
if (spec.contract) {
|
|
139
141
|
attachToolContract(tool, {
|
|
140
142
|
contractId: spec.contract.contractId,
|
package/dist/core/trace.d.ts
CHANGED
|
@@ -19,6 +19,44 @@
|
|
|
19
19
|
import type { BrainRetryErrClass, TaskStatus, ToolEffect } from "./types.js";
|
|
20
20
|
import type { ThinkingLevel } from "../internal/harness-types.js";
|
|
21
21
|
import type { ToolManifestRow } from "../prompt-assembly/tool-catalog.js";
|
|
22
|
+
import type { PromptEpochActivation, PromptIdentityLayers } from "../prompt-assembly/epoch.js";
|
|
23
|
+
import type { ChainLink, SupersededOverlay } from "../prompt-assembly/overlay.js";
|
|
24
|
+
import type { HostForm, HostRole, RendererId } from "../prompt-assembly/catalog/schema.js";
|
|
25
|
+
/** The run's prompt identity as the manifest reports it: the identity digest, its inputs, and the session record that
|
|
26
|
+
* names it (the record's counter and how it came to be). */
|
|
27
|
+
export interface PromptManifestIdentity {
|
|
28
|
+
artifact: string;
|
|
29
|
+
layers: PromptIdentityLayers;
|
|
30
|
+
epoch: number;
|
|
31
|
+
activatedBy: PromptEpochActivation;
|
|
32
|
+
}
|
|
33
|
+
/** The run's selector values — the plain form of the identity's `binding` element. */
|
|
34
|
+
export interface PromptManifestSelectors {
|
|
35
|
+
binding?: string;
|
|
36
|
+
traits: string[];
|
|
37
|
+
host: {
|
|
38
|
+
role: HostRole;
|
|
39
|
+
form: HostForm;
|
|
40
|
+
};
|
|
41
|
+
facts: Record<string, boolean>;
|
|
42
|
+
}
|
|
43
|
+
/** One rendered section: where it sits, which variant and renderer made it, whose text it carries (`locale`: the
|
|
44
|
+
* catalog's canonical text, or text an overlay author wrote), its content digest (`sha256:` unsalted for published
|
|
45
|
+
* text, `salted:` for text carrying the task's or the run's own inputs) and its history (`chain`). */
|
|
46
|
+
export interface PromptManifestSection {
|
|
47
|
+
id: string;
|
|
48
|
+
band: string;
|
|
49
|
+
rank: number;
|
|
50
|
+
variant?: string;
|
|
51
|
+
renderer?: {
|
|
52
|
+
id: RendererId;
|
|
53
|
+
version: number;
|
|
54
|
+
};
|
|
55
|
+
chars: number;
|
|
56
|
+
locale: "canonical" | "overlay";
|
|
57
|
+
contentHash: string;
|
|
58
|
+
chain: ChainLink[];
|
|
59
|
+
}
|
|
22
60
|
/**
|
|
23
61
|
* R4 (1.285): the scalar face of `TaskResult.stats.mechanisms`, echoed on `task.end` so "did the
|
|
24
62
|
* engine machinery fire" is answerable from the trace alone. Counters/flags only —
|
|
@@ -82,46 +120,27 @@ export type TraceEvent = {
|
|
|
82
120
|
ts: number;
|
|
83
121
|
} | {
|
|
84
122
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* (block ids + sizes + short content hashes — never prompt text, per the file-header privacy rule).
|
|
123
|
+
* The labelled composition of the assembled system prompt (manifest v3), emitted once right after `task.start`:
|
|
124
|
+
* which prompt this is (the identity and its selector values), which blocks and sections composed it, and where
|
|
125
|
+
* each section's text came from (its chain of overlays, the superseded ones marked). Metadata-only — ids, sizes
|
|
126
|
+
* and digests, never prompt text (the file-header privacy rule).
|
|
90
127
|
*/
|
|
91
128
|
kind: "prompt.assembled";
|
|
92
|
-
version:
|
|
129
|
+
version: 3;
|
|
93
130
|
taskId: string;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
* `env.context`, `memory.tail`), size in chars, sha256-prefix content hash. [c209-C]:
|
|
99
|
-
* `skills.block` is GONE — the skills listing left the stable prefix for the skills_listing
|
|
100
|
-
* reminder frame (observable via `steering_injected` source "skills_listing"). */
|
|
131
|
+
identity: PromptManifestIdentity;
|
|
132
|
+
selectors: PromptManifestSelectors;
|
|
133
|
+
/** Ordered blocks: stable id (e.g. `role.base`, `harness.context`, `memory.safety`, `env.context`,
|
|
134
|
+
* `memory.tail`), size in chars, salted short content hash — the block-view id wordlist is a downstream contract. */
|
|
101
135
|
blocks: Array<{
|
|
102
136
|
id: string;
|
|
103
137
|
chars: number;
|
|
104
138
|
hash: string;
|
|
105
139
|
}>;
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
*
|
|
109
|
-
|
|
110
|
-
* Absent on the legacy free-form provider path (single opaque block, no section structure).
|
|
111
|
-
* `contentHash` (digest tiering): UNSALTED full sha256, present ONLY on
|
|
112
|
-
* operator-declared sections (typed `stableBlocks` lane) — the center-publish ↔ manifest
|
|
113
|
-
* reconciliation anchor. Core-native sections stay salted-only (`hash`).
|
|
114
|
-
*/
|
|
115
|
-
sections?: Array<{
|
|
116
|
-
id: string;
|
|
117
|
-
slot: string;
|
|
118
|
-
carrier: string;
|
|
119
|
-
cadence: string;
|
|
120
|
-
cacheClass: string;
|
|
121
|
-
chars: number;
|
|
122
|
-
hash: string;
|
|
123
|
-
contentHash?: string;
|
|
124
|
-
}>;
|
|
140
|
+
sections: PromptManifestSection[];
|
|
141
|
+
/** Every overlay the composition superseded (a later one on the same target won, or it changed nothing this
|
|
142
|
+
* run); absent when none was. */
|
|
143
|
+
superseded?: SupersededOverlay[];
|
|
125
144
|
/**
|
|
126
145
|
* S2 (additive): the mounted tools plane — per-tool contract identity, durable-replay
|
|
127
146
|
* aliases, presentation-invariant shape digest and full wire-schema digest (initial mount face;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UNC under the win family: two leading separators, a host, a share — either separator, as `path.win32`
|
|
3
|
+
* reads it. The ONE UNC recognizer behind `isAbsoluteForFamily`, `pathIdentityOf` and `joinForFamily`
|
|
4
|
+
* (tools/fs/safety.ts), the symlink-chain reader (core/path-identity.ts) and the engine's own chain walk
|
|
5
|
+
* (engine/execution-env/symlink-chain.ts).
|
|
6
|
+
*
|
|
7
|
+
* A pure spelling test with no dependency, so the engine layer and the tools layer both read it from here:
|
|
8
|
+
* the engine never imports tools/, and tools reach the engine only through the `internal/harness` facade.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isUncSpelling(p: string): boolean;
|
|
@@ -34,6 +34,14 @@ export declare function egressText<T extends EgressTier>(tier: T, text: string,
|
|
|
34
34
|
export declare function egressThrownText<T extends EgressTier>(tier: T, err: unknown): Egress<T>;
|
|
35
35
|
/** The `same-principal` tier's pass, under the name hosts call it by (the engine calls {@link egressText}). */
|
|
36
36
|
export declare function redactSecrets(s: string, report?: RedactionReport): Egress<"same-principal">;
|
|
37
|
+
/**
|
|
38
|
+
* An extension's own words — its registration name, a bus reason, a key it wrote — made fit for an operator line: the
|
|
39
|
+
* `same-principal` egress pass first, then one line and bounded. The pass runs before the cut, so a cut never leaves part
|
|
40
|
+
* of a credential the pass would have recognised whole. Every station sentence that carries such words reads them here.
|
|
41
|
+
* It lives beside the pass, not in the stations module: a value import of the stations graph from a station's consumer
|
|
42
|
+
* closed a load-order cycle through the fs tools' barrel (an export the barrel copied before it existed).
|
|
43
|
+
*/
|
|
44
|
+
export declare function extensionWords(s: string, max: number): string;
|
|
37
45
|
/** The `human` tier's pass, under the name hosts call it by (the engine calls {@link egressText}). */
|
|
38
46
|
export declare function redactHostLeaks(s: string, report?: RedactionReport): Egress<"human">;
|
|
39
47
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { delimitUntrusted, neutralizeForFence } from "./untrusted-text.js";
|
|
1
|
+
import { delimitUntrusted, inlineUntrusted, neutralizeForFence } from "./untrusted-text.js";
|
|
2
2
|
import { egressPasses, runRedactionPasses } from "./redaction-passes.js";
|
|
3
3
|
import { CREDENTIAL_VOCABULARY, egressPassGroups, isSensitiveRecordKey, URI_SCHEME_SOURCE } from "./credential-vocabulary.js";
|
|
4
4
|
import { isErrorLike, readMember, thrownText } from "./thrown-value.js";
|
|
@@ -34,6 +34,9 @@ export function egressThrownText(tier, err) {
|
|
|
34
34
|
export function redactSecrets(s, report) {
|
|
35
35
|
return egressText("same-principal", s, report);
|
|
36
36
|
}
|
|
37
|
+
export function extensionWords(s, max) {
|
|
38
|
+
return inlineUntrusted(egressText("same-principal", s), max);
|
|
39
|
+
}
|
|
37
40
|
export function redactHostLeaks(s, report) {
|
|
38
41
|
return egressText("human", s, report);
|
|
39
42
|
}
|
|
@@ -27,6 +27,7 @@ import type { HumanInputAttachment } from "./task-event.js";
|
|
|
27
27
|
import { type ModelFileReader } from "../tools/fs/fs-read.js";
|
|
28
28
|
import type { SyntheticReadJudge } from "./synthetic-read-verdict.js";
|
|
29
29
|
import { type ReminderDisclosureCounts } from "./reminder-disclosure.js";
|
|
30
|
+
import type { ContextWindowOverlay } from "./context-settings.js";
|
|
30
31
|
/** At most this many attachments on one objective. */
|
|
31
32
|
export declare const USER_ATTACHMENTS_MAX = 20;
|
|
32
33
|
/** The longest path or name an entry may carry (the platform path limit). */
|
|
@@ -133,9 +134,18 @@ export interface ReadUserAttachmentsInput {
|
|
|
133
134
|
* frame carries the commit its delivery owes, run only when the frame is in the transcript.
|
|
134
135
|
*/
|
|
135
136
|
export declare function readUserAttachments(input: ReadUserAttachmentsInput): Promise<MintedAttachmentFrame[]>;
|
|
137
|
+
/** The objective as the window check sees it: a reader of the live overlay over the model's window declarations (the
|
|
138
|
+
* same seat the request guard reads) and the objective text's length — it rides the first request ahead of the
|
|
139
|
+
* frames. The overlay is a GETTER because it is read when the frames exist, not when the call is made: the reads are
|
|
140
|
+
* asynchronous and a deployment may swap its window declarations meanwhile, as it may before any request. */
|
|
141
|
+
export interface AttachmentWindowInput {
|
|
142
|
+
readonly overlay: () => ContextWindowOverlay | undefined;
|
|
143
|
+
readonly objectiveChars: number;
|
|
144
|
+
}
|
|
136
145
|
/** The objective lane's read: once the UserPromptSubmit hook let the objective through (a blocked objective reads
|
|
137
|
-
* nothing), and before the pre-call gate, which prices the frames (`chars`).
|
|
138
|
-
|
|
146
|
+
* nothing), and before the pre-call gate, which prices the frames (`chars`). Refuses the whole objective when the frames
|
|
147
|
+
* and the objective cannot ride one request ({@link refuseFramesOverWindow}). Commits nothing. */
|
|
148
|
+
export declare function readObjectiveAttachments(prepared: Pick<import("./runner/contracts.js").Prepared, "userAttachments" | "modelFileReader" | "syntheticReadVerdict" | "cwdRef" | "reminderMark" | "reminderDisclosureCounts" | "abortController" | "harness">, inputId: string, blocked: boolean, window: AttachmentWindowInput): Promise<{
|
|
139
149
|
frames: MintedAttachmentFrame[];
|
|
140
150
|
chars: number;
|
|
141
151
|
}>;
|
|
@@ -3,10 +3,12 @@ import { READ_OUTCOMES } from "../tools/fs/fs-read.js";
|
|
|
3
3
|
import { renderDirectoryListing } from "../tools/fs/dir-entries.js";
|
|
4
4
|
import { MAX_READ_OUTPUT_CHARS } from "../tools/fs/fs-shared.js";
|
|
5
5
|
import { normalizeFileText } from "../tools/fs/encoding.js";
|
|
6
|
-
import { ADMITTED_IMAGE_MIME_TYPES, admitImageBytes } from "
|
|
6
|
+
import { ADMITTED_IMAGE_MIME_TYPES, admitImageBytes } from "./image-admission.js";
|
|
7
7
|
import { PDF_MAX_PAGES_PER_READ } from "../tools/fs/pdf.js";
|
|
8
8
|
import { MARKED_BLOCK_AFTER_DATA, mintSystemReminder } from "./reminder-mint.js";
|
|
9
9
|
import { commitReminderDisclosureEffects, planReminderDisclosure } from "./reminder-disclosure.js";
|
|
10
|
+
import { DEFAULT_CHARS_PER_TOKEN, estimateTokens } from "../internal/harness.js";
|
|
11
|
+
import { guardBudget } from "./context-guard.js";
|
|
10
12
|
export const USER_ATTACHMENTS_MAX = 20;
|
|
11
13
|
export const USER_ATTACHMENT_LABEL_MAX = 4096;
|
|
12
14
|
export const USER_ATTACHMENT_KINDS = Object.freeze(["text", "notebook", "image", "pdf", "directory", "client_text", "client_image"]);
|
|
@@ -383,7 +385,19 @@ function mintFrame(r, at, seat) {
|
|
|
383
385
|
const commit = result !== undefined || extra.length > 0 ? () => seat.commit(result, extra) : undefined;
|
|
384
386
|
return { seed: { content, attachment }, ...(commit !== undefined ? { commit } : {}) };
|
|
385
387
|
}
|
|
386
|
-
|
|
388
|
+
function refuseFramesOverWindow(frames, model, window) {
|
|
389
|
+
const budget = guardBudget(model, window.overlay());
|
|
390
|
+
if (!Number.isFinite(budget))
|
|
391
|
+
return;
|
|
392
|
+
const cpt = model.charsPerToken ?? DEFAULT_CHARS_PER_TOKEN;
|
|
393
|
+
const asMessage = (f) => ({ role: "user", content: [...f.seed.content], timestamp: 0 });
|
|
394
|
+
const tokens = frames.reduce((n, f) => n + estimateTokens(asMessage(f), cpt), 0) + Math.ceil(window.objectiveChars / cpt);
|
|
395
|
+
if (tokens <= budget)
|
|
396
|
+
return;
|
|
397
|
+
const n = frames.length;
|
|
398
|
+
throw userAttachmentRefusal(SEAT_FIELD, `the ${n} ${n === 1 ? "attachment" : "attachments"} and the objective come to about ${tokens} tokens, over the ${budget} tokens one request can hold on this model — to send it the engine would have to drop the objective or some of the attachments. Nothing was sent; attach fewer or smaller parts.`);
|
|
399
|
+
}
|
|
400
|
+
export async function readObjectiveAttachments(prepared, inputId, blocked, window) {
|
|
387
401
|
if (blocked || prepared.userAttachments === undefined)
|
|
388
402
|
return { frames: [], chars: 0 };
|
|
389
403
|
const frames = await readUserAttachments({
|
|
@@ -397,6 +411,7 @@ export async function readObjectiveAttachments(prepared, inputId, blocked) {
|
|
|
397
411
|
counts: prepared.reminderDisclosureCounts,
|
|
398
412
|
signal: prepared.abortController.signal,
|
|
399
413
|
});
|
|
414
|
+
refuseFramesOverWindow(frames, prepared.harness.getModel(), window);
|
|
400
415
|
return { frames, chars: frames.reduce((n, f) => n + f.seed.content.reduce((m, b) => m + (b.type === "text" ? b.text.length : 0), 0), 0) };
|
|
401
416
|
}
|
|
402
417
|
export function lastAttachmentFrameOf(entries, id) {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
import { type PermissionMode } from "./ask-origin.js";
|
|
24
24
|
import type { RunnerDeps, TaskSpec } from "./types.js";
|
|
25
25
|
import { type StoreDurability } from "./checkpoint-store.js";
|
|
26
|
-
import type {
|
|
26
|
+
import type { ModAdmissionRecord } from "./mods/kernel/index.js";
|
|
27
27
|
import type { McpDelivered, McpFailureKind, McpServerLiveness } from "./mcp-failure.js";
|
|
28
28
|
import type { WriteProtectionTargetView } from "./write-protect.js";
|
|
29
29
|
import type { OnAsk } from "./tool-policy.js";
|
|
@@ -180,7 +180,6 @@ export declare function deriveLspSeam(mounted: boolean, diagnosticsLive: boolean
|
|
|
180
180
|
* (`schemaVersion` bumps only on a semantic break of an EXISTING field). The TaskEvent face is the
|
|
181
181
|
* host/operator plane — the manifest never enters model context.
|
|
182
182
|
*/
|
|
183
|
-
export type { WiringManifestHookEntry };
|
|
184
183
|
export interface WiringManifest {
|
|
185
184
|
schemaVersion: 1;
|
|
186
185
|
/** Present on EFFECTIVE (per-leg) manifests only; the static half has no leg. */
|
|
@@ -356,14 +355,16 @@ export interface WiringManifest {
|
|
|
356
355
|
*/
|
|
357
356
|
tools?: import("./tool-roster.js").ToolRoster;
|
|
358
357
|
/**
|
|
359
|
-
* EFFECTIVE half only: the
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
358
|
+
* EFFECTIVE half only: the leg's mods admission — one record per registration of the two seats, in run order: a
|
|
359
|
+
* mounted one with the patterns it actually hung (`events`), the ones it declared observe-only (`observe`) and the
|
|
360
|
+
* judges skipped while it was judged (`skipped`), or a refused one with who refused it and why (`refusedBy`,
|
|
361
|
+
* `reason`). PRESENT IFF the leg has a registration — a deployment that wires none reports nothing here and its
|
|
362
|
+
* manifest (and {@link configFingerprint}) is byte-for-byte what it was. Absence reads as "this leg carries no
|
|
363
|
+
* registration", NOT as "no extension judges this leg's calls": a delegated child can still be screened by an
|
|
364
|
+
* ancestor's chain through the gate's constraint fold. EXCLUDED from {@link configFingerprint}: the task seat is a
|
|
365
|
+
* per-task seat, so one assembly's legs legitimately differ on it.
|
|
365
366
|
*/
|
|
366
|
-
|
|
367
|
+
mods?: readonly ModAdmissionRecord[];
|
|
367
368
|
/**
|
|
368
369
|
* EFFECTIVE half only: the LSP code-intelligence seam. PRESENT IFF a manager seat resolved
|
|
369
370
|
* (`spec.lspManager ?? deps.lspManager`); a deployment that wires none reports nothing (byte-for-byte
|
|
@@ -412,7 +413,7 @@ export interface WiringManifest {
|
|
|
412
413
|
* the engine's seats — the same fact `config.write_protection_target_view_absent` announces once per run
|
|
413
414
|
* when a covered write tool is mounted beside a `"spelling-only"` judge.
|
|
414
415
|
*
|
|
415
|
-
* IN the fingerprint below (unlike `tools`/`lsp`/`
|
|
416
|
+
* IN the fingerprint below (unlike `tools`/`lsp`/`mods`): which view the judge got is an ASSEMBLY fact
|
|
416
417
|
* — it follows the table seat and whether the deployment wired hands at all — so legs of one assembly
|
|
417
418
|
* agree on it, which is exactly the equality the fingerprint advertises.
|
|
418
419
|
*
|
|
@@ -466,7 +467,7 @@ export interface WiringManifest {
|
|
|
466
467
|
* `"on"` — it records (store wired, neither layer declared it off, a filesystem env mounted). `"disabled"` — it does
|
|
467
468
|
* not, whichever layer or missing half made it so (`TaskSpec.fileHistory`, `RunnerDeps.fileHistoryStore: "disabled"`, `RunnerDeps.fileHistoryCapture: "off"`,
|
|
468
469
|
* no store, no filesystem env); the host knows its own deployment seat. ABSENT = an older mint or an external
|
|
469
|
-
* derivation, never a state. Out of {@link configFingerprint}: the request word is a per-task seat (`
|
|
470
|
+
* derivation, never a state. Out of {@link configFingerprint}: the request word is a per-task seat (`mods` reasoning).
|
|
470
471
|
*/
|
|
471
472
|
fileHistory?: "on" | "disabled";
|
|
472
473
|
/** EFFECTIVE half only — a short, non-sensitive fingerprint (sha256 prefix over the canonical
|
|
@@ -544,8 +545,8 @@ export interface WiringFacts {
|
|
|
544
545
|
mcp?: readonly WiringManifestMcpEntry[];
|
|
545
546
|
/** Effective half only — the leg's minted tool roster (see {@link WiringManifest.tools}). */
|
|
546
547
|
tools?: import("./tool-roster.js").ToolRoster;
|
|
547
|
-
/** Effective half only — the
|
|
548
|
-
|
|
548
|
+
/** Effective half only — the leg's mods admission records ({@link WiringManifest.mods}); an empty array and an absent value derive the same thing (no section). */
|
|
549
|
+
mods?: readonly ModAdmissionRecord[];
|
|
549
550
|
/** Effective half only — the LSP seam ({@link WiringManifest.lsp}); absent ⇒ no manager wired. */
|
|
550
551
|
lsp?: {
|
|
551
552
|
mounted: boolean;
|
|
@@ -210,7 +210,7 @@ export function deriveWiringManifest(facts) {
|
|
|
210
210
|
...(facts.half === "effective" && facts.autoMode !== undefined ? { autoMode: readAutoModeFact(facts.autoMode) } : {}),
|
|
211
211
|
...(facts.half === "effective" && facts.mcp !== undefined ? { mcp: facts.mcp.map((e) => ({ ...e })) } : {}),
|
|
212
212
|
...(facts.half === "effective" && facts.tools !== undefined ? { tools: facts.tools } : {}),
|
|
213
|
-
...(facts.half === "effective" && facts.
|
|
213
|
+
...(facts.half === "effective" && facts.mods !== undefined && facts.mods.length > 0 ? { mods: [...facts.mods] } : {}),
|
|
214
214
|
...(facts.half === "effective" && facts.lsp !== undefined ? { lsp: { ...facts.lsp } } : {}),
|
|
215
215
|
...(facts.half === "effective" && facts.hands !== undefined ? { hands: readHandsFact(facts.hands) } : {}),
|
|
216
216
|
...(facts.half === "effective" && facts.permissionMode !== undefined ? { permissionMode: readPermissionModeFact(facts.permissionMode) } : {}),
|
|
@@ -226,7 +226,7 @@ export function deriveWiringManifest(facts) {
|
|
|
226
226
|
: {}),
|
|
227
227
|
};
|
|
228
228
|
if (facts.half === "effective") {
|
|
229
|
-
const { leg: _leg, mcp: _mcp, tools: _tools, lsp: _lsp,
|
|
229
|
+
const { leg: _leg, mcp: _mcp, tools: _tools, lsp: _lsp, mods: _mods, teamRole: _teamRole, peerPresence: _peerPresence, fileHistory: _fileHistory, permissionMode: _permissionMode, ...assembly } = manifest;
|
|
230
230
|
const { provenance: _askSeat, ...askForHash } = assembly.ask;
|
|
231
231
|
const { provenance: _questionSeat, ...questionForHash } = assembly.question;
|
|
232
232
|
manifest.configFingerprint = createHash("sha256")
|
|
@@ -2,8 +2,7 @@ import { renderUserAttachmentView, userAttachmentOf } from "../llm/index.js";
|
|
|
2
2
|
import { normalizeLlmMessageContent } from "../harness/messages.js";
|
|
3
3
|
import { sliceHeadSafe } from "../../core/surrogate-safe-slice.js";
|
|
4
4
|
import { cutEnginePrefix, cutEngineSegments, flattenableUserText } from "../../core/untrusted-text.js";
|
|
5
|
-
import { fileArgPath } from "../../
|
|
6
|
-
import { fileOpAccessOf } from "../../core/tool-registry.js";
|
|
5
|
+
import { fileArgPath, fileOpAccessOf } from "../../core/tool-registry.js";
|
|
7
6
|
export const DURABLE_HISTORY_NAMES = new Map([
|
|
8
7
|
["read", "read"],
|
|
9
8
|
["write", "create"],
|
|
@@ -112,9 +112,10 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
|
|
|
112
112
|
* fail-closed (drop secret-pattern keys, keep PATH/build/locale). `"all"` = full inherit (trusted env);
|
|
113
113
|
* `string[]` = strict allowlist. `shellEnv`/per-exec `env` always pass through. Any other value — an unknown
|
|
114
114
|
* word, a non-string, a list entry that is not a variable name — throws here (`inheritEnvPolicyProblem`'s
|
|
115
|
-
* reason), the same judgment the oracle gate's `inheritEnv` meets. Whatever the policy, the deployment's
|
|
116
|
-
*
|
|
117
|
-
* the
|
|
115
|
+
* reason), the same judgment the oracle gate's `inheritEnv` meets. Whatever the policy, the deployment's own
|
|
116
|
+
* credentials (`declareWithheldEnv`: by name, and by a value equal to a declared or engine-held credential value)
|
|
117
|
+
* are withheld from the inherited part; a list naming a declared name throws here when the declaration came
|
|
118
|
+
* first, and every spawn refuses it (`spawn_error` / `spawn_failed`) whenever it came. */
|
|
118
119
|
inheritEnv?: "all" | "scrub" | string[];
|
|
119
120
|
/** design/105: inject a resident scheduler daemon backend (the shell daemon). Absent ⇒ scheduling INERT. */
|
|
120
121
|
scheduler?: SchedulerCapability;
|