@sema-agent/core 7.54.1 → 7.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +950 -0
- package/dist/agents/agent-transcript-tool.js +2 -1
- package/dist/agents/builtin-agents.d.ts +12 -14
- package/dist/agents/cascade.js +1 -1
- package/dist/agents/cc-peer-directory.d.ts +36 -0
- package/dist/agents/cc-peer-directory.js +139 -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/child-model-seat.d.ts +0 -11
- package/dist/agents/child-model-seat.js +0 -3
- 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.d.ts +3 -1
- package/dist/agents/list-agents-tool.js +9 -8
- 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 +65 -13
- package/dist/agents/peer-directory.js +90 -25
- 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 +3 -2
- package/dist/agents/read-inbox-tool.js +2 -1
- package/dist/agents/repair-loop.js +2 -2
- 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 +37 -8
- package/dist/agents/subagent.d.ts +39 -82
- package/dist/agents/subagent.js +109 -106
- package/dist/agents/tool-filter.d.ts +31 -46
- package/dist/agents/tool-filter.js +13 -33
- package/dist/agents/verify.d.ts +6 -5
- package/dist/agents/verify.js +3 -3
- package/dist/brain/anthropic.js +43 -81
- package/dist/brain/errors.d.ts +15 -0
- package/dist/brain/errors.js +10 -0
- package/dist/brain/media-degrade.d.ts +18 -7
- package/dist/brain/media-degrade.js +13 -2
- package/dist/brain/model-capability.d.ts +37 -0
- package/dist/brain/model-capability.js +34 -0
- package/dist/brain/model-presets.d.ts +6 -12
- package/dist/brain/model-presets.js +1 -6
- package/dist/brain/open-responses.js +27 -35
- package/dist/brain/openai.js +30 -98
- package/dist/brain/provider-dialect.d.ts +39 -3
- package/dist/brain/provider-dialect.js +28 -0
- package/dist/brain/reasoning-request.d.ts +96 -0
- package/dist/brain/reasoning-request.js +174 -0
- package/dist/brain/reasoning.d.ts +12 -12
- package/dist/brain/reasoning.js +4 -3
- package/dist/brain/request-params.d.ts +62 -9
- package/dist/brain/request-params.js +42 -7
- 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/status-sink.d.ts +20 -0
- package/dist/brain/status-sink.js +7 -0
- package/dist/brain/stream-engine.js +6 -5
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/core/a2a.d.ts +2 -1
- package/dist/core/a2a.js +19 -13
- package/dist/core/advisor-verdict.d.ts +120 -0
- package/dist/core/advisor-verdict.js +92 -0
- package/dist/core/agent-definition.d.ts +17 -8
- package/dist/core/allow-entry.d.ts +69 -36
- package/dist/core/allow-entry.js +81 -52
- package/dist/core/allow-rule-shadow.d.ts +10 -3
- package/dist/core/approval-object.d.ts +2 -1
- package/dist/core/approval-object.js +6 -6
- package/dist/core/ask-origin.d.ts +127 -29
- package/dist/core/ask-origin.js +87 -25
- package/dist/core/ask-question.d.ts +51 -8
- package/dist/core/ask-question.js +12 -7
- package/dist/core/ask-unresolvable-notice.d.ts +8 -3
- package/dist/core/ask-unresolvable-notice.js +16 -2
- 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-generation.d.ts +53 -0
- package/dist/core/checkpoint-generation.js +35 -0
- package/dist/core/checkpoint-queries.d.ts +180 -0
- package/dist/core/checkpoint-queries.js +272 -0
- package/dist/core/checkpoint-requirements.d.ts +19 -4
- package/dist/core/checkpoint-requirements.js +8 -14
- package/dist/core/checkpoint-store.d.ts +165 -72
- package/dist/core/checkpoint-store.js +79 -82
- 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 +11 -4
- package/dist/core/cross-boundary-taint.js +3 -3
- package/dist/core/decision-receipt.d.ts +37 -3
- package/dist/core/decision-receipt.js +19 -19
- package/dist/core/delegation-not-started.d.ts +6 -0
- package/dist/core/delegation-not-started.js +17 -0
- package/dist/core/effective-path-target.d.ts +1 -1
- package/dist/core/engine-attestation.d.ts +93 -0
- package/dist/core/engine-attestation.js +70 -0
- package/dist/core/engine-capabilities.d.ts +4 -1
- package/dist/core/engine-capabilities.js +1 -1
- package/dist/core/engine-notice.d.ts +45 -12
- 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 +147 -21
- package/dist/core/file-history-store.js +58 -32
- package/dist/core/gate-fold.d.ts +1 -1
- package/dist/core/gate-fold.js +24 -11
- package/dist/core/gate-lanes.js +81 -68
- package/dist/core/gate-outcome.d.ts +40 -6
- package/dist/core/gate-outcome.js +56 -0
- package/dist/core/governance-codes.d.ts +17 -3
- package/dist/core/governance-codes.js +16 -0
- package/dist/core/hands-band.d.ts +1 -1
- package/dist/core/hooks.d.ts +21 -20
- package/dist/core/hooks.js +3 -1
- package/dist/core/host-floor.d.ts +128 -0
- package/dist/core/host-floor.js +206 -0
- package/dist/core/host-target.d.ts +84 -0
- package/dist/core/host-target.js +92 -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 +17 -13
- package/dist/core/mcp.js +240 -189
- package/dist/core/media-byte-cap.d.ts +1 -1
- package/dist/core/memory-engine/delegation-settlement.js +15 -24
- package/dist/core/memory-engine/engine.d.ts +9 -9
- package/dist/core/memory-engine/engine.js +4 -4
- package/dist/core/memory-engine/layout.d.ts +60 -8
- package/dist/core/memory-engine/layout.js +65 -6
- package/dist/core/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/model-seat.d.ts +10 -3
- package/dist/core/mods/classic-events.d.ts +67 -0
- package/dist/core/mods/classic-events.js +1 -0
- package/dist/core/mods/dollar.d.ts +13 -0
- package/dist/core/mods/extension-call.d.ts +31 -0
- package/dist/core/mods/extension-call.js +43 -0
- package/dist/core/mods/kernel/dispatch.d.ts +20 -3
- package/dist/core/mods/kernel/dispatch.js +140 -69
- package/dist/core/mods/kernel/events.d.ts +47 -11
- package/dist/core/mods/kernel/events.js +66 -42
- package/dist/core/mods/kernel/index.d.ts +4 -4
- package/dist/core/mods/kernel/index.js +2 -2
- package/dist/core/mods/kernel/receive.d.ts +39 -5
- package/dist/core/mods/kernel/receive.js +290 -17
- package/dist/core/mods/kernel/registration.d.ts +33 -2
- package/dist/core/mods/kernel/registration.js +6 -7
- package/dist/core/mods/kernel/site-rules.d.ts +44 -16
- package/dist/core/mods/kernel/site-rules.js +24 -42
- package/dist/core/mods/spec-seats.d.ts +69 -0
- package/dist/core/mods/spec-seats.js +114 -0
- package/dist/core/mods/stations.d.ts +28 -8
- package/dist/core/mods/stations.js +29 -13
- package/dist/core/mods/tool-call.d.ts +79 -0
- package/dist/core/mods/tool-call.js +152 -0
- package/dist/core/namespaced-rule-name.d.ts +44 -24
- package/dist/core/namespaced-rule-name.js +50 -43
- 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 +13 -1
- package/dist/core/parent-spec-seat.js +6 -0
- package/dist/core/park-selfcheck.js +1 -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 +30 -5
- package/dist/core/permission-rule-consent.js +147 -50
- package/dist/core/permission-rule-model.d.ts +245 -65
- package/dist/core/permission-rule-model.js +421 -107
- package/dist/core/permission-rule-org.d.ts +6 -2
- package/dist/core/permission-rule-org.js +7 -3
- package/dist/core/permission-rule-provider.d.ts +6 -2
- package/dist/core/permission-rule-provider.js +41 -11
- package/dist/core/permission-rule-store.d.ts +22 -26
- package/dist/core/permission-rule-store.js +12 -6
- package/dist/core/permission-rule-sync.d.ts +11 -2
- package/dist/core/permission-rule-sync.js +11 -3
- package/dist/core/permission-rule-syntax.d.ts +5 -4
- package/dist/core/permission-rule-syntax.js +2 -2
- package/dist/core/permission-rules.d.ts +53 -15
- package/dist/core/permission-rules.js +125 -100
- package/dist/core/persisted-rule-arms.d.ts +6 -4
- package/dist/core/persisted-rule-arms.js +10 -12
- package/dist/core/present-plan-tool.js +3 -1
- package/dist/core/principal-name.d.ts +20 -0
- package/dist/core/principal-name.js +22 -0
- package/dist/core/prompt-section-seat.js +4 -6
- package/dist/core/protocol-http-auth.d.ts +26 -5
- package/dist/core/protocol-http-auth.js +137 -4
- package/dist/core/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/retired-keys.d.ts +16 -0
- package/dist/core/retired-keys.js +16 -4
- package/dist/core/rewrite-rejudge.d.ts +60 -0
- package/dist/core/rewrite-rejudge.js +36 -0
- package/dist/core/roles.d.ts +34 -3
- package/dist/core/roles.js +66 -53
- package/dist/core/rule-lane-reads.d.ts +20 -15
- package/dist/core/rule-lane-reads.js +45 -17
- 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 +29 -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 +18 -26
- package/dist/core/runner/announce-once-ledger.js +19 -46
- package/dist/core/runner/approval-feedback.js +6 -3
- package/dist/core/runner/assemble-result.d.ts +2 -1
- package/dist/core/runner/assemble-result.js +1 -1
- package/dist/core/runner/call-hook-stations.d.ts +3 -2
- package/dist/core/runner/caller-roster.d.ts +21 -2
- package/dist/core/runner/caller-roster.js +38 -0
- package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
- package/dist/core/runner/capability-withheld-seat.js +24 -0
- package/dist/core/runner/classifier-ladder.d.ts +33 -13
- package/dist/core/runner/classifier-ladder.js +15 -14
- package/dist/core/runner/compaction-restate.d.ts +10 -6
- package/dist/core/runner/compaction-restate.js +9 -3
- package/dist/core/runner/construction-doors.js +3 -0
- package/dist/core/runner/contracts.d.ts +40 -33
- 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 +21 -16
- package/dist/core/runner/cross-boundary-lane.js +58 -34
- 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 +4 -4
- package/dist/core/runner/denial-limit-arms.js +1 -1
- 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/file-history-request.d.ts +18 -0
- package/dist/core/runner/file-history-request.js +21 -13
- package/dist/core/runner/file-history-restore.d.ts +45 -0
- package/dist/core/runner/file-history-restore.js +46 -0
- package/dist/core/runner/gate-exit.d.ts +9 -3
- package/dist/core/runner/gate-exit.js +11 -5
- package/dist/core/runner/image.d.ts +7 -17
- package/dist/core/runner/image.js +9 -60
- package/dist/core/runner/initial-run-state.js +1 -1
- package/dist/core/runner/permission-rule-lanes.d.ts +6 -6
- package/dist/core/runner/permission-rule-lanes.js +38 -15
- package/dist/core/runner/person-path-rows.d.ts +12 -9
- package/dist/core/runner/person-path-rows.js +19 -8
- package/dist/core/runner/prepare-advisor.d.ts +63 -0
- package/dist/core/runner/prepare-advisor.js +77 -0
- package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
- package/dist/core/runner/prepare-ask-lane.js +5 -2
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
- package/dist/core/runner/prepare-caps-and-workflow.js +5 -4
- package/dist/core/runner/prepare-config-doors.d.ts +31 -38
- package/dist/core/runner/prepare-config-doors.js +57 -34
- package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
- package/dist/core/runner/prepare-defer-classify.js +7 -8
- package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
- package/dist/core/runner/prepare-delegation-surface.js +1 -1
- package/dist/core/runner/prepare-file-history.d.ts +48 -8
- package/dist/core/runner/prepare-file-history.js +41 -73
- package/dist/core/runner/prepare-gate-stations.d.ts +2 -5
- package/dist/core/runner/prepare-gate-stations.js +12 -8
- package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
- package/dist/core/runner/prepare-hands-readface.js +15 -14
- package/dist/core/runner/prepare-inherited-gate.d.ts +11 -7
- package/dist/core/runner/prepare-inherited-gate.js +8 -6
- package/dist/core/runner/prepare-memory-engine-session.js +1 -1
- package/dist/core/runner/prepare-park-ask.js +12 -12
- package/dist/core/runner/prepare-policy-chain.d.ts +7 -4
- package/dist/core/runner/prepare-policy-chain.js +68 -81
- 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-assembly.d.ts +5 -7
- package/dist/core/runner/prepare-prompt-assembly.js +10 -8
- package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
- package/dist/core/runner/prepare-prompt-inputs.js +4 -6
- package/dist/core/runner/prepare-protocol-tools.d.ts +4 -2
- package/dist/core/runner/prepare-protocol-tools.js +5 -4
- package/dist/core/runner/prepare-safety-scan.d.ts +9 -12
- package/dist/core/runner/prepare-safety-scan.js +8 -23
- package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
- package/dist/core/runner/prepare-suspend-saga.js +5 -6
- package/dist/core/runner/prepare-task.d.ts +1 -1
- package/dist/core/runner/prepare-task.js +41 -35
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
- package/dist/core/runner/prepare-tool-disclosure-mount.js +24 -18
- package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
- package/dist/core/runner/prepare-turn-wiring.js +2 -7
- package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -4
- package/dist/core/runner/prepare-wiring-manifest.js +3 -3
- package/dist/core/runner/resume-admission.js +1 -1
- package/dist/core/runner/resume-apply.js +11 -12
- package/dist/core/runner/resume-checkpoint-screen.js +3 -0
- package/dist/core/runner/resume-claim.d.ts +4 -2
- package/dist/core/runner/resume-claim.js +15 -8
- package/dist/core/runner/resume-policy-outcome.js +1 -1
- package/dist/core/runner/retired-runner-deps.js +2 -1
- package/dist/core/runner/rewind-files.d.ts +15 -0
- package/dist/core/runner/rewind-files.js +132 -0
- package/dist/core/runner/run-attachment-seats.js +2 -2
- package/dist/core/runner/run-brain-sinks.d.ts +4 -1
- package/dist/core/runner/run-brain-sinks.js +4 -2
- package/dist/core/runner/run-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 +14 -7
- package/dist/core/runner/run-leg.d.ts +1 -1
- package/dist/core/runner/run-leg.js +43 -18
- package/dist/core/runner/run-settle-and-teardown.js +3 -2
- 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 +15 -22
- package/dist/core/runner/runtask.d.ts +3 -0
- package/dist/core/runner/runtask.js +8 -9
- package/dist/core/runner/session-read-file-states.d.ts +15 -0
- package/dist/core/runner/session-read-file-states.js +28 -0
- package/dist/core/runner/session-rule-policy.d.ts +22 -21
- package/dist/core/runner/session-rule-policy.js +17 -31
- package/dist/core/runner/shell-env-withheld.d.ts +33 -0
- package/dist/core/runner/shell-env-withheld.js +51 -0
- package/dist/core/runner/side-call-account.d.ts +32 -8
- package/dist/core/runner/side-call-account.js +23 -1
- package/dist/core/runner/skills-seat.js +6 -2
- package/dist/core/runner/stream-settle-backstop.js +1 -1
- package/dist/core/runner/strict-output-schema.d.ts +1 -1
- package/dist/core/runner/sub-agent-deny-lists.js +4 -6
- package/dist/core/runner/synthetic-tools.d.ts +16 -13
- package/dist/core/runner/synthetic-tools.js +8 -3
- package/dist/core/runner/tool-disclosure.d.ts +10 -12
- package/dist/core/runner/tool-disclosure.js +3 -4
- package/dist/core/runner/tool-end-body.d.ts +1 -1
- package/dist/core/runner/tool-end-body.js +10 -9
- package/dist/core/runner/tool-face-overlay.d.ts +2 -1
- package/dist/core/runner/tool-face-overlay.js +17 -1
- package/dist/core/runner/tool-not-executed.d.ts +5 -0
- package/dist/core/runner/tool-not-executed.js +11 -0
- package/dist/core/runner/tool-occurrence.d.ts +8 -0
- package/dist/core/runner/tool-occurrence.js +7 -0
- package/dist/core/runner/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 +91 -80
- package/dist/core/runner/turn-attachments.js +62 -37
- package/dist/core/runner-deps.d.ts +42 -42
- package/dist/core/runtime-caps.d.ts +4 -4
- package/dist/core/safety-axis-vocab.d.ts +6 -4
- package/dist/core/safety-axis-vocab.js +6 -5
- package/dist/core/safety-merge-corpus.js +26 -2
- 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/secret-env.d.ts +26 -3
- package/dist/core/secret-env.js +44 -8
- package/dist/core/select-model.js +3 -3
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/sensitive-path-policy.js +1 -1
- package/dist/core/session-policy-store.d.ts +102 -35
- package/dist/core/session-policy-store.js +210 -48
- package/dist/core/session-reconcile.d.ts +2 -2
- package/dist/core/session-store.d.ts +106 -37
- package/dist/core/session-store.js +165 -91
- package/dist/core/session.d.ts +101 -57
- package/dist/core/session.js +53 -0
- package/dist/core/shared-memory/tools.js +3 -1
- package/dist/core/shared-memory/types.d.ts +1 -1
- package/dist/core/shell-read-silence.d.ts +11 -12
- package/dist/core/shell-read-silence.js +9 -5
- package/dist/core/shell-run-candidates.js +3 -1
- package/dist/core/shell-wrapper-projection.js +1 -1
- package/dist/core/shell-wrapper-table.d.ts +14 -7
- package/dist/core/shell-wrapper-table.js +5 -4
- package/dist/core/side-query.d.ts +10 -0
- package/dist/core/side-query.js +15 -1
- package/dist/core/skill-grant.d.ts +7 -2
- package/dist/core/skill-grant.js +5 -0
- package/dist/core/skills-directory.js +6 -2
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +168 -3
- package/dist/core/store-contracts/file-history-store-contract.js +74 -4
- package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
- package/dist/core/store-contracts/peer-directory-contract.js +14 -2
- package/dist/core/store-contracts/session-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 +176 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +6 -8
- package/dist/core/store-contracts/session-store-contract.js +361 -51
- package/dist/core/store-contracts/workflow-journal-store-contract.js +26 -1
- package/dist/core/stub-env.d.ts +2 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/surrogate-safe-slice.d.ts +3 -3
- package/dist/core/synthetic-read-verdict.js +3 -3
- package/dist/core/task-event.d.ts +42 -8
- package/dist/core/task-notification.d.ts +19 -15
- 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 +13 -4
- package/dist/core/task-registry.js +14 -2
- package/dist/core/task-result.d.ts +21 -3
- package/dist/core/task-spec.d.ts +69 -64
- 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/tighten-task-spec.js +2 -1
- package/dist/core/tool-catalog-entries.d.ts +36 -2
- package/dist/core/tool-catalog-entries.js +69 -43
- package/dist/core/tool-check-reading.d.ts +11 -0
- package/dist/core/tool-check-reading.js +11 -6
- 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 +5 -5
- package/dist/core/tool-name-aliases.d.ts +29 -8
- package/dist/core/tool-name-aliases.js +22 -4
- package/dist/core/tool-name-readings.d.ts +10 -43
- package/dist/core/tool-name-readings.js +2 -11
- package/dist/core/tool-policy.d.ts +85 -196
- package/dist/core/tool-policy.js +150 -175
- package/dist/core/tool-registry.d.ts +14 -7
- package/dist/core/tool-registry.js +17 -7
- package/dist/core/tool-result-store.js +5 -1
- package/dist/core/tool-roster.d.ts +57 -33
- package/dist/core/tool-roster.js +56 -68
- package/dist/core/tool-spec-members.js +8 -3
- package/dist/core/tool-spec.d.ts +53 -31
- package/dist/core/tools.js +51 -10
- package/dist/core/trace.d.ts +6 -2
- package/dist/core/types.d.ts +1 -1
- package/dist/core/untrusted-egress.d.ts +1 -1
- package/dist/core/untrusted-text.d.ts +1 -1
- package/dist/core/user-attachment.d.ts +8 -1
- package/dist/core/user-attachment.js +64 -4
- package/dist/core/warm-resume.d.ts +1 -1
- package/dist/core/wiring-manifest.d.ts +58 -0
- package/dist/core/wiring-manifest.js +14 -5
- package/dist/core/workflow-journal-store.d.ts +62 -0
- package/dist/core/workflow-journal-store.js +78 -2
- 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/compaction/compaction.js +3 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +26 -8
- package/dist/engine/execution-env/node-execution-env.js +54 -24
- package/dist/engine/harness/agent-harness.d.ts +39 -9
- package/dist/engine/harness/agent-harness.js +87 -33
- package/dist/engine/harness/types.d.ts +58 -9
- package/dist/engine/harness/types.js +12 -1
- package/dist/engine/llm/types.d.ts +36 -19
- 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 +23 -1
- package/dist/engine/loop/agent-loop.js +26 -34
- package/dist/engine/loop/types.d.ts +31 -19
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/memory-repo.d.ts +18 -12
- package/dist/engine/session/memory-repo.js +24 -9
- 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 +32 -3
- package/dist/engine/session/repo-utils.js +50 -5
- package/dist/index.d.ts +47 -23
- package/dist/index.js +35 -17
- 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 +2 -2
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/goal.js +2 -2
- package/dist/orchestration/run-workflow-tool.d.ts +8 -6
- package/dist/orchestration/run-workflow-tool.js +10 -6
- 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 +5 -13
- package/dist/orchestration/workflow.js +57 -49
- package/dist/prompt-assembly/artifact.d.ts +2 -2
- package/dist/prompt-assembly/artifact.js +5 -3
- package/dist/prompt-assembly/assemble.d.ts +3 -2
- package/dist/prompt-assembly/assemble.js +1 -1
- package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
- package/dist/prompt-assembly/catalog/schema.js +34 -2
- package/dist/prompt-assembly/catalog/sections.js +0 -1
- package/dist/prompt-assembly/composer.d.ts +3 -1
- package/dist/prompt-assembly/composer.js +1 -1
- package/dist/prompt-assembly/event-registry.js +2 -0
- package/dist/prompt-assembly/overlay.js +3 -3
- package/dist/prompt-assembly/renderers.d.ts +1 -1
- package/dist/prompt-assembly/renderers.js +0 -3
- package/dist/prompt-assembly/role-base.d.ts +15 -0
- package/dist/prompt-assembly/role-base.js +9 -0
- package/dist/prompt-assembly/select.d.ts +39 -14
- package/dist/prompt-assembly/select.js +47 -16
- package/dist/prompt-assembly/sugar.d.ts +17 -11
- package/dist/prompt-assembly/sugar.js +8 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +39 -2
- package/dist/prompt-assembly/tool-catalog.js +117 -4
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
- package/dist/prompt-assembly/turn-snapshot.js +0 -3
- package/dist/prompt-assembly/types.d.ts +0 -7
- package/dist/prompts/default.d.ts +14 -14
- package/dist/scenarios/full-body.d.ts +15 -15
- package/dist/scenarios/full-body.js +4 -3
- package/dist/shell/lex.js +10 -1
- package/dist/stores/file/adoption/adopt.d.ts +4 -3
- package/dist/stores/file/adoption/adopt.js +27 -33
- package/dist/stores/file/adoption/marker.d.ts +6 -13
- package/dist/stores/file/adoption/marker.js +9 -17
- package/dist/stores/file/checkpoint-store.d.ts +24 -0
- package/dist/stores/file/checkpoint-store.js +45 -7
- package/dist/stores/file/file-history-store.d.ts +20 -19
- package/dist/stores/file/file-history-store.js +157 -141
- 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/index.js +2 -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 +18 -18
- package/dist/stores/file/permission-rule-store.d.ts +18 -2
- package/dist/stores/file/permission-rule-store.js +31 -18
- package/dist/stores/file/session-policy-store.d.ts +3 -3
- package/dist/stores/file/session-store.d.ts +54 -16
- package/dist/stores/file/session-store.js +114 -85
- 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 +5 -3
- package/dist/tools/fs/bash-program-position.d.ts +19 -2
- package/dist/tools/fs/bash-program-position.js +56 -9
- package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -3
- package/dist/tools/fs/fs-bash.d.ts +2 -2
- package/dist/tools/fs/fs-bash.js +8 -6
- package/dist/tools/fs/fs-glob.d.ts +86 -0
- package/dist/tools/fs/fs-glob.js +226 -0
- package/dist/tools/fs/fs-read.js +14 -14
- package/dist/tools/fs/fs-search-tools.js +7 -7
- package/dist/tools/fs/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/pattern-kill-guard.d.ts +22 -0
- package/dist/tools/fs/pattern-kill-guard.js +397 -0
- package/dist/tools/fs/pdf.d.ts +9 -6
- package/dist/tools/fs/pdf.js +3 -3
- package/dist/tools/fs/program-read-model.d.ts +57 -7
- package/dist/tools/fs/program-read-model.js +11 -1
- package/dist/tools/fs/program-read-model.rows.js +78 -21
- package/dist/tools/fs/read-deny-home.js +3 -2
- package/dist/tools/fs/read-deny.d.ts +29 -7
- package/dist/tools/fs/read-deny.js +63 -22
- package/dist/tools/fs/removal-targets.d.ts +18 -8
- package/dist/tools/fs/removal-targets.js +47 -20
- package/dist/tools/fs/safety.d.ts +9 -9
- package/dist/tools/fs/search.d.ts +16 -6
- package/dist/tools/fs/search.js +20 -26
- package/dist/tools/fs/shell-read-argv.js +89 -12
- package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
- package/dist/tools/fs/shell-read-bindings.js +41 -0
- package/dist/tools/fs/shell-read-check.js +12 -20
- package/dist/tools/fs/shell-read-environment.d.ts +5 -1
- package/dist/tools/fs/shell-read-environment.js +3 -2
- package/dist/tools/fs/shell-read-establish.d.ts +15 -0
- package/dist/tools/fs/shell-read-establish.js +19 -20
- package/dist/tools/fs/shell-read-judge.d.ts +4 -0
- package/dist/tools/fs/shell-read-judge.js +5 -2
- package/dist/tools/fs/shell-read-plan.js +24 -16
- package/dist/tools/fs/shell-read-start.d.ts +6 -1
- package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
- package/dist/tools/fs/shell-read-write-targets.js +2 -3
- package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
- package/dist/tools/fs/shell-reentry-text.js +40 -2
- package/dist/tools/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 +65 -64
- package/dist/tools/web.d.ts +20 -15
- package/dist/tools/web.js +55 -69
- 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 +5894 -5638
- package/wire-changes/core@7.55.0.json +3318 -0
- package/wire-changes/core@7.56.0.json +3891 -0
- package/wire-changes/mods-kernel@7.56.0.json +303 -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
|
@@ -62,6 +62,18 @@ export interface JsonlRecordJudge {
|
|
|
62
62
|
accepts(record: object): boolean;
|
|
63
63
|
what: string;
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* The FIRST record of an open JSONL file of `size` bytes — the record {@link readJsonlRecords} would return first — read forward one
|
|
67
|
+
* block at a time and stopping there: a read bounded by the lines before it, never by the file. Skipped lines are not disclosed (the
|
|
68
|
+
* whole-file read discloses them); `undefined` = the file holds no record.
|
|
69
|
+
*/
|
|
70
|
+
export declare function firstJsonlRecord(fd: number, size: number, judge?: JsonlRecordJudge): object | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* The LAST record of an open JSONL file of `size` bytes that `pick` accepts — the last such record {@link readJsonlRecords} would
|
|
73
|
+
* return — found by walking back from the end one block at a time: a read bounded by the lines after it, never by the file. The
|
|
74
|
+
* unterminated last segment is judged as the whole-file read judges it. Skipped lines are not disclosed; `undefined` = none.
|
|
75
|
+
*/
|
|
76
|
+
export declare function lastJsonlRecord(fd: number, size: number, pick: (record: object) => boolean, judge?: JsonlRecordJudge): object | undefined;
|
|
65
77
|
/**
|
|
66
78
|
* An append-only JSONL log opened once with `O_APPEND` and held for the file's lifetime. One record =
|
|
67
79
|
* one `JSON.stringify(...) + "\n"` written in a SINGLE `writeSync` call (never split across writes → the
|
|
@@ -162,6 +174,9 @@ export declare class AppendLog {
|
|
|
162
174
|
*/
|
|
163
175
|
private rollBackFailedWrite;
|
|
164
176
|
close(): void;
|
|
177
|
+
/** Whether this log's open descriptor is the file its path names now (same device and inode). A file removed or replaced under it
|
|
178
|
+
* is not — its writes land on an inode no reader of the path sees — and neither is a log with no open descriptor. */
|
|
179
|
+
isFileAtPath(): boolean;
|
|
165
180
|
/**
|
|
166
181
|
* RB-167 — release the descriptor for a compaction SWAP. The next write reopens it lazily.
|
|
167
182
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { appendFileSync, closeSync, constants as FS, existsSync, fstatSync, ftruncateSync, linkSync, mkdirSync, openSync, readFileSync, readSync, renameSync, truncateSync, unlinkSync, writeFileSync, writeSync, fsyncSync, } from "node:fs";
|
|
1
|
+
import { appendFileSync, closeSync, constants as FS, existsSync, fstatSync, ftruncateSync, linkSync, mkdirSync, openSync, readFileSync, readSync, renameSync, statSync, truncateSync, unlinkSync, writeFileSync, writeSync, fsyncSync, } from "node:fs";
|
|
2
2
|
import { constants as bufferConstants } from "node:buffer";
|
|
3
3
|
import { homedir, hostname, uptime } from "node:os";
|
|
4
4
|
import { hrtime } from "node:process";
|
|
@@ -142,19 +142,11 @@ export function readJsonlRecords(path, onCorrupt, judge) {
|
|
|
142
142
|
const line = parts[i];
|
|
143
143
|
if (line === "")
|
|
144
144
|
continue;
|
|
145
|
-
const read =
|
|
146
|
-
if (read.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
discloseSkip(
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
if (read.form === "not-an-object") {
|
|
153
|
-
discloseSkip("not-an-object", i + 1, `jsonl record is ${jsonTypeName(read.value)}, not an object`);
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
if (judge !== undefined && !judge.accepts(read.record)) {
|
|
157
|
-
discloseSkip("missing-required", i + 1, judge.what);
|
|
145
|
+
const read = readJsonlLine(line, i === parts.length - 1, judge);
|
|
146
|
+
if (read.verdict === "partial-tail")
|
|
147
|
+
break;
|
|
148
|
+
if (read.verdict === "skip") {
|
|
149
|
+
discloseSkip(read.form, i + 1, read.what);
|
|
158
150
|
continue;
|
|
159
151
|
}
|
|
160
152
|
out.push(read.record);
|
|
@@ -166,6 +158,77 @@ export function readJsonlRecords(path, onCorrupt, judge) {
|
|
|
166
158
|
}
|
|
167
159
|
return out;
|
|
168
160
|
}
|
|
161
|
+
function readJsonlLine(line, unterminated, judge) {
|
|
162
|
+
const read = jsonlTextFormOf(line);
|
|
163
|
+
if (read.form === "unparseable")
|
|
164
|
+
return unterminated ? { verdict: "partial-tail" } : { verdict: "skip", form: "torn-json", what: "unparseable jsonl record" };
|
|
165
|
+
if (read.form === "not-an-object")
|
|
166
|
+
return { verdict: "skip", form: "not-an-object", what: `jsonl record is ${jsonTypeName(read.value)}, not an object` };
|
|
167
|
+
if (judge !== undefined && !judge.accepts(read.record))
|
|
168
|
+
return { verdict: "skip", form: "missing-required", what: judge.what };
|
|
169
|
+
return { verdict: "record", record: read.record };
|
|
170
|
+
}
|
|
171
|
+
function assertJudgeableLine(length) {
|
|
172
|
+
if (length > JSONL_TAIL_SEGMENT_LIMIT)
|
|
173
|
+
throw new Error(`jsonl record cursor: a line of ${length} bytes is past the judgeable bound (${JSONL_TAIL_SEGMENT_LIMIT})`);
|
|
174
|
+
}
|
|
175
|
+
function jsonlLineText(bytes) {
|
|
176
|
+
assertJudgeableLine(bytes.length);
|
|
177
|
+
return bytes.toString("utf8");
|
|
178
|
+
}
|
|
179
|
+
export function firstJsonlRecord(fd, size, judge) {
|
|
180
|
+
let carry = Buffer.alloc(0);
|
|
181
|
+
for (let from = 0; from < size;) {
|
|
182
|
+
const block = Buffer.allocUnsafe(Math.min(JSONL_TAIL_READ_BLOCK, size - from));
|
|
183
|
+
readExactly(fd, block, block.length, from);
|
|
184
|
+
from += block.length;
|
|
185
|
+
let data = carry.length > 0 ? Buffer.concat([carry, block]) : block;
|
|
186
|
+
for (let nl = data.indexOf(0x0a); nl >= 0; nl = data.indexOf(0x0a)) {
|
|
187
|
+
const text = jsonlLineText(data.subarray(0, nl));
|
|
188
|
+
data = data.subarray(nl + 1);
|
|
189
|
+
if (text === "")
|
|
190
|
+
continue;
|
|
191
|
+
const read = readJsonlLine(text, false, judge);
|
|
192
|
+
if (read.verdict === "record")
|
|
193
|
+
return read.record;
|
|
194
|
+
}
|
|
195
|
+
carry = Buffer.from(data);
|
|
196
|
+
assertJudgeableLine(carry.length);
|
|
197
|
+
}
|
|
198
|
+
if (carry.length === 0)
|
|
199
|
+
return undefined;
|
|
200
|
+
const read = readJsonlLine(jsonlLineText(carry), true, judge);
|
|
201
|
+
return read.verdict === "record" ? read.record : undefined;
|
|
202
|
+
}
|
|
203
|
+
export function lastJsonlRecord(fd, size, pick, judge) {
|
|
204
|
+
let carry = Buffer.alloc(0);
|
|
205
|
+
let segmentEndsFile = true;
|
|
206
|
+
const visit = (bytes) => {
|
|
207
|
+
const unterminated = segmentEndsFile;
|
|
208
|
+
segmentEndsFile = false;
|
|
209
|
+
if (bytes.length === 0)
|
|
210
|
+
return undefined;
|
|
211
|
+
const read = readJsonlLine(jsonlLineText(bytes), unterminated, judge);
|
|
212
|
+
return read.verdict === "record" && pick(read.record) ? read.record : undefined;
|
|
213
|
+
};
|
|
214
|
+
for (let end = size; end > 0;) {
|
|
215
|
+
const from = Math.max(0, end - JSONL_TAIL_READ_BLOCK);
|
|
216
|
+
const block = Buffer.allocUnsafe(end - from);
|
|
217
|
+
readExactly(fd, block, block.length, from);
|
|
218
|
+
end = from;
|
|
219
|
+
const data = carry.length > 0 ? Buffer.concat([block, carry]) : block;
|
|
220
|
+
let segEnd = data.length;
|
|
221
|
+
for (let nl = segEnd > 0 ? data.lastIndexOf(0x0a, segEnd - 1) : -1; nl >= 0; nl = segEnd > 0 ? data.lastIndexOf(0x0a, segEnd - 1) : -1) {
|
|
222
|
+
const hit = visit(data.subarray(nl + 1, segEnd));
|
|
223
|
+
if (hit !== undefined)
|
|
224
|
+
return hit;
|
|
225
|
+
segEnd = nl;
|
|
226
|
+
}
|
|
227
|
+
carry = Buffer.from(data.subarray(0, segEnd));
|
|
228
|
+
assertJudgeableLine(carry.length);
|
|
229
|
+
}
|
|
230
|
+
return visit(carry);
|
|
231
|
+
}
|
|
169
232
|
function jsonTypeName(value) {
|
|
170
233
|
if (value === null)
|
|
171
234
|
return "null";
|
|
@@ -271,6 +334,18 @@ export class AppendLog {
|
|
|
271
334
|
this.disposed = true;
|
|
272
335
|
this.releaseFd();
|
|
273
336
|
}
|
|
337
|
+
isFileAtPath() {
|
|
338
|
+
if (this.fd < 0)
|
|
339
|
+
return false;
|
|
340
|
+
try {
|
|
341
|
+
const open = fstatSync(this.fd, { bigint: true });
|
|
342
|
+
const named = statSync(this.path, { bigint: true });
|
|
343
|
+
return open.dev === named.dev && open.ino === named.ino;
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
274
349
|
closeForSwap() {
|
|
275
350
|
this.releaseFd();
|
|
276
351
|
}
|
|
@@ -27,7 +27,7 @@ export { resolveDataRoot, sanitizeScope, sanitizePathComponent, createFileConsol
|
|
|
27
27
|
export { FileStoreLockError, type FileStoreLockErrorCode } from "./fs-atomic.js";
|
|
28
28
|
export { atomicWriteFile, writeThenLink, ensureDir, readJsonlRecords, AppendLog } from "./fs-atomic.js";
|
|
29
29
|
export { processFingerprint, isProcessLive, type ProcessFingerprint } from "./fs-atomic.js";
|
|
30
|
-
export { AdoptionError, assertAdoptionBootGate, readRootAdoptionFile, writeRootAdoptionFile, ROOT_ADOPTION_FILE, type AdoptionErrorCode, type
|
|
30
|
+
export { AdoptionError, assertAdoptionBootGate, readRootAdoptionFile, writeRootAdoptionFile, ROOT_ADOPTION_FILE, type AdoptionErrorCode, type AdoptionReport, type AdoptionReceipt, type AdoptionLegReport, type AffectedDeploymentConfig, type RootAdoptionFile, } from "./adoption/marker.js";
|
|
31
31
|
export { adoptLocalDataRoot, ackAdoptionConfig, witnessAdoptionConfig, listAdoptionQuarantine, readAdoptionStatus, type AdoptionStatus, type AdoptLocalDataRootOptions, type AdoptLocalDataRootResult, type AdoptionCarriageLeg, type AdoptionCarriageLegContext, type AdoptionConfigWitnessReceipt, } from "./adoption/adopt.js";
|
|
32
32
|
/**
|
|
33
33
|
* design/80 — the file-backed {@link EngineStorageBackend} for the local (TOC) single-user binary, selected
|
|
@@ -62,7 +62,8 @@ export class FileStorageBackend {
|
|
|
62
62
|
this.fileSessions = repo;
|
|
63
63
|
this.ttl = new TtlSessionStore({ repo, evict: opts.evict ?? "forget", durability: "durable", placements: { subagent: { durability: "durable" } } });
|
|
64
64
|
this.sessionStore = this.ttl;
|
|
65
|
-
|
|
65
|
+
const sessionHeadOf = this.ttl.headOf;
|
|
66
|
+
this.fileCheckpoints = new FileCheckpointStore(this.root, { ...opts.checkpoint, ...corruptRead, ...(sessionHeadOf !== undefined ? { sessionHeadOf } : {}) });
|
|
66
67
|
built.push(() => this.fileCheckpoints.close());
|
|
67
68
|
this.checkpointStore = this.fileCheckpoints;
|
|
68
69
|
this.fileMemory = new FileMemoryStore(this.root, opts.embedder ? { embedder: opts.embedder } : {});
|
|
@@ -52,6 +52,9 @@ export declare class FileMailboxStore implements MailboxStore {
|
|
|
52
52
|
/** design/385 — the whole cross-process set (box lock + fresh re-read + descriptor reopen +
|
|
53
53
|
* compaction under the lock) is in place and accepted by `mailboxCrossProcessContract`. */
|
|
54
54
|
readonly crossProcessSafe = true;
|
|
55
|
+
/** The sha-256 of the PHYSICAL path of the boxes directory: every instance over one directory — whatever
|
|
56
|
+
* spelling of the root it was built from, in any process — answers the same identity. */
|
|
57
|
+
readonly identity: string;
|
|
55
58
|
private readonly dir;
|
|
56
59
|
private readonly tmpDir;
|
|
57
60
|
private readonly fsyncEnabled;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { join, resolve, sep } from "node:path";
|
|
2
|
-
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
3
3
|
import { assertRetentionPolicy } from "../../core/retention-policy.js";
|
|
4
4
|
import { existsSync, linkSync, readdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { detachMailboxMessage, newestSentAt, readMailboxPeerMeta, } from "../../core/mailbox-store.js";
|
|
@@ -324,6 +324,7 @@ function sweepLockResidue(dir, lockName) {
|
|
|
324
324
|
}
|
|
325
325
|
export class FileMailboxStore {
|
|
326
326
|
crossProcessSafe = true;
|
|
327
|
+
identity;
|
|
327
328
|
dir;
|
|
328
329
|
tmpDir;
|
|
329
330
|
fsyncEnabled;
|
|
@@ -347,6 +348,7 @@ export class FileMailboxStore {
|
|
|
347
348
|
ensureDir(lexicalTmp);
|
|
348
349
|
this.dir = physicalPathOf(lexicalDir);
|
|
349
350
|
this.tmpDir = physicalPathOf(lexicalTmp);
|
|
351
|
+
this.identity = createHash("sha256").update(this.dir).digest("hex");
|
|
350
352
|
}
|
|
351
353
|
boxPath(scope, handle) {
|
|
352
354
|
return join(this.dir, sanitizeScope(scope), `${sanitizePathComponent(handle).toLowerCase()}.jsonl`);
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* join, deliberately not a rename. Rows the far side refuses during ⑤ move to the local quarantine
|
|
25
25
|
* area — preserved and disclosed, never deleted (the F-011 "nothing is lost" floor).
|
|
26
26
|
*/
|
|
27
|
-
import type
|
|
27
|
+
import { type RuleOwner } from "../../core/rule-owner.js";
|
|
28
28
|
import { type PermissionRuleSyncResult, type PermissionRuleSyncTransport } from "../../core/permission-rule-sync.js";
|
|
29
29
|
export type AdoptFileRuleStoreResult =
|
|
30
30
|
/** The full arc completed (this call, or an earlier one — the terminal marker makes it idempotent). */
|
|
@@ -1,28 +1,34 @@
|
|
|
1
1
|
import { existsSync, renameSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { writerOf } from "../../core/permission-rule-store.js";
|
|
4
|
+
import { readRuleOwner, ruleOwnerText, sameRuleOwner } from "../../core/rule-owner.js";
|
|
5
|
+
import { principalNameOf } from "../../core/principal-name.js";
|
|
4
6
|
import { createPermissionRuleStoreProvider } from "../../core/permission-rule-provider.js";
|
|
5
7
|
import { syncPermissionRules } from "../../core/permission-rule-sync.js";
|
|
6
8
|
import { thrownText } from "../../core/thrown-value.js";
|
|
7
9
|
import { FileStoreLockError } from "./fs-atomic.js";
|
|
8
10
|
import { FileDurableRulePartitionProvider, LOCAL_OWNER_FILE, principalRuleFileName, readRuleAdoptionFile, writeRuleAdoptionFile, } from "./permission-rule-store.js";
|
|
9
11
|
export async function adoptFilePermissionRuleStore(opts) {
|
|
10
|
-
if (
|
|
11
|
-
throw new Error("adoptFilePermissionRuleStore requires the adopting principal — adoption is the act of giving this bucket an identity");
|
|
12
|
+
if (principalNameOf(opts.toPrincipal) === undefined) {
|
|
13
|
+
throw new Error("adoptFilePermissionRuleStore requires the adopting principal, a principal name — adoption is the act of giving this bucket an identity");
|
|
12
14
|
}
|
|
13
|
-
|
|
15
|
+
const from = readRuleOwner(opts.from);
|
|
16
|
+
if (from === undefined) {
|
|
17
|
+
throw new Error("adoptFilePermissionRuleStore requires a source owner — a principal owner whose principal is a principal name, or the local owner");
|
|
18
|
+
}
|
|
19
|
+
if (from.kind === "principal" && from.principal === opts.toPrincipal) {
|
|
14
20
|
throw new Error(`the bucket already belongs to "${opts.toPrincipal}" — there is nothing to adopt`);
|
|
15
21
|
}
|
|
16
|
-
const sourceFile = join(opts.dir,
|
|
22
|
+
const sourceFile = join(opts.dir, from.kind === "local-owner" ? LOCAL_OWNER_FILE : principalRuleFileName(from.principal));
|
|
17
23
|
const targetFile = join(opts.dir, principalRuleFileName(opts.toPrincipal));
|
|
18
24
|
const existing = readRuleAdoptionFile(opts.dir);
|
|
19
25
|
if (existing !== undefined) {
|
|
20
26
|
if ("adopted" in existing) {
|
|
21
|
-
if (existing.adopted.toPrincipal === opts.toPrincipal &&
|
|
27
|
+
if (existing.adopted.toPrincipal === opts.toPrincipal && sameRuleOwner(existing.adopted.from, from))
|
|
22
28
|
return { status: "adopted" };
|
|
23
|
-
throw new Error(`this directory already carries a completed adoption (${
|
|
29
|
+
throw new Error(`this directory already carries a completed adoption (${ruleOwnerText(existing.adopted.from)} → "${existing.adopted.toPrincipal}") — a second adoption of the same directory is not a shape this helper supports`);
|
|
24
30
|
}
|
|
25
|
-
if (existing.marker.toPrincipal !== opts.toPrincipal || !
|
|
31
|
+
if (existing.marker.toPrincipal !== opts.toPrincipal || !sameRuleOwner(existing.marker.from, from)) {
|
|
26
32
|
throw new Error(`an adoption toward "${existing.marker.toPrincipal}" is already in flight in this directory — refusing to start a different one (resume the original, or repair the marker by hand)`);
|
|
27
33
|
}
|
|
28
34
|
}
|
|
@@ -44,7 +50,7 @@ export async function adoptFilePermissionRuleStore(opts) {
|
|
|
44
50
|
throw new Error("the target store refused a write face");
|
|
45
51
|
let phase = existing !== undefined && "marker" in existing ? existing.marker.phase : 2;
|
|
46
52
|
if (existing === undefined) {
|
|
47
|
-
writeRuleAdoptionFile(opts.dir, marker(
|
|
53
|
+
writeRuleAdoptionFile(opts.dir, marker(from, opts.toPrincipal, 2));
|
|
48
54
|
phase = 2;
|
|
49
55
|
}
|
|
50
56
|
if (phase < 3) {
|
|
@@ -55,11 +61,11 @@ export async function adoptFilePermissionRuleStore(opts) {
|
|
|
55
61
|
}
|
|
56
62
|
if (sourcePresent)
|
|
57
63
|
renameSync(sourceFile, targetFile);
|
|
58
|
-
writeRuleAdoptionFile(opts.dir, marker(
|
|
64
|
+
writeRuleAdoptionFile(opts.dir, marker(from, opts.toPrincipal, 3));
|
|
59
65
|
phase = 3;
|
|
60
66
|
}
|
|
61
67
|
if (phase < 4) {
|
|
62
|
-
writeRuleAdoptionFile(opts.dir, marker(
|
|
68
|
+
writeRuleAdoptionFile(opts.dir, marker(from, opts.toPrincipal, 4));
|
|
63
69
|
phase = 4;
|
|
64
70
|
}
|
|
65
71
|
let syncResult;
|
|
@@ -82,12 +88,12 @@ export async function adoptFilePermissionRuleStore(opts) {
|
|
|
82
88
|
error: `the first sync round did not land clean (${(syncResult.warnings ?? []).join("; ") || `${syncResult.dropped.length} drop(s)`}) — resume when the endpoint is healthy`,
|
|
83
89
|
};
|
|
84
90
|
}
|
|
85
|
-
writeRuleAdoptionFile(opts.dir, marker(
|
|
91
|
+
writeRuleAdoptionFile(opts.dir, marker(from, opts.toPrincipal, 5));
|
|
86
92
|
phase = 5;
|
|
87
93
|
}
|
|
88
94
|
writeRuleAdoptionFile(opts.dir, {
|
|
89
95
|
schemaVersion: 1,
|
|
90
|
-
adopted: { from
|
|
96
|
+
adopted: { from, toPrincipal: opts.toPrincipal, atMs: (opts.now ?? Date.now)() },
|
|
91
97
|
});
|
|
92
98
|
return { status: "adopted", ...(syncResult !== undefined ? { syncResult } : {}) };
|
|
93
99
|
}
|
|
@@ -98,9 +104,3 @@ export async function adoptFilePermissionRuleStore(opts) {
|
|
|
98
104
|
function marker(from, toPrincipal, phase) {
|
|
99
105
|
return { schemaVersion: 1, marker: { from, toPrincipal, phase } };
|
|
100
106
|
}
|
|
101
|
-
function sameOwner(a, b) {
|
|
102
|
-
return a.kind === "principal" ? b.kind === "principal" && a.principal === b.principal : b.kind === "local-owner";
|
|
103
|
-
}
|
|
104
|
-
function ownerText(o) {
|
|
105
|
-
return o.kind === "principal" ? `principal "${o.principal}"` : "the local owner";
|
|
106
|
-
}
|
|
@@ -8,6 +8,16 @@
|
|
|
8
8
|
* reader accepts schema 4 ONLY: any other schema word is refused whole, loudly, bytes left untouched —
|
|
9
9
|
* this engine performs no migration of an older engine's buckets.
|
|
10
10
|
*
|
|
11
|
+
* ## A bucket carries its rule grammar
|
|
12
|
+
*
|
|
13
|
+
* Every write stamps the bucket with this engine's rule grammar (`grammar`, the number the session rules
|
|
14
|
+
* store stamps too); every read judges it through the one stamp judge (`readRuleGrammarStamp`). A bucket
|
|
15
|
+
* stamped with a later grammar was written by a newer engine whose rows this one may read as nothing — a
|
|
16
|
+
* deny it cannot parse refuses nothing — so it is refused WHOLE, like any bucket this engine cannot read,
|
|
17
|
+
* with its own code (`PERMISSION_RULES_LATER_GRAMMAR_CODE`): reads answer zero rules and say so, writes
|
|
18
|
+
* refuse, the bytes stay as they are. A bucket without the member was written before the stamp and reads
|
|
19
|
+
* in this engine's grammar; the next write stamps it.
|
|
20
|
+
*
|
|
11
21
|
* ## Why this store builds its own symlink refusal
|
|
12
22
|
*
|
|
13
23
|
* The other file stores canonicalize with `realpath`, which RESOLVES a symlink rather than refusing one —
|
|
@@ -50,7 +60,8 @@
|
|
|
50
60
|
* For this backend the trust is host = user, exactly as for the settings file it mirrors.
|
|
51
61
|
*/
|
|
52
62
|
import type { PersistedRule, RuleTombstone } from "../../core/permission-rule-model.js";
|
|
53
|
-
import type { DurableRulePartition, DurableRulePartitionProvider, PermissionRuleWriter, QuarantinedRuleAdd,
|
|
63
|
+
import type { DurableRulePartition, DurableRulePartitionProvider, PermissionRuleWriter, QuarantinedRuleAdd, RuleSyncFrontier, StoredRules, WritableDurableRulePartition } from "../../core/permission-rule-store.js";
|
|
64
|
+
import { type RuleOwner } from "../../core/rule-owner.js";
|
|
54
65
|
import { PERMISSION_RULE_WRITER } from "../../core/permission-rule-store.js";
|
|
55
66
|
import { type OrgRuleStatePersistence, type PersistedOrgRuleState } from "../../core/permission-rule-org.js";
|
|
56
67
|
import type { StoreDurability, StoreFidelity } from "../../core/checkpoint-store.js";
|
|
@@ -72,6 +83,9 @@ interface RuleFile {
|
|
|
72
83
|
lastRoundAtMs?: number;
|
|
73
84
|
};
|
|
74
85
|
quarantined?: QuarantinedRuleAdd[];
|
|
86
|
+
/** The rule grammar the rows were written in: stamped by every write, judged by every read (see the module note).
|
|
87
|
+
* Absent on a bucket written before the stamp. */
|
|
88
|
+
grammar?: number;
|
|
75
89
|
checksum: string;
|
|
76
90
|
}
|
|
77
91
|
/** The deployment-wide org state file: last-known-good snapshot + anti-rollback high-water, one blob. */
|
|
@@ -145,6 +159,7 @@ declare class FileDurableRulePartition implements WritableDurableRulePartition {
|
|
|
145
159
|
* sync wire (`readRaw`) or adjudication.
|
|
146
160
|
*/
|
|
147
161
|
private screenDurableRows;
|
|
162
|
+
/** Publish `next` stamped with this engine's rule grammar — the stamp's one mint — and answer the checksum written. */
|
|
148
163
|
private write;
|
|
149
164
|
list(): Promise<StoredRules>;
|
|
150
165
|
/** The quarantine area (design/182 §5.2/§8.3): introspection only — never part of `list()`. Its posture
|
|
@@ -162,7 +177,8 @@ declare class FileDurableRulePartition implements WritableDurableRulePartition {
|
|
|
162
177
|
* unrecoverable one: the next redemption would write a fresh file over the damaged one, discarding every
|
|
163
178
|
* standing rule, every tombstone, the revision and the replica identity, along with the evidence of what
|
|
164
179
|
* went wrong. Reads already answer zero rules for the same condition, so the lane stays fail-closed
|
|
165
|
-
* while a person looks at the file.
|
|
180
|
+
* while a person looks at the file. A bucket a newer engine wrote is one of these: writing it in this
|
|
181
|
+
* engine's grammar would stamp rows this engine cannot read with a grammar that claims it can.
|
|
166
182
|
*/
|
|
167
183
|
private current;
|
|
168
184
|
/**
|
|
@@ -3,8 +3,11 @@ import { join } from "node:path";
|
|
|
3
3
|
import { createHash, randomBytes } from "node:crypto";
|
|
4
4
|
import { isRuleBehavior } from "../../core/permission-rule-model.js";
|
|
5
5
|
import { posixModeBitsMeaningful } from "../../core/posix-mode-face.js";
|
|
6
|
-
import {
|
|
6
|
+
import { readRuleOwner } from "../../core/rule-owner.js";
|
|
7
|
+
import { principalNameOf, readPrincipal } from "../../core/principal-name.js";
|
|
8
|
+
import { PERMISSION_RULES_LATER_GRAMMAR_CODE, PERMISSION_RULE_WRITER, applySyncJoin, applyTombstones, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, foldDelta, unknownRuleWriteDeltaError, } from "../../core/permission-rule-store.js";
|
|
7
9
|
import { sameOrgPolicyContent } from "../../core/permission-rule-org.js";
|
|
10
|
+
import { SESSION_RULES_GRAMMAR, readRuleGrammarStamp } from "../../core/session-policy-store.js";
|
|
8
11
|
import { canonicalize } from "../../core/canonical-json.js";
|
|
9
12
|
import { BootLock, FileStoreLockError } from "./fs-atomic.js";
|
|
10
13
|
import { assertAdoptionBootGate } from "./adoption/marker.js";
|
|
@@ -54,12 +57,6 @@ export function readRuleAdoptionFile(dir) {
|
|
|
54
57
|
}
|
|
55
58
|
return judged.marker;
|
|
56
59
|
}
|
|
57
|
-
function isRuleOwnerShape(v) {
|
|
58
|
-
if (v === null || typeof v !== "object")
|
|
59
|
-
return false;
|
|
60
|
-
const owner = v;
|
|
61
|
-
return owner.kind === "local-owner" || (owner.kind === "principal" && typeof owner.principal === "string");
|
|
62
|
-
}
|
|
63
60
|
function isRuleAdoptionFileShape(v) {
|
|
64
61
|
if (v === null || typeof v !== "object" || v.schemaVersion !== 1)
|
|
65
62
|
return false;
|
|
@@ -70,7 +67,7 @@ function isRuleAdoptionFileShape(v) {
|
|
|
70
67
|
const rec = (hasMarker ? v.marker : v.adopted);
|
|
71
68
|
if (rec === null || typeof rec !== "object")
|
|
72
69
|
return false;
|
|
73
|
-
if (
|
|
70
|
+
if (readRuleOwner(rec.from) === undefined || principalNameOf(rec.toPrincipal) === undefined)
|
|
74
71
|
return false;
|
|
75
72
|
return hasMarker ? rec.phase === 2 || rec.phase === 3 || rec.phase === 4 || rec.phase === 5 : typeof rec.atMs === "number" && Number.isFinite(rec.atMs);
|
|
76
73
|
}
|
|
@@ -144,6 +141,9 @@ function refusalText(onError, sentence, location) {
|
|
|
144
141
|
discloseTo(onError, `${sentence} (at ${location})`);
|
|
145
142
|
return `${sentence}. The location is reported to the store's error disclosure (onError), not in this message.`;
|
|
146
143
|
}
|
|
144
|
+
function unreadableError(r, sentence = r.unreadable) {
|
|
145
|
+
return r.code !== undefined ? Object.assign(new Error(sentence), { code: r.code }) : new Error(sentence);
|
|
146
|
+
}
|
|
147
147
|
function discloseTo(onError, message) {
|
|
148
148
|
try {
|
|
149
149
|
onError?.(message);
|
|
@@ -226,6 +226,12 @@ class FileDurableRulePartition {
|
|
|
226
226
|
const { checksum, ...body } = parsed;
|
|
227
227
|
if (checksum !== checksumOf(body))
|
|
228
228
|
return unreadable(`${bucket} failed its integrity check; ${whole}`);
|
|
229
|
+
const grammar = readRuleGrammarStamp(parsed.grammar, SESSION_RULES_GRAMMAR, { rules: `the rules in ${bucket}`, held: "rows" });
|
|
230
|
+
if ("got" in grammar) {
|
|
231
|
+
return grammar.later === true
|
|
232
|
+
? { ...unreadable(`${grammar.sentence} — loading zero rules and refusing every write until then; the file is left as it is`), code: PERMISSION_RULES_LATER_GRAMMAR_CODE }
|
|
233
|
+
: unreadable(`${grammar.sentence}; ${whole}`);
|
|
234
|
+
}
|
|
229
235
|
const rowKinds = [
|
|
230
236
|
["rule", parsed.rules],
|
|
231
237
|
["tombstone", parsed.tombstones],
|
|
@@ -254,12 +260,15 @@ class FileDurableRulePartition {
|
|
|
254
260
|
}
|
|
255
261
|
write(next) {
|
|
256
262
|
assertSafeDirAtRequest(this.dir, this.onError, "write through", this.vetting);
|
|
257
|
-
|
|
263
|
+
const body = { ...next, grammar: SESSION_RULES_GRAMMAR };
|
|
264
|
+
const checksum = checksumOf(body);
|
|
265
|
+
atomicPublish(this.dir, this.file, JSON.stringify({ ...body, checksum }, null, 2));
|
|
266
|
+
return checksum;
|
|
258
267
|
}
|
|
259
268
|
async list() {
|
|
260
269
|
const r = this.read();
|
|
261
270
|
if ("unreadable" in r)
|
|
262
|
-
throw
|
|
271
|
+
throw unreadableError(r);
|
|
263
272
|
if (!("file" in r))
|
|
264
273
|
return { ...EMPTY_READ };
|
|
265
274
|
const screened = this.screenDurableRows(r.file);
|
|
@@ -273,13 +282,13 @@ class FileDurableRulePartition {
|
|
|
273
282
|
async quarantined() {
|
|
274
283
|
const r = this.read();
|
|
275
284
|
if ("unreadable" in r)
|
|
276
|
-
throw
|
|
285
|
+
throw unreadableError(r);
|
|
277
286
|
return "file" in r ? this.screenDurableRows(r.file).quarantined : [];
|
|
278
287
|
}
|
|
279
288
|
current() {
|
|
280
289
|
const r = this.read();
|
|
281
290
|
if ("unreadable" in r) {
|
|
282
|
-
throw
|
|
291
|
+
throw unreadableError(r, `refusing to write the permission-rule store while it cannot be read: ${r.unreadable}`);
|
|
283
292
|
}
|
|
284
293
|
if ("absent" in r) {
|
|
285
294
|
return { schemaVersion: 4, actor: `file-${randomBytes(6).toString("hex")}`, counter: 0, rev: 0, rules: [], tombstones: [] };
|
|
@@ -296,8 +305,7 @@ class FileDurableRulePartition {
|
|
|
296
305
|
};
|
|
297
306
|
}
|
|
298
307
|
writeAndVerify(next) {
|
|
299
|
-
const expected =
|
|
300
|
-
this.write(next);
|
|
308
|
+
const expected = this.write(next);
|
|
301
309
|
const after = this.read();
|
|
302
310
|
return "file" in after && after.file.checksum === expected;
|
|
303
311
|
}
|
|
@@ -445,17 +453,22 @@ export class FileDurableRulePartitionProvider {
|
|
|
445
453
|
this.lock = lock;
|
|
446
454
|
};
|
|
447
455
|
forPrincipal(principal) {
|
|
448
|
-
|
|
456
|
+
const reading = readPrincipal(principal);
|
|
457
|
+
if (reading.kind === "invalid") {
|
|
458
|
+
throw new Error(`the principal given is not a principal name (got ${reading.fault}) — refusing to resolve a bucket for it; a provided value that names nobody is not "no principal"`);
|
|
459
|
+
}
|
|
460
|
+
if (reading.kind === "absent") {
|
|
449
461
|
return { list: async () => ({ ...EMPTY_READ }), durability: "process-local" };
|
|
450
462
|
}
|
|
463
|
+
const name = reading.name;
|
|
451
464
|
const adoption = this.adoptionMarker();
|
|
452
465
|
if (adoption !== undefined) {
|
|
453
466
|
const rec = "adopted" in adoption ? adoption.adopted : adoption.marker;
|
|
454
|
-
if (rec.from.kind === "principal" && rec.from.principal ===
|
|
455
|
-
return this.readOnlySourceView(principalRuleFileName(
|
|
467
|
+
if (rec.from.kind === "principal" && rec.from.principal === name) {
|
|
468
|
+
return this.readOnlySourceView(principalRuleFileName(name), principalRuleFileName(rec.toPrincipal), "adopted" in adoption || adoption.marker.phase >= 4);
|
|
456
469
|
}
|
|
457
470
|
}
|
|
458
|
-
return new FileDurableRulePartition(this.dir, join(this.dir, principalRuleFileName(
|
|
471
|
+
return new FileDurableRulePartition(this.dir, join(this.dir, principalRuleFileName(name)), this.acquireWriteLock, this.onError, this.vetting);
|
|
459
472
|
}
|
|
460
473
|
readOnlySourceView(sourceName, targetName, flipped) {
|
|
461
474
|
const pick = flipped ? targetName : existsSync(join(this.dir, sourceName)) ? sourceName : targetName;
|
|
@@ -151,9 +151,9 @@ export declare class FileSessionPolicyStore implements SessionPolicyStore {
|
|
|
151
151
|
private disclose;
|
|
152
152
|
/** The ONE refusal for a rules file that is PRESENT but cannot be served as rules — every damage grade lands
|
|
153
153
|
* here (`unreadable` bytes, `unparseable` JSON, a `malformed` row), so the keyed read and the write that reads
|
|
154
|
-
* before it answer with one voice. Session rules only TIGHTEN: a row is
|
|
155
|
-
*
|
|
156
|
-
*
|
|
154
|
+
* before it answer with one voice. Session rules only TIGHTEN: a row is a restriction on the session's calls, so
|
|
155
|
+
* reading a damaged one as "no rules" would drop the restriction itself — a loosening no write made, which the
|
|
156
|
+
* write judge would refuse below the row's operator part. ABSENCE (ENOENT) is the only "no rules"; it never reaches
|
|
157
157
|
* here. The disclosure sink fires with the refusal (swallow-guarded: a throwing sink cannot turn it back into an
|
|
158
158
|
* answer) and is the ONLY carrier of the file's path: the thrown message reaches end users through a host's error
|
|
159
159
|
* body, so it names no on-disk location. Two ways out, both the operator's: fix the file, or delete it — deleting is an explicit "no rules" and
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Session, SessionCreateOptions, SessionForkOptions, SessionMetadata, SessionPlacementRecord, SessionRepo, SessionTreeEntry } from "../../internal/harness.js";
|
|
1
|
+
import type { Session, SessionCreateOptions, SessionForkOptions, SessionHead, SessionMetadata, SessionPlacementRecord, SessionRepo, SessionRow, SessionTreeEntry } from "../../internal/harness.js";
|
|
2
2
|
import type { PlacedSessionRow } from "../../core/session.js";
|
|
3
3
|
import { type CorruptReadInfo } from "./corrupt-read-sink.js";
|
|
4
4
|
export interface FileSessionRepoOptions {
|
|
@@ -8,8 +8,9 @@ export interface FileSessionRepoOptions {
|
|
|
8
8
|
* "corrupt read as missing" are one failure grammar, so they get one seat name.
|
|
9
9
|
*
|
|
10
10
|
* Fires for: an unreadable sessions DIRECTORY (the listing degrades to "no sessions"), a session log
|
|
11
|
-
*
|
|
12
|
-
* record dropped on replay plus that replay's
|
|
11
|
+
* whose header could not be read during a listing (skipped from the result — a listing reads headers,
|
|
12
|
+
* it never replays a log), and each corrupt interior JSONL record dropped on replay plus that replay's
|
|
13
|
+
* tally (turns missing from an otherwise healthy session).
|
|
13
14
|
*
|
|
14
15
|
* Never fires on plain ENOENT / `not_found` — that is honest absence, and the torn TAIL stays silent
|
|
15
16
|
* too (dying mid-write is the append log's documented crash-recovery shape, not corruption).
|
|
@@ -37,12 +38,37 @@ export declare class FileSessionRepo implements SessionRepo {
|
|
|
37
38
|
private pathFor;
|
|
38
39
|
/**
|
|
39
40
|
* Read + torn-tail-recover a session file into (meta, entries). Three answers: no file → `not_found`; a
|
|
40
|
-
* file
|
|
41
|
-
* here lays the header down first and the header alone carries `createdAt` / fork /
|
|
42
|
-
* is not a session this store wrote, or its header line is damaged);
|
|
43
|
-
* record disclosed.
|
|
41
|
+
* file whose first record is not a meta header → `corrupt_session`, even when every other record is intact
|
|
42
|
+
* (every write path here lays the header down first and the header alone carries `createdAt` / fork /
|
|
43
|
+
* placement / owner, so the file is not a session this store wrote, or its header line is damaged);
|
|
44
|
+
* otherwise the session, each skipped record disclosed.
|
|
44
45
|
*/
|
|
45
46
|
private read;
|
|
47
|
+
/**
|
|
48
|
+
* The row's cells from its FIRST record — the one header every write path lays down before any entry; a later meta record is
|
|
49
|
+
* never read as the header. Each occupant cell goes through the one incarnation decoding (an unknown occupant, said here when the
|
|
50
|
+
* cell is there but names nobody) and the owner cell through its decoding (a cell that is neither an owner nor anonymous refuses
|
|
51
|
+
* the row). `skipped` words the corrupt-header refusal's reading of the records around it, where the caller has one.
|
|
52
|
+
*/
|
|
53
|
+
private headerOf;
|
|
54
|
+
/**
|
|
55
|
+
* The row's head in one read, without replaying the log: ONE descriptor on the session file, its first record for the owner and
|
|
56
|
+
* occupant cells, and walking back from its end to the last entry record for the leaf. The three come from one inode — a file
|
|
57
|
+
* replaced (fork / import) or removed (delete) while this reads is still the inode this descriptor opened — so they answer for one
|
|
58
|
+
* row generation. The leaf is what a replay computes (the leaf after the last entry the whole-file read keeps, judged by the same
|
|
59
|
+
* per-line rule, a torn tail dropped alike): the log is the only carrier, so no state exists in which the log holds an entry the
|
|
60
|
+
* head does not see. A leaf entry naming an id the log does not hold is not checked here (a replay refuses that log on open).
|
|
61
|
+
*/
|
|
62
|
+
headOf(sessionId: string): Promise<SessionHead | undefined>;
|
|
63
|
+
/**
|
|
64
|
+
* The row's {@link SessionRow} — its header cells and the newest write it holds, the log's modification time (every write to a row
|
|
65
|
+
* is an append to its log; the placed listing's age reads the same time) — in one read of the header, never a replay of the log.
|
|
66
|
+
* `undefined` = no row; a row whose header cannot be read rejects (`corrupt_session`).
|
|
67
|
+
*/
|
|
68
|
+
private rowOf;
|
|
69
|
+
/** The one descriptor a by-id read of the row takes: its size and modification time and its header, from one inode (a file replaced
|
|
70
|
+
* or removed while this reads is still the inode this descriptor opened); `undefined` = no file. */
|
|
71
|
+
private atRow;
|
|
46
72
|
private storage;
|
|
47
73
|
/**
|
|
48
74
|
* RB-437 — release every shared authority this repo joined (LAST holder ⇒ evict + close the append fd).
|
|
@@ -59,12 +85,25 @@ export declare class FileSessionRepo implements SessionRepo {
|
|
|
59
85
|
dispose(): Promise<void>;
|
|
60
86
|
create(options?: SessionCreateOptions): Promise<Session>;
|
|
61
87
|
open(metadata: SessionMetadata): Promise<Session>;
|
|
62
|
-
|
|
88
|
+
/** Record activity on the row now: its log's modification time — the one time a listing reads, which every append moves too — is
|
|
89
|
+
* set to now, the log's bytes untouched. A missing file is nothing to record; any other fault rejects. */
|
|
90
|
+
touch(sessionId: string): Promise<void>;
|
|
91
|
+
/** Every ordinary row with the newest write its log holds ({@link rowOf}): one header read per session file, no replay — what a
|
|
92
|
+
* listing costs grows with the number of sessions, never with their history. Placed rows are the placed listing's. */
|
|
93
|
+
list(): Promise<SessionRow[]>;
|
|
94
|
+
/**
|
|
95
|
+
* Every row of the sessions directory, each read by {@link rowOf}. The listing degrades to "no sessions" so a
|
|
96
|
+
* browse face never throws — but "I could not read the directory" and "there are none" are different facts, and only the sink can
|
|
97
|
+
* tell them apart (ENOENT is honest absence: the constructor creates the directory, so it was removed underneath us). A session
|
|
98
|
+
* whose header cannot be read is skipped and disclosed — it exists and is missing from the listing — while a file that vanished
|
|
99
|
+
* between the directory read and its own is honest absence.
|
|
100
|
+
*/
|
|
101
|
+
private rows;
|
|
63
102
|
/**
|
|
64
103
|
* Subagent transcript persistence — the PLACED partition's own enumeration (the joint reap's
|
|
65
104
|
* partition-leg input; `TtlSessionStore` re-exposes it verbatim). Age (`olderThanMs`) is judged on
|
|
66
|
-
* the session FILE's mtime — the transcript's last append
|
|
67
|
-
*
|
|
105
|
+
* the session FILE's mtime — the transcript's last append, the time the host listing reads too
|
|
106
|
+
* (mtime is also the CC orphan-adoption window's basis, so the age reads agree).
|
|
68
107
|
* Rows missing either `(scope, handle)` join half return the honest `tupleIncomplete` variant
|
|
69
108
|
* (consumers fail closed on it — never age-reaped, see the SessionStore contract).
|
|
70
109
|
*/
|
|
@@ -73,21 +112,20 @@ export declare class FileSessionRepo implements SessionRepo {
|
|
|
73
112
|
scope?: string;
|
|
74
113
|
}): Promise<PlacedSessionRow[]>;
|
|
75
114
|
/** The row as it stands before a file-replacing write: `undefined` ⇔ there is no row (no file); a row
|
|
76
|
-
* whose header cannot be read
|
|
115
|
+
* whose header cannot be read rejects (it exists, and nobody can name its cells). */
|
|
77
116
|
private priorHeader;
|
|
78
117
|
/** Cheap placement probe for one id (the TtlSessionStore's cold-cache release consults it so the
|
|
79
|
-
* placed real-deletion obligation holds after a restart). `undefined` = missing file OR unplaced. */
|
|
118
|
+
* placed real-deletion obligation holds after a restart). `undefined` = missing file OR unplaced; a row that cannot be read rejects. */
|
|
80
119
|
placementOf(sessionId: string): Promise<SessionPlacementRecord | undefined>;
|
|
81
120
|
delete(metadata: SessionMetadata): Promise<void>;
|
|
82
|
-
fork(sourceMetadata: SessionMetadata, options?: SessionForkOptions): Promise<Session>;
|
|
121
|
+
fork(sourceMetadata: SessionMetadata, options?: SessionForkOptions & SessionCreateOptions): Promise<Session>;
|
|
83
122
|
/** 2c session-sync (the FILE half): the FULL oldest-first log for export. The file backend
|
|
84
123
|
* has NO F3 floor — `read` returns EVERY persisted entry (`id`/`parentId` verbatim) — so this is the complete
|
|
85
124
|
* log, BYPASSing any bounded tail (matches `InMemorySessionRepo.exportEntries`). Missing file → not_found. */
|
|
86
125
|
exportEntries(sessionId: string): Promise<SessionTreeEntry[]>;
|
|
87
126
|
/** 2c session-sync: import a verbatim log into `sessionId`. The single fail-closed invariant gate runs
|
|
88
|
-
* FIRST ({@link validateEntriesForImport}); `owner
|
|
89
|
-
*
|
|
90
|
-
* atomically via tmp→fsync→rename — the rename is the commit point, so a crash leaves either nothing or an
|
|
127
|
+
* FIRST ({@link validateEntriesForImport}); a new row's header records `owner`, an existing row's is laid down again whole. Writes the WHOLE file
|
|
128
|
+
* (meta + entries) atomically via tmp→fsync→rename — the rename is the commit point, so a crash leaves either nothing or an
|
|
91
129
|
* orphan temp, never a partially-imported session (mirrors `fork`). An existing session is REPLACED (the
|
|
92
130
|
* orchestrator's importSession owns the already-exists policy, same as InMemory's overwrite). */
|
|
93
131
|
importEntries(sessionId: string, owner: string | undefined, entries: SessionTreeEntry[], options?: {
|