@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
|
@@ -2,7 +2,7 @@ import { createHash, randomBytes } from "node:crypto";
|
|
|
2
2
|
import { appendFileSync, closeSync, existsSync, fsyncSync, openSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { thrownText } from "../../core/thrown-value.js";
|
|
5
|
-
import { applyFileRestoreViaEnv, boundaryPublishVerdict, worldStillMatchesMint, captureFileBackupViaEnv, modeProvenDifferent, previewFileDelta, describeTrackKey, fileHistoryExportDigest, resolveTrackKey, trackKeyOf, validateFileHistoryExport, } from "../../core/file-history-store.js";
|
|
5
|
+
import { applyFileRestoreViaEnv, boundaryPublishVerdict, worldStillMatchesMint, annulProofFailure, captureFileBackupViaEnv, modeProvenDifferent, previewFileDelta, describeTrackKey, fileHistoryExportDigest, caughtFault, DAMAGED_RECORD, resolveTrackKey, trackKeyOf, validateFileHistoryExport, } from "../../core/file-history-store.js";
|
|
6
6
|
import { fileHistoryBoundariesToKeep, resolveFileHistoryRetention } from "../../core/file-history-retention.js";
|
|
7
7
|
import { atomicWriteFile, ensureDir, sanitizePathComponent, sanitizeScope, writeThenLink } from "./fs-atomic.js";
|
|
8
8
|
import { guardCorruptSink } from "./corrupt-read-sink.js";
|
|
@@ -109,6 +109,12 @@ function nestedMapSet(map, scope, key, value) {
|
|
|
109
109
|
map.set(scope, (inner = new Map()));
|
|
110
110
|
inner.set(key, value);
|
|
111
111
|
}
|
|
112
|
+
function worstFault(faults) {
|
|
113
|
+
const terminal = faults.find((f) => f.permanence === "terminal");
|
|
114
|
+
if (terminal !== undefined)
|
|
115
|
+
return terminal;
|
|
116
|
+
return faults.length > 0 && faults.every((f) => f.permanence === "transient") ? faults[0] : {};
|
|
117
|
+
}
|
|
112
118
|
function safeRm(path) {
|
|
113
119
|
try {
|
|
114
120
|
rmSync(path, { force: true, recursive: true });
|
|
@@ -227,21 +233,21 @@ export class FileFileHistoryStore {
|
|
|
227
233
|
if (err.code === "ENOENT")
|
|
228
234
|
return { corrupt: false, tracked: new Map() };
|
|
229
235
|
this.disclose(path, `tracked set unreadable (${err.code ?? "unknown"}) — this scope's history is UNUSABLE until it is repaired`);
|
|
230
|
-
return { corrupt: true, tracked: new Map() };
|
|
236
|
+
return { corrupt: true, tracked: new Map(), fault: caughtFault(err) };
|
|
231
237
|
}
|
|
232
238
|
const parsed = parseJsonRecord(raw);
|
|
233
239
|
if (parsed === null) {
|
|
234
240
|
this.disclose(path, "unparseable tracked set (torn/zero-byte write?) — this scope's history is UNUSABLE until it is repaired");
|
|
235
|
-
return { corrupt: true, tracked: new Map() };
|
|
241
|
+
return { corrupt: true, tracked: new Map(), fault: DAMAGED_RECORD };
|
|
236
242
|
}
|
|
237
243
|
const rows = trackedRowsOf(parsed);
|
|
238
244
|
if (rows === null) {
|
|
239
245
|
this.disclose(path, "tracked set is not a pair array of [key, record] rows — this scope's history is UNUSABLE until it is repaired");
|
|
240
|
-
return { corrupt: true, tracked: new Map() };
|
|
246
|
+
return { corrupt: true, tracked: new Map(), fault: DAMAGED_RECORD };
|
|
241
247
|
}
|
|
242
248
|
if (parsed.digest !== undefined && (typeof parsed.digest !== "string" || parsed.digest !== trackedDigest(rows))) {
|
|
243
249
|
this.disclose(path, "tracked set fails its own integrity digest (edited in place, or written by something that is not this store) — this scope's history is UNUSABLE until it is repaired");
|
|
244
|
-
return { corrupt: true, tracked: new Map() };
|
|
250
|
+
return { corrupt: true, tracked: new Map(), fault: DAMAGED_RECORD };
|
|
245
251
|
}
|
|
246
252
|
return { corrupt: false, tracked: new Map(rows) };
|
|
247
253
|
}
|
|
@@ -256,6 +262,10 @@ export class FileFileHistoryStore {
|
|
|
256
262
|
atomicWriteFile(join(this.base, "tmp"), this.trackedPath(scope), JSON.stringify(doc));
|
|
257
263
|
}
|
|
258
264
|
readBoundary(path) {
|
|
265
|
+
const read = this.readBoundaryState(path);
|
|
266
|
+
return read instanceof Map ? read : null;
|
|
267
|
+
}
|
|
268
|
+
readBoundaryState(path) {
|
|
259
269
|
let raw;
|
|
260
270
|
try {
|
|
261
271
|
raw = readFileSync(path, "utf8");
|
|
@@ -263,33 +273,33 @@ export class FileFileHistoryStore {
|
|
|
263
273
|
catch (err) {
|
|
264
274
|
if (err.code === "ENOENT")
|
|
265
275
|
return null;
|
|
266
|
-
this.disclose(path, `boundary unreadable (${err.code ?? "unknown"}) —
|
|
267
|
-
return
|
|
276
|
+
this.disclose(path, `boundary unreadable (${err.code ?? "unknown"}) — not a usable boundary`);
|
|
277
|
+
return caughtFault(err);
|
|
268
278
|
}
|
|
269
279
|
{
|
|
270
280
|
const doc = parseJsonRecord(raw);
|
|
271
281
|
if (doc === null) {
|
|
272
|
-
this.disclose(path, "unparseable boundary (torn/zero-byte write?) —
|
|
273
|
-
return
|
|
282
|
+
this.disclose(path, "unparseable boundary (torn/zero-byte write?) — not a usable boundary");
|
|
283
|
+
return DAMAGED_RECORD;
|
|
274
284
|
}
|
|
275
285
|
if (doc.formatVersion !== "file-history/1" || !Array.isArray(doc.files)) {
|
|
276
|
-
this.disclose(path, "boundary is not a file-history/1 pair array —
|
|
277
|
-
return
|
|
286
|
+
this.disclose(path, "boundary is not a file-history/1 pair array — not a usable boundary");
|
|
287
|
+
return DAMAGED_RECORD;
|
|
278
288
|
}
|
|
279
289
|
const parsed = { formatVersion: doc.formatVersion, files: doc.files, digest: doc.digest };
|
|
280
290
|
for (const pair of parsed.files) {
|
|
281
291
|
if (!Array.isArray(pair) || pair.length !== 2 || typeof pair[0] !== "string" || !Number.isInteger(pair[1]) || pair[1] < 1) {
|
|
282
|
-
this.disclose(path, "boundary carries a malformed mapping row —
|
|
283
|
-
return
|
|
292
|
+
this.disclose(path, "boundary carries a malformed mapping row — not a usable boundary");
|
|
293
|
+
return DAMAGED_RECORD;
|
|
284
294
|
}
|
|
285
295
|
}
|
|
286
296
|
if (new Set(parsed.files.map(([k]) => k)).size !== parsed.files.length) {
|
|
287
|
-
this.disclose(path, "boundary maps the same path twice —
|
|
288
|
-
return
|
|
297
|
+
this.disclose(path, "boundary maps the same path twice — not a usable boundary");
|
|
298
|
+
return DAMAGED_RECORD;
|
|
289
299
|
}
|
|
290
300
|
if (typeof parsed.digest !== "string" || parsed.digest !== boundaryDigest(parsed.files)) {
|
|
291
|
-
this.disclose(path, "boundary fails its own integrity digest (rows added or dropped?) —
|
|
292
|
-
return
|
|
301
|
+
this.disclose(path, "boundary fails its own integrity digest (rows added or dropped?) — not a usable boundary");
|
|
302
|
+
return DAMAGED_RECORD;
|
|
293
303
|
}
|
|
294
304
|
return new Map(parsed.files);
|
|
295
305
|
}
|
|
@@ -304,23 +314,11 @@ export class FileFileHistoryStore {
|
|
|
304
314
|
return undefined;
|
|
305
315
|
}
|
|
306
316
|
}
|
|
307
|
-
unjudgeableBoundaryIdsOf(scope) {
|
|
308
|
-
const dir = this.boundaryDir(scope);
|
|
309
|
-
let names;
|
|
310
|
-
try {
|
|
311
|
-
names = readdirSync(dir);
|
|
312
|
-
}
|
|
313
|
-
catch (err) {
|
|
314
|
-
return err.code === "ENOENT" ? null : [];
|
|
315
|
-
}
|
|
316
|
-
const bad = names.filter((f) => f.endsWith(".json") && this.readBoundary(join(dir, f)) === null).map((f) => f.slice(0, -".json".length));
|
|
317
|
-
return bad.length > 0 ? bad : null;
|
|
318
|
-
}
|
|
319
317
|
carryConsumedIds(fromScope, toScope) {
|
|
320
318
|
const spent = this.readReapedIds(fromScope);
|
|
321
|
-
if (spent
|
|
319
|
+
if (!(spent instanceof Set)) {
|
|
322
320
|
this.disclose(this.reapedLogPath(fromScope), "source consumed-id ledger unreadable — the adoption is refused rather than published without its lineage's tombstones");
|
|
323
|
-
return
|
|
321
|
+
return spent;
|
|
324
322
|
}
|
|
325
323
|
if (spent.size === 0)
|
|
326
324
|
return true;
|
|
@@ -339,7 +337,7 @@ export class FileFileHistoryStore {
|
|
|
339
337
|
if (err.code === "ENOENT")
|
|
340
338
|
return new Set();
|
|
341
339
|
this.disclose(path, `consumed-id ledger unreadable (${err.code ?? "unknown"})`);
|
|
342
|
-
return
|
|
340
|
+
return caughtFault(err);
|
|
343
341
|
}
|
|
344
342
|
const cached = this.reapedCache.get(scope);
|
|
345
343
|
if (cached !== undefined && cached.size === size)
|
|
@@ -354,7 +352,7 @@ export class FileFileHistoryStore {
|
|
|
354
352
|
}
|
|
355
353
|
catch (err) {
|
|
356
354
|
this.disclose(path, `consumed-id ledger unreadable (${err.code ?? "unknown"})`);
|
|
357
|
-
return
|
|
355
|
+
return caughtFault(err);
|
|
358
356
|
}
|
|
359
357
|
}
|
|
360
358
|
markReaped(scope, ids) {
|
|
@@ -381,7 +379,7 @@ export class FileFileHistoryStore {
|
|
|
381
379
|
}
|
|
382
380
|
catch (err) {
|
|
383
381
|
this.disclose(path, `consumed-id ledger could not be appended (${err.code ?? "unknown"}) — the boundaries it names are NOT being reaped, so this scope is not bounded until it can be written`);
|
|
384
|
-
return
|
|
382
|
+
return caughtFault(err);
|
|
385
383
|
}
|
|
386
384
|
}
|
|
387
385
|
boundaryOrderOf(path) {
|
|
@@ -409,7 +407,7 @@ export class FileFileHistoryStore {
|
|
|
409
407
|
const { key, kind, family } = describeTrackKey(root, absPath);
|
|
410
408
|
const before = this.readTrackedState(scope);
|
|
411
409
|
if (before.corrupt)
|
|
412
|
-
return { ok: false, error: { code: "track_failed", message: `file history for scope "${scope}" is unreadable — refusing to mint a first-touch record over an unusable graph
|
|
410
|
+
return { ok: false, error: { code: "track_failed", message: `file history for scope "${scope}" is unreadable — refusing to mint a first-touch record over an unusable graph`, ...before.fault } };
|
|
413
411
|
const existing = before.tracked.get(key);
|
|
414
412
|
if (existing !== undefined) {
|
|
415
413
|
if (existing.observedByLaterTouch !== true) {
|
|
@@ -421,7 +419,7 @@ export class FileFileHistoryStore {
|
|
|
421
419
|
const cap = await captureFileBackupViaEnv(env, absPath, root, signal);
|
|
422
420
|
const after = this.readTrackedState(scope);
|
|
423
421
|
if (after.corrupt)
|
|
424
|
-
return { ok: false, error: { code: "track_failed", message: `file history for scope "${scope}" became unreadable during the first-touch capture — nothing was recorded
|
|
422
|
+
return { ok: false, error: { code: "track_failed", message: `file history for scope "${scope}" became unreadable during the first-touch capture — nothing was recorded`, ...after.fault } };
|
|
425
423
|
const tracked = after.tracked;
|
|
426
424
|
const raced = tracked.get(key);
|
|
427
425
|
if (raced !== undefined) {
|
|
@@ -452,7 +450,7 @@ export class FileFileHistoryStore {
|
|
|
452
450
|
return { ok: true, minted: true };
|
|
453
451
|
}
|
|
454
452
|
catch (err) {
|
|
455
|
-
return { ok: false, error: { code: "track_failed", message: `first-touch record for ${absPath} could not be persisted: ${thrownText(err)}
|
|
453
|
+
return { ok: false, error: { code: "track_failed", message: `first-touch record for ${absPath} could not be persisted: ${thrownText(err)}`, ...caughtFault(err) } };
|
|
456
454
|
}
|
|
457
455
|
}
|
|
458
456
|
async annulTrack(scope, absPath, root, verify) {
|
|
@@ -460,13 +458,16 @@ export class FileFileHistoryStore {
|
|
|
460
458
|
const key = trackKeyOf(root, absPath);
|
|
461
459
|
const state = this.readTrackedState(scope);
|
|
462
460
|
if (state.corrupt) {
|
|
463
|
-
return { ok: false, error: { code: "
|
|
461
|
+
return { ok: false, error: { code: "track_failed", message: `file history for scope "${scope}" is unreadable — the first-touch record (if any) was left in place; repair the graph before retraction can be judged`, ...state.fault } };
|
|
464
462
|
}
|
|
465
463
|
const tracked = state.tracked;
|
|
466
464
|
const rec = tracked.get(key);
|
|
467
465
|
if (rec === undefined)
|
|
468
466
|
return { ok: true };
|
|
469
|
-
|
|
467
|
+
const listed = this.listBoundaryIds(scope);
|
|
468
|
+
if (!Array.isArray(listed))
|
|
469
|
+
return { ok: false, error: { code: "track_failed", message: `scope "${scope}" has ${listed.what} — the first-touch record for ${absPath} was left in place, since whether a boundary references it cannot be judged`, ...listed.fault } };
|
|
470
|
+
for (const entryId of listed) {
|
|
470
471
|
const bp = this.tryBoundaryPath(scope, entryId);
|
|
471
472
|
const mapping = bp === null ? null : this.readBoundary(bp);
|
|
472
473
|
if (mapping?.has(key) === true) {
|
|
@@ -480,12 +481,11 @@ export class FileFileHistoryStore {
|
|
|
480
481
|
return { ok: false, error: { code: "conflict", message: `first-touch record for ${absPath} has since been served to another edit of the same path — it is that edit's baseline now, not a retractable mint` } };
|
|
481
482
|
}
|
|
482
483
|
const proof = verify === undefined ? undefined : await worldStillMatchesMint(verify.env, absPath, root, rec.baseAvailable, rec.versions[0]?.blobHash ?? null, verify.signal);
|
|
483
|
-
if (proof !== undefined &&
|
|
484
|
-
return
|
|
485
|
-
}
|
|
484
|
+
if (proof !== undefined && proof.verdict !== "unchanged")
|
|
485
|
+
return annulProofFailure(proof, absPath);
|
|
486
486
|
const fresh = this.readTrackedState(scope);
|
|
487
487
|
if (fresh.corrupt)
|
|
488
|
-
return { ok: false, error: { code: "
|
|
488
|
+
return { ok: false, error: { code: "track_failed", message: `file history for scope "${scope}" became unreadable — the record was left in place`, ...fresh.fault } };
|
|
489
489
|
const still = fresh.tracked.get(key);
|
|
490
490
|
if (still === undefined)
|
|
491
491
|
return { ok: true };
|
|
@@ -495,7 +495,10 @@ export class FileFileHistoryStore {
|
|
|
495
495
|
if (still.mintId !== rec.mintId || still.baseAvailable !== rec.baseAvailable || still.versions.length !== rec.versions.length || still.versions[0]?.blobHash !== rec.versions[0]?.blobHash || still.versions[0]?.backupTime !== rec.versions[0]?.backupTime) {
|
|
496
496
|
return { ok: false, error: { code: "conflict", message: `first-touch record for ${absPath} was replaced while this retraction was being proven — the record now there belongs to a newer edit` } };
|
|
497
497
|
}
|
|
498
|
-
|
|
498
|
+
const relisted = this.listBoundaryIds(scope);
|
|
499
|
+
if (!Array.isArray(relisted))
|
|
500
|
+
return { ok: false, error: { code: "track_failed", message: `scope "${scope}" came to have ${relisted.what} while this retraction was being proven — the record was left in place`, ...relisted.fault } };
|
|
501
|
+
for (const entryId of relisted) {
|
|
499
502
|
const bp2 = this.tryBoundaryPath(scope, entryId);
|
|
500
503
|
const mapping2 = bp2 === null ? null : this.readBoundary(bp2);
|
|
501
504
|
if (mapping2?.has(key) === true) {
|
|
@@ -507,53 +510,65 @@ export class FileFileHistoryStore {
|
|
|
507
510
|
return { ok: true };
|
|
508
511
|
}
|
|
509
512
|
catch (err) {
|
|
510
|
-
return { ok: false, error: { code: "track_failed", message: `annulling the first-touch record for ${absPath} failed: ${thrownText(err)}
|
|
513
|
+
return { ok: false, error: { code: "track_failed", message: `annulling the first-touch record for ${absPath} failed: ${thrownText(err)}`, ...caughtFault(err) } };
|
|
511
514
|
}
|
|
512
515
|
}
|
|
513
516
|
scopeIsEmptySync(scope) {
|
|
514
517
|
const state = this.readTrackedState(scope);
|
|
515
518
|
if (state.corrupt)
|
|
516
|
-
return
|
|
517
|
-
|
|
519
|
+
return { fault: state.fault, what: "an unreadable tracked set" };
|
|
520
|
+
const listed = this.listBoundaryIds(scope);
|
|
521
|
+
if (!Array.isArray(listed))
|
|
522
|
+
return listed;
|
|
523
|
+
return state.tracked.size === 0 && listed.length === 0 ? "empty" : "not_empty";
|
|
524
|
+
}
|
|
525
|
+
async importTargetOf(scope, data, when) {
|
|
526
|
+
const emptiness = this.scopeIsEmptySync(scope);
|
|
527
|
+
if (emptiness === "empty")
|
|
528
|
+
return "empty";
|
|
529
|
+
if (emptiness !== "not_empty") {
|
|
530
|
+
return { ok: false, error: { code: "adopt_failed", message: `importHistory target "${scope}" ${when === "before" ? "has" : "came to have"} ${emptiness.what} — a scope whose history cannot be judged is not an empty target; nothing was ${when === "before" ? "fetched or " : ""}published`, ...emptiness.fault } };
|
|
531
|
+
}
|
|
532
|
+
const existing = await this.exportHistory(scope);
|
|
533
|
+
if (existing.ok && existing.history !== null && fileHistoryExportDigest(existing.history) === fileHistoryExportDigest(data))
|
|
534
|
+
return "identical";
|
|
535
|
+
const message = when === "before"
|
|
536
|
+
? `importHistory target "${scope}" was judged not empty and not this envelope — it holds a DIFFERENT history, or it changed (or could not be read) between the two reads that judge it — a first import requires an empty target and a retry is legal only for the identical envelope (atomic visibility prevents half-graphs; this law prevents publishing the wrong complete graph over locally-grown history)`
|
|
537
|
+
: `importHistory target "${scope}" changed while this import was fetching blobs — it gained a DIFFERENT history, or changed (or could not be read) between the two reads that judge it — nothing was published`;
|
|
538
|
+
return { ok: false, error: { code: "conflict", message } };
|
|
518
539
|
}
|
|
519
540
|
publishStagedScopeSync(scope, staging) {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
try {
|
|
526
|
-
return readdirSync(this.boundaryDir(scope));
|
|
527
|
-
}
|
|
528
|
-
catch {
|
|
529
|
-
return [];
|
|
530
|
-
}
|
|
531
|
-
})()) {
|
|
532
|
-
if (f.endsWith(".json"))
|
|
533
|
-
destroyed.push(f.slice(0, -".json".length));
|
|
534
|
-
}
|
|
535
|
-
if (!this.markReaped(scope, destroyed))
|
|
536
|
-
return "ledger_failed";
|
|
537
|
-
safeRm(target);
|
|
538
|
-
renameSync(staging, target);
|
|
541
|
+
const emptiness = this.scopeIsEmptySync(scope);
|
|
542
|
+
if (emptiness !== "empty")
|
|
543
|
+
return emptiness;
|
|
544
|
+
safeRm(this.scopeDir(scope));
|
|
545
|
+
renameSync(staging, this.scopeDir(scope));
|
|
539
546
|
return "published";
|
|
540
547
|
}
|
|
541
548
|
listBoundaryIds(scope) {
|
|
542
549
|
const dir = this.boundaryDir(scope);
|
|
543
|
-
let
|
|
550
|
+
let names;
|
|
544
551
|
try {
|
|
545
|
-
|
|
552
|
+
names = readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
546
553
|
}
|
|
547
554
|
catch (err) {
|
|
548
|
-
if (err.code
|
|
549
|
-
|
|
550
|
-
}
|
|
551
|
-
return
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
555
|
+
if (err.code === "ENOENT")
|
|
556
|
+
return [];
|
|
557
|
+
this.disclose(dir, `boundary directory unreadable (${err.code ?? "unknown"}) — this scope's history cannot be judged until it can be listed`);
|
|
558
|
+
return { fault: caughtFault(err), what: "a boundary directory that cannot be listed" };
|
|
559
|
+
}
|
|
560
|
+
const ids = [];
|
|
561
|
+
const unusable = [];
|
|
562
|
+
const faults = [];
|
|
563
|
+
for (const f of names) {
|
|
564
|
+
const read = this.readBoundaryState(join(dir, f));
|
|
565
|
+
(read instanceof Map ? ids : unusable).push(f.slice(0, -".json".length));
|
|
566
|
+
if (!(read instanceof Map))
|
|
567
|
+
faults.push(read ?? {});
|
|
568
|
+
}
|
|
569
|
+
if (unusable.length === 0)
|
|
570
|
+
return ids;
|
|
571
|
+
return { fault: worstFault(faults), what: `boundaries that cannot be used (${unusable.slice(0, 3).map((i) => JSON.stringify(i)).join(", ")}${unusable.length > 3 ? ", …" : ""})` };
|
|
557
572
|
}
|
|
558
573
|
async snapshot(scope, entryId, env, root, signal) {
|
|
559
574
|
const bpath = this.tryBoundaryPath(scope, entryId);
|
|
@@ -562,8 +577,8 @@ export class FileFileHistoryStore {
|
|
|
562
577
|
if (this.readBoundary(bpath) !== null)
|
|
563
578
|
return { ok: true };
|
|
564
579
|
const consumed = this.readReapedIds(scope);
|
|
565
|
-
if (consumed
|
|
566
|
-
return { ok: false, error: { code: "snapshot_failed", message: `the consumed-entry ledger for scope "${scope}" cannot be read — refusing to mint a boundary while it is impossible to tell a fresh entry id from one retention already reaped
|
|
580
|
+
if (!(consumed instanceof Set)) {
|
|
581
|
+
return { ok: false, error: { code: "snapshot_failed", message: `the consumed-entry ledger for scope "${scope}" cannot be read — refusing to mint a boundary while it is impossible to tell a fresh entry id from one retention already reaped`, ...consumed } };
|
|
567
582
|
}
|
|
568
583
|
if (consumed.has(entryId)) {
|
|
569
584
|
return { ok: false, error: { code: "snapshot_failed", message: `entry "${entryId}" already had a boundary and it was reaped by retention — a fresh capture now would record post-turn bytes under a pre-turn key, so this entry has no boundary and cannot get one back` } };
|
|
@@ -582,7 +597,7 @@ export class FileFileHistoryStore {
|
|
|
582
597
|
const state = this.readTrackedState(scope);
|
|
583
598
|
if (state.corrupt) {
|
|
584
599
|
nestedSetAdd(this.spentAttempts, scope, entryId);
|
|
585
|
-
return { ok: false, error: { code: "snapshot_failed", message: `file history for scope "${scope}" is unreadable — a boundary minted over an unusable graph would claim to restore state that is not there
|
|
600
|
+
return { ok: false, error: { code: "snapshot_failed", message: `file history for scope "${scope}" is unreadable — a boundary minted over an unusable graph would claim to restore state that is not there`, ...state.fault } };
|
|
586
601
|
}
|
|
587
602
|
const tracked = state.tracked;
|
|
588
603
|
const staged = new Map();
|
|
@@ -628,7 +643,7 @@ export class FileFileHistoryStore {
|
|
|
628
643
|
const currentState = this.readTrackedState(scope);
|
|
629
644
|
if (currentState.corrupt) {
|
|
630
645
|
nestedSetAdd(this.spentAttempts, scope, entryId);
|
|
631
|
-
return { ok: false, error: { code: "snapshot_failed", message: `file history for scope "${scope}" became unreadable during the capture — no boundary was published
|
|
646
|
+
return { ok: false, error: { code: "snapshot_failed", message: `file history for scope "${scope}" became unreadable during the capture — no boundary was published`, ...currentState.fault } };
|
|
632
647
|
}
|
|
633
648
|
const current = currentState.tracked;
|
|
634
649
|
for (const [key, cap] of staged) {
|
|
@@ -663,9 +678,10 @@ export class FileFileHistoryStore {
|
|
|
663
678
|
catch (err) {
|
|
664
679
|
if (err.code !== "EEXIST")
|
|
665
680
|
throw err;
|
|
666
|
-
|
|
681
|
+
const existing = this.readBoundaryState(bpath);
|
|
682
|
+
if (!(existing instanceof Map)) {
|
|
667
683
|
nestedSetAdd(this.spentAttempts, scope, entryId);
|
|
668
|
-
return { ok: false, error: { code: "snapshot_failed", message: `a boundary file for entry "${entryId}" already exists but cannot be read — this turn has no usable boundary (the unreadable file is left in place for an operator rather than silently replaced)
|
|
684
|
+
return { ok: false, error: { code: "snapshot_failed", message: `a boundary file for entry "${entryId}" already exists but cannot be read — this turn has no usable boundary (the unreadable file is left in place for an operator rather than silently replaced)`, ...existing } };
|
|
669
685
|
}
|
|
670
686
|
}
|
|
671
687
|
this.applyBoundaryRetention(scope, entryId);
|
|
@@ -673,7 +689,7 @@ export class FileFileHistoryStore {
|
|
|
673
689
|
}
|
|
674
690
|
catch (err) {
|
|
675
691
|
nestedSetAdd(this.spentAttempts, scope, entryId);
|
|
676
|
-
return { ok: false, error: { code: "snapshot_failed", message: `boundary for entry "${entryId}" could not be committed: ${thrownText(err)}
|
|
692
|
+
return { ok: false, error: { code: "snapshot_failed", message: `boundary for entry "${entryId}" could not be committed: ${thrownText(err)}`, ...caughtFault(err) } };
|
|
677
693
|
}
|
|
678
694
|
finally {
|
|
679
695
|
this.activeCaptures.get(scope)?.delete(entryId);
|
|
@@ -685,13 +701,16 @@ export class FileFileHistoryStore {
|
|
|
685
701
|
let modeNotPreserved = 0;
|
|
686
702
|
try {
|
|
687
703
|
const bpath = this.tryBoundaryPath(scope, entryId);
|
|
688
|
-
const boundary = bpath === null ? null : this.
|
|
704
|
+
const boundary = bpath === null ? null : this.readBoundaryState(bpath);
|
|
689
705
|
if (boundary === null) {
|
|
690
706
|
return { outcome: "failed", ...ledger, error: { code: "not_found", message: `no history boundary for entry "${entryId}"` } };
|
|
691
707
|
}
|
|
708
|
+
if (!(boundary instanceof Map)) {
|
|
709
|
+
return { outcome: "failed", ...ledger, error: { code: "restore_failed", message: `the history boundary for entry "${entryId}" is there but cannot be used — NOTHING was restored`, ...boundary } };
|
|
710
|
+
}
|
|
692
711
|
const state = this.readTrackedState(scope);
|
|
693
712
|
if (state.corrupt) {
|
|
694
|
-
return { outcome: "failed", ...ledger, error: { code: "restore_failed", message: `file history for scope "${scope}" is unreadable — the boundary exists but its version records cannot be read, so NOTHING was restored
|
|
713
|
+
return { outcome: "failed", ...ledger, error: { code: "restore_failed", message: `file history for scope "${scope}" is unreadable — the boundary exists but its version records cannot be read, so NOTHING was restored`, ...state.fault } };
|
|
695
714
|
}
|
|
696
715
|
const tracked = state.tracked;
|
|
697
716
|
for (const key of [...tracked.keys()].sort()) {
|
|
@@ -703,7 +722,7 @@ export class FileFileHistoryStore {
|
|
|
703
722
|
let targetVersion = boundary.get(key);
|
|
704
723
|
if (targetVersion === undefined) {
|
|
705
724
|
if (!rec.baseAvailable) {
|
|
706
|
-
ledger.refused.push({ path: key, reason: "base_unavailable" });
|
|
725
|
+
ledger.refused.push({ path: key, reason: "base_unavailable", class: "base_unavailable" });
|
|
707
726
|
continue;
|
|
708
727
|
}
|
|
709
728
|
targetVersion = 1;
|
|
@@ -715,7 +734,7 @@ export class FileFileHistoryStore {
|
|
|
715
734
|
}
|
|
716
735
|
const resolved = resolveTrackKey(root, key, descriptorOf(rec));
|
|
717
736
|
if (!resolved.ok) {
|
|
718
|
-
ledger.refused.push({ path: key, reason: resolved.reason });
|
|
737
|
+
ledger.refused.push({ path: key, reason: resolved.reason, class: resolved.class });
|
|
719
738
|
continue;
|
|
720
739
|
}
|
|
721
740
|
let target;
|
|
@@ -757,7 +776,7 @@ export class FileFileHistoryStore {
|
|
|
757
776
|
else if (applied.outcome === "identical")
|
|
758
777
|
ledger.identicalSkipped.push(key);
|
|
759
778
|
else if (applied.outcome === "refused")
|
|
760
|
-
ledger.refused.push({ path: key, reason: applied.reason });
|
|
779
|
+
ledger.refused.push({ path: key, reason: applied.reason, class: applied.class });
|
|
761
780
|
else
|
|
762
781
|
ledger.failed.push({ path: key, reason: applied.reason });
|
|
763
782
|
if ((applied.outcome === "applied" || applied.outcome === "identical") && applied.modeNotPreserved === true)
|
|
@@ -767,7 +786,7 @@ export class FileFileHistoryStore {
|
|
|
767
786
|
}
|
|
768
787
|
catch (err) {
|
|
769
788
|
const touched = ledger.filesChanged.length > 0 || ledger.identicalSkipped.length > 0 || ledger.refused.length > 0 || ledger.failed.length > 0;
|
|
770
|
-
return { outcome: touched ? "partial" : "failed", ...ledger, error: { code: "restore_failed", message: thrownText(err) } };
|
|
789
|
+
return { outcome: touched ? "partial" : "failed", ...ledger, error: { code: "restore_failed", message: thrownText(err), ...caughtFault(err) } };
|
|
771
790
|
}
|
|
772
791
|
}
|
|
773
792
|
async canRestore(scope, entryId) {
|
|
@@ -854,7 +873,7 @@ export class FileFileHistoryStore {
|
|
|
854
873
|
const id = file.slice(0, -".json".length);
|
|
855
874
|
if (keep.has(id))
|
|
856
875
|
continue;
|
|
857
|
-
if (
|
|
876
|
+
if (this.markReaped(scope, [id]) !== true) {
|
|
858
877
|
survivors.add(id);
|
|
859
878
|
continue;
|
|
860
879
|
}
|
|
@@ -1006,28 +1025,25 @@ export class FileFileHistoryStore {
|
|
|
1006
1025
|
try {
|
|
1007
1026
|
if (fromScope === toScope)
|
|
1008
1027
|
return { ok: true };
|
|
1009
|
-
const
|
|
1010
|
-
if (
|
|
1011
|
-
return { ok: false, error: { code: "adopt_failed", message: `adoptScope target "${toScope}" has an unreadable tracked set — a scope whose bytes cannot be judged is not an empty target` } };
|
|
1012
|
-
}
|
|
1013
|
-
const targetTracked = targetState.tracked;
|
|
1014
|
-
const targetBoundaries = this.listBoundaryIds(toScope);
|
|
1015
|
-
if (targetTracked.size > 0 || targetBoundaries.length > 0) {
|
|
1028
|
+
const target = this.scopeIsEmptySync(toScope);
|
|
1029
|
+
if (target === "not_empty") {
|
|
1016
1030
|
return { ok: false, error: { code: "conflict", message: `adoptScope target "${toScope}" already has history of its own — adoption is legal only onto an EMPTY scope (the fork/resume boundary before the new session's first turn)` } };
|
|
1017
1031
|
}
|
|
1032
|
+
if (target !== "empty")
|
|
1033
|
+
return { ok: false, error: { code: "adopt_failed", message: `adoptScope target "${toScope}" has ${target.what} — a scope whose history cannot be judged is not an empty target; nothing was published`, ...target.fault } };
|
|
1018
1034
|
const sourceState = this.readTrackedState(fromScope);
|
|
1019
1035
|
if (sourceState.corrupt) {
|
|
1020
|
-
return { ok: false, error: { code: "adopt_failed", message: `adoptScope source "${fromScope}" has an unreadable tracked set — adopting it would publish boundaries with no version records behind them
|
|
1036
|
+
return { ok: false, error: { code: "adopt_failed", message: `adoptScope source "${fromScope}" has an unreadable tracked set — adopting it would publish boundaries with no version records behind them`, ...sourceState.fault } };
|
|
1021
1037
|
}
|
|
1022
1038
|
const source = sourceState.tracked;
|
|
1023
|
-
const unjudgeable = this.unjudgeableBoundaryIdsOf(fromScope);
|
|
1024
|
-
if (unjudgeable !== null) {
|
|
1025
|
-
return { ok: false, error: { code: "adopt_failed", message: `adoptScope source "${fromScope}" has ${unjudgeable.length > 0 ? `boundaries that cannot be judged (${unjudgeable.slice(0, 3).map((i) => JSON.stringify(i)).join(", ")}${unjudgeable.length > 3 ? ", …" : ""})` : "a boundary directory that cannot be listed"} — adopting it would publish a graph that silently drops those turns and hands their entry ids back to the fork; nothing was published` } };
|
|
1026
|
-
}
|
|
1027
1039
|
const sourceBoundaries = this.listBoundaryIds(fromScope);
|
|
1040
|
+
if (!Array.isArray(sourceBoundaries)) {
|
|
1041
|
+
return { ok: false, error: { code: "adopt_failed", message: `adoptScope source "${fromScope}" has ${sourceBoundaries.what} — adopting it would publish a graph that silently drops those turns and hands their entry ids back to the fork; nothing was published`, ...sourceBoundaries.fault } };
|
|
1042
|
+
}
|
|
1028
1043
|
if (source.size === 0 && sourceBoundaries.length === 0) {
|
|
1029
|
-
|
|
1030
|
-
|
|
1044
|
+
const carried = this.carryConsumedIds(fromScope, toScope);
|
|
1045
|
+
if (carried !== true) {
|
|
1046
|
+
return { ok: false, error: { code: "adopt_failed", message: `adoptScope could not carry the consumed-entry ledger from "${fromScope}" to "${toScope}" — refusing rather than reporting a carry that would let an already-consumed entry id be minted again in the fork`, ...carried } };
|
|
1031
1047
|
}
|
|
1032
1048
|
return { ok: true };
|
|
1033
1049
|
}
|
|
@@ -1035,15 +1051,16 @@ export class FileFileHistoryStore {
|
|
|
1035
1051
|
for (const v of rec.versions) {
|
|
1036
1052
|
if (v.blobHash === null)
|
|
1037
1053
|
continue;
|
|
1038
|
-
let
|
|
1054
|
+
let fault;
|
|
1039
1055
|
try {
|
|
1040
|
-
|
|
1056
|
+
if (createHash("sha256").update(readFileSync(this.blobPath(v.blobHash))).digest("hex") !== v.blobHash)
|
|
1057
|
+
fault = DAMAGED_RECORD;
|
|
1041
1058
|
}
|
|
1042
|
-
catch {
|
|
1043
|
-
|
|
1059
|
+
catch (err) {
|
|
1060
|
+
fault = err.code === "ENOENT" ? DAMAGED_RECORD : caughtFault(err);
|
|
1044
1061
|
}
|
|
1045
|
-
if (
|
|
1046
|
-
return { ok: false, error: { code: "adopt_failed", message: `adoptScope source "${fromScope}" references blob ${v.blobHash} for ${key}@v${v.version}, which is missing or fails content-address integrity — nothing was published
|
|
1062
|
+
if (fault !== undefined) {
|
|
1063
|
+
return { ok: false, error: { code: "adopt_failed", message: `adoptScope source "${fromScope}" references blob ${v.blobHash} for ${key}@v${v.version}, which is missing or fails content-address integrity — nothing was published`, ...fault } };
|
|
1047
1064
|
}
|
|
1048
1065
|
}
|
|
1049
1066
|
}
|
|
@@ -1068,16 +1085,17 @@ export class FileFileHistoryStore {
|
|
|
1068
1085
|
const bdoc = { formatVersion: "file-history/1", files: [...mapping], digest: boundaryDigest([...mapping]), ...(sourceCommittedAt !== undefined ? { committedAt: sourceCommittedAt } : {}) };
|
|
1069
1086
|
atomicWriteFile(join(this.base, "tmp"), join(staging, "boundaries", `${historyPathComponent(id)}.json`), JSON.stringify(bdoc));
|
|
1070
1087
|
}
|
|
1071
|
-
|
|
1088
|
+
const carried = this.carryConsumedIds(fromScope, toScope);
|
|
1089
|
+
if (carried !== true) {
|
|
1072
1090
|
safeRm(staging);
|
|
1073
|
-
return { ok: false, error: { code: "adopt_failed", message: `adoptScope could not carry the consumed-entry ledger from "${fromScope}" to "${toScope}" — nothing was published, because a fork missing its lineage's tombstones can mint an already-consumed entry id
|
|
1091
|
+
return { ok: false, error: { code: "adopt_failed", message: `adoptScope could not carry the consumed-entry ledger from "${fromScope}" to "${toScope}" — nothing was published, because a fork missing its lineage's tombstones can mint an already-consumed entry id`, ...carried } };
|
|
1074
1092
|
}
|
|
1075
1093
|
const published = this.publishStagedScopeSync(toScope, staging);
|
|
1076
1094
|
if (published !== "published") {
|
|
1077
1095
|
safeRm(staging);
|
|
1078
1096
|
return published === "not_empty"
|
|
1079
1097
|
? { ok: false, error: { code: "conflict", message: `adoptScope target "${toScope}" gained history of its own while this adoption was being staged — nothing was published` } }
|
|
1080
|
-
: { ok: false, error: { code: "adopt_failed", message: `adoptScope
|
|
1098
|
+
: { ok: false, error: { code: "adopt_failed", message: `adoptScope target "${toScope}" came to have ${published.what} while this adoption was being staged — a scope whose history cannot be judged is not an empty target; nothing was published`, ...published.fault } };
|
|
1081
1099
|
}
|
|
1082
1100
|
}
|
|
1083
1101
|
catch (err) {
|
|
@@ -1087,27 +1105,29 @@ export class FileFileHistoryStore {
|
|
|
1087
1105
|
return { ok: true };
|
|
1088
1106
|
}
|
|
1089
1107
|
catch (err) {
|
|
1090
|
-
return { ok: false, error: { code: "adopt_failed", message: `adoptScope failed: ${thrownText(err)}
|
|
1108
|
+
return { ok: false, error: { code: "adopt_failed", message: `adoptScope failed: ${thrownText(err)}`, ...caughtFault(err) } };
|
|
1091
1109
|
}
|
|
1092
1110
|
}
|
|
1093
1111
|
async exportHistory(scope) {
|
|
1112
|
+
const unexportable = (what, fault) => ({ ok: false, error: { code: "adopt_failed", message: `exportHistory scope "${scope}" has ${what} — its history cannot be exported whole, so nothing was exported`, ...fault } });
|
|
1094
1113
|
const state = this.readTrackedState(scope);
|
|
1095
|
-
if (state.corrupt)
|
|
1096
|
-
return
|
|
1097
|
-
}
|
|
1114
|
+
if (state.corrupt)
|
|
1115
|
+
return unexportable("an unreadable tracked set", state.fault);
|
|
1098
1116
|
const tracked = state.tracked;
|
|
1099
1117
|
const boundaryIds = this.listBoundaryIds(scope);
|
|
1118
|
+
if (!Array.isArray(boundaryIds))
|
|
1119
|
+
return unexportable(boundaryIds.what, boundaryIds.fault);
|
|
1100
1120
|
if (tracked.size === 0 && boundaryIds.length === 0)
|
|
1101
|
-
return null;
|
|
1121
|
+
return { ok: true, history: null };
|
|
1102
1122
|
const boundaries = [];
|
|
1103
1123
|
for (const entryId of [...boundaryIds].sort()) {
|
|
1104
1124
|
const bp = this.tryBoundaryPath(scope, entryId);
|
|
1105
1125
|
const mapping = bp === null ? null : this.readBoundary(bp);
|
|
1106
1126
|
if (mapping === null)
|
|
1107
|
-
|
|
1127
|
+
return unexportable(`a boundary ("${entryId}") that stopped being usable while it was exported`, {});
|
|
1108
1128
|
boundaries.push({ entryId, files: [...mapping.entries()].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)).map(([relOrAbsPath, version]) => ({ relOrAbsPath, version })) });
|
|
1109
1129
|
}
|
|
1110
|
-
|
|
1130
|
+
const history = {
|
|
1111
1131
|
formatVersion: "file-history/1",
|
|
1112
1132
|
tracked: [...tracked.entries()]
|
|
1113
1133
|
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
@@ -1120,20 +1140,17 @@ export class FileFileHistoryStore {
|
|
|
1120
1140
|
})),
|
|
1121
1141
|
boundaries,
|
|
1122
1142
|
};
|
|
1143
|
+
return { ok: true, history };
|
|
1123
1144
|
}
|
|
1124
1145
|
async importHistory(scope, data, srcGetBlob) {
|
|
1125
1146
|
try {
|
|
1126
1147
|
const shaped = validateFileHistoryExport(data);
|
|
1127
1148
|
if (!shaped.ok)
|
|
1128
1149
|
return shaped;
|
|
1129
|
-
const
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
identicalRepublish = true;
|
|
1134
|
-
else
|
|
1135
|
-
return { ok: false, error: { code: "conflict", message: `importHistory target "${scope}" already holds a DIFFERENT history — a first import requires an empty target and a retry is legal only for the identical envelope (atomic visibility prevents half-graphs; this law prevents publishing the wrong complete graph over locally-grown history)` } };
|
|
1136
|
-
}
|
|
1150
|
+
const target = await this.importTargetOf(scope, data, "before");
|
|
1151
|
+
if (typeof target === "object")
|
|
1152
|
+
return target;
|
|
1153
|
+
const identicalRepublish = target === "identical";
|
|
1137
1154
|
const importJournal = join(this.scopeDir(scope), "staging", `import-${Date.now().toString(36)}-${randomBytes(6).toString("hex")}.jsonl`);
|
|
1138
1155
|
ensureDir(join(this.scopeDir(scope), "staging"));
|
|
1139
1156
|
appendFileSync(importJournal, `${JSON.stringify({ entryId: `import:${scope}`, pid: process.pid, startedAt: new Date().toISOString() })}\n`);
|
|
@@ -1147,7 +1164,7 @@ export class FileFileHistoryStore {
|
|
|
1147
1164
|
return await this.runImport(scope, data, srcGetBlob, importJournal, identicalRepublish);
|
|
1148
1165
|
}
|
|
1149
1166
|
catch (err) {
|
|
1150
|
-
return { ok: false, error: { code: "unsupported_format", message: `importHistory failed: ${thrownText(err)}
|
|
1167
|
+
return { ok: false, error: { code: "unsupported_format", message: `importHistory failed: ${thrownText(err)}`, ...caughtFault(err) } };
|
|
1151
1168
|
}
|
|
1152
1169
|
}
|
|
1153
1170
|
async runImport(scope, data, srcGetBlob, importJournal, identicalRepublish) {
|
|
@@ -1174,10 +1191,10 @@ export class FileFileHistoryStore {
|
|
|
1174
1191
|
bytes = await srcGetBlob(v.blobHash);
|
|
1175
1192
|
}
|
|
1176
1193
|
catch (err) {
|
|
1177
|
-
return { ok: false, error: { code: "unsupported_format", message: `source blob ${v.blobHash} fetch failed: ${thrownText(err)}
|
|
1194
|
+
return { ok: false, error: { code: "unsupported_format", message: `source blob ${v.blobHash} fetch failed: ${thrownText(err)}`, ...caughtFault(err) } };
|
|
1178
1195
|
}
|
|
1179
1196
|
if (bytes === undefined)
|
|
1180
|
-
return { ok: false, error: { code: "
|
|
1197
|
+
return { ok: false, error: { code: "adopt_failed", message: `source blob ${v.blobHash} is missing — the envelope's graph cannot be completed, so nothing is published` } };
|
|
1181
1198
|
if (createHash("sha256").update(bytes).digest("hex") !== v.blobHash) {
|
|
1182
1199
|
return { ok: false, error: { code: "unsupported_format", message: `source blob ${v.blobHash} fails content-address integrity — refused, nothing published` } };
|
|
1183
1200
|
}
|
|
@@ -1186,12 +1203,11 @@ export class FileFileHistoryStore {
|
|
|
1186
1203
|
}
|
|
1187
1204
|
if (identicalRepublish)
|
|
1188
1205
|
return { ok: true };
|
|
1189
|
-
const now = await this.
|
|
1190
|
-
if (now
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
return
|
|
1194
|
-
}
|
|
1206
|
+
const now = await this.importTargetOf(scope, data, "after");
|
|
1207
|
+
if (now === "identical")
|
|
1208
|
+
return { ok: true };
|
|
1209
|
+
if (now !== "empty")
|
|
1210
|
+
return now;
|
|
1195
1211
|
const staging = `${this.scopeDir(scope)}.importing-${process.pid}-${randomBytes(6).toString("hex")}`;
|
|
1196
1212
|
safeRm(staging);
|
|
1197
1213
|
try {
|
|
@@ -1218,13 +1234,13 @@ export class FileFileHistoryStore {
|
|
|
1218
1234
|
}
|
|
1219
1235
|
catch (err) {
|
|
1220
1236
|
safeRm(staging);
|
|
1221
|
-
return { ok: false, error: { code: "adopt_failed", message: `importHistory could not publish the staged graph for "${scope}": ${thrownText(err)} — nothing was published (a local storage fault, not a malformed envelope)
|
|
1237
|
+
return { ok: false, error: { code: "adopt_failed", message: `importHistory could not publish the staged graph for "${scope}": ${thrownText(err)} — nothing was published (a local storage fault, not a malformed envelope)`, ...caughtFault(err) } };
|
|
1222
1238
|
}
|
|
1223
1239
|
if (published !== "published") {
|
|
1224
1240
|
safeRm(staging);
|
|
1225
1241
|
return published === "not_empty"
|
|
1226
1242
|
? { ok: false, error: { code: "conflict", message: `importHistory target "${scope}" gained history of its own while this import was being staged — nothing was published` } }
|
|
1227
|
-
: { ok: false, error: { code: "adopt_failed", message: `importHistory
|
|
1243
|
+
: { ok: false, error: { code: "adopt_failed", message: `importHistory target "${scope}" came to have ${published.what} while this import was being staged — a scope whose history cannot be judged is not an empty target; nothing was published`, ...published.fault } };
|
|
1228
1244
|
}
|
|
1229
1245
|
}
|
|
1230
1246
|
catch (err) {
|
|
@@ -1234,7 +1250,7 @@ export class FileFileHistoryStore {
|
|
|
1234
1250
|
return { ok: true };
|
|
1235
1251
|
}
|
|
1236
1252
|
catch (err) {
|
|
1237
|
-
return { ok: false, error: { code: "unsupported_format", message: `importHistory failed: ${thrownText(err)}
|
|
1253
|
+
return { ok: false, error: { code: "unsupported_format", message: `importHistory failed: ${thrownText(err)}`, ...caughtFault(err) } };
|
|
1238
1254
|
}
|
|
1239
1255
|
finally {
|
|
1240
1256
|
safeRm(importJournal);
|