@sema-agent/core 7.54.1 → 7.55.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 +437 -0
- package/dist/agents/agent-transcript-tool.js +2 -1
- package/dist/agents/builtin-agents.d.ts +12 -14
- package/dist/agents/cc-peer-directory.d.ts +36 -0
- package/dist/agents/cc-peer-directory.js +138 -0
- package/dist/agents/cc-peer-wire.d.ts +105 -0
- package/dist/agents/cc-peer-wire.js +98 -0
- package/dist/agents/cc-uds-peer-channel.d.ts +40 -0
- package/dist/agents/cc-uds-peer-channel.js +457 -0
- package/dist/agents/cross-session-envelope.d.ts +4 -1
- package/dist/agents/cross-session-envelope.js +8 -1
- package/dist/agents/cross-session-judge.d.ts +2 -2
- package/dist/agents/list-agents-tool.js +2 -1
- package/dist/agents/observer.d.ts +4 -5
- package/dist/agents/observer.js +2 -1
- package/dist/agents/peer-admission.d.ts +6 -0
- package/dist/agents/peer-admission.js +4 -1
- package/dist/agents/peer-directory.d.ts +43 -9
- package/dist/agents/peer-directory.js +66 -23
- package/dist/agents/peer-notices.d.ts +1 -1
- package/dist/agents/peer-session-drain.d.ts +3 -1
- package/dist/agents/peer-session-drain.js +1 -0
- package/dist/agents/read-inbox-tool.js +2 -1
- package/dist/agents/retain-ledger.d.ts +1 -1
- package/dist/agents/roster-store.d.ts +1 -1
- package/dist/agents/send-message-tool.d.ts +10 -0
- package/dist/agents/send-message-tool.js +34 -5
- package/dist/agents/subagent.d.ts +34 -79
- package/dist/agents/subagent.js +45 -46
- package/dist/agents/tool-filter.d.ts +29 -46
- package/dist/agents/tool-filter.js +8 -31
- package/dist/agents/verify.d.ts +3 -3
- package/dist/brain/anthropic.js +14 -9
- package/dist/brain/errors.d.ts +15 -0
- package/dist/brain/errors.js +10 -0
- package/dist/brain/model-presets.d.ts +4 -4
- package/dist/brain/open-responses.js +15 -10
- package/dist/brain/openai.js +17 -12
- package/dist/brain/provider-dialect.d.ts +39 -3
- package/dist/brain/provider-dialect.js +28 -0
- package/dist/brain/reasoning.d.ts +1 -1
- package/dist/brain/request-params.d.ts +55 -5
- package/dist/brain/request-params.js +35 -3
- package/dist/brain/retry.d.ts +1 -1
- package/dist/brain/route-adjudicator.d.ts +15 -0
- package/dist/brain/route-adjudicator.js +15 -0
- package/dist/brain/stream-engine.js +6 -5
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/core/advisor-verdict.d.ts +120 -0
- package/dist/core/advisor-verdict.js +92 -0
- package/dist/core/agent-definition.d.ts +7 -8
- package/dist/core/allow-entry.d.ts +49 -23
- package/dist/core/allow-entry.js +57 -32
- package/dist/core/allow-rule-shadow.d.ts +7 -0
- package/dist/core/approval-object.d.ts +2 -1
- package/dist/core/approval-object.js +6 -6
- package/dist/core/ask-origin.d.ts +63 -11
- package/dist/core/ask-origin.js +27 -5
- package/dist/core/ask-question.js +10 -4
- package/dist/core/auto-compaction.d.ts +11 -8
- package/dist/core/auto-compaction.js +4 -2
- package/dist/core/auto-mode-arming.d.ts +2 -2
- package/dist/core/auto-mode-defaults.d.ts +8 -8
- package/dist/core/auto-mode-prompt-assets.d.ts +3 -3
- package/dist/core/auto-mode-prompt.d.ts +1 -1
- package/dist/core/auto-mode.d.ts +17 -9
- package/dist/core/auto-mode.js +9 -6
- package/dist/core/background-agent-store.d.ts +3 -3
- package/dist/core/canonical-json.d.ts +1 -1
- package/dist/core/canonical-json.js +2 -2
- package/dist/core/checkpoint-requirements.d.ts +6 -3
- package/dist/core/checkpoint-requirements.js +4 -14
- package/dist/core/checkpoint-store.d.ts +80 -51
- package/dist/core/checkpoint-store.js +56 -74
- package/dist/core/child-clamp-seats.d.ts +6 -0
- package/dist/core/child-clamp-seats.js +3 -16
- package/dist/core/compliance.d.ts +2 -2
- package/dist/core/context-edit.d.ts +6 -7
- package/dist/core/cross-boundary-taint.d.ts +9 -3
- package/dist/core/cross-boundary-taint.js +5 -3
- package/dist/core/decision-receipt.js +2 -2
- package/dist/core/effective-path-target.d.ts +1 -1
- package/dist/core/engine-notice.d.ts +19 -5
- package/dist/core/exec-output-tail.d.ts +1 -1
- package/dist/core/file-history-retention.d.ts +1 -1
- package/dist/core/file-history-store.d.ts +59 -9
- package/dist/core/file-history-store.js +35 -17
- package/dist/core/gate-fold.js +3 -2
- package/dist/core/gate-lanes.js +12 -8
- package/dist/core/gate-outcome.d.ts +17 -4
- package/dist/core/gate-outcome.js +30 -0
- package/dist/core/governance-codes.d.ts +13 -3
- package/dist/core/governance-codes.js +10 -0
- package/dist/core/hands-band.d.ts +1 -1
- package/dist/core/hooks.d.ts +4 -4
- package/dist/core/host-target.d.ts +49 -0
- package/dist/core/host-target.js +59 -0
- package/dist/core/image-downsample.d.ts +1 -1
- package/dist/core/lsp-diagnostics.d.ts +4 -4
- package/dist/core/lsp.d.ts +3 -3
- package/dist/core/mailbox-store.d.ts +4 -0
- package/dist/core/mcp-connection-pool.d.ts +18 -2
- package/dist/core/mcp-connection-pool.js +53 -6
- package/dist/core/mcp-failure.d.ts +23 -4
- package/dist/core/mcp-failure.js +26 -11
- package/dist/core/mcp-listing-drift.d.ts +10 -0
- package/dist/core/mcp-listing-drift.js +6 -0
- package/dist/core/mcp-server-link.d.ts +173 -0
- package/dist/core/mcp-server-link.js +127 -0
- package/dist/core/mcp-server-spec.d.ts +4 -2
- package/dist/core/mcp-session-end.d.ts +26 -0
- package/dist/core/mcp-session-end.js +29 -0
- package/dist/core/mcp-startup-request.d.ts +17 -0
- package/dist/core/mcp-startup-request.js +17 -0
- package/dist/core/mcp.d.ts +13 -13
- package/dist/core/mcp.js +187 -162
- package/dist/core/media-byte-cap.d.ts +1 -1
- package/dist/core/memory-engine/engine.d.ts +9 -9
- package/dist/core/memory-engine/provenance-wording.d.ts +1 -1
- package/dist/core/memory-engine/tools.js +4 -1
- package/dist/core/mode-policy.d.ts +1 -1
- package/dist/core/namespaced-rule-name.d.ts +33 -7
- package/dist/core/namespaced-rule-name.js +39 -25
- package/dist/core/output-style.d.ts +1 -1
- package/dist/core/param-rule-reach.d.ts +15 -0
- package/dist/core/param-rule-reach.js +30 -0
- package/dist/core/parent-spec-seat.d.ts +8 -1
- package/dist/core/parent-spec-seat.js +4 -0
- package/dist/core/pause-registry.d.ts +16 -5
- package/dist/core/pause-registry.js +6 -2
- package/dist/core/peer-channel.d.ts +70 -0
- package/dist/core/peer-channel.js +1 -0
- package/dist/core/permission-rule-consent.d.ts +11 -5
- package/dist/core/permission-rule-consent.js +37 -30
- package/dist/core/permission-rule-model.d.ts +233 -64
- package/dist/core/permission-rule-model.js +384 -85
- package/dist/core/permission-rule-provider.d.ts +2 -1
- package/dist/core/permission-rule-store.d.ts +20 -25
- package/dist/core/permission-rule-store.js +1 -4
- package/dist/core/permission-rule-sync.d.ts +11 -2
- package/dist/core/permission-rule-sync.js +8 -1
- package/dist/core/permission-rules.d.ts +49 -11
- package/dist/core/permission-rules.js +123 -89
- package/dist/core/persisted-rule-arms.d.ts +4 -2
- package/dist/core/present-plan-tool.js +3 -1
- package/dist/core/protocol-naming.d.ts +2 -2
- package/dist/core/read-only-shell-table.d.ts +1 -1
- package/dist/core/read-only-shell.d.ts +1 -1
- package/dist/core/roles.d.ts +6 -2
- package/dist/core/roles.js +45 -44
- package/dist/core/rule-offer-read.d.ts +53 -0
- package/dist/core/rule-offer-read.js +146 -0
- package/dist/core/rule-owner.d.ts +46 -0
- package/dist/core/rule-owner.js +28 -0
- package/dist/core/runner/advisor-instructions.d.ts +70 -0
- package/dist/core/runner/advisor-instructions.js +61 -0
- package/dist/core/runner/advisor-tool.d.ts +33 -0
- package/dist/core/runner/advisor-tool.js +112 -0
- package/dist/core/runner/announce-once-ledger.d.ts +4 -26
- package/dist/core/runner/announce-once-ledger.js +14 -46
- package/dist/core/runner/approval-feedback.js +6 -3
- package/dist/core/runner/assemble-result.d.ts +1 -1
- package/dist/core/runner/caller-roster.d.ts +7 -0
- package/dist/core/runner/caller-roster.js +11 -0
- package/dist/core/runner/classifier-ladder.d.ts +27 -5
- package/dist/core/runner/classifier-ladder.js +12 -11
- package/dist/core/runner/compaction-restate.d.ts +10 -6
- package/dist/core/runner/compaction-restate.js +9 -3
- package/dist/core/runner/contracts.d.ts +13 -9
- package/dist/core/runner/conversation-segment.d.ts +28 -0
- package/dist/core/runner/conversation-segment.js +42 -0
- package/dist/core/runner/cross-boundary-lane.d.ts +6 -5
- package/dist/core/runner/cross-boundary-lane.js +26 -15
- package/dist/core/runner/decide-continuation.d.ts +7 -4
- package/dist/core/runner/decide-continuation.js +2 -2
- package/dist/core/runner/denial-limit-arms.d.ts +2 -2
- package/dist/core/runner/derived-route-fallback.d.ts +24 -24
- package/dist/core/runner/derived-route-fallback.js +9 -7
- package/dist/core/runner/gate-exit.d.ts +6 -0
- package/dist/core/runner/gate-exit.js +7 -2
- package/dist/core/runner/initial-run-state.js +1 -1
- package/dist/core/runner/permission-rule-lanes.d.ts +2 -2
- package/dist/core/runner/permission-rule-lanes.js +14 -7
- package/dist/core/runner/person-path-rows.js +1 -1
- package/dist/core/runner/prepare-advisor.d.ts +63 -0
- package/dist/core/runner/prepare-advisor.js +77 -0
- package/dist/core/runner/prepare-caps-and-workflow.js +1 -1
- package/dist/core/runner/prepare-config-doors.d.ts +6 -4
- package/dist/core/runner/prepare-config-doors.js +18 -12
- package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
- package/dist/core/runner/prepare-delegation-surface.js +1 -1
- package/dist/core/runner/prepare-file-history.js +39 -39
- package/dist/core/runner/prepare-gate-stations.d.ts +1 -4
- package/dist/core/runner/prepare-gate-stations.js +2 -7
- package/dist/core/runner/prepare-inherited-gate.d.ts +5 -4
- package/dist/core/runner/prepare-inherited-gate.js +3 -3
- package/dist/core/runner/prepare-park-ask.js +7 -7
- package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
- package/dist/core/runner/prepare-policy-chain.js +4 -10
- package/dist/core/runner/prepare-project-context.d.ts +5 -2
- package/dist/core/runner/prepare-project-context.js +6 -3
- package/dist/core/runner/prepare-prompt-inputs.js +1 -1
- package/dist/core/runner/prepare-protocol-tools.d.ts +2 -2
- package/dist/core/runner/prepare-protocol-tools.js +3 -2
- package/dist/core/runner/prepare-safety-scan.d.ts +9 -12
- package/dist/core/runner/prepare-safety-scan.js +8 -6
- package/dist/core/runner/prepare-task.js +15 -18
- package/dist/core/runner/prepare-tool-disclosure-mount.js +6 -4
- package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -3
- package/dist/core/runner/prepare-wiring-manifest.js +2 -2
- package/dist/core/runner/resume-policy-outcome.js +1 -1
- package/dist/core/runner/retired-runner-deps.js +1 -1
- package/dist/core/runner/run-attachment-seats.js +0 -1
- package/dist/core/runner/run-compaction-machinery.d.ts +1 -1
- package/dist/core/runner/run-compaction-machinery.js +2 -12
- package/dist/core/runner/run-git-lane.d.ts +1 -0
- package/dist/core/runner/run-harness-handlers.js +2 -3
- package/dist/core/runner/run-leg.js +13 -0
- package/dist/core/runner/run-settle-and-teardown.js +1 -1
- package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
- package/dist/core/runner/run-turn-boundary.d.ts +1 -0
- package/dist/core/runner/run-turn-boundary.js +14 -12
- package/dist/core/runner/session-rule-policy.d.ts +22 -21
- package/dist/core/runner/session-rule-policy.js +13 -28
- package/dist/core/runner/side-call-account.d.ts +32 -8
- package/dist/core/runner/side-call-account.js +23 -1
- package/dist/core/runner/strict-output-schema.d.ts +1 -1
- package/dist/core/runner/sub-agent-deny-lists.js +4 -3
- package/dist/core/runner/synthetic-tools.d.ts +10 -13
- package/dist/core/runner/synthetic-tools.js +4 -2
- package/dist/core/runner/tool-disclosure.js +2 -1
- package/dist/core/runner/tool-face-overlay.d.ts +2 -1
- package/dist/core/runner/tool-face-overlay.js +17 -1
- package/dist/core/runner/tool-progress-lane.d.ts +2 -2
- package/dist/core/runner/tool-turn-repair-seat.d.ts +3 -2
- package/dist/core/runner/turn-attachments.d.ts +60 -67
- package/dist/core/runner-deps.d.ts +37 -37
- package/dist/core/runtime-caps.d.ts +4 -4
- package/dist/core/safety-merge-corpus.js +17 -1
- package/dist/core/same-plain-value.d.ts +40 -0
- package/dist/core/same-plain-value.js +49 -0
- package/dist/core/scheduler.d.ts +1 -1
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/sensitive-path-policy.js +1 -1
- package/dist/core/session-policy-store.d.ts +77 -22
- package/dist/core/session-policy-store.js +56 -14
- package/dist/core/session-reconcile.d.ts +2 -2
- package/dist/core/session-store.d.ts +80 -30
- package/dist/core/session-store.js +118 -76
- package/dist/core/session.d.ts +24 -46
- package/dist/core/shared-memory/tools.js +3 -1
- package/dist/core/shared-memory/types.d.ts +1 -1
- package/dist/core/side-query.d.ts +10 -0
- package/dist/core/side-query.js +5 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +29 -2
- package/dist/core/store-contracts/file-history-store-contract.js +43 -3
- package/dist/core/store-contracts/session-policy-store-contract.d.ts +7 -0
- package/dist/core/store-contracts/session-policy-store-contract.js +130 -0
- package/dist/core/store-contracts/session-repo-contract.js +125 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +4 -7
- package/dist/core/store-contracts/session-store-contract.js +215 -41
- package/dist/core/store-contracts/workflow-journal-store-contract.js +26 -1
- package/dist/core/surrogate-safe-slice.d.ts +3 -3
- package/dist/core/task-event.d.ts +10 -4
- package/dist/core/task-notification.d.ts +3 -3
- package/dist/core/task-registry-agent.d.ts +4 -4
- package/dist/core/task-registry-shared.d.ts +4 -4
- package/dist/core/task-registry-shared.js +1 -0
- package/dist/core/task-registry.d.ts +4 -4
- package/dist/core/task-registry.js +3 -1
- package/dist/core/task-result.d.ts +3 -3
- package/dist/core/task-spec.d.ts +52 -52
- package/dist/core/task-stream.d.ts +6 -6
- package/dist/core/task-tool-shape.d.ts +4 -4
- package/dist/core/tighten-task-spec.d.ts +1 -1
- package/dist/core/tool-catalog-entries.d.ts +19 -2
- package/dist/core/tool-catalog-entries.js +57 -42
- package/dist/core/tool-conformance.js +1 -0
- package/dist/core/tool-errors.d.ts +2 -2
- package/dist/core/tool-face-reader.js +5 -3
- package/dist/core/tool-face.d.ts +21 -2
- package/dist/core/tool-face.js +1 -1
- package/dist/core/tool-model-gate.d.ts +3 -3
- package/dist/core/tool-name-aliases.d.ts +29 -8
- package/dist/core/tool-name-aliases.js +27 -3
- package/dist/core/tool-name-readings.d.ts +5 -8
- package/dist/core/tool-name-readings.js +1 -2
- package/dist/core/tool-policy.d.ts +24 -5
- package/dist/core/tool-policy.js +34 -10
- package/dist/core/tool-registry.d.ts +14 -7
- package/dist/core/tool-registry.js +17 -7
- package/dist/core/tool-result-store.js +2 -1
- package/dist/core/tool-roster.d.ts +47 -18
- package/dist/core/tool-roster.js +53 -32
- package/dist/core/tool-spec-members.js +1 -1
- package/dist/core/tool-spec.d.ts +35 -21
- package/dist/core/tools.js +3 -2
- package/dist/core/trace.d.ts +4 -0
- package/dist/core/untrusted-egress.d.ts +1 -1
- package/dist/core/untrusted-text.d.ts +1 -1
- package/dist/core/warm-resume.d.ts +1 -1
- package/dist/core/wiring-manifest.d.ts +49 -0
- package/dist/core/wiring-manifest.js +13 -5
- package/dist/core/workflow-journal-store.d.ts +62 -0
- package/dist/core/workflow-journal-store.js +77 -1
- package/dist/core/workflow-run-store.d.ts +6 -0
- package/dist/core/workflow-run-store.js +2 -0
- package/dist/engine/compaction/compaction.d.ts +9 -9
- package/dist/engine/execution-env/node-execution-env.d.ts +19 -5
- package/dist/engine/execution-env/node-execution-env.js +43 -22
- package/dist/engine/harness/agent-harness.d.ts +14 -8
- package/dist/engine/harness/agent-harness.js +33 -26
- package/dist/engine/harness/types.d.ts +29 -7
- package/dist/engine/harness/types.js +12 -1
- package/dist/engine/llm/types.d.ts +9 -9
- package/dist/engine/llm/validation.d.ts +4 -1
- package/dist/engine/llm/validation.js +13 -1
- package/dist/engine/loop/agent-loop.d.ts +1 -1
- package/dist/engine/loop/agent-loop.js +10 -8
- package/dist/engine/loop/types.d.ts +15 -13
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/memory-repo.d.ts +10 -11
- package/dist/engine/session/memory-repo.js +13 -8
- package/dist/engine/session/parent-chain-guard.d.ts +3 -2
- package/dist/engine/session/parent-chain-guard.js +1 -1
- package/dist/engine/session/repo-utils.d.ts +31 -3
- package/dist/engine/session/repo-utils.js +42 -5
- package/dist/index.d.ts +27 -15
- package/dist/index.js +21 -11
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/harness.d.ts +3 -3
- package/dist/internal/harness.js +2 -2
- package/dist/internal/llm.d.ts +1 -1
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/goal.js +2 -2
- package/dist/orchestration/run-workflow-tool.d.ts +2 -2
- package/dist/orchestration/run-workflow-tool.js +5 -3
- package/dist/orchestration/workflow-size-guideline.d.ts +4 -4
- package/dist/orchestration/workflow-types.d.ts +18 -0
- package/dist/orchestration/workflow-types.js +6 -0
- package/dist/orchestration/workflow.d.ts +2 -13
- package/dist/orchestration/workflow.js +21 -31
- package/dist/prompt-assembly/event-registry.js +1 -0
- package/dist/prompt-assembly/tool-catalog.d.ts +3 -0
- package/dist/prompt-assembly/tool-catalog.js +3 -0
- package/dist/prompts/default.d.ts +14 -14
- package/dist/scenarios/full-body.d.ts +4 -4
- package/dist/stores/file/adoption/adopt.d.ts +4 -3
- package/dist/stores/file/adoption/adopt.js +24 -31
- package/dist/stores/file/adoption/marker.d.ts +6 -13
- package/dist/stores/file/adoption/marker.js +6 -15
- package/dist/stores/file/checkpoint-store.d.ts +3 -0
- package/dist/stores/file/checkpoint-store.js +9 -3
- package/dist/stores/file/file-history-store.d.ts +20 -19
- package/dist/stores/file/file-history-store.js +152 -135
- package/dist/stores/file/fs-atomic.d.ts +15 -0
- package/dist/stores/file/fs-atomic.js +89 -14
- package/dist/stores/file/index.d.ts +1 -1
- package/dist/stores/file/mailbox-store.d.ts +3 -0
- package/dist/stores/file/mailbox-store.js +3 -1
- package/dist/stores/file/permission-rule-adopt.d.ts +1 -1
- package/dist/stores/file/permission-rule-adopt.js +15 -16
- package/dist/stores/file/permission-rule-store.d.ts +18 -2
- package/dist/stores/file/permission-rule-store.js +21 -14
- package/dist/stores/file/session-policy-store.d.ts +3 -3
- package/dist/stores/file/session-store.d.ts +26 -11
- package/dist/stores/file/session-store.js +77 -40
- package/dist/stores/file/workflow-journal-store.d.ts +10 -4
- package/dist/stores/file/workflow-journal-store.js +28 -13
- package/dist/tools/artifact/artifact-text.d.ts +1 -1
- package/dist/tools/artifact/artifact-tool.js +2 -1
- package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -3
- package/dist/tools/fs/fs-bash.d.ts +2 -2
- package/dist/tools/fs/fs-bash.js +3 -1
- package/dist/tools/fs/fs-shared.d.ts +8 -8
- package/dist/tools/fs/gh-rate-limit.d.ts +1 -1
- package/dist/tools/fs/notebook.d.ts +2 -2
- package/dist/tools/fs/read-deny.d.ts +29 -7
- package/dist/tools/fs/read-deny.js +63 -22
- package/dist/tools/fs/removal-targets.d.ts +1 -1
- package/dist/tools/fs/safety.d.ts +9 -9
- package/dist/tools/fs/search.d.ts +6 -6
- package/dist/tools/fs/shell-read-check.js +6 -1
- package/dist/tools/fs/shell-read-judge.d.ts +4 -0
- package/dist/tools/fs/shell-read-judge.js +5 -2
- package/dist/tools/loop-tick.d.ts +2 -2
- package/dist/tools/scheduler-tools.js +5 -1
- package/dist/tools/task-list.d.ts +7 -7
- package/dist/tools/task-list.js +5 -1
- package/dist/tools/todo.js +2 -1
- package/dist/tools/web.d.ts +1 -1
- package/dist/tools/web.js +40 -37
- package/dist/tools/worktree.d.ts +3 -3
- package/dist/tools/worktree.js +3 -1
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +5756 -5638
- package/wire-changes/core@7.55.0.json +3318 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +0 -39
- package/dist/core/store-contracts/session-store-incarnation-contract.js +0 -95
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { attest } from "./tool-policy.js";
|
|
2
2
|
import { MCP_NAMESPACE, protocolOf } from "./protocol-table.js";
|
|
3
3
|
import { catalogRuleFaceOf, isShellFaceToolName, pathTargetOf } from "./tool-registry.js";
|
|
4
|
+
import { HOST_UNREADABLE_SENTENCE, callHostTargetOf } from "./host-target.js";
|
|
4
5
|
import { indexOfUnescaped, lastIndexOfUnescaped, parsePermissionRule, ruleSpellingOf } from "./permission-rule-syntax.js";
|
|
5
|
-
import {
|
|
6
|
+
import { callPathFaceOf, canonicalNameValue, COMMAND_RULE_TOOL, domainRuleAdmits, isUsablePathBase, laneToolNamesOf, mountedOnlyArgumentOf, mountedValueArmOf, NAME_RULE_FACES, nameRuleReach, nameRuleSubjectOf, nameValueAbsentReason, nameValuesUnreadReason, parseRuleText, PATH_RULE_BASE_LABEL, PATH_RULE_FACES, programRunReachOf, ruleBasesNeeded, ruleLaneOf, ruleShapeOf, shellRuleParamOf, ruleContentOf } from "./permission-rule-model.js";
|
|
6
7
|
import { pathFamilyOf } from "../tools/fs/safety.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
8
|
+
import { callTargetReadingOf, callTargetViewsOf } from "./effective-path-target.js";
|
|
9
|
+
import { DEFAULT_MAX_SCALAR_VALUE_CHARS, paramRuleReaches } from "./param-rule-reach.js";
|
|
9
10
|
import { bindPathRules, judgeRuleRows, policyAnchors, rowsWhereTheyLead } from "./path-rule-binding.js";
|
|
10
11
|
import { ruleDenialSentence } from "./rule-denial-sentence.js";
|
|
11
12
|
import { heldValues } from "./tool-name-readings.js";
|
|
@@ -25,20 +26,28 @@ function describeBehavior(v) {
|
|
|
25
26
|
default: return v === null ? "null" : "an object";
|
|
26
27
|
}
|
|
27
28
|
}
|
|
29
|
+
export function ruleIssue(rule, code, message, libraryOption) {
|
|
30
|
+
return { rule, code, message, ...(libraryOption !== undefined ? { libraryOption } : {}) };
|
|
31
|
+
}
|
|
28
32
|
export const DEFAULT_CAPS = {
|
|
29
33
|
maxRules: 256,
|
|
30
34
|
maxRuleLength: 512,
|
|
31
35
|
maxPatternLength: 256,
|
|
32
36
|
maxStars: 16,
|
|
33
|
-
maxScalarValueChars:
|
|
37
|
+
maxScalarValueChars: DEFAULT_MAX_SCALAR_VALUE_CHARS,
|
|
34
38
|
};
|
|
35
39
|
import { isNamespacedCoveringRuleName, namespacedRuleNameCovers, wildcardMatch } from "./namespaced-rule-name.js";
|
|
40
|
+
import { wildcardPeerRefusalOf } from "./tool-name-aliases.js";
|
|
36
41
|
export { isNamespacedCoveringRuleName, namespacedRuleNameCovers, wildcardMatch };
|
|
42
|
+
const vocabularyOf = (face) => face.params ?? face.primaryParams;
|
|
43
|
+
const carriedPhrase = (face) => {
|
|
44
|
+
const vocabulary = vocabularyOf(face);
|
|
45
|
+
if (vocabulary.length > 0)
|
|
46
|
+
return `it carries ${[...vocabulary].sort().join(", ")}`;
|
|
47
|
+
return face.params !== undefined ? "it declares no rule-readable parameters" : "its parameters are not declared statically: each mount's schema is its own";
|
|
48
|
+
};
|
|
37
49
|
export function catalogRuleFaceView(toolName) {
|
|
38
|
-
|
|
39
|
-
if (face === undefined)
|
|
40
|
-
return undefined;
|
|
41
|
-
return { ...face, pathTargeting: pathTargetOf(toolName) !== undefined };
|
|
50
|
+
return catalogRuleFaceOf(toolName);
|
|
42
51
|
}
|
|
43
52
|
export const fileToolParamVocabulary = (canonicalTool) => {
|
|
44
53
|
const face = catalogRuleFaceOf(canonicalTool);
|
|
@@ -83,25 +92,25 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
|
|
|
83
92
|
const command = { deny: [], ask: [] };
|
|
84
93
|
const namespacedCovering = { deny: [], ask: [] };
|
|
85
94
|
const issues = [];
|
|
86
|
-
const bad = (rule, code, message) => {
|
|
87
|
-
issues.push(
|
|
95
|
+
const bad = (rule, code, message, libraryOption) => {
|
|
96
|
+
issues.push(ruleIssue(rule, code, message, libraryOption));
|
|
88
97
|
};
|
|
89
98
|
if (rules.length > caps.maxRules) {
|
|
90
|
-
return { byTool, command, namespacedCovering, issues: [
|
|
99
|
+
return { byTool, command, namespacedCovering, issues: [ruleIssue("", "invalid.cap_exceeded", `${rules.length} rules — a rule set holds at most ${caps.maxRules}`, { name: "caps.maxRules" })] };
|
|
91
100
|
}
|
|
92
101
|
for (const r of rules) {
|
|
93
102
|
const text = r.rule;
|
|
94
103
|
const behavior = r.behavior;
|
|
95
104
|
if (behavior !== "deny" && behavior !== "ask") {
|
|
96
105
|
if (behavior === "allow")
|
|
97
|
-
bad(text, "unsupported.allow", "an allow rule does not belong to a policy — allow entries live on the allow layer
|
|
106
|
+
bad(text, "unsupported.allow", "an allow rule does not belong to a policy — allow entries live on the allow layer (the request's allow list, or the deployment's); deny / ask rules stay here", { name: "TaskSpec.allowedTools" });
|
|
98
107
|
else
|
|
99
108
|
bad(text, "invalid.behavior", `a rule's behavior is one of "deny" | "ask" — got ${describeBehavior(behavior)}; a misspelled verb would compile to a rule that silently never fires`);
|
|
100
109
|
continue;
|
|
101
110
|
}
|
|
102
111
|
const verb = behavior;
|
|
103
112
|
if (text.length > caps.maxRuleLength) {
|
|
104
|
-
bad(text, "invalid.cap_exceeded", `rule longer than ${caps.maxRuleLength} chars
|
|
113
|
+
bad(text, "invalid.cap_exceeded", `rule longer than ${caps.maxRuleLength} chars`, { name: "caps.maxRuleLength" });
|
|
105
114
|
continue;
|
|
106
115
|
}
|
|
107
116
|
const parsed = ruleSpellingOf(text);
|
|
@@ -111,23 +120,29 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
|
|
|
111
120
|
continue;
|
|
112
121
|
}
|
|
113
122
|
if (parsed.toolName === "*") {
|
|
114
|
-
bad(text, "invalid.tool_name",
|
|
123
|
+
bad(text, "invalid.tool_name", "`*` names no tool — a rule reaches the tool it names, so this one would compile and never match; name the tool", { name: "defaultAction" });
|
|
115
124
|
continue;
|
|
116
125
|
}
|
|
117
126
|
const toolName = parsed.toolName;
|
|
118
127
|
const parenthesised = parsed.ruleContent !== undefined || indexOfUnescaped(text, "(") !== -1;
|
|
119
128
|
if (toolName.startsWith(MCP_NAMESPACE.prefix) && parenthesised) {
|
|
120
|
-
bad(text, "unsupported.mcp_paren", "MCP rules do not support patterns in parentheses (CC parity);
|
|
129
|
+
bad(text, "unsupported.mcp_paren", "MCP rules do not support patterns in parentheses (CC parity); a rule names a whole tool (`mcp__<server>__<tool>`) or a whole server (`mcp__<server>`), and what a tool does is declared per tool in the MCP server's spec", { name: "toolAxes" });
|
|
121
130
|
continue;
|
|
122
131
|
}
|
|
123
|
-
|
|
132
|
+
const wildPeer = wildcardPeerRefusalOf(toolName, verb);
|
|
133
|
+
if (wildPeer !== undefined) {
|
|
134
|
+
bad(text, "invalid.tool_name", wildPeer);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (parenthesised && isNamespacedCoveringRuleName(toolName, verb)) {
|
|
124
138
|
bad(text, "unsupported.covering_paren", `"${toolName}" reaches a SET of tools, and the generic param DSL is keyed by exact tool name — a parenthesised rule on it can never match. ` +
|
|
125
139
|
`Write the parenthesised rule against one exact tool name, or drop the parentheses to keep the covering rule.`);
|
|
126
140
|
continue;
|
|
127
141
|
}
|
|
128
142
|
const entry = byTool.get(toolName) ?? { bare: {}, param: { deny: [], ask: [] }, content: { deny: [], ask: [] } };
|
|
129
|
-
|
|
130
|
-
|
|
143
|
+
const content = ruleContentOf(parsed);
|
|
144
|
+
if (content === undefined) {
|
|
145
|
+
if (isNamespacedCoveringRuleName(toolName, verb)) {
|
|
131
146
|
namespacedCovering[verb].push({ ruleName: toolName, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
|
|
132
147
|
continue;
|
|
133
148
|
}
|
|
@@ -135,52 +150,70 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
|
|
|
135
150
|
byTool.set(toolName, entry);
|
|
136
151
|
continue;
|
|
137
152
|
}
|
|
138
|
-
const content = parsed.ruleContent;
|
|
139
153
|
const colon = content.indexOf(":");
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
154
|
+
let face;
|
|
155
|
+
if (!isShellFaceToolName(toolName)) {
|
|
156
|
+
const resolved = faceOf(toolName);
|
|
157
|
+
if (resolved.judged && resolved.face === undefined) {
|
|
158
|
+
bad(text, "unsupported.tool_unknown", `"${toolName}" is not a tool on this leg's roster — the rule would compile and never match`);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
face = resolved.face;
|
|
162
|
+
}
|
|
163
|
+
const lane = ruleLaneOf(toolName, content);
|
|
164
|
+
if (lane === "command") {
|
|
165
|
+
if (toolName !== COMMAND_RULE_TOOL) {
|
|
166
|
+
const commandWordParam = shellRuleParamOf(COMMAND_RULE_TOOL, content);
|
|
167
|
+
bad(text, "invalid.command_rule", commandWordParam !== undefined && !content.endsWith(":*")
|
|
168
|
+
? `"${text}" is a parameter rule on "${commandWordParam}", which ${toolName} does not declare (its rule parameters: ${(catalogRuleFaceOf(toolName)?.params ?? []).join(", ")}); a parameter rule reaches only the tool that declares the parameter, so ${COMMAND_RULE_TOOL}(${content}) is a rule on ${COMMAND_RULE_TOOL}'s own argument and does not reach ${toolName}. A shell command rule is written ${COMMAND_RULE_TOOL}(<command>) — it reaches ${toolName} and every other tool that runs a shell command by the command it runs.`
|
|
148
169
|
: `a shell command rule is written ${COMMAND_RULE_TOOL}(…) — it reaches ${toolName} and every other tool that runs a shell command by the command it runs; "${text}" names no rule upstream reads. Write ${COMMAND_RULE_TOOL}(${content}).`);
|
|
149
170
|
continue;
|
|
150
171
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
bad(text, "invalid.command_rule", `${parsedCommand.reject.code}: ${parsedCommand.reject.message}`);
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
command[verb].push({ parsed: parsedCommand.rule, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
|
|
172
|
+
const parsedCommand = parseRuleText(text, verb);
|
|
173
|
+
if ("reject" in parsedCommand) {
|
|
174
|
+
bad(text, "invalid.command_rule", `${parsedCommand.reject.code}: ${parsedCommand.reject.message}`);
|
|
158
175
|
continue;
|
|
159
176
|
}
|
|
177
|
+
command[verb].push({ parsed: parsedCommand.rule, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
|
|
178
|
+
continue;
|
|
160
179
|
}
|
|
161
180
|
else {
|
|
162
|
-
|
|
163
|
-
if (resolved.judged && resolved.face === undefined) {
|
|
164
|
-
bad(text, "unsupported.tool_unknown", `"${toolName}" is not a tool on this leg's roster — the rule would compile and never match`);
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
const face = resolved.face;
|
|
168
|
-
if (nameGrammarReads(toolName, content)) {
|
|
181
|
+
if (lane === "name") {
|
|
169
182
|
const parsedName = parseRuleText(text, verb);
|
|
170
183
|
if ("reject" in parsedName) {
|
|
171
184
|
bad(text, "invalid.command_rule", `${parsedName.reject.code}: ${parsedName.reject.message}`);
|
|
172
185
|
continue;
|
|
173
186
|
}
|
|
174
187
|
const param = NAME_RULE_FACES[toolName].param;
|
|
175
|
-
if (face
|
|
176
|
-
bad(text, "unsupported.param_unknown", `"${param}" is not a parameter of ${toolName} on this leg (
|
|
188
|
+
if (face !== undefined && !vocabularyOf(face).includes(param)) {
|
|
189
|
+
bad(text, "unsupported.param_unknown", `"${param}" is not a parameter of ${toolName} on this leg (${carriedPhrase(face)}) — a ${toolName} rule is read against it, so the rule would compile and never match`);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
const mountedOnly = mountedOnlyArgumentOf(toolName, content, face?.params);
|
|
193
|
+
if (mountedOnly !== undefined) {
|
|
194
|
+
bad(text, "unsupported.param_unknown", `"${mountedOnly}" is an argument declared only by the ${toolName} tool this leg mounts, which is not rule-readable (#2248) — "${text}" would read as the ${param} "${content}" and never reach a call setting ${mountedOnly}; write the rule on the whole tool (\`${toolName}\`), or on the ${param} it means`);
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const resolved = face?.nameValues !== undefined ? canonicalNameValue(parsedName.rule.command, face.nameValues) : undefined;
|
|
198
|
+
if (resolved?.kind === "ambiguous") {
|
|
199
|
+
bad(text, "invalid.name_ambiguous", `"${parsedName.rule.command}" names ${resolved.entries.length} of the ${param} values this leg's ${toolName} offers (${resolved.entries.join(", ")}) — they differ only by case, spacing or punctuation, so which one the rule means is not determinable; write the exact one`);
|
|
177
200
|
continue;
|
|
178
201
|
}
|
|
179
202
|
entry.content[verb].push({ parsed: parsedName.rule, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
|
|
180
203
|
byTool.set(toolName, entry);
|
|
181
204
|
continue;
|
|
182
205
|
}
|
|
183
|
-
if (
|
|
206
|
+
if (lane === "domain") {
|
|
207
|
+
const parsedHost = parseRuleText(text, verb);
|
|
208
|
+
if ("reject" in parsedHost) {
|
|
209
|
+
bad(text, "invalid.command_rule", `${parsedHost.reject.code}: ${parsedHost.reject.message}`);
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
entry.content[verb].push({ parsed: parsedHost.rule, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
|
|
213
|
+
byTool.set(toolName, entry);
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (lane === "path") {
|
|
184
217
|
const parsedPath = parseRuleText(text, verb);
|
|
185
218
|
if ("reject" in parsedPath) {
|
|
186
219
|
bad(text, "invalid.command_rule", `${parsedPath.reject.code}: ${parsedPath.reject.message}`);
|
|
@@ -189,7 +222,7 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
|
|
|
189
222
|
for (const base of ruleBasesNeeded(parsedPath.rule)) {
|
|
190
223
|
const declared = base === "cwd" ? (pathBases.cwd ?? pathBases.root) : pathBases[base];
|
|
191
224
|
if (declared !== undefined && !isUsablePathBase(declared, pathFamilyOf(pathBases))) {
|
|
192
|
-
bad(text, "unsupported.path_base", `"${text}" is relative to ${PATH_RULE_BASE_LABEL[base]}, and the
|
|
225
|
+
bad(text, "unsupported.path_base", `"${text}" is relative to ${PATH_RULE_BASE_LABEL[base]}, and the one this policy declares for it is not an absolute path of its tree's family — the rule could not be judged on any call`, { name: `pathBases.${base === "cwd" && pathBases.cwd === undefined ? "root" : base}` });
|
|
193
226
|
}
|
|
194
227
|
}
|
|
195
228
|
if (issues.length > 0 && issues[issues.length - 1].rule === text && issues[issues.length - 1].code === "unsupported.path_base")
|
|
@@ -199,15 +232,21 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
|
|
|
199
232
|
byTool.set(toolName, entry);
|
|
200
233
|
continue;
|
|
201
234
|
}
|
|
202
|
-
if (face
|
|
235
|
+
if (face !== undefined && colon > 0) {
|
|
203
236
|
const paramPart = content.slice(0, colon).trim();
|
|
204
|
-
|
|
237
|
+
const vocabulary = vocabularyOf(face);
|
|
238
|
+
if (!vocabulary.includes(paramPart)) {
|
|
205
239
|
if (face.nonScalar?.includes(paramPart)) {
|
|
206
240
|
bad(text, "unsupported.param_non_scalar", `"${paramPart}" is a parameter of ${toolName} but its value is an object or an array — the generic matcher compares scalars only; the rule would compile and never match`);
|
|
207
241
|
}
|
|
208
242
|
else {
|
|
209
|
-
|
|
210
|
-
|
|
243
|
+
const statesNothing = face.params === undefined && vocabulary.length === 0;
|
|
244
|
+
bad(text, "unsupported.param_unknown", statesNothing
|
|
245
|
+
? `"${paramPart}" cannot be judged on ${toolName} here (${carriedPhrase(face)}) — write the rule on the whole tool (\`${toolName}\`).`
|
|
246
|
+
: `"${paramPart}" is not a scalar parameter of ${toolName} (${carriedPhrase(face)}${vocabulary.length > 0 ? "; arrays and objects are not rule-readable" : ""}) — the rule would compile and never match. ` +
|
|
247
|
+
(pathTargetOf(toolName) !== undefined
|
|
248
|
+
? `For a path glob use the tool-specific lane (\`${toolName}(src/**)\` is not the generic param DSL); a Windows path such as \`${toolName}(C:/foo)\` parses as the param "C".`
|
|
249
|
+
: `${vocabulary.length > 0 ? "Name one of its parameters, or write" : "Write"} the rule on the whole tool (\`${toolName}\`).`), statesNothing ? { name: "ruleFaces" } : undefined);
|
|
211
250
|
}
|
|
212
251
|
continue;
|
|
213
252
|
}
|
|
@@ -224,14 +263,19 @@ function compile(rules, caps, primaryFieldGeneric, ruleFaces, pathBases = {}) {
|
|
|
224
263
|
continue;
|
|
225
264
|
}
|
|
226
265
|
if (pattern.length > caps.maxPatternLength || countStars(pattern) > caps.maxStars) {
|
|
227
|
-
bad(text, "invalid.cap_exceeded", `pattern
|
|
266
|
+
bad(text, "invalid.cap_exceeded", `a pattern holds at most ${caps.maxPatternLength} characters and ${caps.maxStars} stars`, { name: pattern.length > caps.maxPatternLength ? "caps.maxPatternLength" : "caps.maxStars" });
|
|
228
267
|
continue;
|
|
229
268
|
}
|
|
230
269
|
if (faceOf(toolName).face?.primaryParams.includes(param) === true && primaryFieldGeneric === "reject") {
|
|
231
|
-
|
|
270
|
+
const form = ruleShapeOf({ toolName, args: {} }, verb);
|
|
271
|
+
bad(text, "invalid.primary_field", `"${param}" is ${toolName}'s primary field, and a rule on it matches the WHOLE value lexically — no shell or path semantics — so \`${toolName}(${param}:git push*)\` would NOT match \`cd /x && git push\`. ` +
|
|
272
|
+
`Write the rule ${form === undefined ? "" : `as \`${form}\`, or `}on the whole tool (\`${toolName}\`).`, { name: "primaryFieldGeneric", value: "allow-lexical" });
|
|
232
273
|
continue;
|
|
233
274
|
}
|
|
234
275
|
entry.param[verb].push({ param, pattern, behavior: verb, ruleText: text, source: r.source });
|
|
276
|
+
const valueArm = mountedValueArmOf(text, toolName, verb);
|
|
277
|
+
if (valueArm !== undefined)
|
|
278
|
+
entry.content[verb].push({ parsed: valueArm, ruleText: text, ...(r.source !== undefined ? { source: r.source } : {}) });
|
|
235
279
|
byTool.set(toolName, entry);
|
|
236
280
|
}
|
|
237
281
|
return { byTool, command, namespacedCovering, issues };
|
|
@@ -244,42 +288,10 @@ function isPlainObjectArgs(args) {
|
|
|
244
288
|
return typeof args === "object" && args !== null && !Array.isArray(args);
|
|
245
289
|
}
|
|
246
290
|
function matchParamRules(rules, req, maxScalarValueChars) {
|
|
247
|
-
|
|
248
|
-
if (!isPlainObjectArgs(args))
|
|
249
|
-
return undefined;
|
|
250
|
-
for (const r of rules) {
|
|
251
|
-
if (!Object.hasOwn(args, r.param)) {
|
|
252
|
-
if (readingAbsorbs(req, r.param, r.pattern))
|
|
253
|
-
return r;
|
|
254
|
-
continue;
|
|
255
|
-
}
|
|
256
|
-
const raw = args[r.param];
|
|
257
|
-
if (raw === undefined || raw === null)
|
|
258
|
-
continue;
|
|
259
|
-
const t = typeof raw;
|
|
260
|
-
if (t === "object" || t === "function" || t === "symbol")
|
|
261
|
-
continue;
|
|
262
|
-
const value = String(raw).trim();
|
|
263
|
-
if (value.length > maxScalarValueChars)
|
|
264
|
-
return r;
|
|
265
|
-
if (wildcardMatch(r.pattern, value))
|
|
266
|
-
return r;
|
|
267
|
-
}
|
|
268
|
-
return undefined;
|
|
269
|
-
}
|
|
270
|
-
function readingAbsorbs(req, param, pattern) {
|
|
271
|
-
if (pattern.includes("*"))
|
|
272
|
-
return false;
|
|
273
|
-
try {
|
|
274
|
-
const read = canonicalize(argsAsTheToolReads(req, { ...req.args, [param]: pattern }));
|
|
275
|
-
return read !== UNCANONICALIZABLE && read === canonicalize(req.args);
|
|
276
|
-
}
|
|
277
|
-
catch {
|
|
278
|
-
return false;
|
|
279
|
-
}
|
|
291
|
+
return rules.find((r) => paramRuleReaches(req, r.param, r.pattern, maxScalarValueChars));
|
|
280
292
|
}
|
|
281
|
-
function ruleDenial(req, ruleText, source) {
|
|
282
|
-
return ruleDenialSentence({ source: "permission", tool: req.toolName, rule: ruleText, ...(source ? { origin: source } : {}) });
|
|
293
|
+
function ruleDenial(req, ruleText, source, detail) {
|
|
294
|
+
return ruleDenialSentence({ source: "permission", tool: req.toolName, rule: ruleText, ...(source ? { origin: source } : {}), ...(detail !== undefined ? { detail } : {}) });
|
|
283
295
|
}
|
|
284
296
|
function ruleAskMessage(ruleText, source) {
|
|
285
297
|
return `flagged by permission rule "${ruleText}"${source ? ` (${source})` : ""}`;
|
|
@@ -386,11 +398,33 @@ export function createPermissionRulePolicy(rules, opts) {
|
|
|
386
398
|
const judgeOthers = (lane, req) => {
|
|
387
399
|
const command = isPlainObjectArgs(req.args) ? req.args[commandParam] : undefined;
|
|
388
400
|
let unreadable;
|
|
401
|
+
let host = null;
|
|
389
402
|
for (const r of lane) {
|
|
390
403
|
if (r.parsed.match === "name" || r.parsed.match === "name_prefix") {
|
|
391
404
|
const named = nameRuleSubjectOf(r.parsed.tool, req.args);
|
|
392
|
-
if (named
|
|
405
|
+
if (named === undefined)
|
|
406
|
+
continue;
|
|
407
|
+
const reach = nameRuleReach(r.parsed, named, req.face?.nameValues);
|
|
408
|
+
if (reach === "reached")
|
|
393
409
|
return { rule: r };
|
|
410
|
+
if (reach === "unread")
|
|
411
|
+
unreadable ??= { rule: r, unreadable: nameValuesUnreadReason(r.parsed.tool) };
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
if (r.parsed.match === "host" || r.parsed.match === "subdomain") {
|
|
415
|
+
if (host === null)
|
|
416
|
+
host = callHostTargetOf(req, "tighten");
|
|
417
|
+
if (host === undefined)
|
|
418
|
+
continue;
|
|
419
|
+
if ("host" in host) {
|
|
420
|
+
if (domainRuleAdmits(r.parsed, host.host))
|
|
421
|
+
return { rule: r };
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
const why = `the host the call reaches cannot be read (${HOST_UNREADABLE_SENTENCE[host.unreadable]})`;
|
|
425
|
+
if (r.parsed.behavior === "deny")
|
|
426
|
+
return { rule: r, detail: why };
|
|
427
|
+
unreadable ??= { rule: r, unreadable: why };
|
|
394
428
|
continue;
|
|
395
429
|
}
|
|
396
430
|
if (typeof command !== "string")
|
|
@@ -407,7 +441,7 @@ export function createPermissionRulePolicy(rules, opts) {
|
|
|
407
441
|
for (const r of [...entry.content.deny, ...entry.content.ask]) {
|
|
408
442
|
if (r.parsed.match !== "name" || nameRuleSubjectOf(r.parsed.tool, req.args) !== undefined)
|
|
409
443
|
continue;
|
|
410
|
-
const absent =
|
|
444
|
+
const absent = nameValueAbsentReason(r.parsed.tool);
|
|
411
445
|
if (absent !== undefined)
|
|
412
446
|
return ruleDenialSentence({ source: "permission", tool: req.toolName, rule: r.ruleText, ...(r.source ? { origin: r.source } : {}), detail: absent });
|
|
413
447
|
}
|
|
@@ -454,7 +488,7 @@ export function createPermissionRulePolicy(rules, opts) {
|
|
|
454
488
|
const denyLane = contentLaneOf("deny", entry, shellCall, callFace);
|
|
455
489
|
const contentDeny = denyLane.length > 0 ? contentHit(denyLane, req) : undefined;
|
|
456
490
|
if (contentDeny !== undefined && contentDeny.unreadable === undefined) {
|
|
457
|
-
const denied = { action: "deny", message: ruleDenial(req, contentDeny.rule.ruleText, contentDeny.rule.source) };
|
|
491
|
+
const denied = { action: "deny", message: ruleDenial(req, contentDeny.rule.ruleText, contentDeny.rule.source, contentDeny.detail) };
|
|
458
492
|
const face = contentDeny.view !== undefined ? callPathFaceOf(req) : undefined;
|
|
459
493
|
return face !== undefined ? attest(denied, req, { pathDenial: { rule: contentDeny.rule.ruleText, view: contentDeny.view, face } }) : denied;
|
|
460
494
|
}
|
|
@@ -61,8 +61,10 @@ export declare function disclosedRuleSet(rules: readonly PersistedRuleHitRule[])
|
|
|
61
61
|
* · UNREADABLE STORE — a partition of the store (or all of it) could not be READ (`unreadable` without a `reason`): a deny
|
|
62
62
|
* or ask row inside it may forbid this call and nobody can tell, so it fails CLOSED the same way, to the question
|
|
63
63
|
* only a person answers — an allow becomes an ask carrying `requiresRealApproval`, an ask acquires the bit, a deny stays
|
|
64
|
-
* a deny. Every call
|
|
65
|
-
*
|
|
64
|
+
* a deny. Every call is in this state until a read succeeds again, whatever its tool — rules nobody could read are rules
|
|
65
|
+
* whose tools nobody knows (a newer engine's grammar names rules for tools this one names none for), so the lane hands
|
|
66
|
+
* this form for a call no rule grammar here speaks for too; it announces the skipped store once per run and reads again
|
|
67
|
+
* on the next call. The two forms differ in WHICH fact the gate records (one class for
|
|
66
68
|
* both, `rule_unreadable`, bypass-immune) and in the
|
|
67
69
|
* resumed-call belt, which vetoes only the call form: a person already answered that call's question.
|
|
68
70
|
* An allow hit (or no hit) returns the decision untouched: the allow arm is the station's.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import { delimitUntrusted } from "./untrusted-text.js";
|
|
3
|
-
import { toolFace } from "./tool-catalog-entries.js";
|
|
3
|
+
import { mountRuleFace, toolFace } from "./tool-catalog-entries.js";
|
|
4
4
|
export const PRESENT_PLAN_TOOL_NAME = "ExitPlanMode";
|
|
5
5
|
export const ENTER_PLAN_MODE_TOOL_NAME = "EnterPlanMode";
|
|
6
6
|
const ENTER_PLAN_MODE_DESCRIPTION = `Enter PLAN MODE (read-only): stop making changes and switch to exploration/planning. For the rest of this run, every write/edit/mutating tool call ASKS the user first ("Cannot write to <path> while in plan mode."; where nobody can answer, it is refused) while read-only tools (Read, Grep, Glob, etc.) still work. When your plan is ready, call ${PRESENT_PLAN_TOOL_NAME} with it — the run PAUSES for a human to approve it, then continues (read-only lifted) so you can execute.
|
|
@@ -33,6 +33,7 @@ export function createEnterPlanModeTool(enterPlanMode) {
|
|
|
33
33
|
return {
|
|
34
34
|
name: ENTER_PLAN_MODE_TOOL_NAME,
|
|
35
35
|
...toolFace("enter-plan-mode"),
|
|
36
|
+
ruleFace: mountRuleFace("enter-plan-mode"),
|
|
36
37
|
description: ENTER_PLAN_MODE_DESCRIPTION,
|
|
37
38
|
parameters: Type.Object({}),
|
|
38
39
|
executionMode: "sequential",
|
|
@@ -62,6 +63,7 @@ export function createPresentPlanTool(requestReview) {
|
|
|
62
63
|
return {
|
|
63
64
|
name: PRESENT_PLAN_TOOL_NAME,
|
|
64
65
|
...toolFace("exit-plan-mode"),
|
|
66
|
+
ruleFace: mountRuleFace("exit-plan-mode"),
|
|
65
67
|
description: PRESENT_PLAN_DESCRIPTION,
|
|
66
68
|
parameters: Type.Object({
|
|
67
69
|
plan: Type.String({
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { ProtocolNamespace } from "./protocol-table.js";
|
|
2
2
|
/** The provider's tool-name pattern is `^[a-zA-Z0-9_-]{1,64}$` — the limit applies to the ASSEMBLED name,
|
|
3
|
-
* not to its segments (design/116 W5-5
|
|
3
|
+
* not to its segments (design/116 W5-5). */
|
|
4
4
|
export declare const TOOL_NAME_MAX_CHARS = 64;
|
|
5
5
|
/** Reserved for the tool segment when budgeting the peer segment: a peer kept at the full name budget
|
|
6
6
|
* overflows the assembled name on its own (prefix + 64 + separator = 71 > 64), which is how the tool
|
|
7
7
|
* segment used to be handed a NEGATIVE budget. A tool name shorter than this is not recognizable. */
|
|
8
8
|
export declare const MINTED_TOOL_SEGMENT_MIN_CHARS = 16;
|
|
9
9
|
/**
|
|
10
|
-
* design/116 W5-5
|
|
10
|
+
* design/116 W5-5 — normalize a peer/tool segment to the API tool-name charset by
|
|
11
11
|
* replacing every other character with `_`. CC does exactly this on BOTH segments when composing
|
|
12
12
|
* `mcp__<server>__<tool>` (services/mcp/normalization.ts `normalizeNameForMCP` + mcpStringUtils.ts
|
|
13
13
|
* `buildMcpToolName`), so a peer advertising a dotted/spaced/unicode name can't mint a name the provider
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The READ-ONLY shell tables — the closed data the read-only reader (`read-only-shell.ts`) judges a
|
|
3
|
-
* command against, transcribed from upstream's own tables
|
|
3
|
+
* command against, transcribed from upstream's own tables and kept as DATA so the parity
|
|
4
4
|
* question is answered by diffing two tables, never by reading two programs:
|
|
5
5
|
* - {@link READ_ONLY_COMMAND_TABLE} — the flag-vetted commands: a command (one or more leading words,
|
|
6
6
|
* `git status`, `gh pr view`, `grep`) with the closed set of flags it may carry, each flag's value
|
|
@@ -8,7 +8,7 @@ export type ReadOnlyShellVerdict = {
|
|
|
8
8
|
readonly readOnly: false;
|
|
9
9
|
readonly reason: string;
|
|
10
10
|
};
|
|
11
|
-
/** The reference implementation's question for a compound that changes directory and runs git (
|
|
11
|
+
/** The reference implementation's question for a compound that changes directory and runs git (`cd-git-compound`). */
|
|
12
12
|
export declare const CD_GIT_COMPOUND_SENTENCE = "This command changes directory before running a version-control command, which can pick up untrusted hooks or repository configuration from the target directory. Approve only if you trust it.";
|
|
13
13
|
/**
|
|
14
14
|
* Does this line change directory and run git — a `cd` beside a `git` — other than by ONE plain `cd <path>` that lands
|
package/dist/core/roles.d.ts
CHANGED
|
@@ -3,8 +3,12 @@ import type { Model } from "../internal/llm.js";
|
|
|
3
3
|
import { type ModelRef, type ModelRole, type ModelRoles, type RoleSpec } from "./types.js";
|
|
4
4
|
export type { ModelRole, RoleSpec, ModelRoles } from "./types.js";
|
|
5
5
|
export { MODEL_ROLES } from "./types.js";
|
|
6
|
-
/**
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a ModelRef against the catalog (a Model object passes through). A word the catalog does not hold, and a value that is no model
|
|
8
|
+
* reference, are refused by `config.unknown_role` with `detail { field: seat, reason }` — `seat` names where the caller wrote the word
|
|
9
|
+
* (`"model"` when the caller names none).
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveModel(ref: ModelRef, models?: Record<string, Model>, seat?: string): Model;
|
|
8
12
|
/** 档位降档链(强→弱)。解析某档无绑定时沿链向后找第一个有绑定的档(fail-open 可用性优先;绑定缺口
|
|
9
13
|
* 在部署 catalog 审计面可见)。`ultra` 预留:排在 `max` 前,今天不绑,未来加档零码改。 */
|
|
10
14
|
export declare const DEFAULT_TIER_ORDER: readonly string[];
|