@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
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The advisor seat's two answers, each minted here once and read by every reader: whether the advisor tool attaches for
|
|
3
|
+
* a (main model, advisor model) pair on a deployment ({@link advisorAttachVerdict} — the prepare mount, a host's advisor
|
|
4
|
+
* query and its echo all ask this one function), and whether a conversation has switched the advisor off
|
|
5
|
+
* ({@link advisorHoldOf} — read off the transcript, its only source of truth, at the mount, at every call and by a host).
|
|
6
|
+
* The closed sets the answers are spelled in live beside them.
|
|
7
|
+
*/
|
|
8
|
+
import type { SessionTreeEntry } from "../internal/harness-types.js";
|
|
9
|
+
import { type BrainErrorCode } from "../brain/errors.js";
|
|
10
|
+
import type { AssertAllKeysHandled } from "./ask-origin.js";
|
|
11
|
+
import type { EngineNotice, Model, ModelRef, RunnerDeps } from "./types.js";
|
|
12
|
+
/** The tool's wire name. */
|
|
13
|
+
export declare const ADVISOR_TOOL_NAME = "advisor";
|
|
14
|
+
/** What a fork is told when it inherits the advisor tool with its parent's prefix — the reference's sentence. */
|
|
15
|
+
export declare const ADVISOR_FORK_SENTENCE = "Never consult the advisor tool.";
|
|
16
|
+
/** Why the advisor tool is not attached on a leg whose spec names an advisor model. The first six are the static verdict's
|
|
17
|
+
* answers; the last three are the mount's (the tool selector unmounted it, its route cannot pair, the transcript could
|
|
18
|
+
* not be read). */
|
|
19
|
+
export declare const ADVISOR_NOT_ATTACHED_REASONS: readonly ["disabled", "unknown_model", "advisor_unranked", "weakest_tier", "main_unranked", "pairing", "route_refused", "excluded", "hold_unknown"];
|
|
20
|
+
export type AdvisorNotAttachedReason = (typeof ADVISOR_NOT_ATTACHED_REASONS)[number];
|
|
21
|
+
/**
|
|
22
|
+
* Each reason's sentence to the person (`advisor.not_attached`, once per conversation per pair) — `null` for a reason that
|
|
23
|
+
* tells nobody: the deployment switched the advisor off (it is ignored), the deployment's tool selector unmounted it
|
|
24
|
+
* (`excluded`), or its route cannot pair with the deployment's credentials (`route_refused`, told to the operator by
|
|
25
|
+
* `route.seat_detached` — only an operator can fix it).
|
|
26
|
+
*/
|
|
27
|
+
declare const NOT_ATTACHED_SENTENCE: {
|
|
28
|
+
readonly disabled: null;
|
|
29
|
+
readonly unknown_model: (a: string) => string;
|
|
30
|
+
readonly advisor_unranked: (a: string) => string;
|
|
31
|
+
readonly weakest_tier: (a: string) => string;
|
|
32
|
+
readonly main_unranked: (_a: string, m: string) => string;
|
|
33
|
+
readonly pairing: (a: string, m: string) => string;
|
|
34
|
+
readonly route_refused: null;
|
|
35
|
+
readonly excluded: null;
|
|
36
|
+
readonly hold_unknown: () => string;
|
|
37
|
+
};
|
|
38
|
+
export type NotAttachedSentenceCoversEveryReason = AssertAllKeysHandled<Exclude<AdvisorNotAttachedReason, keyof typeof NOT_ATTACHED_SENTENCE>>;
|
|
39
|
+
/** The shape door of `TaskSpec.advisorModel` (read only while the deployment switch is on): absent, a non-empty ref, or a
|
|
40
|
+
* Model object; anything else refuses (`config.advisor_model_invalid`) — a model the engine cannot read names no advisor. */
|
|
41
|
+
export declare function assertAdvisorModelShape(ref: unknown): void;
|
|
42
|
+
/** The three faces of one advisor call: guidance came back, the advisor model refused, or no guidance could be had. */
|
|
43
|
+
export declare const ADVISOR_OUTCOMES: readonly ["reviewed", "declined", "unavailable"];
|
|
44
|
+
export type AdvisorOutcome = (typeof ADVISOR_OUTCOMES)[number];
|
|
45
|
+
/** The static verdict: the advisor attaches on `model`, or does not and says why. */
|
|
46
|
+
export type AdvisorAttachVerdict = {
|
|
47
|
+
readonly state: "on";
|
|
48
|
+
readonly model: Model;
|
|
49
|
+
} | {
|
|
50
|
+
readonly state: "not_attached";
|
|
51
|
+
readonly reason: Exclude<AdvisorNotAttachedReason, "route_refused" | "excluded" | "hold_unknown">;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Whether the advisor tool attaches for `advisor` beside the run's `main` model, in command order: the deployment switch,
|
|
55
|
+
* then the advisor itself (a model the catalog cannot resolve, one on no declared tier, one on the weakest tier — `lite`,
|
|
56
|
+
* the tier the `haiku` alias names), then the main model (on no declared tier, or on a WEAKER tier than the advisor's:
|
|
57
|
+
* an advisor at least as capable as the main model attaches). Tiers are read by the classifier seat's own reading
|
|
58
|
+
* ({@link tierIndexOf}) over a catalog {@link normalizeSeatDeps} expanded, so a host holding raw deps gets the engine's
|
|
59
|
+
* answer. No tiers declared ⇒ no ranks ⇒ not attached.
|
|
60
|
+
*/
|
|
61
|
+
export declare function advisorAttachVerdict(args: {
|
|
62
|
+
deps: Pick<RunnerDeps, "models" | "tiers" | "advisorTool">;
|
|
63
|
+
main: Model;
|
|
64
|
+
advisor: ModelRef;
|
|
65
|
+
}): AdvisorAttachVerdict;
|
|
66
|
+
/**
|
|
67
|
+
* Which failure of an advisor request switches the advisor off for the conversation: the advisor model's credential refused
|
|
68
|
+
* (`auth`), or a provider 400 / 422 its minter ruled out as an over-window request (`invalid_request` with
|
|
69
|
+
* `inputTooLongRuledOut`) — deterministic client faults that repeat until the conversation is compacted. Every other code,
|
|
70
|
+
* an over-window refusal and an unclassified 400 pass (the next call may succeed). Total over the brain codes by its fence.
|
|
71
|
+
*/
|
|
72
|
+
export declare const ADVISOR_HOLD_CAUSES: Readonly<{
|
|
73
|
+
readonly auth: "hold";
|
|
74
|
+
readonly invalid_request: "hold_unless_window";
|
|
75
|
+
readonly rate_limit: "pass";
|
|
76
|
+
readonly server: "pass";
|
|
77
|
+
readonly network: "pass";
|
|
78
|
+
readonly http: "pass";
|
|
79
|
+
readonly stream_torn: "pass";
|
|
80
|
+
readonly refusal: "pass";
|
|
81
|
+
readonly length_empty: "pass";
|
|
82
|
+
}>;
|
|
83
|
+
/** What one failure's code does to the conversation's advisor ({@link ADVISOR_HOLD_CAUSES}). */
|
|
84
|
+
export type AdvisorHoldDisposition = "hold" | "hold_unless_window" | "pass";
|
|
85
|
+
export type HoldCausesCoverEveryBrainCode = AssertAllKeysHandled<Exclude<BrainErrorCode, keyof typeof ADVISOR_HOLD_CAUSES>>;
|
|
86
|
+
/** What a failed advisor request said about itself — the fields the hold reads and the card carries. */
|
|
87
|
+
export interface AdvisorFailure {
|
|
88
|
+
readonly code?: BrainErrorCode;
|
|
89
|
+
readonly errorKind?: "input_too_long" | "degenerate" | "length_empty";
|
|
90
|
+
readonly inputTooLongRuledOut?: true;
|
|
91
|
+
}
|
|
92
|
+
/** Whether this failure switches the advisor off for the conversation ({@link ADVISOR_HOLD_CAUSES}). */
|
|
93
|
+
export declare function advisorFailureHolds(f: AdvisorFailure): boolean;
|
|
94
|
+
/** The conversation's advisor switch-off, with the cause of the call that switched it. */
|
|
95
|
+
export interface AdvisorHold {
|
|
96
|
+
readonly code?: BrainErrorCode;
|
|
97
|
+
readonly errorKind?: AdvisorFailure["errorKind"];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Whether the conversation on this branch has switched the advisor off, read off the transcript: an advisor tool result
|
|
101
|
+
* recorded after the latest compaction whose card says `hold: true` — the latest such card's cause. A compaction clears it
|
|
102
|
+
* (the card lands before it); a new conversation has none; a fork copies its parent's branch and with it the hold.
|
|
103
|
+
* `undefined` = not held. Members of a recorded card outside their closed sets are not carried.
|
|
104
|
+
*/
|
|
105
|
+
export declare function advisorHoldOf(entries: ReadonlyArray<SessionTreeEntry>): AdvisorHold | undefined;
|
|
106
|
+
/** A not-attached reason the person is told about — its own fact or one they can act on — as a type. */
|
|
107
|
+
export type AdvisorToldReason = {
|
|
108
|
+
[R in AdvisorNotAttachedReason]: (typeof NOT_ATTACHED_SENTENCE)[R] extends null ? never : R;
|
|
109
|
+
}[AdvisorNotAttachedReason];
|
|
110
|
+
/** Whether the person is told about this reason ({@link NOT_ATTACHED_SENTENCE}: the reasons with a sentence). */
|
|
111
|
+
export declare function advisorReasonTold(reason: AdvisorNotAttachedReason): reason is AdvisorToldReason;
|
|
112
|
+
/** The `advisor.not_attached` notice for a reason the person is told about. */
|
|
113
|
+
export declare function advisorNotAttachedNotice(args: {
|
|
114
|
+
reason: AdvisorToldReason;
|
|
115
|
+
advisorModel: string;
|
|
116
|
+
mainModel: string;
|
|
117
|
+
sessionId: string;
|
|
118
|
+
runId?: string;
|
|
119
|
+
}): EngineNotice;
|
|
120
|
+
export {};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { ALL_BRAIN_ERROR_CODES } from "../brain/errors.js";
|
|
2
|
+
import { DEFAULT_TIER_ORDER, resolveModel } from "./roles.js";
|
|
3
|
+
import { normalizeSeatDeps, tierIndexOf } from "./runner/classifier-ladder.js";
|
|
4
|
+
export const ADVISOR_TOOL_NAME = "advisor";
|
|
5
|
+
export const ADVISOR_FORK_SENTENCE = "Never consult the advisor tool.";
|
|
6
|
+
export const ADVISOR_NOT_ATTACHED_REASONS = Object.freeze(["disabled", "unknown_model", "advisor_unranked", "weakest_tier", "main_unranked", "pairing", "route_refused", "excluded", "hold_unknown"]);
|
|
7
|
+
const NOT_ATTACHED_SENTENCE = {
|
|
8
|
+
disabled: null,
|
|
9
|
+
unknown_model: (a) => `The advisor model "${a}" is not in this deployment's model catalog, so the advisor is off.`,
|
|
10
|
+
advisor_unranked: (a) => `"${a}" cannot be used as an advisor: the deployment declares no tier for it (declare RunnerDeps.tiers so the engine knows which model is stronger).`,
|
|
11
|
+
weakest_tier: (a) => `"${a}" cannot be used as an advisor: it is on the weakest tier.`,
|
|
12
|
+
main_unranked: (_a, m) => `The advisor will not activate on the main model (${m}): the deployment declares no tier for it (declare RunnerDeps.tiers). Subagents may still use it.`,
|
|
13
|
+
pairing: (a, m) => `${a} is less capable than the current main model (${m}), so the advisor will not activate. Choose a more capable advisor, or switch to a smaller main model.`,
|
|
14
|
+
route_refused: null,
|
|
15
|
+
excluded: null,
|
|
16
|
+
hold_unknown: () => `The advisor is off for this run: whether this conversation had switched it off could not be read.`,
|
|
17
|
+
};
|
|
18
|
+
export function assertAdvisorModelShape(ref) {
|
|
19
|
+
if (ref === undefined || (typeof ref === "string" ? ref !== "" : typeof ref === "object" && ref !== null && typeof ref.id === "string"))
|
|
20
|
+
return;
|
|
21
|
+
const shown = typeof ref === "string" ? "an empty string" : ref === null ? "null" : Array.isArray(ref) ? "an array" : typeof ref;
|
|
22
|
+
throw Object.assign(new Error(`TaskSpec.advisorModel must be a non-empty model ref or a Model (got ${shown}) — a model the engine cannot read names no advisor.`), { code: "config.advisor_model_invalid" });
|
|
23
|
+
}
|
|
24
|
+
export const ADVISOR_OUTCOMES = Object.freeze(["reviewed", "declined", "unavailable"]);
|
|
25
|
+
export function advisorAttachVerdict(args) {
|
|
26
|
+
if (args.deps.advisorTool === "disabled")
|
|
27
|
+
return { state: "not_attached", reason: "disabled" };
|
|
28
|
+
const deps = normalizeSeatDeps(args.deps);
|
|
29
|
+
let advisor;
|
|
30
|
+
try {
|
|
31
|
+
advisor = resolveModel(args.advisor, deps.models);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return { state: "not_attached", reason: "unknown_model" };
|
|
35
|
+
}
|
|
36
|
+
const advisorTier = tierIndexOf(deps, advisor);
|
|
37
|
+
if (advisorTier === undefined)
|
|
38
|
+
return { state: "not_attached", reason: "advisor_unranked" };
|
|
39
|
+
if (advisorTier === DEFAULT_TIER_ORDER.indexOf("lite"))
|
|
40
|
+
return { state: "not_attached", reason: "weakest_tier" };
|
|
41
|
+
const mainTier = tierIndexOf(deps, args.main);
|
|
42
|
+
if (mainTier === undefined)
|
|
43
|
+
return { state: "not_attached", reason: "main_unranked" };
|
|
44
|
+
if (advisorTier > mainTier)
|
|
45
|
+
return { state: "not_attached", reason: "pairing" };
|
|
46
|
+
return { state: "on", model: advisor };
|
|
47
|
+
}
|
|
48
|
+
export const ADVISOR_HOLD_CAUSES = Object.freeze({
|
|
49
|
+
auth: "hold",
|
|
50
|
+
invalid_request: "hold_unless_window",
|
|
51
|
+
rate_limit: "pass",
|
|
52
|
+
server: "pass",
|
|
53
|
+
network: "pass",
|
|
54
|
+
http: "pass",
|
|
55
|
+
stream_torn: "pass",
|
|
56
|
+
refusal: "pass",
|
|
57
|
+
length_empty: "pass",
|
|
58
|
+
});
|
|
59
|
+
export function advisorFailureHolds(f) {
|
|
60
|
+
if (f.code === undefined)
|
|
61
|
+
return false;
|
|
62
|
+
const row = ADVISOR_HOLD_CAUSES[f.code];
|
|
63
|
+
return row === "hold" || (row === "hold_unless_window" && f.errorKind !== "input_too_long" && f.inputTooLongRuledOut === true);
|
|
64
|
+
}
|
|
65
|
+
const ERROR_KINDS = new Set(["input_too_long", "degenerate", "length_empty"]);
|
|
66
|
+
export function advisorHoldOf(entries) {
|
|
67
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
68
|
+
const e = entries[i];
|
|
69
|
+
if (e.type === "compaction")
|
|
70
|
+
return undefined;
|
|
71
|
+
if (e.type !== "message" || e.message.role !== "toolResult" || e.message.toolName !== ADVISOR_TOOL_NAME)
|
|
72
|
+
continue;
|
|
73
|
+
const d = e.message.details;
|
|
74
|
+
if (d === null || typeof d !== "object" || d.type !== "advisor" || d.hold !== true)
|
|
75
|
+
continue;
|
|
76
|
+
const code = ALL_BRAIN_ERROR_CODES.find((c) => c === d.code);
|
|
77
|
+
const errorKind = typeof d.errorKind === "string" && ERROR_KINDS.has(d.errorKind) ? d.errorKind : undefined;
|
|
78
|
+
return { ...(code !== undefined ? { code } : {}), ...(errorKind !== undefined ? { errorKind } : {}) };
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
export function advisorReasonTold(reason) {
|
|
83
|
+
return NOT_ATTACHED_SENTENCE[reason] !== null;
|
|
84
|
+
}
|
|
85
|
+
export function advisorNotAttachedNotice(args) {
|
|
86
|
+
const sentence = NOT_ATTACHED_SENTENCE[args.reason];
|
|
87
|
+
return {
|
|
88
|
+
code: "advisor.not_attached",
|
|
89
|
+
message: sentence(args.advisorModel, args.mainModel),
|
|
90
|
+
detail: { advisorModel: args.advisorModel, mainModel: args.mainModel, reason: args.reason, sessionId: args.sessionId, ...(args.runId !== undefined ? { runId: args.runId } : {}) },
|
|
91
|
+
};
|
|
92
|
+
}
|
|
@@ -19,8 +19,7 @@ export interface AgentDefinition {
|
|
|
19
19
|
/** Guidance shown to the model for WHEN to pick this agent (listed in the delegation tool's description). */
|
|
20
20
|
whenToUse?: string;
|
|
21
21
|
/**
|
|
22
|
-
* F4 (
|
|
23
|
-
* `(lean && e.whenToUseLean) || e.whenToUse`): a SHORT variant of {@link whenToUse} preferred on
|
|
22
|
+
* F4 (`whenToUseLean`): a SHORT variant of {@link whenToUse} preferred on
|
|
24
23
|
* lean-prompt surfaces. sema posture: the engine runs the CC lean-prompt arm wholesale (web.ts
|
|
25
24
|
* lean-card precedent), so roster listings/descriptions prefer this text whenever present;
|
|
26
25
|
* {@link whenToUse} remains the fallback. Optional — a single-text agent behaves exactly as before.
|
|
@@ -36,7 +35,7 @@ export interface AgentDefinition {
|
|
|
36
35
|
/** Tool denylist (a deny always wins), tool NAMES: `Tool(content)` hides the whole `Tool`. See {@link allowTools} for the per-agent delegation-tool note. */
|
|
37
36
|
denyTools?: string[];
|
|
38
37
|
/**
|
|
39
|
-
* F7 (
|
|
38
|
+
* F7 (per-agent `skills`:
|
|
40
39
|
* CC preloads each named skill's prompt content into the child's opening messages, warning on misses).
|
|
41
40
|
* sema shape: full {@link SkillSpec} objects (sema has no ambient skill registry to resolve bare names
|
|
42
41
|
* against) threaded into the chosen child's `TaskSpec.skills` — disclosed in its `<skills>` block +
|
|
@@ -44,7 +43,7 @@ export interface AgentDefinition {
|
|
|
44
43
|
*/
|
|
45
44
|
skills?: SkillSpec[];
|
|
46
45
|
/**
|
|
47
|
-
* F7 (
|
|
46
|
+
* F7 (per-agent `background`, OR-ed into
|
|
48
47
|
* the background predicate, GA/ungated): `true` = this agent ALWAYS launches on the background lane
|
|
49
48
|
* (an omitted `run_in_background` no longer means sync, and the per-call parameter cannot force sync —
|
|
50
49
|
* CC-same OR semantics). Requires the delegation tool's `background` surface; without one the child
|
|
@@ -52,7 +51,7 @@ export interface AgentDefinition {
|
|
|
52
51
|
*/
|
|
53
52
|
background?: boolean;
|
|
54
53
|
/**
|
|
55
|
-
* F7 (
|
|
54
|
+
* F7 (per-agent `isolation`):
|
|
56
55
|
* default isolation for this agent; an explicit per-call `isolation` argument wins. sema supports
|
|
57
56
|
* `"worktree"` (CC's `"remote"` arm is a claude.ai-session concern, not ported).
|
|
58
57
|
*/
|
|
@@ -86,8 +85,8 @@ export interface AgentDefinition {
|
|
|
86
85
|
*/
|
|
87
86
|
memoryPersistenceCapable?: boolean;
|
|
88
87
|
/**
|
|
89
|
-
* Observer agents (
|
|
90
|
-
* 面 C
|
|
88
|
+
* Observer agents (schema
|
|
89
|
+
* 面 C): "Agent type auto-spawned as a background observer whenever this agent runs.
|
|
91
90
|
* The observer receives read-only activity digests and reports via the ObserverReport tool; it
|
|
92
91
|
* never participates in the task." Resolution is warn-and-unobserved on an unknown type and
|
|
93
92
|
* refuses chaining (an observer's own `observer` declaration is ignored). Gated by
|
|
@@ -116,7 +115,7 @@ export interface SkillSpec {
|
|
|
116
115
|
* either list asks once (`Execute skill: <name>`, the card listing what it releases); a skill the person invoked by
|
|
117
116
|
* name ({@link import("./task-spec.js").TaskSpec.userInvokedSkills}) grants without asking. The grant holds for that
|
|
118
117
|
* run (a steer it takes in does not end it) and the next runTask starts without it. An entry this grammar reads as nothing — `*` (it voids an allow list; on a deny list it is inert and the rest of the
|
|
119
|
-
* list still refuses), `mcp__
|
|
118
|
+
* list still refuses), `mcp__*` / `mcp__*__*` (an allow entry names a peer), a write path, a domain — grants nothing and is announced at the start of the run (`permission.allowed_tool_not_granted`). A table whose value is not a list (a string, an object…) reads as one such entry; `null` is no table.
|
|
120
119
|
*/
|
|
121
120
|
allowedTools?: string[];
|
|
122
121
|
/** The tools refused for the rest of the run this skill is activated in — the frontmatter `disallowed-tools` list,
|
|
@@ -126,7 +126,7 @@ export declare function compileAllowList(entries: readonly string[], behavior: "
|
|
|
126
126
|
inert: AllowEntryInert[];
|
|
127
127
|
};
|
|
128
128
|
/** The programs whose open allow rule the reference implementation drops in auto mode — its interpreter / launcher table
|
|
129
|
-
* plus the shells and the run-anything builtins
|
|
129
|
+
* plus the shells and the run-anything builtins. A program that only reaches the network is not here. */
|
|
130
130
|
export declare const AUTO_STRIPPED_PROGRAMS: readonly ["python", "python3", "python2", "node", "deno", "tsx", "ruby", "perl", "php", "lua", "npx", "bunx", "npm run", "yarn run", "pnpm run", "bun run", "bash", "sh", "ssh", "zsh", "fish", "eval", "exec", "env", "xargs", "sudo"];
|
|
131
131
|
/**
|
|
132
132
|
* Does auto mode strip this allow entry for this call (see the module doc)? Read for every rule-shaped member — a list
|
|
@@ -163,17 +163,23 @@ export declare function uncoveredCommandSegment(rows: readonly AllowEntryRow[],
|
|
|
163
163
|
* segment covered by a row — or, for a `grant` list, read-only by itself); deny: a row whose program run the call performs (the
|
|
164
164
|
* wide tightening reading; a call that cannot be read against the row is refused too). PATH — the persisted path adjudication
|
|
165
165
|
* (allow: the narrow reading, every view of the target inside what the row names; deny: any view reaching it). NAME / DOMAIN —
|
|
166
|
-
* the one predicate of each (the name the call names, the host it
|
|
167
|
-
*
|
|
166
|
+
* the one predicate of each (the name the call names, the host it reaches — a deny row read on the protective reading, an allow
|
|
167
|
+
* row on the tool's own declared slot, `callHostTargetOf`; a mounted name tool's value resolved against the agent types the call's
|
|
168
|
+
* face carries, `nameRuleReach`); a closed-set tool's call naming no value is refused by a deny list's row of the tool and granted
|
|
169
|
+
* by no allow row (the persisted walk's reading, `nameValueAbsentReason`), a mounted tool's call whose face carries no values is
|
|
170
|
+
* refused by a deny list's row of the tool and granted by no allow row, and a call whose host cannot be read is refused by a deny
|
|
171
|
+
* list's host row and granted by no allow row (`adjudicatePersistedDomainRules`).
|
|
168
172
|
*/
|
|
169
173
|
export declare function judgeAllowEntries<R extends AllowEntryRow>(rows: readonly R[], req: ToolCallRequest, behavior: "allow" | "deny", ctx: AllowEntryJudgeContext, posture?: AdmissionPosture): readonly R[] | undefined;
|
|
170
174
|
/** The allow rows of a list, as the allow layer reads them in `mode`: the strip applied BEFORE the match (in `auto`). */
|
|
171
175
|
export declare function allowingRows<R extends AllowEntryRow>(rows: readonly R[], req: ToolCallRequest, mode: PermissionMode | undefined): readonly R[];
|
|
172
176
|
/** The two sources {@link AllowEntryTable} holds (a skill's list is the skill table's). */
|
|
173
177
|
export type AllowEntrySource = "request" | "deployment";
|
|
174
|
-
/** What spoke for a call: the entries it stands on, as the list spells them
|
|
178
|
+
/** What spoke for a call: the entries it stands on, as the list spells them, and — for entries of the list the run received —
|
|
179
|
+
* the index of every element of that list that is one of them (a string listed twice has both). */
|
|
175
180
|
export interface AllowEntryHit {
|
|
176
181
|
readonly entries: readonly string[];
|
|
182
|
+
readonly positions?: readonly number[];
|
|
177
183
|
}
|
|
178
184
|
/** The face the gate reads one entry list through. */
|
|
179
185
|
export interface AllowEntryLane {
|
|
@@ -208,9 +214,16 @@ export interface AllowEntryGateSeats {
|
|
|
208
214
|
export declare class AllowEntryTable {
|
|
209
215
|
private held;
|
|
210
216
|
private readonly heldEntries;
|
|
217
|
+
/** Each entry of the list the run RECEIVED for this source, with its indices in that list — what a hit's `positions` read. */
|
|
218
|
+
private receivedAt;
|
|
211
219
|
/** Write a list's rows (a row already held is not held twice). Returns the entries that read as nothing. `roster` as in
|
|
212
|
-
* {@link readRuleEntry}: a list the leg itself wrote is read against it, a carried one (a delegating parent's capture) is not.
|
|
213
|
-
|
|
220
|
+
* {@link readRuleEntry}: a list the leg itself wrote is read against it, a carried one (a delegating parent's capture) is not.
|
|
221
|
+
* `received`: this list is the one the run received for the source (the request's `TaskSpec.allowedTools`, the deployment's
|
|
222
|
+
* `RunnerDeps.allowedTools`), the list a hit's positions are read in; a carried capture is not. */
|
|
223
|
+
seed(entries: readonly string[], reading?: {
|
|
224
|
+
readonly roster?: ReadonlySet<string>;
|
|
225
|
+
readonly received?: true;
|
|
226
|
+
}): readonly AllowEntryInert[];
|
|
214
227
|
/** The entries held, as written (a copy) — what a delegated child is handed. */
|
|
215
228
|
entries(): readonly string[];
|
|
216
229
|
/** Does the table hold a path row — must the leg read each call's target views for it? */
|
|
@@ -245,21 +258,32 @@ export declare function withDeploymentAllowedTools<D extends {
|
|
|
245
258
|
}>(deps: D): D;
|
|
246
259
|
/** The code a list value that is not a list of strings refuses with — the policy compiler's family, with its issues. */
|
|
247
260
|
export declare const INVALID_PERMISSION_RULES_CODE = "config.invalid_permission_rules";
|
|
261
|
+
/** The two seats an allow list is handed over at — the library coordinates the refusal carries as `libraryOption`, each with the
|
|
262
|
+
* words the sentence says instead. */
|
|
263
|
+
declare const ALLOW_LIST_SEATS: {
|
|
264
|
+
readonly "TaskSpec.allowedTools": "the request's allow list";
|
|
265
|
+
readonly "RunnerDeps.allowedTools": "the deployment's allow list";
|
|
266
|
+
};
|
|
267
|
+
type AllowedToolsSeat = keyof typeof ALLOW_LIST_SEATS;
|
|
248
268
|
/**
|
|
249
|
-
* Screen and snapshot one `allowedTools` value (`seat`
|
|
250
|
-
* ⇒ a frozen copy (the one read every later reader takes);
|
|
251
|
-
* {@link INVALID_PERMISSION_RULES_CODE} and an issue per defect — never dropped, never read
|
|
269
|
+
* Screen and snapshot one `allowedTools` value (`seat` is the seat it was handed at; the sentence says it in words, the issues'
|
|
270
|
+
* `libraryOption` names it): absent ⇒ undefined; a list of strings ⇒ a frozen copy (the one read every later reader takes);
|
|
271
|
+
* anything else refuses loudly with {@link INVALID_PERMISSION_RULES_CODE} and an issue per defect — never dropped, never read
|
|
272
|
+
* as "no entries".
|
|
252
273
|
*/
|
|
253
|
-
export declare function screenAllowedToolsValue(value: unknown, seat:
|
|
274
|
+
export declare function screenAllowedToolsValue(value: unknown, seat: AllowedToolsSeat): readonly string[] | undefined;
|
|
254
275
|
/** The disclosure record for one member, minted from the entries it matched: each sanitized (deployment or model-authored
|
|
255
276
|
* text on a human trust boundary) and capped, the rest counted. */
|
|
256
277
|
export declare function allowRuleShadowOf(member: AllowRuleMember, entries: readonly string[]): AllowRuleShadow;
|
|
257
278
|
/** Read a disclosure value off a decision WITHOUT trusting it (a policy's own value, an ancestor's): every record a known
|
|
258
279
|
* member with a list of strings, or nothing — a display member must never throw where a card is minted. */
|
|
259
280
|
export declare function readAllowRuleShadows(value: unknown): readonly AllowRuleShadow[] | undefined;
|
|
260
|
-
/**
|
|
261
|
-
*
|
|
262
|
-
|
|
281
|
+
/** The ask class whose reason is not a row: `probe` is the class of a FINDING about this very call (the read station's, or a
|
|
282
|
+
* probe's), and only the ask's own account of it — its `probeReason` — can say which ({@link allowRuleShadowSentence}). */
|
|
283
|
+
export type AccountedClass = "probe";
|
|
284
|
+
/** Why a matched entry did not clear the ask, by the ask's class — one row per class that has a reason of its own, so a class
|
|
285
|
+
* added later is a compile error here rather than somebody else's reason on the card. Two facts the ask carries are read first,
|
|
286
|
+
* because they name the reason more exactly than a class shared by several: a table word (`mandate` — the exact mark) and the
|
|
263
287
|
* deployment's own authorship (`authoredBy`) — {@link allowRuleShadowSentence} is the reader that applies that order.
|
|
264
288
|
* Exported (frozen) so a host that renders the card's "why it cannot be cleared" half reads the engine's row, never a copy. */
|
|
265
289
|
export declare const SHADOW_REASON: Readonly<{
|
|
@@ -272,26 +296,25 @@ export declare const SHADOW_REASON: Readonly<{
|
|
|
272
296
|
readonly transcript_write: "this write targets the session transcript — it is cleared by confirming this call, never by an allow rule";
|
|
273
297
|
readonly org_rule: "an organization policy rule requires approval for this call";
|
|
274
298
|
readonly rule_unreadable: "a rule that may govern this call cannot currently be read (this deployment's organization policy, a partition of the person's standing rules, or this call against a deny or ask rule), so whether one forbids it is unknown";
|
|
275
|
-
readonly ask_rule:
|
|
299
|
+
readonly ask_rule: "an explicit ask rule matched this call (a person's or the deployment's ask-me-each-time outranks a standing allow rule)";
|
|
276
300
|
readonly denial_limit_fallback: "the auto-mode classifier refused too many calls in a row, so a person decides";
|
|
277
301
|
readonly classifier_no_ruling: "the auto-mode classifier could not judge this call, so a person decides";
|
|
278
302
|
readonly requires_user_interaction: "this tool's server declares that a call must be put to a person";
|
|
279
|
-
readonly cross_boundary:
|
|
303
|
+
readonly cross_boundary: "this run executes on a device outside the deployment's trust boundary and the deployment is multi-tenant, so an org-side write — or, after an off-target read, a call bound for the device — is confirmed by the deployment's approver for this call: no standing allow rule and no automatic lane answers for it, and an allow the configuration gives (a blanket seat or a policy's answer) is refused";
|
|
280
304
|
readonly operator_forced: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule";
|
|
281
|
-
readonly shell_floor:
|
|
282
|
-
readonly target_unresolved:
|
|
283
|
-
readonly
|
|
284
|
-
readonly
|
|
285
|
-
readonly
|
|
286
|
-
readonly tool_marks_a2a: string;
|
|
305
|
+
readonly shell_floor: "this deployment mandates per-call confirmation for shell commands (shellGate: always)";
|
|
306
|
+
readonly target_unresolved: "where this write leads on disk could not be determined (a link on the way could not be examined, or the environment could not resolve the target), so whether it lands on a guarded path is unknown — it is cleared by confirming this call: no standing rule and no automatic decider answers for it, though a wired approver seat can";
|
|
307
|
+
readonly write_protection: "this write's target is on the deployment's write-protection table (the agent's own configuration is guarded one look per write) — it is cleared by confirming this call, never by a standing allow rule";
|
|
308
|
+
readonly tool_marks_mcp: "this tool carries egress/irreversibility/interaction marks (a mandated confirmation a rule cannot clear)";
|
|
309
|
+
readonly tool_marks_a2a: "this tool carries egress/irreversibility/interaction marks (a mandated confirmation a rule cannot clear)";
|
|
287
310
|
readonly policy_rra: "the deployment's policy requires a real approval for this call";
|
|
288
311
|
readonly artifact_shared_read: "this read targets another task's shared artifact — it is cleared by confirming this call";
|
|
289
312
|
readonly mode: "the permission mode puts this question to a person";
|
|
290
313
|
readonly unstated: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule";
|
|
291
314
|
readonly ordinary: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule";
|
|
292
315
|
}>;
|
|
293
|
-
/** The fence over the reason table: `never` while every class has a row. */
|
|
294
|
-
export type ShadowReasonTableCoversEveryClass = AssertAllKeysHandled<Exclude<AskClass, keyof typeof SHADOW_REASON>>;
|
|
316
|
+
/** The fence over the reason table: `never` while every class that has a reason of its own has a row. */
|
|
317
|
+
export type ShadowReasonTableCoversEveryClass = AssertAllKeysHandled<Exclude<AskClass, keyof typeof SHADOW_REASON | AccountedClass>>;
|
|
295
318
|
/**
|
|
296
319
|
* The disclosure in the sentence a PERSON reads — rendered where a card or a park row is minted, never onto the decision
|
|
297
320
|
* the classifier reads: "<members> match(es) this call but do(es) not clear the ask — <why>".
|
|
@@ -300,6 +323,7 @@ export declare function allowRuleShadowSentence(shadows: readonly AllowRuleShado
|
|
|
300
323
|
askClass?: AskClass;
|
|
301
324
|
mandate?: PersistedRuleMandate;
|
|
302
325
|
authoredBy?: "deployment";
|
|
326
|
+
probeReason?: string;
|
|
303
327
|
}): string;
|
|
304
328
|
/** The card's two disclosure members off a surviving ask, minted at every station that builds an approval request: the
|
|
305
329
|
* sanitized records, and the message with the sentence rendered onto it. */
|
|
@@ -309,6 +333,7 @@ export declare function cardDisclosureOf(decision: {
|
|
|
309
333
|
askClass?: AskClass;
|
|
310
334
|
mandate?: PersistedRuleMandate;
|
|
311
335
|
authoredBy?: "deployment";
|
|
336
|
+
probeReason?: string;
|
|
312
337
|
}, fallbackMessage: string): {
|
|
313
338
|
message: string;
|
|
314
339
|
allowRuleShadowed?: readonly AllowRuleShadow[];
|
|
@@ -348,3 +373,4 @@ export declare function inertEntryPhrase(e: AllowEntryInert): string;
|
|
|
348
373
|
* `disallowed-tools` holds such an entry is named as one that does not activate.
|
|
349
374
|
*/
|
|
350
375
|
export declare function allowedToolsNotGrantedNotice(inert: readonly AllowEntryInertNote[], sessionId: string | undefined): EngineNotice;
|
|
376
|
+
export {};
|
package/dist/core/allow-entry.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { heldBy } from "./tool-name-readings.js";
|
|
2
|
-
import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "./permission-rules.js";
|
|
2
|
+
import { isNamespacedCoveringRuleName, namespacedRuleNameCovers, ruleIssue } from "./permission-rules.js";
|
|
3
3
|
import { parsePermissionRule, ruleSpellingOf } from "./permission-rule-syntax.js";
|
|
4
4
|
import { judgeRuleToolName, splitNamespacedName } from "./tool-name-aliases.js";
|
|
5
5
|
import { catalogToolNames, isShellFaceToolName } from "./tool-registry.js";
|
|
6
6
|
import { ALLOW_RULE_MEMBERS } from "./allow-rule-shadow.js";
|
|
7
|
-
import {
|
|
7
|
+
import { callHostTargetOf } from "./host-target.js";
|
|
8
|
+
import { COMMAND_RULE_TOOL, adjudicatePersistedDomainRules, adjudicatePersistedNameRules, commandCoverageOf, laneToolNamesOf, ruleContentOf, noticeRuleText, parseRuleText, programRunReachOf, ruleToolGrammarOf, commandPatternMayRun } from "./permission-rule-model.js";
|
|
8
9
|
import { pathRuleLaneAnswer } from "./runner/permission-rule-lanes.js";
|
|
9
10
|
import { callTargetReadingOf } from "./effective-path-target.js";
|
|
10
11
|
import { splitShellCompoundSegments } from "../tools/fs/bash-readonly-classifier.js";
|
|
11
|
-
import { mandateDisclosureOf } from "./ask-origin.js";
|
|
12
|
-
import { inlineUntrusted } from "./untrusted-text.js";
|
|
12
|
+
import { ASK_RULE_DISCLOSURE, MANDATE_DISCLOSURE, mandateDisclosureOf } from "./ask-origin.js";
|
|
13
|
+
import { inlineUntrusted, isMintableProbeReason } from "./untrusted-text.js";
|
|
13
14
|
import { valueTypeLabel } from "./tool-name-list.js";
|
|
14
15
|
import { deliverEngineNotice } from "./engine-notice.js";
|
|
15
16
|
export const ALLOW_ENTRY_INERT_REASONS = Object.freeze(["wildcard_all", "namespace_wildcard", "content_unsupported", "grammar", "tool_name", "near_miss", "earlier_grammar"]);
|
|
@@ -38,8 +39,8 @@ export function nearMissSpellingOf(name, roster) {
|
|
|
38
39
|
export function rootFacingToolNames(carried) {
|
|
39
40
|
return new Set([...catalogToolNames(), ...carried]);
|
|
40
41
|
}
|
|
41
|
-
function toolNameReading(name, roster) {
|
|
42
|
-
const verdict = judgeRuleToolName(name, roster);
|
|
42
|
+
function toolNameReading(name, roster, behavior) {
|
|
43
|
+
const verdict = judgeRuleToolName(name, roster, behavior);
|
|
43
44
|
if (verdict.kind === "unprefixed_namespace")
|
|
44
45
|
return { kind: "inert", reason: "tool_name", verdict: verdict.kind };
|
|
45
46
|
if (verdict.kind !== "current") {
|
|
@@ -60,15 +61,15 @@ export function readRuleEntry(raw, behavior, roster) {
|
|
|
60
61
|
if (name === "*")
|
|
61
62
|
return inert("wildcard_all");
|
|
62
63
|
if (roster !== undefined) {
|
|
63
|
-
const stale = toolNameReading(name, roster);
|
|
64
|
+
const stale = toolNameReading(name, roster, behavior);
|
|
64
65
|
if (stale !== undefined)
|
|
65
66
|
return stale;
|
|
66
67
|
}
|
|
67
|
-
if (parsed
|
|
68
|
+
if (ruleContentOf(parsed) === undefined) {
|
|
68
69
|
const split = splitNamespacedName(name);
|
|
69
70
|
if (split !== undefined) {
|
|
70
71
|
if (split.peer.includes("*"))
|
|
71
|
-
return inert("namespace_wildcard");
|
|
72
|
+
return isNamespacedCoveringRuleName(name, behavior) ? row({ kind: "namespace", pattern: name }) : inert("namespace_wildcard");
|
|
72
73
|
if (isNamespacedCoveringRuleName(name))
|
|
73
74
|
return row({ kind: "namespace", pattern: name });
|
|
74
75
|
return row({ kind: "tool", name });
|
|
@@ -158,7 +159,7 @@ export function autoStripped(compiled, call) {
|
|
|
158
159
|
case "tool":
|
|
159
160
|
return call !== undefined && answersTo(call, isShellFaceToolName);
|
|
160
161
|
case "command":
|
|
161
|
-
return shellContentStripped(shellRuleContent(compiled.rule));
|
|
162
|
+
return compiled.rule.match === "pattern" ? commandPatternMayRun(compiled.rule.command, AUTO_STRIPPED_PROGRAMS) : shellContentStripped(shellRuleContent(compiled.rule));
|
|
162
163
|
case "namespace":
|
|
163
164
|
case "path":
|
|
164
165
|
case "name":
|
|
@@ -240,7 +241,8 @@ export function judgeAllowEntries(rows, req, behavior, ctx, posture = "grant") {
|
|
|
240
241
|
const table = familyRows.map((r) => r.compiled.rule);
|
|
241
242
|
for (const name of laneToolNamesOf(req).filter((n) => ruleToolGrammarOf(n) === grammar)) {
|
|
242
243
|
const at = { tool: name, cwd: ctx.root, ...(ctx.sessionId !== undefined ? { sessionId: ctx.sessionId } : {}) };
|
|
243
|
-
const
|
|
244
|
+
const named = { ...req, toolName: name };
|
|
245
|
+
const verdict = grammar === "name" ? adjudicatePersistedNameRules(table, { ...at, request: req }) : adjudicatePersistedDomainRules(table, { ...at, hosts: { tighten: callHostTargetOf(named, "tighten"), grant: callHostTargetOf(named, "grant") } });
|
|
244
246
|
if (verdict !== undefined && verdict.behavior === behavior)
|
|
245
247
|
return [familyRows.find((r) => r.compiled.rule === verdict.rules[0]) ?? familyRows[0]];
|
|
246
248
|
}
|
|
@@ -253,8 +255,19 @@ export function allowingRows(rows, req, mode) {
|
|
|
253
255
|
export class AllowEntryTable {
|
|
254
256
|
held = [];
|
|
255
257
|
heldEntries = new Set();
|
|
256
|
-
|
|
257
|
-
|
|
258
|
+
receivedAt = new Map();
|
|
259
|
+
seed(entries, reading = {}) {
|
|
260
|
+
const { rows, inert } = compileAllowList(entries, "allow", reading.roster);
|
|
261
|
+
if (reading.received === true) {
|
|
262
|
+
this.receivedAt = new Map();
|
|
263
|
+
entries.forEach((e, i) => {
|
|
264
|
+
const at = this.receivedAt.get(e);
|
|
265
|
+
if (at === undefined)
|
|
266
|
+
this.receivedAt.set(e, [i]);
|
|
267
|
+
else
|
|
268
|
+
at.push(i);
|
|
269
|
+
});
|
|
270
|
+
}
|
|
258
271
|
for (const r of rows) {
|
|
259
272
|
if (this.heldEntries.has(r.entry))
|
|
260
273
|
continue;
|
|
@@ -273,15 +286,19 @@ export class AllowEntryTable {
|
|
|
273
286
|
return {
|
|
274
287
|
allowing: (req, mode) => {
|
|
275
288
|
const hit = judgeAllowEntries(allowingRows(this.held, req, mode), req, "allow", ctx);
|
|
276
|
-
|
|
289
|
+
if (hit === undefined)
|
|
290
|
+
return undefined;
|
|
291
|
+
const entries = hit.map((r) => r.entry);
|
|
292
|
+
const positions = entries.flatMap((e) => this.receivedAt.get(e) ?? []).sort((a, b) => a - b);
|
|
293
|
+
return { entries, ...(positions.length > 0 ? { positions } : {}) };
|
|
277
294
|
},
|
|
278
295
|
};
|
|
279
296
|
}
|
|
280
297
|
}
|
|
281
298
|
export function seedAllowEntryTables(tables, lists, roster) {
|
|
282
299
|
tables.request.seed(lists.inherited ?? []);
|
|
283
|
-
const requestInert = tables.request.seed(lists.request ?? [], roster);
|
|
284
|
-
const deploymentInert = tables.deployment.seed(lists.deployment ?? [], roster).filter((e) => e.reason === "tool_name" || e.reason === "near_miss");
|
|
300
|
+
const requestInert = tables.request.seed(lists.request ?? [], { roster, received: true });
|
|
301
|
+
const deploymentInert = tables.deployment.seed(lists.deployment ?? [], { roster, received: true }).filter((e) => e.reason === "tool_name" || e.reason === "near_miss");
|
|
285
302
|
return [
|
|
286
303
|
...lists.skillInert.map((e) => ({ source: "skill", ...e })),
|
|
287
304
|
...requestInert.map((e) => ({ source: "request", ...e })),
|
|
@@ -298,22 +315,27 @@ export function withDeploymentAllowedTools(deps) {
|
|
|
298
315
|
return { ...deps, allowedTools };
|
|
299
316
|
}
|
|
300
317
|
export const INVALID_PERMISSION_RULES_CODE = "config.invalid_permission_rules";
|
|
318
|
+
const ALLOW_LIST_SEATS = {
|
|
319
|
+
"TaskSpec.allowedTools": "the request's allow list",
|
|
320
|
+
"RunnerDeps.allowedTools": "the deployment's allow list",
|
|
321
|
+
};
|
|
301
322
|
export function screenAllowedToolsValue(value, seat) {
|
|
302
323
|
if (value === undefined)
|
|
303
324
|
return undefined;
|
|
325
|
+
const label = ALLOW_LIST_SEATS[seat];
|
|
304
326
|
const issues = [];
|
|
305
327
|
if (!Array.isArray(value)) {
|
|
306
|
-
issues.push(
|
|
328
|
+
issues.push(ruleIssue("", "invalid.entry_type", `${label} must be a list of permission-rule strings (got ${value === null ? "null" : typeof value})`, { name: seat }));
|
|
307
329
|
}
|
|
308
330
|
else {
|
|
309
331
|
const list = value;
|
|
310
332
|
list.forEach((entry, i) => {
|
|
311
333
|
if (typeof entry !== "string")
|
|
312
|
-
issues.push(
|
|
334
|
+
issues.push(ruleIssue("", "invalid.entry_type", `entry ${i} of ${label} must be a permission-rule string (got ${entry === null ? "null" : typeof entry})`, { name: seat }));
|
|
313
335
|
});
|
|
314
336
|
}
|
|
315
337
|
if (issues.length > 0) {
|
|
316
|
-
const e = new Error(`${
|
|
338
|
+
const e = new Error(`${label}: ${issues.length} invalid entr${issues.length === 1 ? "y" : "ies"} — refusing rather than running without them:\n${issues.map((i) => ` [${i.code}] ${i.message}`).join("\n")}`);
|
|
317
339
|
e.code = INVALID_PERMISSION_RULES_CODE;
|
|
318
340
|
e.issues = issues;
|
|
319
341
|
throw e;
|
|
@@ -359,18 +381,17 @@ export const SHADOW_REASON = Object.freeze({
|
|
|
359
381
|
transcript_write: "this write targets the session transcript — it is cleared by confirming this call, never by an allow rule",
|
|
360
382
|
org_rule: "an organization policy rule requires approval for this call",
|
|
361
383
|
rule_unreadable: "a rule that may govern this call cannot currently be read (this deployment's organization policy, a partition of the person's standing rules, or this call against a deny or ask rule), so whether one forbids it is unknown",
|
|
362
|
-
ask_rule:
|
|
384
|
+
ask_rule: ASK_RULE_DISCLOSURE,
|
|
363
385
|
denial_limit_fallback: "the auto-mode classifier refused too many calls in a row, so a person decides",
|
|
364
386
|
classifier_no_ruling: "the auto-mode classifier could not judge this call, so a person decides",
|
|
365
387
|
requires_user_interaction: "this tool's server declares that a call must be put to a person",
|
|
366
|
-
cross_boundary:
|
|
388
|
+
cross_boundary: MANDATE_DISCLOSURE.cross_boundary_taint,
|
|
367
389
|
operator_forced: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule",
|
|
368
|
-
shell_floor:
|
|
369
|
-
target_unresolved:
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
tool_marks_a2a: mandateDisclosureOf("tool_marks"),
|
|
390
|
+
shell_floor: MANDATE_DISCLOSURE.operator_always,
|
|
391
|
+
target_unresolved: MANDATE_DISCLOSURE.target_unresolved,
|
|
392
|
+
write_protection: MANDATE_DISCLOSURE.write_protection,
|
|
393
|
+
tool_marks_mcp: MANDATE_DISCLOSURE.tool_marks,
|
|
394
|
+
tool_marks_a2a: MANDATE_DISCLOSURE.tool_marks,
|
|
374
395
|
policy_rra: "the deployment's policy requires a real approval for this call",
|
|
375
396
|
artifact_shared_read: "this read targets another task's shared artifact — it is cleared by confirming this call",
|
|
376
397
|
mode: "the permission mode puts this question to a person",
|
|
@@ -398,12 +419,16 @@ function memberPhrase(s) {
|
|
|
398
419
|
}
|
|
399
420
|
export function allowRuleShadowSentence(shadows, ask) {
|
|
400
421
|
const one = shadows.length === 1 && (shadows[0].member === "hook" || shadows[0].entries.length + (shadows[0].omitted ?? 0) === 1);
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
|
|
422
|
+
const { askClass, mandate, authoredBy, probeReason } = ask;
|
|
423
|
+
const account = typeof probeReason === "string" && probeReason.trim().length > 0 && isMintableProbeReason(probeReason) ? probeReason : undefined;
|
|
424
|
+
const why = mandate !== undefined
|
|
425
|
+
? mandateDisclosureOf(mandate, account)
|
|
426
|
+
: authoredBy === "deployment"
|
|
404
427
|
? "this deployment requires a person's confirmation for this call"
|
|
405
|
-
:
|
|
406
|
-
|
|
428
|
+
: askClass === "probe"
|
|
429
|
+
? account
|
|
430
|
+
: SHADOW_REASON[askClass ?? "ordinary"];
|
|
431
|
+
return `${shadows.map(memberPhrase).join("; ")} ${one ? "matches this call but does not clear the ask" : "match this call but do not clear the ask"}${why !== undefined ? ` — ${why}` : ""}`;
|
|
407
432
|
}
|
|
408
433
|
export function cardDisclosureOf(decision, fallbackMessage) {
|
|
409
434
|
const base = decision.message ?? fallbackMessage;
|