@adhdev/daemon-core 0.9.82-rc.49 → 0.9.82-rc.490
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 +65 -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 +53532 -19073
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +53283 -18989
- 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 +1268 -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,695 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* M3: Mission persistence (minimal form).
|
|
3
|
+
*
|
|
4
|
+
* A mission is a persistent record of a multi-task goal so the plan lives in
|
|
5
|
+
* the system rather than in the coordinator LLM's context. Coordinator
|
|
6
|
+
* sessions can die or compact; a new coordinator reads the mission back at
|
|
7
|
+
* launch and continues.
|
|
8
|
+
*
|
|
9
|
+
* Explicit non-goals (see docs/mesh-product-plan-v2.md Phase M3): this is not
|
|
10
|
+
* a workflow engine and there is no automatic takeover daemon. Progress is
|
|
11
|
+
* never stored — it is derived from queue task statuses (mission_id) at
|
|
12
|
+
* query time.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { randomUUID } from 'crypto';
|
|
16
|
+
import { LOG } from '../logging/logger.js';
|
|
17
|
+
import { MeshRuntimeStore } from './mesh-runtime-store.js';
|
|
18
|
+
import { getQueue } from './mesh-work-queue.js';
|
|
19
|
+
import { computeMeshMissionStats, type MeshMissionStats } from './mesh-task-stats.js';
|
|
20
|
+
import { appendLedgerEntry } from './mesh-ledger.js';
|
|
21
|
+
import { queuePendingMeshCoordinatorEvent } from './mesh-events-pending.js';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Max chars of mission goal text written into a ledger entry payload. Mission
|
|
25
|
+
* goals can be hundreds–thousands of chars; the ledger is an append-only audit
|
|
26
|
+
* stream, so we store a bounded summary (+ a length/truncated flag) rather than
|
|
27
|
+
* the full text to keep the ledger from bloating on repeated goal rewrites.
|
|
28
|
+
*/
|
|
29
|
+
const LEDGER_GOAL_SUMMARY_MAX = 200;
|
|
30
|
+
|
|
31
|
+
function summarizeGoalForLedger(goal: string): string {
|
|
32
|
+
return goal.length > LEDGER_GOAL_SUMMARY_MAX ? goal.slice(0, LEDGER_GOAL_SUMMARY_MAX) : goal;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type MeshMissionStatus = 'active' | 'paused' | 'completed' | 'abandoned';
|
|
36
|
+
|
|
37
|
+
export const MESH_MISSION_STATUSES: MeshMissionStatus[] = ['active', 'paused', 'completed', 'abandoned'];
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Provenance of a mission. `magi` marks an inline mission auto-created by a
|
|
41
|
+
* mesh_magi_review fan-out (one per cross-verification run). `coordinator` (the
|
|
42
|
+
* default semantic for an unstamped/legacy mission) marks a coordinator- or
|
|
43
|
+
* user-authored mission. Used to bound the accumulation of completed MAGI missions
|
|
44
|
+
* out of the default mesh_mission_list surface — see listMeshMissionSummaries.
|
|
45
|
+
*/
|
|
46
|
+
export type MeshMissionSource = 'magi' | 'coordinator';
|
|
47
|
+
|
|
48
|
+
export interface MeshMissionRecord {
|
|
49
|
+
id: string;
|
|
50
|
+
meshId: string;
|
|
51
|
+
title: string;
|
|
52
|
+
goal: string;
|
|
53
|
+
status: MeshMissionStatus;
|
|
54
|
+
/**
|
|
55
|
+
* Optional provenance tag. Absent on missions created before this field existed
|
|
56
|
+
* and on coordinator/user missions that don't bother stamping it — both are
|
|
57
|
+
* treated as coordinator missions (never auto-hidden). Only explicit `magi`
|
|
58
|
+
* missions are bounded out of the default list once completed.
|
|
59
|
+
*/
|
|
60
|
+
source?: MeshMissionSource;
|
|
61
|
+
/**
|
|
62
|
+
* G3: idempotency marker for the mission_close_candidate nudge. ISO timestamp of
|
|
63
|
+
* the last emit; absent/undefined when the mission has not (or no longer) been in a
|
|
64
|
+
* fully-terminal state. Owned by maybeEmitMissionCloseCandidate — never set by a
|
|
65
|
+
* regular upsert. See summarizeMissionTasks / maybeEmitMissionCloseCandidate.
|
|
66
|
+
*/
|
|
67
|
+
closeCandidateEmittedAt?: string;
|
|
68
|
+
createdAt: string;
|
|
69
|
+
updatedAt: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface MeshMissionTaskAggregate {
|
|
73
|
+
total: number;
|
|
74
|
+
pending: number;
|
|
75
|
+
assigned: number;
|
|
76
|
+
completed: number;
|
|
77
|
+
failed: number;
|
|
78
|
+
cancelled: number;
|
|
79
|
+
/** Pending tasks held back by a dependency failure (blockedReason set). */
|
|
80
|
+
blocked: number;
|
|
81
|
+
/** Latest updatedAt across the mission's tasks, or null with no tasks. */
|
|
82
|
+
lastActivityAt: string | null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface MeshMissionSummary extends MeshMissionRecord {
|
|
86
|
+
tasks: MeshMissionTaskAggregate;
|
|
87
|
+
/**
|
|
88
|
+
* Operational rollup (durations / attempts) derived from the ledger via
|
|
89
|
+
* computeMeshMissionStats. Optional: only populated by surfaces that opt in
|
|
90
|
+
* (e.g. mesh_status), since the rollup scans a bounded ledger tail per
|
|
91
|
+
* mission. Absent on the lightweight task-aggregate-only summaries.
|
|
92
|
+
*/
|
|
93
|
+
stats?: MeshMissionStats;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Slim mission summary for the mesh_status compact (default) surface. Drops the
|
|
98
|
+
* full `goal` text — which can be hundreds of chars per mission and is repeated
|
|
99
|
+
* for every mission on every status call — keeping only a short preview plus a
|
|
100
|
+
* `goalTruncated` flag when the original was longer. The stored goal is never
|
|
101
|
+
* mutated; this is an output-only projection. Coordinators that need the full
|
|
102
|
+
* goal call mesh_status with verbose=true, or read the mission directly via
|
|
103
|
+
* mesh_mission_upsert / getMeshMission.
|
|
104
|
+
*/
|
|
105
|
+
export interface MeshMissionSlimSummary extends Omit<MeshMissionSummary, 'goal'> {
|
|
106
|
+
/** Short preview of the goal (≤ GOAL_PREVIEW_MAX chars), '' when goal empty. */
|
|
107
|
+
goalPreview: string;
|
|
108
|
+
/** True when the stored goal was longer than the preview (full text elided). */
|
|
109
|
+
goalTruncated: boolean;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Max chars of goal text retained in the slim (compact) mission summary. */
|
|
113
|
+
export const GOAL_PREVIEW_MAX = 120;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Shorter goal preview used by the mesh_status compact (LLM coordinator) surface.
|
|
117
|
+
* The coordinator only needs to recognize a mission, not read its full goal, and
|
|
118
|
+
* mesh_status repeats every live mission on every poll — so the status preview is
|
|
119
|
+
* tighter than the dashboard / mesh_mission_list preview (GOAL_PREVIEW_MAX).
|
|
120
|
+
*/
|
|
121
|
+
export const COMPACT_STATUS_GOAL_PREVIEW_MAX = 80;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* mesh_mission_list default fold sizes. Without an explicit `statuses` filter the
|
|
125
|
+
* tool returns non-terminal (active/paused) missions in full detail but folds the
|
|
126
|
+
* completed/abandoned history into counts + a capped newest-first id list — a mesh
|
|
127
|
+
* can accumulate hundreds of terminal missions and returning them all (each with a
|
|
128
|
+
* ledger-scanned stats rollup) blew past the tool payload / token budget and spilled
|
|
129
|
+
* to a file. When an explicit `statuses` filter IS given, the matching missions are
|
|
130
|
+
* returned in detail but still bounded by MESH_MISSION_LIST_STATUS_LIMIT so a
|
|
131
|
+
* status:["completed"] call on a huge history stays bounded (overflow → truncated).
|
|
132
|
+
*/
|
|
133
|
+
export const MESH_MISSION_LIST_HISTORY_ID_LIMIT = 30;
|
|
134
|
+
export const MESH_MISSION_LIST_STATUS_LIMIT = 50;
|
|
135
|
+
|
|
136
|
+
function normalizeMissionStatus(value: unknown): MeshMissionStatus {
|
|
137
|
+
return MESH_MISSION_STATUSES.includes(value as MeshMissionStatus)
|
|
138
|
+
? value as MeshMissionStatus
|
|
139
|
+
: 'active';
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function normalizeMissionSource(value: unknown): MeshMissionSource | undefined {
|
|
143
|
+
return value === 'magi' || value === 'coordinator' ? value : undefined;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function upsertMeshMission(meshId: string, input: {
|
|
147
|
+
id?: string;
|
|
148
|
+
title: string;
|
|
149
|
+
goal?: string;
|
|
150
|
+
status?: string;
|
|
151
|
+
source?: MeshMissionSource;
|
|
152
|
+
}): MeshMissionRecord {
|
|
153
|
+
const title = typeof input.title === 'string' ? input.title.trim() : '';
|
|
154
|
+
if (!title) throw new Error('mission_title_required: a mission needs a non-empty title');
|
|
155
|
+
if (input.status !== undefined && !MESH_MISSION_STATUSES.includes(input.status as MeshMissionStatus)) {
|
|
156
|
+
throw new Error(`invalid_mission_status: '${input.status}' (valid: ${MESH_MISSION_STATUSES.join(', ')})`);
|
|
157
|
+
}
|
|
158
|
+
const id = typeof input.id === 'string' && input.id.trim() ? input.id.trim() : randomUUID();
|
|
159
|
+
const store = MeshRuntimeStore.getInstance();
|
|
160
|
+
const existing = store.getMission(meshId, id);
|
|
161
|
+
const prevStatus = existing ? normalizeMissionStatus(existing.status) : null;
|
|
162
|
+
const prevGoal = existing?.goal ?? '';
|
|
163
|
+
const record = {
|
|
164
|
+
id,
|
|
165
|
+
meshId,
|
|
166
|
+
title,
|
|
167
|
+
goal: typeof input.goal === 'string' ? input.goal : existing?.goal ?? '',
|
|
168
|
+
status: normalizeMissionStatus(input.status ?? existing?.status),
|
|
169
|
+
// source is write-once: only forwarded when the caller supplies one. The
|
|
170
|
+
// store COALESCEs it against the existing value, so a later status/goal
|
|
171
|
+
// upsert that omits source never clears a previously-stamped tag.
|
|
172
|
+
...(input.source ? { source: input.source } : {}),
|
|
173
|
+
};
|
|
174
|
+
store.upsertMission(record);
|
|
175
|
+
const saved = store.getMission(meshId, id)!;
|
|
176
|
+
const result: MeshMissionRecord = {
|
|
177
|
+
...saved,
|
|
178
|
+
status: normalizeMissionStatus(saved.status),
|
|
179
|
+
source: normalizeMissionSource(saved.source),
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// Mission audit trail: record this mutation in the mesh ledger so mission
|
|
183
|
+
// lifecycle (create, goal rewrite, status transition) is auditable alongside
|
|
184
|
+
// task events and survives a coordinator restart. Best-effort: a ledger
|
|
185
|
+
// failure must never break the primary mission write.
|
|
186
|
+
appendMissionLedgerEntries(meshId, {
|
|
187
|
+
isCreate: !existing,
|
|
188
|
+
record: result,
|
|
189
|
+
prevStatus,
|
|
190
|
+
prevGoal,
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Append the relevant ledger entries for a mission upsert. Emits at most one
|
|
198
|
+
* entry per distinct change:
|
|
199
|
+
* - new mission → mission_created
|
|
200
|
+
* - status differs from prior → mission_status_changed
|
|
201
|
+
* - goal text differs from prior → mission_goal_updated (no-op rewrites skipped)
|
|
202
|
+
*/
|
|
203
|
+
function appendMissionLedgerEntries(
|
|
204
|
+
meshId: string,
|
|
205
|
+
args: { isCreate: boolean; record: MeshMissionRecord; prevStatus: MeshMissionStatus | null; prevGoal: string },
|
|
206
|
+
): void {
|
|
207
|
+
const { isCreate, record, prevStatus, prevGoal } = args;
|
|
208
|
+
try {
|
|
209
|
+
if (isCreate) {
|
|
210
|
+
const goal = record.goal ?? '';
|
|
211
|
+
appendLedgerEntry(meshId, {
|
|
212
|
+
kind: 'mission_created',
|
|
213
|
+
payload: {
|
|
214
|
+
missionId: record.id,
|
|
215
|
+
title: record.title,
|
|
216
|
+
goalSummary: summarizeGoalForLedger(goal),
|
|
217
|
+
goalLength: goal.length,
|
|
218
|
+
goalTruncated: goal.length > LEDGER_GOAL_SUMMARY_MAX,
|
|
219
|
+
status: record.status,
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (prevStatus !== null && prevStatus !== record.status) {
|
|
225
|
+
appendLedgerEntry(meshId, {
|
|
226
|
+
kind: 'mission_status_changed',
|
|
227
|
+
payload: {
|
|
228
|
+
missionId: record.id,
|
|
229
|
+
title: record.title,
|
|
230
|
+
fromStatus: prevStatus,
|
|
231
|
+
toStatus: record.status,
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
const nextGoal = record.goal ?? '';
|
|
236
|
+
if (nextGoal !== prevGoal) {
|
|
237
|
+
appendLedgerEntry(meshId, {
|
|
238
|
+
kind: 'mission_goal_updated',
|
|
239
|
+
payload: {
|
|
240
|
+
missionId: record.id,
|
|
241
|
+
title: record.title,
|
|
242
|
+
prevGoalSummary: summarizeGoalForLedger(prevGoal),
|
|
243
|
+
nextGoalSummary: summarizeGoalForLedger(nextGoal),
|
|
244
|
+
prevGoalLength: prevGoal.length,
|
|
245
|
+
nextGoalLength: nextGoal.length,
|
|
246
|
+
goalTruncated: prevGoal.length > LEDGER_GOAL_SUMMARY_MAX || nextGoal.length > LEDGER_GOAL_SUMMARY_MAX,
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
} catch { /* audit trail is best-effort; never break the mission write */ }
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function getMeshMissions(meshId: string, statuses?: MeshMissionStatus[]): MeshMissionRecord[] {
|
|
254
|
+
return MeshRuntimeStore.getInstance().getMissions(meshId, statuses)
|
|
255
|
+
.map(m => ({ ...m, status: normalizeMissionStatus(m.status), source: normalizeMissionSource(m.source) }));
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function getMeshMission(meshId: string, missionId: string): MeshMissionRecord | null {
|
|
259
|
+
const record = MeshRuntimeStore.getInstance().getMission(meshId, missionId);
|
|
260
|
+
return record ? { ...record, status: normalizeMissionStatus(record.status), source: normalizeMissionSource(record.source) } : null;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** Aggregate task statuses for a mission at query time (no stored progress). */
|
|
264
|
+
export function summarizeMissionTasks(meshId: string, missionId: string): MeshMissionTaskAggregate {
|
|
265
|
+
const tasks = getQueue(meshId).filter(task => task.missionId === missionId);
|
|
266
|
+
const aggregate: MeshMissionTaskAggregate = {
|
|
267
|
+
total: tasks.length,
|
|
268
|
+
pending: 0,
|
|
269
|
+
assigned: 0,
|
|
270
|
+
completed: 0,
|
|
271
|
+
failed: 0,
|
|
272
|
+
cancelled: 0,
|
|
273
|
+
blocked: 0,
|
|
274
|
+
lastActivityAt: null,
|
|
275
|
+
};
|
|
276
|
+
for (const task of tasks) {
|
|
277
|
+
if (task.status === 'pending') aggregate.pending += 1;
|
|
278
|
+
else if (task.status === 'assigned') aggregate.assigned += 1;
|
|
279
|
+
else if (task.status === 'completed') aggregate.completed += 1;
|
|
280
|
+
else if (task.status === 'failed') aggregate.failed += 1;
|
|
281
|
+
else if (task.status === 'cancelled') aggregate.cancelled += 1;
|
|
282
|
+
if (task.status === 'pending' && task.blockedReason) aggregate.blocked += 1;
|
|
283
|
+
if (task.updatedAt && (!aggregate.lastActivityAt || task.updatedAt > aggregate.lastActivityAt)) {
|
|
284
|
+
aggregate.lastActivityAt = task.updatedAt;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return aggregate;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export function summarizeMeshMission(meshId: string, mission: MeshMissionRecord): MeshMissionSummary {
|
|
291
|
+
return { ...mission, tasks: summarizeMissionTasks(meshId, mission.id) };
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* G3 — all-tasks-terminal detection: true when a mission has at least one task and
|
|
296
|
+
* every task has reached a terminal status (no pending, no assigned). This is the
|
|
297
|
+
* derived signal (never a stored flag) that a mission has no more work in flight and
|
|
298
|
+
* is a candidate for the coordinator to close. A mission with zero tasks is NOT a
|
|
299
|
+
* candidate — an empty mission is a freshly-created plan, not a finished one.
|
|
300
|
+
*/
|
|
301
|
+
export function isMissionAllTasksTerminal(aggregate: MeshMissionTaskAggregate): boolean {
|
|
302
|
+
return aggregate.total > 0 && aggregate.pending === 0 && aggregate.assigned === 0;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* G3 (step ①) — emit a `mission_close_candidate` coordinator nudge the first time an
|
|
307
|
+
* ACTIVE mission's tasks all become terminal, and reset the idempotency marker when a
|
|
308
|
+
* mission leaves the terminal state. Call this after any task-status mutation that can
|
|
309
|
+
* change a mission's aggregate (completion / failure / cancel / dependency-failure /
|
|
310
|
+
* new task). Fire-and-forget and fully best-effort — a throw here must never break the
|
|
311
|
+
* task mutation that triggered it.
|
|
312
|
+
*
|
|
313
|
+
* Design invariants (docs/MESH_PROMPT_ARCH_REVIEW_2026-07.md §9-1 G3):
|
|
314
|
+
* - NEVER transitions the mission status. This only publishes a "consider closing"
|
|
315
|
+
* hint; the coordinator/human decides via mesh_mission_upsert.
|
|
316
|
+
* - Idempotent per all-terminal EDGE. The mission's close_candidate_emitted_at marker
|
|
317
|
+
* guarantees exactly one emit per terminal transition; while the mission stays
|
|
318
|
+
* all-terminal, subsequent calls no-op (no per-tick spam). When the mission returns
|
|
319
|
+
* to non-terminal (a new/re-opened task), the marker is cleared so a later
|
|
320
|
+
* re-completion nudges again.
|
|
321
|
+
* - Only ACTIVE missions nudge. A paused/completed/abandoned mission is never a
|
|
322
|
+
* close candidate (already decided, or intentionally on hold).
|
|
323
|
+
*
|
|
324
|
+
* Returns true iff an event was emitted on this call.
|
|
325
|
+
*/
|
|
326
|
+
export function maybeEmitMissionCloseCandidate(meshId: string, missionId: string): boolean {
|
|
327
|
+
try {
|
|
328
|
+
const mission = getMeshMission(meshId, missionId);
|
|
329
|
+
if (!mission) return false;
|
|
330
|
+
const store = MeshRuntimeStore.getInstance();
|
|
331
|
+
const aggregate = summarizeMissionTasks(meshId, missionId);
|
|
332
|
+
const allTerminal = isMissionAllTasksTerminal(aggregate);
|
|
333
|
+
const alreadyEmitted = typeof mission.closeCandidateEmittedAt === 'string' && mission.closeCandidateEmittedAt.length > 0;
|
|
334
|
+
|
|
335
|
+
// Reset edge: mission is no longer all-terminal (new/re-opened task) but still
|
|
336
|
+
// carries a stale marker → clear it so a future re-completion can nudge again.
|
|
337
|
+
// Applies regardless of mission status (a re-opened completed mission also resets).
|
|
338
|
+
if (!allTerminal) {
|
|
339
|
+
if (alreadyEmitted) store.setMissionCloseCandidateEmittedAt(meshId, missionId, null);
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// All-terminal, but only an ACTIVE mission is a close candidate. A paused mission
|
|
344
|
+
// is intentionally on hold; a completed/abandoned one is already decided. We do
|
|
345
|
+
// NOT mark in these cases — if the mission is later reactivated while still
|
|
346
|
+
// all-terminal, it should nudge then.
|
|
347
|
+
if (mission.status !== 'active') return false;
|
|
348
|
+
|
|
349
|
+
// Idempotency: already nudged for this terminal edge → no-op (no per-tick spam).
|
|
350
|
+
if (alreadyEmitted) return false;
|
|
351
|
+
|
|
352
|
+
const emittedAt = new Date().toISOString();
|
|
353
|
+
emitMissionCloseCandidateEvent(meshId, mission, aggregate, emittedAt);
|
|
354
|
+
// Mark AFTER a successful emit path so a mid-emit throw leaves the marker unset
|
|
355
|
+
// and the next mutation retries rather than silently dropping the only nudge.
|
|
356
|
+
store.setMissionCloseCandidateEmittedAt(meshId, missionId, emittedAt);
|
|
357
|
+
return true;
|
|
358
|
+
} catch (e: any) {
|
|
359
|
+
LOG.warn('MeshMissions', `maybeEmitMissionCloseCandidate failed for mission ${missionId} on mesh ${meshId}: ${e?.message || e}`);
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Build and queue the mission_close_candidate pending coordinator event. Broadcast
|
|
366
|
+
* scope (defaultScopeForEvent → 'broadcast' since it is neither a terminal-task nor a
|
|
367
|
+
* system event), so it reaches any coordinator on the mesh without needing an
|
|
368
|
+
* intendedFor identity — a mission-hygiene hint is not tied to a single dispatcher.
|
|
369
|
+
*/
|
|
370
|
+
function emitMissionCloseCandidateEvent(
|
|
371
|
+
meshId: string,
|
|
372
|
+
mission: MeshMissionRecord,
|
|
373
|
+
aggregate: MeshMissionTaskAggregate,
|
|
374
|
+
emittedAt: string,
|
|
375
|
+
): void {
|
|
376
|
+
const coordinatorMessage =
|
|
377
|
+
`Mission "${mission.title}" (id: ${mission.id}) has no tasks left in flight — all ${aggregate.total} `
|
|
378
|
+
+ `task(s) are terminal (${aggregate.completed} completed, ${aggregate.failed} failed, ${aggregate.cancelled} cancelled). `
|
|
379
|
+
+ `It is a candidate to close. Review its outcome and, if done, set its status with `
|
|
380
|
+
+ `mesh_mission_upsert(mission_id: "${mission.id}", status: "completed" | "abandoned"). `
|
|
381
|
+
+ `This is only a hint — the mission stays 'active' until you decide.`;
|
|
382
|
+
queuePendingMeshCoordinatorEvent({
|
|
383
|
+
event: 'mission_close_candidate',
|
|
384
|
+
meshId,
|
|
385
|
+
nodeLabel: '',
|
|
386
|
+
metadataEvent: {
|
|
387
|
+
missionId: mission.id,
|
|
388
|
+
title: mission.title,
|
|
389
|
+
status: mission.status,
|
|
390
|
+
aggregate: {
|
|
391
|
+
total: aggregate.total,
|
|
392
|
+
completed: aggregate.completed,
|
|
393
|
+
failed: aggregate.failed,
|
|
394
|
+
cancelled: aggregate.cancelled,
|
|
395
|
+
},
|
|
396
|
+
lastActivityAt: aggregate.lastActivityAt,
|
|
397
|
+
emittedAt,
|
|
398
|
+
},
|
|
399
|
+
coordinatorMessage,
|
|
400
|
+
queuedAt: Date.parse(emittedAt) || 0,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/** Active mission summaries for mesh_status / coordinator prompt injection. */
|
|
405
|
+
export function getActiveMeshMissionSummaries(meshId: string): MeshMissionSummary[] {
|
|
406
|
+
return getMeshMissions(meshId, ['active']).map(mission => summarizeMeshMission(meshId, mission));
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/** Project a full mission summary down to the slim (goal-elided) shape. */
|
|
410
|
+
function slimMissionSummary(summary: MeshMissionSummary, previewMax: number = GOAL_PREVIEW_MAX): MeshMissionSlimSummary {
|
|
411
|
+
const goal = typeof summary.goal === 'string' ? summary.goal : '';
|
|
412
|
+
const goalTruncated = goal.length > previewMax;
|
|
413
|
+
const { goal: _omitGoal, ...rest } = summary;
|
|
414
|
+
return {
|
|
415
|
+
...rest,
|
|
416
|
+
goalPreview: goalTruncated ? goal.slice(0, previewMax) : goal,
|
|
417
|
+
goalTruncated,
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Mission summaries for the mesh_status dashboard surface: every active/paused
|
|
423
|
+
* mission plus a capped, newest-first slice of completed/abandoned history so
|
|
424
|
+
* the dashboard can render a collapsible "history" section without unbounded
|
|
425
|
+
* payload growth. Returned newest-first within each group (active/paused first,
|
|
426
|
+
* then history), so the frontend can split on `status` directly.
|
|
427
|
+
*
|
|
428
|
+
* Compact mode (the default) elides each mission's full `goal` text — which is
|
|
429
|
+
* repeated verbatim on every status poll and dominates the payload when a mesh
|
|
430
|
+
* has many missions — returning only a short `goalPreview` + `goalTruncated`
|
|
431
|
+
* flag. Pass `verbose: true` to get the full `goal` text per mission. The stored
|
|
432
|
+
* goal is untouched in both modes; this is an output-only projection.
|
|
433
|
+
*/
|
|
434
|
+
export function getMeshStatusMissionSummaries(
|
|
435
|
+
meshId: string,
|
|
436
|
+
options?: { historyLimit?: number; verbose?: boolean; withStats?: boolean },
|
|
437
|
+
): MeshMissionSummary[] | MeshMissionSlimSummary[] {
|
|
438
|
+
const historyLimit = Math.max(0, options?.historyLimit ?? 10);
|
|
439
|
+
const all = getMeshMissions(meshId);
|
|
440
|
+
const live = all.filter(m => m.status === 'active' || m.status === 'paused');
|
|
441
|
+
const history = all
|
|
442
|
+
.filter(m => m.status === 'completed' || m.status === 'abandoned')
|
|
443
|
+
.sort((a, b) => (b.updatedAt || '').localeCompare(a.updatedAt || ''))
|
|
444
|
+
.slice(0, historyLimit);
|
|
445
|
+
let full = [...live, ...history].map(mission => summarizeMeshMission(meshId, mission));
|
|
446
|
+
// Operational stats (durations / attempts) are an opt-in projection: each
|
|
447
|
+
// mission's rollup scans a bounded ledger tail, so we only compute it for
|
|
448
|
+
// the bounded set we are about to return (live + capped history), not for
|
|
449
|
+
// every mission in the mesh. The dashboard graph opts in so mission detail
|
|
450
|
+
// can show wall-clock / retries without a second round trip.
|
|
451
|
+
if (options?.withStats) {
|
|
452
|
+
full = full.map(summary => ({ ...summary, stats: computeMeshMissionStats(meshId, summary.id) }));
|
|
453
|
+
}
|
|
454
|
+
return options?.verbose ? full : full.map(summary => slimMissionSummary(summary));
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/** Folded completed/abandoned history for the mesh_status compact surface. */
|
|
458
|
+
export interface MeshStatusMissionsHistoryFold {
|
|
459
|
+
/** Total completed + abandoned missions. */
|
|
460
|
+
count: number;
|
|
461
|
+
/** Count by lifecycle status (e.g. { completed, abandoned }). */
|
|
462
|
+
byStatus: Record<string, number>;
|
|
463
|
+
/** Newest-first id list (capped) so each folded mission stays addressable. */
|
|
464
|
+
missionIds: string[];
|
|
465
|
+
note: string;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/** Compact mesh_status mission projection: live detail + folded history. */
|
|
469
|
+
export interface MeshStatusMissionsCompact {
|
|
470
|
+
/**
|
|
471
|
+
* Active + paused missions, goal-elided to COMPACT_STATUS_GOAL_PREVIEW_MAX and
|
|
472
|
+
* WITHOUT the operational `stats` rollup — the `tasks` aggregate already carries
|
|
473
|
+
* progress, and stats (durations/retries) is a verbose/dashboard concern.
|
|
474
|
+
*/
|
|
475
|
+
live: MeshMissionSlimSummary[];
|
|
476
|
+
/** Completed + abandoned missions folded to counts + ids; null when none. */
|
|
477
|
+
historyFold: MeshStatusMissionsHistoryFold | null;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Mission projection for the mesh_status COMPACT (LLM coordinator) surface.
|
|
482
|
+
*
|
|
483
|
+
* Unlike getMeshStatusMissionSummaries (which emits every live mission plus a
|
|
484
|
+
* capped slice of full-detail history, each carrying a stats rollup), this keeps
|
|
485
|
+
* per-mission detail ONLY for live (active/paused) missions and folds the whole
|
|
486
|
+
* completed/abandoned history into a counts + id-list summary. Combined with the
|
|
487
|
+
* tighter goal preview and dropped stats, this is what keeps the compact
|
|
488
|
+
* mesh_status payload bounded as a mesh accumulates missions — the missions
|
|
489
|
+
* section previously dominated the payload (full goalPreview + tasks + stats per
|
|
490
|
+
* mission, for every live mission and up to 10 history missions, on every poll).
|
|
491
|
+
*
|
|
492
|
+
* The stored missions are untouched; this is an output-only projection. Full
|
|
493
|
+
* mission detail (goal text + stats + history) stays available via
|
|
494
|
+
* mesh_status verbose=true or mesh_mission_list.
|
|
495
|
+
*/
|
|
496
|
+
export function getMeshStatusMissionsCompact(
|
|
497
|
+
meshId: string,
|
|
498
|
+
options?: { previewMax?: number; historyIdLimit?: number },
|
|
499
|
+
): MeshStatusMissionsCompact {
|
|
500
|
+
const previewMax = Math.max(0, options?.previewMax ?? COMPACT_STATUS_GOAL_PREVIEW_MAX);
|
|
501
|
+
const historyIdLimit = Math.max(0, options?.historyIdLimit ?? 20);
|
|
502
|
+
const all = getMeshMissions(meshId);
|
|
503
|
+
const live = all
|
|
504
|
+
.filter(m => m.status === 'active' || m.status === 'paused')
|
|
505
|
+
.map(mission => slimMissionSummary(summarizeMeshMission(meshId, mission), previewMax));
|
|
506
|
+
const history = all
|
|
507
|
+
.filter(m => m.status === 'completed' || m.status === 'abandoned')
|
|
508
|
+
.sort((a, b) => (b.updatedAt || '').localeCompare(a.updatedAt || ''));
|
|
509
|
+
let historyFold: MeshStatusMissionsHistoryFold | null = null;
|
|
510
|
+
if (history.length > 0) {
|
|
511
|
+
const byStatus: Record<string, number> = {};
|
|
512
|
+
for (const m of history) byStatus[m.status] = (byStatus[m.status] ?? 0) + 1;
|
|
513
|
+
historyFold = {
|
|
514
|
+
count: history.length,
|
|
515
|
+
byStatus,
|
|
516
|
+
missionIds: history.slice(0, historyIdLimit).map(m => m.id),
|
|
517
|
+
note: 'Completed/abandoned missions are folded to counts + ids in compact mesh_status. Use mesh_mission_list or mesh_status verbose=true for their goal/task detail.',
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
return { live, historyFold };
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Read-only mission listing for the mesh_mission_list tool. Returns summaries
|
|
525
|
+
* (record + live task aggregate) for missions matching `statuses` — or every
|
|
526
|
+
* mission when `statuses` is omitted/empty — newest-first by updatedAt. Unlike
|
|
527
|
+
* getMeshStatusMissionSummaries this does NOT cap or group by lifecycle, so a
|
|
528
|
+
* coordinator can deliberately surface paused/abandoned/completed missions that
|
|
529
|
+
* the live status view would hide or truncate.
|
|
530
|
+
*
|
|
531
|
+
* MAGI bounding: by default this EXCLUDES completed MAGI missions (source==='magi'
|
|
532
|
+
* && status==='completed') — a mesh_magi_review fan-out auto-creates one inline
|
|
533
|
+
* mission per run and auto-closes it on collection, so without this they accumulate
|
|
534
|
+
* unbounded and drown out coordinator missions in the list. In-progress MAGI missions
|
|
535
|
+
* (active/paused) are still shown so a running cross-verification stays visible. Pass
|
|
536
|
+
* `includeMagi: true` to return every mission including completed MAGI ones. A mission
|
|
537
|
+
* with no `source` (legacy / coordinator) is never affected.
|
|
538
|
+
*
|
|
539
|
+
* Compact (the default) elides each goal to a capped preview + goalTruncated
|
|
540
|
+
* flag; verbose returns the full goal text. The stored goal is never mutated.
|
|
541
|
+
*/
|
|
542
|
+
export function listMeshMissionSummaries(
|
|
543
|
+
meshId: string,
|
|
544
|
+
options?: { statuses?: MeshMissionStatus[]; verbose?: boolean; includeMagi?: boolean },
|
|
545
|
+
): MeshMissionSummary[] | MeshMissionSlimSummary[] {
|
|
546
|
+
const statuses = options?.statuses && options.statuses.length > 0 ? options.statuses : undefined;
|
|
547
|
+
const includeMagi = options?.includeMagi === true;
|
|
548
|
+
const missions = getMeshMissions(meshId, statuses)
|
|
549
|
+
// Bound completed-MAGI accumulation by default. Only a mission EXPLICITLY
|
|
550
|
+
// tagged source==='magi' AND completed is hidden — coordinator/legacy
|
|
551
|
+
// (source undefined) missions and in-progress MAGI missions always pass.
|
|
552
|
+
.filter(m => includeMagi || !(m.source === 'magi' && m.status === 'completed'))
|
|
553
|
+
.sort((a, b) => (b.updatedAt || '').localeCompare(a.updatedAt || ''));
|
|
554
|
+
const full = missions.map(mission => summarizeMeshMission(meshId, mission));
|
|
555
|
+
return options?.verbose ? full : full.map(summary => slimMissionSummary(summary));
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/** Shaped mesh_mission_list result: bounded detail list + optional folded history. */
|
|
559
|
+
export interface MeshMissionListResult {
|
|
560
|
+
/** Detailed (slim or verbose) mission summaries — bounded, newest-first. */
|
|
561
|
+
missions: MeshMissionSummary[] | MeshMissionSlimSummary[];
|
|
562
|
+
/**
|
|
563
|
+
* Completed/abandoned missions folded to counts + ids. Present (default path)
|
|
564
|
+
* when no explicit status filter is given and terminal missions exist. Null when
|
|
565
|
+
* an explicit status filter is active (those missions go into `missions`).
|
|
566
|
+
*/
|
|
567
|
+
historyFold: MeshStatusMissionsHistoryFold | null;
|
|
568
|
+
/** True when an explicit status filter matched more than `limit` missions. */
|
|
569
|
+
truncated: boolean;
|
|
570
|
+
/** Total missions matching the query BEFORE the detail-list cap was applied. */
|
|
571
|
+
matched: number;
|
|
572
|
+
/** Newest-first ids of missions dropped by the detail-list cap (truncated path). */
|
|
573
|
+
overflowIds?: string[];
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* mesh_mission_list projection: payload-bounded regardless of mesh mission count.
|
|
578
|
+
*
|
|
579
|
+
* Default (no explicit `statuses`): non-terminal missions (active/paused) return in
|
|
580
|
+
* detail; completed/abandoned missions are folded to counts + a capped id list
|
|
581
|
+
* (historyFold), NOT emitted one-by-one. This is what keeps the tool from returning
|
|
582
|
+
* hundreds of terminal missions (each with a ledger stats rollup) and overflowing the
|
|
583
|
+
* token budget.
|
|
584
|
+
*
|
|
585
|
+
* Explicit `statuses` (e.g. ["completed"]): the coordinator asked to see those
|
|
586
|
+
* missions, so they ARE returned in detail — but still bounded by `limit` (default
|
|
587
|
+
* MESH_MISSION_LIST_STATUS_LIMIT). Overflow beyond `limit` is reported via
|
|
588
|
+
* truncated:true + overflowIds rather than silently dropped.
|
|
589
|
+
*
|
|
590
|
+
* MAGI + verbose semantics match listMeshMissionSummaries. `withStats` opts each
|
|
591
|
+
* detailed mission into the ledger-scanned stats rollup (off by default — the tasks
|
|
592
|
+
* aggregate is enough for a list view).
|
|
593
|
+
*/
|
|
594
|
+
export function listMeshMissionsForTool(
|
|
595
|
+
meshId: string,
|
|
596
|
+
options?: {
|
|
597
|
+
statuses?: MeshMissionStatus[];
|
|
598
|
+
verbose?: boolean;
|
|
599
|
+
includeMagi?: boolean;
|
|
600
|
+
withStats?: boolean;
|
|
601
|
+
limit?: number;
|
|
602
|
+
historyIdLimit?: number;
|
|
603
|
+
},
|
|
604
|
+
): MeshMissionListResult {
|
|
605
|
+
const explicitStatuses = options?.statuses && options.statuses.length > 0 ? options.statuses : undefined;
|
|
606
|
+
const includeMagi = options?.includeMagi === true;
|
|
607
|
+
const verbose = options?.verbose === true;
|
|
608
|
+
const withStats = options?.withStats === true;
|
|
609
|
+
const limit = Math.max(1, options?.limit ?? MESH_MISSION_LIST_STATUS_LIMIT);
|
|
610
|
+
const historyIdLimit = Math.max(0, options?.historyIdLimit ?? MESH_MISSION_LIST_HISTORY_ID_LIMIT);
|
|
611
|
+
|
|
612
|
+
const passesMagi = (m: MeshMissionRecord) => includeMagi || !(m.source === 'magi' && m.status === 'completed');
|
|
613
|
+
const byUpdatedDesc = (a: MeshMissionRecord, b: MeshMissionRecord) => (b.updatedAt || '').localeCompare(a.updatedAt || '');
|
|
614
|
+
|
|
615
|
+
const project = (mission: MeshMissionRecord): MeshMissionSummary | MeshMissionSlimSummary => {
|
|
616
|
+
let summary = summarizeMeshMission(meshId, mission);
|
|
617
|
+
if (withStats) {
|
|
618
|
+
try {
|
|
619
|
+
summary = { ...summary, stats: computeMeshMissionStats(meshId, mission.id) };
|
|
620
|
+
} catch { /* stats optional — omit on failure */ }
|
|
621
|
+
}
|
|
622
|
+
return verbose ? summary : slimMissionSummary(summary);
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
const foldHistory = (history: MeshMissionRecord[]): MeshStatusMissionsHistoryFold | null => {
|
|
626
|
+
if (history.length === 0) return null;
|
|
627
|
+
const byStatus: Record<string, number> = {};
|
|
628
|
+
for (const m of history) byStatus[m.status] = (byStatus[m.status] ?? 0) + 1;
|
|
629
|
+
return {
|
|
630
|
+
count: history.length,
|
|
631
|
+
byStatus,
|
|
632
|
+
missionIds: history.slice(0, historyIdLimit).map(m => m.id),
|
|
633
|
+
note: 'Completed/abandoned missions are folded to counts + ids. Pass status (e.g. status:["completed"]) to list them in detail.',
|
|
634
|
+
};
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
if (explicitStatuses) {
|
|
638
|
+
// Explicit filter: return matching missions in detail, capped at `limit`.
|
|
639
|
+
const matched = getMeshMissions(meshId, explicitStatuses)
|
|
640
|
+
.filter(passesMagi)
|
|
641
|
+
.sort(byUpdatedDesc);
|
|
642
|
+
const shown = matched.slice(0, limit);
|
|
643
|
+
const overflow = matched.slice(limit);
|
|
644
|
+
return {
|
|
645
|
+
missions: shown.map(project) as MeshMissionSummary[] | MeshMissionSlimSummary[],
|
|
646
|
+
historyFold: null,
|
|
647
|
+
truncated: overflow.length > 0,
|
|
648
|
+
matched: matched.length,
|
|
649
|
+
...(overflow.length > 0 ? { overflowIds: overflow.map(m => m.id) } : {}),
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// Default: detail for non-terminal missions, fold terminal history.
|
|
654
|
+
const all = getMeshMissions(meshId).filter(passesMagi);
|
|
655
|
+
const live = all
|
|
656
|
+
.filter(m => m.status === 'active' || m.status === 'paused')
|
|
657
|
+
.sort(byUpdatedDesc);
|
|
658
|
+
const history = all
|
|
659
|
+
.filter(m => m.status === 'completed' || m.status === 'abandoned')
|
|
660
|
+
.sort(byUpdatedDesc);
|
|
661
|
+
const shown = live.slice(0, limit);
|
|
662
|
+
const overflow = live.slice(limit);
|
|
663
|
+
return {
|
|
664
|
+
missions: shown.map(project) as MeshMissionSummary[] | MeshMissionSlimSummary[],
|
|
665
|
+
historyFold: foldHistory(history),
|
|
666
|
+
truncated: overflow.length > 0,
|
|
667
|
+
matched: live.length,
|
|
668
|
+
...(overflow.length > 0 ? { overflowIds: overflow.map(m => m.id) } : {}),
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* M3-3: render active missions as a prompt section for {{mission}}.
|
|
674
|
+
* Empty string when no active mission — the prompt stays byte-identical to
|
|
675
|
+
* the pre-M3 output in that case (regression guarantee).
|
|
676
|
+
*/
|
|
677
|
+
export function buildMissionPromptSection(meshId: string): string {
|
|
678
|
+
const summaries = getActiveMeshMissionSummaries(meshId);
|
|
679
|
+
if (summaries.length === 0) return '';
|
|
680
|
+
const lines: string[] = ['## Active Mission' + (summaries.length > 1 ? 's' : '')];
|
|
681
|
+
for (const mission of summaries) {
|
|
682
|
+
const t = mission.tasks;
|
|
683
|
+
lines.push(
|
|
684
|
+
`- **${mission.title}** (id: \`${mission.id}\`)`
|
|
685
|
+
+ (mission.goal ? `\n Goal: ${mission.goal}` : '')
|
|
686
|
+
+ `\n Tasks: ${t.total} total — ${t.pending} pending (${t.blocked} blocked), ${t.assigned} assigned, ${t.completed} completed, ${t.failed} failed, ${t.cancelled} cancelled`
|
|
687
|
+
+ (t.lastActivityAt ? `\n Last activity: ${t.lastActivityAt}` : ''),
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
lines.push(
|
|
691
|
+
'Continue this mission from its current task state. Do not re-enqueue tasks that already exist — check mesh_view_queue first. '
|
|
692
|
+
+ 'Update the mission with mesh_mission_upsert when its goal changes or it reaches a terminal state (completed/abandoned).',
|
|
693
|
+
);
|
|
694
|
+
return lines.join('\n');
|
|
695
|
+
}
|