@sema-agent/core 7.47.0 → 7.49.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 +472 -0
- package/README.md +2 -2
- package/dist/agents/cascade.d.ts +2 -5
- package/dist/agents/child-failure.d.ts +20 -0
- package/dist/agents/child-failure.js +28 -0
- package/dist/agents/cross-session-ref.d.ts +11 -3
- package/dist/agents/cross-session-ref.js +6 -0
- package/dist/agents/cumulative-stats.d.ts +12 -15
- package/dist/agents/cumulative-stats.js +1 -1
- package/dist/agents/extra-tool-names.js +1 -1
- package/dist/agents/inherited-tool-pool.d.ts +17 -13
- package/dist/agents/inherited-tool-pool.js +4 -3
- package/dist/agents/peer-session-drain.d.ts +3 -2
- package/dist/agents/peer-session-drain.js +5 -4
- package/dist/agents/send-message-tool.js +2 -9
- package/dist/agents/subagent.d.ts +10 -29
- package/dist/agents/subagent.js +65 -53
- package/dist/agents/suspend-guard.d.ts +1 -1
- package/dist/agents/tool-filter.d.ts +76 -65
- package/dist/agents/tool-filter.js +122 -92
- package/dist/agents/verify.d.ts +4 -7
- package/dist/agents/verify.js +6 -7
- package/dist/bench/metrics.d.ts +1 -2
- package/dist/brain/anthropic.js +133 -79
- package/dist/brain/errors.d.ts +53 -6
- package/dist/brain/errors.js +22 -2
- package/dist/brain/input-too-long.d.ts +40 -19
- package/dist/brain/input-too-long.js +3 -16
- package/dist/brain/open-responses.js +19 -10
- package/dist/brain/openai.js +123 -32
- package/dist/brain/provider-dialect.d.ts +214 -0
- package/dist/brain/provider-dialect.js +186 -0
- package/dist/brain/request-params.d.ts +27 -8
- package/dist/brain/request-params.js +7 -12
- package/dist/brain/request-route.d.ts +84 -0
- package/dist/brain/request-route.js +41 -0
- package/dist/brain/retry.d.ts +8 -0
- package/dist/brain/retry.js +10 -4
- package/dist/brain/route-adjudicator.d.ts +7 -0
- package/dist/brain/route-adjudicator.js +5 -1
- package/dist/brain/status-sink.d.ts +20 -0
- package/dist/brain/status-sink.js +11 -0
- package/dist/brain/stream-engine.d.ts +52 -1
- package/dist/brain/stream-engine.js +81 -24
- package/dist/brain/stream-shared.d.ts +57 -11
- package/dist/brain/stream-shared.js +28 -2
- package/dist/core/a2a.d.ts +1 -0
- package/dist/core/agent-config-dir.js +3 -2
- package/dist/core/allow-entry.d.ts +21 -12
- package/dist/core/allow-entry.js +39 -32
- package/dist/core/arg-summary.d.ts +17 -24
- package/dist/core/arg-summary.js +169 -68
- package/dist/core/ask-origin.d.ts +42 -24
- package/dist/core/ask-origin.js +18 -13
- package/dist/core/auto-mode-prompt-assets.d.ts +2 -2
- package/dist/core/auto-mode-prompt-assets.js +1 -1
- package/dist/core/auto-mode-prompt.d.ts +11 -1
- package/dist/core/auto-mode-prompt.js +13 -10
- package/dist/core/auto-mode-rebuild.d.ts +7 -0
- package/dist/core/auto-mode-rebuild.js +4 -1
- package/dist/core/canonical-json.d.ts +3 -0
- package/dist/core/canonical-json.js +2 -1
- package/dist/core/checkpoint-requirements.d.ts +892 -0
- package/dist/core/checkpoint-requirements.js +333 -0
- package/dist/core/checkpoint-store.d.ts +95 -66
- package/dist/core/checkpoint-store.js +14 -26
- package/dist/core/child-clamp-seats.d.ts +228 -69
- package/dist/core/child-clamp-seats.js +211 -17
- package/dist/core/classifier-unavailable-arm.d.ts +5 -1
- package/dist/core/classifier-unavailable-arm.js +3 -3
- package/dist/core/compliance.d.ts +3 -0
- package/dist/core/compliance.js +9 -4
- package/dist/core/credential-vocabulary.d.ts +140 -0
- package/dist/core/credential-vocabulary.js +131 -0
- package/dist/core/decision-receipt.js +1 -1
- package/dist/core/effective-path-target.d.ts +73 -16
- package/dist/core/effective-path-target.js +63 -33
- package/dist/core/engine-notice.d.ts +32 -7
- package/dist/core/file-history-store.js +2 -2
- package/dist/core/fs-write-gate-policy.d.ts +4 -0
- package/dist/core/fs-write-gate-policy.js +22 -5
- package/dist/core/gate-bounded-await.d.ts +28 -13
- package/dist/core/gate-bounded-await.js +41 -4
- package/dist/core/gate-fold.d.ts +1 -1
- package/dist/core/gate-fold.js +24 -25
- package/dist/core/gate-lanes.js +16 -15
- package/dist/core/gate-outcome.d.ts +20 -5
- package/dist/core/gate-outcome.js +5 -0
- package/dist/core/governance-codes.d.ts +11 -4
- package/dist/core/governance-codes.js +14 -3
- package/dist/core/hooks.d.ts +4 -0
- package/dist/core/locked-config.d.ts +8 -0
- package/dist/core/locked-config.js +14 -2
- package/dist/core/lsp.js +3 -5
- package/dist/core/mailbox-store.d.ts +3 -4
- package/dist/core/mcp-connection-pool.d.ts +75 -0
- package/dist/core/mcp-connection-pool.js +128 -0
- package/dist/core/mcp-failure.d.ts +2 -1
- package/dist/core/mcp-failure.js +13 -2
- package/dist/core/mcp-server-spec.d.ts +1 -1
- package/dist/core/mcp.d.ts +4 -0
- package/dist/core/mcp.js +70 -43
- package/dist/core/memory-engine/content-origin.js +2 -14
- package/dist/core/memory-engine/engine.d.ts +32 -22
- package/dist/core/memory-engine/engine.js +103 -55
- package/dist/core/memory-engine/file-backend.d.ts +13 -30
- package/dist/core/memory-engine/file-backend.js +37 -252
- package/dist/core/memory-engine/index.d.ts +1 -1
- package/dist/core/memory-engine/index.js +1 -1
- package/dist/core/memory-engine/layout.d.ts +139 -9
- package/dist/core/memory-engine/layout.js +350 -7
- package/dist/core/memory-engine/scope-contract.d.ts +10 -0
- package/dist/core/memory-engine/scope-contract.js +8 -0
- package/dist/core/memory-engine/session-incarnation.d.ts +14 -4
- package/dist/core/memory-engine/session-incarnation.js +5 -2
- package/dist/core/memory-engine/types.d.ts +10 -1
- package/dist/core/memory.js +5 -17
- package/dist/core/model-seat.d.ts +4 -4
- package/dist/core/model-seat.js +1 -1
- package/dist/core/mounted-mcp.d.ts +57 -0
- package/dist/core/mounted-mcp.js +19 -0
- package/dist/core/namespaced-rule-name.d.ts +29 -0
- package/dist/core/namespaced-rule-name.js +52 -0
- package/dist/core/park-selfcheck.d.ts +1 -1
- package/dist/core/park-selfcheck.js +16 -6
- package/dist/core/path-guard-rows.d.ts +99 -0
- package/dist/core/path-guard-rows.js +45 -0
- package/dist/core/path-identity.d.ts +22 -16
- package/dist/core/path-identity.js +10 -10
- package/dist/core/path-rule-binding.d.ts +2 -1
- package/dist/core/path-rule-binding.js +3 -1
- package/dist/core/pause-registry.d.ts +16 -2
- package/dist/core/pause-registry.js +6 -0
- package/dist/core/permission-rule-consent.js +0 -7
- package/dist/core/permission-rule-model.d.ts +68 -24
- package/dist/core/permission-rule-model.js +105 -24
- package/dist/core/permission-rule-store.js +2 -2
- package/dist/core/permission-rules.d.ts +3 -30
- package/dist/core/permission-rules.js +4 -54
- package/dist/core/read-root-candidate.d.ts +1 -3
- package/dist/core/read-root-candidate.js +4 -15
- package/dist/core/real-approval.d.ts +4 -3
- package/dist/core/retired-keys.d.ts +13 -0
- package/dist/core/retired-keys.js +14 -0
- package/dist/core/roles.d.ts +2 -3
- package/dist/core/roles.js +15 -6
- package/dist/core/runner/assemble-result.d.ts +0 -7
- package/dist/core/runner/assemble-result.js +19 -31
- package/dist/core/runner/caller-roster.d.ts +78 -0
- package/dist/core/runner/caller-roster.js +219 -0
- package/dist/core/runner/checkpoint-scope.d.ts +16 -16
- package/dist/core/runner/checkpoint-scope.js +2 -2
- package/dist/core/runner/child-tree.js +2 -2
- package/dist/core/runner/contracts.d.ts +68 -35
- package/dist/core/runner/decide-continuation.d.ts +51 -3
- package/dist/core/runner/decide-continuation.js +76 -21
- package/dist/core/runner/denial-limit-arms.d.ts +17 -5
- package/dist/core/runner/denial-limit-arms.js +11 -9
- package/dist/core/runner/extra-body-dropped-seat.d.ts +8 -0
- package/dist/core/runner/extra-body-dropped-seat.js +22 -0
- package/dist/core/runner/finish-reason-seat.d.ts +9 -0
- package/dist/core/runner/finish-reason-seat.js +40 -0
- package/dist/core/runner/gate-exit.d.ts +44 -32
- package/dist/core/runner/gate-exit.js +112 -25
- package/dist/core/runner/inherited-ask-grants.js +6 -4
- package/dist/core/runner/mcp-redial.d.ts +3 -3
- package/dist/core/runner/mcp-redial.js +3 -4
- package/dist/core/runner/park-commit.d.ts +1 -1
- package/dist/core/runner/permission-rule-lanes.d.ts +1 -2
- package/dist/core/runner/permission-rule-lanes.js +5 -4
- package/dist/core/runner/prepare-artifact.d.ts +4 -0
- package/dist/core/runner/prepare-artifact.js +2 -1
- package/dist/core/runner/prepare-ask-lane.d.ts +2 -0
- package/dist/core/runner/prepare-ask-lane.js +12 -6
- package/dist/core/runner/prepare-boundary-parks.d.ts +5 -8
- package/dist/core/runner/prepare-boundary-parks.js +4 -7
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +11 -15
- package/dist/core/runner/prepare-caps-and-workflow.js +19 -27
- package/dist/core/runner/prepare-config-doors.d.ts +9 -9
- package/dist/core/runner/prepare-config-doors.js +10 -5
- package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
- package/dist/core/runner/prepare-defer-classify.js +5 -3
- package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
- package/dist/core/runner/prepare-delegation-surface.js +3 -3
- package/dist/core/runner/prepare-gate-stations.d.ts +4 -4
- package/dist/core/runner/prepare-gate-stations.js +9 -7
- package/dist/core/runner/prepare-hands-readface.d.ts +7 -7
- package/dist/core/runner/prepare-hands-readface.js +7 -7
- package/dist/core/runner/prepare-inherited-gate.d.ts +7 -6
- package/dist/core/runner/prepare-inherited-gate.js +14 -15
- package/dist/core/runner/prepare-listings.d.ts +7 -24
- package/dist/core/runner/prepare-listings.js +4 -5
- package/dist/core/runner/prepare-memory-engine-session.d.ts +2 -0
- package/dist/core/runner/prepare-memory-engine-session.js +4 -3
- package/dist/core/runner/prepare-memory.d.ts +6 -0
- package/dist/core/runner/prepare-memory.js +13 -13
- package/dist/core/runner/prepare-offload-wrappers.d.ts +5 -0
- package/dist/core/runner/prepare-offload-wrappers.js +3 -3
- package/dist/core/runner/prepare-park-ask.d.ts +7 -8
- package/dist/core/runner/prepare-park-ask.js +17 -10
- package/dist/core/runner/prepare-policy-chain.js +24 -44
- package/dist/core/runner/prepare-project-context.d.ts +1 -1
- package/dist/core/runner/prepare-project-context.js +3 -4
- package/dist/core/runner/prepare-protocol-tools.d.ts +9 -3
- package/dist/core/runner/prepare-protocol-tools.js +3 -4
- package/dist/core/runner/prepare-run-refs.d.ts +3 -0
- package/dist/core/runner/prepare-run-refs.js +2 -1
- package/dist/core/runner/prepare-safety-scan.d.ts +4 -8
- package/dist/core/runner/prepare-safety-scan.js +1 -2
- package/dist/core/runner/prepare-suspend-saga.d.ts +7 -1
- package/dist/core/runner/prepare-suspend-saga.js +28 -12
- package/dist/core/runner/prepare-task.d.ts +1 -1
- package/dist/core/runner/prepare-task.js +67 -56
- package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -10
- package/dist/core/runner/prepare-wiring-manifest.js +5 -8
- package/dist/core/runner/resume-apply.js +7 -14
- package/dist/core/runner/resume-checkpoint-screen.js +11 -4
- package/dist/core/runner/resume-internals-and-config.js +2 -2
- package/dist/core/runner/resume-policy-outcome.js +5 -32
- package/dist/core/runner/resume-review-outcome.js +4 -1
- package/dist/core/runner/retired-runner-deps.d.ts +6 -0
- package/dist/core/runner/retired-runner-deps.js +10 -1
- package/dist/core/runner/run-brain-sinks.d.ts +4 -0
- package/dist/core/runner/run-brain-sinks.js +5 -2
- package/dist/core/runner/run-harness-handlers.js +27 -34
- package/dist/core/runner/run-leg.d.ts +0 -2
- package/dist/core/runner/run-leg.js +32 -33
- package/dist/core/runner/run-terminal-adoption.js +4 -3
- package/dist/core/runner/runtask.js +8 -8
- package/dist/core/runner/session-rule-policy.js +5 -5
- package/dist/core/runner/stream-settle-backstop.js +7 -4
- package/dist/core/runner/sub-agent-deny-lists.d.ts +51 -12
- package/dist/core/runner/sub-agent-deny-lists.js +111 -80
- package/dist/core/runner/terminal-account.d.ts +48 -0
- package/dist/core/runner/terminal-account.js +186 -0
- package/dist/core/runner/tool-end-body.d.ts +54 -17
- package/dist/core/runner/tool-end-body.js +27 -2
- package/dist/core/runner/tool-face-overlay.d.ts +3 -1
- package/dist/core/runner/tool-face-overlay.js +6 -4
- package/dist/core/runner/tool-occurrence.d.ts +106 -0
- package/dist/core/runner/tool-occurrence.js +123 -0
- package/dist/core/runner/tool-progress-lane.d.ts +16 -8
- package/dist/core/runner/tool-progress-lane.js +25 -34
- package/dist/core/runner/turn-attachments.d.ts +1 -1
- package/dist/core/runner/write-protection-station.d.ts +21 -9
- package/dist/core/runner/write-protection-station.js +20 -17
- package/dist/core/runner-deps.d.ts +12 -22
- package/dist/core/safety-axis-vocab.d.ts +1 -1
- package/dist/core/safety-merge-corpus.d.ts +1 -1
- package/dist/core/secret-env.d.ts +16 -5
- package/dist/core/secret-env.js +23 -63
- package/dist/core/sensitive-path-policy.d.ts +19 -18
- package/dist/core/sensitive-path-policy.js +73 -49
- package/dist/core/session-policy-store.d.ts +6 -3
- package/dist/core/session-policy-store.js +28 -10
- package/dist/core/session-reconcile.d.ts +3 -0
- package/dist/core/session-reconcile.js +5 -4
- package/dist/core/session-store.d.ts +5 -0
- package/dist/core/session-store.js +12 -0
- package/dist/core/session.d.ts +13 -0
- package/dist/core/shared-memory/normalize.d.ts +17 -4
- package/dist/core/shared-memory/normalize.js +7 -7
- package/dist/core/shell-lexer.js +5 -4
- package/dist/core/shell-wrapper-table.d.ts +2 -2
- package/dist/core/shell-wrapper-table.js +1 -1
- package/dist/core/skill-grant.js +1 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +13 -0
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +7 -14
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +27 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.js +92 -0
- package/dist/core/stub-env.d.ts +2 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/synthetic-read-verdict.js +2 -2
- package/dist/core/task-event.d.ts +59 -5
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +42 -9
- package/dist/core/terminal-cause.d.ts +94 -11
- package/dist/core/tighten-task-spec.d.ts +5 -4
- package/dist/core/tighten-task-spec.js +20 -25
- package/dist/core/tool-catalog-entries.d.ts +5 -7
- package/dist/core/tool-catalog-entries.js +14 -15
- package/dist/core/tool-face.d.ts +47 -0
- package/dist/core/tool-face.js +5 -0
- package/dist/core/tool-model-gate.d.ts +5 -5
- package/dist/core/tool-name-aliases.d.ts +35 -10
- package/dist/core/tool-name-aliases.js +15 -0
- package/dist/core/tool-name-list.d.ts +30 -0
- package/dist/core/tool-name-list.js +55 -0
- package/dist/core/tool-name-readings.d.ts +1 -9
- package/dist/core/tool-name-readings.js +1 -3
- package/dist/core/tool-policy.d.ts +195 -85
- package/dist/core/tool-policy.js +165 -381
- package/dist/core/tool-registry.d.ts +44 -1
- package/dist/core/tool-registry.js +26 -0
- package/dist/core/tool-roster.d.ts +19 -1
- package/dist/core/tool-roster.js +21 -2
- package/dist/core/tool-spec-members.d.ts +45 -0
- package/dist/core/tool-spec-members.js +169 -0
- package/dist/core/tool-spec.d.ts +46 -8
- package/dist/core/tools.d.ts +6 -2
- package/dist/core/tools.js +8 -4
- package/dist/core/untrusted-egress.js +29 -26
- package/dist/core/untrusted-text.d.ts +13 -10
- package/dist/core/untrusted-text.js +6 -44
- package/dist/core/workflow-journal-store.d.ts +4 -1
- package/dist/core/write-protect.d.ts +65 -29
- package/dist/core/write-protect.js +235 -177
- package/dist/engine/compaction/compaction.d.ts +2 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +5 -23
- package/dist/engine/execution-env/node-execution-env.js +16 -38
- package/dist/engine/execution-env/symlink-chain.d.ts +23 -0
- package/dist/engine/execution-env/symlink-chain.js +32 -0
- package/dist/engine/harness/types.d.ts +7 -0
- package/dist/engine/llm/tool-turns.d.ts +3 -0
- package/dist/engine/llm/tool-turns.js +1 -0
- package/dist/engine/llm/types.d.ts +59 -23
- package/dist/engine/loop/agent-loop.js +16 -2
- package/dist/engine/session/memory-repo.js +11 -3
- package/dist/engine/session/repo-utils.d.ts +8 -0
- package/dist/engine/session/repo-utils.js +13 -0
- package/dist/index.d.ts +20 -23
- package/dist/index.js +17 -20
- package/dist/internal/harness.d.ts +1 -1
- package/dist/internal/harness.js +1 -1
- package/dist/internal/llm.d.ts +2 -2
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/governance-baseline-validity.js +1 -1
- package/dist/orchestration/run-spec.js +3 -3
- package/dist/orchestration/run-workflow-tool.d.ts +16 -35
- package/dist/orchestration/run-workflow-tool.js +38 -78
- package/dist/orchestration/workflow-governance.d.ts +21 -25
- package/dist/orchestration/workflow-governance.js +38 -78
- package/dist/orchestration/workflow-primitives.d.ts +7 -22
- package/dist/orchestration/workflow-primitives.js +5 -12
- package/dist/orchestration/workflow-types.d.ts +1 -1
- package/dist/orchestration/workflow.d.ts +61 -11
- package/dist/orchestration/workflow.js +191 -119
- package/dist/prompt-assembly/types.d.ts +1 -1
- package/dist/scenarios/full-body.d.ts +1 -1
- package/dist/shell/lex.d.ts +0 -21
- package/dist/shell/lex.js +278 -70
- package/dist/shell/shell-words.d.ts +35 -0
- package/dist/shell/shell-words.js +65 -0
- package/dist/stores/file/checkpoint-store.d.ts +5 -5
- package/dist/stores/file/checkpoint-store.js +5 -2
- package/dist/stores/file/index.d.ts +0 -8
- package/dist/stores/file/index.js +0 -12
- package/dist/stores/file/session-store.d.ts +3 -0
- package/dist/stores/file/session-store.js +44 -19
- package/dist/tools/artifact/artifact-tool.js +2 -0
- package/dist/tools/fs/bash-program-position.d.ts +17 -3
- package/dist/tools/fs/bash-program-position.js +25 -10
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/bash-readonly-classifier.js +8 -7
- package/dist/tools/fs/containment-face.d.ts +4 -0
- package/dist/tools/fs/containment-face.js +3 -0
- package/dist/tools/fs/fs-shared.d.ts +10 -0
- package/dist/tools/fs/fs-shared.js +18 -0
- package/dist/tools/fs/fs-write.js +4 -2
- package/dist/tools/fs/index.d.ts +3 -2
- package/dist/tools/fs/index.js +2 -2
- package/dist/tools/fs/program-read-model.d.ts +99 -23
- package/dist/tools/fs/program-read-model.js +129 -55
- package/dist/tools/fs/program-read-model.rows.d.ts +0 -14
- package/dist/tools/fs/program-read-model.rows.js +18 -10
- package/dist/tools/fs/read-deny-home.d.ts +35 -30
- package/dist/tools/fs/read-deny-home.js +45 -38
- package/dist/tools/fs/read-deny.d.ts +35 -27
- package/dist/tools/fs/read-deny.js +126 -92
- package/dist/tools/fs/removal-targets.d.ts +56 -23
- package/dist/tools/fs/removal-targets.js +74 -87
- package/dist/tools/fs/safety.d.ts +29 -22
- package/dist/tools/fs/safety.js +17 -11
- package/dist/tools/fs/search.js +10 -8
- package/dist/tools/fs/shell-read-argv.d.ts +4 -7
- package/dist/tools/fs/shell-read-argv.js +6 -8
- package/dist/tools/fs/shell-read-bindings.d.ts +203 -46
- package/dist/tools/fs/shell-read-bindings.js +488 -144
- package/dist/tools/fs/shell-read-builtins.d.ts +35 -0
- package/dist/tools/fs/shell-read-builtins.js +43 -0
- package/dist/tools/fs/shell-read-check.d.ts +15 -1
- package/dist/tools/fs/shell-read-check.js +51 -42
- package/dist/tools/fs/shell-read-establish.js +9 -10
- package/dist/tools/fs/shell-read-functions.d.ts +22 -0
- package/dist/tools/fs/shell-read-functions.js +29 -0
- package/dist/tools/fs/shell-read-judge.d.ts +48 -18
- package/dist/tools/fs/shell-read-judge.js +33 -4
- package/dist/tools/fs/shell-read-plan.d.ts +13 -20
- package/dist/tools/fs/shell-read-plan.js +200 -194
- package/dist/tools/fs/shell-read-start.d.ts +80 -0
- package/dist/tools/fs/shell-read-start.js +99 -0
- package/dist/tools/fs/shell-read-word.d.ts +35 -6
- package/dist/tools/fs/shell-read-word.js +89 -9
- package/dist/tools/fs/shell-read-workdir.d.ts +156 -0
- package/dist/tools/fs/shell-read-workdir.js +281 -0
- package/dist/tools/fs/shell-read-write-targets.d.ts +5 -2
- package/dist/tools/fs/shell-read-write-targets.js +14 -5
- package/dist/tools/fs/shell-reentry-text.d.ts +26 -26
- package/dist/tools/fs/shell-reentry-text.js +31 -34
- package/dist/tools/task-list.d.ts +1 -2
- package/dist/tools/web.js +1 -1
- package/package.json +4 -1
- package/test/export-surface.snapshot.json +107 -143
- package/wire-changes/core@7.48.0.json +252 -0
- package/wire-changes/core@7.49.0.json +4765 -0
- package/dist/agents/teacher.d.ts +0 -159
- package/dist/agents/teacher.js +0 -577
- package/dist/agents/team.d.ts +0 -226
- package/dist/agents/team.js +0 -257
- package/dist/core/strategy-store.d.ts +0 -238
- package/dist/core/strategy-store.js +0 -253
- package/dist/orchestration/builtin-workflows.d.ts +0 -133
- package/dist/orchestration/builtin-workflows.js +0 -159
- package/dist/scenarios/env.d.ts +0 -40
- package/dist/scenarios/env.js +0 -39
- package/dist/scenarios/scenario-registry.d.ts +0 -110
- package/dist/scenarios/scenario-registry.js +0 -140
- package/dist/scenarios/teacher-quickstart.d.ts +0 -40
- package/dist/scenarios/teacher-quickstart.js +0 -12
- package/dist/stores/cc/lockfile.d.ts +0 -10
- package/dist/stores/cc/lockfile.js +0 -98
- package/dist/stores/cc/mailbox-store.d.ts +0 -20
- package/dist/stores/cc/mailbox-store.js +0 -255
- package/dist/stores/cc/roster-adapter.d.ts +0 -12
- package/dist/stores/cc/roster-adapter.js +0 -117
- package/dist/stores/cc/sidecar-transcript.d.ts +0 -97
- package/dist/stores/cc/sidecar-transcript.js +0 -264
- package/dist/stores/cc/task-list-store.d.ts +0 -2
- package/dist/stores/cc/task-list-store.js +0 -125
- package/dist/stores/file/strategy-store.d.ts +0 -97
- package/dist/stores/file/strategy-store.js +0 -341
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { anchorSpelling, canonicalizeTarget, isAbsoluteForFamily, isWinFormPath, writeTargetPath, isUncPath, pathFamilyOf } from "../tools/fs/safety.js";
|
|
2
|
+
import { judgePathRows } from "./path-guard-rows.js";
|
|
3
3
|
import { protectivePathTargetOf } from "./tool-registry.js";
|
|
4
4
|
import { pathTargetBaseOf } from "./effective-path-target.js";
|
|
5
5
|
import { canonicalDataRootKeys, dataRootSpellings, relativeUnderRoot } from "./sensitive-path-policy.js";
|
|
6
|
-
import { symlinkChainHops } from "./path-identity.js";
|
|
6
|
+
import { chainHopsOrNone, symlinkChainHops } from "./path-identity.js";
|
|
7
7
|
import { readDenyPatternRun } from "../tools/fs/read-deny.js";
|
|
8
8
|
import { agentConfigDirSegments, agentConfigDirTail } from "./agent-config-dir.js";
|
|
9
9
|
import { thrownText } from "./thrown-value.js";
|
|
10
|
+
import { fromSource, gateWaitFailureOf } from "./gate-bounded-await.js";
|
|
10
11
|
const freezeTable = (rows) => Object.freeze(rows.map((r) => Object.freeze(r)));
|
|
11
12
|
export const WRITE_PROTECTED_DEFAULT_TABLE = freezeTable([
|
|
12
13
|
{ name: ".gitconfig", kind: "basename" },
|
|
@@ -85,39 +86,52 @@ function describeEntryValue(v) {
|
|
|
85
86
|
return String(v);
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
|
-
function normalizeWriteProtectedEntry(entry) {
|
|
89
|
+
function normalizeWriteProtectedEntry(entry, owner = "writeProtectedPaths") {
|
|
89
90
|
const shape = typeof entry === "string" ? { name: entry, kind: entry.includes("/") ? "segment-run" : "segment" } : entry;
|
|
90
91
|
if (typeof shape !== "object" || shape === null || typeof shape.name !== "string") {
|
|
91
|
-
throw new Error(
|
|
92
|
+
throw new Error(`${owner}: entry ${describeEntryValue(entry)} is not a name string or { name, kind } row.`);
|
|
92
93
|
}
|
|
93
94
|
const name = shape.name;
|
|
94
95
|
if (!KINDS.includes(shape.kind)) {
|
|
95
|
-
throw new Error(
|
|
96
|
+
throw new Error(`${owner}: entry ${describeEntryValue(entry)} has kind ${describeEntryValue(shape.kind)} — known kinds: ${KINDS.join(", ")}.`);
|
|
96
97
|
}
|
|
97
98
|
const kind = shape.kind;
|
|
98
99
|
const { homeAnchored, run } = readDenyPatternRun(name);
|
|
99
100
|
if (homeAnchored) {
|
|
100
|
-
throw new Error(
|
|
101
|
+
throw new Error(`${owner}: entry ${describeEntryValue(name)} opens with the home word "~", which this table does not place — its names are matched wherever their segments appear. ` +
|
|
101
102
|
(run.length > 0 ? `Spell the name without it (${describeEntryValue(run)}), which covers the home's file and every same-named one.` : "The home directory itself is not a row; spell the name of what it holds."));
|
|
102
103
|
}
|
|
103
104
|
if (name.includes("*") || name.includes("?")) {
|
|
104
|
-
throw new Error(
|
|
105
|
+
throw new Error(`${owner}: entry ${describeEntryValue(name)} contains a wildcard metacharacter — this table speaks LITERAL names only (a silently-literal "*" would guard less than it reads); pattern semantics live in createSensitivePathPolicy.`);
|
|
105
106
|
}
|
|
106
107
|
if (name.includes("\\")) {
|
|
107
|
-
throw new Error(
|
|
108
|
+
throw new Error(`${owner}: entry ${describeEntryValue(name)} contains a backslash — names are "/"-separated (both path families are matched); spell the segments with "/".`);
|
|
108
109
|
}
|
|
109
110
|
const segments = name.split("/").filter((s) => s.length > 0);
|
|
110
111
|
if (segments.length === 0) {
|
|
111
|
-
throw new Error(
|
|
112
|
+
throw new Error(`${owner}: entry ${describeEntryValue(name)} contains no path segments and would protect nothing — remove the entry or spell the name.`);
|
|
112
113
|
}
|
|
113
114
|
if (segments.some((s) => s === "." || s === "..")) {
|
|
114
|
-
throw new Error(
|
|
115
|
+
throw new Error(`${owner}: entry ${describeEntryValue(name)} contains a "." or ".." segment — the judge folds dot segments lexically before matching, so such a row could never match anything; spell the real name.`);
|
|
115
116
|
}
|
|
116
117
|
if (segments.length > 1 && kind !== "segment-run") {
|
|
117
|
-
throw new Error(
|
|
118
|
+
throw new Error(`${owner}: entry ${describeEntryValue(name)} spans ${segments.length} segments but declares kind "${kind}" — multi-segment names match as kind "segment-run".`);
|
|
118
119
|
}
|
|
119
120
|
return { name: segments.join("/"), kind };
|
|
120
121
|
}
|
|
122
|
+
export function writeProtectedEntryProblem(entry, owner) {
|
|
123
|
+
try {
|
|
124
|
+
normalizeWriteProtectedEntry(entry, owner);
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
return e.message;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
export function writeProtectedEntryIdentity(entry) {
|
|
132
|
+
const row = normalizeWriteProtectedEntry(entry);
|
|
133
|
+
return `${row.kind}:${foldWriteProtectName(row.name)}`;
|
|
134
|
+
}
|
|
121
135
|
export function resolveWriteProtectedTable(entries) {
|
|
122
136
|
if (entries === undefined)
|
|
123
137
|
return WRITE_PROTECTED_DEFAULT_TABLE;
|
|
@@ -128,7 +142,7 @@ export function resolveWriteProtectedTable(entries) {
|
|
|
128
142
|
const seen = new Set();
|
|
129
143
|
for (const entry of entries) {
|
|
130
144
|
const row = normalizeWriteProtectedEntry(entry);
|
|
131
|
-
const key =
|
|
145
|
+
const key = writeProtectedEntryIdentity(row);
|
|
132
146
|
if (seen.has(key))
|
|
133
147
|
continue;
|
|
134
148
|
seen.add(key);
|
|
@@ -185,206 +199,250 @@ function relativeUnderDataRoot(path, roots) {
|
|
|
185
199
|
}
|
|
186
200
|
return null;
|
|
187
201
|
}
|
|
202
|
+
export function spelledExemptionOf(dataRootPaths) {
|
|
203
|
+
const roots = dataRootPaths.map((r) => {
|
|
204
|
+
const win = isWinFormPath(r);
|
|
205
|
+
return { win, segments: pathViewSegments(r, "literal", win ? BOTH_SEPARATOR_FAMILIES : POSIX_SEPARATOR_FAMILY, uncAnchorSegments(r)) };
|
|
206
|
+
});
|
|
207
|
+
return (spelling) => relativeUnderDataRoot(spelling, roots);
|
|
208
|
+
}
|
|
188
209
|
export const WRITE_PROTECTION_TARGET_VIEWS = Object.freeze(["spelling-only", "target"]);
|
|
189
210
|
export function compileWriteProtection(entries, opts) {
|
|
190
211
|
const rows = resolveWriteProtectedTable(entries);
|
|
191
212
|
if (rows.length === 0)
|
|
192
213
|
return undefined;
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
|
|
214
|
+
const { dataRoot, ...seats } = opts ?? {};
|
|
215
|
+
return compileWriteJudgment(rows, entries === undefined ? "builtin" : "replacement", { ...seats, exemptRoots: dataRootSpellings(dataRoot) }).matcher;
|
|
216
|
+
}
|
|
217
|
+
export function compileLegWriteJudgment(entries, opts) {
|
|
218
|
+
const rows = resolveWriteProtectedTable(entries);
|
|
219
|
+
const compiled = compileWriteJudgment(rows, "replacement", opts);
|
|
220
|
+
const guardRows = opts.guardRows;
|
|
221
|
+
return {
|
|
222
|
+
matcher: rows.length === 0 ? undefined : compiled.matcher,
|
|
223
|
+
judgeWriteTarget: rows.length === 0 && guardRows === undefined
|
|
224
|
+
? undefined
|
|
225
|
+
: async (target, judgeOpts) => {
|
|
226
|
+
const hit = await compiled.judgment(target, { ...(judgeOpts?.signal !== undefined ? { signal: judgeOpts.signal } : {}), ...(judgeOpts?.canonical === true ? { canonical: true } : {}) }, guardRows);
|
|
227
|
+
return hit === undefined ? undefined : hit.unreadable === undefined && TABLE_ROWS.has(hit.row) ? "protected" : "guarded";
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
const TABLE_ROWS = new WeakSet();
|
|
232
|
+
function heldRows(cause) {
|
|
233
|
+
return { name: "the deployment's guarded write rows", grammar: { kind: "segment-glob", run: "" }, polarity: "deny", faces: ["write"], placement: "anywhere", fold: "exact", exemptible: false, origin: "replacement", reach: () => ({ reach: "unreadable", reason: `the rows did not come back: ${cause}` }) };
|
|
234
|
+
}
|
|
235
|
+
function compileWriteJudgment(rows, origin, opts) {
|
|
236
|
+
const dataRootPaths = opts.exemptRoots;
|
|
237
|
+
const spelledRemainder = spelledExemptionOf(dataRootPaths);
|
|
238
|
+
const readingMemo = new Map();
|
|
239
|
+
const readingsOf = (spelling) => {
|
|
240
|
+
const known = readingMemo.get(spelling);
|
|
241
|
+
if (known !== undefined)
|
|
242
|
+
return known;
|
|
243
|
+
const raw = [pathViewSegments(spelling, "literal", POSIX_SEPARATOR_FAMILY, uncAnchorSegments(spelling)), pathViewSegments(spelling, "literal"), ...WIN32_NORMALIZATIONS.map((n) => pathViewSegments(spelling, n))];
|
|
244
|
+
const folded = raw.map((segs) => segs.map(foldWriteProtectSegment));
|
|
245
|
+
if (readingMemo.size >= 64)
|
|
246
|
+
readingMemo.clear();
|
|
247
|
+
readingMemo.set(spelling, folded);
|
|
248
|
+
return folded;
|
|
249
|
+
};
|
|
250
|
+
const literalRow = (row, reach, placement) => {
|
|
251
|
+
const minted = { name: row.name, kind: row.kind, grammar: { kind: "literal-name", match: row.kind, name: row.name }, polarity: "ask", faces: ["write"], placement, fold: "protective", exemptible: true, origin, reach };
|
|
252
|
+
TABLE_ROWS.add(minted);
|
|
253
|
+
return minted;
|
|
254
|
+
};
|
|
255
|
+
const tableRows = [];
|
|
256
|
+
for (const kind of KINDS) {
|
|
257
|
+
for (const row of rows) {
|
|
258
|
+
if (row.kind !== kind)
|
|
259
|
+
continue;
|
|
260
|
+
const parts = foldWriteProtectName(row.name).split("/").filter((s) => s.length > 0);
|
|
261
|
+
tableRows.push(literalRow(row, (view) => (readingsOf(view.path).some((segs) => literalNameMeets(kind, parts, segs)) ? REACHED : NOT_REACHED), "anywhere"));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
201
264
|
const configTails = [];
|
|
202
265
|
for (const row of rows) {
|
|
203
|
-
const folded = foldWriteProtectName(row.name);
|
|
204
|
-
if (row.kind === "basename") {
|
|
205
|
-
if (!basenames.has(folded))
|
|
206
|
-
basenames.set(folded, row.name);
|
|
207
|
-
}
|
|
208
|
-
else if (row.kind === "segment") {
|
|
209
|
-
if (!segments.has(folded))
|
|
210
|
-
segments.set(folded, row.name);
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
runs.push({ name: row.name, parts: folded.split("/").filter((s) => s.length > 0) });
|
|
214
|
-
}
|
|
215
266
|
const tail = row.kind === "basename" ? undefined : agentConfigDirTail(row.name);
|
|
216
267
|
if (tail !== undefined && opts?.agentConfigDir !== undefined)
|
|
217
|
-
configTails.push({
|
|
268
|
+
configTails.push({ row, tail: foldWriteProtectName(tail).split("/").filter((s) => s.length > 0) });
|
|
218
269
|
}
|
|
219
270
|
const configRootSpelled = opts?.agentConfigDir === undefined ? [] : [agentConfigDirSegments(opts.agentConfigDir)];
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
return null;
|
|
271
|
+
const configRowsAt = (canonicalRoots) => configTails.map(({ row, tail }) => literalRow(row, (view) => {
|
|
272
|
+
if (!isAbsoluteForFamily("own", view.path))
|
|
273
|
+
return NOT_REACHED;
|
|
274
|
+
const roots = view.kind === "canonical" ? [...configRootSpelled, ...canonicalRoots] : configRootSpelled;
|
|
275
|
+
return readingsOf(view.path).some((segs) => roots.some((root) => atConfigRoot(segs, root.map(foldWriteProtectSegment), tail))) ? REACHED : NOT_REACHED;
|
|
276
|
+
}, { below: opts?.agentConfigDir ?? "" }));
|
|
277
|
+
const tableAt = (canonicalRoots) => (configTails.length === 0 ? tableRows : [...tableRows, ...configRowsAt(canonicalRoots)]);
|
|
278
|
+
const spelledView = (spelled, kind) => {
|
|
279
|
+
const remainder = spelledRemainder(spelled);
|
|
280
|
+
return { path: spelled, kind, ...(remainder !== null ? { exemptRemainder: remainder } : {}) };
|
|
230
281
|
};
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if (
|
|
241
|
-
return
|
|
282
|
+
const anchoredSpelling = (path, cwd) => {
|
|
283
|
+
const base = typeof cwd === "string" && cwd.length > 0 ? cwd : undefined;
|
|
284
|
+
return base !== undefined ? anchorSpelling(pathFamilyOf({ cwd: base }), base, path) : path;
|
|
285
|
+
};
|
|
286
|
+
const env = opts?.env;
|
|
287
|
+
const rootPath = opts?.rootPath;
|
|
288
|
+
const judgment = async (path, ctx, extraSource) => {
|
|
289
|
+
let noted = false;
|
|
290
|
+
const noteAbsence = (cause, unresolvedSymlink) => {
|
|
291
|
+
if (noted)
|
|
292
|
+
return;
|
|
293
|
+
noted = true;
|
|
294
|
+
opts?.onViewAbsent?.({ cause, unresolvedSymlink });
|
|
295
|
+
};
|
|
296
|
+
const sourceFailed = (err, what) => {
|
|
297
|
+
if (gateWaitFailureOf(err) !== "aborted")
|
|
298
|
+
noteAbsence(what === undefined ? thrownText(err) : `${what}: ${thrownText(err)}`, false);
|
|
299
|
+
};
|
|
300
|
+
const extra = await (async () => {
|
|
301
|
+
if (extraSource === undefined)
|
|
302
|
+
return [];
|
|
303
|
+
const answer = await fromSource(() => extraSource({ ...(env !== undefined ? { env } : {}), ...(ctx.signal !== undefined ? { signal: ctx.signal } : {}) }), ctx.signal, "deploymentRows");
|
|
304
|
+
if (answer.ok)
|
|
305
|
+
return answer.value;
|
|
306
|
+
sourceFailed(answer.cause, "the deployment's guarded write rows did not come back, so the writes they could guard are not placed");
|
|
307
|
+
return [heldRows(thrownText(answer.cause))];
|
|
308
|
+
})();
|
|
309
|
+
const givenKey = ctx.canonical === true && env !== undefined;
|
|
310
|
+
const base = ctx.base ?? ctx.cwd ?? rootPath;
|
|
311
|
+
const lexical = givenKey ? undefined : spelledView(anchoredSpelling(path, ctx.base ?? ctx.cwd), "lexical");
|
|
312
|
+
const bySpelling = lexical === undefined ? undefined : judgePathRows([...tableAt([]), ...extra], { views: [lexical] }, "tighten");
|
|
313
|
+
if (bySpelling !== undefined && bySpelling.unreadable === undefined && TABLE_ROWS.has(bySpelling.row))
|
|
314
|
+
return bySpelling;
|
|
315
|
+
if (env === undefined)
|
|
316
|
+
return bySpelling;
|
|
317
|
+
const family = pathFamilyOf({ root: rootPath, cwd: ctx.cwd ?? env.cwd });
|
|
318
|
+
const rootLookupFailed = (err) => sourceFailed(err, "a root's key did not come back, so that root takes no part");
|
|
319
|
+
let canonKey = givenKey ? path : undefined;
|
|
320
|
+
let canonAliased = false;
|
|
321
|
+
let targetUnread;
|
|
322
|
+
let targetUnreadSymlink = false;
|
|
323
|
+
if (!givenKey) {
|
|
324
|
+
const answer = await fromSource(() => canonicalizeTarget(env, path, ctx.signal, family, base), ctx.signal, "canonicalTarget");
|
|
325
|
+
if (!answer.ok) {
|
|
326
|
+
sourceFailed(answer.cause);
|
|
327
|
+
targetUnread = thrownText(answer.cause);
|
|
328
|
+
}
|
|
329
|
+
else if (answer.value.ok) {
|
|
330
|
+
canonKey = answer.value.key;
|
|
331
|
+
canonAliased = answer.value.aliasResolved === true;
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
noteAbsence(answer.value.message, answer.value.unresolvedSymlink === true);
|
|
335
|
+
targetUnread = answer.value.message;
|
|
336
|
+
targetUnreadSymlink = answer.value.unresolvedSymlink === true;
|
|
337
|
+
}
|
|
242
338
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
339
|
+
const canonicalRoots = canonKey === undefined || configTails.length === 0 || opts?.agentConfigDir === undefined ? [] : (await canonicalDataRootKeys(env, [opts.agentConfigDir], ctx.signal, rootLookupFailed)).map(agentConfigDirSegments);
|
|
340
|
+
const table = [...tableAt(canonicalRoots), ...extra];
|
|
341
|
+
const aliased = canonAliased ? { aliasResolved: true } : {};
|
|
342
|
+
const views = [...(lexical !== undefined ? [{ ...lexical, ...aliased }] : []), ...(canonKey !== undefined ? [{ path: canonKey, kind: "canonical", ...aliased }] : [])];
|
|
343
|
+
const identity = {};
|
|
344
|
+
const identityRemainder = () => (identity.asked ??= (async () => {
|
|
345
|
+
if (canonKey === undefined)
|
|
346
|
+
return undefined;
|
|
347
|
+
for (const rootKey of await canonicalDataRootKeys(env, dataRootPaths, ctx.signal, rootLookupFailed)) {
|
|
348
|
+
const relative = relativeUnderRoot(canonKey, rootKey);
|
|
349
|
+
if (relative !== null)
|
|
350
|
+
return relative;
|
|
248
351
|
}
|
|
352
|
+
return undefined;
|
|
353
|
+
})());
|
|
354
|
+
const judged = async () => {
|
|
355
|
+
const unread = targetUnread !== undefined ? { unreadable: targetUnread } : {};
|
|
356
|
+
const hit = judgePathRows(table, { views, ...unread }, "tighten");
|
|
357
|
+
if (hit === undefined)
|
|
358
|
+
return undefined;
|
|
359
|
+
const relative = await identityRemainder();
|
|
360
|
+
const final = relative === undefined ? hit : judgePathRows(table, { views: views.map((v) => (v.kind === "canonical" ? { ...v, exemptRemainder: relative } : v)), identityExempt: true, ...unread }, "tighten");
|
|
361
|
+
return final !== undefined && final.unreadable !== undefined && targetUnread !== undefined && targetUnreadSymlink ? { ...final, unresolvedSymlink: true } : final;
|
|
362
|
+
};
|
|
363
|
+
const byTarget = canonKey === undefined ? undefined : await judged();
|
|
364
|
+
if (byTarget !== undefined && byTarget.unreadable === undefined && TABLE_ROWS.has(byTarget.row))
|
|
365
|
+
return byTarget;
|
|
366
|
+
if (givenKey)
|
|
367
|
+
return byTarget;
|
|
368
|
+
if (identity.asked !== undefined && (await identity.asked) !== undefined && table.every((row) => row.exemptible))
|
|
369
|
+
return byTarget;
|
|
370
|
+
const chain = await fromSource(() => symlinkChainHops(env, path, ctx.signal, family, base), ctx.signal, "canonicalChain");
|
|
371
|
+
if (!chain.ok) {
|
|
372
|
+
sourceFailed(chain.cause);
|
|
373
|
+
targetUnread ??= thrownText(chain.cause);
|
|
249
374
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
if (bothSeparators !== null)
|
|
258
|
-
return bothSeparators;
|
|
259
|
-
for (const normalization of WIN32_NORMALIZATIONS) {
|
|
260
|
-
const hit = judgeSegments(pathViewSegments(spelling, normalization), configRoots);
|
|
261
|
-
if (hit !== null)
|
|
262
|
-
return hit;
|
|
375
|
+
else {
|
|
376
|
+
if (!chain.value.ok && chain.value.asked) {
|
|
377
|
+
noteAbsence(chain.value.cause, false);
|
|
378
|
+
targetUnread ??= chain.value.cause;
|
|
379
|
+
}
|
|
380
|
+
for (const hop of chainHopsOrNone(chain.value))
|
|
381
|
+
views.push(spelledView(hop, "hop"));
|
|
263
382
|
}
|
|
264
|
-
return
|
|
265
|
-
};
|
|
266
|
-
const judgeSpelled = (spelled) => {
|
|
267
|
-
const remainder = relativeUnderDataRoot(spelled, rootViews);
|
|
268
|
-
return remainder === null ? judgeViews(spelled) : judgeViews(remainder, []);
|
|
383
|
+
return judged();
|
|
269
384
|
};
|
|
270
|
-
const
|
|
271
|
-
const base = typeof cwd === "string" && cwd.length > 0 ? cwd : undefined;
|
|
272
|
-
const family = pathFamilyOf({ cwd: base });
|
|
273
|
-
const spelled = base !== undefined && family !== undefined && !isAbsoluteForFamily(family, path) ? joinForFamily(family, base, path) : path;
|
|
274
|
-
return judgeSpelled(spelled);
|
|
275
|
-
};
|
|
276
|
-
const env = opts?.env;
|
|
277
|
-
const rootPath = opts?.rootPath;
|
|
278
|
-
return {
|
|
385
|
+
const matcher = {
|
|
279
386
|
rows,
|
|
280
387
|
targetView: env === undefined ? "spelling-only" : "target",
|
|
281
388
|
matchPath(path, cwd) {
|
|
282
|
-
|
|
389
|
+
const hit = judgePathRows(tableAt([]), { views: [spelledView(anchoredSpelling(path, cwd), "lexical")] }, "tighten");
|
|
390
|
+
return hit === undefined ? null : { name: hit.row.name, kind: hit.row.kind };
|
|
283
391
|
},
|
|
284
392
|
async judge(path, ctx = {}) {
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
if (bySpelling !== null)
|
|
288
|
-
return { kind: "hit", hit: bySpelling, via: "spelling" };
|
|
289
|
-
if (env === undefined)
|
|
393
|
+
const hit = await judgment(path, ctx);
|
|
394
|
+
if (hit === undefined)
|
|
290
395
|
return { kind: "clear" };
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const noteAbsence = (cause, unresolvedSymlink) => {
|
|
295
|
-
if (noted)
|
|
296
|
-
return;
|
|
297
|
-
noted = true;
|
|
298
|
-
opts?.onViewAbsent?.({ cause, unresolvedSymlink });
|
|
299
|
-
};
|
|
300
|
-
let canonKey = givenKey ? path : undefined;
|
|
301
|
-
if (!givenKey) {
|
|
302
|
-
try {
|
|
303
|
-
const canon = await canonicalizeTarget(env, path, ctx.signal, family, base);
|
|
304
|
-
if (canon.ok)
|
|
305
|
-
canonKey = canon.key;
|
|
306
|
-
else
|
|
307
|
-
noteAbsence(canon.message, canon.unresolvedSymlink === true);
|
|
308
|
-
}
|
|
309
|
-
catch (err) {
|
|
310
|
-
noteAbsence(thrownText(err), false);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
try {
|
|
314
|
-
if (canonKey !== undefined) {
|
|
315
|
-
const canonicalRoots = configTails.length === 0 || opts?.agentConfigDir === undefined ? [] : (await canonicalDataRootKeys(env, [opts.agentConfigDir], ctx.signal)).map(agentConfigDirSegments);
|
|
316
|
-
const byTarget = judgeViews(canonKey, [...configRootSpelled, ...canonicalRoots]);
|
|
317
|
-
if (byTarget !== null) {
|
|
318
|
-
for (const rootKey of await canonicalDataRootKeys(env, dataRootPaths, ctx.signal)) {
|
|
319
|
-
const relative = relativeUnderRoot(canonKey, rootKey);
|
|
320
|
-
if (relative === null)
|
|
321
|
-
continue;
|
|
322
|
-
if (relative === "")
|
|
323
|
-
return { kind: "clear" };
|
|
324
|
-
const remainder = judgeViews(relative, []);
|
|
325
|
-
return remainder === null ? { kind: "clear" } : { kind: "hit", hit: remainder, via: "target" };
|
|
326
|
-
}
|
|
327
|
-
return { kind: "hit", hit: byTarget, via: "target" };
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
for (const hop of givenKey ? [] : await symlinkChainHops(env, path, ctx.signal, family, base, (cause) => noteAbsence(cause, false))) {
|
|
331
|
-
const byHop = judgeSpelled(hop);
|
|
332
|
-
if (byHop === null)
|
|
333
|
-
continue;
|
|
334
|
-
if (canonKey !== undefined) {
|
|
335
|
-
for (const rootKey of await canonicalDataRootKeys(env, dataRootPaths, ctx.signal)) {
|
|
336
|
-
if (relativeUnderRoot(canonKey, rootKey) !== null)
|
|
337
|
-
return { kind: "clear" };
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
return { kind: "hit", hit: byHop, via: "chain" };
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
catch (err) {
|
|
344
|
-
noteAbsence(thrownText(err), false);
|
|
345
|
-
}
|
|
346
|
-
return { kind: "clear" };
|
|
396
|
+
if (hit.unreadable !== undefined)
|
|
397
|
+
return { kind: "unresolvable", cause: hit.unreadable, unresolvedSymlink: hit.unresolvedSymlink === true };
|
|
398
|
+
return verdictOf(hit);
|
|
347
399
|
},
|
|
348
400
|
};
|
|
401
|
+
return { matcher, judgment };
|
|
349
402
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
403
|
+
const REACHED = { reach: "reached" };
|
|
404
|
+
const NOT_REACHED = { reach: "not_reached" };
|
|
405
|
+
function literalNameMeets(kind, parts, segs) {
|
|
406
|
+
if (segs.length === 0)
|
|
407
|
+
return false;
|
|
408
|
+
if (kind === "basename")
|
|
409
|
+
return segs[segs.length - 1] === parts[0];
|
|
410
|
+
if (kind === "segment")
|
|
411
|
+
return segs.includes(parts[0]);
|
|
412
|
+
for (let i = 0; i + parts.length <= segs.length; i++)
|
|
413
|
+
if (parts.every((p, j) => segs[i + j] === p))
|
|
414
|
+
return true;
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
function atConfigRoot(segs, root, tail) {
|
|
418
|
+
return segs.length >= root.length + tail.length && root.every((a, i) => segs[i] === a) && tail.every((t, i) => segs[root.length + i] === t);
|
|
419
|
+
}
|
|
420
|
+
function verdictOf(hit) {
|
|
421
|
+
return { kind: "hit", hit: { name: hit.row.name, kind: hit.row.kind }, via: hit.viewKind === "canonical" ? "target" : hit.viewKind === "hop" ? "chain" : "spelling" };
|
|
422
|
+
}
|
|
423
|
+
export function writeProtectionTightenDecision(toolName, verdict) {
|
|
424
|
+
if (verdict.kind === "clear")
|
|
425
|
+
return undefined;
|
|
362
426
|
if (verdict.kind === "unresolvable") {
|
|
363
|
-
if (releasableAskClassesFor(face).includes("write_protection_unresolved")) {
|
|
364
|
-
return {
|
|
365
|
-
action: "ask",
|
|
366
|
-
message: verdict.unresolvedSymlink
|
|
367
|
-
? `tool "${toolName}" writes to a symlink whose real target could not be resolved, so the write-protection judge cannot tell whether it lands on a protected path (${verdict.cause}) — explicit approval required`
|
|
368
|
-
: `tool "${toolName}" writes to a target that could not be resolved on this tree, so the write-protection judge cannot tell whether it lands on a protected path (${verdict.cause}) — explicit approval required`,
|
|
369
|
-
decisionReason: "safety",
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
427
|
return {
|
|
373
428
|
action: "deny",
|
|
374
|
-
message: verdict.unresolvedSymlink
|
|
375
|
-
? `tool "${toolName}" is blocked: its target is a symlink whose real target could not be resolved, so the write-protection judge cannot tell whether it lands on a protected path (${verdict.cause})`
|
|
376
|
-
: `tool "${toolName}" is blocked: its target could not be resolved on this tree, so the write-protection judge cannot tell whether it lands on a protected path (${verdict.cause})`,
|
|
429
|
+
message: `tool "${toolName}" is refused (target_unresolved): where its write target leads on disk could not be determined${verdict.unresolvedSymlink ? " (a link on the way could not be followed)" : ""}, so the write-protected table cannot tell whether it lands on a protected path — ${verdict.cause}`,
|
|
377
430
|
decisionReason: "safety",
|
|
378
431
|
};
|
|
379
432
|
}
|
|
380
|
-
return
|
|
433
|
+
return {
|
|
434
|
+
action: "ask",
|
|
435
|
+
message: verdict.via === "target"
|
|
436
|
+
? `tool "${toolName}" writes to a write-protected path — its real target resolves onto table entry "${verdict.hit.name}" — explicit approval required`
|
|
437
|
+
: verdict.via === "chain"
|
|
438
|
+
? `tool "${toolName}" writes to a write-protected path — its symlink chain passes through table entry "${verdict.hit.name}" — explicit approval required`
|
|
439
|
+
: `tool "${toolName}" writes to a write-protected path (table entry "${verdict.hit.name}") — explicit approval required`,
|
|
440
|
+
decisionReason: "safety",
|
|
441
|
+
};
|
|
381
442
|
}
|
|
382
443
|
export function writeProtectionMandated(verdict) {
|
|
383
444
|
return verdict.kind === "hit";
|
|
384
445
|
}
|
|
385
|
-
export function writeProtectionUnresolved(verdict) {
|
|
386
|
-
return verdict.kind === "unresolvable";
|
|
387
|
-
}
|
|
388
446
|
export function createWriteProtectionCheck(entries, opts) {
|
|
389
447
|
const matcher = compileWriteProtection(entries, opts);
|
|
390
448
|
return matcher === undefined ? undefined : writeProtectionMountOver(matcher, opts?.rootPath);
|
|
@@ -450,8 +450,8 @@ export interface CompactionPreparation {
|
|
|
450
450
|
* (raised in review as a contradiction; it is not one, but it was unstated). Byte-identity is
|
|
451
451
|
* over the SUMMARIZATION REQUEST ASSEMBLY, and there it is exact. Registering
|
|
452
452
|
* `<instruction-files>` in the authority census additionally puts it in the derived
|
|
453
|
-
* fenced/shelled-lane sets, so external bytes that literally spell the tag are now defused
|
|
454
|
-
*
|
|
453
|
+
* fenced/shelled-lane sets, so external bytes that literally spell the tag are now defused (an
|
|
454
|
+
* entity in the bracket's place) on those lanes — for every deployment, seat or no seat. That is not a compatibility break
|
|
455
455
|
* smuggled in: those lanes rewrite bytes BY CONTRACT (that is what makes them fences), it is what
|
|
456
456
|
* registering any new authority envelope means in this tree, and the alternative — a
|
|
457
457
|
* model-facing authority tag that the fences built to defuse forgeries do not defuse — is
|
|
@@ -8,21 +8,6 @@ import type { SchedulerCapability, ScheduledIntent, SchedulerContext, ScheduledT
|
|
|
8
8
|
import { SchedulerError } from "../../core/scheduler.js";
|
|
9
9
|
/** Convert user-facing timeout seconds into a positive, timer-safe millisecond delay. */
|
|
10
10
|
export declare function resolveExecTimeoutMs(timeoutSeconds: unknown): number | undefined;
|
|
11
|
-
/**
|
|
12
|
-
* Anchor a RELATIVE symlink target at its link's own directory, UNFOLDED and with exactly one separator
|
|
13
|
-
* between the two. A directory that IS a root already ends in its own separator (`/`, `C:\`, `C:/`,
|
|
14
|
-
* `\\host\share\`, all of which `dirname` answers that way), and concatenating a second one mints a
|
|
15
|
-
* DOUBLE-separator spelling for a path that has one spelling — `/tmp -> private/tmp` came back as
|
|
16
|
-
* `//private/tmp`, which the judges that walk this chain then match against nothing, because a guarded row
|
|
17
|
-
* and a containment root are both written with single separators. Joining through `path.resolve`/`path.join`
|
|
18
|
-
* would fix the separator and fold `..` with it, which is the one thing this walk may not do.
|
|
19
|
-
*
|
|
20
|
-
* `separator` is the one the caller's `dirname` writes, passed rather than read from the module so the rule
|
|
21
|
-
* is a pure function of its inputs. A backslash counts as a terminator only where it IS a separator: on a
|
|
22
|
-
* POSIX tree a directory whose name ends in one (`/a/b\`) is an ordinary name, and reading it as terminated
|
|
23
|
-
* would rename `/a/b\/t` to `/a/b\t` — the same class of rewrite as folding `..` lexically.
|
|
24
|
-
*/
|
|
25
|
-
export declare function anchorAtLinkDir(linkDir: string, target: string, separator: string): string;
|
|
26
11
|
/** review finding (win32): `where bash.exe` can resolve to `System32\bash.exe` — the
|
|
27
12
|
* WSL LAUNCHER, not a native shell. Running it drops into a Linux subsystem where Windows cwd/paths
|
|
28
13
|
* do not exist; silently adopting it is exactly the "wrong shell, false green" failure D1 forbids.
|
|
@@ -99,6 +84,9 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
|
|
|
99
84
|
/** `ExecutionEnv.homeDir` = the `HOME` the shell child receives (its `~`/`$HOME`/`${HOME}` all expand to it), read LIVE off the same `shellEnv`-over-`inheritEnv` merge each exec gets; ABSENT when the
|
|
100
85
|
* child gets none (an allowlist that withholds it: `~` then falls back to passwd while `$HOME` is empty — two values, no single home, home-relative operands stay fail-closed). Residual: a per-exec `env.HOME` override. */
|
|
101
86
|
get homeDir(): string | undefined;
|
|
87
|
+
/** `ExecutionEnv.cdPath` = the `CDPATH` the shell child receives, read LIVE off the same merge each exec gets (never the
|
|
88
|
+
* engine process's own environment): its entries, `[]` when the child gets none. Residual: a per-exec `env.CDPATH`. */
|
|
89
|
+
get cdPath(): readonly string[];
|
|
102
90
|
private shellPath?;
|
|
103
91
|
private shellEnv?;
|
|
104
92
|
private inheritEnv;
|
|
@@ -194,14 +182,8 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
|
|
|
194
182
|
fileIdentity(path: string): Promise<Result<string, FileError>>;
|
|
195
183
|
readLink(path: string): Promise<Result<string, FileError>>;
|
|
196
184
|
/**
|
|
197
|
-
* The LEAF symlink chain ({@link FileSystem.canonicalChain}):
|
|
198
|
-
*
|
|
199
|
-
* reached. A relative target is ANCHORED at its link's directory and never folded — `..` is the filesystem's
|
|
200
|
-
* to resolve during the next `readlink`'s own lookup (a lexical fold reads `bridge/../next` as `next` and misses
|
|
201
|
-
* every link behind `bridge`). Anchoring puts EXACTLY ONE separator between the directory and the target
|
|
202
|
-
* ({@link anchorAtLinkDir}); a root directory already ends in its own. One syscall per hop, no `lstat`. On a
|
|
203
|
-
* win32 host a share-shaped hop is kept and ends the walk unprobed. Any other errno is an answer nobody can
|
|
204
|
-
* use (`err`), never a shortened chain.
|
|
185
|
+
* The LEAF symlink chain ({@link FileSystem.canonicalChain}): {@link walkSymlinkChain} over {@link readLinkTarget}
|
|
186
|
+
* (not the `readLink` method: a wrapper counting or overriding it sees only a caller's own calls).
|
|
205
187
|
*/
|
|
206
188
|
canonicalChain(path: string): Promise<Result<SymlinkChain, FileError>>;
|
|
207
189
|
exists(path: string): Promise<Result<boolean, FileError>>;
|