@adhdev/daemon-core 0.9.82-rc.49 → 0.9.82-rc.491
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/dist/boot/daemon-lifecycle.d.ts +9 -0
- package/dist/boot/process-hardening.d.ts +50 -0
- package/dist/build-info.d.ts +37 -0
- package/dist/chat/source-machine.d.ts +166 -0
- package/dist/chat/source-resolver.d.ts +104 -0
- package/dist/chat/subscription-updates.d.ts +1 -0
- package/dist/cli-adapter-types.d.ts +68 -2
- package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
- package/dist/cli-adapters/cli-state-engine.d.ts +220 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +137 -64
- package/dist/cli-adapters/provider-cli-parse.d.ts +5 -0
- package/dist/cli-adapters/provider-cli-runtime.d.ts +34 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +74 -0
- package/dist/cli-adapters/pty-write-chunking.d.ts +34 -0
- package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
- package/dist/cli-adapters/resolve-executable.d.ts +69 -0
- package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +6 -3
- package/dist/cli-adapters/terminal-backends/types.d.ts +10 -2
- package/dist/cli-adapters/terminal-screen.d.ts +4 -11
- package/dist/commands/chat-commands-debug-bundle.d.ts +14 -0
- package/dist/commands/chat-commands-read.d.ts +23 -0
- package/dist/commands/chat-commands-scope.d.ts +39 -0
- package/dist/commands/chat-commands-shared.d.ts +33 -0
- package/dist/commands/chat-commands-write.d.ts +14 -0
- package/dist/commands/chat-commands.d.ts +10 -23
- package/dist/commands/cli-manager.d.ts +71 -1
- package/dist/commands/handler.d.ts +125 -0
- package/dist/commands/high-family/index.d.ts +3 -0
- package/dist/commands/high-family/mesh-coordinator-launch.d.ts +2 -0
- package/dist/commands/high-family/mesh-events.d.ts +2 -0
- package/dist/commands/high-family/mesh-status.d.ts +2 -0
- package/dist/commands/high-family/types.d.ts +64 -0
- package/dist/commands/low-family/coordinator-prompt.d.ts +9 -0
- package/dist/commands/low-family/daemon-lifecycle.d.ts +2 -0
- package/dist/commands/low-family/diagnostics.d.ts +2 -0
- package/dist/commands/low-family/index.d.ts +3 -0
- package/dist/commands/low-family/mesh-ledger.d.ts +10 -0
- package/dist/commands/low-family/mesh-node-logs.d.ts +2 -0
- package/dist/commands/low-family/notification.d.ts +2 -0
- package/dist/commands/low-family/refine-config.d.ts +2 -0
- package/dist/commands/low-family/session-host.d.ts +2 -0
- package/dist/commands/low-family/spec-providerdev.d.ts +11 -0
- package/dist/commands/low-family/status-meta.d.ts +2 -0
- package/dist/commands/low-family/types.d.ts +33 -0
- package/dist/commands/med-family/cli-agent.d.ts +2 -0
- package/dist/commands/med-family/fast-forward.d.ts +2 -0
- package/dist/commands/med-family/ide.d.ts +10 -0
- package/dist/commands/med-family/index.d.ts +3 -0
- package/dist/commands/med-family/mesh-crud.d.ts +48 -0
- package/dist/commands/med-family/mesh-host-pairing.d.ts +2 -0
- package/dist/commands/med-family/mesh-queue.d.ts +2 -0
- package/dist/commands/med-family/mesh-restart.d.ts +2 -0
- package/dist/commands/med-family/types.d.ts +152 -0
- package/dist/commands/mesh-coordinator.d.ts +85 -1
- package/dist/commands/router-aggregate-status.d.ts +24 -0
- package/dist/commands/router-mesh-session-owner.d.ts +59 -0
- package/dist/commands/router-refine.d.ts +151 -0
- package/dist/commands/router-worktree-cleanup.d.ts +133 -0
- package/dist/commands/router.d.ts +203 -15
- package/dist/commands/upgrade-helper.d.ts +41 -1
- package/dist/config/chat-history.d.ts +11 -0
- package/dist/config/config.d.ts +19 -0
- package/dist/config/mesh-config.d.ts +66 -0
- package/dist/config/mesh-json-config.d.ts +199 -0
- package/dist/config/registry-resolver.d.ts +54 -0
- package/dist/config/repo-settings.d.ts +77 -0
- package/dist/config/state-store.d.ts +30 -0
- package/dist/daemon/dev-server.d.ts +0 -2
- package/dist/detection/cli-detector.d.ts +17 -0
- package/dist/detection/ide-detector.d.ts +13 -0
- package/dist/detection/win32-ide-version.d.ts +37 -0
- package/dist/git/change-impact-config.d.ts +159 -0
- package/dist/git/git-commands.d.ts +26 -2
- package/dist/git/git-diff.d.ts +6 -0
- package/dist/git/git-executor.d.ts +11 -0
- package/dist/git/git-status.d.ts +80 -0
- package/dist/git/git-types.d.ts +2 -50
- package/dist/git/git-worktree.d.ts +71 -1
- package/dist/git/index.d.ts +3 -1
- package/dist/index.d.ts +70 -17
- package/dist/index.js +53556 -19074
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +53380 -19063
- package/dist/index.mjs.map +1 -1
- package/dist/installer.d.ts +1 -4
- package/dist/ipc/local-ipc-server.d.ts +91 -0
- package/dist/launch.d.ts +1 -1
- package/dist/logging/async-batch-writer.d.ts +10 -0
- package/dist/logging/debug-config.d.ts +16 -0
- package/dist/logging/log-redactor.d.ts +24 -0
- package/dist/logging/log-tail-reader.d.ts +81 -0
- package/dist/logging/logger.d.ts +1 -1
- package/dist/mesh/contracts.d.ts +256 -0
- package/dist/mesh/coordinator-prompt.d.ts +76 -0
- package/dist/mesh/coordinator-registry.d.ts +59 -0
- package/dist/mesh/mesh-active-work.d.ts +203 -0
- package/dist/mesh/mesh-clone-grace.d.ts +8 -0
- package/dist/mesh/mesh-completion-synthesis.d.ts +4 -0
- package/dist/mesh/mesh-coordinator-config.d.ts +21 -0
- package/dist/mesh/mesh-delivery-policy.d.ts +104 -0
- package/dist/mesh/mesh-event-classify.d.ts +7 -0
- package/dist/mesh/mesh-event-forwarding.d.ts +58 -0
- package/dist/mesh/mesh-event-trace.d.ts +21 -0
- package/dist/mesh/mesh-events-coordinator.d.ts +4 -0
- package/dist/mesh/mesh-events-pending.d.ts +258 -0
- package/dist/mesh/mesh-events-stale.d.ts +61 -0
- package/dist/mesh/mesh-events-utils.d.ts +75 -0
- package/dist/mesh/mesh-events.d.ts +6 -49
- package/dist/mesh/mesh-fast-forward.d.ts +81 -0
- package/dist/mesh/mesh-host-ownership.d.ts +21 -1
- package/dist/mesh/mesh-init.d.ts +128 -0
- package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -4
- package/dist/mesh/mesh-ledger.d.ts +139 -1
- package/dist/mesh/mesh-magi-status.d.ts +63 -0
- package/dist/mesh/mesh-missions.d.ts +281 -0
- package/dist/mesh/mesh-node-identity.d.ts +310 -0
- package/dist/mesh/mesh-queue-assignment.d.ts +162 -0
- package/dist/mesh/mesh-reconcile-acked-hold.d.ts +17 -0
- package/dist/mesh/mesh-reconcile-config.d.ts +6 -0
- package/dist/mesh/mesh-reconcile-identity.d.ts +6 -0
- package/dist/mesh/mesh-reconcile-loop.d.ts +84 -0
- package/dist/mesh/mesh-reconcile-v2-backstop.d.ts +16 -0
- package/dist/mesh/mesh-refine-batch.d.ts +68 -0
- package/dist/mesh/mesh-refine-gates.d.ts +457 -0
- package/dist/mesh/mesh-refine-status.d.ts +62 -0
- package/dist/mesh/mesh-remote-event-pull.d.ts +15 -0
- package/dist/mesh/mesh-review-inbox.d.ts +90 -0
- package/dist/mesh/mesh-routing.d.ts +70 -0
- package/dist/mesh/mesh-runtime-store.d.ts +567 -0
- package/dist/mesh/mesh-scheduling-runtime.d.ts +78 -0
- package/dist/mesh/mesh-task-inflight.d.ts +46 -0
- package/dist/mesh/mesh-task-stats.d.ts +49 -0
- package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +34 -0
- package/dist/mesh/mesh-warmup-deadline.d.ts +68 -0
- package/dist/mesh/mesh-work-queue.d.ts +392 -1
- package/dist/mesh/preview-freshness.d.ts +28 -0
- package/dist/mesh/refine-config.d.ts +97 -0
- package/dist/mesh/worktree-bootstrap-config.d.ts +219 -0
- package/dist/providers/acp-provider-instance.d.ts +5 -0
- package/dist/providers/approval-utils.d.ts +46 -0
- package/dist/providers/chat-message-normalization.d.ts +58 -1
- package/dist/providers/cli-provider-effect-format.d.ts +30 -0
- package/dist/providers/cli-provider-history-dedup.d.ts +17 -0
- package/dist/providers/cli-provider-input-prompt.d.ts +12 -0
- package/dist/providers/cli-provider-instance-types.d.ts +45 -0
- package/dist/providers/cli-provider-instance.d.ts +426 -30
- package/dist/providers/cli-provider-status-helpers.d.ts +46 -0
- package/dist/providers/cli-provider-transcript-merge.d.ts +7 -0
- package/dist/providers/contracts.d.ts +196 -6
- package/dist/providers/external-sources.d.ts +71 -0
- package/dist/providers/manual-attendance.d.ts +79 -0
- package/dist/providers/native-history/antigravity-claim-registry.d.ts +39 -0
- package/dist/providers/native-history/antigravity-cli-transcript.d.ts +137 -0
- package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
- package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
- package/dist/providers/native-history/constants.d.ts +12 -0
- package/dist/providers/native-history/dispatcher.d.ts +44 -0
- package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
- package/dist/providers/native-history/index.d.ts +13 -0
- package/dist/providers/provider-instance-manager.d.ts +30 -0
- package/dist/providers/provider-instance.d.ts +31 -1
- package/dist/providers/provider-loader.d.ts +42 -5
- package/dist/providers/provider-trust.d.ts +31 -0
- package/dist/providers/read-chat-contract.d.ts +29 -0
- package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
- package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +86 -0
- package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
- package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
- package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
- package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
- package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
- package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
- package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
- package/dist/providers/sdk/v1/index.d.ts +30 -0
- package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
- package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
- package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
- package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
- package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
- package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
- package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
- package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
- package/dist/providers/spec/adapter.d.ts +98 -0
- package/dist/providers/spec/cli-adapter.d.ts +223 -0
- package/dist/providers/spec/evaluator.d.ts +45 -0
- package/dist/providers/spec/fsm-driver.d.ts +449 -0
- package/dist/providers/spec/fsm-evaluator.d.ts +93 -0
- package/dist/providers/spec/fsm-loader.d.ts +14 -0
- package/dist/providers/spec/fsm-types.d.ts +202 -0
- package/dist/providers/spec/native-history-executor.d.ts +41 -0
- package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
- package/dist/providers/spec/route.d.ts +4 -0
- package/dist/providers/spec/types.d.ts +244 -0
- package/dist/providers/status-monitor.d.ts +7 -7
- package/dist/providers/transcript-v2.d.ts +176 -0
- package/dist/providers/types/interactive-prompt.d.ts +84 -0
- package/dist/providers/working-dir.d.ts +17 -0
- package/dist/repo-mesh-types.d.ts +616 -12
- package/dist/runtime-defaults.d.ts +2 -0
- package/dist/session-host/managed-host.d.ts +64 -0
- package/dist/session-host/runtime-surface.d.ts +10 -16
- package/dist/sessions/registry.d.ts +26 -0
- package/dist/shared-types-extra.d.ts +2 -4
- package/dist/shared-types.d.ts +110 -55
- package/dist/status/chat-tail-hot-sessions.d.ts +40 -0
- package/dist/status/normalize.d.ts +1 -1
- package/dist/status/normalize.js +1 -0
- package/dist/status/normalize.js.map +1 -1
- package/dist/status/normalize.mjs +1 -0
- package/dist/status/normalize.mjs.map +1 -1
- package/dist/status/reporter.d.ts +2 -0
- package/dist/status/snapshot.d.ts +27 -0
- package/dist/system/hash.d.ts +8 -0
- package/dist/system/load-better-sqlite3.d.ts +21 -0
- package/dist/types.d.ts +20 -6
- package/package.json +11 -4
- package/src/agent-stream/poller.ts +2 -3
- package/src/agent-stream/provider-adapter.ts +1 -1
- package/src/boot/daemon-lifecycle.ts +80 -14
- package/src/boot/process-hardening.ts +89 -0
- package/src/build-info.ts +73 -0
- package/src/chat/source-machine.ts +534 -0
- package/src/chat/source-resolver.ts +0 -0
- package/src/chat/subscription-updates.ts +20 -1
- package/src/cli-adapter-types.d.ts +3 -1
- package/src/cli-adapter-types.ts +68 -2
- package/src/cli-adapters/cli-script-runner.ts +421 -0
- package/src/cli-adapters/cli-state-engine.ts +1282 -0
- package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +1048 -1143
- package/src/cli-adapters/provider-cli-parse.d.ts +2 -0
- package/src/cli-adapters/provider-cli-parse.ts +19 -0
- package/src/cli-adapters/provider-cli-runtime.ts +56 -7
- package/src/cli-adapters/provider-cli-shared.d.ts +4 -0
- package/src/cli-adapters/provider-cli-shared.ts +121 -11
- package/src/cli-adapters/pty-transport.ts +2 -1
- package/src/cli-adapters/pty-write-chunking.ts +106 -0
- package/src/cli-adapters/raw-terminal-io.ts +252 -0
- package/src/cli-adapters/resolve-executable.ts +204 -0
- package/src/cli-adapters/session-host-transport.ts +2 -1
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +63 -29
- package/src/cli-adapters/terminal-backends/types.ts +10 -3
- package/src/cli-adapters/terminal-screen.ts +16 -81
- package/src/commands/chat-commands-debug-bundle.ts +398 -0
- package/src/commands/chat-commands-read.ts +2788 -0
- package/src/commands/chat-commands-scope.ts +54 -0
- package/src/commands/chat-commands-shared.ts +114 -0
- package/src/commands/chat-commands-write.ts +891 -0
- package/src/commands/chat-commands.ts +19 -1841
- package/src/commands/cli-manager.d.ts +2 -0
- package/src/commands/cli-manager.ts +724 -27
- package/src/commands/handler.ts +865 -2
- package/src/commands/high-family/index.ts +28 -0
- package/src/commands/high-family/mesh-coordinator-launch.ts +696 -0
- package/src/commands/high-family/mesh-events.ts +102 -0
- package/src/commands/high-family/mesh-status.ts +857 -0
- package/src/commands/high-family/types.ts +80 -0
- package/src/commands/low-family/coordinator-prompt.ts +125 -0
- package/src/commands/low-family/daemon-lifecycle.ts +120 -0
- package/src/commands/low-family/diagnostics.ts +57 -0
- package/src/commands/low-family/index.ts +37 -0
- package/src/commands/low-family/mesh-ledger.ts +62 -0
- package/src/commands/low-family/mesh-node-logs.ts +87 -0
- package/src/commands/low-family/notification.ts +116 -0
- package/src/commands/low-family/refine-config.ts +106 -0
- package/src/commands/low-family/session-host.ts +282 -0
- package/src/commands/low-family/spec-providerdev.ts +217 -0
- package/src/commands/low-family/status-meta.ts +112 -0
- package/src/commands/low-family/types.ts +39 -0
- package/src/commands/med-family/cli-agent.ts +270 -0
- package/src/commands/med-family/fast-forward.ts +230 -0
- package/src/commands/med-family/ide.ts +163 -0
- package/src/commands/med-family/index.ts +37 -0
- package/src/commands/med-family/mesh-crud.ts +1309 -0
- package/src/commands/med-family/mesh-host-pairing.ts +234 -0
- package/src/commands/med-family/mesh-queue.ts +167 -0
- package/src/commands/med-family/mesh-restart.ts +92 -0
- package/src/commands/med-family/types.ts +153 -0
- package/src/commands/mesh-coordinator.ts +334 -124
- package/src/commands/router-aggregate-status.ts +209 -0
- package/src/commands/router-mesh-session-owner.ts +114 -0
- package/src/commands/router-refine.ts +1794 -0
- package/src/commands/router-worktree-cleanup.ts +870 -0
- package/src/commands/router.ts +567 -4149
- package/src/commands/stream-commands.ts +8 -0
- package/src/commands/upgrade-helper.ts +310 -45
- package/src/config/chat-history.ts +517 -24
- package/src/config/config.ts +30 -0
- package/src/config/mesh-config.ts +300 -24
- package/src/config/mesh-json-config.ts +376 -0
- package/src/config/recent-activity.ts +8 -2
- package/src/config/registry-resolver.ts +100 -0
- package/src/config/repo-settings.ts +111 -0
- package/src/config/state-store.ts +55 -0
- package/src/daemon/dev-auto-implement.ts +3 -2
- package/src/daemon/dev-cli-debug.ts +10 -1
- package/src/daemon/dev-server.ts +0 -541
- package/src/detection/cli-detector.ts +94 -9
- package/src/detection/ide-detector.ts +55 -16
- package/src/detection/win32-ide-version.ts +106 -0
- package/src/git/change-impact-config.ts +354 -0
- package/src/git/git-commands.ts +112 -16
- package/src/git/git-diff.ts +81 -11
- package/src/git/git-executor.ts +12 -0
- package/src/git/git-status.ts +822 -48
- package/src/git/git-types.ts +14 -62
- package/src/git/git-worktree.ts +261 -4
- package/src/git/index.ts +17 -0
- package/src/index.ts +190 -13
- package/src/installer.d.ts +1 -1
- package/src/installer.ts +8 -6
- package/src/ipc/local-ipc-server.ts +278 -0
- package/src/launch.d.ts +1 -1
- package/src/launch.ts +37 -28
- package/src/logging/async-batch-writer.ts +55 -0
- package/src/logging/command-log.ts +7 -5
- package/src/logging/debug-config.ts +25 -0
- package/src/logging/debug-trace.ts +7 -2
- package/src/logging/log-redactor.ts +100 -0
- package/src/logging/log-tail-reader.ts +341 -0
- package/src/logging/logger.ts +14 -7
- package/src/mesh/contracts.ts +510 -0
- package/src/mesh/coordinator-prompt.ts +627 -34
- package/src/mesh/coordinator-registry.ts +121 -0
- package/src/mesh/mesh-active-work.ts +706 -0
- package/src/mesh/mesh-clone-grace.ts +68 -0
- package/src/mesh/mesh-completion-synthesis.ts +416 -0
- package/src/mesh/mesh-coordinator-config.ts +97 -0
- package/src/mesh/mesh-delivery-policy.ts +284 -0
- package/src/mesh/mesh-event-classify.ts +78 -0
- package/src/mesh/mesh-event-forwarding.ts +2030 -0
- package/src/mesh/mesh-event-trace.ts +67 -0
- package/src/mesh/mesh-events-coordinator.ts +32 -0
- package/src/mesh/mesh-events-pending.ts +1548 -0
- package/src/mesh/mesh-events-stale.ts +452 -0
- package/src/mesh/mesh-events-utils.ts +443 -0
- package/src/mesh/mesh-events.ts +43 -1035
- package/src/mesh/mesh-fast-forward.ts +856 -0
- package/src/mesh/mesh-host-ownership.ts +41 -3
- package/src/mesh/mesh-init.ts +350 -0
- package/src/mesh/mesh-ledger-reconciliation.ts +12 -7
- package/src/mesh/mesh-ledger.ts +897 -102
- package/src/mesh/mesh-magi-status.ts +223 -0
- package/src/mesh/mesh-missions.ts +695 -0
- package/src/mesh/mesh-node-identity.ts +2065 -0
- package/src/mesh/mesh-queue-assignment.ts +2498 -0
- package/src/mesh/mesh-reconcile-acked-hold.ts +230 -0
- package/src/mesh/mesh-reconcile-config.ts +66 -0
- package/src/mesh/mesh-reconcile-identity.ts +103 -0
- package/src/mesh/mesh-reconcile-loop.ts +1696 -0
- package/src/mesh/mesh-reconcile-v2-backstop.ts +62 -0
- package/src/mesh/mesh-refine-batch.ts +205 -0
- package/src/mesh/mesh-refine-gates.ts +1792 -0
- package/src/mesh/mesh-refine-status.ts +231 -0
- package/src/mesh/mesh-remote-event-pull.ts +279 -0
- package/src/mesh/mesh-review-inbox.ts +308 -0
- package/src/mesh/mesh-routing.ts +291 -0
- package/src/mesh/mesh-runtime-store.ts +2292 -0
- package/src/mesh/mesh-scheduling-runtime.ts +198 -0
- package/src/mesh/mesh-task-inflight.ts +70 -0
- package/src/mesh/mesh-task-stats.ts +161 -0
- package/src/mesh/mesh-unresolved-forward-outbox.ts +215 -0
- package/src/mesh/mesh-warmup-deadline.ts +152 -0
- package/src/mesh/mesh-work-queue.ts +1489 -145
- package/src/mesh/preview-freshness.ts +163 -0
- package/src/mesh/refine-config.ts +129 -12
- package/src/mesh/worktree-bootstrap-config.ts +599 -0
- package/src/providers/acp-provider-instance.ts +43 -10
- package/src/providers/approval-utils.d.ts +5 -0
- package/src/providers/approval-utils.ts +100 -6
- package/src/providers/chat-message-normalization.ts +126 -4
- package/src/providers/cli-provider-effect-format.ts +53 -0
- package/src/providers/cli-provider-history-dedup.ts +75 -0
- package/src/providers/cli-provider-input-prompt.ts +133 -0
- package/src/providers/cli-provider-instance-types.ts +131 -0
- package/src/providers/cli-provider-instance.ts +2771 -499
- package/src/providers/cli-provider-status-helpers.ts +123 -0
- package/src/providers/cli-provider-transcript-merge.ts +114 -0
- package/src/providers/contracts.d.ts +55 -0
- package/src/providers/contracts.ts +207 -6
- package/src/providers/extension-provider-instance.ts +12 -7
- package/src/providers/external-sources.ts +218 -0
- package/src/providers/ide-provider-instance.ts +35 -12
- package/src/providers/manual-attendance.ts +105 -0
- package/src/providers/native-history/antigravity-claim-registry.ts +138 -0
- package/src/providers/native-history/antigravity-cli-transcript.ts +1275 -0
- package/src/providers/native-history/claude-cli-transcript.ts +396 -0
- package/src/providers/native-history/codex-cli-transcript.ts +479 -0
- package/src/providers/native-history/constants.ts +19 -0
- package/src/providers/native-history/dispatcher.ts +617 -0
- package/src/providers/native-history/hermes-cli-transcript.ts +312 -0
- package/src/providers/native-history/index.ts +30 -0
- package/src/providers/provider-instance-manager.ts +71 -0
- package/src/providers/provider-instance.ts +24 -1
- package/src/providers/provider-loader.ts +700 -55
- package/src/providers/provider-schema.ts +93 -14
- package/src/providers/provider-trust.ts +114 -0
- package/src/providers/read-chat-contract.ts +76 -16
- package/src/providers/sdk/README.md +49 -0
- package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
- package/src/providers/sdk/v1/builders/cli/detect-status.ts +313 -0
- package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
- package/src/providers/sdk/v1/builders/cli/parse-approval.ts +261 -0
- package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
- package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
- package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
- package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
- package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
- package/src/providers/sdk/v1/index.ts +152 -0
- package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
- package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
- package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
- package/src/providers/sdk/v1/schemas/cli/provider.schema.json +538 -0
- package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
- package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
- package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
- package/src/providers/sdk/v1/types/cli/index.ts +365 -0
- package/src/providers/sdk/v1/types/common/index.ts +229 -0
- package/src/providers/sdk/v1/validators/index.ts +19 -0
- package/src/providers/sdk/v1/validators/manifest.ts +110 -0
- package/src/providers/sdk/v1/validators/taint.ts +309 -0
- package/src/providers/spec/adapter.ts +246 -0
- package/src/providers/spec/cli-adapter.ts +1064 -0
- package/src/providers/spec/evaluator.ts +407 -0
- package/src/providers/spec/fsm-driver.ts +1528 -0
- package/src/providers/spec/fsm-evaluator.ts +290 -0
- package/src/providers/spec/fsm-loader.ts +128 -0
- package/src/providers/spec/fsm-types.ts +301 -0
- package/src/providers/spec/native-history-executor.ts +1241 -0
- package/src/providers/spec/pre-launch-trust.ts +104 -0
- package/src/providers/spec/route.ts +51 -0
- package/src/providers/spec/types.ts +284 -0
- package/src/providers/status-monitor.d.ts +7 -7
- package/src/providers/status-monitor.ts +37 -22
- package/src/providers/transcript-v2.ts +567 -0
- package/src/providers/types/interactive-prompt.ts +536 -0
- package/src/providers/version-archive.ts +64 -24
- package/src/providers/working-dir.ts +23 -0
- package/src/repo-mesh-types.ts +861 -14
- package/src/runtime-defaults.ts +39 -0
- package/src/session-host/managed-host.ts +218 -0
- package/src/session-host/runtime-surface.ts +20 -80
- package/src/sessions/registry.ts +44 -0
- package/src/shared-types-extra.ts +2 -4
- package/src/shared-types.d.ts +8 -0
- package/src/shared-types.ts +148 -55
- package/src/status/builders.ts +69 -6
- package/src/status/chat-tail-hot-sessions.ts +117 -2
- package/src/status/normalize.ts +2 -0
- package/src/status/reporter.ts +19 -1
- package/src/status/snapshot.ts +100 -27
- package/src/system/hash.ts +23 -0
- package/src/system/host-memory.ts +29 -12
- package/src/system/load-better-sqlite3.ts +68 -0
- package/src/types.ts +26 -6
- package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
- package/dist/mesh/mesh-sync.d.ts +0 -53
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
- package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
- package/src/mesh/mesh-sync.ts +0 -111
|
@@ -0,0 +1,857 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RF-ROUTER HIGH family — mesh aggregate status + review inbox.
|
|
3
|
+
*
|
|
4
|
+
* mesh_status: the coordinator's aggregate mesh render — resolves membership,
|
|
5
|
+
* gates the memory cache against pending coordinator events / explicit refresh,
|
|
6
|
+
* optionally fans out a direct peer-truth probe, then renders per-node health
|
|
7
|
+
* (live session records, local/remote/inline git truth, branch convergence) and
|
|
8
|
+
* folds in queue/ledger/missions/async-refine/historical-session/active-refine
|
|
9
|
+
* state. get_mesh_review_inbox: derives review-inbox items from node statuses +
|
|
10
|
+
* ledger and annotates each with a worktree git-diff summary. Extracted verbatim
|
|
11
|
+
* from executeDaemonCommand — only `this.*` router members became `ctx.*` and the
|
|
12
|
+
* relative dynamic-import paths were re-based one directory deeper.
|
|
13
|
+
*/
|
|
14
|
+
import * as fs from 'fs';
|
|
15
|
+
import { hostname as osHostname } from 'os';
|
|
16
|
+
import { loadConfig } from '../../config/config.js';
|
|
17
|
+
import { getGitRepoStatus } from '../../git/git-status.js';
|
|
18
|
+
import {
|
|
19
|
+
normalizeMeshNodeId,
|
|
20
|
+
daemonIdsEquivalent,
|
|
21
|
+
normalizeNodeCapabilitySlots,
|
|
22
|
+
} from '@adhdev/mesh-shared';
|
|
23
|
+
import {
|
|
24
|
+
getPendingMeshCoordinatorEvents,
|
|
25
|
+
getMeshV2DrainCounters,
|
|
26
|
+
getMeshV2BackstopCounters,
|
|
27
|
+
isMeshProtocolV2EnforceEnabled,
|
|
28
|
+
} from '../../mesh/mesh-events.js';
|
|
29
|
+
import type { MeshProtocolV2Counters } from '../../repo-mesh-types.js';
|
|
30
|
+
import { getRecentUnroutableDeliveries } from '../../mesh/mesh-routing.js';
|
|
31
|
+
import { normalizeMeshDaemonRole, resolveMeshHostStatus } from '../../mesh/mesh-host-ownership.js';
|
|
32
|
+
import { buildPreviewFreshness } from '../../mesh/preview-freshness.js';
|
|
33
|
+
import { buildMeshAsyncRefineJobs } from '../../mesh/mesh-refine-status.js';
|
|
34
|
+
import { partitionSessionHostRecords } from '../../session-host/runtime-surface.js';
|
|
35
|
+
import {
|
|
36
|
+
readStringValue,
|
|
37
|
+
readObjectRecord,
|
|
38
|
+
readBooleanValue,
|
|
39
|
+
readMeshNodeMachineId,
|
|
40
|
+
readMeshNodeHostname,
|
|
41
|
+
readProviderPriorityFromPolicy,
|
|
42
|
+
buildMeshNodeMachineIdentity,
|
|
43
|
+
buildMeshNodeDisplayLabel,
|
|
44
|
+
collectLiveMeshSessionRecords,
|
|
45
|
+
readLiveMeshNodeWorkspace,
|
|
46
|
+
summarizeMeshSessionRecord,
|
|
47
|
+
buildInlineMeshTransitGitStatus,
|
|
48
|
+
deriveMeshNodeHealthFromGit,
|
|
49
|
+
buildLivePeerGitConnection,
|
|
50
|
+
probeRemoteMeshGitStatusWithRetry,
|
|
51
|
+
recordInlineMeshDirectGitTruth,
|
|
52
|
+
persistNodeReporterPlatform,
|
|
53
|
+
applyCachedInlineMeshNodeStatus,
|
|
54
|
+
applyInlineMeshBranchConvergence,
|
|
55
|
+
finalizeMeshNodeStatus,
|
|
56
|
+
summarizeInlineMeshBranchConvergence,
|
|
57
|
+
buildHistoricalMeshSessions,
|
|
58
|
+
hydrateInlineMeshDirectTruth,
|
|
59
|
+
MESH_NODE_LIVE_TRUTH_MARKER,
|
|
60
|
+
logRepoMeshStatusDebug,
|
|
61
|
+
summarizeRepoMeshStatusDebug,
|
|
62
|
+
MESH_DIRECT_PROBE_TIMEOUT_MS,
|
|
63
|
+
MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS,
|
|
64
|
+
} from '../router.js';
|
|
65
|
+
import type { HighFamilyContext, HighFamilyHandler } from './types.js';
|
|
66
|
+
|
|
67
|
+
export const meshStatusHandlers: Record<string, HighFamilyHandler> = {
|
|
68
|
+
mesh_status: async (ctx: HighFamilyContext, args: any) => {
|
|
69
|
+
const meshId = typeof args?.meshId === 'string' ? args.meshId.trim() : '';
|
|
70
|
+
if (!meshId) return { success: false, error: 'meshId required' };
|
|
71
|
+
// Latency telemetry: stamp handler entry so every return path can
|
|
72
|
+
// report durationMs. Makes the detail-open cost measurable in the
|
|
73
|
+
// repo-mesh-status debug log (cache hit ≈ single-digit ms; a full
|
|
74
|
+
// live rebuild is the ~seconds path this change is reducing).
|
|
75
|
+
const startedAtMs = Date.now();
|
|
76
|
+
try {
|
|
77
|
+
const meshRecord = await ctx.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
78
|
+
const mesh = meshRecord?.mesh;
|
|
79
|
+
if (!mesh) return { success: false, error: 'Mesh not found' };
|
|
80
|
+
// Pass the evaluating daemon's id so a host mesh whose
|
|
81
|
+
// hostDaemonId was never persisted (HOST-MISSEED-FIRSTSETUP) gets
|
|
82
|
+
// pinned to THIS daemon — the dashboard then renders M4 as host
|
|
83
|
+
// instead of falling back to 'no host yet'.
|
|
84
|
+
const meshHost = resolveMeshHostStatus(mesh, { localDaemonId: ctx.deps.statusInstanceId });
|
|
85
|
+
|
|
86
|
+
const refreshRequested = args?.refresh === true || args?.forceRefresh === true;
|
|
87
|
+
// Compact (default) elides each mission's full goal text from the
|
|
88
|
+
// payload — coordinators polling node health don't need every
|
|
89
|
+
// mission's multi-hundred-char goal repeated. verbose=true (or the
|
|
90
|
+
// explicit compact=false) restores full goals. Verbose bypasses the
|
|
91
|
+
// shared (compact) aggregate cache so a verbose call never poisons
|
|
92
|
+
// the compact cache and vice versa.
|
|
93
|
+
const verboseMissions = args?.verbose === true || args?.compact === false;
|
|
94
|
+
// See (B3) below: scope the peek to this daemon when the
|
|
95
|
+
// caller doesn't tell us, otherwise scoped events look
|
|
96
|
+
// missing and we falsely return a stale cache.
|
|
97
|
+
const peekScope = typeof args?.coordinatorDaemonId === 'string' && args.coordinatorDaemonId.trim()
|
|
98
|
+
? args.coordinatorDaemonId.trim()
|
|
99
|
+
: (ctx.deps.statusInstanceId || undefined);
|
|
100
|
+
const pendingCoordinatorEventCount = getPendingMeshCoordinatorEvents(meshId, peekScope).length;
|
|
101
|
+
const hadAggregateCache = ctx.aggregateMeshStatusCache.has(meshId);
|
|
102
|
+
if (!refreshRequested && !verboseMissions && pendingCoordinatorEventCount === 0) {
|
|
103
|
+
const cachedStatus = ctx.getCachedAggregateMeshStatus(meshId, mesh, { requireDirectPeerTruth: args?.requireDirectPeerTruth === true });
|
|
104
|
+
if (cachedStatus) {
|
|
105
|
+
logRepoMeshStatusDebug('return_cached', {
|
|
106
|
+
meshId,
|
|
107
|
+
command: 'mesh_status',
|
|
108
|
+
refreshRequested,
|
|
109
|
+
durationMs: Date.now() - startedAtMs,
|
|
110
|
+
summary: summarizeRepoMeshStatusDebug(cachedStatus),
|
|
111
|
+
});
|
|
112
|
+
return cachedStatus;
|
|
113
|
+
}
|
|
114
|
+
// SWR stale-serve: the strict serve above missed only because
|
|
115
|
+
// some node still has a pending peer-git probe (the
|
|
116
|
+
// shouldRefreshStalePendingAggregate gate). Rather than block
|
|
117
|
+
// this interactive detail-open on a full synchronous live
|
|
118
|
+
// rebuild, serve the held (slightly stale) snapshot instantly
|
|
119
|
+
// and kick ONE coalesced background freshen whose result
|
|
120
|
+
// repopulates the cache for the next poll/subscription push.
|
|
121
|
+
// allowStalePending relaxes ONLY the pending-git freshness gate;
|
|
122
|
+
// getCachedAggregateMeshStatus still enforces the queueRevision
|
|
123
|
+
// guard, so a genuine queue/identity mutation is never stale-served.
|
|
124
|
+
const staleStatus = ctx.getCachedAggregateMeshStatus(meshId, mesh, {
|
|
125
|
+
requireDirectPeerTruth: args?.requireDirectPeerTruth === true,
|
|
126
|
+
allowStalePending: true,
|
|
127
|
+
});
|
|
128
|
+
if (staleStatus) {
|
|
129
|
+
if (!ctx.swrRefreshInFlight.has(meshId)) {
|
|
130
|
+
ctx.swrRefreshInFlight.add(meshId);
|
|
131
|
+
// Fire-and-forget: a full refresh (peer fan-out) that
|
|
132
|
+
// rewrites the aggregate cache. Errors are swallowed —
|
|
133
|
+
// the stale snapshot was already returned to the caller.
|
|
134
|
+
void Promise.resolve()
|
|
135
|
+
.then(() => ctx.execute('mesh_status', {
|
|
136
|
+
meshId,
|
|
137
|
+
inlineMesh: args?.inlineMesh,
|
|
138
|
+
coordinatorDaemonId: args?.coordinatorDaemonId,
|
|
139
|
+
requireDirectPeerTruth: args?.requireDirectPeerTruth === true,
|
|
140
|
+
refresh: true,
|
|
141
|
+
}, 'mesh_status_swr_freshen'))
|
|
142
|
+
.catch(() => {})
|
|
143
|
+
.finally(() => { ctx.swrRefreshInFlight.delete(meshId); });
|
|
144
|
+
}
|
|
145
|
+
logRepoMeshStatusDebug('return_stale_swr', {
|
|
146
|
+
meshId,
|
|
147
|
+
command: 'mesh_status',
|
|
148
|
+
refreshRequested,
|
|
149
|
+
durationMs: Date.now() - startedAtMs,
|
|
150
|
+
summary: summarizeRepoMeshStatusDebug(staleStatus),
|
|
151
|
+
});
|
|
152
|
+
return staleStatus;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const refreshReason = refreshRequested
|
|
156
|
+
? 'explicit_refresh'
|
|
157
|
+
: pendingCoordinatorEventCount > 0
|
|
158
|
+
? 'pending_coordinator_events'
|
|
159
|
+
: hadAggregateCache
|
|
160
|
+
? 'stale_pending_cache_refresh'
|
|
161
|
+
: 'cold_cache_miss';
|
|
162
|
+
|
|
163
|
+
const { getMeshQueueStats, getQueue } = await import('../../mesh/mesh-work-queue.js');
|
|
164
|
+
const queue = getQueue(meshId);
|
|
165
|
+
const queueSummary = getMeshQueueStats(meshId);
|
|
166
|
+
|
|
167
|
+
// Scheduling-runtime projection — the load-balancer's live view (tie-break
|
|
168
|
+
// strategy, global parallel caps + consumption, per-node load/priority/provider
|
|
169
|
+
// caps). Built from the SAME helper + args the MCP `mesh_status` tool uses
|
|
170
|
+
// (mesh-tools-status.ts: buildMeshSchedulingRuntime(mesh, getQueue(mesh.id)))
|
|
171
|
+
// so the dashboard surface and the coordinator MCP surface render an identical
|
|
172
|
+
// runtime. Without this the dashboard Status/Runtime tab showed the
|
|
173
|
+
// "not reported by this daemon (older build)" fallback (RepoMeshStatus.scheduling
|
|
174
|
+
// was never populated by this daemon-command producer). Computed once so each
|
|
175
|
+
// node entry can attach its slice and statusResult can carry the mesh rollup.
|
|
176
|
+
const { buildMeshSchedulingRuntime } = await import('../../mesh/mesh-scheduling-runtime.js');
|
|
177
|
+
const schedulingRuntime = buildMeshSchedulingRuntime(mesh, queue);
|
|
178
|
+
const schedulingByNode = new Map(schedulingRuntime.nodes.map(n => [n.nodeId, n]));
|
|
179
|
+
|
|
180
|
+
const { readLedgerEntries, getLedgerSummary } = await import('../../mesh/mesh-ledger.js');
|
|
181
|
+
const ledgerEntries = readLedgerEntries(meshId, { tail: 20 });
|
|
182
|
+
const asyncRefineLedgerEntries = readLedgerEntries(meshId, { tail: 100 });
|
|
183
|
+
const ledgerSummary = getLedgerSummary(meshId);
|
|
184
|
+
const sessionHostRecords = ctx.deps.sessionHostControl?.listSessions
|
|
185
|
+
? await ctx.deps.sessionHostControl.listSessions().catch(() => [])
|
|
186
|
+
: [];
|
|
187
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
188
|
+
|
|
189
|
+
const localMachineId = loadConfig().machineId || '';
|
|
190
|
+
// Local daemon's operator-set nickname — stamped onto the self/base
|
|
191
|
+
// node at render time so the friendly label resolves even before the
|
|
192
|
+
// persisted node record (addNode) has been rewritten with it.
|
|
193
|
+
const localMachineNickname = (() => {
|
|
194
|
+
const nick = loadConfig().machineNickname;
|
|
195
|
+
return typeof nick === 'string' && nick.trim() ? nick.trim() : '';
|
|
196
|
+
})();
|
|
197
|
+
const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
|
|
198
|
+
// Shared probe gate for this mesh_status call: the bootstrap
|
|
199
|
+
// hydrate below and the per-node render loop further down both
|
|
200
|
+
// probe the same peers — route both through this cache so they
|
|
201
|
+
// dedup within the call and reuse recent results across calls.
|
|
202
|
+
const meshGitProbeCache = ctx.meshGitProbeCache;
|
|
203
|
+
const directTruth = requireDirectPeerTruth
|
|
204
|
+
? await hydrateInlineMeshDirectTruth({
|
|
205
|
+
mesh,
|
|
206
|
+
meshSource: meshRecord.source,
|
|
207
|
+
dispatchMeshCommand: ctx.deps.dispatchMeshCommand,
|
|
208
|
+
getMeshPeerConnectionStatus: ctx.deps.getMeshPeerConnectionStatus,
|
|
209
|
+
statusInstanceId: ctx.deps.statusInstanceId,
|
|
210
|
+
localMachineId,
|
|
211
|
+
// Standing-state model: only an explicit refresh fans
|
|
212
|
+
// out a blocking peer git probe. Default loads return
|
|
213
|
+
// held truth so one slow peer can't block the graph.
|
|
214
|
+
probeRemotePeers: refreshRequested,
|
|
215
|
+
probeCache: meshGitProbeCache,
|
|
216
|
+
})
|
|
217
|
+
: {
|
|
218
|
+
directEvidenceCount: 0,
|
|
219
|
+
localConfirmedCount: 0,
|
|
220
|
+
peerAttemptedCount: 0,
|
|
221
|
+
peerConfirmedCount: 0,
|
|
222
|
+
standingEvidenceCount: 0,
|
|
223
|
+
unavailableNodeIds: [] as string[],
|
|
224
|
+
deadNodeIds: [] as string[],
|
|
225
|
+
};
|
|
226
|
+
// Default/cached loads may not attempt a remote peer probe yet; do not surface that as
|
|
227
|
+
// a direct mesh truth failure until an explicit probe attempt actually fails.
|
|
228
|
+
const passivePeerTruthNotAttempted = requireDirectPeerTruth
|
|
229
|
+
&& !refreshRequested
|
|
230
|
+
&& directTruth.directEvidenceCount > 0
|
|
231
|
+
&& directTruth.peerAttemptedCount === 0;
|
|
232
|
+
const effectiveDirectTruth = passivePeerTruthNotAttempted
|
|
233
|
+
? { ...directTruth, unavailableNodeIds: [] as string[] }
|
|
234
|
+
: directTruth;
|
|
235
|
+
const unavailableDirectTruthNodeIds = new Set(effectiveDirectTruth.unavailableNodeIds);
|
|
236
|
+
const unavailableNodesAreOnlyRemovedWorktrees = unavailableDirectTruthNodeIds.size > 0
|
|
237
|
+
&& Array.isArray(mesh.nodes)
|
|
238
|
+
&& mesh.nodes
|
|
239
|
+
.filter((node: any) => unavailableDirectTruthNodeIds.has(normalizeMeshNodeId(node) ?? ''))
|
|
240
|
+
.every((node: any) => node?.isLocalWorktree === true);
|
|
241
|
+
// Default (non-refresh) loads never hard-fail: held
|
|
242
|
+
// standing-state truth is returned and the graph renders
|
|
243
|
+
// immediately. The hard mesh_direct_peer_truth_unavailable
|
|
244
|
+
// failure is reserved for an explicit refresh that actually
|
|
245
|
+
// attempted a peer probe and could not confirm any evidence.
|
|
246
|
+
const directTruthSatisfied = !requireDirectPeerTruth
|
|
247
|
+
|| !refreshRequested
|
|
248
|
+
|| (effectiveDirectTruth.directEvidenceCount > 0 && (effectiveDirectTruth.unavailableNodeIds.length === 0 || unavailableNodesAreOnlyRemovedWorktrees));
|
|
249
|
+
if (requireDirectPeerTruth && refreshRequested && !directTruthSatisfied) {
|
|
250
|
+
const failureResult = {
|
|
251
|
+
success: false,
|
|
252
|
+
code: 'mesh_direct_peer_truth_unavailable',
|
|
253
|
+
error: 'Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct mesh_status probes succeed.',
|
|
254
|
+
sourceOfTruth: {
|
|
255
|
+
membership: meshRecord.source === 'inline_cache'
|
|
256
|
+
? 'coordinator_inline_mesh_cache'
|
|
257
|
+
: meshRecord.source === 'local_config'
|
|
258
|
+
? 'local_mesh_config'
|
|
259
|
+
: 'inline_bootstrap_snapshot',
|
|
260
|
+
coordinatorOwnsLiveTruth: false,
|
|
261
|
+
currentStatus: 'direct_peer_truth_unavailable',
|
|
262
|
+
directPeerTruth: {
|
|
263
|
+
required: true,
|
|
264
|
+
satisfied: false,
|
|
265
|
+
directEvidenceCount: directTruth.directEvidenceCount,
|
|
266
|
+
localConfirmedCount: directTruth.localConfirmedCount,
|
|
267
|
+
peerAttemptedCount: directTruth.peerAttemptedCount,
|
|
268
|
+
peerConfirmedCount: directTruth.peerConfirmedCount,
|
|
269
|
+
unavailableNodeIds: directTruth.unavailableNodeIds,
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
logRepoMeshStatusDebug('direct_truth_unavailable', {
|
|
274
|
+
meshId,
|
|
275
|
+
command: 'mesh_status',
|
|
276
|
+
refreshRequested,
|
|
277
|
+
meshSource: meshRecord.source,
|
|
278
|
+
directTruth,
|
|
279
|
+
});
|
|
280
|
+
return failureResult;
|
|
281
|
+
}
|
|
282
|
+
const directTruthUnavailableNodeIds = new Set(effectiveDirectTruth.unavailableNodeIds);
|
|
283
|
+
const coordinatorHostname = osHostname();
|
|
284
|
+
const selectedCoordinatorNodeId = readStringValue(
|
|
285
|
+
mesh.coordinator?.preferredNodeId,
|
|
286
|
+
normalizeMeshNodeId(mesh.nodes?.[0] as any),
|
|
287
|
+
);
|
|
288
|
+
const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes)
|
|
289
|
+
? selectedCoordinatorNodeId
|
|
290
|
+
: undefined;
|
|
291
|
+
const refreshedAt = new Date().toISOString();
|
|
292
|
+
// Per-node render is parallelized (Promise.allSettled below):
|
|
293
|
+
// each node's git probe (local getGitRepoStatus or the remote
|
|
294
|
+
// P2P fan-out) is independent, so serializing them stacked one
|
|
295
|
+
// slow node's latency onto every other node. Each node has its
|
|
296
|
+
// own bounded timeout; a rejected/timed-out node degrades to a
|
|
297
|
+
// partial/last-known status for THAT node only and never rejects
|
|
298
|
+
// the whole aggregate. Order is preserved by mapping over the
|
|
299
|
+
// original entries() index and re-assembling in order.
|
|
300
|
+
const renderMeshNode = async (nodeIndex: number, node: any): Promise<Record<string, unknown>> => {
|
|
301
|
+
const nodeId = normalizeMeshNodeId(node) ?? '';
|
|
302
|
+
const daemonId = readStringValue(node.daemonId);
|
|
303
|
+
const nodeMachineId = readMeshNodeMachineId(node as Record<string, unknown>);
|
|
304
|
+
const nodeHostname = readMeshNodeHostname(node as Record<string, unknown>);
|
|
305
|
+
const providerPriority = readProviderPriorityFromPolicy(node.policy);
|
|
306
|
+
const configuredCoordinatorNode = Boolean(
|
|
307
|
+
nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId,
|
|
308
|
+
);
|
|
309
|
+
const sparseConfiguredCoordinatorNode = configuredCoordinatorNode
|
|
310
|
+
&& !daemonId
|
|
311
|
+
&& !nodeMachineId
|
|
312
|
+
&& !nodeHostname;
|
|
313
|
+
const isSelfNode = Boolean(
|
|
314
|
+
nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId,
|
|
315
|
+
) || Boolean(
|
|
316
|
+
daemonId && (daemonIdsEquivalent(daemonId, localMachineId) || daemonIdsEquivalent(daemonId, ctx.deps.statusInstanceId)),
|
|
317
|
+
) || Boolean(meshRecord?.inline && nodeIndex === 0)
|
|
318
|
+
|| sparseConfiguredCoordinatorNode;
|
|
319
|
+
// The self/base node's friendly label comes from THIS daemon's
|
|
320
|
+
// local config.machineNickname. Stamp it onto the node record (if
|
|
321
|
+
// not already carried) so buildMeshNodeDisplayLabel below resolves
|
|
322
|
+
// to the nickname and labelSource reads 'explicit_metadata' even
|
|
323
|
+
// before addNode's persisted record has been rewritten.
|
|
324
|
+
if (isSelfNode && localMachineNickname && !readStringValue(node.machineNickname, node.machine_nickname)) {
|
|
325
|
+
node.machineNickname = localMachineNickname;
|
|
326
|
+
}
|
|
327
|
+
const machineIdentity = buildMeshNodeMachineIdentity(node as Record<string, unknown>, {
|
|
328
|
+
localMachineId,
|
|
329
|
+
localDaemonId: ctx.deps.statusInstanceId,
|
|
330
|
+
coordinatorHostname,
|
|
331
|
+
isSelfNode,
|
|
332
|
+
});
|
|
333
|
+
const status: Record<string, unknown> = {
|
|
334
|
+
nodeId,
|
|
335
|
+
machineLabel: buildMeshNodeDisplayLabel(node as Record<string, unknown>, nodeId, providerPriority),
|
|
336
|
+
labelSource: readStringValue(node.machineLabel, node.machine_label, node.machineNickname, node.machine_nickname, node.alias)
|
|
337
|
+
? 'explicit_metadata'
|
|
338
|
+
: 'workspace_host_provider_context',
|
|
339
|
+
workspace: node.workspace,
|
|
340
|
+
repoRoot: node.repoRoot,
|
|
341
|
+
isLocalWorktree: node.isLocalWorktree,
|
|
342
|
+
worktreeBranch: node.worktreeBranch,
|
|
343
|
+
role: normalizeMeshDaemonRole(node.role) || (meshHost.hostNodeId && nodeId === meshHost.hostNodeId ? 'host' : undefined),
|
|
344
|
+
daemonId,
|
|
345
|
+
machineId: nodeMachineId || node.machineId,
|
|
346
|
+
machine: machineIdentity,
|
|
347
|
+
machineStatus: node.machineStatus,
|
|
348
|
+
health: 'unknown',
|
|
349
|
+
providers: node.providers || [],
|
|
350
|
+
// T7: surface self-healed provider versions + build version (from the
|
|
351
|
+
// git_status envelope, persisted on the node) so the coordinator/UI can
|
|
352
|
+
// spot a provider-version skew across nodes. Additive; omitted when a
|
|
353
|
+
// node has never reported them.
|
|
354
|
+
...(node.reportedProviderVersions && typeof node.reportedProviderVersions === 'object'
|
|
355
|
+
? { providerVersions: node.reportedProviderVersions }
|
|
356
|
+
: {}),
|
|
357
|
+
...(typeof node.reportedDaemonBuildVersion === 'string' && node.reportedDaemonBuildVersion
|
|
358
|
+
? { daemonBuildVersion: node.reportedDaemonBuildVersion }
|
|
359
|
+
: {}),
|
|
360
|
+
providerPriority,
|
|
361
|
+
// ORCHESTRATION_NODE_SLOTS.md: surface the node's capability
|
|
362
|
+
// slots so the dashboard slot editor can read them. Only
|
|
363
|
+
// emitted when explicitly configured (derived-from-legacy
|
|
364
|
+
// slots stay implicit — the editor shows the legacy fields).
|
|
365
|
+
...(Array.isArray((node.policy as any)?.slots) && (node.policy as any).slots.length
|
|
366
|
+
? { slots: normalizeNodeCapabilitySlots((node.policy as any).slots) }
|
|
367
|
+
: {}),
|
|
368
|
+
activeSessions: [],
|
|
369
|
+
activeSessionDetails: [],
|
|
370
|
+
launchReady: false,
|
|
371
|
+
};
|
|
372
|
+
// Per-node scheduling slice (load / priority / provider caps / claim-block
|
|
373
|
+
// reasons) read by the dashboard's MeshNodeSchedulingBadges. Full shape —
|
|
374
|
+
// unlike the MCP compact path this is a dashboard surface, so it keeps the
|
|
375
|
+
// whole RepoMeshNodeSchedulingStatus. Redundant nodeId dropped (the entry
|
|
376
|
+
// already carries it).
|
|
377
|
+
const nodeScheduling = schedulingByNode.get(nodeId);
|
|
378
|
+
if (nodeScheduling) {
|
|
379
|
+
const { nodeId: _omitNodeId, ...nodeSchedulingRest } = nodeScheduling;
|
|
380
|
+
status.scheduling = nodeSchedulingRest;
|
|
381
|
+
}
|
|
382
|
+
if (isSelfNode) {
|
|
383
|
+
status.connection = {
|
|
384
|
+
perspective: 'selected_coordinator',
|
|
385
|
+
source: 'mesh_peer_status',
|
|
386
|
+
state: 'self',
|
|
387
|
+
transport: 'local',
|
|
388
|
+
reported: true,
|
|
389
|
+
reason: 'Selected coordinator daemon',
|
|
390
|
+
lastStateChangeAt: refreshedAt,
|
|
391
|
+
};
|
|
392
|
+
} else if (daemonId) {
|
|
393
|
+
const connection = ctx.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
394
|
+
status.connection = connection ?? {
|
|
395
|
+
perspective: 'selected_coordinator',
|
|
396
|
+
source: 'not_reported',
|
|
397
|
+
state: 'unknown',
|
|
398
|
+
transport: 'unknown',
|
|
399
|
+
reported: false,
|
|
400
|
+
reason: 'No live mesh peer telemetry reported by the selected coordinator yet.',
|
|
401
|
+
};
|
|
402
|
+
} else {
|
|
403
|
+
status.connection = {
|
|
404
|
+
perspective: 'selected_coordinator',
|
|
405
|
+
source: 'not_reported',
|
|
406
|
+
state: 'unknown',
|
|
407
|
+
transport: 'unknown',
|
|
408
|
+
reported: false,
|
|
409
|
+
reason: 'Node has no daemon id, so mesh transport cannot be reported from the selected coordinator.',
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
|
|
413
|
+
meshId,
|
|
414
|
+
node,
|
|
415
|
+
nodeId,
|
|
416
|
+
liveSessionRecords: liveMeshSessions,
|
|
417
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId,
|
|
418
|
+
});
|
|
419
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
420
|
+
meshId,
|
|
421
|
+
nodeId,
|
|
422
|
+
liveSessionRecords: matchedLiveSessionRecords,
|
|
423
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId,
|
|
424
|
+
}) || (typeof node.workspace === 'string' ? node.workspace : '');
|
|
425
|
+
status.workspace = workspace || node.workspace;
|
|
426
|
+
if (matchedLiveSessionRecords.length > 0) {
|
|
427
|
+
const sessionIds = matchedLiveSessionRecords
|
|
428
|
+
.map((record: any) => typeof record?.sessionId === 'string' ? record.sessionId : '')
|
|
429
|
+
.filter(Boolean);
|
|
430
|
+
const providerTypes = matchedLiveSessionRecords
|
|
431
|
+
.map((record: any) => readStringValue(record?.providerType))
|
|
432
|
+
.filter(Boolean) as string[];
|
|
433
|
+
status.activeSessions = sessionIds;
|
|
434
|
+
status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
|
|
435
|
+
if (providerTypes.length > 0) {
|
|
436
|
+
status.providers = Array.from(new Set([...(Array.isArray(status.providers) ? status.providers as string[] : []), ...providerTypes]));
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
if (workspace) {
|
|
440
|
+
if (!fs.existsSync(workspace)) {
|
|
441
|
+
// Workspace not local — prefer direct live inline truth, then attempt a P2P git probe.
|
|
442
|
+
const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
|
|
443
|
+
let remoteProbeApplied = false;
|
|
444
|
+
if (inlineTransitGit) {
|
|
445
|
+
status.git = inlineTransitGit;
|
|
446
|
+
status.health = inlineTransitGit.isGitRepo
|
|
447
|
+
? deriveMeshNodeHealthFromGit(inlineTransitGit as unknown as Record<string, unknown>)
|
|
448
|
+
: 'degraded';
|
|
449
|
+
const connection = readObjectRecord(status.connection);
|
|
450
|
+
const connectionState = readStringValue(connection.state);
|
|
451
|
+
const connectionReported = readBooleanValue(connection.reported) ?? false;
|
|
452
|
+
if (!connectionReported || connectionState === 'unknown') {
|
|
453
|
+
status.connection = buildLivePeerGitConnection(connection, refreshedAt);
|
|
454
|
+
}
|
|
455
|
+
remoteProbeApplied = true;
|
|
456
|
+
} else if (refreshRequested && !isSelfNode && daemonId && ctx.deps.dispatchMeshCommand && !directTruthUnavailableNodeIds.has(nodeId)) {
|
|
457
|
+
// Only an explicit refresh fans out a blocking
|
|
458
|
+
// per-node git probe. On the default load a peer
|
|
459
|
+
// with no held truth falls through to
|
|
460
|
+
// gitProbePending below — the graph still renders.
|
|
461
|
+
// Bounded retry (shared with the bootstrap hydrate
|
|
462
|
+
// path), gated on the peer staying connected, so a
|
|
463
|
+
// slow TURN-relayed peer is recovered rather than
|
|
464
|
+
// dropped after a single timeout.
|
|
465
|
+
const runNodeProbe = () => probeRemoteMeshGitStatusWithRetry({
|
|
466
|
+
dispatchMeshCommand: ctx.deps.dispatchMeshCommand,
|
|
467
|
+
daemonId,
|
|
468
|
+
workspace,
|
|
469
|
+
timeoutMs: MESH_DIRECT_PROBE_TIMEOUT_MS,
|
|
470
|
+
retryTimeoutMs: MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS,
|
|
471
|
+
getConnection: ctx.deps.getMeshPeerConnectionStatus,
|
|
472
|
+
onConnection: connection => { status.connection = connection; },
|
|
473
|
+
});
|
|
474
|
+
// Same shared cache as the bootstrap hydrate path: within one
|
|
475
|
+
// mesh_status call this dedups the bootstrap probe against this
|
|
476
|
+
// per-node probe for the same peer, and across calls it reuses a
|
|
477
|
+
// recent result so the dashboard auto-retry loop can't restart a
|
|
478
|
+
// fresh refreshUpstream probe seconds apart.
|
|
479
|
+
const remoteGit = await meshGitProbeCache.probe(daemonId, workspace, runNodeProbe);
|
|
480
|
+
if (remoteGit) {
|
|
481
|
+
status.git = remoteGit;
|
|
482
|
+
status[MESH_NODE_LIVE_TRUTH_MARKER] = true;
|
|
483
|
+
status.health = remoteGit.isGitRepo
|
|
484
|
+
? deriveMeshNodeHealthFromGit(remoteGit as unknown as Record<string, unknown>)
|
|
485
|
+
: 'degraded';
|
|
486
|
+
const connection = readObjectRecord(status.connection);
|
|
487
|
+
const connectionState = readStringValue(connection.state);
|
|
488
|
+
const connectionReported = readBooleanValue(connection.reported) ?? false;
|
|
489
|
+
if (!connectionReported || connectionState === 'unknown') {
|
|
490
|
+
status.connection = buildLivePeerGitConnection(connection, refreshedAt);
|
|
491
|
+
}
|
|
492
|
+
const reporter = recordInlineMeshDirectGitTruth(node, remoteGit, 'selected_coordinator_mesh_p2p_git');
|
|
493
|
+
persistNodeReporterPlatform(meshRecord.source, mesh, nodeId, reporter);
|
|
494
|
+
remoteProbeApplied = true;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
if (!remoteProbeApplied) {
|
|
498
|
+
const connectionState = readStringValue((status.connection as any)?.state);
|
|
499
|
+
const pendingPeerGitProbe = !inlineTransitGit
|
|
500
|
+
&& !isSelfNode
|
|
501
|
+
&& !!daemonId
|
|
502
|
+
&& (
|
|
503
|
+
readStringValue(status.machineStatus) === 'online'
|
|
504
|
+
|| readStringValue(status.health) === 'online'
|
|
505
|
+
|| connectionState === 'connecting'
|
|
506
|
+
|| connectionState === 'connected'
|
|
507
|
+
|| connectionState === 'unknown'
|
|
508
|
+
);
|
|
509
|
+
if (pendingPeerGitProbe) {
|
|
510
|
+
status.gitProbePending = true;
|
|
511
|
+
status.health = 'unknown';
|
|
512
|
+
}
|
|
513
|
+
if (applyCachedInlineMeshNodeStatus(
|
|
514
|
+
status,
|
|
515
|
+
node,
|
|
516
|
+
pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : undefined,
|
|
517
|
+
)) {
|
|
518
|
+
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
519
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
520
|
+
return status;
|
|
521
|
+
}
|
|
522
|
+
if (meshRecord?.source === 'inline_cache' && !isSelfNode) {
|
|
523
|
+
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
524
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
525
|
+
return status;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
} else {
|
|
529
|
+
try {
|
|
530
|
+
// Route through the shared per-request cache so this
|
|
531
|
+
// local probe reuses the bootstrap hydrate's probe for
|
|
532
|
+
// the same workspace (and vice versa) instead of
|
|
533
|
+
// re-shelling ~14 git processes across the 1.5s TTL.
|
|
534
|
+
const runLocalProbe = () => getGitRepoStatus(workspace, { timeoutMs: 10_000, refreshUpstream: true }) as unknown as Promise<Record<string, unknown> | null>;
|
|
535
|
+
const gitStatus = (await meshGitProbeCache.probeLocal(workspace, runLocalProbe)) as any;
|
|
536
|
+
if (!gitStatus) throw new Error('local_git_probe_unavailable');
|
|
537
|
+
status.git = gitStatus;
|
|
538
|
+
status[MESH_NODE_LIVE_TRUTH_MARKER] = true;
|
|
539
|
+
const reporter = recordInlineMeshDirectGitTruth(node, gitStatus as unknown as Record<string, unknown>, 'selected_coordinator_local_git');
|
|
540
|
+
persistNodeReporterPlatform(meshRecord.source, mesh, nodeId, reporter);
|
|
541
|
+
if (gitStatus.isGitRepo) {
|
|
542
|
+
status.health = deriveMeshNodeHealthFromGit(gitStatus as unknown as Record<string, unknown>);
|
|
543
|
+
} else {
|
|
544
|
+
status.health = 'degraded';
|
|
545
|
+
if (gitStatus.error && !status.error) status.error = gitStatus.error;
|
|
546
|
+
}
|
|
547
|
+
} catch {
|
|
548
|
+
if (!applyCachedInlineMeshNodeStatus(status, node)) {
|
|
549
|
+
status.health = 'degraded';
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
} else {
|
|
554
|
+
applyCachedInlineMeshNodeStatus(status, node);
|
|
555
|
+
}
|
|
556
|
+
applyInlineMeshBranchConvergence(mesh, node, status);
|
|
557
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
558
|
+
return status;
|
|
559
|
+
};
|
|
560
|
+
const meshNodeEntries = [...(mesh.nodes || []).entries()];
|
|
561
|
+
const settledNodeStatuses = await Promise.allSettled(
|
|
562
|
+
meshNodeEntries.map(([nodeIndex, node]) => renderMeshNode(nodeIndex, node)),
|
|
563
|
+
);
|
|
564
|
+
const nodeStatuses = settledNodeStatuses.map((settled, i) => {
|
|
565
|
+
if (settled.status === 'fulfilled') return settled.value;
|
|
566
|
+
// A per-node render should never reject (every git path is
|
|
567
|
+
// caught internally), but if one does, degrade to a minimal
|
|
568
|
+
// last-known/unknown entry for THAT node so a single failure
|
|
569
|
+
// can't drop the whole aggregate. Best-effort recovery of the
|
|
570
|
+
// node's cached inline truth, else an unknown-health stub.
|
|
571
|
+
const [nodeIndex, node] = meshNodeEntries[i];
|
|
572
|
+
const nodeId = normalizeMeshNodeId(node) ?? '';
|
|
573
|
+
const daemonId = readStringValue(node.daemonId);
|
|
574
|
+
const fallback: Record<string, unknown> = {
|
|
575
|
+
nodeId,
|
|
576
|
+
machineLabel: buildMeshNodeDisplayLabel(node as Record<string, unknown>, nodeId, readProviderPriorityFromPolicy(node.policy)),
|
|
577
|
+
workspace: node.workspace,
|
|
578
|
+
repoRoot: node.repoRoot,
|
|
579
|
+
isLocalWorktree: node.isLocalWorktree,
|
|
580
|
+
worktreeBranch: node.worktreeBranch,
|
|
581
|
+
daemonId,
|
|
582
|
+
machineId: readMeshNodeMachineId(node as Record<string, unknown>) || node.machineId,
|
|
583
|
+
health: 'unknown',
|
|
584
|
+
providers: node.providers || [],
|
|
585
|
+
activeSessions: [],
|
|
586
|
+
activeSessionDetails: [],
|
|
587
|
+
launchReady: false,
|
|
588
|
+
error: settled.reason instanceof Error ? settled.reason.message : 'node render failed',
|
|
589
|
+
};
|
|
590
|
+
applyCachedInlineMeshNodeStatus(fallback, node);
|
|
591
|
+
applyInlineMeshBranchConvergence(mesh, node, fallback);
|
|
592
|
+
finalizeMeshNodeStatus({ status: fallback, node, daemonId, isSelfNode: false, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
|
|
593
|
+
return fallback;
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
// (B3) Resolve the coordinator daemon scope for the peek.
|
|
597
|
+
// mesh_status is a read-only status query — it must not consume
|
|
598
|
+
// (drain) pending events as a side effect. Coordinators that see
|
|
599
|
+
// pendingCoordinatorEvents in the response are expected to call
|
|
600
|
+
// get_pending_mesh_events to explicitly drain them after processing.
|
|
601
|
+
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === 'string' && args.coordinatorDaemonId.trim()
|
|
602
|
+
? args.coordinatorDaemonId.trim()
|
|
603
|
+
: (ctx.deps.statusInstanceId || undefined);
|
|
604
|
+
const pendingCoordinatorEvents = getPendingMeshCoordinatorEvents(meshId, callerCoordinatorDaemonId);
|
|
605
|
+
// R4: surface recent fail-loud routing drops so a coordinator/operator can see
|
|
606
|
+
// that a worker completion was lost (envelope present, mesh unresolved) instead
|
|
607
|
+
// of it vanishing silently. Diagnostic-only — never cached (see omit below).
|
|
608
|
+
const unroutableDeliveries = getRecentUnroutableDeliveries();
|
|
609
|
+
// T6 (B3c): live enforce/observability counters from this daemon. A
|
|
610
|
+
// process-lifetime snapshot (never cached — like unroutableDeliveries)
|
|
611
|
+
// so an operator/coordinator can read enforce state, quarantine tallies,
|
|
612
|
+
// and last-resort backstop fires straight from the aggregate status.
|
|
613
|
+
const meshProtocolV2Counters: MeshProtocolV2Counters = {
|
|
614
|
+
enforce: isMeshProtocolV2EnforceEnabled(),
|
|
615
|
+
drain: { ...getMeshV2DrainCounters() },
|
|
616
|
+
backstop: { ...getMeshV2BackstopCounters() },
|
|
617
|
+
};
|
|
618
|
+
const previewFreshness = (() => {
|
|
619
|
+
const localRepoRoot = nodeStatuses
|
|
620
|
+
.map((node: any) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace))
|
|
621
|
+
.find((candidate: string | undefined) => !!candidate && fs.existsSync(candidate));
|
|
622
|
+
return localRepoRoot ? buildPreviewFreshness(localRepoRoot) : undefined;
|
|
623
|
+
})();
|
|
624
|
+
const asyncRefineJobs = buildMeshAsyncRefineJobs({
|
|
625
|
+
meshId,
|
|
626
|
+
ledgerEntries: asyncRefineLedgerEntries,
|
|
627
|
+
pendingEvents: [...pendingCoordinatorEvents],
|
|
628
|
+
});
|
|
629
|
+
const historicalSessions = buildHistoricalMeshSessions({
|
|
630
|
+
meshId,
|
|
631
|
+
nodes: mesh.nodes || [],
|
|
632
|
+
liveSessionRecords: liveMeshSessions,
|
|
633
|
+
});
|
|
634
|
+
const { getMeshStatusMissionSummaries } = await import('../../mesh/mesh-missions.js');
|
|
635
|
+
// withStats opts in to per-mission operational rollups (durations /
|
|
636
|
+
// retries) for the dashboard mission detail. The rollup scans a
|
|
637
|
+
// bounded ledger tail per mission, but only over the bounded set
|
|
638
|
+
// returned here (live + capped history), so the cost stays linear
|
|
639
|
+
// in visible missions rather than the whole mesh history.
|
|
640
|
+
const missions = getMeshStatusMissionSummaries(meshId, { verbose: verboseMissions, withStats: true });
|
|
641
|
+
|
|
642
|
+
// FIX C-backend: fold persisted MAGI cross-verification activity into the
|
|
643
|
+
// dashboard mesh_status payload so the web MAGI surface (extractMagiActivity)
|
|
644
|
+
// can read synthesis output — needs_verification counts, the independence
|
|
645
|
+
// banner, git skew, and a bounded needs_verification preview — without
|
|
646
|
+
// re-running collection. Mirrors the MCP mesh_status tool
|
|
647
|
+
// (mesh-tools-status.ts buildMeshMagiActivity / summarizeMeshMagiActivity).
|
|
648
|
+
// Read magi_dispatched/magi_synthesis entries over a wider tail than the 20
|
|
649
|
+
// rendered above (MAGI events are sparse — a 20-entry tail routinely misses
|
|
650
|
+
// the dispatch/synthesis pair). Compact (the default) folds synthesized groups
|
|
651
|
+
// to a bounded recent set + a count summary; verbose carries the full list.
|
|
652
|
+
const { buildMeshMagiActivity, summarizeMeshMagiActivity } = await import('../../mesh/mesh-magi-status.js');
|
|
653
|
+
const magiLedgerEntries = readLedgerEntries(meshId, { kind: ['magi_dispatched', 'magi_synthesis'], tail: 200 });
|
|
654
|
+
const magiActivity = buildMeshMagiActivity({ meshId, ledgerEntries: magiLedgerEntries });
|
|
655
|
+
let magiActivityFold: ReturnType<typeof summarizeMeshMagiActivity> | undefined;
|
|
656
|
+
if (magiActivity.length > 0 && !verboseMissions) {
|
|
657
|
+
magiActivityFold = summarizeMeshMagiActivity(magiActivity);
|
|
658
|
+
}
|
|
659
|
+
const statusResult = {
|
|
660
|
+
success: true,
|
|
661
|
+
meshId: mesh.id,
|
|
662
|
+
meshName: mesh.name,
|
|
663
|
+
repoIdentity: mesh.repoIdentity,
|
|
664
|
+
defaultBranch: mesh.defaultBranch,
|
|
665
|
+
refreshedAt,
|
|
666
|
+
meshHost,
|
|
667
|
+
sourceOfTruth: {
|
|
668
|
+
membership: meshRecord?.source === 'inline_cache'
|
|
669
|
+
? 'coordinator_inline_mesh_cache'
|
|
670
|
+
: meshRecord?.source === 'local_config'
|
|
671
|
+
? 'local_mesh_config'
|
|
672
|
+
: 'inline_bootstrap_snapshot',
|
|
673
|
+
coordinatorOwnsLiveTruth: directTruthSatisfied,
|
|
674
|
+
meshHost: {
|
|
675
|
+
owner: 'mesh_host_daemon',
|
|
676
|
+
localRole: meshHost.role,
|
|
677
|
+
hostDaemonId: meshHost.hostDaemonId,
|
|
678
|
+
hostNodeId: meshHost.hostNodeId,
|
|
679
|
+
hostAddress: meshHost.hostAddress,
|
|
680
|
+
},
|
|
681
|
+
...(requireDirectPeerTruth ? {
|
|
682
|
+
currentStatus: directTruthSatisfied ? 'live_git_and_session_probes' : 'direct_peer_truth_unavailable',
|
|
683
|
+
directPeerTruth: {
|
|
684
|
+
required: true,
|
|
685
|
+
satisfied: directTruthSatisfied,
|
|
686
|
+
directEvidenceCount: effectiveDirectTruth.directEvidenceCount,
|
|
687
|
+
localConfirmedCount: effectiveDirectTruth.localConfirmedCount,
|
|
688
|
+
peerAttemptedCount: effectiveDirectTruth.peerAttemptedCount,
|
|
689
|
+
peerConfirmedCount: effectiveDirectTruth.peerConfirmedCount,
|
|
690
|
+
unavailableNodeIds: effectiveDirectTruth.unavailableNodeIds,
|
|
691
|
+
partialNodeFailures: effectiveDirectTruth.unavailableNodeIds,
|
|
692
|
+
},
|
|
693
|
+
} : {}),
|
|
694
|
+
historicalEvidenceOnly: ['recoveryHints', 'ledger.summary', 'queue.summary', 'historicalSessions'],
|
|
695
|
+
},
|
|
696
|
+
branchConvergenceSummary: summarizeInlineMeshBranchConvergence(nodeStatuses),
|
|
697
|
+
...(previewFreshness ? { previewFreshness, deployFreshness: previewFreshness } : {}),
|
|
698
|
+
nodes: nodeStatuses,
|
|
699
|
+
// Mesh-level scheduling rollup (strategy + global cap consumption). Mirrors
|
|
700
|
+
// the MCP `mesh_status` tool's `scheduling` block field-for-field so both
|
|
701
|
+
// surfaces read the same runtime; per-node detail lives on each
|
|
702
|
+
// nodes[].scheduling above.
|
|
703
|
+
scheduling: {
|
|
704
|
+
strategy: schedulingRuntime.strategy,
|
|
705
|
+
maxParallelTasks: schedulingRuntime.maxParallelTasks,
|
|
706
|
+
maxReadonlyParallelTasks: schedulingRuntime.maxReadonlyParallelTasks,
|
|
707
|
+
activeWriteAssigned: schedulingRuntime.activeWriteAssigned,
|
|
708
|
+
activeReadonlyAssigned: schedulingRuntime.activeReadonlyAssigned,
|
|
709
|
+
globalWriteCapReached: schedulingRuntime.globalWriteCapReached,
|
|
710
|
+
globalReadonlyCapReached: schedulingRuntime.globalReadonlyCapReached,
|
|
711
|
+
},
|
|
712
|
+
queue: { tasks: queue, summary: queueSummary },
|
|
713
|
+
ledger: { entries: ledgerEntries, summary: ledgerSummary },
|
|
714
|
+
...(missions.length > 0 ? { missions } : {}),
|
|
715
|
+
// Compact (default): bounded folded groups + a status-count summary.
|
|
716
|
+
// Verbose: the full reconstructed activity list. Mirrors the MCP tool.
|
|
717
|
+
...(magiActivity.length > 0
|
|
718
|
+
? (magiActivityFold
|
|
719
|
+
? {
|
|
720
|
+
...(magiActivityFold.groups.length > 0 ? { magiActivity: magiActivityFold.groups } : {}),
|
|
721
|
+
magiActivitySummary: {
|
|
722
|
+
total: magiActivityFold.total,
|
|
723
|
+
byStatus: magiActivityFold.byStatus,
|
|
724
|
+
...(magiActivityFold.staleSynthesized > 0 ? { staleSynthesized: magiActivityFold.staleSynthesized } : {}),
|
|
725
|
+
},
|
|
726
|
+
}
|
|
727
|
+
: { magiActivity })
|
|
728
|
+
: {}),
|
|
729
|
+
...(asyncRefineJobs.length > 0 ? { asyncRefineJobs } : {}),
|
|
730
|
+
...(historicalSessions ? { historicalSessions } : {}),
|
|
731
|
+
...(pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {}),
|
|
732
|
+
...(unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {}),
|
|
733
|
+
meshProtocolV2Counters,
|
|
734
|
+
activeRefineJobs: Array.from(ctx.runningRefineJobs.values())
|
|
735
|
+
.filter(job => job.meshId === meshId)
|
|
736
|
+
.map(job => ({
|
|
737
|
+
jobId: job.jobId,
|
|
738
|
+
nodeId: job.targetNodeId,
|
|
739
|
+
workspace: job.workspace,
|
|
740
|
+
startedAt: job.startedAt,
|
|
741
|
+
status: job.status,
|
|
742
|
+
targetCoordinatorDaemonId: job.targetCoordinatorDaemonId,
|
|
743
|
+
})),
|
|
744
|
+
};
|
|
745
|
+
const { pendingCoordinatorEvents: _pendingCoordinatorEvents, unroutableDeliveries: _unroutableDeliveries, meshProtocolV2Counters: _meshProtocolV2Counters, ...cacheableStatusResult } = statusResult as any;
|
|
746
|
+
// Verbose carries full mission goals; never store it in the shared
|
|
747
|
+
// (compact) aggregate cache or a later compact poll would return the
|
|
748
|
+
// heavy goals from cache. Return it without caching.
|
|
749
|
+
const rememberedStatus = verboseMissions
|
|
750
|
+
? cacheableStatusResult
|
|
751
|
+
: ctx.rememberAggregateMeshStatus(meshId, cacheableStatusResult, refreshReason);
|
|
752
|
+
const returnedStatus = {
|
|
753
|
+
...rememberedStatus,
|
|
754
|
+
...(pendingCoordinatorEvents.length > 0 ? { pendingCoordinatorEvents } : {}),
|
|
755
|
+
...(unroutableDeliveries.length > 0 ? { unroutableDeliveries } : {}),
|
|
756
|
+
meshProtocolV2Counters,
|
|
757
|
+
};
|
|
758
|
+
logRepoMeshStatusDebug('return_live', {
|
|
759
|
+
meshId,
|
|
760
|
+
command: 'mesh_status',
|
|
761
|
+
refreshRequested,
|
|
762
|
+
refreshReason,
|
|
763
|
+
meshSource: meshRecord.source,
|
|
764
|
+
directTruth,
|
|
765
|
+
durationMs: Date.now() - startedAtMs,
|
|
766
|
+
summary: summarizeRepoMeshStatusDebug(returnedStatus),
|
|
767
|
+
});
|
|
768
|
+
return returnedStatus;
|
|
769
|
+
} catch (e: any) {
|
|
770
|
+
return { success: false, error: e.message };
|
|
771
|
+
}
|
|
772
|
+
},
|
|
773
|
+
|
|
774
|
+
get_mesh_review_inbox: async (ctx: HighFamilyContext, args: any) => {
|
|
775
|
+
const meshId = typeof args?.meshId === 'string' ? args.meshId.trim() : '';
|
|
776
|
+
if (!meshId) return { success: false, error: 'meshId required' };
|
|
777
|
+
try {
|
|
778
|
+
const { deriveMeshReviewInboxItems } = await import('../../mesh/mesh-review-inbox.js');
|
|
779
|
+
const { readLedgerEntries } = await import('../../mesh/mesh-ledger.js');
|
|
780
|
+
const { getGitDiffSummary } = await import('../../git/git-diff.js');
|
|
781
|
+
const { existsSync } = await import('node:fs');
|
|
782
|
+
|
|
783
|
+
const meshRecord = await ctx.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
784
|
+
const mesh = meshRecord?.mesh;
|
|
785
|
+
if (!mesh) return { success: false, error: 'Mesh not found' };
|
|
786
|
+
|
|
787
|
+
// Ensure we have a fresh aggregate status so nodeStatuses carry
|
|
788
|
+
// computed fields (connection.state, branchConvergence, isLocalWorktree)
|
|
789
|
+
// that the raw mesh.nodes config objects don't have.
|
|
790
|
+
// When the caller provides an inlineMesh, prefer its nodes directly
|
|
791
|
+
// (they already carry the computed fields from the coordinator).
|
|
792
|
+
const inlineNodes = args?.inlineMesh && Array.isArray((args.inlineMesh as any)?.nodes)
|
|
793
|
+
? (args.inlineMesh as any).nodes as Record<string, unknown>[]
|
|
794
|
+
: null;
|
|
795
|
+
let cachedStatus = !inlineNodes ? ctx.getCachedAggregateMeshStatus(meshId, mesh, {}) : null;
|
|
796
|
+
if (!cachedStatus && !inlineNodes) {
|
|
797
|
+
const freshStatus = await ctx.execute('mesh_status', {
|
|
798
|
+
meshId,
|
|
799
|
+
inlineMesh: args?.inlineMesh,
|
|
800
|
+
refresh: true,
|
|
801
|
+
}, 'get_mesh_review_inbox');
|
|
802
|
+
cachedStatus = (freshStatus?.success !== false) ? freshStatus : null;
|
|
803
|
+
}
|
|
804
|
+
const nodeStatuses: Record<string, unknown>[] = inlineNodes
|
|
805
|
+
? inlineNodes
|
|
806
|
+
: Array.isArray(cachedStatus?.nodes)
|
|
807
|
+
? cachedStatus.nodes as Record<string, unknown>[]
|
|
808
|
+
: Array.isArray(mesh.nodes)
|
|
809
|
+
? mesh.nodes as Record<string, unknown>[]
|
|
810
|
+
: [];
|
|
811
|
+
|
|
812
|
+
const ledgerEntries = readLedgerEntries(meshId, { tail: 300 });
|
|
813
|
+
const derivation = deriveMeshReviewInboxItems({ nodes: nodeStatuses, ledgerEntries });
|
|
814
|
+
|
|
815
|
+
for (const item of derivation.items) {
|
|
816
|
+
const workspace = item.workspace;
|
|
817
|
+
if (!workspace || !existsSync(workspace)) continue;
|
|
818
|
+
const baseRef = item.defaultBranch
|
|
819
|
+
? `origin/${item.defaultBranch}`
|
|
820
|
+
: 'origin/main';
|
|
821
|
+
try {
|
|
822
|
+
const diffResult = await getGitDiffSummary(workspace, { baseRef, maxFiles: 100 });
|
|
823
|
+
if (diffResult.isGitRepo) {
|
|
824
|
+
item.diffSummary = {
|
|
825
|
+
baseRef,
|
|
826
|
+
files: diffResult.files.map(f => ({
|
|
827
|
+
path: f.path,
|
|
828
|
+
status: f.status,
|
|
829
|
+
insertions: f.insertions,
|
|
830
|
+
deletions: f.deletions,
|
|
831
|
+
binary: f.binary,
|
|
832
|
+
oldPath: f.oldPath,
|
|
833
|
+
})),
|
|
834
|
+
totalFiles: diffResult.files.length,
|
|
835
|
+
totalInsertions: diffResult.totalInsertions,
|
|
836
|
+
totalDeletions: diffResult.totalDeletions,
|
|
837
|
+
truncated: diffResult.truncated,
|
|
838
|
+
...(diffResult.error ? { error: diffResult.error } : {}),
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
} catch {
|
|
842
|
+
item.diffSummary = null;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
return {
|
|
847
|
+
success: true,
|
|
848
|
+
meshId,
|
|
849
|
+
inbox: derivation.items,
|
|
850
|
+
remoteNodesExcluded: derivation.remoteNodesExcluded,
|
|
851
|
+
excludedRemoteNodeIds: derivation.excludedRemoteNodeIds,
|
|
852
|
+
};
|
|
853
|
+
} catch (e: any) {
|
|
854
|
+
return { success: false, error: e.message };
|
|
855
|
+
}
|
|
856
|
+
},
|
|
857
|
+
};
|