@adhdev/daemon-core 0.9.82-rc.43 → 0.9.82-rc.431
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 +200 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +126 -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 +7 -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 +15 -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 +60 -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 +29 -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 +142 -0
- package/dist/commands/mesh-coordinator.d.ts +85 -1
- package/dist/commands/router.d.ts +276 -2
- package/dist/commands/upgrade-helper.d.ts +41 -1
- package/dist/config/chat-history.d.ts +9 -0
- package/dist/config/config.d.ts +5 -0
- package/dist/config/mesh-config.d.ts +100 -1
- package/dist/config/mesh-json-config.d.ts +199 -0
- package/dist/config/repo-settings.d.ts +77 -0
- package/dist/daemon/dev-server.d.ts +0 -2
- 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 +11 -1
- 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 +57 -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 +64 -14
- package/dist/index.js +49391 -19228
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +48574 -18570
- 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/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 +164 -0
- package/dist/mesh/coordinator-prompt.d.ts +89 -0
- package/dist/mesh/coordinator-registry.d.ts +59 -0
- package/dist/mesh/mesh-active-work.d.ts +174 -0
- package/dist/mesh/mesh-clone-grace.d.ts +8 -0
- package/dist/mesh/mesh-coordinator-config.d.ts +21 -0
- package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
- package/dist/mesh/mesh-event-classify.d.ts +5 -0
- package/dist/mesh/mesh-event-forwarding.d.ts +41 -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 +69 -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 +9 -0
- package/dist/mesh/mesh-init.d.ts +86 -0
- package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -4
- package/dist/mesh/mesh-ledger.d.ts +77 -1
- package/dist/mesh/mesh-magi-status.d.ts +63 -0
- package/dist/mesh/mesh-missions.d.ts +189 -0
- package/dist/mesh/mesh-node-identity.d.ts +289 -0
- package/dist/mesh/mesh-queue-assignment.d.ts +113 -0
- package/dist/mesh/mesh-reconcile-loop.d.ts +65 -0
- package/dist/mesh/mesh-refine-batch.d.ts +68 -0
- package/dist/mesh/mesh-refine-gates.d.ts +428 -0
- package/dist/mesh/mesh-refine-status.d.ts +62 -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 +450 -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 +30 -0
- package/dist/mesh/mesh-warmup-deadline.d.ts +68 -0
- package/dist/mesh/mesh-work-queue.d.ts +290 -5
- package/dist/mesh/preview-freshness.d.ts +18 -0
- package/dist/mesh/refine-config.d.ts +216 -0
- package/dist/mesh/worktree-bootstrap-config.d.ts +145 -0
- package/dist/providers/acp-provider-instance.d.ts +5 -0
- package/dist/providers/approval-utils.d.ts +20 -0
- package/dist/providers/chat-message-normalization.d.ts +31 -1
- package/dist/providers/cli-provider-instance.d.ts +221 -3
- package/dist/providers/contracts.d.ts +139 -6
- package/dist/providers/external-sources.d.ts +71 -0
- package/dist/providers/manual-attendance.d.ts +63 -0
- package/dist/providers/native-history/antigravity-cli-transcript.d.ts +100 -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 +27 -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 +29 -0
- package/dist/providers/provider-instance.d.ts +23 -1
- package/dist/providers/provider-loader.d.ts +26 -4
- 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 +91 -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 +422 -0
- package/dist/providers/spec/fsm-evaluator.d.ts +76 -0
- package/dist/providers/spec/fsm-loader.d.ts +14 -0
- package/dist/providers/spec/fsm-types.d.ts +174 -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 +222 -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 +501 -13
- package/dist/runtime-defaults.d.ts +2 -0
- package/dist/sessions/registry.d.ts +6 -0
- package/dist/shared-types-extra.d.ts +2 -4
- package/dist/shared-types.d.ts +59 -2
- 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 +26 -0
- package/dist/system/hash.d.ts +8 -0
- package/dist/system/load-better-sqlite3.d.ts +21 -0
- package/dist/types.d.ts +5 -0
- package/package.json +7 -3
- package/src/agent-stream/poller.ts +2 -3
- package/src/agent-stream/provider-adapter.ts +1 -1
- package/src/boot/daemon-lifecycle.ts +63 -12
- 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 +1246 -0
- package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +914 -1144
- 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/WINDOWS-UPGRADE-LOCK-FAILURE.md +198 -0
- package/src/commands/chat-commands-debug-bundle.ts +398 -0
- package/src/commands/chat-commands-read.ts +2327 -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.ts +544 -26
- package/src/commands/handler.ts +841 -2
- package/src/commands/high-family/index.ts +28 -0
- package/src/commands/high-family/mesh-coordinator-launch.ts +678 -0
- package/src/commands/high-family/mesh-events.ts +80 -0
- package/src/commands/high-family/mesh-status.ts +710 -0
- package/src/commands/high-family/types.ts +76 -0
- package/src/commands/low-family/coordinator-prompt.ts +72 -0
- package/src/commands/low-family/daemon-lifecycle.ts +107 -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 +274 -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 +238 -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 +1066 -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 +143 -0
- package/src/commands/mesh-coordinator.ts +334 -124
- package/src/commands/router.ts +2711 -3254
- package/src/commands/stream-commands.ts +8 -0
- package/src/commands/upgrade-helper.ts +310 -45
- package/src/config/chat-history.ts +483 -24
- package/src/config/config.ts +12 -0
- package/src/config/mesh-config.ts +495 -22
- package/src/config/mesh-json-config.ts +376 -0
- package/src/config/recent-activity.ts +8 -2
- package/src/config/repo-settings.ts +111 -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 +28 -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 +59 -15
- package/src/git/git-diff.ts +81 -11
- package/src/git/git-executor.ts +12 -0
- package/src/git/git-status.ts +767 -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 +194 -12
- 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/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 +338 -0
- package/src/mesh/coordinator-prompt.ts +381 -33
- package/src/mesh/coordinator-registry.ts +121 -0
- package/src/mesh/mesh-active-work.ts +645 -0
- package/src/mesh/mesh-clone-grace.ts +68 -0
- package/src/mesh/mesh-coordinator-config.ts +97 -0
- package/src/mesh/mesh-delivery-policy.ts +315 -0
- package/src/mesh/mesh-event-classify.ts +51 -0
- package/src/mesh/mesh-event-forwarding.ts +1888 -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 +656 -0
- package/src/mesh/mesh-events-stale.ts +389 -0
- package/src/mesh/mesh-events-utils.ts +443 -0
- package/src/mesh/mesh-events.ts +33 -1035
- package/src/mesh/mesh-fast-forward.ts +843 -0
- package/src/mesh/mesh-host-ownership.ts +73 -0
- package/src/mesh/mesh-init.ts +260 -0
- package/src/mesh/mesh-ledger-reconciliation.ts +12 -7
- package/src/mesh/mesh-ledger.ts +656 -102
- package/src/mesh/mesh-magi-status.ts +223 -0
- package/src/mesh/mesh-missions.ts +449 -0
- package/src/mesh/mesh-node-identity.ts +1887 -0
- package/src/mesh/mesh-queue-assignment.ts +1918 -0
- package/src/mesh/mesh-reconcile-loop.ts +1780 -0
- package/src/mesh/mesh-refine-batch.ts +205 -0
- package/src/mesh/mesh-refine-gates.ts +1673 -0
- package/src/mesh/mesh-refine-status.ts +231 -0
- package/src/mesh/mesh-review-inbox.ts +307 -0
- package/src/mesh/mesh-routing.ts +291 -0
- package/src/mesh/mesh-runtime-store.ts +1853 -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 +185 -0
- package/src/mesh/mesh-warmup-deadline.ts +152 -0
- package/src/mesh/mesh-work-queue.ts +1243 -141
- package/src/mesh/preview-freshness.ts +118 -0
- package/src/mesh/refine-config.ts +423 -0
- package/src/mesh/worktree-bootstrap-config.ts +450 -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 +57 -5
- package/src/providers/chat-message-normalization.ts +92 -4
- package/src/providers/cli-provider-instance.ts +1933 -104
- package/src/providers/contracts.d.ts +55 -0
- package/src/providers/contracts.ts +150 -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 +85 -0
- package/src/providers/native-history/antigravity-cli-transcript.ts +643 -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 +339 -0
- package/src/providers/native-history/hermes-cli-transcript.ts +230 -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 +19 -1
- package/src/providers/provider-loader.ts +668 -50
- package/src/providers/provider-schema.ts +87 -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 +250 -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 +504 -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 +235 -0
- package/src/providers/spec/cli-adapter.ts +1056 -0
- package/src/providers/spec/evaluator.ts +407 -0
- package/src/providers/spec/fsm-driver.ts +1410 -0
- package/src/providers/spec/fsm-evaluator.ts +272 -0
- package/src/providers/spec/fsm-loader.ts +120 -0
- package/src/providers/spec/fsm-types.ts +273 -0
- package/src/providers/spec/native-history-executor.ts +1128 -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 +262 -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 +740 -14
- package/src/runtime-defaults.ts +39 -0
- package/src/sessions/registry.ts +6 -0
- package/src/shared-types-extra.ts +2 -4
- package/src/shared-types.d.ts +8 -0
- package/src/shared-types.ts +64 -1
- package/src/status/builders.ts +26 -6
- package/src/status/normalize.ts +2 -0
- package/src/status/reporter.ts +19 -1
- package/src/status/snapshot.ts +95 -26
- 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 +5 -0
- 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,450 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'fs';
|
|
2
|
+
import { join, resolve as pathResolve } from 'path';
|
|
3
|
+
import { execFile, execFileSync } from 'node:child_process';
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
5
|
+
import { promisify } from 'node:util';
|
|
6
|
+
import * as yaml from 'js-yaml';
|
|
7
|
+
import { resolveWin32Executable, buildWin32ExecFileSpawn } from '../cli-adapters/resolve-executable.js';
|
|
8
|
+
import {
|
|
9
|
+
isMeshConfigRecord,
|
|
10
|
+
normalizeMeshCommandConfig,
|
|
11
|
+
type MeshRefineValidationCommandPlan,
|
|
12
|
+
type RepoMeshRefineValidationCommandConfig,
|
|
13
|
+
} from './refine-config.js';
|
|
14
|
+
import type { MeshAsyncJobLifecycle } from '../repo-mesh-types.js';
|
|
15
|
+
|
|
16
|
+
// 'complete' is the terminal status the coordinator's markWorktreeBootstrapTerminalState
|
|
17
|
+
// (router.ts) stamps when the worktree_bootstrap_complete event fires — distinct from
|
|
18
|
+
// 'ready' (which carries a staleInputs digest from an in-process run). It is terminal and
|
|
19
|
+
// must be recognized as such by evaluateWorktreeBootstrapState so a later re-hydration never
|
|
20
|
+
// round-trips it back to 'stale'/'never_ran'.
|
|
21
|
+
export type WorktreeBootstrapStatus = 'ready' | 'complete' | 'running' | 'failed' | 'not_configured' | 'disabled' | 'stale';
|
|
22
|
+
|
|
23
|
+
export interface RepoMeshWorktreeBootstrapConfig {
|
|
24
|
+
version: 1;
|
|
25
|
+
enabled?: boolean;
|
|
26
|
+
runOnClone?: boolean;
|
|
27
|
+
required?: boolean;
|
|
28
|
+
commands?: RepoMeshRefineValidationCommandConfig[];
|
|
29
|
+
staleInputs?: string[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface WorktreeBootstrapState extends MeshAsyncJobLifecycle {
|
|
33
|
+
status: WorktreeBootstrapStatus;
|
|
34
|
+
required: boolean;
|
|
35
|
+
configSource?: string;
|
|
36
|
+
configSourceType?: 'repo_file' | 'mesh_policy' | 'unavailable' | 'invalid';
|
|
37
|
+
lastCommand?: string;
|
|
38
|
+
exitCode?: number | null;
|
|
39
|
+
commandsRun?: Array<Record<string, unknown>>;
|
|
40
|
+
staleInputs?: string[];
|
|
41
|
+
/**
|
|
42
|
+
* M2-1: sha256 per staleInputs path recorded when the bootstrap reached
|
|
43
|
+
* 'ready'. evaluateWorktreeBootstrapState compares current file hashes
|
|
44
|
+
* against this to detect staleness (e.g. base merge changed a lockfile).
|
|
45
|
+
* Missing files hash to the literal 'absent'.
|
|
46
|
+
*/
|
|
47
|
+
staleInputsDigest?: Record<string, string>;
|
|
48
|
+
/** M2-1: why an evaluated state resolved to stale (digest_mismatch | never_ran). */
|
|
49
|
+
staleReason?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Fix (3) safety net: a worktree node whose bootstrap state is stuck 'running' far longer than
|
|
53
|
+
// any real bootstrap (observed ~2m8s) is almost certainly one whose terminal-state stamp never
|
|
54
|
+
// reached this daemon's mesh view — the claim/dispatch defer guards would otherwise gate it
|
|
55
|
+
// forever. This backstop lets a dispatch through ONLY when BOTH hold: the 'running' state is
|
|
56
|
+
// older than WORKTREE_BOOTSTRAP_STALE_RUNNING_MS AND the node's working tree is git-clean. The
|
|
57
|
+
// clean co-requirement is the real guard — a genuinely in-progress bootstrap (npm install /
|
|
58
|
+
// native-addon repair) leaves the tree mid-build, so a clean tree means the bootstrap work has
|
|
59
|
+
// settled. The threshold is floored well above the observed real bootstrap so a slow-but-live
|
|
60
|
+
// bootstrap is never downgraded. Conservative by design: when clean-ness cannot be verified (no
|
|
61
|
+
// local workspace on disk, or git errors) it returns false and the gate stays closed.
|
|
62
|
+
export const WORKTREE_BOOTSTRAP_STALE_RUNNING_MS = 10 * 60 * 1000;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Enumerate registered submodule paths for a worktree, generically (no hardcoded
|
|
66
|
+
* 'oss'/'adhdev-providers'). Reads `.gitmodules` via `git config --file .gitmodules
|
|
67
|
+
* --get-regexp path`, whose lines are `submodule.<name>.path <relativePath>`. Paths
|
|
68
|
+
* are returned normalized to forward slashes (git porcelain always emits '/'),
|
|
69
|
+
* trailing slash stripped. Returns an empty set when there are no submodules or the
|
|
70
|
+
* lookup fails — callers must then treat any change as dirty (conservative).
|
|
71
|
+
*/
|
|
72
|
+
function getRegisteredSubmodulePaths(workspace: string): Set<string> {
|
|
73
|
+
const paths = new Set<string>();
|
|
74
|
+
try {
|
|
75
|
+
const out = execFileSync(
|
|
76
|
+
resolveWin32Executable('git'),
|
|
77
|
+
['config', '--file', '.gitmodules', '--get-regexp', 'path'],
|
|
78
|
+
{ cwd: workspace, encoding: 'utf8', timeout: 10_000, windowsHide: true },
|
|
79
|
+
);
|
|
80
|
+
for (const line of String(out).split(/\r?\n/)) {
|
|
81
|
+
const trimmed = line.trim();
|
|
82
|
+
if (!trimmed) continue;
|
|
83
|
+
// `submodule.<name>.path <relativePath>` — value is everything after the first space.
|
|
84
|
+
const spaceIdx = trimmed.indexOf(' ');
|
|
85
|
+
if (spaceIdx < 0) continue;
|
|
86
|
+
const value = trimmed.slice(spaceIdx + 1).trim().replace(/\\/g, '/').replace(/\/+$/, '');
|
|
87
|
+
if (value) paths.add(value);
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
// No .gitmodules / not a submodule superproject / git error → no exemptions.
|
|
91
|
+
}
|
|
92
|
+
return paths;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* True when `git status --porcelain` output represents a worktree that is clean
|
|
97
|
+
* EXCEPT for submodule-gitlink-pointer moves. A worktree task that commits inside a
|
|
98
|
+
* registered submodule (e.g. oss/) leaves the superproject's gitlink outOfSync — a
|
|
99
|
+
* porcelain line of exactly " M <submodulePath>" (or "M <submodulePath>") — which is
|
|
100
|
+
* a NORMAL product of that task and must NOT disqualify the stale backstop. Any other
|
|
101
|
+
* line (a real file edit, an untracked file, a staged add, an unmerged path) means the
|
|
102
|
+
* tree is genuinely dirty → not clean. We filter gitlink lines explicitly rather than
|
|
103
|
+
* using `git status --ignore-submodules=all`, which would also mask a submodule with
|
|
104
|
+
* genuinely-uncommitted *content* (=dirty still surfaces pointer moves we want to ignore;
|
|
105
|
+
* =all would over-suppress).
|
|
106
|
+
*/
|
|
107
|
+
function isCleanIgnoringSubmoduleGitlinks(porcelain: string, submodulePaths: Set<string>): boolean {
|
|
108
|
+
const lines = porcelain.split(/\r?\n/).filter(line => line.length > 0);
|
|
109
|
+
for (const line of lines) {
|
|
110
|
+
// Porcelain v1 line: two status chars (XY) + space + path. A submodule gitlink
|
|
111
|
+
// pointer move shows X or Y as 'M' with the other position a space, e.g.
|
|
112
|
+
// " M oss" (worktree-modified) or "M oss" (index-modified). Quoted paths
|
|
113
|
+
// (core.quotePath) wrap in double-quotes — those never match a bare submodule path,
|
|
114
|
+
// so they correctly fall through as dirty.
|
|
115
|
+
const status = line.slice(0, 2);
|
|
116
|
+
const path = line.slice(3).trim().replace(/\\/g, '/').replace(/\/+$/, '');
|
|
117
|
+
const isGitlinkPointerMove = (status === ' M' || status === 'M ') && submodulePaths.has(path);
|
|
118
|
+
if (!isGitlinkPointerMove) return false; // any non-gitlink change → dirty
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function isWorktreeBootstrapStaleRunning(
|
|
124
|
+
node: { worktreeBootstrap?: { status?: string; startedAt?: string; updatedAt?: string; completedAt?: string }; workspace?: string } | undefined,
|
|
125
|
+
nowMs: number = Date.now(),
|
|
126
|
+
): boolean {
|
|
127
|
+
const wb = node?.worktreeBootstrap;
|
|
128
|
+
if (!wb || wb.status !== 'running') return false;
|
|
129
|
+
const startedRaw = wb.updatedAt || wb.startedAt;
|
|
130
|
+
if (!startedRaw) return false;
|
|
131
|
+
const startedMs = Date.parse(startedRaw);
|
|
132
|
+
if (!Number.isFinite(startedMs)) return false;
|
|
133
|
+
if (nowMs - startedMs <= WORKTREE_BOOTSTRAP_STALE_RUNNING_MS) return false;
|
|
134
|
+
const workspace = typeof node?.workspace === 'string' ? node.workspace.trim() : '';
|
|
135
|
+
if (!workspace || !existsSync(workspace)) return false; // only verifiable for a local workspace
|
|
136
|
+
try {
|
|
137
|
+
const out = execFileSync(resolveWin32Executable('git'), ['status', '--porcelain'], {
|
|
138
|
+
cwd: workspace,
|
|
139
|
+
encoding: 'utf8',
|
|
140
|
+
timeout: 10_000,
|
|
141
|
+
windowsHide: true,
|
|
142
|
+
});
|
|
143
|
+
const porcelain = String(out).replace(/\r?\n$/, '');
|
|
144
|
+
if (porcelain.trim() === '') return true; // truly clean
|
|
145
|
+
// A worktree task that committed inside a submodule leaves the superproject's
|
|
146
|
+
// submodule-gitlink pointer outOfSync (" M oss"); that is the normal aftermath of the
|
|
147
|
+
// task this backstop exists to unstick, not an in-progress bootstrap, so a tree dirty
|
|
148
|
+
// ONLY by gitlink pointer moves still counts as clean here.
|
|
149
|
+
const submodulePaths = getRegisteredSubmodulePaths(workspace);
|
|
150
|
+
if (submodulePaths.size === 0) return false; // no submodules → no exemption, dirty
|
|
151
|
+
return isCleanIgnoringSubmoduleGitlinks(porcelain, submodulePaths);
|
|
152
|
+
} catch {
|
|
153
|
+
return false; // cannot verify clean → stay conservative (gate remains closed)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface WorktreeBootstrapConfigLoadResult {
|
|
158
|
+
config?: RepoMeshWorktreeBootstrapConfig;
|
|
159
|
+
source: string;
|
|
160
|
+
sourceType: 'repo_file' | 'mesh_policy' | 'unavailable' | 'invalid';
|
|
161
|
+
path?: string;
|
|
162
|
+
error?: string;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export const MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS = [
|
|
166
|
+
'.adhdev/worktree_bootstrap.json',
|
|
167
|
+
'.adhdev/worktree_bootstrap.yaml',
|
|
168
|
+
'.adhdev/worktree_bootstrap.yml',
|
|
169
|
+
'.adhdev/worktree-bootstrap.json',
|
|
170
|
+
'.adhdev/worktree-bootstrap.yaml',
|
|
171
|
+
'.adhdev/worktree-bootstrap.yml',
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
export const MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA = {
|
|
175
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
176
|
+
title: 'ADHDev Repo Mesh Worktree Bootstrap Config',
|
|
177
|
+
type: 'object',
|
|
178
|
+
additionalProperties: false,
|
|
179
|
+
required: ['version'],
|
|
180
|
+
properties: {
|
|
181
|
+
version: { const: 1 },
|
|
182
|
+
enabled: { type: 'boolean', default: true },
|
|
183
|
+
runOnClone: { type: 'boolean', default: true },
|
|
184
|
+
required: { type: 'boolean', default: true },
|
|
185
|
+
staleInputs: { type: 'array', maxItems: 16, items: { type: 'string', minLength: 1 } },
|
|
186
|
+
commands: {
|
|
187
|
+
type: 'array',
|
|
188
|
+
minItems: 1,
|
|
189
|
+
maxItems: 4,
|
|
190
|
+
items: {
|
|
191
|
+
type: 'object',
|
|
192
|
+
additionalProperties: false,
|
|
193
|
+
required: ['command'],
|
|
194
|
+
properties: {
|
|
195
|
+
command: { type: 'string', minLength: 1 },
|
|
196
|
+
args: { type: 'array', items: { type: 'string' } },
|
|
197
|
+
category: { enum: ['typecheck', 'test', 'lint', 'build', 'custom'] },
|
|
198
|
+
cwd: { type: 'string' },
|
|
199
|
+
timeoutMs: { type: 'number', minimum: 1000, maximum: 600000 },
|
|
200
|
+
outputLimitBytes: { type: 'number', minimum: 1024, maximum: 1048576 },
|
|
201
|
+
env: { type: 'object', additionalProperties: { type: 'string' } },
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
} as const;
|
|
207
|
+
|
|
208
|
+
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
209
|
+
const DEFAULT_OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
210
|
+
const OUTPUT_SUMMARY_CHARS = 2_000;
|
|
211
|
+
|
|
212
|
+
function parseConfigText(path: string, text: string): unknown {
|
|
213
|
+
if (/\.json$/i.test(path)) return JSON.parse(text);
|
|
214
|
+
return yaml.load(text);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function truncateOutput(value: unknown): string {
|
|
218
|
+
const text = typeof value === 'string' ? value : value == null ? '' : String(value);
|
|
219
|
+
if (text.length <= OUTPUT_SUMMARY_CHARS) return text;
|
|
220
|
+
return `${text.slice(0, OUTPUT_SUMMARY_CHARS)}\n[truncated ${text.length - OUTPUT_SUMMARY_CHARS} chars]`;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function validateMeshWorktreeBootstrapConfig(config: unknown, source = 'inline'): {
|
|
224
|
+
valid: boolean;
|
|
225
|
+
errors: string[];
|
|
226
|
+
commands: MeshRefineValidationCommandPlan[];
|
|
227
|
+
rejectedCommands: Array<Record<string, unknown>>;
|
|
228
|
+
} {
|
|
229
|
+
const errors: string[] = [];
|
|
230
|
+
const commands: MeshRefineValidationCommandPlan[] = [];
|
|
231
|
+
const rejectedCommands: Array<Record<string, unknown>> = [];
|
|
232
|
+
if (!isMeshConfigRecord(config)) return { valid: false, errors: ['config must be an object'], commands, rejectedCommands };
|
|
233
|
+
if (config.version !== 1) errors.push('version must be 1');
|
|
234
|
+
if (config.enabled !== undefined && typeof config.enabled !== 'boolean') errors.push('enabled must be a boolean when provided');
|
|
235
|
+
if (config.runOnClone !== undefined && typeof config.runOnClone !== 'boolean') errors.push('runOnClone must be a boolean when provided');
|
|
236
|
+
if (config.required !== undefined && typeof config.required !== 'boolean') errors.push('required must be a boolean when provided');
|
|
237
|
+
if (config.staleInputs !== undefined && (!Array.isArray(config.staleInputs) || !config.staleInputs.every(input => typeof input === 'string' && input.trim()))) {
|
|
238
|
+
errors.push('staleInputs must be an array of non-empty strings when provided');
|
|
239
|
+
}
|
|
240
|
+
if (config.commands !== undefined && !Array.isArray(config.commands)) errors.push('commands must be an array');
|
|
241
|
+
if (Array.isArray(config.commands)) {
|
|
242
|
+
config.commands.forEach((entry, index) => {
|
|
243
|
+
const normalized = normalizeMeshCommandConfig(entry, `${source}:commands[${index}]`);
|
|
244
|
+
if (normalized.command) commands.push(normalized.command);
|
|
245
|
+
if (normalized.rejected) rejectedCommands.push(normalized.rejected);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
if (config.enabled !== false && config.runOnClone !== false && commands.length === 0) errors.push('commands must contain at least one command when bootstrap is enabled');
|
|
249
|
+
if (rejectedCommands.length) errors.push('one or more bootstrap commands are invalid');
|
|
250
|
+
return { valid: errors.length === 0, errors, commands, rejectedCommands };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function loadMeshWorktreeBootstrapConfig(mesh: any, workspace: string): WorktreeBootstrapConfigLoadResult {
|
|
254
|
+
const inline = mesh?.worktreeBootstrapConfig || mesh?.policy?.worktreeBootstrapConfig || mesh?.policy?.worktreeBootstrap;
|
|
255
|
+
if (inline !== undefined) {
|
|
256
|
+
const validation = validateMeshWorktreeBootstrapConfig(inline, 'mesh.policy.worktreeBootstrapConfig');
|
|
257
|
+
if (!validation.valid) return { source: 'mesh.policy.worktreeBootstrapConfig', sourceType: 'invalid', error: String(validation.rejectedCommands[0]?.reason || validation.errors.join('; ')) };
|
|
258
|
+
return { config: inline as RepoMeshWorktreeBootstrapConfig, source: 'mesh.policy.worktreeBootstrapConfig', sourceType: 'mesh_policy' };
|
|
259
|
+
}
|
|
260
|
+
for (const relative of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
|
|
261
|
+
const configPath = join(workspace, relative);
|
|
262
|
+
if (!existsSync(configPath)) continue;
|
|
263
|
+
try {
|
|
264
|
+
const parsed = parseConfigText(configPath, readFileSync(configPath, 'utf-8'));
|
|
265
|
+
const validation = validateMeshWorktreeBootstrapConfig(parsed, relative);
|
|
266
|
+
if (!validation.valid) return { source: relative, sourceType: 'invalid', path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join('; ')) };
|
|
267
|
+
return { config: parsed as RepoMeshWorktreeBootstrapConfig, source: relative, sourceType: 'repo_file', path: configPath };
|
|
268
|
+
} catch (error: any) {
|
|
269
|
+
return { source: relative, sourceType: 'invalid', path: configPath, error: error?.message || String(error) };
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return { source: 'unavailable', sourceType: 'unavailable', error: `No worktree bootstrap config found. Checked: ${MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS.join(', ')}` };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/** M2-1: hash staleInputs files so 'ready' can be invalidated when they change. */
|
|
276
|
+
export function computeStaleInputsDigest(workspace: string, staleInputs: string[] | undefined): Record<string, string> {
|
|
277
|
+
const digest: Record<string, string> = {};
|
|
278
|
+
for (const relative of staleInputs ?? []) {
|
|
279
|
+
const filePath = join(workspace, relative);
|
|
280
|
+
try {
|
|
281
|
+
digest[relative] = createHash('sha256').update(readFileSync(filePath)).digest('hex');
|
|
282
|
+
} catch {
|
|
283
|
+
digest[relative] = 'absent';
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return digest;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* M2-1: the official bootstrap state contract. Resolves the effective state
|
|
291
|
+
* for a node workspace from config presence + the persisted last-run state +
|
|
292
|
+
* a staleInputs digest comparison. Read-only — never runs commands.
|
|
293
|
+
*
|
|
294
|
+
* ready — last run succeeded and staleInputs are unchanged
|
|
295
|
+
* stale — never ran, or a staleInputs file changed since 'ready'
|
|
296
|
+
* running/failed — persisted lifecycle state passes through
|
|
297
|
+
* not_configured / disabled / (invalid → failed) — from config resolution
|
|
298
|
+
*/
|
|
299
|
+
export function evaluateWorktreeBootstrapState(mesh: any, workspace: string, persisted?: WorktreeBootstrapState | null): WorktreeBootstrapState {
|
|
300
|
+
const loaded = loadMeshWorktreeBootstrapConfig(mesh, workspace);
|
|
301
|
+
if (!loaded.config) {
|
|
302
|
+
return { status: 'not_configured', required: false, configSource: loaded.source, configSourceType: loaded.sourceType, error: loaded.error };
|
|
303
|
+
}
|
|
304
|
+
const required = loaded.config.required !== false;
|
|
305
|
+
if (loaded.config.enabled === false || loaded.config.runOnClone === false) {
|
|
306
|
+
return { status: 'disabled', required, configSource: loaded.path || loaded.source, configSourceType: loaded.sourceType };
|
|
307
|
+
}
|
|
308
|
+
if (loaded.sourceType === 'invalid') {
|
|
309
|
+
return { status: 'failed', required, configSource: loaded.path || loaded.source, configSourceType: 'invalid', error: loaded.error };
|
|
310
|
+
}
|
|
311
|
+
if (persisted?.status === 'running') return { ...persisted, required };
|
|
312
|
+
if (persisted?.status === 'failed') return { ...persisted, required };
|
|
313
|
+
// 'complete' is the terminal stamp written by markWorktreeBootstrapTerminalState
|
|
314
|
+
// (router.ts) on the worktree_bootstrap_complete event. Pass it through unchanged so a
|
|
315
|
+
// later getMeshWithCache re-hydration never re-derives it back to 'stale'/'never_ran' —
|
|
316
|
+
// doing so would reopen the dispatch/claim gate against a node whose bootstrap is done.
|
|
317
|
+
if (persisted?.status === 'complete') return { ...persisted, required };
|
|
318
|
+
if (persisted?.status === 'ready') {
|
|
319
|
+
const staleInputs = loaded.config.staleInputs ?? persisted.staleInputs ?? [];
|
|
320
|
+
if (staleInputs.length > 0 && persisted.staleInputsDigest) {
|
|
321
|
+
const current = computeStaleInputsDigest(workspace, staleInputs);
|
|
322
|
+
const changed = staleInputs.filter(p => current[p] !== persisted.staleInputsDigest![p]);
|
|
323
|
+
if (changed.length > 0) {
|
|
324
|
+
return {
|
|
325
|
+
...persisted,
|
|
326
|
+
status: 'stale',
|
|
327
|
+
required,
|
|
328
|
+
staleReason: `digest_mismatch: ${changed.join(', ')}`,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return { ...persisted, required };
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
status: 'stale',
|
|
336
|
+
required,
|
|
337
|
+
configSource: loaded.path || loaded.source,
|
|
338
|
+
configSourceType: loaded.sourceType,
|
|
339
|
+
staleInputs: loaded.config.staleInputs,
|
|
340
|
+
staleReason: 'never_ran',
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export async function runMeshWorktreeBootstrap(mesh: any, workspace: string): Promise<WorktreeBootstrapState> {
|
|
345
|
+
const loaded = loadMeshWorktreeBootstrapConfig(mesh, workspace);
|
|
346
|
+
if (!loaded.config) {
|
|
347
|
+
return { status: 'not_configured', required: false, configSource: loaded.source, configSourceType: loaded.sourceType, error: loaded.error };
|
|
348
|
+
}
|
|
349
|
+
const required = loaded.config.required !== false;
|
|
350
|
+
if (loaded.config.enabled === false || loaded.config.runOnClone === false) {
|
|
351
|
+
return { status: 'disabled', required, configSource: loaded.path || loaded.source, configSourceType: loaded.sourceType };
|
|
352
|
+
}
|
|
353
|
+
const validation = validateMeshWorktreeBootstrapConfig(loaded.config, loaded.source);
|
|
354
|
+
if (!validation.valid) {
|
|
355
|
+
return { status: 'failed', required, configSource: loaded.path || loaded.source, configSourceType: 'invalid', error: String(validation.rejectedCommands[0]?.reason || validation.errors.join('; ')), commandsRun: [] };
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const execFileAsync = promisify(execFile);
|
|
359
|
+
const state: WorktreeBootstrapState = {
|
|
360
|
+
status: 'running',
|
|
361
|
+
required,
|
|
362
|
+
configSource: loaded.path || loaded.source,
|
|
363
|
+
configSourceType: loaded.sourceType,
|
|
364
|
+
startedAt: new Date().toISOString(),
|
|
365
|
+
commandsRun: [],
|
|
366
|
+
staleInputs: loaded.config.staleInputs,
|
|
367
|
+
};
|
|
368
|
+
const staleInputPaths = loaded.config.staleInputs ?? [];
|
|
369
|
+
// Snapshot which staleInputs files are absent at bootstrap start.
|
|
370
|
+
// Files already present before we start are not interference signals.
|
|
371
|
+
const initiallyAbsent = staleInputPaths.filter(p => !existsSync(join(workspace, p)));
|
|
372
|
+
for (const command of validation.commands) {
|
|
373
|
+
// Check if any initially-absent staleInputs files appeared since bootstrap started
|
|
374
|
+
// (indicates another process modified the environment mid-run).
|
|
375
|
+
if (initiallyAbsent.length > 0) {
|
|
376
|
+
const appearedNow = initiallyAbsent.filter(p => existsSync(join(workspace, p)));
|
|
377
|
+
if (appearedNow.length > 0) {
|
|
378
|
+
state.status = 'stale';
|
|
379
|
+
state.completedAt = new Date().toISOString();
|
|
380
|
+
state.error = `Bootstrap interrupted: staleInputs files appeared during run: ${appearedNow.join(', ')}`;
|
|
381
|
+
return state;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
const cwd = command.cwd ? pathResolve(workspace, command.cwd) : workspace;
|
|
385
|
+
const startedAt = Date.now();
|
|
386
|
+
state.lastCommand = command.displayCommand;
|
|
387
|
+
// On win32 a bare npm/npx/tsc is a .cmd shim that libuv's spawn search
|
|
388
|
+
// (which appends only .com/.exe) cannot resolve → spawn ENOENT. Resolve
|
|
389
|
+
// to an absolute path first (no-op on non-win32 / already-absolute).
|
|
390
|
+
const resolvedCommand = resolveWin32Executable(command.command);
|
|
391
|
+
// A win32 .cmd/.bat shim (npm/npx/tsc) cannot be exec'd directly — wrap
|
|
392
|
+
// it in cmd.exe /c (no-op off win32 / for a real .exe).
|
|
393
|
+
const spawn = buildWin32ExecFileSpawn(resolvedCommand, command.args);
|
|
394
|
+
try {
|
|
395
|
+
const result = await execFileAsync(spawn.file, spawn.args, {
|
|
396
|
+
cwd,
|
|
397
|
+
encoding: 'utf8',
|
|
398
|
+
timeout: command.timeoutMs || DEFAULT_TIMEOUT_MS,
|
|
399
|
+
maxBuffer: command.outputLimitBytes || DEFAULT_OUTPUT_LIMIT_BYTES,
|
|
400
|
+
env: { ...process.env, CI: process.env.CI || '1', ...(command.env || {}) },
|
|
401
|
+
windowsHide: true,
|
|
402
|
+
...(spawn.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}),
|
|
403
|
+
});
|
|
404
|
+
state.commandsRun?.push({
|
|
405
|
+
command: command.command,
|
|
406
|
+
args: command.args,
|
|
407
|
+
displayCommand: command.displayCommand,
|
|
408
|
+
category: command.category,
|
|
409
|
+
source: command.source,
|
|
410
|
+
cwd,
|
|
411
|
+
passed: true,
|
|
412
|
+
durationMs: Date.now() - startedAt,
|
|
413
|
+
exitCode: 0,
|
|
414
|
+
stdout: truncateOutput(result.stdout),
|
|
415
|
+
stderr: truncateOutput(result.stderr),
|
|
416
|
+
});
|
|
417
|
+
} catch (error: any) {
|
|
418
|
+
const exitCode = typeof error?.code === 'number' ? error.code : null;
|
|
419
|
+
state.status = 'failed';
|
|
420
|
+
state.exitCode = exitCode;
|
|
421
|
+
state.error = error?.message || String(error);
|
|
422
|
+
state.completedAt = new Date().toISOString();
|
|
423
|
+
state.commandsRun?.push({
|
|
424
|
+
command: command.command,
|
|
425
|
+
args: command.args,
|
|
426
|
+
displayCommand: command.displayCommand,
|
|
427
|
+
category: command.category,
|
|
428
|
+
source: command.source,
|
|
429
|
+
cwd,
|
|
430
|
+
passed: false,
|
|
431
|
+
durationMs: Date.now() - startedAt,
|
|
432
|
+
exitCode,
|
|
433
|
+
signal: typeof error?.signal === 'string' ? error.signal : null,
|
|
434
|
+
timedOut: error?.killed === true || /timed out/i.test(String(error?.message || '')),
|
|
435
|
+
stdout: truncateOutput(error?.stdout),
|
|
436
|
+
stderr: truncateOutput(error?.stderr || error?.message),
|
|
437
|
+
});
|
|
438
|
+
return state;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
state.status = 'ready';
|
|
442
|
+
state.exitCode = 0;
|
|
443
|
+
state.completedAt = new Date().toISOString();
|
|
444
|
+
// M2-1: record staleInputs hashes so evaluateWorktreeBootstrapState can
|
|
445
|
+
// invalidate this 'ready' when an input (e.g. lockfile) changes later.
|
|
446
|
+
if (staleInputPaths.length > 0) {
|
|
447
|
+
state.staleInputsDigest = computeStaleInputsDigest(workspace, staleInputPaths);
|
|
448
|
+
}
|
|
449
|
+
return state;
|
|
450
|
+
}
|
|
@@ -51,7 +51,9 @@ import { normalizeContent, flattenContent, normalizeInputEnvelope } from './cont
|
|
|
51
51
|
import { assertProviderSupportsDeclaredInput, getEffectiveMessageInputSupport } from './provider-input-support.js';
|
|
52
52
|
import type { ProviderInstance, ProviderState, AcpProviderState, ProviderErrorReason, ProviderEvent, InstanceContext, SessionModalState } from './provider-instance.js';
|
|
53
53
|
import { StatusMonitor } from './status-monitor.js';
|
|
54
|
+
import { ManualAttendanceTracker } from './manual-attendance.js';
|
|
54
55
|
import { buildLegacyModelModeSummaryMetadata } from './summary-metadata.js';
|
|
56
|
+
import { workingDirBasename } from './working-dir.js';
|
|
55
57
|
import {
|
|
56
58
|
buildAssistantChatMessage,
|
|
57
59
|
buildChatMessage,
|
|
@@ -287,6 +289,8 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
287
289
|
private partialBlocks: ContentBlock[] = [];
|
|
288
290
|
/** Tool calls collected during current turn */
|
|
289
291
|
private turnToolCalls: ToolCallInfo[] = [];
|
|
292
|
+
/** Guard: prevent concurrent sendPrompt calls from racing on shared state */
|
|
293
|
+
private _sendPromptInFlight = false;
|
|
290
294
|
|
|
291
295
|
// Error tracking
|
|
292
296
|
private errorMessage: string | null = null;
|
|
@@ -326,8 +330,8 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
326
330
|
this.settings = context.settings || {};
|
|
327
331
|
this.monitor.updateConfig({
|
|
328
332
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
329
|
-
|
|
330
|
-
|
|
333
|
+
noProgressAlert: (this.settings.noProgressAlert ?? this.settings.longGeneratingAlert) !== false,
|
|
334
|
+
noProgressThresholdSec: this.settings.noProgressThresholdSec ?? this.settings.longGeneratingThresholdSec ?? 180,
|
|
331
335
|
});
|
|
332
336
|
|
|
333
337
|
await this.spawnAgent();
|
|
@@ -343,7 +347,7 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
343
347
|
}
|
|
344
348
|
|
|
345
349
|
getSessionModalState(): SessionModalState {
|
|
346
|
-
const dirName = this.workingDir
|
|
350
|
+
const dirName = workingDirBasename(this.workingDir);
|
|
347
351
|
return {
|
|
348
352
|
id: this.instanceId,
|
|
349
353
|
status: this.currentStatus,
|
|
@@ -356,7 +360,7 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
356
360
|
}
|
|
357
361
|
|
|
358
362
|
getState(): AcpProviderState {
|
|
359
|
-
const dirName = this.workingDir
|
|
363
|
+
const dirName = workingDirBasename(this.workingDir);
|
|
360
364
|
|
|
361
365
|
const recentMessages = normalizeChatMessages(this.messages.map(m => {
|
|
362
366
|
const content = m.content;
|
|
@@ -671,8 +675,8 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
671
675
|
this.settings = { ...this.settings, ...newSettings };
|
|
672
676
|
this.monitor.updateConfig({
|
|
673
677
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
674
|
-
|
|
675
|
-
|
|
678
|
+
noProgressAlert: (this.settings.noProgressAlert ?? this.settings.longGeneratingAlert) !== false,
|
|
679
|
+
noProgressThresholdSec: this.settings.noProgressThresholdSec ?? this.settings.longGeneratingThresholdSec ?? 180,
|
|
676
680
|
});
|
|
677
681
|
this.log.info(`[${this.type}] Settings updated: ${Object.keys(newSettings).join(', ')}`);
|
|
678
682
|
}
|
|
@@ -842,7 +846,12 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
842
846
|
}
|
|
843
847
|
|
|
844
848
|
// ─── Auto-approve: skip user confirmation ───
|
|
845
|
-
|
|
849
|
+
// Held while a human is actively attending this session (manual
|
|
850
|
+
// attendance) so they can decide the permission themselves; falls
|
|
851
|
+
// through to the waiting_approval manual path below. A background
|
|
852
|
+
// worker is never attended, so its delegated auto-approve fires
|
|
853
|
+
// as before.
|
|
854
|
+
if (this.settings.autoApprove !== false && !this.manualAttendance.isAttended()) {
|
|
846
855
|
const toolTitle = tc.title || tc.toolCallId || 'tool call';
|
|
847
856
|
this.log.info(`[${this.type}] Auto-approving: ${toolTitle}`);
|
|
848
857
|
this.appendSystemMessage(`Auto-approved: ${toolTitle}`);
|
|
@@ -1002,7 +1011,11 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1002
1011
|
}
|
|
1003
1012
|
} catch (e: any) {
|
|
1004
1013
|
this.log.warn(`[${this.type}] session/new failed: ${e?.message}`);
|
|
1005
|
-
this.
|
|
1014
|
+
if (!this.errorReason) {
|
|
1015
|
+
this.errorReason = 'init_failed';
|
|
1016
|
+
this.errorMessage = `ACP session creation failed: ${e?.message}`;
|
|
1017
|
+
}
|
|
1018
|
+
this.currentStatus = 'error';
|
|
1006
1019
|
}
|
|
1007
1020
|
}
|
|
1008
1021
|
|
|
@@ -1012,6 +1025,12 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1012
1025
|
return;
|
|
1013
1026
|
}
|
|
1014
1027
|
|
|
1028
|
+
if (this._sendPromptInFlight) {
|
|
1029
|
+
this.log.warn(`[${this.type}] sendPrompt already in flight — dropping concurrent request`);
|
|
1030
|
+
throw new Error('ACP sendPrompt already in flight');
|
|
1031
|
+
}
|
|
1032
|
+
this._sendPromptInFlight = true;
|
|
1033
|
+
|
|
1015
1034
|
// Build prompt content
|
|
1016
1035
|
const promptParts: any[] = contentBlocks && contentBlocks.length > 0
|
|
1017
1036
|
? contentBlocks.map((b) => {
|
|
@@ -1098,6 +1117,8 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1098
1117
|
this.finalizeAssistantMessage();
|
|
1099
1118
|
this.currentStatus = 'idle';
|
|
1100
1119
|
this.detectStatusTransition();
|
|
1120
|
+
} finally {
|
|
1121
|
+
this._sendPromptInFlight = false;
|
|
1101
1122
|
}
|
|
1102
1123
|
}
|
|
1103
1124
|
|
|
@@ -1113,6 +1134,17 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1113
1134
|
|
|
1114
1135
|
private permissionResolvers: ((approved: boolean) => void)[] = [];
|
|
1115
1136
|
|
|
1137
|
+
// Provider-common manual-attendance signal: while a human is actively driving
|
|
1138
|
+
// this session from the dashboard, auto-approve holds so they can decide on
|
|
1139
|
+
// the permission request themselves. Background workers are never attended →
|
|
1140
|
+
// delegated auto-approve is unaffected.
|
|
1141
|
+
private readonly manualAttendance = new ManualAttendanceTracker();
|
|
1142
|
+
|
|
1143
|
+
/** @see ProviderInstance.noteManualInteraction */
|
|
1144
|
+
noteManualInteraction(now = Date.now()): void {
|
|
1145
|
+
this.manualAttendance.note(now);
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1116
1148
|
async resolvePermission(approved: boolean): Promise<void> {
|
|
1117
1149
|
const resolver = this.permissionResolvers.shift();
|
|
1118
1150
|
if (resolver) {
|
|
@@ -1490,7 +1522,7 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1490
1522
|
private detectStatusTransition(): void {
|
|
1491
1523
|
const now = Date.now();
|
|
1492
1524
|
const newStatus = this.currentStatus;
|
|
1493
|
-
const dirName = this.workingDir
|
|
1525
|
+
const dirName = workingDirBasename(this.workingDir);
|
|
1494
1526
|
const chatTitle = `${this.provider.name} · ${dirName}`;
|
|
1495
1527
|
const progressFingerprint = newStatus === 'generating'
|
|
1496
1528
|
? `${this.partialContent}::${JSON.stringify(this.partialBlocks)}::${JSON.stringify(this.activeToolCalls.map(t => ({ name: t.name, status: t.status })))}`.slice(-2000)
|
|
@@ -1518,7 +1550,8 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1518
1550
|
|
|
1519
1551
|
// Monitor check
|
|
1520
1552
|
const agentKey = `${this.type}:acp`;
|
|
1521
|
-
const
|
|
1553
|
+
const approvalPending = newStatus === 'waiting_approval';
|
|
1554
|
+
const monitorEvents = this.monitor.check(agentKey, newStatus, now, progressFingerprint, approvalPending);
|
|
1522
1555
|
for (const me of monitorEvents) {
|
|
1523
1556
|
this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
1524
1557
|
}
|
|
@@ -4,4 +4,9 @@ export declare function pickApprovalButton(buttons: string[] | null | undefined,
|
|
|
4
4
|
index: number;
|
|
5
5
|
label: string;
|
|
6
6
|
};
|
|
7
|
+
export declare function pickAutoApprovalButton(buttons: string[] | null | undefined): {
|
|
8
|
+
index: number;
|
|
9
|
+
label: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function hasNegativeApprovalOption(buttons: string[] | null | undefined): boolean;
|
|
7
12
|
export declare function formatAutoApprovalMessage(modalMessage?: string, buttonLabel?: string): string;
|