@adhdev/daemon-core 0.9.82-rc.36 → 0.9.82-rc.360
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 +8 -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 +55 -2
- package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
- package/dist/cli-adapters/cli-state-engine.d.ts +198 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +116 -64
- package/dist/cli-adapters/provider-cli-parse.d.ts +4 -0
- package/dist/cli-adapters/provider-cli-runtime.d.ts +34 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +53 -0
- package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
- package/dist/cli-adapters/resolve-executable.d.ts +14 -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/cli-manager.d.ts +2 -1
- package/dist/commands/handler.d.ts +125 -0
- package/dist/commands/mesh-coordinator.d.ts +85 -1
- package/dist/commands/router.d.ts +336 -1
- 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 +77 -1
- 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 +23 -0
- package/dist/git/git-types.d.ts +2 -50
- package/dist/git/index.d.ts +2 -0
- package/dist/index.d.ts +54 -13
- package/dist/index.js +44143 -17595
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +43858 -17438
- 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 +46 -0
- package/dist/logging/logger.d.ts +1 -1
- package/dist/mesh/contracts.d.ts +164 -0
- package/dist/mesh/coordinator-prompt.d.ts +36 -0
- package/dist/mesh/coordinator-registry.d.ts +59 -0
- package/dist/mesh/mesh-active-work.d.ts +174 -0
- package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
- package/dist/mesh/mesh-event-trace.d.ts +21 -0
- package/dist/mesh/mesh-events-coordinator.d.ts +170 -0
- package/dist/mesh/mesh-events-pending.d.ts +55 -0
- package/dist/mesh/mesh-events-stale.d.ts +40 -0
- package/dist/mesh/mesh-events-utils.d.ts +62 -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 -3
- package/dist/mesh/mesh-ledger.d.ts +77 -1
- package/dist/mesh/mesh-missions.d.ts +164 -0
- package/dist/mesh/mesh-reconcile-loop.d.ts +7 -0
- package/dist/mesh/mesh-refine-batch.d.ts +68 -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 +429 -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-work-queue.d.ts +246 -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 +135 -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 +12 -0
- package/dist/providers/cli-provider-instance.d.ts +106 -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/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 +14 -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 +368 -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 +295 -13
- 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/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 +55 -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 +1 -0
- package/src/cli-adapter-types.ts +56 -2
- package/src/cli-adapters/cli-script-runner.ts +421 -0
- package/src/cli-adapters/cli-state-engine.ts +1215 -0
- package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +774 -1141
- package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
- package/src/cli-adapters/provider-cli-parse.ts +13 -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 +100 -11
- package/src/cli-adapters/pty-transport.ts +2 -1
- package/src/cli-adapters/raw-terminal-io.ts +252 -0
- package/src/cli-adapters/resolve-executable.ts +90 -0
- package/src/cli-adapters/session-host-transport.ts +2 -1
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +53 -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.ts +1823 -62
- package/src/commands/cli-manager.ts +336 -19
- package/src/commands/handler.ts +841 -2
- package/src/commands/mesh-coordinator.ts +332 -122
- package/src/commands/router.ts +7624 -1312
- 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 +388 -6
- package/src/config/recent-activity.ts +8 -2
- package/src/daemon/dev-auto-implement.ts +3 -2
- package/src/daemon/dev-cli-debug.ts +10 -1
- 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 +55 -14
- package/src/git/git-diff.ts +81 -11
- package/src/git/git-executor.ts +12 -0
- package/src/git/git-status.ts +574 -43
- package/src/git/git-types.ts +14 -62
- package/src/git/git-worktree.ts +8 -1
- package/src/git/index.ts +16 -0
- package/src/index.ts +156 -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 +220 -0
- package/src/logging/logger.ts +14 -7
- package/src/mesh/contracts.ts +329 -0
- package/src/mesh/coordinator-prompt.ts +234 -31
- package/src/mesh/coordinator-registry.ts +121 -0
- package/src/mesh/mesh-active-work.ts +667 -0
- package/src/mesh/mesh-delivery-policy.ts +315 -0
- package/src/mesh/mesh-event-trace.ts +67 -0
- package/src/mesh/mesh-events-coordinator.ts +2572 -0
- package/src/mesh/mesh-events-pending.ts +599 -0
- package/src/mesh/mesh-events-stale.ts +309 -0
- package/src/mesh/mesh-events-utils.ts +381 -0
- package/src/mesh/mesh-events.ts +30 -1035
- package/src/mesh/mesh-fast-forward.ts +839 -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 -5
- package/src/mesh/mesh-ledger.ts +591 -102
- package/src/mesh/mesh-missions.ts +322 -0
- package/src/mesh/mesh-reconcile-loop.ts +1096 -0
- package/src/mesh/mesh-refine-batch.ts +197 -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 +1697 -0
- package/src/mesh/mesh-task-stats.ts +161 -0
- package/src/mesh/mesh-unresolved-forward-outbox.ts +185 -0
- package/src/mesh/mesh-work-queue.ts +997 -141
- package/src/mesh/preview-freshness.ts +118 -0
- package/src/mesh/refine-config.ts +423 -0
- package/src/mesh/worktree-bootstrap-config.ts +331 -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 +45 -5
- package/src/providers/cli-provider-instance.ts +1254 -101
- 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/dispatcher.ts +340 -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 +30 -0
- package/src/providers/provider-instance.ts +19 -1
- package/src/providers/provider-loader.ts +670 -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 +1051 -0
- package/src/providers/spec/evaluator.ts +407 -0
- package/src/providers/spec/fsm-driver.ts +1251 -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 +1136 -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 +378 -14
- 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/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
|
@@ -8,8 +8,23 @@
|
|
|
8
8
|
* 3. How to orchestrate work across nodes
|
|
9
9
|
*
|
|
10
10
|
* The prompt is generated dynamically from the current mesh state.
|
|
11
|
+
*
|
|
12
|
+
* User customization:
|
|
13
|
+
* ~/.adhdev/coordinator-prompts/<cliType>.md — full override
|
|
14
|
+
* ~/.adhdev/coordinator-prompts/<cliType>.append.md — appended to default
|
|
15
|
+
* ~/.adhdev/coordinator-prompts/default.md — full override (any CLI)
|
|
16
|
+
* ~/.adhdev/coordinator-prompts/default.append.md — appended to default (any CLI)
|
|
17
|
+
*
|
|
18
|
+
* CLI-specific files take precedence over default.* files. The override file
|
|
19
|
+
* still gets the node/policy facts substituted via the same {{placeholders}}
|
|
20
|
+
* the daemon understands; an override that doesn't reference them just gets
|
|
21
|
+
* a static prompt, which is also fine.
|
|
11
22
|
*/
|
|
12
23
|
|
|
24
|
+
import * as fs from 'node:fs';
|
|
25
|
+
import * as os from 'node:os';
|
|
26
|
+
import * as path from 'node:path';
|
|
27
|
+
|
|
13
28
|
import type {
|
|
14
29
|
LocalMeshEntry,
|
|
15
30
|
RepoMeshPolicy,
|
|
@@ -25,10 +40,76 @@ export interface CoordinatorPromptContext {
|
|
|
25
40
|
status?: RepoMeshStatus;
|
|
26
41
|
userInstruction?: string;
|
|
27
42
|
coordinatorCliType?: string;
|
|
43
|
+
/**
|
|
44
|
+
* M3: pre-rendered active mission section (from buildMissionPromptSection).
|
|
45
|
+
* Empty/undefined when the mesh has no active mission — the prompt output
|
|
46
|
+
* stays identical to the pre-M3 form in that case.
|
|
47
|
+
*/
|
|
48
|
+
missionSection?: string;
|
|
28
49
|
}
|
|
29
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Compose the final coordinator prompt from four layers, in this precedence:
|
|
53
|
+
*
|
|
54
|
+
* 1. Per-launch `extraSystemPrompt` (always appended, as "## Additional
|
|
55
|
+
* Context"). Never wins as a base — it's launch-scope context.
|
|
56
|
+
* 2. Mesh-level append (`mesh.coordinator.systemPromptAppend` or the legacy
|
|
57
|
+
* `systemPromptSuffix`). Stacks after whichever base won.
|
|
58
|
+
* 3. User-file append (`~/.adhdev/coordinator-prompts/<cli>.append.md` or
|
|
59
|
+
* `default.append.md`). Also stacks; same placeholder expansion as the
|
|
60
|
+
* override path.
|
|
61
|
+
* 4. Base prompt, picked in this order:
|
|
62
|
+
* a. `mesh.coordinator.systemPromptOverride` (mesh-level override)
|
|
63
|
+
* b. user-file override (`~/.adhdev/coordinator-prompts/<cli>.md` or
|
|
64
|
+
* `default.md`)
|
|
65
|
+
* c. daemon default (assembled from identity/nodes/policy/tools/…)
|
|
66
|
+
*
|
|
67
|
+
* That layering lets a user customize prompts at three increasing scopes
|
|
68
|
+
* (machine, mesh, single launch) without losing the daemon's stock rules.
|
|
69
|
+
*/
|
|
30
70
|
export function buildCoordinatorSystemPrompt(ctx: CoordinatorPromptContext): string {
|
|
31
|
-
const { mesh,
|
|
71
|
+
const { mesh, userInstruction, coordinatorCliType } = ctx;
|
|
72
|
+
|
|
73
|
+
// ── Pick the base prompt ──
|
|
74
|
+
const meshOverride = mesh.coordinator?.systemPromptOverride?.trim();
|
|
75
|
+
let base: string;
|
|
76
|
+
if (meshOverride) {
|
|
77
|
+
base = expandPromptPlaceholders(meshOverride, ctx);
|
|
78
|
+
} else {
|
|
79
|
+
const userOverride = readUserPromptFile(coordinatorCliType, 'md');
|
|
80
|
+
if (userOverride !== null) {
|
|
81
|
+
base = expandPromptPlaceholders(userOverride, ctx);
|
|
82
|
+
} else {
|
|
83
|
+
base = buildDefaultCoordinatorPrompt(ctx);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const sections: string[] = [base];
|
|
88
|
+
|
|
89
|
+
// ── User-level append runs after whichever base won ──
|
|
90
|
+
const userAppend = readUserPromptFile(coordinatorCliType, 'append.md');
|
|
91
|
+
if (userAppend !== null) {
|
|
92
|
+
sections.push(expandPromptPlaceholders(userAppend, ctx));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ── Mesh-level append (prefer the new field, fall back to the legacy alias) ──
|
|
96
|
+
const meshAppend = (mesh.coordinator?.systemPromptAppend
|
|
97
|
+
?? mesh.coordinator?.systemPromptSuffix)?.trim();
|
|
98
|
+
if (meshAppend) {
|
|
99
|
+
sections.push(expandPromptPlaceholders(meshAppend, ctx));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ── Per-launch context lands last so it's the most recent thing the
|
|
103
|
+
// agent reads. Marked as Additional Context, not a rule update. ──
|
|
104
|
+
if (userInstruction) {
|
|
105
|
+
sections.push(`## Additional Context\n${userInstruction}`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return sections.join('\n\n');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function buildDefaultCoordinatorPrompt(ctx: CoordinatorPromptContext): string {
|
|
112
|
+
const { mesh, status, coordinatorCliType } = ctx;
|
|
32
113
|
const sections: string[] = [];
|
|
33
114
|
|
|
34
115
|
// ── Identity ──
|
|
@@ -46,6 +127,11 @@ Repository: \`${mesh.repoIdentity}\`${mesh.defaultBranch ? `\nDefault branch: \`
|
|
|
46
127
|
sections.push('## Nodes\nNo nodes configured yet. Ask the user to add nodes with `adhdev mesh add-node`.');
|
|
47
128
|
}
|
|
48
129
|
|
|
130
|
+
// ── Active Mission (M3) — only present when one exists ──
|
|
131
|
+
if (ctx.missionSection?.trim()) {
|
|
132
|
+
sections.push(ctx.missionSection.trim());
|
|
133
|
+
}
|
|
134
|
+
|
|
49
135
|
// ── Policy ──
|
|
50
136
|
sections.push(buildPolicySection({ ...DEFAULT_MESH_POLICY, ...(mesh.policy || {}) }));
|
|
51
137
|
|
|
@@ -61,22 +147,90 @@ Repository: \`${mesh.repoIdentity}\`${mesh.defaultBranch ? `\nDefault branch: \`
|
|
|
61
147
|
// ── Rules ──
|
|
62
148
|
sections.push(buildRulesSection(coordinatorCliType));
|
|
63
149
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
sections.push(`## Additional Context\n${userInstruction}`);
|
|
67
|
-
}
|
|
150
|
+
return sections.join('\n\n');
|
|
151
|
+
}
|
|
68
152
|
|
|
69
|
-
|
|
70
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Look up a user-customization file under ~/.adhdev/coordinator-prompts/.
|
|
155
|
+
*
|
|
156
|
+
* Lookup order:
|
|
157
|
+
* 1. <cliType>.<suffix> — provider-specific
|
|
158
|
+
* 2. default.<suffix> — shared across providers
|
|
159
|
+
*
|
|
160
|
+
* Returns null when neither exists; an empty/whitespace-only file is also
|
|
161
|
+
* treated as "no override" so users can drop in a stub without affecting
|
|
162
|
+
* behavior. Read errors (permission, IO) are swallowed and logged-as-null
|
|
163
|
+
* intentionally: a broken override file should never block coordinator
|
|
164
|
+
* launch, it should just behave as if the file weren't there.
|
|
165
|
+
*/
|
|
166
|
+
function readUserPromptFile(cliType: string | undefined, suffix: string): string | null {
|
|
167
|
+
const dir = path.join(os.homedir(), '.adhdev', 'coordinator-prompts');
|
|
168
|
+
const candidates: string[] = [];
|
|
169
|
+
if (cliType) candidates.push(path.join(dir, `${cliType}.${suffix}`));
|
|
170
|
+
candidates.push(path.join(dir, `default.${suffix}`));
|
|
171
|
+
for (const p of candidates) {
|
|
172
|
+
try {
|
|
173
|
+
const text = fs.readFileSync(p, 'utf8');
|
|
174
|
+
if (text.trim()) return text;
|
|
175
|
+
} catch { /* missing file is the common case — keep going */ }
|
|
71
176
|
}
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
72
179
|
|
|
73
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Expand `{{placeholder}}` tokens against current mesh state.
|
|
182
|
+
*
|
|
183
|
+
* Tokens we support today:
|
|
184
|
+
* {{meshName}} — mesh.name
|
|
185
|
+
* {{repo}} — mesh.repoIdentity
|
|
186
|
+
* {{defaultBranch}} — mesh.defaultBranch or empty
|
|
187
|
+
* {{cliType}} — coordinator CLI type or empty
|
|
188
|
+
* {{nodes}} — full node section (status if known, otherwise config)
|
|
189
|
+
* {{mission}} — active mission summary section (empty when none)
|
|
190
|
+
* {{policy}} — full policy section
|
|
191
|
+
* {{tools}} — the canonical tools table
|
|
192
|
+
* {{workflow}} — the canonical orchestration workflow
|
|
193
|
+
* {{rules}} — the canonical rules section (with coordinatorNote)
|
|
194
|
+
* {{toolExposurePreflight}} — the MCP-missing preflight reminder
|
|
195
|
+
*
|
|
196
|
+
* Unknown tokens are left as-is — that way typos are obvious in the rendered
|
|
197
|
+
* prompt instead of silently disappearing. Tokens are not recursive: an
|
|
198
|
+
* expanded value's own {{...}} content stays literal.
|
|
199
|
+
*/
|
|
200
|
+
function expandPromptPlaceholders(template: string, ctx: CoordinatorPromptContext): string {
|
|
201
|
+
const { mesh, status, coordinatorCliType } = ctx;
|
|
202
|
+
const nodesSection = status?.nodes?.length
|
|
203
|
+
? buildNodeStatusSection(status.nodes)
|
|
204
|
+
: mesh.nodes.length
|
|
205
|
+
? buildNodeConfigSection(mesh)
|
|
206
|
+
: '## Nodes\nNo nodes configured yet. Ask the user to add nodes with `adhdev mesh add-node`.';
|
|
207
|
+
const replacements: Record<string, string> = {
|
|
208
|
+
meshName: mesh.name,
|
|
209
|
+
repo: mesh.repoIdentity,
|
|
210
|
+
defaultBranch: mesh.defaultBranch || '',
|
|
211
|
+
cliType: coordinatorCliType || '',
|
|
212
|
+
nodes: nodesSection,
|
|
213
|
+
mission: ctx.missionSection?.trim() || '',
|
|
214
|
+
policy: buildPolicySection({ ...DEFAULT_MESH_POLICY, ...(mesh.policy || {}) }),
|
|
215
|
+
tools: TOOLS_SECTION,
|
|
216
|
+
workflow: WORKFLOW_SECTION,
|
|
217
|
+
rules: buildRulesSection(coordinatorCliType),
|
|
218
|
+
toolExposurePreflight: TOOL_EXPOSURE_PREFLIGHT_SECTION,
|
|
219
|
+
};
|
|
220
|
+
return template.replace(/\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g, (m, key) => {
|
|
221
|
+
return Object.prototype.hasOwnProperty.call(replacements, key) ? replacements[key] : m;
|
|
222
|
+
});
|
|
74
223
|
}
|
|
75
224
|
|
|
76
225
|
// ─── Section Builders ───────────────────────────
|
|
77
226
|
|
|
78
227
|
function buildNodeStatusSection(nodes: RepoMeshNodeStatus[]): string {
|
|
79
|
-
const lines = [
|
|
228
|
+
const lines = [
|
|
229
|
+
'## Current Node Status',
|
|
230
|
+
'',
|
|
231
|
+
'Node labels are display context, not aliases. Use exact `nodeId` values in mesh tool calls; do not invent shorthand names such as M1/M2 unless they are explicitly configured labels.',
|
|
232
|
+
'',
|
|
233
|
+
];
|
|
80
234
|
for (const n of nodes) {
|
|
81
235
|
const healthIcon = n.health === 'online' ? '🟢' :
|
|
82
236
|
n.health === 'dirty' ? '🟡' :
|
|
@@ -85,31 +239,78 @@ function buildNodeStatusSection(nodes: RepoMeshNodeStatus[]): string {
|
|
|
85
239
|
? `sessions: ${n.activeSessions.join(', ')}`
|
|
86
240
|
: 'no active sessions';
|
|
87
241
|
const branch = n.git?.branch ? `branch: \`${n.git.branch}\`` : '';
|
|
88
|
-
|
|
89
|
-
|
|
242
|
+
const context = [
|
|
243
|
+
n.daemonId ? `daemon: \`${n.daemonId}\`` : '',
|
|
244
|
+
n.providers?.length ? `providers: ${n.providers.join(', ')}` : '',
|
|
245
|
+
].filter(Boolean).join(' | ');
|
|
246
|
+
lines.push(`- ${healthIcon} **${n.machineLabel}** (nodeId: \`${n.nodeId}\`)`);
|
|
247
|
+
lines.push(` workspace: \`${n.workspace}\`${context ? ` | ${context}` : ''} | ${branch} | ${sessions}`);
|
|
90
248
|
if (n.error) lines.push(` ⚠️ ${n.error}`);
|
|
249
|
+
const nodePrompt = typeof (n as any).systemPrompt === 'string' ? (n as any).systemPrompt.trim() : '';
|
|
250
|
+
if (nodePrompt) {
|
|
251
|
+
lines.push(` 📌 Node instruction: ${indentFollowing(nodePrompt, ' ')}`);
|
|
252
|
+
}
|
|
91
253
|
}
|
|
92
254
|
return lines.join('\n');
|
|
93
255
|
}
|
|
94
256
|
|
|
95
257
|
function buildNodeConfigSection(mesh: LocalMeshEntry): string {
|
|
96
|
-
const lines = [
|
|
258
|
+
const lines = [
|
|
259
|
+
'## Configured Nodes',
|
|
260
|
+
'',
|
|
261
|
+
'Node labels are display context, not aliases. Use exact `nodeId` values in mesh tool calls; do not invent shorthand names such as M1/M2 unless they are explicitly configured labels.',
|
|
262
|
+
'',
|
|
263
|
+
];
|
|
97
264
|
for (const n of mesh.nodes) {
|
|
98
265
|
const labels: string[] = [];
|
|
99
266
|
if (n.isLocalWorktree) labels.push('worktree');
|
|
100
267
|
if (n.policy?.readOnly) labels.push('read-only');
|
|
101
268
|
const suffix = labels.length ? ` [${labels.join(', ')}]` : '';
|
|
102
|
-
|
|
269
|
+
const explicitMachineLabel = typeof (n as any).machineLabel === 'string' ? (n as any).machineLabel : '';
|
|
270
|
+
const explicitLabel = explicitMachineLabel ? ` label: **${explicitMachineLabel}** |` : '';
|
|
271
|
+
const providerPriority = n.policy?.providerPriority?.length ? ` | providers: ${n.policy.providerPriority.join(', ')}` : '';
|
|
272
|
+
// Per-(node, provider) maxParallel cap. Only maxParallel is enforced by the
|
|
273
|
+
// queue; routing is governed by required_tags, not provider roles.
|
|
274
|
+
const providerRoles = Array.isArray(n.policy?.providerRoles)
|
|
275
|
+
? (n.policy!.providerRoles as Array<{ providerType?: unknown; maxParallel?: unknown }>)
|
|
276
|
+
.map(r => {
|
|
277
|
+
const type = typeof r?.providerType === 'string' ? r.providerType.trim() : '';
|
|
278
|
+
if (!type) return '';
|
|
279
|
+
const cap = Number.isFinite(Number(r?.maxParallel)) ? ` (max ${Math.floor(Number(r.maxParallel))})` : '';
|
|
280
|
+
return `${type}${cap}`;
|
|
281
|
+
})
|
|
282
|
+
.filter(Boolean)
|
|
283
|
+
: [];
|
|
284
|
+
const providerRolesSuffix = providerRoles.length ? ` | caps: ${providerRoles.join(', ')}` : '';
|
|
285
|
+
lines.push(`- ${explicitLabel} nodeId: \`${n.id}\` | workspace: \`${n.workspace}\`${n.daemonId ? ` | daemon: \`${n.daemonId}\`` : ''}${providerPriority}${providerRolesSuffix}${suffix}`);
|
|
286
|
+
const nodePrompt = typeof (n as any).systemPrompt === 'string' ? (n as any).systemPrompt.trim() : '';
|
|
287
|
+
if (nodePrompt) {
|
|
288
|
+
lines.push(` 📌 Node instruction: ${indentFollowing(nodePrompt, ' ')}`);
|
|
289
|
+
}
|
|
103
290
|
}
|
|
104
291
|
lines.push('', '_Use `mesh_status` to probe live health before delegating work._');
|
|
105
292
|
return lines.join('\n');
|
|
106
293
|
}
|
|
107
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Indent every line after the first by `pad`. Used so multi-line node
|
|
297
|
+
* instructions still visually nest under the node bullet without the
|
|
298
|
+
* second line dangling at column zero.
|
|
299
|
+
*/
|
|
300
|
+
function indentFollowing(text: string, pad: string): string {
|
|
301
|
+
const lines = text.split('\n');
|
|
302
|
+
if (lines.length === 1) return lines[0];
|
|
303
|
+
return [lines[0], ...lines.slice(1).map(l => pad + l)].join('\n');
|
|
304
|
+
}
|
|
305
|
+
|
|
108
306
|
function buildPolicySection(policy: RepoMeshPolicy): string {
|
|
109
307
|
const rules: string[] = [];
|
|
110
308
|
if (policy.requirePreTaskCheckpoint) rules.push('- Create a git checkpoint **before** starting each task');
|
|
111
309
|
if (policy.requirePostTaskCheckpoint) rules.push('- Create a git checkpoint **after** each task completes');
|
|
112
310
|
if (policy.requireApprovalForPush) rules.push('- **Ask for user approval** before pushing to remote');
|
|
311
|
+
if (policy.allowAutoPublishSubmoduleMainCommits) {
|
|
312
|
+
rules.push('- Refinery may auto-publish unreachable submodule gitlink commits to submodule origin/main with non-force pushes after validation and patch-equivalence pass');
|
|
313
|
+
}
|
|
113
314
|
if (policy.requireApprovalForDestructiveGit) rules.push('- **Ask for user approval** before destructive git operations (force push, reset, etc.)');
|
|
114
315
|
|
|
115
316
|
const dirtyBehavior = {
|
|
@@ -140,6 +341,8 @@ const TOOLS_SECTION = `## Available Tools
|
|
|
140
341
|
| \`mesh_read_debug\` | Collect a daemon-side chat/parser debug bundle for a session |
|
|
141
342
|
| \`mesh_task_history\` | Read the task ledger — dispatches, completions, failures. Use to understand what has been done before deciding next steps |
|
|
142
343
|
| \`mesh_git_status\` | Check git status on a specific node |
|
|
344
|
+
| \`mesh_read_node_logs\` | Fetch a remote node's daemon log tail directly over P2P (grep/since/byte-bounded, secrets redacted) — no session/PowerShell needed to debug a node's daemon |
|
|
345
|
+
| \`mesh_fast_forward_node\` | Safely dry-run or explicitly execute an obvious clean fast-forward without launching an agent session |
|
|
143
346
|
| \`mesh_checkpoint\` | Create a git checkpoint on a node |
|
|
144
347
|
| \`mesh_approve\` | Approve/reject a pending agent action |
|
|
145
348
|
| \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
|
|
@@ -154,17 +357,17 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
154
357
|
const WORKFLOW_SECTION = `## Orchestration Workflow
|
|
155
358
|
|
|
156
359
|
1. **Assess** — Call \`mesh_status\` to see which nodes are healthy and available. Check \`mesh_task_history\` to understand what has already been done in this mesh — previous delegations, completions, and failures.
|
|
157
|
-
2. **Plan** — Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist. If \`mesh_task_history\` shows a recent failure for a task, decide whether to retry or reassign.
|
|
360
|
+
2. **Plan** — Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist. If \`mesh_task_history\` shows a recent failure for a task, decide whether to retry or reassign. **For multi-task work, create a mission first**: call \`mesh_mission_upsert\` with a title and goal, then attach every enqueued task with \`mission_id\`. Express "B after A" ordering with \`depends_on\` on the queue task instead of waiting and polling — the system claims dependents automatically when their dependencies complete. When the mission's outcome is decided, update its status (\`completed\`/\`abandoned\`) via \`mesh_mission_upsert\`. If the prompt already shows an **Active Mission**, continue it from its current task state — do not re-enqueue tasks that already exist.
|
|
158
361
|
3. **Queue / Delegate** — The Mesh uses an autonomous pull-based Work Queue:
|
|
159
362
|
a. **General Tasks**: Enqueue tasks using \`mesh_enqueue_task\`. Idle node agents will automatically pull tasks from the queue and begin working.
|
|
160
363
|
b. **Node Preparation**: Reuse an existing idle session on the correct node/provider before launching a new chat/session. Call \`mesh_launch_session\` only when no suitable session exists, when the user explicitly asks for a fresh provider/session, or when branch/worktree isolation requires it. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
|
|
161
364
|
c. **Targeted Tasks**: Use \`mesh_send_task\` only when you need to bypass the queue and force a specific node to execute a task immediately.
|
|
162
365
|
d. For the first dispatch of a new task, provide a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
|
|
163
366
|
e. For a continuation of the same issue in an existing session, send a concise **delta instruction**: current verified state, the exact failed/blocked step, the newly approved action, and final reporting requirements. Do not resend the full original task or open a new chat solely to continue the same work; that wastes coordinator and worker context.
|
|
164
|
-
4. **Monitor** — Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly.
|
|
367
|
+
4. **Monitor** — Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly. Do **not** repeatedly call \`mesh_status\` or \`mesh_view_queue\` just to wait for assigned/generating work. After dispatching a direct or queued task, send one progress update with the task/session handle, then stop. Wait for \`pendingCoordinatorEvents\` or another completion/approval/status signal, an explicit user status request, or a real timeout/stall signal before reading status/chat/queue again. Use at most one compact \`mesh_read_chat\` check after a terminal signal. Handle approvals via \`mesh_approve\`. **Proactively parallelize new work.** When the user reports a new bug or asks for new work, start it immediately if it is independent of in-flight tasks and there is headroom under \`maxParallelTasks\` — do not wait for a current task to finish or for the user to prompt you to parallelize. Read-only diagnosis (\`live_debug_readonly\`) has no isolation or merge cost, so dispatch it in parallel right away. The no-polling / concurrency-limit rules constrain *re-checking or duplicating already-dispatched work*; they are **not** a reason to defer starting a new, independent task.
|
|
165
368
|
5. **Verify** — When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
|
|
166
369
|
6. **Checkpoint** — Call \`mesh_checkpoint\` to save the work.
|
|
167
|
-
7. **Converge branches** — Before marking any task complete, classify every touched node/branch into exactly one final state: \`merged_to_main\`, \`pushed_feature_branch_needs_merge\`, \`blocked_review\`, \`cleanup_candidate\`, or \`not_mergeable\`. Use \`mesh_status\` branchConvergenceSummary and \`mesh_refine_node\` for clean worktree branches when safe. A task that remains on a non-main branch is not fully complete unless the final report names the follow-up state and next step.
|
|
370
|
+
7. **Converge branches** — Before marking any task complete, classify every touched node/branch into exactly one final state: \`merged_to_main\`, \`pushed_feature_branch_needs_merge\`, \`blocked_review\`, \`cleanup_candidate\`, or \`not_mergeable\`. Use \`mesh_status\` branchConvergenceSummary. For obvious clean branch catch-up (ahead 0, behind > 0, upstream fresh, no dirty/stash/submodule issues), use \`mesh_fast_forward_node\` dry-run first and execute only when explicitly safe/approved; this avoids consuming an agent session. Use \`mesh_refine_node\` for clean worktree branches when safe. Before/refine merging root commits that contain submodule gitlink changes, require each submodule commit to be reachable from the configured submodule remote main branch, not merely present on a feature ref or local checkout. If \`mesh_refine_node\` returns \`submodule_reachability_failed\` or publish-required evidence, keep the public convergence bucket as \`blocked_review\`; unless \`allowAutoPublishSubmoduleMainCommits\` is explicitly enabled and Refinery reports successful non-force publish plus post-publish verification, ask the user for explicit approval to push/publish the unreachable submodule commit(s) to submodule main, then rerun \`mesh_refine_node\`. Do not merge the root branch until the submodule commit(s) are reachable from submodule origin/main. A task that remains on a non-main branch is not fully complete unless the final report names the follow-up state and next step.
|
|
168
371
|
8. **Clean up** — Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
|
|
169
372
|
9. **Report** — Summarize what was done, what changed, any issues, and the branch convergence state.
|
|
170
373
|
|
|
@@ -188,19 +391,19 @@ function buildRulesSection(coordinatorCliType?: string): string {
|
|
|
188
391
|
|
|
189
392
|
return `## Rules
|
|
190
393
|
|
|
191
|
-
- **
|
|
192
|
-
- **
|
|
193
|
-
- **
|
|
194
|
-
- **
|
|
195
|
-
- **
|
|
196
|
-
- **
|
|
197
|
-
- **
|
|
198
|
-
- **
|
|
199
|
-
- **
|
|
200
|
-
- **
|
|
201
|
-
- **
|
|
202
|
-
- **
|
|
203
|
-
- **
|
|
204
|
-
- **
|
|
205
|
-
- **
|
|
394
|
+
- **Route, don't implement.** Delegate all code reading, analysis, and execution to node agents. Never read source files or run commands in the coordinator — keep context lean.
|
|
395
|
+
- **Front-load task messages.** Include everything the agent needs (files, problem, expected fix) in \`mesh_enqueue_task\` / \`mesh_send_task\`. Append a structured result request at the end: ask the worker to conclude with a JSON block containing \`status\`, \`changedFiles\`, \`gitStatus\`, \`validationResults\`, \`errors\`, \`nextAction\`. The daemon parses this automatically; you can read it from \`mesh_task_history\`.
|
|
396
|
+
- **Reuse idle sessions.** For follow-up, retry, commit/push, or cleanup on the same issue, send only the delta to the existing idle session. Start fresh only for independent work, provider mismatch, transcript contamination, or required worktree isolation.
|
|
397
|
+
- **Respect explicit provider requests.** Map: Hermes → \`hermes-cli\`, Claude/Claude Code → \`claude-cli\`, Codex → \`codex-cli\`, Gemini → \`gemini-cli\`, Antigravity → \`antigravity-cli\`. Never substitute the coordinator's own runtime.
|
|
398
|
+
- **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
|
|
399
|
+
- **Limit parallelism.** Start with 1–2 tasks; scale only on success. Never duplicate a session because \`mesh_read_chat\` shows no final message while tool/terminal activity is ongoing. This caps *concurrent* load — it does not mean serialize independent work: when a new, independent request arrives and there is headroom under \`maxParallelTasks\`, dispatch it right away rather than waiting for an in-flight task or a user nudge (read-only diagnosis especially, since it has no merge cost).
|
|
400
|
+
- **Check history first.** Call \`mesh_task_history\` at session start to avoid duplicate work and inform recovery. On failure, read task history before retrying.
|
|
401
|
+
- **Sequence shared-base-moving merges.** Parallel dispatch is encouraged, but merging one worktree can advance another in-flight worktree's base — especially the oss submodule pointer — turning a clean fast-forward into a diverged rebase (patch-equivalence correctly blocks this). Before merging an in-flight worktree while siblings are also in flight, land in an intentional order, re-clone long-running worktrees from the advanced base, or expect to manually rebase + ff-only the laggards; merging an independent fix mid-flight can strand siblings into a rebase.
|
|
402
|
+
- **Converge branches.** After worktree tasks: refine/fast-forward, or classify as \`pushed_feature_branch_needs_merge\` / \`blocked_review\` / \`cleanup_candidate\` / \`not_mergeable\`. Clean up with \`mesh_remove_node\`.
|
|
403
|
+
- **Refinery is config-driven.** \`mesh_refine_node\` must run validation from \`.adhdev/refine.{json,yaml,yml}\` or \`repo-mesh.refine.*\`. Heuristics are scaffolding only.
|
|
404
|
+
- **Submodule reachability = publish-needed.** \`submodule_reachability_failed\` → classify as \`blocked_review\`, request user approval to push to submodule main, then rerun \`mesh_refine_node\`.
|
|
405
|
+
- **Honor per-node instructions.** When a node carries a 📌 Node instruction in the nodes section, include the relevant parts of that instruction in the task message you send to that node. Don't paraphrase the instruction into your own words — quote it verbatim so the worker agent sees exactly what the user wrote.
|
|
406
|
+
- **Mission status does not update itself.** When a mission's tasks are all done or the work is abandoned, explicitly call \`mesh_mission_upsert\` to set status \`completed\` or \`abandoned\`. Never leave a finished mission in \`active\`. All-cancelled tasks with no further work → \`abandoned\`.
|
|
407
|
+
- **Never fabricate tool results.** Always call the actual tool.
|
|
408
|
+
- **Keep the user informed.** One or two sentences after each delegation round.${coordinatorNote}`;
|
|
206
409
|
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MeshCoordinatorRegistry — Persisted record of active mesh coordinator sessions.
|
|
3
|
+
*
|
|
4
|
+
* Survives daemon restarts: when a CLI coordinator session is re-attached after
|
|
5
|
+
* a daemon restart the in-memory `settings.meshCoordinatorFor` on the provider
|
|
6
|
+
* instance is gone, so the registry file fills the gap.
|
|
7
|
+
*
|
|
8
|
+
* Keyed by sessionId (the CLI instance key / runtimeKey).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { join } from 'path';
|
|
12
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
13
|
+
import { getDaemonDataDir } from '../config/config.js';
|
|
14
|
+
|
|
15
|
+
export interface CoordinatorRegistryEntry {
|
|
16
|
+
meshId: string;
|
|
17
|
+
sessionId: string;
|
|
18
|
+
workspace?: string;
|
|
19
|
+
startedAt: number;
|
|
20
|
+
/** CLI type used to launch the coordinator (claude-cli / codex-cli / …). */
|
|
21
|
+
cliType?: string;
|
|
22
|
+
/** Final system prompt sent to the coordinator after all overrides, appends,
|
|
23
|
+
* and extraSystemPrompt have been applied. Surfaced via the session-info
|
|
24
|
+
* endpoint so users can audit exactly what prompt the agent saw. */
|
|
25
|
+
systemPrompt?: string;
|
|
26
|
+
/** Per-launch extraSystemPrompt the caller passed in, if any. Stored
|
|
27
|
+
* separately from `systemPrompt` so the UI can show what the user
|
|
28
|
+
* added vs. what the daemon's default template produced. */
|
|
29
|
+
extraSystemPrompt?: string;
|
|
30
|
+
/** How the prompt was actually injected (cli_arg / context_file / …). */
|
|
31
|
+
injection?: { mode: string; target?: string };
|
|
32
|
+
/** Path of the MCP config file the daemon wrote for this session. */
|
|
33
|
+
mcpConfigPath?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const _registry = new Map<string, CoordinatorRegistryEntry>();
|
|
37
|
+
|
|
38
|
+
function getRegistryPath(): string {
|
|
39
|
+
return join(getDaemonDataDir(), 'mesh-coordinators.json');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Load persisted coordinator registry from disk into in-memory map. Called once on daemon boot. */
|
|
43
|
+
export function loadMeshCoordinatorRegistry(): void {
|
|
44
|
+
const path = getRegistryPath();
|
|
45
|
+
if (!existsSync(path)) return;
|
|
46
|
+
try {
|
|
47
|
+
const raw = JSON.parse(readFileSync(path, 'utf-8'));
|
|
48
|
+
if (!Array.isArray(raw)) return;
|
|
49
|
+
_registry.clear();
|
|
50
|
+
for (const entry of raw) {
|
|
51
|
+
if (typeof entry?.sessionId === 'string' && typeof entry?.meshId === 'string') {
|
|
52
|
+
_registry.set(entry.sessionId, entry as CoordinatorRegistryEntry);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
} catch { /* ignore corrupt file */ }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function saveRegistry(): void {
|
|
59
|
+
try {
|
|
60
|
+
writeFileSync(
|
|
61
|
+
getRegistryPath(),
|
|
62
|
+
JSON.stringify([..._registry.values()], null, 2),
|
|
63
|
+
{ encoding: 'utf-8', mode: 0o600 },
|
|
64
|
+
);
|
|
65
|
+
} catch { /* best-effort */ }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Register a coordinator session. Persists to disk immediately. */
|
|
69
|
+
export function registerMeshCoordinator(entry: CoordinatorRegistryEntry): void {
|
|
70
|
+
_registry.set(entry.sessionId, entry);
|
|
71
|
+
saveRegistry();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Remove a coordinator session by sessionId. Persists to disk.
|
|
75
|
+
*
|
|
76
|
+
* Also best-effort strips any context_file wrapper block we wrote into
|
|
77
|
+
* the workspace at launch time (AGENTS.md / GEMINI.md), because those
|
|
78
|
+
* files are auto-loaded by their CLIs on every subsequent launch — and
|
|
79
|
+
* a wrapper block surviving the coordinator session would silently
|
|
80
|
+
* inject the coordinator system prompt into ordinary non-coordinator
|
|
81
|
+
* sessions in the same workspace, which is exactly the bug we're
|
|
82
|
+
* fixing here.
|
|
83
|
+
*
|
|
84
|
+
* Stripping rules:
|
|
85
|
+
* - Look for the start sentinel anywhere in the file; if absent,
|
|
86
|
+
* leave the file alone (user-authored content).
|
|
87
|
+
* - If the wrapper block was the only thing in the file, delete the
|
|
88
|
+
* file outright so we don't leave behind an empty AGENTS.md.
|
|
89
|
+
* - Otherwise drop only the block between the sentinels and trim a
|
|
90
|
+
* leading/trailing blank line so we don't leave dangling separators.
|
|
91
|
+
*/
|
|
92
|
+
export function unregisterMeshCoordinator(sessionId: string): void {
|
|
93
|
+
const entry = _registry.get(sessionId);
|
|
94
|
+
if (!_registry.delete(sessionId)) return;
|
|
95
|
+
saveRegistry();
|
|
96
|
+
if (!entry) return;
|
|
97
|
+
const workspace = entry.workspace;
|
|
98
|
+
const target = entry.injection?.mode === 'context_file' && typeof entry.injection.target === 'string'
|
|
99
|
+
? entry.injection.target
|
|
100
|
+
: '';
|
|
101
|
+
if (!workspace || !target) return;
|
|
102
|
+
// injection.target is workspace-relative (AGENTS.md / GEMINI.md); we don't
|
|
103
|
+
// resolve absolute paths here because we never wrote one — applyMesh-
|
|
104
|
+
// CoordinatorSystemPromptInjection joins via path.join(workspace, …).
|
|
105
|
+
const filePath = `${workspace.replace(/\/$/, '')}/${target}`;
|
|
106
|
+
try {
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
108
|
+
const { stripCoordinatorWrapperFile } = require('../commands/mesh-coordinator.js');
|
|
109
|
+
stripCoordinatorWrapperFile(filePath);
|
|
110
|
+
} catch { /* best-effort cleanup; never throw out of unregister */ }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Look up a coordinator entry by session ID. Returns undefined if not registered. */
|
|
114
|
+
export function getCoordinatorForSession(sessionId: string): CoordinatorRegistryEntry | undefined {
|
|
115
|
+
return _registry.get(sessionId);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** List all coordinator entries for a given workspace path. */
|
|
119
|
+
export function listCoordinatorsForWorkspace(workspace: string): CoordinatorRegistryEntry[] {
|
|
120
|
+
return [..._registry.values()].filter(e => e.workspace === workspace);
|
|
121
|
+
}
|