@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,7 +1,7 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { assertAdoptionBootGate } from "./adoption/marker.js";
|
|
3
3
|
import { checkpointExecutionRecorded, executionRecordDisposition, ExecutionOutcomeConflictError, } from "../../core/checkpoint-execution-record.js";
|
|
4
|
-
import { appendPendingSteer, CheckpointError, checkpointOccMatches, checkpointRowMatches, summarizeCheckpoint, validatePendingSteer, winnerFromOutcome, } from "../../core/checkpoint-store.js";
|
|
4
|
+
import { appendPendingSteer, CheckpointError, checkpointOccMatches, checkpointRowMatches, encodeAtFidelity, summarizeCheckpoint, validatePendingSteer, winnerFromOutcome, } from "../../core/checkpoint-store.js";
|
|
5
5
|
import { SharedLedgerTable } from "./shared-ledger.js";
|
|
6
6
|
import { guardCorruptSink } from "./corrupt-read-sink.js";
|
|
7
7
|
const CHECKPOINT_LEDGER_EVENT_REGISTRY = {
|
|
@@ -109,7 +109,10 @@ export class FileCheckpointStore {
|
|
|
109
109
|
return this.ledger.withLock(token, fn);
|
|
110
110
|
}
|
|
111
111
|
commit(ev, fsync) {
|
|
112
|
-
this.
|
|
112
|
+
const held = encodeAtFidelity(this.fidelity, ev);
|
|
113
|
+
if (!held.ok)
|
|
114
|
+
throw held.cause;
|
|
115
|
+
this.ledger.commit(held.value, fsync, this.compactEvery);
|
|
113
116
|
}
|
|
114
117
|
async put(token, cp) {
|
|
115
118
|
return this.withLock(token, () => {
|
|
@@ -8,7 +8,6 @@ import { type FileSessionPolicyStoreOptions } from "./session-policy-store.js";
|
|
|
8
8
|
import { type FileFileHistoryStoreOptions } from "./file-history-store.js";
|
|
9
9
|
import type { CorruptReadInfo } from "./corrupt-read-sink.js";
|
|
10
10
|
import type { FileHistoryStore } from "../../core/file-history-store.js";
|
|
11
|
-
import type { StrategyStore } from "../../core/strategy-store.js";
|
|
12
11
|
import type { BackgroundAgentStore } from "../../core/background-agent-store.js";
|
|
13
12
|
import type { MailboxStore } from "../../core/mailbox-store.js";
|
|
14
13
|
import type { RosterStore } from "../../agents/roster-store.js";
|
|
@@ -23,7 +22,6 @@ export { FileSessionPolicyStore, type FileSessionPolicyStoreOptions, type Sessio
|
|
|
23
22
|
export { FileFileHistoryStore, type FileFileHistoryStoreOptions } from "./file-history-store.js";
|
|
24
23
|
export { FileWorkflowJournalStore, MAX_JOURNAL_RESULT_BYTES, oversizeJournalResult } from "./workflow-journal-store.js";
|
|
25
24
|
export { FileUsageWindowStore, type FileUsageWindowStoreOptions } from "./usage-window-store.js";
|
|
26
|
-
export { FileStrategyStore, type FileStrategyStoreOptions } from "./strategy-store.js";
|
|
27
25
|
export { resolveDataRoot, sanitizeScope, sanitizePathComponent, createFileConsolidationLock } from "./fs-atomic.js";
|
|
28
26
|
export { FileStoreLockError, type FileStoreLockErrorCode } from "./fs-atomic.js";
|
|
29
27
|
export { atomicWriteFile, writeThenLink, ensureDir, readJsonlRecords, AppendLog } from "./fs-atomic.js";
|
|
@@ -152,12 +150,6 @@ export declare class FileStorageBackend {
|
|
|
152
150
|
/** design/151 §7 S3c — the durable SendMessage mailbox (tier-3 parking lane), same data root.
|
|
153
151
|
* Wire into `RunnerDeps.mailboxStore` (single-instance pairing, same as above). */
|
|
154
152
|
readonly mailboxStore: MailboxStore;
|
|
155
|
-
/** File-backed teacher-mode strategy repository (`root/strategies`) — pass as
|
|
156
|
-
* `TeacherConfig.strategyStore` (with a `scope`) so escalation strategies survive a restart;
|
|
157
|
-
* the in-memory default forgets everything each process, which zeroes the cross-session reuse
|
|
158
|
-
* the repository exists for. Aggregated here so the TOC full-persistence assembly stays one
|
|
159
|
-
* constructor (the same half-wiring hazard as the delegation trio). */
|
|
160
|
-
readonly strategyStore: StrategyStore;
|
|
161
153
|
/** design/147 S1c — the durable name→agent roster (layer 0.5 resolution), `root/roster.json`.
|
|
162
154
|
* Wire into `RunnerDeps.rosterStore` so name-addressing survives a restart alongside the rows. */
|
|
163
155
|
readonly rosterStore: RosterStore;
|
|
@@ -13,7 +13,6 @@ import { FileUsageWindowStore } from "./usage-window-store.js";
|
|
|
13
13
|
import { FileBackgroundAgentStore } from "./background-agent-store.js";
|
|
14
14
|
import { FileMailboxStore } from "./mailbox-store.js";
|
|
15
15
|
import { FileRosterStore } from "../../agents/roster-store.js";
|
|
16
|
-
import { FileStrategyStore } from "./strategy-store.js";
|
|
17
16
|
import { FileFileHistoryStore } from "./file-history-store.js";
|
|
18
17
|
export { FileCheckpointStore } from "./checkpoint-store.js";
|
|
19
18
|
export { FileMemoryStore } from "./memory-store.js";
|
|
@@ -23,7 +22,6 @@ export { FileSessionPolicyStore } from "./session-policy-store.js";
|
|
|
23
22
|
export { FileFileHistoryStore } from "./file-history-store.js";
|
|
24
23
|
export { FileWorkflowJournalStore, MAX_JOURNAL_RESULT_BYTES, oversizeJournalResult } from "./workflow-journal-store.js";
|
|
25
24
|
export { FileUsageWindowStore } from "./usage-window-store.js";
|
|
26
|
-
export { FileStrategyStore } from "./strategy-store.js";
|
|
27
25
|
export { resolveDataRoot, sanitizeScope, sanitizePathComponent, createFileConsolidationLock } from "./fs-atomic.js";
|
|
28
26
|
export { FileStoreLockError } from "./fs-atomic.js";
|
|
29
27
|
export { atomicWriteFile, writeThenLink, ensureDir, readJsonlRecords, AppendLog } from "./fs-atomic.js";
|
|
@@ -41,7 +39,6 @@ export class FileStorageBackend {
|
|
|
41
39
|
usageWindowStore;
|
|
42
40
|
backgroundAgentStore;
|
|
43
41
|
mailboxStore;
|
|
44
|
-
strategyStore;
|
|
45
42
|
rosterStore;
|
|
46
43
|
fileHistoryStore;
|
|
47
44
|
consolidationLock;
|
|
@@ -84,15 +81,6 @@ export class FileStorageBackend {
|
|
|
84
81
|
built.push(() => this.fileMailbox.close());
|
|
85
82
|
this.mailboxStore = this.fileMailbox;
|
|
86
83
|
this.rosterStore = new FileRosterStore(join(this.root, "roster.json"), corruptRead ?? {});
|
|
87
|
-
const strategiesRoot = join(this.root, "strategies");
|
|
88
|
-
this.strategyStore = new FileStrategyStore({
|
|
89
|
-
root: strategiesRoot,
|
|
90
|
-
...(opts.onCorruptRead !== undefined
|
|
91
|
-
? {
|
|
92
|
-
onIncident: (i) => opts.onCorruptRead?.({ kind: "file", path: i.path ?? strategiesRoot, reason: `strategy ${i.op}: ${i.error}` }),
|
|
93
|
-
}
|
|
94
|
-
: {}),
|
|
95
|
-
});
|
|
96
84
|
this.fileHistoryStore = new FileFileHistoryStore(this.root, { ...(opts.fileHistory ?? {}), ...(corruptRead ?? {}) });
|
|
97
85
|
this.consolidationLock = createFileConsolidationLock(join(this.root, "consolidation-locks"));
|
|
98
86
|
}
|
|
@@ -72,6 +72,9 @@ export declare class FileSessionRepo implements SessionRepo {
|
|
|
72
72
|
olderThanMs?: number;
|
|
73
73
|
scope?: string;
|
|
74
74
|
}): Promise<PlacedSessionRow[]>;
|
|
75
|
+
/** The row as it stands before a file-replacing write: `undefined` ⇔ there is no row (no file); a row
|
|
76
|
+
* whose header cannot be read answers an empty header (it exists, its cells are unknown). */
|
|
77
|
+
private priorHeader;
|
|
75
78
|
/** Cheap placement probe for one id (the TtlSessionStore's cold-cache release consults it so the
|
|
76
79
|
* placed real-deletion obligation holds after a restart). `undefined` = missing file OR unplaced. */
|
|
77
80
|
placementOf(sessionId: string): Promise<SessionPlacementRecord | undefined>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, rmSync, statSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { BaseSessionStorage, StoredSession, SessionError, getEntriesToFork, uuidv7, validateEntriesForImport, } from "../../internal/harness.js";
|
|
3
|
+
import { BaseSessionStorage, StoredSession, SessionError, assertForkTarget, forkRowCells, getEntriesToFork, incarnationCell, uuidv7, validateEntriesForImport, } from "../../internal/harness.js";
|
|
4
4
|
import { canonicalStoreKey, AppendLog, atomicWriteFile, ensureDir, readJsonlRecords, sanitizePathComponent } from "./fs-atomic.js";
|
|
5
5
|
import { guardCorruptSink } from "./corrupt-read-sink.js";
|
|
6
6
|
import { assertAdoptionBootGate } from "./adoption/marker.js";
|
|
@@ -102,10 +102,25 @@ export class FileSessionRepo {
|
|
|
102
102
|
if (meta === undefined) {
|
|
103
103
|
throw new SessionError("corrupt_session", `Session ${id} is unreadable: its log has no meta header (${tally?.dropped ?? 0} of ${tally?.total ?? lines.length} records skipped as corrupt)`);
|
|
104
104
|
}
|
|
105
|
-
const { createdAt, forkedFrom, placement } = meta;
|
|
106
|
-
|
|
105
|
+
const { createdAt, forkedFrom, placement, incarnation, forkedFromIncarnation } = meta;
|
|
106
|
+
for (const [key, token] of [["incarnation", incarnation], ["forkedFromIncarnation", forkedFromIncarnation]]) {
|
|
107
|
+
if (token !== undefined && typeof token !== "string")
|
|
108
|
+
this.disclose(path, `session header carries a non-string ${key} (${typeof token}) — read as an UNKNOWN occupant`, id);
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
meta: {
|
|
112
|
+
id,
|
|
113
|
+
createdAt,
|
|
114
|
+
...(forkedFrom !== undefined ? { forkedFrom } : {}),
|
|
115
|
+
...(placement !== undefined ? { placement } : {}),
|
|
116
|
+
...(typeof incarnation === "string" ? { incarnation } : {}),
|
|
117
|
+
...(typeof forkedFromIncarnation === "string" ? { forkedFromIncarnation } : {}),
|
|
118
|
+
},
|
|
119
|
+
entries,
|
|
120
|
+
};
|
|
107
121
|
}
|
|
108
|
-
storage(
|
|
122
|
+
storage(meta, entries) {
|
|
123
|
+
const { id } = meta;
|
|
109
124
|
const canonical = canonicalStoreKey(this.pathFor(id));
|
|
110
125
|
const live = sharedSessionStorages.get(canonical)?.deref();
|
|
111
126
|
if (live !== undefined) {
|
|
@@ -114,7 +129,7 @@ export class FileSessionRepo {
|
|
|
114
129
|
return live;
|
|
115
130
|
}
|
|
116
131
|
const log = new AppendLog(this.pathFor(id));
|
|
117
|
-
const created = new FileSessionStorage(log,
|
|
132
|
+
const created = new FileSessionStorage(log, meta, entries, canonical);
|
|
118
133
|
sharedSessionStorages.set(canonical, new WeakRef(created));
|
|
119
134
|
created.addHolder(this);
|
|
120
135
|
this.joined.set(canonical, new WeakRef(created));
|
|
@@ -140,15 +155,16 @@ export class FileSessionRepo {
|
|
|
140
155
|
if (!existsSync(path)) {
|
|
141
156
|
evictSharedSessionStorage(canonicalStoreKey(path));
|
|
142
157
|
const placement = options.placement !== undefined ? { ...options.placement, placedAt: options.placement.placedAt ?? Date.now() } : undefined;
|
|
143
|
-
|
|
144
|
-
|
|
158
|
+
const meta = { id, createdAt, ...(placement !== undefined ? { placement } : {}), ...incarnationCell(undefined) };
|
|
159
|
+
atomicWriteFile(this.tmpDir, path, `${JSON.stringify({ kind: "meta", ...meta })}\n`);
|
|
160
|
+
return new StoredSession(this.storage(meta, []));
|
|
145
161
|
}
|
|
146
|
-
const {
|
|
147
|
-
return new StoredSession(this.storage(
|
|
162
|
+
const { meta, entries } = this.read(id);
|
|
163
|
+
return new StoredSession(this.storage({ ...meta, createdAt: meta.createdAt || createdAt }, entries));
|
|
148
164
|
}
|
|
149
165
|
async open(metadata) {
|
|
150
|
-
const {
|
|
151
|
-
return new StoredSession(this.storage(
|
|
166
|
+
const { meta, entries } = this.read(metadata.id);
|
|
167
|
+
return new StoredSession(this.storage(meta, entries));
|
|
152
168
|
}
|
|
153
169
|
async list() {
|
|
154
170
|
let names;
|
|
@@ -167,7 +183,7 @@ export class FileSessionRepo {
|
|
|
167
183
|
continue;
|
|
168
184
|
const id = name.slice(0, -SUFFIX.length);
|
|
169
185
|
try {
|
|
170
|
-
const { createdAt, forkedFrom, placement } = this.read(id);
|
|
186
|
+
const { createdAt, forkedFrom, placement } = this.read(id).meta;
|
|
171
187
|
if (placement !== undefined)
|
|
172
188
|
continue;
|
|
173
189
|
out.push({ id, createdAt, ...(forkedFrom !== undefined ? { forkedFrom } : {}) });
|
|
@@ -199,7 +215,7 @@ export class FileSessionRepo {
|
|
|
199
215
|
const id = name.slice(0, -SUFFIX.length);
|
|
200
216
|
let placement;
|
|
201
217
|
try {
|
|
202
|
-
placement = this.read(id).placement;
|
|
218
|
+
placement = this.read(id).meta.placement;
|
|
203
219
|
}
|
|
204
220
|
catch (err) {
|
|
205
221
|
if (!(err instanceof SessionError && err.code === "not_found")) {
|
|
@@ -227,9 +243,17 @@ export class FileSessionRepo {
|
|
|
227
243
|
}
|
|
228
244
|
return out;
|
|
229
245
|
}
|
|
246
|
+
priorHeader(id) {
|
|
247
|
+
try {
|
|
248
|
+
return this.read(id).meta;
|
|
249
|
+
}
|
|
250
|
+
catch (err) {
|
|
251
|
+
return err instanceof SessionError && err.code === "not_found" ? undefined : {};
|
|
252
|
+
}
|
|
253
|
+
}
|
|
230
254
|
async placementOf(sessionId) {
|
|
231
255
|
try {
|
|
232
|
-
return this.read(sessionId).placement;
|
|
256
|
+
return this.read(sessionId).meta.placement;
|
|
233
257
|
}
|
|
234
258
|
catch {
|
|
235
259
|
return undefined;
|
|
@@ -245,20 +269,20 @@ export class FileSessionRepo {
|
|
|
245
269
|
}
|
|
246
270
|
}
|
|
247
271
|
async fork(sourceMetadata, options = {}) {
|
|
272
|
+
assertForkTarget(sourceMetadata.id, options.id);
|
|
248
273
|
const source = await this.open(sourceMetadata);
|
|
249
274
|
const forked = await getEntriesToFork(source.getStorage(), options);
|
|
250
275
|
const id = options.id ?? uuidv7();
|
|
251
276
|
const createdAt = new Date().toISOString();
|
|
252
277
|
const path = this.pathFor(id);
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
];
|
|
278
|
+
const meta = { id, createdAt, ...forkRowCells(await source.getMetadata()) };
|
|
279
|
+
const lines = [JSON.stringify({ kind: "meta", ...meta })];
|
|
256
280
|
for (const entry of forked) {
|
|
257
281
|
lines.push(JSON.stringify({ kind: "entry", entry }));
|
|
258
282
|
}
|
|
259
283
|
evictSharedSessionStorage(canonicalStoreKey(path));
|
|
260
284
|
atomicWriteFile(this.tmpDir, path, `${lines.join("\n")}\n`);
|
|
261
|
-
return new StoredSession(this.storage(
|
|
285
|
+
return new StoredSession(this.storage(meta, [...forked]));
|
|
262
286
|
}
|
|
263
287
|
async exportEntries(sessionId) {
|
|
264
288
|
return this.read(sessionId).entries;
|
|
@@ -266,9 +290,10 @@ export class FileSessionRepo {
|
|
|
266
290
|
async importEntries(sessionId, owner, entries, options) {
|
|
267
291
|
void owner;
|
|
268
292
|
const validated = validateEntriesForImport(entries, options);
|
|
293
|
+
const prior = this.priorHeader(sessionId);
|
|
269
294
|
evictSharedSessionStorage(canonicalStoreKey(this.pathFor(sessionId)));
|
|
270
295
|
const createdAt = new Date().toISOString();
|
|
271
|
-
const lines = [JSON.stringify({ kind: "meta", id: sessionId, createdAt })];
|
|
296
|
+
const lines = [JSON.stringify({ kind: "meta", id: sessionId, createdAt, ...incarnationCell(prior) })];
|
|
272
297
|
for (const entry of validated) {
|
|
273
298
|
lines.push(JSON.stringify({ kind: "entry", entry }));
|
|
274
299
|
}
|
|
@@ -5,6 +5,7 @@ import { Type } from "typebox";
|
|
|
5
5
|
import { ARTIFACT_ACTION_CONCURRENCY_SAFE, ARTIFACT_COMMIT_THROW_OUTCOME, ARTIFACT_FAILURE_RESULT_CODE, ARTIFACT_HOST_ERROR_CODE, ARTIFACT_LIST_SCOPES, ARTIFACT_PLANE_CONTENT_ORIGIN, ARTIFACT_PUBLISH_CONTEXTS, } from "../../core/artifact-host.js";
|
|
6
6
|
import { ARTIFACT_TOOL_NAME, toolFace } from "../../core/tool-catalog-entries.js";
|
|
7
7
|
import { resolveAsk } from "../../core/tool-policy.js";
|
|
8
|
+
import { approvalCardOf } from "../../core/tool-roster.js";
|
|
8
9
|
import { errorResult } from "../../core/tools.js";
|
|
9
10
|
import { inlineUntrusted } from "../../core/untrusted-text.js";
|
|
10
11
|
import { actionDescription, artifactDescription, PARAM_TEXT, urlDescription } from "./artifact-text.js";
|
|
@@ -343,6 +344,7 @@ export function createArtifactTool(opts) {
|
|
|
343
344
|
args: { action: "read", url },
|
|
344
345
|
message: `Read a shared artifact: ${inlineUntrusted(url, 300)}${title}${version} — an artifact another person shared with this user; approving covers re-reads of it for the rest of this run.`,
|
|
345
346
|
requiresRealApproval: true,
|
|
347
|
+
approvalCard: approvalCardOf({ toolName: ARTIFACT_TOOL_NAME }, toolFace("artifact").renderHints?.approvalCard),
|
|
346
348
|
}, onAsk, ctx.signal);
|
|
347
349
|
if (resolved.action !== "allow")
|
|
348
350
|
return { ok: false, reason: resolved.message ?? "not approved" };
|
|
@@ -16,9 +16,8 @@ export declare const NOT_AUTO_ALLOWED = "\u2014 not auto-allowed";
|
|
|
16
16
|
export declare function programBasename(word: string): string;
|
|
17
17
|
/**
|
|
18
18
|
* The `NAME=` / `NAME+=` prefix as WRITTEN in a whitespace-split token. This is NOT the position reader's grammar
|
|
19
|
-
* — the reader reads the lexer's {@link LexedWord.assignment} fact — but the
|
|
20
|
-
* command TEXT rather than its words (the
|
|
21
|
-
* they read it here so that they read one spelling. It retires with them.
|
|
19
|
+
* — the reader reads the lexer's {@link LexedWord.assignment} fact — but the one reader that still walks the
|
|
20
|
+
* command TEXT rather than its words (the activity summary) reads it here. It retires with it.
|
|
22
21
|
*/
|
|
23
22
|
export declare const ASSIGNMENT_PREFIX: RegExp;
|
|
24
23
|
/** The prefix a whitespace-split token BEGINS with, or `undefined` — the text readers' view of
|
|
@@ -30,10 +29,21 @@ export declare function writtenAssignmentPrefix(token: string): {
|
|
|
30
29
|
readonly appends: boolean;
|
|
31
30
|
readonly settlesWholeName: boolean;
|
|
32
31
|
} | undefined;
|
|
32
|
+
/** The names a segment's COMMAND ENVIRONMENT sets for the program it starts: the assignment words in front of the
|
|
33
|
+
* program (the lexer's {@link LexedWord.assignment} fact, a launcher's `NAME=value` operand included) — or `all` where
|
|
34
|
+
* a launcher in front of it may set, clear or replace the environment (`env -u` / `-i`, `sudo`, `su`, …). */
|
|
35
|
+
export declare function commandEnvironmentNames(argv: readonly LexedWord[]): ReadonlySet<string> | "all";
|
|
33
36
|
export { SHELL_CONTROL_PREFIXES };
|
|
34
37
|
/** A control word is a keyword only when bash sees it BARE: `'if'` / `"do"` / `\\!` are command names (a program
|
|
35
38
|
* looked up on PATH, whose failure changes nothing), so a quoted or escaped spelling never counts as one. */
|
|
36
39
|
export declare function isBareControlWord(words: readonly LexedWord[], i: number, set: ReadonlySet<string>): boolean;
|
|
40
|
+
/** Does the shell read this word as syntax — a reserved word, a control word, `{`, `coproc` — of `set`? Only a word
|
|
41
|
+
* written BARE where bash reads a command's first word (the lexer's {@link LexedWord.atCommandPosition}): a quoted or
|
|
42
|
+
* escaped spelling is a command name, and a word an expansion produced (a value, a split field) is never syntax —
|
|
43
|
+
* bash parses the line before it expands it. The one reading every syntax reader of a command's words asks. */
|
|
44
|
+
export declare function isShellSyntaxWord(w: LexedWord | undefined, set: ReadonlySet<string>): boolean;
|
|
45
|
+
/** The words that head a loop over a list (`for NAME in …`, `select NAME in …`). */
|
|
46
|
+
export declare const LOOP_LIST_HEADS: ReadonlySet<string>;
|
|
37
47
|
/**
|
|
38
48
|
* A word bash strips as an ASSIGNMENT before it chooses the program: the lexer's assignment fact, written BARE
|
|
39
49
|
* (the name, the brackets and the operator unquoted — a quoted VALUE still assigns, a quoted operator is a
|
|
@@ -92,6 +102,10 @@ export interface ProgramPosition {
|
|
|
92
102
|
} | undefined;
|
|
93
103
|
/** Why no program could be read; `undefined` beside `program: undefined` means the chain simply names none. */
|
|
94
104
|
readonly refusal: ProgramPositionRefusal | undefined;
|
|
105
|
+
/** A launcher of the chain moves the directory or the root the program runs in, or where its word is looked up
|
|
106
|
+
* (`env -C <dir>`, `sudo -R <dir>`, `env -P <dirs>`): the program is still the word it names, but where its path
|
|
107
|
+
* operands resolve is not the command line's working directory — each consumer reads that as it must. */
|
|
108
|
+
readonly launcherMovesBase: boolean;
|
|
95
109
|
}
|
|
96
110
|
/**
|
|
97
111
|
* Read the program position of one segment's argv words.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SHELL_CONTROL_PREFIXES } from "../../shell/lex.js";
|
|
2
|
-
import {
|
|
2
|
+
import { shellWordsOf } from "../../shell/shell-words.js";
|
|
3
|
+
import { BLOCK_WORD_NAMES, LAUNCHER_NAMES, feedsArgvFromStdin, launcherOptionMovesBase, launcherOptionStep, launcherRunsShell, programRow, selectedOptions, streamDefaultProgram } from "./program-read-model.js";
|
|
3
4
|
export const NOT_AUTO_ALLOWED = "— not auto-allowed";
|
|
4
5
|
export function programBasename(word) {
|
|
5
6
|
return word.includes("/") ? (word.split("/").pop() ?? word) : word;
|
|
@@ -14,11 +15,21 @@ export function writtenAssignmentPrefix(token) {
|
|
|
14
15
|
const bracket = written.indexOf("[");
|
|
15
16
|
return { prefix, name: bracket < 0 ? written : written.slice(0, bracket), appends, settlesWholeName: !appends && bracket < 0 };
|
|
16
17
|
}
|
|
18
|
+
const ENVIRONMENT_KEEPING_LAUNCHERS = new Set(["nice", "nohup", "time", "timeout", "stdbuf", "ionice", "chrt", "taskset", "command", "builtin", "caffeinate"]);
|
|
19
|
+
export function commandEnvironmentNames(argv) {
|
|
20
|
+
const pos = readProgramPosition(argv);
|
|
21
|
+
if (pos.launchers.some((l) => !ENVIRONMENT_KEEPING_LAUNCHERS.has(l.name)))
|
|
22
|
+
return "all";
|
|
23
|
+
return new Set(argv.slice(0, pos.program?.index ?? argv.length).flatMap((w) => (w.assignment?.bare === true ? [w.assignment.name] : [])));
|
|
24
|
+
}
|
|
17
25
|
export { SHELL_CONTROL_PREFIXES };
|
|
18
26
|
export function isBareControlWord(words, i, set) {
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
return isShellSyntaxWord(words[i], set);
|
|
28
|
+
}
|
|
29
|
+
export function isShellSyntaxWord(w, set) {
|
|
30
|
+
return w !== undefined && w.atCommandPosition && w.raw === w.folded && set.has(w.folded);
|
|
21
31
|
}
|
|
32
|
+
export const LOOP_LIST_HEADS = shellWordsOf("loop_list_head");
|
|
22
33
|
export function isLeadingAssignmentWord(words, i) {
|
|
23
34
|
const w = words[i];
|
|
24
35
|
return w !== undefined && w.assignment !== undefined && w.assignment.bare && w.atCommandPosition;
|
|
@@ -27,7 +38,7 @@ function launcherRowOf(name) {
|
|
|
27
38
|
const row = programRow(name);
|
|
28
39
|
return row?.launcher !== undefined ? row : undefined;
|
|
29
40
|
}
|
|
30
|
-
function pastLauncherOptions(launcher, folded, i) {
|
|
41
|
+
function pastLauncherOptions(launcher, folded, i, moved) {
|
|
31
42
|
const row = launcherRowOf(launcher);
|
|
32
43
|
if (row === undefined)
|
|
33
44
|
return i;
|
|
@@ -44,6 +55,8 @@ function pastLauncherOptions(launcher, folded, i) {
|
|
|
44
55
|
return i;
|
|
45
56
|
if (step === 2 && folded[i + 1] === undefined)
|
|
46
57
|
return i;
|
|
58
|
+
if (launcherOptionMovesBase(row, tok))
|
|
59
|
+
moved?.();
|
|
47
60
|
i += step;
|
|
48
61
|
}
|
|
49
62
|
}
|
|
@@ -57,7 +70,7 @@ export function readProgramPosition(words) {
|
|
|
57
70
|
controlWords.push(i);
|
|
58
71
|
i = pastLauncherOptions(controlWord, folded, i + 1);
|
|
59
72
|
}
|
|
60
|
-
const none = (written, assignments, refusal) => ({ controlWords, written, assignments, launchers: [], argvFromStdin: false, runsDefaultProgram: false, program: undefined, refusal });
|
|
73
|
+
const none = (written, assignments, refusal) => ({ controlWords, written, assignments, launchers: [], argvFromStdin: false, runsDefaultProgram: false, program: undefined, refusal, launcherMovesBase: false });
|
|
61
74
|
if (i >= folded.length)
|
|
62
75
|
return none(undefined, []);
|
|
63
76
|
const written = i;
|
|
@@ -75,25 +88,27 @@ export function readProgramPosition(words) {
|
|
|
75
88
|
return none(written, assignments, { kind: "option_at_program_position", owner, option: head });
|
|
76
89
|
}
|
|
77
90
|
if (!LAUNCHER_NAMES.has(basename)) {
|
|
78
|
-
return { controlWords, written, assignments, launchers: [], argvFromStdin: false, runsDefaultProgram: false, program: { index: i, name: head, basename }, refusal: undefined };
|
|
91
|
+
return { controlWords, written, assignments, launchers: [], argvFromStdin: false, runsDefaultProgram: false, program: { index: i, name: head, basename }, refusal: undefined, launcherMovesBase: false };
|
|
79
92
|
}
|
|
80
93
|
const launchers = [{ index: i, name: basename }];
|
|
81
94
|
const owner = head;
|
|
82
95
|
const shellRefusal = (launcher, from) => ({ kind: "control_syntax_at_program_position", owner, word: "sh", runsShell: { launcher, from } });
|
|
83
96
|
let lastRow = launcherRowOf(basename)?.launcher;
|
|
84
97
|
let owedOperands = lastRow?.requiredOperands ?? 0;
|
|
85
|
-
const chain0 = (program, refusal) => ({ controlWords, written, assignments, launchers, argvFromStdin: false, runsDefaultProgram: false, program, refusal });
|
|
98
|
+
const chain0 = (program, refusal) => ({ controlWords, written, assignments, launchers, argvFromStdin: false, runsDefaultProgram: false, program, refusal, launcherMovesBase: false });
|
|
86
99
|
if (launcherRunsShell(launcherRowOf(basename), folded.slice(i + 1)))
|
|
87
100
|
return chain0(undefined, shellRefusal(i, i + 1));
|
|
88
101
|
let argvFromStdin = feedsArgvFromStdin(basename);
|
|
89
102
|
let lastReentry = argvFromStdin ? i : -1;
|
|
90
103
|
let reentryDefault = argvFromStdin ? streamDefaultProgram(basename) : undefined;
|
|
104
|
+
let launcherMovesBase = false;
|
|
105
|
+
const moved = () => { launcherMovesBase = true; };
|
|
91
106
|
const chain = (program, refusal) => {
|
|
92
107
|
const runsDefaultProgram = lastReentry === folded.length - 1;
|
|
93
|
-
return { controlWords, written, assignments, launchers, argvFromStdin, runsDefaultProgram, ...(runsDefaultProgram && reentryDefault !== undefined ? { defaultProgram: reentryDefault } : {}), program, refusal };
|
|
108
|
+
return { controlWords, written, assignments, launchers, argvFromStdin, runsDefaultProgram, ...(runsDefaultProgram && reentryDefault !== undefined ? { defaultProgram: reentryDefault } : {}), program, refusal, launcherMovesBase };
|
|
94
109
|
};
|
|
95
110
|
const selectsShell = (l, end) => selectedOptions(launcherRowOf(l.name), folded.slice(l.index + 1, end)).some((o) => o.mode === "interactive");
|
|
96
|
-
for (let j = pastLauncherOptions(basename, folded, i + 1); j < folded.length; j++) {
|
|
111
|
+
for (let j = pastLauncherOptions(basename, folded, i + 1, moved); j < folded.length; j++) {
|
|
97
112
|
const t = folded[j];
|
|
98
113
|
if (owedOperands > 0 && !t.startsWith("-")) {
|
|
99
114
|
owedOperands -= 1;
|
|
@@ -118,7 +133,7 @@ export function readProgramPosition(words) {
|
|
|
118
133
|
if (launcherRunsShell(launcherRowOf(wordBasename), folded.slice(j + 1)))
|
|
119
134
|
return chain(undefined, shellRefusal(j, j + 1));
|
|
120
135
|
owedOperands = lastRow?.requiredOperands ?? 0;
|
|
121
|
-
j = pastLauncherOptions(wordBasename, folded, j + 1) - 1;
|
|
136
|
+
j = pastLauncherOptions(wordBasename, folded, j + 1, moved) - 1;
|
|
122
137
|
continue;
|
|
123
138
|
}
|
|
124
139
|
if (t.startsWith("-"))
|
|
@@ -361,7 +361,7 @@ export declare function formatOutOfRootReadApprovalOption(directory: string): st
|
|
|
361
361
|
* resolved to nothing, was dropped, and the verdict was empty, i.e. a read outside every root
|
|
362
362
|
* AUTO-ALLOWED on the one face whose doctrine is hard refusal in exactly that direction.
|
|
363
363
|
* The second fact is why the lane split in
|
|
364
|
-
* {@link collectSegmentBoundaryFindings} tests {@link
|
|
364
|
+
* {@link collectSegmentBoundaryFindings} tests {@link isAbsoluteForFamily} (an address's own family) BESIDE this predicate,
|
|
365
365
|
* which is what the option-payload arm always did; the two now read one rule rather than two. */
|
|
366
366
|
export declare function isPathShapedToken(tok: string): boolean;
|
|
367
367
|
/** Resolve one operand against the boundary's base, WITHOUT touching the filesystem. Returns undefined
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { anchorSpelling, isAbsoluteForFamily, isBlockedDevicePath, isShellRootedSpellingUnmapped, nativeUncSpellingOf, normalizeAbsPathLexically, win32NamespaceScreen, pathFamilyOf } from "./safety.js";
|
|
2
2
|
import { PARSE_FAILURE_SENTENCE, UNRESOLVED_SENTENCE, argvOf, lexShell, literalTildeSpelling, } from "../../shell/lex.js";
|
|
3
|
+
import { shellWordsOf } from "../../shell/shell-words.js";
|
|
3
4
|
import { textBindsHome } from "./shell-read-bindings.js";
|
|
4
5
|
import { NOT_AUTO_ALLOWED, argvReentryUnjudged, isBareControlWord, programPositionRefusalSentence, readProgramPosition, } from "./bash-program-position.js";
|
|
5
6
|
import { BLOCK_WORD_NAMES, attachedStdinFile, declaresOption, firstOperandSlot, opensNoOperand, programDelivery, programRow, programTextReadings, readArgRoles, readArgs, readProgramTextLanguage, runsShellText, selectedOptions, slotValueCandidates, suppliesFirstOperandSlot, takesSeparatedDatum, valuesAreLiteral, writeReadings, writesPath, } from "./program-read-model.js";
|
|
@@ -171,7 +172,7 @@ const PARENT_SEGMENT_RE = /(?:^|[\\/])\.\.(?:[\\/]|$)/;
|
|
|
171
172
|
export function resolveOperandSpellings(base, operand, homeDir) {
|
|
172
173
|
let raw = operand;
|
|
173
174
|
if (raw === "~" || raw.startsWith("~/")) {
|
|
174
|
-
if (homeDir === undefined || !
|
|
175
|
+
if (homeDir === undefined || !isAbsoluteForFamily("own", homeDir))
|
|
175
176
|
return undefined;
|
|
176
177
|
raw = raw === "~" ? homeDir : `${homeDir.replace(/[/\\]+$/, "")}/${raw.slice(2)}`;
|
|
177
178
|
}
|
|
@@ -181,13 +182,13 @@ export function resolveOperandSpellings(base, operand, homeDir) {
|
|
|
181
182
|
const family = base === undefined ? undefined : pathFamilyOf({ root: base });
|
|
182
183
|
if (!win32NamespaceScreen(raw, family).ok)
|
|
183
184
|
return undefined;
|
|
184
|
-
if (isAbsoluteForFamily(family, raw))
|
|
185
|
+
if (isAbsoluteForFamily(family ?? "own", raw))
|
|
185
186
|
return spellingsOf(nativeUncSpellingOf(family, raw));
|
|
186
187
|
if (base === undefined || family === undefined || !isAbsoluteForFamily(family, base))
|
|
187
188
|
return undefined;
|
|
188
189
|
if (isShellRootedSpellingUnmapped(family, raw))
|
|
189
190
|
return undefined;
|
|
190
|
-
return spellingsOf(
|
|
191
|
+
return spellingsOf(anchorSpelling(family, base, raw));
|
|
191
192
|
}
|
|
192
193
|
function spellingsOf(absolute) {
|
|
193
194
|
const folded = normalizeAbsPathLexically(absolute);
|
|
@@ -660,7 +661,7 @@ export function attachedOptionPayloads(tok) {
|
|
|
660
661
|
return out;
|
|
661
662
|
}
|
|
662
663
|
const whole = literal(tok.slice(1));
|
|
663
|
-
if (whole.length > 0 && (isPathShapedToken(whole) ||
|
|
664
|
+
if (whole.length > 0 && (isPathShapedToken(whole) || isAbsoluteForFamily("own", whole)))
|
|
664
665
|
out.push(whole);
|
|
665
666
|
for (let k = 2; k <= tok.length; k++) {
|
|
666
667
|
if (![...tok.slice(1, k)].every((ch) => CLUSTER_OPTION_CHAR.test(ch)))
|
|
@@ -744,7 +745,7 @@ export function classifyCompoundReadonlyDetailed(command, allow, boundary) {
|
|
|
744
745
|
const written = folded[from];
|
|
745
746
|
if (written === undefined)
|
|
746
747
|
return { reason: "empty command" };
|
|
747
|
-
if (
|
|
748
|
+
if (shellWordsOf("background").has(written))
|
|
748
749
|
return { reason: "`coproc` backgrounds a command — a backgrounded process outlives the command" };
|
|
749
750
|
if (isBareControlWord(words, from, BLOCK_WORD_NAMES)) {
|
|
750
751
|
unlistedSegments.add(si);
|
|
@@ -777,7 +778,7 @@ export function classifyCompoundReadonlyDetailed(command, allow, boundary) {
|
|
|
777
778
|
if (runsShellText(name))
|
|
778
779
|
return { reason: unjudgedProgramTextRefusal(parsed.name, "runs its argument as shell text") };
|
|
779
780
|
if (pos.launchers.length > 0) {
|
|
780
|
-
const listed = program !== undefined &&
|
|
781
|
+
const listed = program !== undefined && allow.has(program.basename);
|
|
781
782
|
if (program !== undefined && !listed && runsShellText(program.basename)) {
|
|
782
783
|
return { reason: `"${written}" runs "${program.basename}", which runs its argument as shell text this classifier does not read ${NOT_AUTO_ALLOWED}` };
|
|
783
784
|
}
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
* type gates all still run). One type for both seats: the two faces differ in WHICH band consults
|
|
4
4
|
* them, never in what the word means. */
|
|
5
5
|
export type ContainmentFace = "open" | "roots";
|
|
6
|
+
/** Does a face state skip the roots-containment step? The ONE reading of a face seat a containment judgment takes — the
|
|
7
|
+
* structured tools' path check and the shell station's write face alike: `"open"` skips it; `"roots"` and an ABSENT
|
|
8
|
+
* state run it (absent ⇒ roots, the historical fence). */
|
|
9
|
+
export declare function skipsRootsContainment(face: ContainmentFace | undefined): boolean;
|
|
6
10
|
/** Which band a face governs. Selects the seat spellings and the error codes below — never the
|
|
7
11
|
* resolution ORDER, which is one body shared by both. */
|
|
8
12
|
export type ContainmentFaceKind = "read" | "write";
|
|
@@ -253,6 +253,16 @@ export declare function bashMaxOutputChars(): number;
|
|
|
253
253
|
export declare const FILE_PATH_PARAMS: {
|
|
254
254
|
file_path: Type.TString;
|
|
255
255
|
};
|
|
256
|
+
/**
|
|
257
|
+
* Write's pre-validation argument repair — CC 2.1.296 `orr` (the Write tool's `coerceInput`, cli296.js:247143),
|
|
258
|
+
* the two rules that matter under a non-strict schema: `path` is read as `file_path` when `file_path` is absent
|
|
259
|
+
* and `path` is a string; exactly one of `file_text` / `file_content` is read as `content` when `content` is
|
|
260
|
+
* absent and the value is a string. Anything else — both content aliases, a present `file_path`, a non-string
|
|
261
|
+
* value — is left to the schema, which refuses it by naming the parameter. The repaired key REPLACES the alias
|
|
262
|
+
* (it is deleted), so no second spelling rides on into the gates. Idempotent, and the very same object for a
|
|
263
|
+
* call that needs no repair (the loop's "prepared arguments changed" test is a reference test).
|
|
264
|
+
*/
|
|
265
|
+
export declare function coerceWriteArguments(args: unknown): unknown;
|
|
256
266
|
/** Honest head+tail truncation to {@link bashMaxOutputChars}: the middle is dropped with a real-total
|
|
257
267
|
* marker, because the head AND tail both matter for a shell. Kept as the inline shape even beside the
|
|
258
268
|
* file-backed recovery below — unlike a background task's poll-for-the-latest-tail interaction, a
|
|
@@ -185,6 +185,24 @@ export function bashMaxOutputChars() {
|
|
|
185
185
|
export const FILE_PATH_PARAMS = {
|
|
186
186
|
file_path: Type.String({ description: "File path (within the configured root)." }),
|
|
187
187
|
};
|
|
188
|
+
const WRITE_CONTENT_ALIASES = ["file_text", "file_content"];
|
|
189
|
+
export function coerceWriteArguments(args) {
|
|
190
|
+
if (args === null || typeof args !== "object" || Array.isArray(args))
|
|
191
|
+
return args;
|
|
192
|
+
const a = args;
|
|
193
|
+
let repaired;
|
|
194
|
+
if (!Object.hasOwn(a, "file_path") && typeof a["path"] === "string") {
|
|
195
|
+
repaired = { ...a, file_path: a["path"] };
|
|
196
|
+
delete repaired["path"];
|
|
197
|
+
}
|
|
198
|
+
const spelled = WRITE_CONTENT_ALIASES.filter((k) => Object.hasOwn(a, k));
|
|
199
|
+
const alias = spelled[0];
|
|
200
|
+
if (alias !== undefined && spelled.length === 1 && !Object.hasOwn(a, "content") && typeof a[alias] === "string") {
|
|
201
|
+
repaired = { ...(repaired ?? a), content: a[alias] };
|
|
202
|
+
delete repaired[alias];
|
|
203
|
+
}
|
|
204
|
+
return repaired ?? args;
|
|
205
|
+
}
|
|
188
206
|
export function clipShellOutput(s) {
|
|
189
207
|
return clipWithFilePointer(s, bashMaxOutputChars());
|
|
190
208
|
}
|
|
@@ -3,7 +3,7 @@ import { Type } from "typebox";
|
|
|
3
3
|
import { defineTool, errorResult } from "../../core/tools.js";
|
|
4
4
|
import { sha256, resolveKey, violationText, violationDetails, requireRead, checkStale, checkEditMatch, checkNoChange, fileArgPath, resolveQuoteMatch, adaptNewStringQuotes, resolveEscapeMatch, adaptNewStringEscapes, escapeMatchWasAttempted, ESCAPE_MATCH_MISS_NOTE, deletionOldString, countOccurrences, READ_REFUSED_ESCAPE_HINT, } from "./safety.js";
|
|
5
5
|
import { decodeTextBytes, encodeTextForFile, normalizeEditText, normalizeFileText } from "./encoding.js";
|
|
6
|
-
import { MAX_EDIT_BYTES, decodeEditBytes, tooLargeToEditMessage, truncatedUtf16BodyMessage, persistedTextOf, notReadRefusalText, enoentMessage, FILE_STATE_TRAILER, FILE_PATH_PARAMS, ipynbRedirect, countLines, applyRecordedEdit, } from "./fs-shared.js";
|
|
6
|
+
import { MAX_EDIT_BYTES, decodeEditBytes, tooLargeToEditMessage, truncatedUtf16BodyMessage, persistedTextOf, notReadRefusalText, enoentMessage, FILE_STATE_TRAILER, FILE_PATH_PARAMS, coerceWriteArguments, ipynbRedirect, countLines, applyRecordedEdit, } from "./fs-shared.js";
|
|
7
7
|
import { toolFace } from "../../core/tool-catalog-entries.js";
|
|
8
8
|
import { thrownText } from "../../core/thrown-value.js";
|
|
9
9
|
async function envFinalWrite(env, key, content, signal, opts) {
|
|
@@ -326,7 +326,7 @@ export function createEditFileTool(env, state, rootCanonical, cwdRef, additional
|
|
|
326
326
|
});
|
|
327
327
|
}
|
|
328
328
|
export function createWriteFileTool(env, state, rootCanonical, cwdRef, additionalRoots, beforeWrite, trackEdit, onEdited, writeFace, writeDeny) {
|
|
329
|
-
|
|
329
|
+
const write = defineTool({
|
|
330
330
|
name: "Write",
|
|
331
331
|
...toolFace("write"),
|
|
332
332
|
description: "Writes a file to the local filesystem, overwriting if one exists.\n" +
|
|
@@ -420,6 +420,8 @@ export function createWriteFileTool(env, state, rootCanonical, cwdRef, additiona
|
|
|
420
420
|
};
|
|
421
421
|
},
|
|
422
422
|
});
|
|
423
|
+
write.prepareArguments = coerceWriteArguments;
|
|
424
|
+
return write;
|
|
423
425
|
}
|
|
424
426
|
const notebookNotIpynbMessage = (notebookPath) => `Error (NotebookEdit): "${notebookPath}" is not a .ipynb file; use Edit for other file types.`;
|
|
425
427
|
const NOTEBOOK_CELL_TYPE_REQUIRED_MESSAGE = `Error (NotebookEdit): Cell type is required when using edit_mode=insert.`;
|
package/dist/tools/fs/index.d.ts
CHANGED
|
@@ -187,8 +187,9 @@ export interface HandsToolkitOptions {
|
|
|
187
187
|
* under a short bound of its own, and a probe of it that fails costs that entry alone. The public shell judgment takes the
|
|
188
188
|
* same list as {@link import("./shell-read-check.js").ShellReadJudgeInput.readDenyHomes}. */
|
|
189
189
|
readDenyHomes?: readonly string[];
|
|
190
|
-
/** Where each home-anchored row's literal head leads beyond the home's spellings
|
|
191
|
-
* ({@link import("./read-deny-home.js").
|
|
190
|
+
/** Where each home-anchored row's literal head leads beyond the home's spellings, and each rooted row's (`/…`) beyond its own
|
|
191
|
+
* spelling ({@link import("./read-deny-home.js").readDenyLinksOf},
|
|
192
|
+
* keyed by the row's pattern) — the Runner passes the
|
|
192
193
|
* locations its own judge was compiled with, so the band and the gate judge one placement.
|
|
193
194
|
* Unless a mount carries both, the band resolves the placement itself the way the Runner does (the homes it carries
|
|
194
195
|
* are its home set — the account is not asked and no home is added;
|
package/dist/tools/fs/index.js
CHANGED
|
@@ -14,7 +14,7 @@ export * from "./read-deny.js";
|
|
|
14
14
|
export { readDenyHomesOf } from "./read-deny-home.js";
|
|
15
15
|
import { BASH_READONLY_DEFAULT_ALLOW } from "./bash-readonly-classifier.js";
|
|
16
16
|
export { BASH_CLASSIFY_EXTRA_ALLOW, bashClassifyDefaultAllow } from "./bash-readonly-classifier.js";
|
|
17
|
-
import { checkedReadDenyHomes, compileReadDeny, compileWriteDeny, readDenyBuiltinConfigOf, readDenyPatternRun } from "./read-deny.js";
|
|
17
|
+
import { checkedReadDenyHomes, compileReadDeny, compileWriteDeny, isRootedReadDenyPattern, readDenyBuiltinConfigOf, readDenyPatternRun } from "./read-deny.js";
|
|
18
18
|
import { withGateTimeout } from "../../core/gate-bounded-await.js";
|
|
19
19
|
import { carryHomeViews, homeViewsAt, placeReadDenyAtHome, placementViewsOf, readDenyPlacedLater, sayPlacementLost } from "./read-deny-home.js";
|
|
20
20
|
import { deploymentFaceClampNotice, resolveContainmentFace } from "./containment-face.js";
|
|
@@ -51,7 +51,7 @@ export function createHandsToolkit(env, readFileState, rootCanonical, opts = {})
|
|
|
51
51
|
const carriedViews = carried ? placementViewsOf(opts.readDenyHomes) : undefined;
|
|
52
52
|
if (carried && carriedViews === undefined)
|
|
53
53
|
sayPlacementLost();
|
|
54
|
-
const placesNothing = !unplaced.entries.some((e) => readDenyPatternRun(e.pattern).homeAnchored);
|
|
54
|
+
const placesNothing = !unplaced.entries.some((e) => readDenyPatternRun(e.pattern).homeAnchored || isRootedReadDenyPattern(e.pattern));
|
|
55
55
|
const late = carried || placesNothing ? undefined : readDenyPlacedLater(carryHomeViews(unplaced, homeViewsAt(env, [])), () => placeReadDenyAtHome(env, compileAt, readDenyHomes));
|
|
56
56
|
const readDeny = late?.matcher ??
|
|
57
57
|
(carried
|