@sema-agent/core 7.55.0 → 7.56.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 +513 -0
- package/dist/agents/cascade.js +1 -1
- package/dist/agents/cc-peer-directory.js +1 -0
- package/dist/agents/child-model-seat.d.ts +0 -11
- package/dist/agents/child-model-seat.js +0 -3
- package/dist/agents/list-agents-tool.d.ts +3 -1
- package/dist/agents/list-agents-tool.js +7 -7
- package/dist/agents/peer-directory.d.ts +22 -4
- package/dist/agents/peer-directory.js +24 -2
- package/dist/agents/peer-session-drain.js +2 -2
- package/dist/agents/repair-loop.js +2 -2
- package/dist/agents/send-message-tool.js +4 -4
- package/dist/agents/subagent.d.ts +6 -4
- package/dist/agents/subagent.js +64 -60
- package/dist/agents/tool-filter.d.ts +7 -5
- package/dist/agents/tool-filter.js +12 -9
- package/dist/agents/verify.d.ts +3 -2
- package/dist/agents/verify.js +3 -3
- package/dist/brain/anthropic.js +30 -73
- package/dist/brain/media-degrade.d.ts +18 -7
- package/dist/brain/media-degrade.js +13 -2
- package/dist/brain/model-capability.d.ts +37 -0
- package/dist/brain/model-capability.js +34 -0
- package/dist/brain/model-presets.d.ts +2 -8
- package/dist/brain/model-presets.js +1 -6
- package/dist/brain/open-responses.js +13 -26
- package/dist/brain/openai.js +14 -87
- package/dist/brain/reasoning-request.d.ts +96 -0
- package/dist/brain/reasoning-request.js +174 -0
- package/dist/brain/reasoning.d.ts +11 -11
- package/dist/brain/reasoning.js +4 -3
- package/dist/brain/request-params.d.ts +7 -4
- package/dist/brain/request-params.js +7 -4
- package/dist/brain/status-sink.d.ts +20 -0
- package/dist/brain/status-sink.js +7 -0
- package/dist/core/a2a.d.ts +2 -1
- package/dist/core/a2a.js +19 -13
- package/dist/core/agent-definition.d.ts +10 -0
- package/dist/core/allow-entry.d.ts +20 -13
- package/dist/core/allow-entry.js +26 -22
- package/dist/core/allow-rule-shadow.d.ts +3 -3
- package/dist/core/ask-origin.d.ts +64 -18
- package/dist/core/ask-origin.js +63 -23
- package/dist/core/ask-question.d.ts +51 -8
- package/dist/core/ask-question.js +3 -4
- package/dist/core/ask-unresolvable-notice.d.ts +8 -3
- package/dist/core/ask-unresolvable-notice.js +16 -2
- package/dist/core/checkpoint-generation.d.ts +53 -0
- package/dist/core/checkpoint-generation.js +35 -0
- package/dist/core/checkpoint-queries.d.ts +180 -0
- package/dist/core/checkpoint-queries.js +272 -0
- package/dist/core/checkpoint-requirements.d.ts +13 -1
- package/dist/core/checkpoint-requirements.js +4 -0
- package/dist/core/checkpoint-store.d.ts +88 -24
- package/dist/core/checkpoint-store.js +24 -9
- package/dist/core/cross-boundary-taint.d.ts +6 -5
- package/dist/core/cross-boundary-taint.js +1 -3
- package/dist/core/decision-receipt.d.ts +37 -3
- package/dist/core/decision-receipt.js +17 -17
- package/dist/core/delegation-not-started.d.ts +6 -0
- package/dist/core/delegation-not-started.js +17 -0
- package/dist/core/engine-attestation.d.ts +93 -0
- package/dist/core/engine-attestation.js +70 -0
- package/dist/core/engine-capabilities.d.ts +4 -1
- package/dist/core/engine-capabilities.js +1 -1
- package/dist/core/engine-notice.d.ts +30 -11
- package/dist/core/file-history-store.d.ts +90 -14
- package/dist/core/file-history-store.js +23 -15
- package/dist/core/gate-fold.d.ts +1 -1
- package/dist/core/gate-fold.js +22 -10
- package/dist/core/gate-lanes.js +73 -64
- package/dist/core/gate-outcome.d.ts +26 -5
- package/dist/core/gate-outcome.js +26 -0
- package/dist/core/governance-codes.d.ts +5 -1
- package/dist/core/governance-codes.js +6 -0
- package/dist/core/hooks.d.ts +17 -16
- package/dist/core/hooks.js +3 -1
- package/dist/core/host-floor.d.ts +128 -0
- package/dist/core/host-floor.js +206 -0
- package/dist/core/host-target.d.ts +38 -3
- package/dist/core/host-target.js +38 -5
- package/dist/core/mcp.d.ts +5 -1
- package/dist/core/mcp.js +67 -41
- package/dist/core/memory-engine/delegation-settlement.js +15 -24
- package/dist/core/memory-engine/engine.js +4 -4
- package/dist/core/memory-engine/layout.d.ts +60 -8
- package/dist/core/memory-engine/layout.js +65 -6
- package/dist/core/model-seat.d.ts +10 -3
- package/dist/core/mods/classic-events.d.ts +67 -0
- package/dist/core/mods/classic-events.js +1 -0
- package/dist/core/mods/dollar.d.ts +13 -0
- package/dist/core/mods/extension-call.d.ts +31 -0
- package/dist/core/mods/extension-call.js +43 -0
- package/dist/core/mods/kernel/dispatch.d.ts +20 -3
- package/dist/core/mods/kernel/dispatch.js +140 -69
- package/dist/core/mods/kernel/events.d.ts +47 -11
- package/dist/core/mods/kernel/events.js +66 -42
- package/dist/core/mods/kernel/index.d.ts +4 -4
- package/dist/core/mods/kernel/index.js +2 -2
- package/dist/core/mods/kernel/receive.d.ts +39 -5
- package/dist/core/mods/kernel/receive.js +290 -17
- package/dist/core/mods/kernel/registration.d.ts +33 -2
- package/dist/core/mods/kernel/registration.js +6 -7
- package/dist/core/mods/kernel/site-rules.d.ts +44 -16
- package/dist/core/mods/kernel/site-rules.js +24 -42
- package/dist/core/mods/spec-seats.d.ts +69 -0
- package/dist/core/mods/spec-seats.js +114 -0
- package/dist/core/mods/stations.d.ts +28 -8
- package/dist/core/mods/stations.js +29 -13
- package/dist/core/mods/tool-call.d.ts +79 -0
- package/dist/core/mods/tool-call.js +152 -0
- package/dist/core/namespaced-rule-name.d.ts +32 -38
- package/dist/core/namespaced-rule-name.js +29 -36
- package/dist/core/parent-spec-seat.d.ts +6 -1
- package/dist/core/parent-spec-seat.js +2 -0
- package/dist/core/park-selfcheck.js +1 -0
- package/dist/core/permission-rule-consent.d.ts +19 -0
- package/dist/core/permission-rule-consent.js +116 -26
- package/dist/core/permission-rule-model.d.ts +14 -3
- package/dist/core/permission-rule-model.js +39 -24
- package/dist/core/permission-rule-org.d.ts +6 -2
- package/dist/core/permission-rule-org.js +7 -3
- package/dist/core/permission-rule-provider.d.ts +5 -2
- package/dist/core/permission-rule-provider.js +41 -11
- package/dist/core/permission-rule-store.d.ts +3 -2
- package/dist/core/permission-rule-store.js +11 -2
- package/dist/core/permission-rule-sync.js +3 -2
- package/dist/core/permission-rule-syntax.d.ts +5 -4
- package/dist/core/permission-rule-syntax.js +2 -2
- package/dist/core/permission-rules.d.ts +4 -4
- package/dist/core/permission-rules.js +11 -20
- package/dist/core/persisted-rule-arms.d.ts +2 -2
- package/dist/core/persisted-rule-arms.js +10 -12
- package/dist/core/principal-name.d.ts +20 -0
- package/dist/core/principal-name.js +22 -0
- package/dist/core/prompt-section-seat.js +4 -6
- package/dist/core/protocol-http-auth.d.ts +26 -5
- package/dist/core/protocol-http-auth.js +137 -4
- package/dist/core/retired-keys.d.ts +16 -0
- package/dist/core/retired-keys.js +16 -4
- package/dist/core/rewrite-rejudge.d.ts +60 -0
- package/dist/core/rewrite-rejudge.js +36 -0
- package/dist/core/roles.d.ts +28 -1
- package/dist/core/roles.js +31 -19
- package/dist/core/rule-lane-reads.d.ts +20 -15
- package/dist/core/rule-lane-reads.js +45 -17
- package/dist/core/rule-owner.d.ts +3 -3
- package/dist/core/rule-owner.js +3 -2
- package/dist/core/runner/announce-once-ledger.d.ts +14 -0
- package/dist/core/runner/announce-once-ledger.js +5 -0
- package/dist/core/runner/assemble-result.d.ts +1 -0
- package/dist/core/runner/assemble-result.js +1 -1
- package/dist/core/runner/call-hook-stations.d.ts +3 -2
- package/dist/core/runner/caller-roster.d.ts +16 -4
- package/dist/core/runner/caller-roster.js +33 -6
- package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
- package/dist/core/runner/capability-withheld-seat.js +24 -0
- package/dist/core/runner/classifier-ladder.d.ts +7 -9
- package/dist/core/runner/classifier-ladder.js +3 -3
- package/dist/core/runner/construction-doors.js +3 -0
- package/dist/core/runner/contracts.d.ts +28 -25
- package/dist/core/runner/cross-boundary-lane.d.ts +17 -13
- package/dist/core/runner/cross-boundary-lane.js +40 -27
- package/dist/core/runner/denial-limit-arms.d.ts +2 -2
- package/dist/core/runner/denial-limit-arms.js +1 -1
- package/dist/core/runner/file-history-request.d.ts +18 -0
- package/dist/core/runner/file-history-request.js +21 -13
- package/dist/core/runner/file-history-restore.d.ts +45 -0
- package/dist/core/runner/file-history-restore.js +46 -0
- package/dist/core/runner/gate-exit.d.ts +3 -3
- package/dist/core/runner/gate-exit.js +4 -3
- package/dist/core/runner/image.d.ts +7 -17
- package/dist/core/runner/image.js +9 -60
- package/dist/core/runner/permission-rule-lanes.d.ts +4 -4
- package/dist/core/runner/permission-rule-lanes.js +26 -10
- package/dist/core/runner/person-path-rows.d.ts +12 -9
- package/dist/core/runner/person-path-rows.js +18 -7
- package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
- package/dist/core/runner/prepare-ask-lane.js +5 -2
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
- package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
- package/dist/core/runner/prepare-config-doors.d.ts +29 -38
- package/dist/core/runner/prepare-config-doors.js +42 -25
- package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
- package/dist/core/runner/prepare-defer-classify.js +7 -8
- package/dist/core/runner/prepare-file-history.d.ts +48 -8
- package/dist/core/runner/prepare-file-history.js +7 -39
- package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
- package/dist/core/runner/prepare-gate-stations.js +10 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
- package/dist/core/runner/prepare-hands-readface.js +15 -14
- package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
- package/dist/core/runner/prepare-inherited-gate.js +5 -3
- package/dist/core/runner/prepare-memory-engine-session.js +1 -1
- package/dist/core/runner/prepare-park-ask.js +5 -5
- package/dist/core/runner/prepare-policy-chain.d.ts +6 -3
- package/dist/core/runner/prepare-policy-chain.js +65 -72
- package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
- package/dist/core/runner/prepare-prompt-assembly.js +10 -8
- package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
- package/dist/core/runner/prepare-prompt-inputs.js +3 -5
- package/dist/core/runner/prepare-protocol-tools.d.ts +2 -0
- package/dist/core/runner/prepare-protocol-tools.js +3 -3
- package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
- package/dist/core/runner/prepare-safety-scan.js +0 -17
- package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
- package/dist/core/runner/prepare-suspend-saga.js +5 -6
- package/dist/core/runner/prepare-task.d.ts +1 -1
- package/dist/core/runner/prepare-task.js +29 -20
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
- package/dist/core/runner/prepare-tool-disclosure-mount.js +20 -16
- package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
- package/dist/core/runner/prepare-turn-wiring.js +2 -7
- package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -2
- package/dist/core/runner/prepare-wiring-manifest.js +3 -3
- package/dist/core/runner/resume-admission.js +1 -1
- package/dist/core/runner/resume-apply.js +11 -12
- package/dist/core/runner/resume-checkpoint-screen.js +3 -0
- package/dist/core/runner/resume-claim.d.ts +4 -2
- package/dist/core/runner/resume-claim.js +15 -8
- package/dist/core/runner/retired-runner-deps.js +1 -0
- package/dist/core/runner/rewind-files.d.ts +15 -0
- package/dist/core/runner/rewind-files.js +132 -0
- package/dist/core/runner/run-attachment-seats.js +2 -1
- package/dist/core/runner/run-brain-sinks.d.ts +4 -1
- package/dist/core/runner/run-brain-sinks.js +4 -2
- package/dist/core/runner/run-harness-handlers.js +12 -4
- package/dist/core/runner/run-leg.d.ts +1 -1
- package/dist/core/runner/run-leg.js +30 -18
- package/dist/core/runner/run-settle-and-teardown.js +2 -1
- package/dist/core/runner/run-turn-boundary.js +1 -10
- package/dist/core/runner/runtask.d.ts +3 -0
- package/dist/core/runner/runtask.js +8 -9
- package/dist/core/runner/session-read-file-states.d.ts +15 -0
- package/dist/core/runner/session-read-file-states.js +28 -0
- package/dist/core/runner/session-rule-policy.js +4 -3
- package/dist/core/runner/shell-env-withheld.d.ts +33 -0
- package/dist/core/runner/shell-env-withheld.js +51 -0
- package/dist/core/runner/skills-seat.js +6 -2
- package/dist/core/runner/stream-settle-backstop.js +1 -1
- package/dist/core/runner/sub-agent-deny-lists.js +4 -7
- package/dist/core/runner/synthetic-tools.d.ts +6 -0
- package/dist/core/runner/synthetic-tools.js +4 -1
- package/dist/core/runner/tool-disclosure.d.ts +10 -12
- package/dist/core/runner/tool-disclosure.js +1 -3
- package/dist/core/runner/tool-end-body.d.ts +1 -1
- package/dist/core/runner/tool-end-body.js +10 -9
- package/dist/core/runner/tool-not-executed.d.ts +5 -0
- package/dist/core/runner/tool-not-executed.js +11 -0
- package/dist/core/runner/tool-occurrence.d.ts +8 -0
- package/dist/core/runner/tool-occurrence.js +7 -0
- package/dist/core/runner/turn-attachments.d.ts +33 -15
- package/dist/core/runner/turn-attachments.js +62 -37
- package/dist/core/runner-deps.d.ts +5 -5
- package/dist/core/safety-axis-vocab.d.ts +6 -4
- package/dist/core/safety-axis-vocab.js +6 -5
- package/dist/core/safety-merge-corpus.js +11 -3
- package/dist/core/secret-env.d.ts +26 -3
- package/dist/core/secret-env.js +44 -8
- package/dist/core/select-model.js +3 -3
- package/dist/core/session-policy-store.d.ts +27 -15
- package/dist/core/session-policy-store.js +156 -36
- package/dist/core/session-store.d.ts +29 -10
- package/dist/core/session-store.js +51 -19
- package/dist/core/session.d.ts +82 -16
- package/dist/core/session.js +53 -0
- package/dist/core/shell-read-silence.d.ts +11 -12
- package/dist/core/shell-read-silence.js +9 -5
- package/dist/core/shell-run-candidates.js +3 -1
- package/dist/core/shell-wrapper-projection.js +1 -1
- package/dist/core/shell-wrapper-table.d.ts +14 -7
- package/dist/core/shell-wrapper-table.js +5 -4
- package/dist/core/side-query.js +10 -1
- package/dist/core/skill-grant.d.ts +7 -2
- package/dist/core/skill-grant.js +5 -0
- package/dist/core/skills-directory.js +6 -2
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +140 -2
- package/dist/core/store-contracts/file-history-store-contract.js +31 -1
- package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
- package/dist/core/store-contracts/peer-directory-contract.js +14 -2
- package/dist/core/store-contracts/session-repo-contract.js +51 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +2 -1
- package/dist/core/store-contracts/session-store-contract.js +150 -14
- package/dist/core/stub-env.d.ts +2 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/synthetic-read-verdict.js +3 -3
- package/dist/core/task-event.d.ts +32 -4
- package/dist/core/task-notification.d.ts +16 -12
- package/dist/core/task-registry.d.ts +9 -0
- package/dist/core/task-registry.js +11 -1
- package/dist/core/task-result.d.ts +18 -0
- package/dist/core/task-spec.d.ts +18 -13
- package/dist/core/tighten-task-spec.js +2 -1
- package/dist/core/tool-catalog-entries.d.ts +17 -0
- package/dist/core/tool-catalog-entries.js +13 -2
- package/dist/core/tool-check-reading.d.ts +11 -0
- package/dist/core/tool-check-reading.js +11 -6
- package/dist/core/tool-model-gate.d.ts +2 -2
- package/dist/core/tool-name-aliases.d.ts +16 -16
- package/dist/core/tool-name-aliases.js +13 -19
- package/dist/core/tool-name-readings.d.ts +5 -35
- package/dist/core/tool-name-readings.js +1 -9
- package/dist/core/tool-policy.d.ts +68 -198
- package/dist/core/tool-policy.js +149 -198
- package/dist/core/tool-result-store.js +3 -0
- package/dist/core/tool-roster.d.ts +14 -19
- package/dist/core/tool-roster.js +11 -44
- package/dist/core/tool-spec-members.js +7 -2
- package/dist/core/tool-spec.d.ts +19 -11
- package/dist/core/tools.js +49 -9
- package/dist/core/trace.d.ts +2 -2
- package/dist/core/types.d.ts +1 -1
- package/dist/core/user-attachment.d.ts +8 -1
- package/dist/core/user-attachment.js +64 -4
- package/dist/core/wiring-manifest.d.ts +9 -0
- package/dist/core/wiring-manifest.js +1 -0
- package/dist/core/workflow-journal-store.js +1 -1
- package/dist/engine/compaction/compaction.js +3 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +7 -3
- package/dist/engine/execution-env/node-execution-env.js +11 -2
- package/dist/engine/harness/agent-harness.d.ts +25 -1
- package/dist/engine/harness/agent-harness.js +54 -7
- package/dist/engine/harness/types.d.ts +29 -2
- package/dist/engine/llm/types.d.ts +28 -11
- package/dist/engine/loop/agent-loop.d.ts +22 -0
- package/dist/engine/loop/agent-loop.js +16 -26
- package/dist/engine/loop/types.d.ts +16 -6
- package/dist/engine/session/memory-repo.d.ts +9 -2
- package/dist/engine/session/memory-repo.js +11 -1
- package/dist/engine/session/repo-utils.d.ts +6 -5
- package/dist/engine/session/repo-utils.js +14 -6
- package/dist/index.d.ts +22 -10
- package/dist/index.js +15 -7
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/llm.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +6 -4
- package/dist/orchestration/run-workflow-tool.js +5 -3
- package/dist/orchestration/workflow.d.ts +3 -0
- package/dist/orchestration/workflow.js +36 -18
- package/dist/prompt-assembly/artifact.d.ts +2 -2
- package/dist/prompt-assembly/artifact.js +5 -3
- package/dist/prompt-assembly/assemble.d.ts +3 -2
- package/dist/prompt-assembly/assemble.js +1 -1
- package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
- package/dist/prompt-assembly/catalog/schema.js +34 -2
- package/dist/prompt-assembly/catalog/sections.js +0 -1
- package/dist/prompt-assembly/composer.d.ts +3 -1
- package/dist/prompt-assembly/composer.js +1 -1
- package/dist/prompt-assembly/event-registry.js +1 -0
- package/dist/prompt-assembly/overlay.js +3 -3
- package/dist/prompt-assembly/renderers.d.ts +1 -1
- package/dist/prompt-assembly/renderers.js +0 -3
- package/dist/prompt-assembly/role-base.d.ts +15 -0
- package/dist/prompt-assembly/role-base.js +9 -0
- package/dist/prompt-assembly/select.d.ts +39 -14
- package/dist/prompt-assembly/select.js +47 -16
- package/dist/prompt-assembly/sugar.d.ts +17 -11
- package/dist/prompt-assembly/sugar.js +8 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +37 -3
- package/dist/prompt-assembly/tool-catalog.js +114 -4
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
- package/dist/prompt-assembly/turn-snapshot.js +0 -3
- package/dist/prompt-assembly/types.d.ts +0 -7
- package/dist/scenarios/full-body.d.ts +11 -11
- package/dist/scenarios/full-body.js +4 -3
- package/dist/shell/lex.js +10 -1
- package/dist/stores/file/adoption/adopt.js +4 -3
- package/dist/stores/file/adoption/marker.js +3 -2
- package/dist/stores/file/checkpoint-store.d.ts +21 -0
- package/dist/stores/file/checkpoint-store.js +38 -6
- package/dist/stores/file/file-history-store.js +6 -7
- package/dist/stores/file/index.js +2 -1
- package/dist/stores/file/permission-rule-adopt.js +4 -3
- package/dist/stores/file/permission-rule-store.js +11 -5
- package/dist/stores/file/session-store.d.ts +29 -6
- package/dist/stores/file/session-store.js +42 -50
- package/dist/tools/artifact/artifact-tool.js +3 -2
- package/dist/tools/fs/bash-program-position.d.ts +19 -2
- package/dist/tools/fs/bash-program-position.js +56 -9
- package/dist/tools/fs/fs-bash.js +5 -5
- package/dist/tools/fs/fs-glob.d.ts +86 -0
- package/dist/tools/fs/fs-glob.js +226 -0
- package/dist/tools/fs/fs-read.js +14 -14
- package/dist/tools/fs/fs-search-tools.js +7 -7
- package/dist/tools/fs/pattern-kill-guard.d.ts +22 -0
- package/dist/tools/fs/pattern-kill-guard.js +397 -0
- package/dist/tools/fs/pdf.d.ts +9 -6
- package/dist/tools/fs/pdf.js +3 -3
- package/dist/tools/fs/program-read-model.d.ts +57 -7
- package/dist/tools/fs/program-read-model.js +11 -1
- package/dist/tools/fs/program-read-model.rows.js +78 -21
- package/dist/tools/fs/read-deny-home.js +3 -2
- package/dist/tools/fs/removal-targets.d.ts +17 -7
- package/dist/tools/fs/removal-targets.js +47 -20
- package/dist/tools/fs/search.d.ts +10 -0
- package/dist/tools/fs/search.js +20 -26
- package/dist/tools/fs/shell-read-argv.js +89 -12
- package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
- package/dist/tools/fs/shell-read-bindings.js +41 -0
- package/dist/tools/fs/shell-read-check.js +6 -19
- package/dist/tools/fs/shell-read-environment.d.ts +5 -1
- package/dist/tools/fs/shell-read-environment.js +3 -2
- package/dist/tools/fs/shell-read-establish.d.ts +15 -0
- package/dist/tools/fs/shell-read-establish.js +19 -20
- package/dist/tools/fs/shell-read-plan.js +24 -16
- package/dist/tools/fs/shell-read-start.d.ts +6 -1
- package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
- package/dist/tools/fs/shell-read-write-targets.js +2 -3
- package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
- package/dist/tools/fs/shell-reentry-text.js +40 -2
- package/dist/tools/todo.js +63 -63
- package/dist/tools/web.d.ts +19 -14
- package/dist/tools/web.js +38 -55
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +143 -5
- package/wire-changes/core@7.56.0.json +3891 -0
- package/wire-changes/mods-kernel@7.56.0.json +303 -0
|
@@ -33,6 +33,7 @@ const OBJECT_PATH = { kind: "object-path" };
|
|
|
33
33
|
const text = (language) => ({ kind: "program-text", language });
|
|
34
34
|
const file = (language) => ({ kind: "program-file", language });
|
|
35
35
|
const WALKS = { walks: true };
|
|
36
|
+
const REBASES = { rebases: true };
|
|
36
37
|
const SWITCH = { arity: 0 };
|
|
37
38
|
const QUERY = { arity: 0, mode: "queries" };
|
|
38
39
|
const val = (value, extra = {}) => ({ arity: 1, ...(value !== undefined ? { value } : {}), ...extra });
|
|
@@ -164,8 +165,8 @@ const date = {
|
|
|
164
165
|
};
|
|
165
166
|
const tar = {
|
|
166
167
|
key: "tar",
|
|
167
|
-
grammars: [grammar({ b: val(COUNT), C: val(NAMES,
|
|
168
|
-
"blocking-factor": val(COUNT), directory: val(NAMES,
|
|
168
|
+
grammars: [grammar({ b: val(COUNT), C: val(NAMES, REBASES), f: val(READ), T: val(READ, { delivers: "operands" }), X: val(READ), g: val(), ...switches("adhjJkmOpPStvwWxzZ"), ...switches("cru", { selects: "traversal" }) }, {
|
|
169
|
+
"blocking-factor": val(COUNT), directory: val(NAMES, REBASES), exclude: val(NAME_PATTERN), "exclude-from": val(READ), file: val(READ), "files-from": val(READ, { delivers: "operands" }), "strip-components": val(COUNT),
|
|
169
170
|
...longSwitches(["absolute-names", "dereference", "extract", "get", "interactive", "keep-old-files", "list", "preserve-permissions", "sparse", "to-stdout", "touch", "verbose", "verify"]), ...BANNERS,
|
|
170
171
|
...longSwitches(["append", "create", "update"], { selects: "traversal" }),
|
|
171
172
|
})],
|
|
@@ -176,6 +177,7 @@ const find = {
|
|
|
176
177
|
key: "find",
|
|
177
178
|
grammars: implementations(grammar({ D: val(LABEL), O: val(COUNT), f: val(NAMES), ...switches("HLPdsx") }, BANNERS, {
|
|
178
179
|
afterFirstOperand: "options",
|
|
180
|
+
acceptsAbbreviations: false,
|
|
179
181
|
dashWords: {
|
|
180
182
|
amin: val(COUNT), anewer: val(NAMES), atime: val(COUNT), cmin: val(COUNT), cnewer: val(NAMES), context: val(LABEL),
|
|
181
183
|
ctime: val(COUNT), fstype: val(LABEL), gid: val(COUNT), group: val(LABEL), ilname: val(NAMES), iname: val(NAME_PATTERN),
|
|
@@ -306,7 +308,7 @@ function interpreterGrammar(language, g) {
|
|
|
306
308
|
put(s, val(file(language), { fillsSlot: true, ...(g.fileEndsOptions === true ? { endsOptions: true } : {}) }));
|
|
307
309
|
for (const s of g.longText ?? [])
|
|
308
310
|
put(s, val(text(language), { fillsSlot: true }));
|
|
309
|
-
return { dialect: "any", short, long, dashWords, afterFirstOperand: "either" };
|
|
311
|
+
return { dialect: "any", short, long, dashWords, afterFirstOperand: "either", ...(g.exactLongNames === true ? { acceptsAbbreviations: false } : {}) };
|
|
310
312
|
}
|
|
311
313
|
const interpreter = (key, language, g, program, stdinWhenUnnamed, extra = {}, departures) => ({
|
|
312
314
|
key,
|
|
@@ -317,9 +319,9 @@ const interpreter = (key, language, g, program, stdinWhenUnnamed, extra = {}, de
|
|
|
317
319
|
witness: BINARY,
|
|
318
320
|
...extra,
|
|
319
321
|
});
|
|
320
|
-
const PERL = { text: "eEmM", separated: "I", attached: "iCFxDV", plain: "nplawcsStTUWX", banner: "vVh" };
|
|
321
|
-
const RUBY = { text: "e", separated: "IrECKT", attached: "F", plain: "nplawcsSU", banner: "vh" };
|
|
322
|
-
const PYTHON = { text: "c", module: "m", separated: "WXQ", plain: "uBEIsSqbdvxOtR", banner: "Vh?", interactive: "i", fileEndsOptions: true };
|
|
322
|
+
const PERL = { text: "eEmM", separated: "I", attached: "iCFxDV", plain: "nplawcsStTUWX", banner: "vVh", exactLongNames: true };
|
|
323
|
+
const RUBY = { text: "e", separated: "IrECKT", attached: "F", plain: "nplawcsSU", banner: "vh", exactLongNames: true };
|
|
324
|
+
const PYTHON = { text: "c", module: "m", separated: "WXQ", plain: "uBEIsSqbdvxOtR", banner: "Vh?", interactive: "i", fileEndsOptions: true, exactLongNames: true };
|
|
323
325
|
const NODE = {
|
|
324
326
|
longText: ["--eval", "--print"], text: "ep",
|
|
325
327
|
longModules: ["--import", "--loader", "--experimental-loader", "--require"],
|
|
@@ -327,25 +329,25 @@ const NODE = {
|
|
|
327
329
|
longAttached: ["--max-old-space-size"],
|
|
328
330
|
longNamesProgram: ["--test"],
|
|
329
331
|
longPlain: ["--inspect", "--inspect-brk", "--no-warnings", "--trace-warnings", "--watch", "--enable-source-maps", "--experimental-modules", "--no-deprecation", "--check"],
|
|
330
|
-
modules: "r", plain: "c", banner: "vh", interactive: "i",
|
|
332
|
+
modules: "r", plain: "c", banner: "vh", interactive: "i", exactLongNames: true,
|
|
331
333
|
};
|
|
332
|
-
const PHP = { longText: ["--run", "--process-begin", "--process-code", "--process-end"], text: "rRBE", file: "fF", separated: "dcz", plain: "nqswl", banner: "vhi", interactive: "a" };
|
|
334
|
+
const PHP = { longText: ["--run", "--process-begin", "--process-code", "--process-end"], text: "rRBE", file: "fF", separated: "dcz", plain: "nqswl", banner: "vhi", interactive: "a", exactLongNames: true };
|
|
333
335
|
const LUA = { text: "e", separated: "l", banner: "vh", interactive: "i" };
|
|
334
336
|
const EXPECT = { text: "c", separated: "Db", plain: "dN", banner: "vh", interactive: "i" };
|
|
335
337
|
const AWK = { longText: ["--source"], text: "e", longFile: ["--file", "--exec"], file: "fE", separated: "F", assignment: "v", banner: "V" };
|
|
336
338
|
const POSIX_AWK = { file: "f", separated: "F", assignment: "v" };
|
|
337
339
|
const AWK_IMPLEMENTATIONS = { gnu: {}, bsd: { lacks: ["-E", "--file", "--exec", "--source"] } };
|
|
338
|
-
const JQ = { longFile: ["--from-file"], file: "f", separated: "L", plain: "nrjcsSaCMRe", banner: "h" };
|
|
340
|
+
const JQ = { longFile: ["--from-file"], file: "f", separated: "L", plain: "nrjcsSaCMRe", banner: "h", exactLongNames: true };
|
|
339
341
|
const BC = { longText: ["--expression"], text: "e", plain: "lqsw", banner: "vh", interactive: "i" };
|
|
340
342
|
const DC = { longText: ["--expression"], text: "e", longFile: ["--file"], file: "f", banner: "hV" };
|
|
341
|
-
const SQLITE = { longText: ["-cmd"], longSupplemental: ["-init"] };
|
|
343
|
+
const SQLITE = { longText: ["-cmd"], longSupplemental: ["-init"], exactLongNames: true };
|
|
342
344
|
const PSQL = { longText: ["--command"], text: "c", longFile: ["--file"], file: "f", separated: "hpUdoF", plain: "aeEqtxXwW", banner: "lV?" };
|
|
343
345
|
const OSASCRIPT = { text: "e", separated: "ls", plain: "i", banner: "h" };
|
|
344
346
|
const RSCRIPT = { text: "e", banner: "h" };
|
|
345
347
|
const JULIA = { longText: ["--eval", "--print"], text: "eE", separated: "JLp", plain: "q", banner: "vh", interactive: "i" };
|
|
346
348
|
const GHCI = { text: "e", separated: "io" };
|
|
347
349
|
const GROOVY = { text: "e", separated: "Dcl", plain: "n", banner: "vh", interactive: "i" };
|
|
348
|
-
const BUN = { longText: ["--eval", "--print"], text: "ep", modules: "r", banner: "vh" };
|
|
350
|
+
const BUN = { longText: ["--eval", "--print"], text: "ep", modules: "r", banner: "vh", exactLongNames: true };
|
|
349
351
|
const launcher = (key, spec = {}, g, extra = {}) => ({
|
|
350
352
|
key,
|
|
351
353
|
grammars: g === undefined ? [] : [g],
|
|
@@ -396,6 +398,47 @@ const SU_OPTIONS = {
|
|
|
396
398
|
programs: ["-m", "-p", "--preserve-environment"],
|
|
397
399
|
};
|
|
398
400
|
const SU = launcherGrammar(SU_OPTIONS, { stepsDashDash: true });
|
|
401
|
+
const VALGRIND_FLAGS = [
|
|
402
|
+
"trace-children", "trace-children-skip", "trace-children-skip-by-arg", "child-silent-after-fork", "vgdb", "vgdb-stop-at", "track-fds", "time-stamp",
|
|
403
|
+
"xml", "xml-user-comment", "demangle", "error-limit", "exit-on-first-error", "error-markers", "show-error-list", "keep-debuginfo", "show-below-main",
|
|
404
|
+
"default-suppressions", "gen-suppressions", "dsymutil", "xtree-memory", "fullpath-after", "allow-mismatched-debuginfo", "smc-check", "read-inline-info",
|
|
405
|
+
"read-var-info", "run-libc-freeres", "run-cxx-freeres", "fair-sched", "sigill-diagnostics", "show-emwarns", "vgdb-shadow-registers", "sim-hints",
|
|
406
|
+
"kernel-variant", "soname-synonyms", "resync-filter", "tool",
|
|
407
|
+
"leak-check", "leak-resolution", "show-leak-kinds", "errors-for-leak-kinds", "leak-check-heuristics", "show-reachable", "show-possibly-lost", "xtree-leak",
|
|
408
|
+
"undef-value-errors", "track-origins", "partial-loads-ok", "expensive-definedness-checks", "workaround-gcc296-bugs", "ignore-ranges", "ignore-range-below-sp",
|
|
409
|
+
"malloc-fill", "free-fill", "keep-stacktraces", "show-mismatched-frees",
|
|
410
|
+
];
|
|
411
|
+
const VALGRIND_COUNTS = [
|
|
412
|
+
"vgdb-error", "log-fd", "xml-fd", "num-callers", "error-exitcode", "input-fd", "max-stackframe", "main-stacksize", "alignment", "redzone-size",
|
|
413
|
+
"max-threads", "merge-recursive-frames", "num-transtab-sectors", "avg-transtab-entry-size", "valgrind-stacksize", "vgdb-poll",
|
|
414
|
+
"unw-stack-scan-thresh", "unw-stack-scan-frames", "freelist-vol", "freelist-big-blocks",
|
|
415
|
+
];
|
|
416
|
+
const VALGRIND_OUTPUT_FILES = ["log-file", "xml-file", "xtree-memory-file", "xtree-leak-file", "callgrind-out-file", "cachegrind-out-file", "massif-out-file", "dhat-out-file"];
|
|
417
|
+
const VALGRIND_WRITE = { kind: "path", effect: "write", programEnv: true };
|
|
418
|
+
const VALGRIND_READ = { kind: "path", effect: "read", programEnv: true };
|
|
419
|
+
const VALGRIND = launcherGrammar({
|
|
420
|
+
switches: ["-q", "-v", "-s", "--quiet", "--verbose", "-h", "--help", "--help-debug", "--help-dyn-options", "--version"],
|
|
421
|
+
banners: ["-h", "--help", "--help-debug", "--help-dyn-options", "--version"],
|
|
422
|
+
optional: {
|
|
423
|
+
...Object.fromEntries(VALGRIND_FLAGS.map((n) => [`--${n}`, LABEL])),
|
|
424
|
+
...Object.fromEntries(VALGRIND_COUNTS.map((n) => [`--${n}`, COUNT])),
|
|
425
|
+
...Object.fromEntries(VALGRIND_OUTPUT_FILES.map((n) => [`--${n}`, VALGRIND_WRITE])),
|
|
426
|
+
"--suppressions": VALGRIND_READ,
|
|
427
|
+
},
|
|
428
|
+
}, { acceptsAbbreviations: false, stepsDashDash: true });
|
|
429
|
+
const SETPRIV = launcherGrammar({
|
|
430
|
+
switches: ["--nnp", "--no-new-privs", "--clear-groups", "--keep-groups", "--init-groups", "--reset-env", "-d", "--dump", "-h", "--help", "-V", "--version"],
|
|
431
|
+
banners: ["-d", "--dump", "-h", "--help", "-V", "--version"],
|
|
432
|
+
values: Object.fromEntries(["ambient-caps", "inh-caps", "bounding-set", "ruid", "euid", "rgid", "egid", "reuid", "regid", "groups", "securebits", "pdeathsig", "selinux-label", "apparmor-profile"].map((n) => [`--${n}`, LABEL])),
|
|
433
|
+
}, { stepsDashDash: true });
|
|
434
|
+
const CHROOT_GRAMMARS = implementations(launcherGrammar({ switches: ["--skip-chdir", "--help", "--version"], values: { "--userspec": LABEL, "--groups": LABEL, "-u": LABEL, "-g": LABEL, "-G": LABEL } }, { stepsDashDash: true }), { lacks: ["-u", "-g", "-G"] }, { lacks: ["--skip-chdir", "--help", "--version", "--userspec", "--groups"] });
|
|
435
|
+
const PRLIMIT_RESOURCES = { c: "core", d: "data", e: "nice", f: "fsize", i: "sigpending", l: "memlock", m: "rss", n: "nofile", q: "msgqueue", r: "rtprio", s: "stack", t: "cpu", u: "nproc", v: "as", x: "locks", y: "rttime" };
|
|
436
|
+
const PRLIMIT = launcherGrammar({
|
|
437
|
+
switches: ["--noheadings", "--raw", "--verbose", "-h", "--help", "-V", "--version"],
|
|
438
|
+
banners: ["-h", "--help", "-V", "--version"],
|
|
439
|
+
values: { "-p": COUNT, "--pid": COUNT, "-o": LABEL, "--output": LABEL },
|
|
440
|
+
optional: Object.fromEntries(Object.entries(PRLIMIT_RESOURCES).flatMap(([letter, name]) => [[`-${letter}`, LABEL], [`--${name}`, LABEL]])),
|
|
441
|
+
}, { stepsDashDash: true });
|
|
399
442
|
const SU_LINUX_ONLY = [...SU_OPTIONS.switches, ...Object.keys(SU_OPTIONS.values), ...SU_OPTIONS.shellText, ...SU_OPTIONS.programs].filter((s) => !["-f", "-l", "-m"].includes(s));
|
|
400
443
|
const launchers = [
|
|
401
444
|
{ key: "env", grammars: implementations(launcherGrammar({
|
|
@@ -427,8 +470,8 @@ const launchers = [
|
|
|
427
470
|
launcher("pkexec", { whenNoProgram: "shell" }, launcherGrammar({ switches: ["--disable-internal-agent", "--keep-cwd", "--version", "--help"], values: { "--user": LABEL } }), { witness: PRIVILEGED }),
|
|
428
471
|
{ key: "su", grammars: implementations(SU, { afterFirstOperand: "options" }, { lacks: SU_LINUX_ONLY, afterFirstOperand: "operands" }), launcher: { shellText: "user", asUser: { home: "target", loginWith: ["-l", "--login"] } }, witness: PRIVILEGED },
|
|
429
472
|
{ key: "runuser", grammars: [launcherGrammar({ ...SU_OPTIONS, values: { ...SU_OPTIONS.values, "-u": LABEL, "--user": LABEL } }, { afterFirstOperand: "options", stepsDashDash: true })], launcher: { shellText: "user", programWith: ["-u", "--user"], asUser: { home: "target", loginWith: ["-l", "--login"] } }, witness: PRIVILEGED },
|
|
430
|
-
|
|
431
|
-
launcher("setpriv", {},
|
|
473
|
+
{ key: "chroot", grammars: CHROOT_GRAMMARS, launcher: { requiredOperands: 1, whenNoProgram: "shell" }, witness: PRIVILEGED },
|
|
474
|
+
launcher("setpriv", {}, SETPRIV, { witness: PRIVILEGED }),
|
|
432
475
|
launcher("nohup", {}, grammar({}, BANNERS, { stepsDashDash: true })),
|
|
433
476
|
{ key: "nice", grammars: implementations(grammar({ n: val(COUNT) }, { adjustment: val(COUNT), ...BANNERS }, { stepsDashDash: true }), {}, { lacks: ["--adjustment", "--help", "--version"] }), launcher: { negativeIntegerIsOwnArgument: true }, witness: BINARY },
|
|
434
477
|
launcher("ionice", {}, launcherGrammar({
|
|
@@ -470,7 +513,7 @@ const launchers = [
|
|
|
470
513
|
}), { witness: LINUX_NAMESPACE }),
|
|
471
514
|
launcher("script", { shellText: "joined" }, launcherGrammar({ shellText: ["-c", "--command"] }), { witness: SHELL_TEXT_LAUNCHER }),
|
|
472
515
|
launcher("numactl", {}, undefined, { witness: LINUX_NAMESPACE }),
|
|
473
|
-
launcher("prlimit", {},
|
|
516
|
+
launcher("prlimit", {}, PRLIMIT, { witness: LINUX_NAMESPACE }),
|
|
474
517
|
launcher("systemd-run", {}, undefined, { witness: { declared: "hands the program to a service manager" } }),
|
|
475
518
|
launcher("strace", {}, launcherGrammar({
|
|
476
519
|
switches: ["-f", "-c", "-C", "-d", "-D", "-h", "-i", "-k", "-q", "-r", "-t", "-T", "-v", "-V", "-w", "-x", "-y", "-z", "-Z", "-F", "--follow-forks", "--summary-only", "--summary", "--debug", "--help", "--version"],
|
|
@@ -486,7 +529,7 @@ const launchers = [
|
|
|
486
529
|
banners: ["-V"],
|
|
487
530
|
values: { "-a": COUNT, "-A": COUNT, "-e": LABEL, "-l": NAMES, "-n": COUNT, "-o": WRITE, "-p": COUNT, "-s": COUNT, "-u": LABEL, "-x": LABEL, "-D": LABEL, "-F": READ, "-w": COUNT, "--align": COUNT, "--config": READ, "--debug": LABEL, "--indent": COUNT, "--library": NAMES, "--output": WRITE, "--string-max": COUNT, "--where": COUNT },
|
|
488
531
|
}), { witness: LINUX_NAMESPACE }),
|
|
489
|
-
launcher("valgrind"),
|
|
532
|
+
launcher("valgrind", {}, VALGRIND),
|
|
490
533
|
launcher("firejail", { whenNoProgram: "shell" }, undefined, { witness: LINUX_NAMESPACE }),
|
|
491
534
|
launcher("bwrap", {}, undefined, { witness: LINUX_NAMESPACE }),
|
|
492
535
|
];
|
|
@@ -507,12 +550,25 @@ const GIT_GREP = {
|
|
|
507
550
|
traversal: { discloses: "contents", always: true },
|
|
508
551
|
};
|
|
509
552
|
const gitObjectSubcommand = (short = {}, long = {}) => ({ grammar: grammar(short, long), operands: { rest: OBJECT_PATH } });
|
|
553
|
+
const GIT_RUNS_LATER = [
|
|
554
|
+
...["core.pager", "core.editor", "sequence.editor", "core.sshcommand", "core.gitproxy", "core.askpass", "core.alternaterefscommand",
|
|
555
|
+
"diff.external", "diff.*.command", "diff.*.textconv", "merge.*.driver", "filter.*.clean", "filter.*.smudge", "filter.*.process",
|
|
556
|
+
"difftool.*.cmd", "difftool.*.path", "mergetool.*.cmd", "mergetool.*.path", "interactive.difffilter",
|
|
557
|
+
"gpg.program", "gpg.*.program", "gpg.ssh.defaultkeycommand", "browser.*.cmd", "browser.*.path", "man.*.cmd", "man.*.path",
|
|
558
|
+
"guitool.*.cmd", "instaweb.httpd", "trailer.*.cmd", "trailer.*.command", "uploadpack.packobjectshook", "gc.recentobjectshook",
|
|
559
|
+
"remote.*.receivepack", "remote.*.uploadpack",
|
|
560
|
+
"sendemail.*tocmd", "sendemail.*cccmd", "sendemail.*headercmd", "sendemail.*sendmailcmd", "sendemail.*smtpserver"].map((key) => ({ key })),
|
|
561
|
+
{ key: "pager.*", orBoolean: true }, { key: "core.fsmonitor", orBoolean: true },
|
|
562
|
+
{ key: "alias.*", bang: true }, { key: "credential.helper", prefixed: "git credential-" }, { key: "credential.*.helper", prefixed: "git credential-" },
|
|
563
|
+
];
|
|
510
564
|
const git = {
|
|
511
565
|
key: "git",
|
|
512
|
-
grammars: [grammar({ p: SWITCH, P: SWITCH, C: val(WORKDIR), c: val() }, {
|
|
566
|
+
grammars: [grammar({ p: SWITCH, P: SWITCH, C: val(WORKDIR), c: val(undefined, { runsLater: { keys: GIT_RUNS_LATER } }) }, {
|
|
513
567
|
...longSwitches(["paginate", "no-pager", "bare", "no-replace-objects", "literal-pathspecs", "glob-pathspecs", "noglob-pathspecs", "icase-pathspecs", "no-optional-locks"]),
|
|
514
|
-
"git-dir": val(WORKDIR), "work-tree": val(WORKDIR), namespace: val(), "config-env": val(), "super-prefix": val(),
|
|
515
|
-
|
|
568
|
+
"git-dir": val(WORKDIR), "work-tree": val(WORKDIR), namespace: val(), "config-env": val(undefined, { runsLater: { keys: GIT_RUNS_LATER, valueFrom: "environment" } }), "super-prefix": val(),
|
|
569
|
+
version: { arity: 0, mode: "banner" },
|
|
570
|
+
}, { acceptsAbbreviations: false })],
|
|
571
|
+
body: "option-values",
|
|
516
572
|
subcommands: {
|
|
517
573
|
commit: gitSubcommand("apsnvqeioz", "Su", "mFCct", ["message", "file", "template", "pathspec-from-file", "author", "date", "cleanup", "fixup", "squash", "trailer", "reuse-message", "reedit-message"]),
|
|
518
574
|
tag: gitSubcommand("asfdvle", "n", "mFu", ["message", "file", "local-user", "cleanup", "trailer", "sort", "format", "contains", "no-contains", "points-at", "merged", "no-merged"]),
|
|
@@ -562,7 +618,7 @@ const CONTAINER_RUN = {
|
|
|
562
618
|
};
|
|
563
619
|
const containerRuntime = (key) => ({
|
|
564
620
|
key,
|
|
565
|
-
grammars: [grammar({ H: val(LABEL), c: val(LABEL), l: val(LABEL), D: SWITCH }, { host: val(LABEL), context: val(LABEL), "log-level": val(LABEL), config: val(READ), tlscacert: val(READ), tlscert: val(READ), tlskey: val(READ), ...longSwitches(["debug", "tls", "tlsverify"]) })],
|
|
621
|
+
grammars: [grammar({ H: val(LABEL), c: val(LABEL), l: val(LABEL), D: SWITCH }, { host: val(LABEL), context: val(LABEL), "log-level": val(LABEL), config: val(READ), tlscacert: val(READ), tlscert: val(READ), tlskey: val(READ), ...longSwitches(["debug", "tls", "tlsverify"]) }, { acceptsAbbreviations: false })],
|
|
566
622
|
operands: { assignmentArguments: "not-paths" },
|
|
567
623
|
subcommands: { run: CONTAINER_RUN, create: CONTAINER_RUN },
|
|
568
624
|
witness: { declared: "a build tool / container client: what a NAME=value argument means is the build's or the container's" },
|
|
@@ -595,8 +651,8 @@ const copyGrammars = (bsdSuffixSwitch, destination) => implementations(grammar({
|
|
|
595
651
|
const writerRows = [
|
|
596
652
|
{ key: "mkdir", grammars: [], operands: { rest: CREATED, dash: "file" }, witness: BINARY },
|
|
597
653
|
{ key: "touch", grammars: implementations(grammar({ h: { arity: 0, writesAt: ["landing", "entry"] } }, { "no-dereference": { arity: 0, writesAt: ["landing", "entry"] } }), {}, { lacks: ["--no-dereference"] }), operands: { rest: TOUCHED, dash: "file" }, witness: BINARY },
|
|
598
|
-
{ key: "rm", grammars: implementations(grammar({ ...switches("rR", { selects: "traversal" }), f: { arity: 0, mode: "forced" } }, { ...longSwitches(["recursive"], { selects: "traversal" }), force: { arity: 0, mode: "forced" } }), {}, { lacks: ["--recursive", "--force"] }), operands: { rest: REMOVED, dash: "file" }, witness: BINARY },
|
|
599
|
-
{ key: "rmdir", grammars: implementations(grammar({ p: { arity: 0, effect: "writes" } }, { parents: { arity: 0, effect: "writes" } }), {}, { lacks: ["--parents"] }), operands: { rest: REMOVED, dash: "file" }, witness: BINARY },
|
|
654
|
+
{ key: "rm", grammars: implementations(grammar({ ...switches("rR", { selects: "traversal" }), f: { arity: 0, mode: "forced" }, ...switches("diIvPWx", { effect: "none" }) }, { ...longSwitches(["recursive"], { selects: "traversal" }), force: { arity: 0, mode: "forced" }, ...longSwitches(["dir", "verbose", "one-file-system", "no-preserve-root", "-presume-input-tty"], { effect: "none" }), interactive: { arity: "attached", value: LABEL, effect: "none" }, "preserve-root": { arity: "attached", value: LABEL, effect: "none" }, ...BANNERS }), { lacks: ["-P", "-W", "-x"] }, { lacks: ["--recursive", "--force", "--dir", "--verbose", "--one-file-system", "--no-preserve-root", "---presume-input-tty", "--interactive", "--preserve-root", "--help", "--version"] }), operands: { rest: REMOVED, dash: "file" }, optionsComplete: true, witness: BINARY },
|
|
655
|
+
{ key: "rmdir", grammars: implementations(grammar({ p: { arity: 0, effect: "writes" }, v: { arity: 0, effect: "none" } }, { parents: { arity: 0, effect: "writes" }, ...longSwitches(["verbose", "ignore-fail-on-non-empty"], { effect: "none" }), ...BANNERS }), {}, { lacks: ["--parents", "--verbose", "--ignore-fail-on-non-empty", "--help", "--version"] }), operands: { rest: REMOVED, dash: "file" }, optionsComplete: true, witness: BINARY },
|
|
600
656
|
{ key: "tee", grammars: [], operands: { rest: WRITE_THROUGH, dash: "file" }, witness: BINARY },
|
|
601
657
|
{ key: "cp", grammars: copyGrammars(true, COPY_DESTINATION), operands: { rest: COPY_SOURCE, last: COPY_DESTINATION, dash: "file" }, witness: BINARY },
|
|
602
658
|
{ key: "mv", grammars: copyGrammars(false, MOVE_DESTINATION), operands: { rest: MOVE_SOURCE, last: MOVE_DESTINATION, dash: "file" }, witness: BINARY },
|
|
@@ -651,6 +707,7 @@ export const PROGRAM_ROWS = [
|
|
|
651
707
|
...[...shellWordsOf("stack_mover")].map((key) => ({ key, grammars: [], movesBase: "stack", witness: BUILTIN_ONLY })),
|
|
652
708
|
...SHELLS.map((s) => shellRow(s, "c-option", BINARY, [SHELL_GRAMMARS[s]], "script")),
|
|
653
709
|
shellRow("eval", "words", BUILTIN_ONLY), shellRow("source", "file-operand", BUILTIN_ONLY), shellRow(".", "file-operand", BUILTIN_ONLY), shellRow("parallel", "non-option-words", BINARY, [], "script"),
|
|
710
|
+
shellRow("fc", "history", BUILTIN_ONLY, [grammar({ ...switches("nr"), s: { arity: 0, effect: "executes" }, ...switches("l", { mode: "banner" }), e: val(COMMAND, { executesWhenValue: "-" }) }, {}, { afterFirstOperand: "operands" })]),
|
|
654
711
|
...codeBodyRows,
|
|
655
712
|
...[...shellWordsOf("block")].map((k) => block(k, BLOCK_GRAMMARS[k])),
|
|
656
713
|
];
|
|
@@ -5,6 +5,7 @@ import { thrownText } from "../../core/thrown-value.js";
|
|
|
5
5
|
import { agentConfigDirTail } from "../../core/agent-config-dir.js";
|
|
6
6
|
import { validatePath } from "../../core/effective-path-target.js";
|
|
7
7
|
import { readDenyPatternRun, readDenyRowAnchor, readDenyRunHead } from "./read-deny.js";
|
|
8
|
+
import { isAbsence } from "./shell-read-environment.js";
|
|
8
9
|
export const AUXILIARY_HOME_PROBE_MS = 2_000;
|
|
9
10
|
const said = new Set();
|
|
10
11
|
function sayOnce(kind, line) {
|
|
@@ -75,7 +76,7 @@ async function homeSpellingsOf(env, home, signal) {
|
|
|
75
76
|
const canonical = await env.canonicalPath(home, signal);
|
|
76
77
|
if (canonical.ok)
|
|
77
78
|
return { spellings: canonical.value !== home ? [home, canonical.value] : [home], canonical: canonical.value, answered: true };
|
|
78
|
-
return { spellings: [home], answered: canonical.error.code
|
|
79
|
+
return { spellings: [home], answered: isAbsence(canonical.error.code) };
|
|
79
80
|
}
|
|
80
81
|
catch {
|
|
81
82
|
return { spellings: [home], answered: false };
|
|
@@ -202,7 +203,7 @@ export async function whereItsAnsweredPrefixLeads(env, at, family = pathFamilyOf
|
|
|
202
203
|
}
|
|
203
204
|
const NO_CHAIN = { ancestors: [], whole: false, unread: [] };
|
|
204
205
|
const unreadChain = (at) => ({ ancestors: [], whole: false, unread: [at] });
|
|
205
|
-
const identityUnread = (id) => id === undefined || (!id.ok && id.error.code
|
|
206
|
+
const identityUnread = (id) => id === undefined || (!id.ok && !isAbsence(id.error.code) && id.error.code !== "not_supported");
|
|
206
207
|
async function chainAbove(env, identity, canonical, signal, deadline) {
|
|
207
208
|
let own;
|
|
208
209
|
const ancestors = [];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { EstablishedRead } from "./shell-read-judge.js";
|
|
1
2
|
import { type EstablishedPlan } from "./shell-read-establish.js";
|
|
2
3
|
import type { ExecutionEnv } from "../../internal/harness-types.js";
|
|
3
4
|
import type { ToolCallRequest } from "../../core/tool-policy.js";
|
|
@@ -35,8 +36,8 @@ export declare function dangerousRemovalOf(path: string, seat: RemovalSeat): Dan
|
|
|
35
36
|
* (`rewritten`), the operands of a removal its argv stream fills in (`stream`), or an operand relative to the directory a
|
|
36
37
|
* launcher option moved the removal into (`relocated`); or a shell handed text the engine cannot read
|
|
37
38
|
* (`unverifiable_shell_text`) — a text a program produces (`produced`: what a pipe or a `<(…)` carries, an argv a stream
|
|
38
|
-
* fills in, a substitution),
|
|
39
|
-
* segment whose program the walk could not name
|
|
39
|
+
* fills in, a substitution), a text nobody read (`unread`: one the lexer could not read at all, {@link unreadPlan}), or a
|
|
40
|
+
* segment whose program the walk could not name (`position`, {@link programUnread}). */
|
|
40
41
|
export type RemovalFinding = (DangerousRemoval & {
|
|
41
42
|
readonly guard: "dangerous_delete";
|
|
42
43
|
readonly untrackedFrom?: string;
|
|
@@ -49,7 +50,7 @@ export type RemovalFinding = (DangerousRemoval & {
|
|
|
49
50
|
readonly guard: "unverifiable_shell_text";
|
|
50
51
|
readonly program: string;
|
|
51
52
|
readonly text: string;
|
|
52
|
-
readonly source: "produced" | "unread";
|
|
53
|
+
readonly source: "produced" | "unread" | "position";
|
|
53
54
|
};
|
|
54
55
|
/**
|
|
55
56
|
* The names a removal target may be built on and still be verified: a root the SHELL provides, never one a command's
|
|
@@ -62,10 +63,12 @@ export type RemovalFinding = (DangerousRemoval & {
|
|
|
62
63
|
export declare const KNOWN_SAFE_ROOTS: readonly string[];
|
|
63
64
|
/**
|
|
64
65
|
* The removal findings of an established plan — ONE walk, nested plans included (a `bash -c` / `sh -c` text, a substitution
|
|
65
|
-
* body), two words. For every `rm` / `rmdir`
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
66
|
+
* body), two words. For every removal segment ({@link removalProgramOf}: an `rm` / `rmdir` the text names, or a program it
|
|
67
|
+
* does not settle, read as `rm`) whose argv the program does not refuse outright ({@link optionsReceived}), each of its
|
|
68
|
+
* OPERANDS (every write target that is not one of its option words: a word some implementation's reading of the
|
|
69
|
+
* program's row writes, {@link writeReadings}) as the plan established it on the WRITE face (the entry the program
|
|
70
|
+
* unlinks, and the deny-floor shadow of a home word the plan did not place) is judged by {@link dangerousRemovalOf},
|
|
71
|
+
* save one the program refuses by its own first step ({@link refusedByRemoval}: `.`, `..`). In a recursive forced removal ({@link recursiveForce}), an operand
|
|
69
72
|
* the shell rewrites from a value the plan's table does not settle — a name with no value here or one set in a form the
|
|
70
73
|
* table cannot read, a substitution, a parameter operator, a positional parameter — is an unverifiable target, save a
|
|
71
74
|
* literal path below a known-safe root the shell still provides there ({@link belowKnownSafeRoot}); so are the operands
|
|
@@ -80,6 +83,13 @@ export declare const KNOWN_SAFE_ROOTS: readonly string[];
|
|
|
80
83
|
* own. The read-face copy of an operand is not judged: it follows a link the removal does not follow.
|
|
81
84
|
*/
|
|
82
85
|
export declare function removalFindingsOf(established: EstablishedPlan, seat: RemovalSeat, safeRoots?: readonly string[], enclosingRelocated?: boolean): RemovalFinding[];
|
|
86
|
+
/** Does the removal program refuse this operand by its own first step — its last path component is `.` or `..`, trailing
|
|
87
|
+
* separators stripped (POSIX `rm` step 1, which GNU, BSD and BusyBox `rm` keep; `rmdir(2)` fails on such a component
|
|
88
|
+
* too)? It removes nothing there, wherever the name lands. The name is the one the program RECEIVES: a pattern's match
|
|
89
|
+
* (the spelling an expansion carries beside its origin: `.*` hands it `.` and `..` beside the dotfiles, and only those two
|
|
90
|
+
* are refused), else the word as the plan spells it; a word the shell rewrites from a value the plan does not settle
|
|
91
|
+
* names nothing known, and is never refused here. */
|
|
92
|
+
export declare function refusedByRemoval(read: EstablishedRead): boolean;
|
|
83
93
|
/** Does this plan (nested plans included) run a removal program, hand a shell a script built when it runs, or hold text
|
|
84
94
|
* nobody could read ({@link unreadPlan}, {@link programUnread})? The guard establishes nothing for a command that does none. */
|
|
85
95
|
export declare function planRunsRemoval(plan: EstablishedPlan["plan"]): boolean;
|
|
@@ -2,11 +2,11 @@ import { planShellReads } from "./shell-read-plan.js";
|
|
|
2
2
|
import { literalTextOf } from "../../shell/lex.js";
|
|
3
3
|
import { createShellReadEstablisher, establishShellReadsLexically } from "./shell-read-establish.js";
|
|
4
4
|
import { isAbsoluteForFamily, isWinFormPath, normalizeAbsPathLexically } from "./safety.js";
|
|
5
|
-
import { launchedCommands, launchedReadings, reentryText, scriptFileAt, spellLaunched } from "./shell-reentry-text.js";
|
|
6
|
-
import { readProgramPosition } from "./bash-program-position.js";
|
|
5
|
+
import { launchedCommands, launchedReadings, reentryText, runsStoredLine, scriptFileAt, spellLaunched } from "./shell-reentry-text.js";
|
|
6
|
+
import { declinedProgramSentence, readProgramPosition } from "./bash-program-position.js";
|
|
7
7
|
import { bashClassifyDefaultAllow } from "./bash-readonly-classifier.js";
|
|
8
8
|
import { programArgs } from "./shell-read-write-targets.js";
|
|
9
|
-
import { implementationsOf, programRow, runsShellText, selectedOptions, writeReadings } from "./program-read-model.js";
|
|
9
|
+
import { declaresOption, implementationsOf, programRow, rowRefusesArgv, runsShellText, selectedOptions, writeReadings } from "./program-read-model.js";
|
|
10
10
|
import { inlineUntrusted } from "../../core/untrusted-text.js";
|
|
11
11
|
export const SHELL_REMOVAL_COMMANDS = Object.freeze(["rm", "rmdir"]);
|
|
12
12
|
const REMOVAL_COMMAND_SET = new Set(SHELL_REMOVAL_COMMANDS);
|
|
@@ -68,10 +68,19 @@ function belowKnownSafeRoot(word, safe, segment) {
|
|
|
68
68
|
const below = rest.map((p) => p.literal).join("");
|
|
69
69
|
return /^\/[^*?[\]]+$/.test(below) && !below.split("/").includes("..");
|
|
70
70
|
}
|
|
71
|
-
function
|
|
71
|
+
function optionsReceived(row, args) {
|
|
72
|
+
const rewrittenAt = args.findIndex((w) => w.rewritten === true);
|
|
73
|
+
const asWritten = (rewrittenAt < 0 ? args : args.slice(0, rewrittenAt)).map((w) => w.spelled);
|
|
74
|
+
const present = args.filter((w) => w.vanishes !== true);
|
|
75
|
+
const chosenAt = present.findIndex((w) => w.rewritten === true);
|
|
76
|
+
const shellChooses = chosenAt >= 0 && writeReadings(row, present.slice(0, chosenAt + 1).map((w) => w.spelled)).some((r) => r.written.length === 0);
|
|
77
|
+
return { refused: rowRefusesArgv(row, asWritten), shellChooses };
|
|
78
|
+
}
|
|
79
|
+
function recursiveForce(row, args, shellChooses) {
|
|
72
80
|
return implementationsOf(row).some((view) => {
|
|
73
81
|
const selected = selectedOptions(view, args, "one-implementation");
|
|
74
|
-
|
|
82
|
+
const selects = (has) => selected.some(has) || (shellChooses && declaresOption(view, has));
|
|
83
|
+
return selects((o) => o.selects === "traversal") && selects((o) => o.mode === "forced");
|
|
75
84
|
});
|
|
76
85
|
}
|
|
77
86
|
export function removalFindingsOf(established, seat, safeRoots = KNOWN_SAFE_ROOTS, enclosingRelocated = false) {
|
|
@@ -81,23 +90,27 @@ export function removalFindingsOf(established, seat, safeRoots = KNOWN_SAFE_ROOT
|
|
|
81
90
|
const safe = new Set(safeRoots);
|
|
82
91
|
for (const segment of established.plan.segments) {
|
|
83
92
|
const program = segment.verb?.basename;
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
93
|
+
const removal = removalProgramOf(segment);
|
|
94
|
+
const args = removal === undefined ? [] : programArgs(segment);
|
|
95
|
+
const spelled = args.map((w) => w.spelled);
|
|
96
|
+
const received = removal === undefined ? undefined : optionsReceived(removal.row, args);
|
|
97
|
+
if (removal !== undefined && received?.refused === false) {
|
|
98
|
+
const { row, named } = removal;
|
|
88
99
|
const removed = new Set(writeReadings(row, spelled).flatMap((r) => r.written.map((w) => w.at)));
|
|
89
100
|
const options = new Set(args.filter((_, at) => !removed.has(at)).map((w) => w.raw));
|
|
90
|
-
const forced = recursiveForce(row, spelled);
|
|
101
|
+
const forced = recursiveForce(row, spelled, received.shellChooses);
|
|
91
102
|
if (forced && segment.reentry === "argv")
|
|
92
|
-
out.push({ guard: "unverifiable_delete", program, operand: segment.text.trim(), source: "stream" });
|
|
103
|
+
out.push({ guard: "unverifiable_delete", program: removal.program, operand: segment.text.trim(), source: "stream" });
|
|
93
104
|
const relocated = enclosingRelocated || readProgramPosition(segment.argv).launcherMovesBase;
|
|
94
105
|
for (const read of established.reads.get(segment) ?? []) {
|
|
95
|
-
if (read.candidate.face !== "write" || options.has(read.candidate.raw))
|
|
106
|
+
if ((named && read.candidate.face !== "write") || read.candidate.provenance === "program_path" || options.has(read.candidate.raw))
|
|
107
|
+
continue;
|
|
108
|
+
if (refusedByRemoval(read))
|
|
96
109
|
continue;
|
|
97
110
|
const kind = removalKindOf(read, seat);
|
|
98
111
|
if (kind !== undefined) {
|
|
99
112
|
const untracked = read.candidate.bases === "unmodelled" ? established.plan.segments.find((s) => s.bases === "unmodelled")?.text.trim() : undefined;
|
|
100
|
-
out.push({ guard: "dangerous_delete", kind, program, operand: read.candidate.raw, target: read.target ?? read.candidate.floorSpelled ?? read.candidate.spelled, ...(untracked !== undefined ? { untrackedFrom: untracked } : {}) });
|
|
113
|
+
out.push({ guard: "dangerous_delete", kind, program: removal.program, operand: read.candidate.raw, target: read.target ?? read.candidate.floorSpelled ?? read.candidate.spelled, ...(untracked !== undefined ? { untrackedFrom: untracked } : {}) });
|
|
101
114
|
continue;
|
|
102
115
|
}
|
|
103
116
|
if (!forced || read.established !== "unestablishable" || (read.candidate.expands !== "unresolvable" && !relocated))
|
|
@@ -105,14 +118,14 @@ export function removalFindingsOf(established, seat, safeRoots = KNOWN_SAFE_ROOT
|
|
|
105
118
|
const word = segment.argv.find((w) => w.raw === read.candidate.raw);
|
|
106
119
|
if (word !== undefined && belowKnownSafeRoot(word, safe, segment))
|
|
107
120
|
continue;
|
|
108
|
-
out.push({ guard: "unverifiable_delete", program, operand: read.candidate.raw, source: read.candidate.expands === "unresolvable" ? "rewritten" : "relocated" });
|
|
121
|
+
out.push({ guard: "unverifiable_delete", program: removal.program, operand: read.candidate.raw, source: read.candidate.expands === "unresolvable" ? "rewritten" : "relocated" });
|
|
109
122
|
}
|
|
110
123
|
}
|
|
111
124
|
const script = runtimeScriptOf(segment);
|
|
112
125
|
if (script !== undefined && program !== undefined)
|
|
113
126
|
out.push({ guard: "unverifiable_shell_text", program, text: script, source: "produced" });
|
|
114
127
|
if (programUnread(segment))
|
|
115
|
-
out.push({ guard: "unverifiable_shell_text", program: segment.launcherChain[0] ?? segment.text.trim(), text: segment.text.trim(), source: "
|
|
128
|
+
out.push({ guard: "unverifiable_shell_text", program: segment.launcherChain[0] ?? segment.text.trim(), text: segment.text.trim(), source: "position" });
|
|
116
129
|
const handedRelocated = enclosingRelocated || readProgramPosition(segment.argv).launcherMovesBase;
|
|
117
130
|
for (const nested of segment.nested) {
|
|
118
131
|
if (unreadPlan(nested)) {
|
|
@@ -143,7 +156,7 @@ function runtimeScriptOf(segment) {
|
|
|
143
156
|
const source = file === undefined ? undefined : argv[file];
|
|
144
157
|
if (source !== undefined && source.pieces.length === 1 && source.pieces[0].expansion?.kind === "process")
|
|
145
158
|
return source.raw;
|
|
146
|
-
if (pos.argvFromStdin)
|
|
159
|
+
if (pos.argvFromStdin || runsStoredLine(program.basename, argv.map((w) => w.folded)))
|
|
147
160
|
return segment.text.trim();
|
|
148
161
|
}
|
|
149
162
|
const named = pos.program !== undefined && pos.refusal === undefined ? [{ shell: program.basename, words: segment.argv.slice(pos.program.index + 1).map((_, k) => spell(pos.program.index + 1 + k)) }] : [];
|
|
@@ -157,8 +170,21 @@ function runtimeScriptOf(segment) {
|
|
|
157
170
|
}
|
|
158
171
|
const unreadPlan = (plan) => plan.unreadable !== undefined && plan.segments.length === 0;
|
|
159
172
|
const programUnread = (s) => s.declines.includes("unreadable_program_position");
|
|
173
|
+
const programNameUnsettled = (s) => s.verb !== undefined && s.reads.some((c) => c.provenance === "program_path" && c.expands === "unresolvable");
|
|
174
|
+
const RM_REMOVAL_ROW = programRow("rm");
|
|
175
|
+
function removalProgramOf(s) {
|
|
176
|
+
const basename = s.verb?.basename;
|
|
177
|
+
const row = basename !== undefined && REMOVAL_COMMAND_SET.has(basename) ? programRow(basename) : undefined;
|
|
178
|
+
if (row !== undefined)
|
|
179
|
+
return { program: basename, row, named: true };
|
|
180
|
+
return programNameUnsettled(s) && RM_REMOVAL_ROW !== undefined ? { program: s.verb.name, row: RM_REMOVAL_ROW, named: false } : undefined;
|
|
181
|
+
}
|
|
182
|
+
export function refusedByRemoval(read) {
|
|
183
|
+
const name = read.established === "expansion" ? read.spellings.find((s) => s !== read.origin) : read.candidate.expands === "unresolvable" ? undefined : read.candidate.spelled;
|
|
184
|
+
return name !== undefined && /(?:^|\/)\.\.?\/*$/.test(name);
|
|
185
|
+
}
|
|
160
186
|
export function planRunsRemoval(plan) {
|
|
161
|
-
return unreadPlan(plan) || plan.segments.some((s) => (s
|
|
187
|
+
return unreadPlan(plan) || plan.segments.some((s) => removalProgramOf(s) !== undefined || runtimeScriptOf(s) !== undefined || programUnread(s) || s.nested.some(planRunsRemoval));
|
|
162
188
|
}
|
|
163
189
|
const DANGEROUS_REMOVAL_SENTENCE = {
|
|
164
190
|
filesystem_root: (p, t) => `\`${p}\` would remove the filesystem root (${t})`,
|
|
@@ -172,8 +198,9 @@ const UNVERIFIABLE_REMOVAL_SENTENCE = {
|
|
|
172
198
|
relocated: (p, o) => `\`${p}\` recursive+force target ${o} is relative to a directory a launcher option moved the program into, which this command does not settle — the deleted path cannot be verified from this command`,
|
|
173
199
|
};
|
|
174
200
|
const UNREADABLE_TEXT_SENTENCE = {
|
|
175
|
-
produced: (p, t) => `\`${p}\` runs shell text that is built only when the command runs (${t}) — the text this shell will run cannot be read by the engine, so whether it removes anything is unknown`,
|
|
176
|
-
unread: (p, t) => `\`${p}\` runs shell text this guard cannot read (${t}) — the text this shell will run cannot be read by the engine, so whether it removes anything is unknown`,
|
|
201
|
+
produced: (p, t) => `\`${p}\` runs shell text that is built only when the command runs (${inlineUntrusted(t, 200)}) — the text this shell will run cannot be read by the engine, so whether it removes anything is unknown; write the text into the command itself (a \`-c\` string, a here-document or a here-string) and the engine reads it as it reads any command`,
|
|
202
|
+
unread: (p, t) => `\`${p}\` runs shell text this guard cannot read (${inlineUntrusted(t, 200)}) — the text this shell will run cannot be read by the engine, so whether it removes anything is unknown`,
|
|
203
|
+
position: (_p, t) => inlineUntrusted(declinedProgramSentence(t), 400),
|
|
177
204
|
};
|
|
178
205
|
function verdictOf(findings) {
|
|
179
206
|
for (const f of findings) {
|
|
@@ -187,7 +214,7 @@ function verdictOf(findings) {
|
|
|
187
214
|
return { guard: f.guard, text: UNVERIFIABLE_REMOVAL_SENTENCE[f.source](f.program, inlineUntrusted(f.operand, 200)) };
|
|
188
215
|
for (const f of findings)
|
|
189
216
|
if (f.guard === "unverifiable_shell_text")
|
|
190
|
-
return { guard: f.guard, text: UNREADABLE_TEXT_SENTENCE[f.source](f.program,
|
|
217
|
+
return { guard: f.guard, text: UNREADABLE_TEXT_SENTENCE[f.source](f.program, f.text) };
|
|
191
218
|
return undefined;
|
|
192
219
|
}
|
|
193
220
|
const REMOVAL_RESOLVE_TIMEOUT_MS = 10_000;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ExecutionEnv } from "../../internal/harness-types.js";
|
|
2
2
|
import { type HomeViewsCarrier } from "./read-deny-home.js";
|
|
3
|
+
import { type FsGlob } from "./fs-glob.js";
|
|
3
4
|
/** The JS scanner's own output ceiling, in bytes of emitted content rows. Pinned to the
|
|
4
5
|
* ripgrep leg's figure ({@link MAX_EXEC_OUTPUT_BYTES}, the exec pipe's rolling-tail bound) so the two
|
|
5
6
|
* legs cannot disagree about how much one search may return; see the collection site in {@link jsGrep}
|
|
@@ -56,6 +57,15 @@ export declare function splitGlobParam(glob: string): string[];
|
|
|
56
57
|
* Exported for direct injection testing.
|
|
57
58
|
*/
|
|
58
59
|
export declare function shellQuote(s: string): string;
|
|
60
|
+
/** Out-parameter for {@link compileGlobToken}: set to `true` when a glob-syntax construct
|
|
61
|
+
* could NOT be compiled and silently fell back to matching the metacharacter LITERALLY. Only the
|
|
62
|
+
* glob-syntax lane (`glob = true`) can set it; the gitignore lane has no such syntax to fail at. */
|
|
63
|
+
export interface GlobCompileReport {
|
|
64
|
+
degraded: boolean;
|
|
65
|
+
}
|
|
66
|
+
/** Compile a gitignore/glob token to a matcher tested against a relative posix path. The matcher is the engine in
|
|
67
|
+
* `fs-glob.ts`: its cost is bounded by the token's length times the path's, whatever the arrangement of the stars. */
|
|
68
|
+
export declare function compileGlobToken(token: string, anchored: boolean, glob?: boolean, report?: GlobCompileReport): FsGlob;
|
|
59
69
|
/**
|
|
60
70
|
* The tokens of a `glob` argument that this engine CANNOT compile as glob syntax, i.e. the ones whose
|
|
61
71
|
* metacharacter would silently degrade to a literal match.
|
package/dist/tools/fs/search.js
CHANGED
|
@@ -4,6 +4,7 @@ import { MAX_EXEC_OUTPUT_BYTES } from "../../core/exec-output-tail.js";
|
|
|
4
4
|
import { anchorSpelling, hasBinaryExtension, isWinFormPath, pathFamilyOf } from "./safety.js";
|
|
5
5
|
import { HomeViewUnreadError, homeViewsOf } from "./read-deny-home.js";
|
|
6
6
|
import { createEntryDenyJudge } from "./dir-entries.js";
|
|
7
|
+
import { compileFsGlob, fsGlobClass } from "./fs-glob.js";
|
|
7
8
|
import { thrownText } from "../../core/thrown-value.js";
|
|
8
9
|
const WALK_MAX_FILES = 5000;
|
|
9
10
|
const WALK_MAX_DEPTH = 32;
|
|
@@ -78,32 +79,31 @@ export function splitGlobParam(glob) {
|
|
|
78
79
|
export function shellQuote(s) {
|
|
79
80
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
80
81
|
}
|
|
81
|
-
function
|
|
82
|
-
const
|
|
83
|
-
|
|
82
|
+
export function compileGlobToken(token, anchored, glob = false, report) {
|
|
83
|
+
const unitOf = (ch) => (ch === "*" ? { kind: "star" } : ch === "?" ? { kind: "one" } : { kind: "text", text: ch });
|
|
84
|
+
const tokens = [];
|
|
84
85
|
for (let i = 0; i < token.length; i++) {
|
|
85
86
|
const c = token[i];
|
|
86
87
|
if (c === "*") {
|
|
87
88
|
if (token[i + 1] === "*") {
|
|
88
|
-
|
|
89
|
+
tokens.push({ kind: "globstar" });
|
|
89
90
|
i++;
|
|
90
91
|
if (token[i + 1] === "/")
|
|
91
92
|
i++;
|
|
92
93
|
}
|
|
93
94
|
else
|
|
94
|
-
|
|
95
|
+
tokens.push({ kind: "star" });
|
|
95
96
|
}
|
|
96
97
|
else if (c === "?")
|
|
97
|
-
|
|
98
|
+
tokens.push({ kind: "one" });
|
|
98
99
|
else if (glob && c === "{") {
|
|
99
100
|
const close = token.indexOf("}", i);
|
|
100
101
|
if (close > i + 1) {
|
|
101
|
-
|
|
102
|
-
re += `(?:${alts.join("|")})`;
|
|
102
|
+
tokens.push({ kind: "alt", alternatives: token.slice(i + 1, close).split(",").map((alt) => [...alt].map(unitOf)) });
|
|
103
103
|
i = close;
|
|
104
104
|
}
|
|
105
105
|
else {
|
|
106
|
-
|
|
106
|
+
tokens.push({ kind: "text", text: "{" });
|
|
107
107
|
if (report)
|
|
108
108
|
report.degraded = true;
|
|
109
109
|
}
|
|
@@ -122,34 +122,28 @@ function globTokenToRegExp(token, anchored, glob = false, report) {
|
|
|
122
122
|
let cls;
|
|
123
123
|
if (close !== -1) {
|
|
124
124
|
const body = token.slice(bodyStart, close).replace(/[\\[\]]/g, "\\$&").replace(/\//g, "");
|
|
125
|
-
cls = `[${neg ? "^/" : ""}${body}]
|
|
126
|
-
try {
|
|
127
|
-
new RegExp(cls);
|
|
128
|
-
}
|
|
129
|
-
catch {
|
|
130
|
-
cls = undefined;
|
|
131
|
-
}
|
|
125
|
+
cls = fsGlobClass(`[${neg ? "^/" : ""}${body}]`);
|
|
132
126
|
}
|
|
133
127
|
if (cls !== undefined) {
|
|
134
|
-
|
|
128
|
+
tokens.push({ kind: "class", class: cls });
|
|
135
129
|
i = close;
|
|
136
130
|
}
|
|
137
131
|
else {
|
|
138
|
-
|
|
132
|
+
tokens.push({ kind: "text", text: "[" });
|
|
139
133
|
if (report)
|
|
140
134
|
report.degraded = true;
|
|
141
135
|
}
|
|
142
136
|
}
|
|
143
137
|
else
|
|
144
|
-
|
|
138
|
+
tokens.push({ kind: "text", text: c });
|
|
145
139
|
}
|
|
146
|
-
return
|
|
140
|
+
return compileFsGlob(tokens, anchored ? "start" : "segment");
|
|
147
141
|
}
|
|
148
142
|
export function invalidGlobTokens(glob) {
|
|
149
143
|
const bad = [];
|
|
150
144
|
for (const token of splitGlobParam(glob)) {
|
|
151
145
|
const report = { degraded: false };
|
|
152
|
-
|
|
146
|
+
compileGlobToken(normalizeGlobToken(token), globIsAnchored(token), true, report);
|
|
153
147
|
if (report.degraded)
|
|
154
148
|
bad.push(token);
|
|
155
149
|
}
|
|
@@ -187,7 +181,7 @@ export function gitignoreMatcher(content) {
|
|
|
187
181
|
const anchored = pat.startsWith("/");
|
|
188
182
|
if (anchored)
|
|
189
183
|
pat = pat.replace(/^\/+/, "");
|
|
190
|
-
return { neg, dirOnly, anchored, re:
|
|
184
|
+
return { neg, dirOnly, anchored, re: compileGlobToken(pat, anchored), bare: pat };
|
|
191
185
|
});
|
|
192
186
|
return (relRaw, isDir) => {
|
|
193
187
|
const rel = relRaw.replace(/\\/g, "/");
|
|
@@ -834,7 +828,7 @@ export async function jsGrepDetailed(env, root, p, signal, guards, deny, denyOut
|
|
|
834
828
|
return rel(abs);
|
|
835
829
|
};
|
|
836
830
|
if (p.glob) {
|
|
837
|
-
const globRes = splitGlobParam(p.glob).map((g) =>
|
|
831
|
+
const globRes = splitGlobParam(p.glob).map((g) => compileGlobToken(normalizeGlobToken(g), globIsAnchored(g), true));
|
|
838
832
|
if (globRes.length > 0)
|
|
839
833
|
files = files.filter((f) => globRes.some((re) => re.test(rel(f).replace(/\\/g, "/"))));
|
|
840
834
|
}
|
|
@@ -842,7 +836,7 @@ export async function jsGrepDetailed(env, root, p, signal, guards, deny, denyOut
|
|
|
842
836
|
if (p.type) {
|
|
843
837
|
const tg = TYPE_GLOBS[p.type.toLowerCase()];
|
|
844
838
|
if (tg) {
|
|
845
|
-
const typeRe =
|
|
839
|
+
const typeRe = compileGlobToken(tg, false, true);
|
|
846
840
|
files = files.filter((f) => typeRe.test(basename(f)));
|
|
847
841
|
}
|
|
848
842
|
else {
|
|
@@ -1380,7 +1374,7 @@ export async function runGlobDetailed(env, root, pattern, opts = {}, signal) {
|
|
|
1380
1374
|
}
|
|
1381
1375
|
const pat = normalizeGlobToken(pattern);
|
|
1382
1376
|
const anchored = globIsAnchored(pattern);
|
|
1383
|
-
const re =
|
|
1377
|
+
const re = compileGlobToken(pat, anchored, true);
|
|
1384
1378
|
const startPrefix = start.replace(/[\\/]+$/, "") + (start.includes("\\") ? "\\" : "/");
|
|
1385
1379
|
const startRelPrefix = startPrefix.startsWith(rootPrefix) ? startPrefix.slice(rootPrefix.length) : startPrefix;
|
|
1386
1380
|
const toStartRel = (p) => {
|
|
@@ -1396,7 +1390,7 @@ export async function runGlobDetailed(env, root, pattern, opts = {}, signal) {
|
|
|
1396
1390
|
const prunable = anchored && !groupSpansSlash;
|
|
1397
1391
|
const firstStarStar = patternSegs.findIndex((s) => s.includes("**"));
|
|
1398
1392
|
const starStarIdx = firstStarStar === -1 ? Infinity : firstStarStar;
|
|
1399
|
-
const segRes = prunable ? patternSegs.map((s) =>
|
|
1393
|
+
const segRes = prunable ? patternSegs.map((s) => compileGlobToken(s, true, true)) : [];
|
|
1400
1394
|
const isLiteralSeg = (s) => s.length > 0 && !/[*?[{]/.test(s);
|
|
1401
1395
|
const literalAt = prunable ? patternSegs.map((s) => (isLiteralSeg(s) ? s : undefined)) : [];
|
|
1402
1396
|
const literalAfterStarStar = new Set(prunable ? patternSegs.filter((s, i) => i > starStarIdx && isLiteralSeg(s)) : []);
|