@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,6 +1,7 @@
|
|
|
1
1
|
import { sliceHeadSafe, sliceTailSafe } from "../../core/surrogate-safe-slice.js";
|
|
2
2
|
import { isAbsoluteForFamily, normalizeAbsPathLexically, pathFamilyOf, pathIdentityOf, spellingOfIdentity } from "./safety.js";
|
|
3
3
|
import { PROBE_REASON_MAX } from "../../core/untrusted-text.js";
|
|
4
|
+
import { wildcardMatch } from "../../core/namespaced-rule-name.js";
|
|
4
5
|
import { validatePath } from "../../core/effective-path-target.js";
|
|
5
6
|
import { judgePathRows } from "../../core/path-guard-rows.js";
|
|
6
7
|
export const READ_DENY_HOME_WORD = "~";
|
|
@@ -313,17 +314,54 @@ function asciiLower(s) {
|
|
|
313
314
|
}
|
|
314
315
|
return out;
|
|
315
316
|
}
|
|
317
|
+
let UNIT_FOLD;
|
|
318
|
+
function foldedUnit(c) {
|
|
319
|
+
if (c < 0x80)
|
|
320
|
+
return c >= 0x61 && c <= 0x7a ? c - 0x20 : c;
|
|
321
|
+
const table = (UNIT_FOLD ??= new Int32Array(0x10000).fill(-1));
|
|
322
|
+
const known = table[c];
|
|
323
|
+
if (known >= 0)
|
|
324
|
+
return known;
|
|
325
|
+
const upper = String.fromCharCode(c).toUpperCase();
|
|
326
|
+
const folded = upper.length === 1 && upper.charCodeAt(0) >= 0x80 ? upper.charCodeAt(0) : c;
|
|
327
|
+
table[c] = folded;
|
|
328
|
+
return folded;
|
|
329
|
+
}
|
|
330
|
+
export function ignoreCaseFold(s) {
|
|
331
|
+
let out = "";
|
|
332
|
+
for (let from = 0; from < s.length; from += 4096) {
|
|
333
|
+
const codes = [];
|
|
334
|
+
for (let i = from, to = Math.min(from + 4096, s.length); i < to; i++)
|
|
335
|
+
codes.push(foldedUnit(s.charCodeAt(i)));
|
|
336
|
+
out += String.fromCharCode(...codes);
|
|
337
|
+
}
|
|
338
|
+
return out;
|
|
339
|
+
}
|
|
340
|
+
export const SEGMENT_FOLDS = { none: (s) => s, ascii: asciiLower, unicode: ignoreCaseFold };
|
|
341
|
+
function foldSegments(fold, segs) {
|
|
342
|
+
return segs.map((s) => SEGMENT_FOLDS[fold](s));
|
|
343
|
+
}
|
|
344
|
+
function foldedViewsOf(views) {
|
|
345
|
+
const memo = new Map();
|
|
346
|
+
return (fold) => {
|
|
347
|
+
let folded = memo.get(fold);
|
|
348
|
+
if (folded === undefined)
|
|
349
|
+
memo.set(fold, (folded = fold === "none" ? views : views.map((segs) => foldSegments(fold, segs))));
|
|
350
|
+
return folded;
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
function segmentMatcher(pattern) {
|
|
354
|
+
return {
|
|
355
|
+
anything: /^\*+$/.test(pattern),
|
|
356
|
+
test: (segment) => !segment.includes("/") && wildcardMatch(pattern, segment),
|
|
357
|
+
};
|
|
358
|
+
}
|
|
316
359
|
export function compileSegmentPattern(raw, fold) {
|
|
317
|
-
const source = fold
|
|
360
|
+
const source = SEGMENT_FOLDS[fold](raw);
|
|
318
361
|
const parts = source.split("/").filter(Boolean);
|
|
319
362
|
if (parts.length === 0)
|
|
320
363
|
return null;
|
|
321
|
-
|
|
322
|
-
const segments = parts.map((segment) => {
|
|
323
|
-
const escaped = segment.replace(/[.+^${}()|[\]\\?]/g, "\\$&").replace(/\*+/g, "[^/]*");
|
|
324
|
-
return new RegExp(`^${escaped}$`, flags);
|
|
325
|
-
});
|
|
326
|
-
return { raw, segments, foldAscii: fold === "ascii" };
|
|
364
|
+
return { raw, segments: parts.map(segmentMatcher), fold };
|
|
327
365
|
}
|
|
328
366
|
export function matchSegmentPatterns(path, compiled, opts) {
|
|
329
367
|
const readings = segmentReadingsOf(path, opts?.aliasResolved === true);
|
|
@@ -339,7 +377,13 @@ function segmentReadingsOf(path, aliasResolved) {
|
|
|
339
377
|
if (known !== undefined)
|
|
340
378
|
return known;
|
|
341
379
|
const views = segmentViewsOf(path, aliasResolved ? { aliasResolved } : undefined);
|
|
342
|
-
|
|
380
|
+
let folded;
|
|
381
|
+
const readings = {
|
|
382
|
+
views,
|
|
383
|
+
lowered: views.map((v) => foldSegments("ascii", v)),
|
|
384
|
+
folded: () => (folded ??= views.map((v) => foldSegments("unicode", v))),
|
|
385
|
+
rooted: isAbsoluteForFamily("own", path),
|
|
386
|
+
};
|
|
343
387
|
if (SEGMENT_READINGS.size >= 512)
|
|
344
388
|
SEGMENT_READINGS.clear();
|
|
345
389
|
SEGMENT_READINGS.set(key, readings);
|
|
@@ -347,7 +391,7 @@ function segmentReadingsOf(path, aliasResolved) {
|
|
|
347
391
|
}
|
|
348
392
|
function segmentRowMeets(pat, readings) {
|
|
349
393
|
const n = pat.segments.length;
|
|
350
|
-
const views = pat.
|
|
394
|
+
const views = pat.fold === "ascii" ? readings.lowered : pat.fold === "unicode" ? readings.folded() : readings.views;
|
|
351
395
|
for (const segs of views) {
|
|
352
396
|
const runAt = (i) => i + n <= segs.length && pat.segments.every((re, j) => re.test(segs[i + j] ?? ""));
|
|
353
397
|
if (pat.anchors !== undefined && readings.rooted) {
|
|
@@ -406,16 +450,13 @@ function rowMeetsPath(pat, segs, rooted) {
|
|
|
406
450
|
}
|
|
407
451
|
return false;
|
|
408
452
|
}
|
|
409
|
-
function isAnySegment(re) {
|
|
410
|
-
return /^\^(\[\^\/\]\*)+\$$/.test(re.source);
|
|
411
|
-
}
|
|
412
453
|
function rowNamedByRoot(pat, segs, rooted) {
|
|
413
454
|
if (pat.anchors !== undefined)
|
|
414
455
|
return rooted && rowMeetsPath(pat, segs, rooted) ? "named" : "none";
|
|
415
456
|
if (pat.rootedOnly === true)
|
|
416
457
|
return "none";
|
|
417
458
|
let k = 0;
|
|
418
|
-
while (k < pat.segments.length &&
|
|
459
|
+
while (k < pat.segments.length && pat.segments[k].anything)
|
|
419
460
|
k++;
|
|
420
461
|
const run = pat.segments.slice(k);
|
|
421
462
|
for (let i = 0; run.length > 0 && i < segs.length; i++) {
|
|
@@ -427,11 +468,11 @@ function rowNamedByRoot(pat, segs, rooted) {
|
|
|
427
468
|
}
|
|
428
469
|
function rowNamedByRootOf(rows, path) {
|
|
429
470
|
const rooted = isAbsoluteForFamily("own", path);
|
|
430
|
-
const
|
|
471
|
+
const foldedViews = foldedViewsOf(segmentViewsOf(path));
|
|
431
472
|
let unplaced;
|
|
432
473
|
for (const pat of rows) {
|
|
433
|
-
for (const view of
|
|
434
|
-
const relation = rowNamedByRoot(pat,
|
|
474
|
+
for (const view of foldedViews(pat.fold)) {
|
|
475
|
+
const relation = rowNamedByRoot(pat, view, rooted);
|
|
435
476
|
if (relation === "named")
|
|
436
477
|
return { pattern: pat.raw };
|
|
437
478
|
if (relation === "unplaced")
|
|
@@ -442,10 +483,10 @@ function rowNamedByRootOf(rows, path) {
|
|
|
442
483
|
}
|
|
443
484
|
function rowAtOrBelowOf(rows, path) {
|
|
444
485
|
const rooted = isAbsoluteForFamily("own", path);
|
|
445
|
-
const
|
|
486
|
+
const foldedViews = foldedViewsOf(segmentViewsOf(path));
|
|
446
487
|
for (const pat of rows) {
|
|
447
|
-
for (const view of
|
|
448
|
-
if (rowMeetsPath(pat,
|
|
488
|
+
for (const view of foldedViews(pat.fold))
|
|
489
|
+
if (rowMeetsPath(pat, view, rooted))
|
|
449
490
|
return pat.raw;
|
|
450
491
|
}
|
|
451
492
|
return null;
|
|
@@ -562,7 +603,7 @@ export function compileReadDeny(additions = [], layer = "additions", builtin, ru
|
|
|
562
603
|
return { ...c, raw: e.pattern };
|
|
563
604
|
if (homeSegments.length === 0)
|
|
564
605
|
return { ...c, raw: e.pattern, unplacedHome: true };
|
|
565
|
-
return { ...c, raw: e.pattern, anchors: homeSegments.map((segs) => (fold
|
|
606
|
+
return { ...c, raw: e.pattern, anchors: homeSegments.map((segs) => foldSegments(fold, segs)) };
|
|
566
607
|
});
|
|
567
608
|
if (!(linked instanceof Map))
|
|
568
609
|
throw new Error(`readDenyHomeLinks: expected a Map from a row's pattern to its locations, got ${typeof linked}.`);
|
|
@@ -576,13 +617,13 @@ export function compileReadDeny(additions = [], layer = "additions", builtin, ru
|
|
|
576
617
|
const rest = c.segments.slice(readDenyRunHead(run));
|
|
577
618
|
for (const location of new Set(checkedReadDenyHomes(locations, "readDenyHomeLinks"))) {
|
|
578
619
|
const segs = homeAnchorSegments(location);
|
|
579
|
-
linkedPlacements.push({ raw: e.pattern, segments: rest,
|
|
620
|
+
linkedPlacements.push({ raw: e.pattern, segments: rest, fold: c.fold, anchors: [foldSegments(c.fold, segs)], rootedOnly: true });
|
|
580
621
|
}
|
|
581
622
|
});
|
|
582
623
|
const judged = linkedPlacements.length === 0 ? compiled : [...compiled, ...linkedPlacements];
|
|
583
624
|
const segmentRows = judged.map((c) => {
|
|
584
625
|
const col = columns.get(c.raw);
|
|
585
|
-
return segmentGuardRow(c, { faces: ["read"], polarity: "deny", exemptible: false, fold: c.
|
|
626
|
+
return segmentGuardRow(c, { faces: ["read"], polarity: "deny", exemptible: false, fold: c.fold === "ascii" ? "ascii" : "exact", origin: col?.origin ?? "addition", ...(col?.tier !== undefined ? { tier: col.tier } : {}) });
|
|
586
627
|
});
|
|
587
628
|
const tableRows = [...segmentRows, ...ruleRows.map(ruleGuardRow)];
|
|
588
629
|
const rgExclusionGlobs = [];
|
|
@@ -22,7 +22,7 @@ export interface DangerousRemoval {
|
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
24
|
* The ONE dangerous-removal predicate: is removing this absolute path removing a protected location? The reference
|
|
25
|
-
* implementation's set
|
|
25
|
+
* implementation's set — the filesystem root (a drive root, a UNC share root), a home directory
|
|
26
26
|
* (every spelling the seat holds), a workspace directory or any of its ANCESTORS (the task root, the working directory, an
|
|
27
27
|
* additional working directory — whether the home lies inside the task root or the task root inside the home), a top-level
|
|
28
28
|
* directory (one segment below the root). `undefined` for a relative path or any other target.
|
|
@@ -57,7 +57,7 @@ export interface ReadEntry {
|
|
|
57
57
|
* attachment picks the most RECENTLY read files, the way CC sorts readFileState by timestamp.
|
|
58
58
|
* Optional/additive: undefined (an entry seeded from an older checkpoint) sorts last, never breaks. */
|
|
59
59
|
lastReadAt?: number;
|
|
60
|
-
/**
|
|
60
|
+
/** TRUE when the Runner pre-seeded this entry because the file's FULL
|
|
61
61
|
* disk-verbatim text was injected into the model's context at startup
|
|
62
62
|
* (ProjectMemoryLoad.seededFiles — CC's own memory preload). A DEFAULT whole-file Read of an
|
|
63
63
|
* UNCHANGED seeded file
|
|
@@ -84,7 +84,7 @@ export declare function sha256(content: string): string;
|
|
|
84
84
|
export interface FsViolation {
|
|
85
85
|
code: "path_not_in_root" | "not_read" | "stale" | "ambiguous_edit" | "invalid" | "read_path_denied" | "write_path_denied";
|
|
86
86
|
/** Set on the `not_read` violation raised by an AUTO-TRUNCATED read
|
|
87
|
-
* ({@link ReadEntry.isPartialView}) rather than by a never-read file. Both carry the same
|
|
87
|
+
* ({@link ReadEntry.isPartialView}) rather than by a never-read file. Both carry the same
|
|
88
88
|
* message; only this one needs {@link PARTIAL_VIEW_READ_ESCAPE_HINT} appended, because for it a plain
|
|
89
89
|
* re-read is a fixpoint. */
|
|
90
90
|
partialView?: true;
|
|
@@ -238,7 +238,7 @@ export declare function binaryMagicFormat(bytes: Uint8Array): string | undefined
|
|
|
238
238
|
*/
|
|
239
239
|
export declare function isBinaryContent(sample: string): boolean;
|
|
240
240
|
/**
|
|
241
|
-
*
|
|
241
|
+
* The UNC/network-path predicate (`n.startsWith("\\\\") || n.startsWith("//")`). Pure.
|
|
242
242
|
*
|
|
243
243
|
* In CC this test is an EARLY ALLOW — it skips the binary-extension and device checks that follow it —
|
|
244
244
|
* and CC applies it to the NORMALIZED path, not the raw argument. See {@link canonicalizeTarget} for
|
|
@@ -572,7 +572,7 @@ export declare function rootAdmittingArtifactStore(storePhysical: string, rootsC
|
|
|
572
572
|
*/
|
|
573
573
|
export declare const PATH_NOT_IN_ROOT_ESCAPE_HINT = "(This boundary applies to the structured file tools. If you genuinely need content outside the allowed root(s), ask for the directory to be added to the deployment's additionalDirectories \u2014 or additionalReadDirectories for read-only access; a deployment that wants reads or writes open everywhere can declare readFace / writeFace: \"open\" instead of listing directories.)";
|
|
574
574
|
/** inv 1 (read-before-edit): a file must have been read this task before it can be edited/overwritten.
|
|
575
|
-
* Message
|
|
575
|
+
* Message as probed (all-tools-live-probe 2026-07-08 §2.1/§3.1/§5.1 — one message for
|
|
576
576
|
* Edit/Write/NotebookEdit: "before writing to it", not the old sema "before editing").
|
|
577
577
|
*
|
|
578
578
|
* CC parity (Edit and Write spell the read gate identically, `!p || p.isPartialView`): an
|
|
@@ -594,7 +594,7 @@ export declare function requireRead(state: ReadFileState, key: string): FsViolat
|
|
|
594
594
|
* Escape-hatch parenthetical appended to the read-before-edit refusal when the target file is over
|
|
595
595
|
* the Read tool's whole-file byte cap: a bare "read it first" would be un-followable there (a default
|
|
596
596
|
* whole-file Read refuses such files → refusal loop). Same parenthetical pattern as the Write tool's
|
|
597
|
-
* encoding-deadlock hint; the
|
|
597
|
+
* encoding-deadlock hint; the base sentence stays untouched for the normal-size case.
|
|
598
598
|
*/
|
|
599
599
|
export declare const OVERSIZE_READ_ESCAPE_HINT = "(This file is over the Read tool's whole-file byte cap, so a default Read is refused \u2014 read it in slices with explicit offset/limit to satisfy the read-first rule, or inspect/transform it with bash (e.g. `sed -n`, `grep`) instead.)";
|
|
600
600
|
/**
|
|
@@ -623,7 +623,7 @@ export declare const READ_REFUSED_ESCAPE_HINT = "(If the Read tool refuses this
|
|
|
623
623
|
/**
|
|
624
624
|
* Edit "no-op" guard (CC FileEditTool parity): refuse an edit whose `old_string`
|
|
625
625
|
* equals `new_string` — without it the edit passes the match check and writes the file back unchanged (a
|
|
626
|
-
* silent no-op that wastes a turn and dirties mtime).
|
|
626
|
+
* silent no-op that wastes a turn and dirties mtime). The message is worded so a CC-trained model recognizes it.
|
|
627
627
|
*/
|
|
628
628
|
export declare function checkNoChange(oldString: string, newString: string): FsViolation | undefined;
|
|
629
629
|
/** inv 2 (staleness): the file's current content hash must match what was recorded at read time.
|
|
@@ -667,7 +667,7 @@ export declare function resolveQuoteMatch(content: string, oldString: string): s
|
|
|
667
667
|
*/
|
|
668
668
|
export declare function resolveEscapeMatch(content: string, oldString: string): string | undefined;
|
|
669
669
|
/**
|
|
670
|
-
*
|
|
670
|
+
* Rewrite `newString` into the SAME spelling the matched
|
|
671
671
|
* span uses. Without this, a match found through {@link resolveEscapeMatch} would replace an escaped
|
|
672
672
|
* span with a literal-character replacement (or vice versa) and silently change the file's encoding
|
|
673
673
|
* convention at that spot. Hex case follows what the file itself used, per-character where known and by
|
|
@@ -677,7 +677,7 @@ export declare function adaptNewStringEscapes(oldString: string, matchedOld: str
|
|
|
677
677
|
/** CC `KZu` (@366558): the old_string shapes for which the escape layers above were even attempted —
|
|
678
678
|
* gates the explanatory note appended to a no-match refusal so it is never a false claim. */
|
|
679
679
|
export declare function escapeMatchWasAttempted(oldString: string): boolean;
|
|
680
|
-
/**
|
|
680
|
+
/** The escape-match miss note. */
|
|
681
681
|
export declare const ESCAPE_MATCH_MISS_NOTE = "\n(note: Edit also tried swapping \\uXXXX escapes and their characters; neither form matched, so the mismatch is likely elsewhere in old_string. Re-read the file and copy the exact surrounding text.)";
|
|
682
682
|
/**
|
|
683
683
|
* When the quote-forgiving match resolved to a curly-quoted file span, convert the straight quotes in
|
|
@@ -697,7 +697,7 @@ export declare function deletionOldString(content: string, oldString: string, ne
|
|
|
697
697
|
/**
|
|
698
698
|
* inv 3 (edit uniqueness): `oldString` must match exactly once unless `replaceAll`. Zero → not found;
|
|
699
699
|
* >1 without replaceAll → ambiguous. `truncated` adds a hint that unseen content may hold more matches (S2).
|
|
700
|
-
* Messages
|
|
700
|
+
* Messages as probed (all-tools-live-probe 2026-07-08 §2.1): first sentence(s) byte-exact,
|
|
701
701
|
* then a `String: <needle>` echo line (CC form). The sema truncated-read hint survives as a parenthetical
|
|
702
702
|
* appended to the sentence (probe verdict: "truncated 提示可并入括注保留").
|
|
703
703
|
*/
|
|
@@ -11,7 +11,7 @@ export declare const JS_GREP_OUTPUT_MAX_BYTES: number;
|
|
|
11
11
|
* "any dot-prefixed name is invisible" rule beside it. */
|
|
12
12
|
export declare const DEFAULT_IGNORE_DIRS: ReadonlySet<string>;
|
|
13
13
|
export interface GrepParams {
|
|
14
|
-
/** Regular expression (ripgrep semantics) —
|
|
14
|
+
/** Regular expression (ripgrep semantics) — the pattern is ALWAYS a regex; the
|
|
15
15
|
* old `regex?: boolean` literal-by-default switch is retired (a legacy `regex` argument sent by an
|
|
16
16
|
* old caller is tolerated and ignored at the tool layer, never a failure). */
|
|
17
17
|
pattern: string;
|
|
@@ -24,7 +24,7 @@ export interface GrepParams {
|
|
|
24
24
|
* line (rg -o / --only-matching). content mode only; ignored otherwise (CC parity). With
|
|
25
25
|
* `multiline` the JS fallback emits the matched SEGMENT's lines (rg -U -o shape). */
|
|
26
26
|
only_matching?: boolean;
|
|
27
|
-
/** content: `path:line:text`. files_with_matches (default
|
|
27
|
+
/** content: `path:line:text`. files_with_matches (default): `path`. count: `path:count`. */
|
|
28
28
|
output_mode?: "content" | "files_with_matches" | "count";
|
|
29
29
|
/** Lines of context around a match (content mode only) — CC's `-C`. */
|
|
30
30
|
context?: number;
|
|
@@ -44,10 +44,10 @@ export interface GrepParams {
|
|
|
44
44
|
/** Skip the first N output lines — CC's `offset` (pagination partner of head_limit). */
|
|
45
45
|
offset?: number;
|
|
46
46
|
}
|
|
47
|
-
/**
|
|
47
|
+
/** Split the `glob` param into individual glob
|
|
48
48
|
* tokens — whitespace-separated first; a token WITHOUT braces is further split on commas
|
|
49
49
|
* (`"*.ts,*.tsx"` → two globs), while a brace token (`*.{ts,tsx}`) is kept whole (its commas are
|
|
50
|
-
* alternation syntax, not separators).
|
|
50
|
+
* alternation syntax, not separators). */
|
|
51
51
|
export declare function splitGlobParam(glob: string): string[];
|
|
52
52
|
/**
|
|
53
53
|
* POSIX-safe single-quote so an arbitrary model-supplied string can't break out of the shell command that
|
|
@@ -111,7 +111,7 @@ export interface WalkResult {
|
|
|
111
111
|
skippedUnreadable: number;
|
|
112
112
|
/** The walk was cut short by an abort — the result is a prefix, not a survey. */
|
|
113
113
|
aborted: boolean;
|
|
114
|
-
/**
|
|
114
|
+
/** Modification time (ms epoch) per walked path (files AND
|
|
115
115
|
* name-only entries), captured from the listing that discovered them — so glob can sort by mtime
|
|
116
116
|
* without a second stat pass. An env whose listings carry no numeric `mtimeMs` simply leaves
|
|
117
117
|
* entries out of this map (consumers fall back to name order). */
|
|
@@ -317,7 +317,7 @@ export declare function runGlob(env: ExecutionEnv, root: string, pattern: string
|
|
|
317
317
|
* shell renders (`filenames`/`numFiles`/`truncated`/`durationMs`/`totalMatches`/`countIsComplete`)
|
|
318
318
|
* without re-parsing the text.
|
|
319
319
|
*
|
|
320
|
-
*
|
|
320
|
+
* Backlog P2-2:
|
|
321
321
|
* · `totalMatches` — "Total number of matching files before truncation. A lower bound when
|
|
322
322
|
* countIsComplete is false." (CC: `totalMatches: g.length`)
|
|
323
323
|
* · `countIsComplete` — "Whether totalMatches is the exact total (true) or a floor because the
|
|
@@ -203,6 +203,11 @@ function fitCause(cause) {
|
|
|
203
203
|
function faceOf(fold) {
|
|
204
204
|
return fold.witness?.read.candidate.face === "write" ? "write" : undefined;
|
|
205
205
|
}
|
|
206
|
+
function reenteredPrograms(fold) {
|
|
207
|
+
const names = [...new Set((fold.reentered ?? []).flatMap((s) => (s.verb !== undefined ? [s.verb.basename] : [])))];
|
|
208
|
+
const quoted = names.map((n) => `"${fitMiddle(n, CAUSE_SPELLING_MAX)}"`);
|
|
209
|
+
return quoted.length === 0 ? "the program it runs" : quoted.length === 1 ? quoted[0] : `${quoted.slice(0, -1).join(", ")} and ${quoted.at(-1)}`;
|
|
210
|
+
}
|
|
206
211
|
function findingAccount(fold, boundary) {
|
|
207
212
|
const w = fold.witness;
|
|
208
213
|
const face = faceOf(fold);
|
|
@@ -228,7 +233,7 @@ function findingAccount(fold, boundary) {
|
|
|
228
233
|
if (fold.declined?.unreadProgramText !== undefined)
|
|
229
234
|
return `"${fitMiddle(fold.declined.text.trim(), ACCOUNT_PART_MAX)}": ${fold.declined.unreadProgramText}, so where it ${verb} cannot be established ${NOT_AUTO_ALLOWED}`;
|
|
230
235
|
if (fold.declined !== undefined)
|
|
231
|
-
return `
|
|
236
|
+
return `the text given to ${reenteredPrograms(fold)} — as an argument, on standard input, or in the file it names — runs as shell text this station does not parse ${NOT_AUTO_ALLOWED}`;
|
|
232
237
|
return `the command's text could not be read as shell, so where it ${verb} cannot be established ${NOT_AUTO_ALLOWED}`;
|
|
233
238
|
case "declined":
|
|
234
239
|
return fold.declined !== undefined ? declineSentence(fold.declined) : `the station could not read which program runs ${NOT_AUTO_ALLOWED}`;
|
|
@@ -358,6 +358,10 @@ export interface ShellReadFold {
|
|
|
358
358
|
readonly finding: ShellReadFinding;
|
|
359
359
|
readonly witness?: ReadFinding;
|
|
360
360
|
readonly declined?: ShellReadSegment;
|
|
361
|
+
/** EVERY segment of the text that re-enters a shell (`sh -c S`, `eval S`, a launcher handing text to a shell, a shell fed on its
|
|
362
|
+
* standard input) and so is at least `unestablishable`, in text order — `declined` holds only the first finding of the rank, and the
|
|
363
|
+
* account of this question names each program, not the first. Present only with an `unestablished` fold. */
|
|
364
|
+
readonly reentered?: readonly ShellReadSegment[];
|
|
361
365
|
/** What the judge did not finish, for an `unanswered` finding: the first thing the establishment recorded ({@link Incomplete.detail}). */
|
|
362
366
|
readonly cause?: string;
|
|
363
367
|
/** Some read of the text could not be established (an `unestablishable`, `unanswered` or `declined` finding anywhere, winning or not). */
|
|
@@ -132,6 +132,7 @@ export function foldShellReadFindings(judged) {
|
|
|
132
132
|
let best = { finding: "none" };
|
|
133
133
|
let unestablished = false;
|
|
134
134
|
let unplacedRead = false;
|
|
135
|
+
const reentered = [];
|
|
135
136
|
const raise = (next) => {
|
|
136
137
|
if (next.finding === "unestablishable" || next.finding === "declined" || next.finding === "unanswered") {
|
|
137
138
|
const face = next.witness?.read.candidate.face;
|
|
@@ -158,8 +159,10 @@ export function foldShellReadFindings(judged) {
|
|
|
158
159
|
if (!denyOnly) {
|
|
159
160
|
if (s.segment.declines.length > 0)
|
|
160
161
|
raise({ finding: "declined", declined: s.segment });
|
|
161
|
-
if (s.segment.reentry === "shell")
|
|
162
|
+
if (s.segment.reentry === "shell") {
|
|
162
163
|
raise({ finding: "unestablishable", declined: s.segment });
|
|
164
|
+
reentered.push(s.segment);
|
|
165
|
+
}
|
|
163
166
|
if (s.segment.unreadProgramText !== undefined)
|
|
164
167
|
raise({ finding: "unestablishable", declined: s.segment });
|
|
165
168
|
const move = s.segment.baseMove;
|
|
@@ -177,7 +180,7 @@ export function foldShellReadFindings(judged) {
|
|
|
177
180
|
unestablished = true;
|
|
178
181
|
best = { finding: "unanswered", cause: unfinished.detail, ...(best.finding === "unestablishable" ? { ...(best.witness !== undefined ? { witness: best.witness } : {}), ...(best.declined !== undefined ? { declined: best.declined } : {}) } : {}) };
|
|
179
182
|
}
|
|
180
|
-
return { ...best, ...(unestablished ? { unestablished: true } : {}), ...(unplacedRead ? { unplacedRead: true } : {}) };
|
|
183
|
+
return { ...best, ...(unestablished ? { unestablished: true } : {}), ...(unplacedRead ? { unplacedRead: true } : {}), ...(unestablished && reentered.length > 0 ? { reentered } : {}) };
|
|
181
184
|
}
|
|
182
185
|
export function judgeEstablishedPlan(plan, established, boundary, nestedOf) {
|
|
183
186
|
return {
|
|
@@ -19,9 +19,9 @@ export interface AutonomousLoopPromptOptions {
|
|
|
19
19
|
*/
|
|
20
20
|
pushNotification?: boolean;
|
|
21
21
|
}
|
|
22
|
-
/**
|
|
22
|
+
/** First-tick preamble, DEFAULT variant (steward framing). The reference later dropped this preamble. */
|
|
23
23
|
export declare const AUTONOMOUS_LOOP_PREAMBLE = "# Autonomous loop check\n\nYou're being invoked on a timer while the user is away or occupied. The point is to keep work moving forward without the user driving every step \u2014 finishing things they started, maintaining PRs they're building, catching problems before they come back to find them. You're a steward, not an initiator. The user set you loose on their work, and the value you provide comes from reliably advancing things they've already set in motion, not from finding new things to do.\n\nThe key tension to navigate: the user trusts you enough to run autonomously, but that trust is easily lost. Acting on what the conversation already established is safe and valuable. Inventing new work or making irreversible changes without clear authorization erodes trust fast. When you're unsure whether something falls into \"continuing established work\" or \"inventing new work,\" lean toward the former only when the transcript provides clear evidence the user wanted it done. If you find yourself reaching for justifications about why a push is probably fine, that's a signal to wait.\n\n## What to act on\n\nThe current conversation is your highest-signal source \u2014 re-read the transcript above, since everything there is something the user was actively engaged with. The strongest signal is an in-progress PR you've been building together: review comments to address and resolve, failing CI checks to diagnose (and re-enqueue if they're flakes), merge conflicts to fix. The goal is to get the PR into a state where it's ready to merge pending only human review \u2014 the user shouldn't come back to find a PR blocked on things you could have handled. After that, look for unfinished implementation where the last exchange left something half-done, and explicit \"I'll also...\" or \"next I'll...\" commitments the conversation made and didn't honor. Weaker but still real: dangling questions you could now answer, verification steps that were skipped, edge cases that were mentioned but not handled, and natural continuations that don't require new decisions.\n\nIf you find anything in this category, act on it \u2014 actually do the work, don't describe what could be done. Run the tests, don't say \"you could run the tests.\" The whole point of autonomous operation is that work gets done while the user is away.\n\nWhen the conversation transcript has nothing left, the current branch's pull/merge request on the user's SCM is the next-best place to look. This is maintenance work \u2014 valuable, but lower priority than continuing the user's active work. Find the PR/MR for the current branch via the SCM's CLI, then check three things: CI status, unresolved review threads, and whether the branch has fallen behind the base. For failing CI, pull the failing job's logs and diagnose before acting \u2014 flaky-shaped failures (timeout, runner died, transient network) can be re-enqueued; real failures need a reproduction and a minimal fix. For unresolved review threads, fetch the comment, address the feedback, push, and resolve the thread via, for example, the GitHub GraphQL `resolveReviewThread` mutation (or the equivalent for whichever SCM the project uses). Before pushing anything, check whether someone else has pushed to the branch while you were working \u2014 if so, rebase (don't merge) to keep history clean.\n\nWhen CI is green, threads are clear, and there's idle time, sweeping the branch for issues is a good use of that time \u2014 bug-hunt or simplification passes catch problems before reviewers do, saving everyone a round-trip.\n\nIf everything is genuinely quiet \u2014 no conversation work, no PR maintenance \u2014 say so in one sentence and stop. No summary of what you checked, no list of what you might do later. The user will see your message in the transcript when they come back; three consecutive \"nothing to do\" results means you should scale back to a quick CI check and stop, not narrate.\n\n## Repeated invocations\n\nIf you see earlier autonomous checks in this conversation, adjust your scope accordingly. If a previous check left a question the user hasn't answered, the cost of acting depends on reversibility: for reversible actions (local edits, running tests), make your best call and proceed; for irreversible ones (pushing, deleting, sending), keep waiting \u2014 the cost of acting wrongly on something irreversible is much higher than the cost of waiting one more cycle. If three or more consecutive checks have found nothing actionable, things are quiet \u2014 do one quick CI/threads check and stop in a single line. Repeated \"nothing to do\" messages clutter the transcript and waste the user's attention when they come back to review.\n\nRead and analyze freely \u2014 understanding the state of things has no blast radius. Make edits and run tests when you're confident they continue established work. Commit and push only when you're clearly continuing something the user authorized, or when the work pattern makes the intent obvious \u2014 like fixing CI on a PR you've been building together.\n";
|
|
24
|
-
/**
|
|
24
|
+
/** First-tick preamble, PERSISTENT variant. Later dropped by the reference. */
|
|
25
25
|
export declare const AUTONOMOUS_LOOP_PREAMBLE_PERSISTENT = "# Autonomous loop check\n\nYou're being invoked on a timer while the user is away or occupied. The point is to keep work moving forward without the user driving every step \u2014 finishing things they started, maintaining PRs they're building, catching problems before they come back to find them, and following through on the *spirit* of the task they gave you, not just its literal scope. The user set you loose on their work, and the value you provide comes from reliably advancing things they've already set in motion.\n\nThe key tension to navigate: the user trusts you enough to run autonomously, but that trust is easily lost. Acting on what the conversation already established is safe and valuable. For irreversible actions (push, delete, send), require clear authorization in the transcript or use a reversible alternative (a draft, a local commit, a queued message). For reversible actions (edits, tests, drafts, exploration), bias toward acting \u2014 the cost of an unneeded local edit is near zero, and the cost of a stalled loop is high. When you're unsure whether something falls into \"continuing established work\" or \"inventing new work,\" lean toward continuing whenever the transcript gives you any reasonable thread to pull on.\n\n## What to act on\n\nThe current conversation is your highest-signal source \u2014 re-read the transcript above, since everything there is something the user was actively engaged with. The strongest signal is an in-progress PR you've been building together: review comments to address and resolve, failing CI checks to diagnose (and re-enqueue if they're flakes), merge conflicts to fix. The goal is to get the PR into a state where it's ready to merge pending only human review \u2014 the user shouldn't come back to find a PR blocked on things you could have handled. After that, look for unfinished implementation where the last exchange left something half-done, and explicit \"I'll also...\" or \"next I'll...\" commitments the conversation made and didn't honor. Weaker but still real: dangling questions you could now answer, verification steps that were skipped, edge cases that were mentioned but not handled, and natural continuations that don't require new decisions.\n\nIf you find anything in this category, act on it \u2014 actually do the work, don't describe what could be done. Run the tests, don't say \"you could run the tests.\" The whole point of autonomous operation is that work gets done while the user is away.\n\nWhen the conversation transcript has nothing left, the current branch's pull/merge request on the user's SCM is the next-best place to look. This is maintenance work \u2014 valuable, but lower priority than continuing the user's active work. Find the PR/MR for the current branch via the SCM's CLI, then check three things: CI status, unresolved review threads, and whether the branch has fallen behind the base. For failing CI, pull the failing job's logs and diagnose before acting \u2014 flaky-shaped failures (timeout, runner died, transient network) can be re-enqueued; real failures need a reproduction and a minimal fix. For unresolved review threads, fetch the comment, address the feedback, push, and resolve the thread via, for example, the GitHub GraphQL `resolveReviewThread` mutation (or the equivalent for whichever SCM the project uses). Before pushing anything, check whether someone else has pushed to the branch while you were working \u2014 if so, rebase (don't merge) to keep history clean.\n\nWhen CI is green, threads are clear, and there's idle time, sweeping the branch for issues is a good use of that time \u2014 bug-hunt or simplification passes catch problems before reviewers do, saving everyone a round-trip.\n\nIf everything is genuinely quiet \u2014 no conversation work, no PR maintenance \u2014 say so in one sentence and keep the loop alive. Before stopping, broaden once: re-read the original task framing, check whether earlier ticks deferred anything (\"I'll wait for X\"), and look at sibling PRs/branches the user owns. Persistence is the point of autonomous mode. Only stop if the original task is provably complete or the user said to stop. (Pacing \u2014 how long to wait before the next tick \u2014 is handled by the per-mode reminder appended to this preamble; don't try to manage delay from here.)\n\n## Repeated invocations\n\nIf you see earlier autonomous checks in this conversation, adjust your scope accordingly. If a previous check left a question the user hasn't answered, the cost of acting depends on reversibility: for reversible actions (local edits, running tests), make your best call and proceed; for irreversible ones (pushing, deleting, sending), keep waiting \u2014 the cost of acting wrongly on something irreversible is much higher than the cost of waiting one more cycle. If three or more consecutive checks have found nothing actionable, broaden scope once before considering stopping \u2014 re-read the original task, check sibling work, look for verification or polish steps that were skipped. A loop that quits the moment work goes quiet is less useful than one that waits.\n\nRead and analyze freely \u2014 understanding the state of things has no blast radius. Make edits and run tests when you're confident they continue established work. Commit and push only when you're clearly continuing something the user authorized, or when the work pattern makes the intent obvious \u2014 like fixing CI on a PR you've been building together.\n";
|
|
26
26
|
/**
|
|
27
27
|
* Resolve a fire-time prompt: if it is one of the two autonomous-loop sentinels, return the tick
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import { defineTool, errorResult } from "../core/tools.js";
|
|
3
3
|
import { hasScheduler, isValidCronExpr, } from "../core/scheduler.js";
|
|
4
|
-
import { toolFace } from "../core/tool-catalog-entries.js";
|
|
4
|
+
import { mountRuleFace, toolFace } from "../core/tool-catalog-entries.js";
|
|
5
5
|
export const SCHEDULE_WAKEUP_TOOL_NAME = "ScheduleWakeup";
|
|
6
6
|
export const AUTONOMOUS_LOOP_SENTINEL = "<<autonomous-loop>>";
|
|
7
7
|
export const AUTONOMOUS_LOOP_DYNAMIC_SENTINEL = "<<autonomous-loop-dynamic>>";
|
|
@@ -201,6 +201,7 @@ Only use minute 0 or 30 when the user names that exact time and clearly means it
|
|
|
201
201
|
const cronCreate = defineTool({
|
|
202
202
|
name: "CronCreate",
|
|
203
203
|
...toolFace("cron-create"),
|
|
204
|
+
ruleFace: mountRuleFace("cron-create"),
|
|
204
205
|
description: cronCreateDescription,
|
|
205
206
|
parameters: Type.Object({
|
|
206
207
|
prompt: Type.String({ description: "Self-contained instructions for the future task (it runs unattended)." }),
|
|
@@ -306,6 +307,7 @@ Only use minute 0 or 30 when the user names that exact time and clearly means it
|
|
|
306
307
|
const cronCancel = defineTool({
|
|
307
308
|
name: "CronDelete",
|
|
308
309
|
...toolFace("cron-delete"),
|
|
310
|
+
ruleFace: mountRuleFace("cron-delete"),
|
|
309
311
|
description: "Cancel a cron job previously scheduled with CronCreate. Idempotent; ids also appear in CronList.",
|
|
310
312
|
parameters: Type.Object({ id: Type.String({ description: "Job ID returned by CronCreate." }) }),
|
|
311
313
|
execute: async (args) => {
|
|
@@ -329,6 +331,7 @@ Only use minute 0 or 30 when the user names that exact time and clearly means it
|
|
|
329
331
|
const cronList = defineTool({
|
|
330
332
|
name: "CronList",
|
|
331
333
|
...toolFace("cron-list"),
|
|
334
|
+
ruleFace: mountRuleFace("cron-list"),
|
|
332
335
|
description: "List all cron jobs scheduled via CronCreate (id, when, label).",
|
|
333
336
|
parameters: Type.Object({}),
|
|
334
337
|
execute: async () => {
|
|
@@ -408,6 +411,7 @@ MOUNT NOTE: this host does not vouch for session-scoped scheduling, so a wakeup
|
|
|
408
411
|
const scheduleWakeup = defineTool({
|
|
409
412
|
name: SCHEDULE_WAKEUP_TOOL_NAME,
|
|
410
413
|
...toolFace("schedule-wakeup"),
|
|
414
|
+
ruleFace: mountRuleFace("schedule-wakeup"),
|
|
411
415
|
description: `${SCHEDULE_WAKEUP_PROMPT}${wakeupMountNote}`,
|
|
412
416
|
parameters: Type.Object({
|
|
413
417
|
delaySeconds: Type.Optional(Type.Number({
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import type { ToolSpec } from "../core/types.js";
|
|
2
2
|
/**
|
|
3
|
-
* design/119
|
|
4
|
-
* `TaskUpdate` / `TaskList`.
|
|
3
|
+
* design/119 — the structured task-list tool family: `TaskCreate` / `TaskGet` /
|
|
4
|
+
* `TaskUpdate` / `TaskList`. The upgrade path over TodoWrite: individual tasks with stable ids,
|
|
5
5
|
* status transitions, dependencies (blocks/blockedBy), an optional owner, and free metadata — instead
|
|
6
|
-
* of TodoWrite's replace-the-whole-list.
|
|
7
|
-
* this one is the DEFAULT — TodoWrite mounts only when the task list is explicitly off (the
|
|
6
|
+
* of TodoWrite's replace-the-whole-list. The two families are MUTUALLY EXCLUSIVE and
|
|
7
|
+
* this one is the DEFAULT — TodoWrite mounts only when the task list is explicitly off (the reference
|
|
8
8
|
* shape: TodoWrite isEnabled = !taskList; see `scenarios/full-body.ts`).
|
|
9
9
|
*
|
|
10
10
|
* State default: like TodoWrite, the default store lives in this factory's closure — FRESH per task
|
|
11
11
|
* and torn down with it; nothing durable, no deps, no egress (the model's own scratch, projected to
|
|
12
|
-
* observers only through each call's tool result / `details`). Descriptions follow
|
|
12
|
+
* observers only through each call's tool result / `details`). Descriptions follow the reference
|
|
13
13
|
* (product-specific lines — teammate assignment, spinner/UI wording — trimmed or generalized).
|
|
14
14
|
*
|
|
15
|
-
* design/147 §6 D2 (
|
|
16
|
-
* task list across several agents —
|
|
15
|
+
* design/147 §6 D2 (shared team task list): pass a {@link TaskListStore} to share ONE
|
|
16
|
+
* task list across several agents — the reference's team coordination artifact ("Check the task list
|
|
17
17
|
* periodically. Create new tasks when work should be divided. Mark tasks resolved when complete.")
|
|
18
18
|
* is a task-list file under the team directory; the sema equivalent is this storage seam. A
|
|
19
19
|
* deployment mounts the SAME store instance into each teammate's tool bundle (same session = same
|
package/dist/tools/task-list.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
|
-
import { toolFace } from "../core/tool-catalog-entries.js";
|
|
2
|
+
import { mountRuleFace, toolFace } from "../core/tool-catalog-entries.js";
|
|
3
3
|
const STATUS = Type.Union([
|
|
4
4
|
Type.Literal("pending"),
|
|
5
5
|
Type.Literal("in_progress"),
|
|
@@ -98,6 +98,7 @@ export function createTaskListTools(store) {
|
|
|
98
98
|
const taskCreate = {
|
|
99
99
|
name: "TaskCreate",
|
|
100
100
|
...toolFace("task-create"),
|
|
101
|
+
ruleFace: mountRuleFace("task-create"),
|
|
101
102
|
description: "Use this tool to create a structured task list for your current session. This helps you track progress, organize complex tasks, and demonstrate thoroughness.\n" +
|
|
102
103
|
"It also helps the user understand the progress of the task and overall progress of their requests.\n" +
|
|
103
104
|
"\n" +
|
|
@@ -170,6 +171,7 @@ export function createTaskListTools(store) {
|
|
|
170
171
|
const taskGet = {
|
|
171
172
|
name: "TaskGet",
|
|
172
173
|
...toolFace("task-get"),
|
|
174
|
+
ruleFace: mountRuleFace("task-get"),
|
|
173
175
|
description: "Use this tool to retrieve a task by its ID from the task list.\n" +
|
|
174
176
|
"\n" +
|
|
175
177
|
"## When to Use This Tool\n" +
|
|
@@ -201,6 +203,7 @@ export function createTaskListTools(store) {
|
|
|
201
203
|
const taskUpdate = {
|
|
202
204
|
name: "TaskUpdate",
|
|
203
205
|
...toolFace("task-update"),
|
|
206
|
+
ruleFace: mountRuleFace("task-update"),
|
|
204
207
|
description: "Use this tool to update a task in the task list.\n" +
|
|
205
208
|
"\n" +
|
|
206
209
|
"## When to Use This Tool\n" +
|
|
@@ -394,6 +397,7 @@ export function createTaskListTools(store) {
|
|
|
394
397
|
const taskList = {
|
|
395
398
|
name: "TaskList",
|
|
396
399
|
...toolFace("task-list"),
|
|
400
|
+
ruleFace: mountRuleFace("task-list"),
|
|
397
401
|
description: "Use this tool to list all tasks in the task list.\n" +
|
|
398
402
|
"\n" +
|
|
399
403
|
"## When to Use This Tool\n" +
|
package/dist/tools/todo.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import { errorResult } from "../core/tools.js";
|
|
3
|
-
import { toolFace } from "../core/tool-catalog-entries.js";
|
|
3
|
+
import { mountRuleFace, toolFace } from "../core/tool-catalog-entries.js";
|
|
4
4
|
export function createTodoWriteTool() {
|
|
5
5
|
const lists = new Map();
|
|
6
6
|
return {
|
|
7
7
|
name: "TodoWrite",
|
|
8
8
|
...toolFace("todo-write"),
|
|
9
|
+
ruleFace: mountRuleFace("todo-write"),
|
|
9
10
|
description: "Create and update a task list for the current session. The list is rendered to the user as your working plan.\n" +
|
|
10
11
|
"\n" +
|
|
11
12
|
'- Each todo has `content`, `status` ("pending" | "in_progress" | "completed"), and `activeForm` (present-tense label shown while in progress).\n' +
|
package/dist/tools/web.d.ts
CHANGED
|
@@ -103,7 +103,7 @@ export declare const WEBFETCH_SUMMARY_MAX_CONTENT = 100000;
|
|
|
103
103
|
export declare const WEBFETCH_SUMMARY_GUIDELINES: string;
|
|
104
104
|
/**
|
|
105
105
|
* sema's own grounding clause for the reference summarizer (ruled 2026-08-05), kept OUT of
|
|
106
|
-
* {@link WEBFETCH_SUMMARY_GUIDELINES} so that block stays the
|
|
106
|
+
* {@link WEBFETCH_SUMMARY_GUIDELINES} so that block stays the fixed block it is documented to
|
|
107
107
|
* be. Interpolated BEFORE it, so the CC block remains the prompt's fixed tail.
|
|
108
108
|
*
|
|
109
109
|
* Two failure modes observed in the field, both of which produce a confident, well-formed, wrong answer:
|