@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
|
@@ -178,11 +178,27 @@ export const SAFETY_MERGE_CONFORMANCE_CORPUS = [
|
|
|
178
178
|
{
|
|
179
179
|
name: "inert-deny-entry-removed-safe",
|
|
180
180
|
intent: "removing a deny entry the grammar reads that names nothing (a wildcard peer, a `__` name with no protocol prefix) relaxes nothing — the comparison reads the EFFECTIVE entries on both sides",
|
|
181
|
-
prior: { toolDeny: ["Bash", "
|
|
181
|
+
prior: { toolDeny: ["Bash", "mcp__git*", "github__x"] },
|
|
182
182
|
next: { toolDeny: ["Bash"] },
|
|
183
183
|
loosens: false,
|
|
184
184
|
reasons: [],
|
|
185
185
|
},
|
|
186
|
+
{
|
|
187
|
+
name: "whole-protocol-deny-removed-loosened",
|
|
188
|
+
intent: "`mcp__*` and `mcp__*__*` in a deny list name every tool of every MCP server: removing either lifts a real deny, unlike a wildcard in another peer segment (which names nothing)",
|
|
189
|
+
prior: { toolDeny: ["Bash", "mcp__*"] },
|
|
190
|
+
next: { toolDeny: ["Bash"] },
|
|
191
|
+
loosens: true,
|
|
192
|
+
reasons: ['removed toolDeny "mcp__*"'],
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
name: "whole-protocol-deny-both-spellings-removed-loosened",
|
|
196
|
+
intent: "each whole-protocol spelling is its own deny entry: dropping one while keeping the other still removes an entry the base layer wrote",
|
|
197
|
+
prior: { toolDeny: ["mcp__*", "mcp__*__*"] },
|
|
198
|
+
next: { toolDeny: ["mcp__*"] },
|
|
199
|
+
loosens: true,
|
|
200
|
+
reasons: ['removed toolDeny "mcp__*__*"'],
|
|
201
|
+
},
|
|
186
202
|
{
|
|
187
203
|
name: "unreadable-deny-prior-loosened",
|
|
188
204
|
intent: "rules whose toolDeny holds an entry no rule grammar reads (an empty entry) cannot be read and refuse every call — an override that can be read loosens them",
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The conservative value-sameness proof the park mint reads when it decides whether a fidelity projection
|
|
3
|
+
* moved a value, and whether a policy's rewrite names the very value about to be filed. A leaf: no imports.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* CONSERVATIVE "these two are provably the same value" for deciding whether a
|
|
7
|
+
* {@link import("./checkpoint-store.js").encodeAtFidelity} projection moved anything, and whether a policy's
|
|
8
|
+
* rewrite names the very value about to be filed.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately NOT the binding hash, which is the wrong instrument for this question in two directions:
|
|
11
|
+
* it folds `-0` onto `0` (a real projection change the policy may care about, invisible to the hash), and
|
|
12
|
+
* it is a digest, so a collision would read as sameness. `Object.is` at the leaves keeps the `-0`
|
|
13
|
+
* distinction; comparing own-key SETS keeps the dropped `undefined`-valued key visible.
|
|
14
|
+
*
|
|
15
|
+
* Conservative on purpose — the answer it must never give wrongly is TRUE, because both callers read
|
|
16
|
+
* TRUE as "nothing moved / the policy named this very value" and act by filing. So sameness has to be
|
|
17
|
+
* PROVED, not merely un-disproved:
|
|
18
|
+
* - the PROTOTYPES must match and be the plain-object or array one. `[object Object]` is not proof of
|
|
19
|
+
* a plain object — a class instance and a null-prototype object both report it, and a tool executing
|
|
20
|
+
* the arguments can observe inherited behaviour. (Neither input to the projection comparison can be
|
|
21
|
+
* such a value: `structuredClone` and `JSON.parse` both produce plain data. A policy's rewrite can.)
|
|
22
|
+
* - own keys are compared with `Reflect.ownKeys` and POSITIONALLY, so a SYMBOL key or a non-enumerable
|
|
23
|
+
* property on one side is a difference rather than an invisible extra, and so is a different order
|
|
24
|
+
* (which `Object.keys`, `JSON.stringify` and any tool iterating its arguments can see).
|
|
25
|
+
* - properties are compared through their DESCRIPTORS — every flag, so a frozen object is not the
|
|
26
|
+
* mutable value a JSON decode produces — and an accessor on either side answers FALSE without being
|
|
27
|
+
* read: an approval decision must not be made by running deployment code, and what a getter returns
|
|
28
|
+
* need not be the same twice.
|
|
29
|
+
* - reference TOPOLOGY counts: two properties that share one object are not two properties holding
|
|
30
|
+
* equal objects, and a JSON round trip is precisely what turns the first into the second.
|
|
31
|
+
* - what it CANNOT prove on its own is that the value it inspected answers ordinary reads the way its
|
|
32
|
+
* descriptors did — a Proxy reports the target's descriptors and can return anything from a `get`.
|
|
33
|
+
* A caller comparing a value it did not construct must first establish that it is an inert data
|
|
34
|
+
* graph (the capture clone does exactly that, and refuses a Proxy outright).
|
|
35
|
+
* - any brand outside plain object/array that is not already reference-identical answers FALSE (a Date
|
|
36
|
+
* is never the string a JSON codec leaves behind, a Map is never the `{}`), and so does any
|
|
37
|
+
* inspection that throws.
|
|
38
|
+
* An uncertain answer therefore costs a policy consultation or a park, never a silently filed value.
|
|
39
|
+
*/
|
|
40
|
+
export declare function samePlainValue(a: unknown, b: unknown): boolean;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const MAX_SAME_VALUE_DEPTH = 256;
|
|
2
|
+
export function samePlainValue(a, b) {
|
|
3
|
+
return sameValueAt(a, b, 0, new Map(), new Map());
|
|
4
|
+
}
|
|
5
|
+
function sameValueAt(a, b, depth, aToB, bToA) {
|
|
6
|
+
if (Object.is(a, b))
|
|
7
|
+
return true;
|
|
8
|
+
if (depth >= MAX_SAME_VALUE_DEPTH)
|
|
9
|
+
return false;
|
|
10
|
+
if (a === null || b === null || typeof a !== "object" || typeof b !== "object")
|
|
11
|
+
return false;
|
|
12
|
+
try {
|
|
13
|
+
const pairedWithA = aToB.get(a);
|
|
14
|
+
const pairedWithB = bToA.get(b);
|
|
15
|
+
if (pairedWithA !== undefined || pairedWithB !== undefined)
|
|
16
|
+
return pairedWithA === b && pairedWithB === a;
|
|
17
|
+
aToB.set(a, b);
|
|
18
|
+
bToA.set(b, a);
|
|
19
|
+
const proto = Object.getPrototypeOf(a);
|
|
20
|
+
if (proto !== Object.getPrototypeOf(b))
|
|
21
|
+
return false;
|
|
22
|
+
if (proto !== Object.prototype && proto !== Array.prototype)
|
|
23
|
+
return false;
|
|
24
|
+
if (Object.isExtensible(a) !== Object.isExtensible(b))
|
|
25
|
+
return false;
|
|
26
|
+
const ka = Reflect.ownKeys(a);
|
|
27
|
+
const kb = Reflect.ownKeys(b);
|
|
28
|
+
if (ka.length !== kb.length)
|
|
29
|
+
return false;
|
|
30
|
+
for (const [i, k] of ka.entries()) {
|
|
31
|
+
if (k !== kb[i])
|
|
32
|
+
return false;
|
|
33
|
+
const da = Object.getOwnPropertyDescriptor(a, k);
|
|
34
|
+
const db = Object.getOwnPropertyDescriptor(b, k);
|
|
35
|
+
if (da === undefined || db === undefined)
|
|
36
|
+
return false;
|
|
37
|
+
if (!("value" in da) || !("value" in db))
|
|
38
|
+
return false;
|
|
39
|
+
if (da.enumerable !== db.enumerable || da.writable !== db.writable || da.configurable !== db.configurable)
|
|
40
|
+
return false;
|
|
41
|
+
if (!sameValueAt(da.value, db.value, depth + 1, aToB, bToA))
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
package/dist/core/scheduler.d.ts
CHANGED
|
@@ -111,7 +111,7 @@ export interface ScheduledTaskSummary {
|
|
|
111
111
|
/** 下次触发的 epoch ms(cron/at 可算;daemon 提供)。 */
|
|
112
112
|
nextRunMs?: number;
|
|
113
113
|
/** 执行形态回显({@link ScheduledIntent.mode})。ScheduleWakeup 的 stop:true 靠它定位要取消的 pending
|
|
114
|
-
* wakeup(cron/task 意图不受 stop
|
|
114
|
+
* wakeup(cron/task 意图不受 stop 影响)。老 backend 不回 = undefined(工具壳以
|
|
115
115
|
* label 兜底过滤)。 */
|
|
116
116
|
mode?: "task" | "session-wakeup";
|
|
117
117
|
/** [c209-D2]:生命周期层级回显({@link ScheduledIntent.lifetime})——缺了它,任务创建后就再无
|
|
@@ -23,7 +23,7 @@ import type { ToolPolicy } from "./tool-policy.js";
|
|
|
23
23
|
export declare function agentConfigDenyPatterns(): readonly string[];
|
|
24
24
|
/**
|
|
25
25
|
* RECOMMENDED default pattern set for {@link createSensitivePathPolicy} (additive export).
|
|
26
|
-
* NO upstream
|
|
26
|
+
* NO upstream anchor exists (the anchor set carries no sensitive/dangerous file-pattern
|
|
27
27
|
* material), so this is an ENGINEERING-CONSENSUS set — each line states its tradeoff. The factory's
|
|
28
28
|
* default behavior is unchanged (no implicit default list; wiring this set is the caller's opt-in:
|
|
29
29
|
* `createSensitivePathPolicy({ patterns: RECOMMENDED_SENSITIVE_PATTERNS, … })`).
|
|
@@ -134,7 +134,7 @@ export function createSensitivePathPolicy(opts) {
|
|
|
134
134
|
const fold = CASE_INSENSITIVE_FS ? "ascii" : "none";
|
|
135
135
|
const lower = (segs) => (CASE_INSENSITIVE_FS ? segs.map((seg) => seg.replace(/[A-Z]/g, (c) => c.toLowerCase())) : segs);
|
|
136
136
|
const anchors = [configRoot, ...(env === undefined ? [] : await canonicalDataRootKeys(env, [configRoot], signal))].map((root) => lower(agentConfigDirSegments(root)));
|
|
137
|
-
return configRows.map(({ raw, tail }) => ({ ...(compileSegmentPattern(tail, fold) ?? { raw, segments: [],
|
|
137
|
+
return configRows.map(({ raw, tail }) => ({ ...(compileSegmentPattern(tail, fold) ?? { raw, segments: [], fold }), raw, anchors, rootedOnly: true }));
|
|
138
138
|
};
|
|
139
139
|
const rowsOf = async (env, signal) => [...guardRows, ...(await configTwins(env, signal)).map(rowOf)];
|
|
140
140
|
const unstampedRoots = Object.freeze(dataRootSpellings(undefined));
|
|
@@ -8,10 +8,12 @@
|
|
|
8
8
|
* must match this InMemory one byte-for-byte — a cross-backend equivalence test is the contract).
|
|
9
9
|
*
|
|
10
10
|
* Safety model:
|
|
11
|
-
* - **tighten-only
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* - **tighten-only below what an operator wrote**: a NORMAL write may not loosen the row's operator part
|
|
12
|
+
* ({@link StoredSessionRules.operatorRules}: what the last operator write set; absent, the whole row) — above it, it
|
|
13
|
+
* may take back what normal writes added (a deny, its own allowlist or allowDirs narrowing). The one `putRules` is
|
|
14
|
+
* the write port and the delete port alike: a rule leaves every gate that reads the row when the row stops holding it.
|
|
15
|
+
* core has NO role system — `operator` is a boolean the caller FREEZES from a verified principal (mirrors
|
|
16
|
+
* `steer.trusted`); core never adjudicates operator-ness, it only honors the flag.
|
|
15
17
|
* - **CAS rev** (optimistic concurrency): a `putRules` with a stale `expectedRev` is rejected, so two replicas
|
|
16
18
|
* can't lose an update (mirrors the checkpoint store's `resolve` OCC).
|
|
17
19
|
* - **one grammar**: the two rule buckets hold rule ENTRIES — the grammar every entry list reads, through its one reader
|
|
@@ -60,10 +62,25 @@ export type SessionRuleEntryField = {
|
|
|
60
62
|
* `*`, one more name no tool carried, which voided nothing beside it;
|
|
61
63
|
* - 1, the one entry reader taking its tool name from the lenient rule parser (trimmed before a `(`, any character but a
|
|
62
64
|
* blank, a parenthesis or a control / format character);
|
|
63
|
-
* - 2, the rule syntax's tool-name head (`ruleSpellingOf`): a name is read as written, in the characters names are minted in
|
|
65
|
+
* - 2, the rule syntax's tool-name head (`ruleSpellingOf`): a name is read as written, in the characters names are minted in;
|
|
66
|
+
* - 3, the whole-protocol names (`mcp__*`, `mcp__*__*`, see `wholeProtocolOf`) read as a deny rule in `toolDeny` — every tool of the
|
|
67
|
+
* protocol — where grammar 2 read them as an entry that names nothing. An engine of grammar 2 given a row written in grammar 3
|
|
68
|
+
* refuses it ({@link grammarOf}) rather than read the deny as nothing;
|
|
69
|
+
* - 4, the delegation tool's type rules (`Agent(<subagent_type>)`) read as a rule on the agent type the call runs — where grammar 3
|
|
70
|
+
* read them as an entry with no rule form (and its write judge refused one) — and a Bash pattern (`Bash(git * main)`, a star
|
|
71
|
+
* anywhere but the two trailing markers) reads as the `pattern` match form — where grammar 3 had no form for it — so an engine of
|
|
72
|
+
* grammar 3 given a row written in grammar 4 refuses it rather than read an `Agent(…)` or `Bash(<pattern>)` deny as nothing.
|
|
64
73
|
* An entry this grammar reads as no rule in a row an earlier grammar wrote reads as `earlier_grammar` ({@link compileSessionRuleBucket}).
|
|
74
|
+
*
|
|
75
|
+
* The persisted rule store stamps the same number on each bucket it writes (and the rule-sync wire on each state it sends):
|
|
76
|
+
* a stored rule's text is a `Tool(content)` entry read by the same parser, so every revision of what such a text means is a
|
|
77
|
+
* revision counted here. A revision that touches only the entry list (a tool-name head, a protocol name) moves the persisted
|
|
78
|
+
* stamp too, and an engine before it then refuses a bucket it could have read — the refusing side. The persisted store keeps
|
|
79
|
+
* no earlier reading: its rows are read in this grammar whatever stamp at or below it they carry, so a revision that changes
|
|
80
|
+
* what an existing persisted rule text means owes that store a reading of its earlier stamps, as {@link earlierGrammarReads}
|
|
81
|
+
* is for entries. Every stamp is judged by {@link readRuleGrammarStamp}.
|
|
65
82
|
*/
|
|
66
|
-
export declare const SESSION_RULES_GRAMMAR =
|
|
83
|
+
export declare const SESSION_RULES_GRAMMAR = 4;
|
|
67
84
|
/** {@link SessionPermissionRules} plus the monotonic `rev` the store stamps (the OCC key). */
|
|
68
85
|
export interface StoredSessionRules extends SessionPermissionRules {
|
|
69
86
|
rev: number;
|
|
@@ -75,18 +92,31 @@ export interface StoredSessionRules extends SessionPermissionRules {
|
|
|
75
92
|
/** The rule grammar the row's entries are read in ({@link SESSION_RULES_GRAMMAR}), stamped by the write judge. Absent =
|
|
76
93
|
* a row stored before the stamp: grammar 0. */
|
|
77
94
|
grammar?: number;
|
|
95
|
+
/** The row's OPERATOR PART: the buckets (and their grammar) the last operator write set — the line a non-operator write
|
|
96
|
+
* may not loosen ({@link judgeSessionRulesWrite}). Minted by the write judge alone, and present only once a non-operator
|
|
97
|
+
* write stamped the row (it carries the part it was judged against; over no row, the part of the value it wrote when that
|
|
98
|
+
* value is a stored row — a rev from 1 — else an empty part). ABSENT = the whole row is the operator's: an operator write, and a row stored before
|
|
99
|
+
* the member, read fail-closed. Never enforced itself — the row's buckets are what every gate reads. */
|
|
100
|
+
operatorRules?: SessionPermissionRules & {
|
|
101
|
+
grammar: number;
|
|
102
|
+
};
|
|
78
103
|
}
|
|
79
|
-
/** A rules value as the shape reading hands it on ({@link readSessionRulesShape}): its buckets,
|
|
80
|
-
* are read in — resolved, so a store that serves it on beside its own counters serves the row's grammar with it
|
|
104
|
+
/** A rules value as the shape reading hands it on ({@link readSessionRulesShape}): its buckets, the grammar its entries
|
|
105
|
+
* are read in — resolved, so a store that serves it on beside its own counters serves the row's grammar with it — and the
|
|
106
|
+
* row's operator part when it carries one ({@link StoredSessionRules.operatorRules}). */
|
|
81
107
|
export type SessionRulesInGrammar = SessionPermissionRules & {
|
|
82
108
|
grammar: number;
|
|
109
|
+
operatorRules?: SessionPermissionRules & {
|
|
110
|
+
grammar: number;
|
|
111
|
+
};
|
|
83
112
|
};
|
|
84
113
|
/** Options for {@link SessionPolicyStore.putRules}. */
|
|
85
114
|
export interface PutRulesOptions {
|
|
86
115
|
/** CAS: reject the write if the stored `rev` is not this (optimistic concurrency). Omit to skip the check. */
|
|
87
116
|
expectedRev?: number;
|
|
88
|
-
/** When true, this write MAY loosen the rules (remove a deny / widen an allowlist or allowDirs)
|
|
89
|
-
* (non-operator) write
|
|
117
|
+
/** When true, this write MAY loosen the rules (remove a deny / widen an allowlist or allowDirs), and what it writes is
|
|
118
|
+
* the operator's whole. A NORMAL (non-operator) write may not loosen the row's operator part
|
|
119
|
+
* ({@link StoredSessionRules.operatorRules}). core does NOT verify operator-ness — the caller (service) FREEZES
|
|
90
120
|
* this from a verified, role-checked principal (mirrors `steer.trusted`). */
|
|
91
121
|
operator?: boolean;
|
|
92
122
|
}
|
|
@@ -105,7 +135,7 @@ export interface SessionRuleEntryRefusal extends AllowEntryInertDetail {
|
|
|
105
135
|
reason: AllowEntryInertReason;
|
|
106
136
|
}
|
|
107
137
|
/** Typed error from {@link SessionPolicyStore.putRules}. `conflict` = stale `expectedRev`; `loosen_forbidden`
|
|
108
|
-
* = a non-operator write tried to relax
|
|
138
|
+
* = a non-operator write tried to relax what an operator wrote; `corrupt` = a backend could not read what it stored (a row, or the
|
|
109
139
|
* erase-surviving rev mark of {@link SessionPolicyStore.deleteBySession}) and refuses rather than read it as fewer rules or
|
|
110
140
|
* stamp an unproven rev; `invalid_shape` = the rules value is not an object of buckets, each a list of strings
|
|
111
141
|
* ({@link readSessionRulesShape}); `inert_entry` = a bucket holds an entry the entry reader reads as nothing. `detail` is
|
|
@@ -142,8 +172,9 @@ export interface SessionRulesRecord {
|
|
|
142
172
|
export interface SessionPolicyStore {
|
|
143
173
|
getRules(sessionId: string, principal?: string): Promise<StoredSessionRules | null>;
|
|
144
174
|
/** Write the rules for a key through the one write judge ({@link judgeSessionRulesWrite}): CAS on `expectedRev`, the
|
|
145
|
-
* shape, every entry's reading (operator writes included), then, for a non-operator write
|
|
146
|
-
*
|
|
175
|
+
* shape, every entry's reading (operator writes included), then, for a non-operator write, the check against the row's
|
|
176
|
+
* operator part — each refusal a {@link SessionPolicyError}, and nothing is written. The same call is the delete port: a
|
|
177
|
+
* value without an entry takes it out of every gate that reads the row. */
|
|
147
178
|
putRules(sessionId: string, principal: string | undefined, rules: SessionPermissionRules, opts?: PutRulesOptions): Promise<StoredSessionRules>;
|
|
148
179
|
/**
|
|
149
180
|
* 2c session-sync: every (principal, rules) record for `sessionId` across ALL principals — `getRules`
|
|
@@ -193,13 +224,33 @@ export interface SessionPolicyStore {
|
|
|
193
224
|
* backend should keep `allowDirs` to real directories; a future symlink-aware write-time canonicalize closes it.
|
|
194
225
|
*/
|
|
195
226
|
declare function lexWithin(root: string, p: string): boolean;
|
|
227
|
+
/**
|
|
228
|
+
* THE ONE JUDGE of a rule grammar stamp, whichever store carries it — a session-rules row ({@link readSessionRulesShape}),
|
|
229
|
+
* the persisted rule store's bucket and the rule-sync wire: the grammar the stamped rules are read in, or the fault that
|
|
230
|
+
* makes them unreadable. `absent` is what a missing stamp reads as (each store says what its unstamped rules were written
|
|
231
|
+
* in). A stamp is a whole number no greater than {@link SESSION_RULES_GRAMMAR}: a later grammar is one this engine cannot
|
|
232
|
+
* read the rules in, and reading them in an older one could grant what their writer refused or drop a refusal it cannot
|
|
233
|
+
* name — so they are refused WHOLE (`later`), never read in part. `rules` names the stamped rules in the sentence, `held`
|
|
234
|
+
* what they hold (`entries`, `rows`).
|
|
235
|
+
*/
|
|
236
|
+
export declare function readRuleGrammarStamp(stamp: unknown, absent: number, words: {
|
|
237
|
+
readonly rules: string;
|
|
238
|
+
readonly held: string;
|
|
239
|
+
}): {
|
|
240
|
+
grammar: number;
|
|
241
|
+
} | {
|
|
242
|
+
got: string;
|
|
243
|
+
sentence: string;
|
|
244
|
+
later?: true;
|
|
245
|
+
};
|
|
196
246
|
/**
|
|
197
247
|
* THE ONE SHAPE READING of a rules value — what every station that takes one reads it through: the write (incoming rules),
|
|
198
248
|
* a store's read-back of its own rows, the tighten comparison's prior, the run-time layer's served row. A rules value is an
|
|
199
249
|
* object whose keys are buckets ({@link SessionPermissionRules}); each bucket present is a list of strings (`allowDirs`: of
|
|
200
250
|
* non-blank strings — a directory is no blank). A bucket's TYPE is all this reads: what an entry means is the entry reader's,
|
|
201
251
|
* in the grammar the value is written in ({@link grammarOf}), handed on as `grammar`. The store's counters (`rev`, `gen`) are
|
|
202
|
-
* passed over,
|
|
252
|
+
* passed over, the row's operator part is read as rules of its own and handed on ({@link readOperatorPart}), and a key
|
|
253
|
+
* holding `undefined` holds nothing. Anything else is a fault, named by key and by TYPE, never by value —
|
|
203
254
|
* a bare string is never one rule and never its characters (`"rm"` spread into `["r","m"]`), and a key outside the buckets is
|
|
204
255
|
* never dropped (a dropped deny is a deny nobody enforces).
|
|
205
256
|
*/
|
|
@@ -277,14 +328,18 @@ export declare function earlierGrammarAnnouncer(sink: ((entries: readonly string
|
|
|
277
328
|
* the rules to stamp, or a {@link SessionPolicyError}, in this order — `conflict` (a stale `expectedRev` against `prior`'s rev),
|
|
278
329
|
* `invalid_shape` ({@link normalizeRules}), `inert_entry` (an entry that reads as nothing in the grammar the rules are written
|
|
279
330
|
* in; operator writes included — a rule that names nothing guards nothing whoever writes it), then, for a non-operator write
|
|
280
|
-
* over
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
331
|
+
* over a row, `loosen_forbidden` ({@link loosenReasons}) against the row's OPERATOR PART ({@link StoredSessionRules.operatorRules};
|
|
332
|
+
* absent, the whole row) — or `corrupt` when that prior cannot be read as rules, which the comparison never reads as fewer.
|
|
333
|
+
* Over no row there is no rev to compare and no tighten gate, and a judge called with `prior = null` (a host's pre-read of a
|
|
334
|
+
* value's shape and entries) answers only those two content refusals. Below what an operator wrote nothing moves; above it,
|
|
335
|
+
* a non-operator takes back what non-operator writes added. The
|
|
336
|
+
* rules to stamp carry `grammar` = {@link SESSION_RULES_GRAMMAR} — what passed the judge means the same in this engine's
|
|
337
|
+
* grammar — and, from a non-operator write, the operator part it was judged against: over no row, the value's own when it is a
|
|
338
|
+
* stored row handed in ({@link isStoredRow}), else an empty one (an operator write's whole value is the operator's, so it
|
|
339
|
+
* carries none). THIS is the one place both stamps are minted, so every store that stores what the judge
|
|
340
|
+
* returns keeps them. `mountedToolNames` = the store's declaration ({@link SessionPolicyStoreOptions.mountedToolNames}).
|
|
284
341
|
*/
|
|
285
|
-
export declare function judgeSessionRulesWrite(prior: StoredSessionRules | null, rules: unknown, opts: PutRulesOptions | undefined, mountedToolNames?: ReadonlySet<string>):
|
|
286
|
-
grammar: number;
|
|
287
|
-
};
|
|
342
|
+
export declare function judgeSessionRulesWrite(prior: StoredSessionRules | null, rules: unknown, opts: PutRulesOptions | undefined, mountedToolNames?: ReadonlySet<string>): SessionRulesInGrammar;
|
|
288
343
|
/**
|
|
289
344
|
* Pure tighten-only diff: the reasons `next` LOOSENS `prior` (empty ⇒ `next` is a pure tightening or no-op), over the EFFECTIVE
|
|
290
345
|
* entries of each rule bucket — the list as the run-time layer enforces it ({@link effectiveEntries}). Rules whose toolDeny holds
|
|
@@ -321,7 +376,7 @@ export declare function continuesLineage(a: {
|
|
|
321
376
|
}): boolean;
|
|
322
377
|
/**
|
|
323
378
|
* In-process default {@link SessionPolicyStore} (single-replica). A deployment that needs cross-replica
|
|
324
|
-
* durability supplies its own backend with the SAME CAS-rev +
|
|
379
|
+
* durability supplies its own backend with the SAME CAS-rev + write-judge semantics. Single-threaded JS makes
|
|
325
380
|
* the read-check-write trivially atomic here; a durable backend folds it into a CAS WHERE clause.
|
|
326
381
|
*/
|
|
327
382
|
export declare class InMemorySessionPolicyStore implements SessionPolicyStore {
|
|
@@ -9,7 +9,8 @@ const SESSION_RULE_BUCKETS = { toolAllow: "allow", toolDeny: "deny", allowDirs:
|
|
|
9
9
|
const BUCKETS = Object.keys(SESSION_RULE_BUCKETS);
|
|
10
10
|
const ENTRY_FIELDS = BUCKETS.filter((f) => SESSION_RULE_BUCKETS[f] !== "dirs");
|
|
11
11
|
const STORE_STAMPS = new Set(["rev", "gen", "grammar"]);
|
|
12
|
-
|
|
12
|
+
const OPERATOR_PART = "operatorRules";
|
|
13
|
+
export const SESSION_RULES_GRAMMAR = 4;
|
|
13
14
|
export class SessionPolicyError extends Error {
|
|
14
15
|
code;
|
|
15
16
|
detail;
|
|
@@ -53,18 +54,26 @@ function lexWithin(root, p) {
|
|
|
53
54
|
return true;
|
|
54
55
|
return np === nr || np.startsWith(nr + "/");
|
|
55
56
|
}
|
|
57
|
+
function isStoredRow(value) {
|
|
58
|
+
const rev = value.rev;
|
|
59
|
+
return typeof rev === "number" && Number.isInteger(rev) && rev >= 1;
|
|
60
|
+
}
|
|
56
61
|
function grammarOf(value) {
|
|
57
62
|
const stamp = value.grammar;
|
|
63
|
+
return readRuleGrammarStamp(stamp, stamp === undefined && isStoredRow(value) ? 0 : SESSION_RULES_GRAMMAR, { rules: "session rules", held: "entries" });
|
|
64
|
+
}
|
|
65
|
+
export function readRuleGrammarStamp(stamp, absent, words) {
|
|
58
66
|
if (stamp === undefined)
|
|
59
|
-
return { grammar:
|
|
67
|
+
return { grammar: absent };
|
|
60
68
|
if (typeof stamp !== "number" || !Number.isInteger(stamp) || stamp < 0) {
|
|
61
69
|
const got = typeof stamp === "number" ? "a number that is not a whole number of 0 or more" : valueTypeLabel(stamp);
|
|
62
|
-
return { got, sentence:
|
|
70
|
+
return { got, sentence: `${words.rules} carry a grammar stamp that is ${got} — the stamp is the whole number of the rule grammar the rules were written in (this engine reads grammar ${SESSION_RULES_GRAMMAR})` };
|
|
63
71
|
}
|
|
64
72
|
if (stamp > SESSION_RULES_GRAMMAR) {
|
|
65
73
|
return {
|
|
66
74
|
got: `${stamp}, a grammar newer than this engine's (${SESSION_RULES_GRAMMAR})`,
|
|
67
|
-
sentence:
|
|
75
|
+
sentence: `${words.rules} were written in rule grammar ${stamp}, newer than this engine reads (grammar ${SESSION_RULES_GRAMMAR}) — refusing rather than read their ${words.held} in an older grammar; an engine that reads grammar ${stamp} reads them`,
|
|
76
|
+
later: true,
|
|
68
77
|
};
|
|
69
78
|
}
|
|
70
79
|
return { grammar: stamp };
|
|
@@ -82,6 +91,13 @@ export function readSessionRulesShape(value) {
|
|
|
82
91
|
for (const [key, v] of Object.entries(value)) {
|
|
83
92
|
if (STORE_STAMPS.has(key) || v === undefined)
|
|
84
93
|
continue;
|
|
94
|
+
if (key === OPERATOR_PART) {
|
|
95
|
+
const part = readOperatorPart(v);
|
|
96
|
+
if ("fault" in part)
|
|
97
|
+
return part;
|
|
98
|
+
rules.operatorRules = part.rules;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
85
101
|
if (!Object.hasOwn(SESSION_RULE_BUCKETS, key)) {
|
|
86
102
|
return fault(key, "not a rule bucket", `session rules hold ${JSON.stringify(key)}, which is not a rule bucket — the buckets are ${BUCKETS.join(", ")}, and a shell command rule is a toolDeny / toolAllow entry written Bash(<command>) (Bash(rm:*) matches a command whose first word is rm)`);
|
|
87
103
|
}
|
|
@@ -100,6 +116,20 @@ export function readSessionRulesShape(value) {
|
|
|
100
116
|
}
|
|
101
117
|
return { rules };
|
|
102
118
|
}
|
|
119
|
+
function readOperatorPart(value) {
|
|
120
|
+
const read = readSessionRulesShape(value);
|
|
121
|
+
if ("fault" in read) {
|
|
122
|
+
const field = read.fault.field === "" ? OPERATOR_PART : `${OPERATOR_PART}.${read.fault.field}`;
|
|
123
|
+
return { fault: { field, got: read.fault.got }, sentence: `the session rules' operator part: ${read.sentence}` };
|
|
124
|
+
}
|
|
125
|
+
const { operatorRules: nested, ...part } = read.rules;
|
|
126
|
+
const unstamped = value.grammar === undefined;
|
|
127
|
+
if (unstamped || nested !== undefined) {
|
|
128
|
+
const got = unstamped ? "rules without a grammar stamp" : "an operator part of its own";
|
|
129
|
+
return { fault: { field: OPERATOR_PART, got }, sentence: `session rules carry an operator part holding ${got} — the part is the rules the last operator write set, stamped with their grammar by the write judge` };
|
|
130
|
+
}
|
|
131
|
+
return { rules: part };
|
|
132
|
+
}
|
|
103
133
|
export function normalizeRules(rules) {
|
|
104
134
|
return canonicalRules(shapeOrRefuse(rules));
|
|
105
135
|
}
|
|
@@ -284,17 +314,29 @@ export function judgeSessionRulesWrite(prior, rules, opts, mountedToolNames = NO
|
|
|
284
314
|
const read = shapeOrRefuse(rules);
|
|
285
315
|
const clean = canonicalRules(read);
|
|
286
316
|
assertEntriesRead(read, mountedToolNames);
|
|
287
|
-
if (
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
}
|
|
317
|
+
if (opts?.operator === true)
|
|
318
|
+
return { ...clean, grammar: SESSION_RULES_GRAMMAR };
|
|
319
|
+
if (prior === null) {
|
|
320
|
+
return { ...clean, grammar: SESSION_RULES_GRAMMAR, operatorRules: isStoredRow(rules) ? operatorPartOf(read) : { grammar: SESSION_RULES_GRAMMAR } };
|
|
321
|
+
}
|
|
322
|
+
const operatorRules = operatorPartOf(readStoredOrRefuse(prior));
|
|
323
|
+
const loosens = loosenReasons(operatorRules, clean, mountedToolNames);
|
|
324
|
+
if (loosens.length > 0) {
|
|
325
|
+
throw new SessionPolicyError("loosen_forbidden", `a non-operator session-rule write may not loosen what an operator wrote; refused: ${loosens.join("; ")}`);
|
|
326
|
+
}
|
|
327
|
+
return { ...clean, grammar: SESSION_RULES_GRAMMAR, operatorRules };
|
|
328
|
+
}
|
|
329
|
+
function operatorPartOf(read) {
|
|
330
|
+
const { operatorRules, ...whole } = read;
|
|
331
|
+
const part = operatorRules ?? whole;
|
|
332
|
+
return { ...canonicalRules(part), grammar: part.grammar };
|
|
333
|
+
}
|
|
334
|
+
function readStoredOrRefuse(prior) {
|
|
335
|
+
const stored = readSessionRulesShape(prior);
|
|
336
|
+
if ("fault" in stored) {
|
|
337
|
+
throw new SessionPolicyError("corrupt", `the stored session rules cannot be read as rules (${stored.sentence}) — refusing to judge a non-operator write against them as fewer rules; an operator write replaces them`);
|
|
296
338
|
}
|
|
297
|
-
return
|
|
339
|
+
return stored.rules;
|
|
298
340
|
}
|
|
299
341
|
export function loosenReasons(priorValue, nextValue, mountedToolNames = NO_DECLARED_TOOLS) {
|
|
300
342
|
const shapeOf = (side, value) => {
|
|
@@ -92,13 +92,13 @@ export interface ReconcileReport {
|
|
|
92
92
|
*/
|
|
93
93
|
export declare function findOrphanToolCalls(messages: AgentMessage[], suspendedBatch?: ReadonlySet<string>): OrphanToolCall[];
|
|
94
94
|
/**
|
|
95
|
-
* backlog #389 伴生 (D-2) —
|
|
95
|
+
* backlog #389 伴生 (D-2) — the reference's interruption markers, as is (
|
|
96
96
|
* minted as a USER message by `Jce` @ `CC:640141-640154`). CC mints one on every abort whose reason is
|
|
97
97
|
* outside `{"interrupt","refusal-fallback-edit"}` — and the interactive Esc / remote cancel, which is
|
|
98
98
|
* what `TaskStream.interrupt()` corresponds to, is precisely on the minting side (`CC:1033698-1033733`).
|
|
99
99
|
* The suppressed reason is the one case where the user's own replacement message is already the context.
|
|
100
100
|
*
|
|
101
|
-
* Taken
|
|
101
|
+
* Taken as is rather than reworded: this string is an INPUT to later reasoning in CC (its own
|
|
102
102
|
* "interrupted then immediately retried the same action" rule reads it back), and the constitution's
|
|
103
103
|
* standing rule is that a question CC has answered is answered in CC's form.
|
|
104
104
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type SessionPlacementRecord, type SessionRepo } from "../internal/harness.js";
|
|
1
|
+
import { type Session, type SessionHead, type SessionPlacementRecord, type SessionRepo } from "../internal/harness.js";
|
|
2
2
|
import { type AcquiredSession, type PlacedSessionRow, type SessionPlacement, type SessionStore, type SessionStoreSummary } from "./session.js";
|
|
3
3
|
import type { StoreDurability } from "./checkpoint-store.js";
|
|
4
4
|
import { SESSION_DEFAULT_TTL_DAYS } from "../config/defaults.js";
|
|
@@ -117,29 +117,27 @@ export declare class TtlSessionStore implements SessionStore {
|
|
|
117
117
|
olderThanMs?: number;
|
|
118
118
|
scope?: string;
|
|
119
119
|
}) => Promise<PlacedSessionRow[]>;
|
|
120
|
+
/** The by-id head read ({@link SessionStore.headOf}): the repo's own, verbatim — the row is the repo's, never this cache's, and a read
|
|
121
|
+
* racing a delete answers either generation (it never waits on one). Present only when the backing repo answers it (absence means no
|
|
122
|
+
* by-id head read, and so no ownership pair for an authorizer). */
|
|
123
|
+
readonly headOf?: (sessionId: string) => Promise<SessionHead | undefined>;
|
|
124
|
+
/** The repo's head read as this store's own decisions read the row through it (the cache check, the existence check), held
|
|
125
|
+
* privately so the store's reading of its rows is the repo's whatever a host does with the face. */
|
|
126
|
+
private readonly repoHead?;
|
|
120
127
|
private repo;
|
|
121
128
|
private entries;
|
|
122
|
-
/** Session-ownership rows (the multi-tenant admission capability face — see SessionStore.ownerOf).
|
|
123
|
-
* Deliberately NOT part of `entries`: an evicted-but-durable session (`forget` / evict:"forget")
|
|
124
|
-
* still EXISTS, and its ownership row outliving the cache entry is what keeps a live session from
|
|
125
|
-
* reading as `undefined` (= re-claimable by anyone). Rows die only when the repo's history does. */
|
|
126
|
-
private owners;
|
|
127
129
|
/** In-flight acquisitions keyed by id, so concurrent acquire(sameId) share one session. */
|
|
128
130
|
private pending;
|
|
129
|
-
/** Subagent transcript persistence — placed ids whose durable deletion FAILED: the
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* append fd pre-rmSync)
|
|
133
|
-
* file still exists (append → log_closed, transcript revival broken until restart). The entry is
|
|
134
|
-
* dropped instead, so a re-acquire replays a FRESH authority from disk; success clears the row. */
|
|
131
|
+
/** Subagent transcript persistence — placed ids whose durable deletion FAILED. Not a reading of placement: the row is that
|
|
132
|
+
* (see `rowIsPlaced`). It makes a later cold `release` read the row whatever the repo or the store's declaration, and it is never
|
|
133
|
+
* believed in the row's place: a read that faults deletes nothing. No cache entry is retained instead, because the repo may have torn down the shared session
|
|
134
|
+
* authority before its removal failed (the File repo closes the append fd pre-rmSync): a retained entry would serve a closed log. */
|
|
135
135
|
private pendingPlacedDeletes;
|
|
136
|
-
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
|
|
141
|
-
* the delete's own settlement (both outcomes release it). */
|
|
142
|
-
private deletingPlaced;
|
|
136
|
+
/** Releases (and idle-sweep deletes) IN FLIGHT that may delete the row: acquire and register — the two that resolve or write the row —
|
|
137
|
+
* await the settlement, because the repo's delete tears down the shared session authority mid-flight — an acquire racing the await window could capture (or rebuild
|
|
138
|
+
* and then lose) an authority the delete is about to close, and the caller would hold a session whose first append answers
|
|
139
|
+
* log_closed while the file still exists. The gate is per-id and bounded by the release's own settlement (both outcomes release it). */
|
|
140
|
+
private releasing;
|
|
143
141
|
/** Sessions pinned by a design/45 checkpoint — skipped by idle sweep until unpinned (B6/§5). */
|
|
144
142
|
private pinned;
|
|
145
143
|
private defaultTtlMs;
|
|
@@ -151,6 +149,10 @@ export declare class TtlSessionStore implements SessionStore {
|
|
|
151
149
|
requireExisting?: boolean;
|
|
152
150
|
placement?: SessionPlacement;
|
|
153
151
|
}): Promise<AcquiredSession>;
|
|
152
|
+
/** Whether a cached view is still the occupant the row holds: the row's head, read in one read, names the same occupant as the cached
|
|
153
|
+
* session (`compareOccupants` — unknown is never the same). Over a repo with no head read there is nothing to read the row with, and
|
|
154
|
+
* the view is served as it is. */
|
|
155
|
+
private cachedViewStands;
|
|
154
156
|
/** The placement admission ({@link admitSessionPlacement}) for this store, judged on every resolution path. The
|
|
155
157
|
* partition declaration is a getter over this store's live field, so it is read where the admission judges the
|
|
156
158
|
* mirror direction (after the request's own members, and only then) — never captured at construction. */
|
|
@@ -179,8 +181,34 @@ export declare class TtlSessionStore implements SessionStore {
|
|
|
179
181
|
* fork capability mounts (it was INERT before — the durable repo had `fork` but the store never exposed it).
|
|
180
182
|
*/
|
|
181
183
|
fork(sourceId: string, owner?: string | null): Promise<string | null>;
|
|
182
|
-
/** Drop a session from the live set. With a durable repo (`evict: "forget"`) the history is kept.
|
|
184
|
+
/** Drop a session from the live set. With a durable repo (`evict: "forget"`) the history is kept. A release that rejects leaves the
|
|
185
|
+
* session where it was: the store keeps no view of it and retries nothing on its own, and a placed row is found again by the
|
|
186
|
+
* partition-GC leg's `listPlaced` — except one whose header is damaged, which `listPlaced` skips and every release of it rejects
|
|
187
|
+
* (`corrupt_session`), so only manual cleanup removes it. */
|
|
183
188
|
release(sessionId: string): Promise<void>;
|
|
189
|
+
/** Run a release that may delete the row while it holds the id: the gate is set before the first await, after any release already in
|
|
190
|
+
* flight for the id, and `acquire` / `register` answer after it settles — no caller captures an authority the delete is about to tear
|
|
191
|
+
* down (the repo closes the shared authority before its removal can fail), or writes the row mid-decision. */
|
|
192
|
+
private holdingId;
|
|
193
|
+
/** The deciding half of {@link release}, under its gate. A delete goes through the cached view only while the row still stands for it
|
|
194
|
+
* (`cachedViewStands`); with no view, or a view of an occupant the row no longer holds (another writer deleted the row, or deleted and
|
|
195
|
+
* created it again), the row decides — its placement read cold ({@link rowIsPlaced}) — and an unplaced row nobody here holds is left
|
|
196
|
+
* as it is. Placement obligation 4: a placed row's release is a REAL deletion whatever the evict policy (the joint reap deletes the
|
|
197
|
+
* agent row first and then calls this to end the transcript; a forget would strand it). A delete runs only on a read that answered
|
|
198
|
+
* — the head read with the view still standing, or the row's own placement: a read that faults deletes nothing, and the release
|
|
199
|
+
* rejects with it. A placed release that fails (a read or the delete) leaves the tombstone, so the retry reads the row again —
|
|
200
|
+
* never a retained cache entry, which could serve a closed log; an unplaced view's release under `evict: "delete"` leaves nothing,
|
|
201
|
+
* so its retry after a failed read resolves and deletes nothing. */
|
|
202
|
+
private releaseRow;
|
|
203
|
+
/** The repo's placement probe, where it has one. */
|
|
204
|
+
private placementProbe;
|
|
205
|
+
/** Whether an uncached id's row is worth reading for its placement: through the probe on a store that declares placements, and by
|
|
206
|
+
* either means for an id whose placed deletion failed here. */
|
|
207
|
+
private rowReadMatters;
|
|
208
|
+
/** Whether the row standing under `sessionId` is placed: the repo's placement probe where it has one, else the row's own metadata,
|
|
209
|
+
* read where {@link rowReadMatters}. Its answer retires the tombstone. A read that FAULTS answers nothing: it rejects (the release
|
|
210
|
+
* deletes nothing and fails with it), and the tombstone stays for the next release to read the row again. */
|
|
211
|
+
private rowIsPlaced;
|
|
184
212
|
/** Drop only the cached view — the repo keeps the session regardless of `evictPolicy`, so a re-acquire
|
|
185
213
|
* re-opens the SAME history (B-17: the reconcile retry / prepare-throw paths must never delete). Cost
|
|
186
214
|
* on the default in-memory repo: ONE retained session object **per forgotten id** until process end
|
|
@@ -193,19 +221,41 @@ export declare class TtlSessionStore implements SessionStore {
|
|
|
193
221
|
pin(sessionId: string): void;
|
|
194
222
|
/** Release a design/45 pin (on resume or checkpoint expiry); the session resumes normal idle eviction. */
|
|
195
223
|
unpin(sessionId: string): void;
|
|
196
|
-
/**
|
|
197
|
-
*
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
* authorization decision — the authorizer re-reads {@link ownerOf} and judges there. */
|
|
224
|
+
/** The owner write of the ownership pair (see the SessionStore contract): an id with no row gets one — an ordinary row recording
|
|
225
|
+
* `owner` in its creating write, through the repo's create (the repo makes the creation first-write-wins); an id whose row exists is
|
|
226
|
+
* left exactly as it is, whatever this call carries. Makes no authorization decision — the authorizer re-reads {@link headOf}. The
|
|
227
|
+
* row is not cached here: it is resolved like any other row on the next `acquire`. */
|
|
201
228
|
register(sessionId: string, owner: string | null): Promise<void>;
|
|
202
|
-
/**
|
|
203
|
-
*
|
|
204
|
-
|
|
205
|
-
* `undefined`; any other repo failure rejects (a fault is not an answer). Never caches, never creates. */
|
|
206
|
-
incarnationOf(sessionId: string): Promise<string | undefined>;
|
|
229
|
+
/** Whether the repo holds a row for `sessionId` — its head read where it has one (no replay of the row's history), else an open. A
|
|
230
|
+
* fault rejects; it is not an answer. */
|
|
231
|
+
private hasRow;
|
|
207
232
|
/** Evict idle-expired sessions from the cache. Deletes durable history only when `evict: "delete"`. */
|
|
208
233
|
sweep(now?: number): void;
|
|
209
234
|
get size(): number;
|
|
210
235
|
dispose(): void;
|
|
211
236
|
}
|
|
237
|
+
/**
|
|
238
|
+
* design/110 (F4) — pick the fork point so a child does NOT inherit an in-flight (uncommitted) tool call.
|
|
239
|
+
*
|
|
240
|
+
* The agent loop commits the assistant turn (`message_end` → `appendMessage`) BEFORE it executes that turn's tool
|
|
241
|
+
* calls. So while the Fork tool's own `execute` runs, the source session's LEAF is the assistant message that carries
|
|
242
|
+
* the Fork tool-call (and any sibling parallel calls) with NO tool results behind it yet. Forking the whole log would
|
|
243
|
+
* copy that orphan call into the child, and the child's wake-time `reconcileInterruptedSession` would inject an
|
|
244
|
+
* `[INTERRUPTED]` result for it — polluting the inherited context ("I called Fork → it was interrupted").
|
|
245
|
+
*
|
|
246
|
+
* Detection: the latest assistant `message` on the leaf's chain (past the tool results behind it) has a `toolCall` block
|
|
247
|
+
* (the message shape — there is NO `toolCalls` field; tool calls are content blocks) that no tool result behind it answers —
|
|
248
|
+
* the loop's own reading of an open batch (`findUnansweredToolBatch`). When so, fork at the turn's PARENT (`position:"at"`
|
|
249
|
+
* includes the parent, excludes the assistant turn) — the correct fork semantics: "inherit my context up to, but not
|
|
250
|
+
* including, the spawn call". A settled leaf (a text-only turn, or a tool turn every call of which is answered), or an
|
|
251
|
+
* unsettled assistant that is somehow a root (no `parentId`, fail-safe), forks the whole log (`{}`).
|
|
252
|
+
*
|
|
253
|
+
* Exported at the package root: the bundled store's `fork` and any other store's `fork` are the same question and must give the same
|
|
254
|
+
* answer — a backend reads the source session (`SessionRepo.open`), asks this, and hands the answer to `SessionRepo.fork` with the id
|
|
255
|
+
* and owner it mints. Forking the whole log instead copies the in-flight turn. The walk is one of the parent-chain walks, so it takes the
|
|
256
|
+
* shared guard: a leaf on a loop of tool-result messages is refused `invalid_session` (the sentence of `getPathToRoot`) instead of followed.
|
|
257
|
+
*/
|
|
258
|
+
export declare function settledForkOptions(source: Session): Promise<{
|
|
259
|
+
entryId?: string;
|
|
260
|
+
position?: "at";
|
|
261
|
+
}>;
|