borgmcp 0.5.2 → 0.6.2

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.
@@ -0,0 +1,116 @@
1
+ /**
2
+ * `borg spawn` — create a new git worktree for a sibling drone and
3
+ * (by default) launch a fresh Claude Code session inside it.
4
+ *
5
+ * Why this exists: the cube's multi-drone pattern wants each drone to
6
+ * have its own worktree so parallel branches don't step on each other,
7
+ * but the manual ceremony (`git worktree add ../foo-name`, then
8
+ * `cd ../foo-name && borg`) is enough friction that drones drift back
9
+ * to working in one worktree and serializing. The subcommand collapses
10
+ * that to `borg spawn <name>`.
11
+ *
12
+ * Layout:
13
+ * Given the current worktree's primary at `/path/to/borg-mcp`, a
14
+ * `borg spawn builder` call creates `/path/to/borg-mcp-builder` as
15
+ * a sibling directory and runs `git worktree add` to register it.
16
+ * Default checkout is detached HEAD at the current HEAD so the new
17
+ * drone starts on a clean reference point without competing with
18
+ * the source worktree's branch state.
19
+ *
20
+ * Flags:
21
+ * --no-launch Create the worktree but don't run `borg` inside.
22
+ * Useful for setting up a tree to come back to later.
23
+ * --branch <ref> Check out a specific branch instead of detached
24
+ * HEAD. If <ref> is already checked out in another
25
+ * worktree, git refuses and we surface that error.
26
+ *
27
+ * Edge cases:
28
+ * - Not inside a git repo → friendly error, exit 1
29
+ * - Target path already exists → friendly error, exit 1
30
+ * - Empty name / name with slashes → format-hint error, exit 1
31
+ * - git worktree add fails → surface git's stderr verbatim, exit 1
32
+ */
33
+ export interface SpawnArgs {
34
+ name: string;
35
+ noLaunch: boolean;
36
+ branch: string | null;
37
+ }
38
+ export type ParseResult = {
39
+ ok: true;
40
+ args: SpawnArgs;
41
+ } | {
42
+ ok: false;
43
+ error: string;
44
+ };
45
+ /**
46
+ * Parse `argv.slice(2)` (i.e. arguments to `borg`, with `spawn` already
47
+ * stripped) into a structured SpawnArgs or a friendly error.
48
+ *
49
+ * Supported shapes:
50
+ * borg spawn <name>
51
+ * borg spawn <name> --no-launch
52
+ * borg spawn <name> --branch <ref>
53
+ * borg spawn <name> --branch <ref> --no-launch
54
+ * (flag order doesn't matter; positional `<name>` may appear before
55
+ * or after the flags)
56
+ *
57
+ * Unknown flags and missing/duplicate positional name are caller-
58
+ * friendly errors with format hints.
59
+ */
60
+ export declare function parseSpawnArgs(rawArgs: string[]): ParseResult;
61
+ export declare function validateName(name: string): {
62
+ ok: true;
63
+ } | {
64
+ ok: false;
65
+ error: string;
66
+ };
67
+ /**
68
+ * Given the absolute path to the primary worktree and a validated
69
+ * spawn name, return the absolute path of the new sibling worktree.
70
+ *
71
+ * Naming convention: `<sibling-parent>/<primary-basename>-<name>`.
72
+ * Example: primary `/home/x/borg-mcp` + name `builder` →
73
+ * `/home/x/borg-mcp-builder`. Keeps related worktrees alphabetically
74
+ * adjacent in `ls`, which matters when a drone-operator has a dozen
75
+ * sibling trees.
76
+ *
77
+ * Pure. Tested directly.
78
+ */
79
+ export declare function computeWorktreePath(primaryWorktreeAbs: string, name: string): string;
80
+ export interface SpawnDeps {
81
+ /** Synchronous spawn — used for `git ...` invocations. */
82
+ runSync?: (cmd: string, args: string[], cwd?: string) => SpawnSyncResult;
83
+ /** Path existence — used to bail on collisions. */
84
+ pathExists?: (p: string) => boolean;
85
+ /** Async spawn — used to launch the in-worktree `borg`. */
86
+ runDetached?: (cmd: string, args: string[], cwd: string) => Promise<number>;
87
+ /** Inject for tests; defaults to `process.cwd()`. */
88
+ cwd?: () => string;
89
+ /** stderr sink — overridable for tests. */
90
+ stderr?: (line: string) => void;
91
+ }
92
+ export interface SpawnSyncResult {
93
+ status: number | null;
94
+ stdout: string;
95
+ stderr: string;
96
+ }
97
+ /**
98
+ * Run the `borg spawn` flow against the given args. Returns the
99
+ * desired process exit code. Pure side-effects flow through `deps`
100
+ * so tests can inject mocks for every external interaction.
101
+ *
102
+ * Flow:
103
+ * 1. Validate name
104
+ * 2. Resolve primary worktree path via `git rev-parse --show-toplevel`
105
+ * (run from the operator's cwd — handles nested worktrees by
106
+ * asking git to find the top, which always points at the current
107
+ * worktree's root; for our naming convention we want the
108
+ * `--git-common-dir` parent which IS the primary worktree's
109
+ * filesystem dir, NOT the current worktree's. Resolve below.)
110
+ * 3. Compute target path; abort if exists
111
+ * 4. Run `git worktree add <target> [<ref>|--detach HEAD]`
112
+ * 5. Print stderr nudge
113
+ * 6. If !noLaunch, exec `borg` inside the new worktree
114
+ */
115
+ export declare function runSpawn(args: SpawnArgs, deps?: SpawnDeps): Promise<number>;
116
+ //# sourceMappingURL=spawn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../src/spawn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAWH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC7B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,WAAW,CA0C7D;AAkBD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAatF;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,kBAAkB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpF;AAMD,MAAM,WAAW,SAAS;IACxB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,eAAe,CAAC;IACzE,mDAAmD;IACnD,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IACpC,2DAA2D;IAC3D,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5E,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAsBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,SAAS,EACf,IAAI,GAAE,SAAc,GACnB,OAAO,CAAC,MAAM,CAAC,CAwGjB"}
package/dist/spawn.js ADDED
@@ -0,0 +1,273 @@
1
+ /**
2
+ * `borg spawn` — create a new git worktree for a sibling drone and
3
+ * (by default) launch a fresh Claude Code session inside it.
4
+ *
5
+ * Why this exists: the cube's multi-drone pattern wants each drone to
6
+ * have its own worktree so parallel branches don't step on each other,
7
+ * but the manual ceremony (`git worktree add ../foo-name`, then
8
+ * `cd ../foo-name && borg`) is enough friction that drones drift back
9
+ * to working in one worktree and serializing. The subcommand collapses
10
+ * that to `borg spawn <name>`.
11
+ *
12
+ * Layout:
13
+ * Given the current worktree's primary at `/path/to/borg-mcp`, a
14
+ * `borg spawn builder` call creates `/path/to/borg-mcp-builder` as
15
+ * a sibling directory and runs `git worktree add` to register it.
16
+ * Default checkout is detached HEAD at the current HEAD so the new
17
+ * drone starts on a clean reference point without competing with
18
+ * the source worktree's branch state.
19
+ *
20
+ * Flags:
21
+ * --no-launch Create the worktree but don't run `borg` inside.
22
+ * Useful for setting up a tree to come back to later.
23
+ * --branch <ref> Check out a specific branch instead of detached
24
+ * HEAD. If <ref> is already checked out in another
25
+ * worktree, git refuses and we surface that error.
26
+ *
27
+ * Edge cases:
28
+ * - Not inside a git repo → friendly error, exit 1
29
+ * - Target path already exists → friendly error, exit 1
30
+ * - Empty name / name with slashes → format-hint error, exit 1
31
+ * - git worktree add fails → surface git's stderr verbatim, exit 1
32
+ */
33
+ import { spawnSync, spawn } from 'node:child_process';
34
+ import { existsSync } from 'node:fs';
35
+ import { basename, dirname, join, resolve } from 'node:path';
36
+ import chalk from 'chalk';
37
+ /**
38
+ * Parse `argv.slice(2)` (i.e. arguments to `borg`, with `spawn` already
39
+ * stripped) into a structured SpawnArgs or a friendly error.
40
+ *
41
+ * Supported shapes:
42
+ * borg spawn <name>
43
+ * borg spawn <name> --no-launch
44
+ * borg spawn <name> --branch <ref>
45
+ * borg spawn <name> --branch <ref> --no-launch
46
+ * (flag order doesn't matter; positional `<name>` may appear before
47
+ * or after the flags)
48
+ *
49
+ * Unknown flags and missing/duplicate positional name are caller-
50
+ * friendly errors with format hints.
51
+ */
52
+ export function parseSpawnArgs(rawArgs) {
53
+ let name = null;
54
+ let noLaunch = false;
55
+ let branch = null;
56
+ for (let i = 0; i < rawArgs.length; i += 1) {
57
+ const arg = rawArgs[i];
58
+ if (arg === '--no-launch') {
59
+ noLaunch = true;
60
+ }
61
+ else if (arg === '--branch') {
62
+ const next = rawArgs[i + 1];
63
+ if (typeof next !== 'string' || next.length === 0) {
64
+ return {
65
+ ok: false,
66
+ error: `--branch requires a ref argument (e.g. \`--branch main\`)`,
67
+ };
68
+ }
69
+ branch = next;
70
+ i += 1;
71
+ }
72
+ else if (arg.startsWith('--')) {
73
+ return {
74
+ ok: false,
75
+ error: `unknown flag: ${arg}. Supported: --no-launch, --branch <ref>`,
76
+ };
77
+ }
78
+ else {
79
+ if (name !== null) {
80
+ return {
81
+ ok: false,
82
+ error: `unexpected extra argument: ${arg} (already have name "${name}")`,
83
+ };
84
+ }
85
+ name = arg;
86
+ }
87
+ }
88
+ if (name === null) {
89
+ return {
90
+ ok: false,
91
+ error: `missing required argument <name>. Usage: borg spawn <name> [--branch <ref>] [--no-launch]`,
92
+ };
93
+ }
94
+ return { ok: true, args: { name, noLaunch, branch } };
95
+ }
96
+ // ------------------------------------------------------------------
97
+ // Name validation
98
+ // ------------------------------------------------------------------
99
+ /**
100
+ * Worktree names get tacked onto the parent directory's path. They
101
+ * must therefore be filesystem-safe AND short enough that the
102
+ * resulting path doesn't make `ls` unreadable. Reject anything with
103
+ * slashes, parent-directory tokens, leading dashes (would parse as
104
+ * a flag), or shell-metacharacter punctuation.
105
+ *
106
+ * Allowed: lowercase ASCII letters, digits, hyphens, underscores.
107
+ * Length 1–48. Anchored. No leading hyphen.
108
+ */
109
+ const NAME_RE = /^[a-z0-9_][a-z0-9_-]{0,47}$/;
110
+ export function validateName(name) {
111
+ if (name.length === 0) {
112
+ return { ok: false, error: `name must not be empty` };
113
+ }
114
+ if (!NAME_RE.test(name)) {
115
+ return {
116
+ ok: false,
117
+ error: `invalid name "${name}". Use lowercase letters, digits, hyphens, or ` +
118
+ `underscores; max 48 chars; must not start with a hyphen.`,
119
+ };
120
+ }
121
+ return { ok: true };
122
+ }
123
+ // ------------------------------------------------------------------
124
+ // Path computation (pure)
125
+ // ------------------------------------------------------------------
126
+ /**
127
+ * Given the absolute path to the primary worktree and a validated
128
+ * spawn name, return the absolute path of the new sibling worktree.
129
+ *
130
+ * Naming convention: `<sibling-parent>/<primary-basename>-<name>`.
131
+ * Example: primary `/home/x/borg-mcp` + name `builder` →
132
+ * `/home/x/borg-mcp-builder`. Keeps related worktrees alphabetically
133
+ * adjacent in `ls`, which matters when a drone-operator has a dozen
134
+ * sibling trees.
135
+ *
136
+ * Pure. Tested directly.
137
+ */
138
+ export function computeWorktreePath(primaryWorktreeAbs, name) {
139
+ const parent = dirname(primaryWorktreeAbs);
140
+ const base = basename(primaryWorktreeAbs);
141
+ return join(parent, `${base}-${name}`);
142
+ }
143
+ const defaultDeps = {
144
+ runSync: (cmd, args, cwd) => {
145
+ const r = spawnSync(cmd, args, { cwd, encoding: 'utf-8' });
146
+ return {
147
+ status: r.status,
148
+ stdout: r.stdout ?? '',
149
+ stderr: r.stderr ?? '',
150
+ };
151
+ },
152
+ pathExists: (p) => existsSync(p),
153
+ runDetached: (cmd, args, cwd) => new Promise((resolveExit, rejectExit) => {
154
+ const child = spawn(cmd, args, { cwd, stdio: 'inherit', shell: false });
155
+ child.on('error', rejectExit);
156
+ child.on('exit', (code) => resolveExit(code ?? 0));
157
+ }),
158
+ cwd: () => process.cwd(),
159
+ stderr: (line) => process.stderr.write(line),
160
+ };
161
+ /**
162
+ * Run the `borg spawn` flow against the given args. Returns the
163
+ * desired process exit code. Pure side-effects flow through `deps`
164
+ * so tests can inject mocks for every external interaction.
165
+ *
166
+ * Flow:
167
+ * 1. Validate name
168
+ * 2. Resolve primary worktree path via `git rev-parse --show-toplevel`
169
+ * (run from the operator's cwd — handles nested worktrees by
170
+ * asking git to find the top, which always points at the current
171
+ * worktree's root; for our naming convention we want the
172
+ * `--git-common-dir` parent which IS the primary worktree's
173
+ * filesystem dir, NOT the current worktree's. Resolve below.)
174
+ * 3. Compute target path; abort if exists
175
+ * 4. Run `git worktree add <target> [<ref>|--detach HEAD]`
176
+ * 5. Print stderr nudge
177
+ * 6. If !noLaunch, exec `borg` inside the new worktree
178
+ */
179
+ export async function runSpawn(args, deps = {}) {
180
+ const { runSync, pathExists, runDetached, cwd, stderr } = {
181
+ ...defaultDeps,
182
+ ...deps,
183
+ };
184
+ // (1) Name validation
185
+ const nameCheck = validateName(args.name);
186
+ if (!nameCheck.ok) {
187
+ stderr(chalk.red(`◼ borg spawn: ${nameCheck.error}\n`));
188
+ return 1;
189
+ }
190
+ // (2) Primary worktree resolution.
191
+ //
192
+ // `git rev-parse --git-common-dir` returns the path to the SHARED
193
+ // `.git` directory (the primary worktree's `.git`). The PRIMARY
194
+ // WORKTREE itself is that directory's parent — which is what we
195
+ // want to use as the basis for the sibling worktree's path. This
196
+ // resolution works correctly even when `borg spawn` is invoked
197
+ // from inside a non-primary worktree (e.g. the operator already
198
+ // cd'd into a sibling drone tree and wants to spin up another).
199
+ const cwdValue = cwd();
200
+ const gitCommonDir = runSync('git', ['rev-parse', '--git-common-dir'], cwdValue);
201
+ if (gitCommonDir.status !== 0) {
202
+ stderr(chalk.red(`◼ borg spawn: not in a git repository (cwd: ${cwdValue})\n`));
203
+ return 1;
204
+ }
205
+ const commonDirRaw = gitCommonDir.stdout.trim();
206
+ // `--git-common-dir` may print a relative path (e.g. `.git`); resolve
207
+ // against cwd to get an absolute reference.
208
+ const commonDirAbs = resolve(cwdValue, commonDirRaw);
209
+ // Strip the trailing `.git` segment to get the primary worktree root.
210
+ // commonDirAbs ends in `/.git` for a regular checkout, or in
211
+ // `/.git/worktrees/<name>` for a non-primary worktree's perspective
212
+ // (but `--common-dir` always returns the SHARED `.git`, so the suffix
213
+ // is just `/.git`). dirname() peels the `.git` segment off.
214
+ const primaryWorktree = basename(commonDirAbs) === '.git' ? dirname(commonDirAbs) : commonDirAbs;
215
+ // (3) Compute + collision-check target path
216
+ const targetPath = computeWorktreePath(primaryWorktree, args.name);
217
+ if (pathExists(targetPath)) {
218
+ stderr(chalk.red(`◼ borg spawn: target path already exists: ${targetPath}\n`));
219
+ return 1;
220
+ }
221
+ // (4) Create the worktree
222
+ const worktreeArgs = args.branch
223
+ ? ['worktree', 'add', targetPath, args.branch]
224
+ : ['worktree', 'add', '--detach', targetPath, 'HEAD'];
225
+ const createResult = runSync('git', worktreeArgs, primaryWorktree);
226
+ if (createResult.status !== 0) {
227
+ const gitErr = createResult.stderr.trim() || createResult.stdout.trim();
228
+ stderr(chalk.red(`◼ borg spawn: git worktree add failed:\n${gitErr}\n`));
229
+ return 1;
230
+ }
231
+ // (5) Stderr nudge.
232
+ //
233
+ // Even though `git worktree add` already prints its own confirmation
234
+ // line, we add a short summary that names the next steps the operator
235
+ // typically wants — particularly the "checkout a branch and pull"
236
+ // reminder for the default detached case, which catches users who
237
+ // would otherwise start work on a stale HEAD without realising.
238
+ stderr(chalk.blue(`◼ Spawned worktree at ${targetPath}\n`));
239
+ if (!args.branch) {
240
+ const shortSha = readShortSha(runSync, targetPath);
241
+ stderr(chalk.gray(`◼ Detached HEAD at ${shortSha}\n`));
242
+ stderr(chalk.gray(`◼ Run \`git checkout main && git pull\` before starting work\n`));
243
+ }
244
+ else {
245
+ stderr(chalk.gray(`◼ Checked out ${args.branch}\n`));
246
+ }
247
+ // (6) Optional drone launch.
248
+ if (args.noLaunch) {
249
+ stderr(chalk.gray(`◼ --no-launch: skipping borg launch\n`));
250
+ stderr(chalk.gray(` cd ${targetPath} && borg\n`));
251
+ return 0;
252
+ }
253
+ stderr(chalk.blue(`◼ Launching Claude Code in ${targetPath}…\n`));
254
+ try {
255
+ const code = await runDetached('borg', [], targetPath);
256
+ return code;
257
+ }
258
+ catch (err) {
259
+ stderr(chalk.red(`◼ borg spawn: failed to launch borg in new worktree: ${err?.message ?? err}\n`));
260
+ return 1;
261
+ }
262
+ }
263
+ /**
264
+ * Best-effort short SHA of the new worktree's HEAD. Used only for the
265
+ * cosmetic "Detached HEAD at <sha>" line; failure here is non-fatal.
266
+ */
267
+ function readShortSha(runSync, worktreePath) {
268
+ const r = runSync('git', ['rev-parse', '--short', 'HEAD'], worktreePath);
269
+ if (r.status === 0)
270
+ return r.stdout.trim();
271
+ return '(unknown)';
272
+ }
273
+ //# sourceMappingURL=spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.js","sourceRoot":"","sources":["../src/spawn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Renderer + inbox-Monitor liveness probe for `borg:stream-status`.
3
+ *
4
+ * Split out from `index.ts` so the 5-state precedence logic and the
5
+ * `pgrep`-based liveness check can be unit-tested without spinning up
6
+ * the MCP server. drone-4's 18:30:51 UX contract is the spec for the
7
+ * rendered output shape; this module is the implementation surface.
8
+ *
9
+ * Top-line states (drone-4 contract):
10
+ * 1. Stream not started.
11
+ * 2. Stream connected, awaiting first content event.
12
+ * 3. Stream connected, last content <X> ago.
13
+ * 4. Stream disconnected (reconnect attempt N).
14
+ * 5. Stream connected (no inbox-Monitor — wake path broken).
15
+ *
16
+ * Precedence when both `disconnected` and `no inbox-Monitor` apply:
17
+ * prefer (4) — wire-disconnect is the upstream cause and resolves
18
+ * automatically when the wire comes back up; State 5 only matters
19
+ * when the wire is healthy but the file-watch isn't.
20
+ */
21
+ import type { StreamStatus } from './log-stream.js';
22
+ /**
23
+ * Best-effort check: is a process tailing this inbox file?
24
+ *
25
+ * Returns:
26
+ * - true: at least one process matches `tail.*<inboxPath>` in pgrep
27
+ * - false: pgrep ran cleanly and found no match
28
+ * - null: cannot determine (pgrep unavailable, spawn error, no inbox path)
29
+ *
30
+ * The null case is informative — it means we don't know, so the
31
+ * renderer must NOT fire State 5 (which would be misleading). State 5
32
+ * only fires when we positively know the wake path is broken.
33
+ *
34
+ * Why `pgrep` and not a more elegant check: Claude Code Monitors are
35
+ * tail-based subprocesses spawned by the harness, completely opaque to
36
+ * the MCP server. The MCP server has no IPC channel into the harness's
37
+ * task table. The cheapest reliable signal we can get from inside the
38
+ * MCP server is "is there a tail subprocess open against this path?"
39
+ * — which is what `pgrep -f` answers.
40
+ *
41
+ * macOS + Linux ship `pgrep`. Windows doesn't (borgmcp targets Mac /
42
+ * Linux per package.json `os` field; the null branch handles other
43
+ * platforms gracefully).
44
+ */
45
+ export declare function checkInboxMonitorHealthy(inboxPath: string | null): boolean | null;
46
+ export interface RenderInputs {
47
+ status: StreamStatus;
48
+ /**
49
+ * Tri-state Monitor liveness: true = healthy, false = wake-path
50
+ * broken, null = cannot determine.
51
+ */
52
+ inboxMonitorHealthy: boolean | null;
53
+ /**
54
+ * Inbox path for the State-5 self-arm instruction. Pass null when
55
+ * unknown (no active cube); State 5 will then surface the failure
56
+ * mode but omit the exact command.
57
+ */
58
+ inboxPath: string | null;
59
+ /** Drone label for the Monitor description copy. */
60
+ droneLabel: string | null;
61
+ /** Cube name for the Monitor description copy. */
62
+ cubeName: string | null;
63
+ /** Relative-time formatter (injected so the renderer is pure). */
64
+ humanAgo: (d: Date) => string;
65
+ }
66
+ /**
67
+ * Render the `borg:stream-status` markdown body per drone-4's 18:30:51
68
+ * contract. Pure function — no I/O, no clock reads. Caller assembles
69
+ * the inputs.
70
+ */
71
+ export declare function renderStreamStatus(inputs: RenderInputs): string;
72
+ //# sourceMappingURL=stream-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-status.d.ts","sourceRoot":"","sources":["../src/stream-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,GAAG,IAAI,GACvB,OAAO,GAAG,IAAI,CAoBhB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB;;;OAGG;IACH,mBAAmB,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC;;;;OAIG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,oDAAoD;IACpD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,kDAAkD;IAClD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kEAAkE;IAClE,QAAQ,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAuG/D"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Renderer + inbox-Monitor liveness probe for `borg:stream-status`.
3
+ *
4
+ * Split out from `index.ts` so the 5-state precedence logic and the
5
+ * `pgrep`-based liveness check can be unit-tested without spinning up
6
+ * the MCP server. drone-4's 18:30:51 UX contract is the spec for the
7
+ * rendered output shape; this module is the implementation surface.
8
+ *
9
+ * Top-line states (drone-4 contract):
10
+ * 1. Stream not started.
11
+ * 2. Stream connected, awaiting first content event.
12
+ * 3. Stream connected, last content <X> ago.
13
+ * 4. Stream disconnected (reconnect attempt N).
14
+ * 5. Stream connected (no inbox-Monitor — wake path broken).
15
+ *
16
+ * Precedence when both `disconnected` and `no inbox-Monitor` apply:
17
+ * prefer (4) — wire-disconnect is the upstream cause and resolves
18
+ * automatically when the wire comes back up; State 5 only matters
19
+ * when the wire is healthy but the file-watch isn't.
20
+ */
21
+ import { spawnSync } from 'node:child_process';
22
+ /**
23
+ * Best-effort check: is a process tailing this inbox file?
24
+ *
25
+ * Returns:
26
+ * - true: at least one process matches `tail.*<inboxPath>` in pgrep
27
+ * - false: pgrep ran cleanly and found no match
28
+ * - null: cannot determine (pgrep unavailable, spawn error, no inbox path)
29
+ *
30
+ * The null case is informative — it means we don't know, so the
31
+ * renderer must NOT fire State 5 (which would be misleading). State 5
32
+ * only fires when we positively know the wake path is broken.
33
+ *
34
+ * Why `pgrep` and not a more elegant check: Claude Code Monitors are
35
+ * tail-based subprocesses spawned by the harness, completely opaque to
36
+ * the MCP server. The MCP server has no IPC channel into the harness's
37
+ * task table. The cheapest reliable signal we can get from inside the
38
+ * MCP server is "is there a tail subprocess open against this path?"
39
+ * — which is what `pgrep -f` answers.
40
+ *
41
+ * macOS + Linux ship `pgrep`. Windows doesn't (borgmcp targets Mac /
42
+ * Linux per package.json `os` field; the null branch handles other
43
+ * platforms gracefully).
44
+ */
45
+ export function checkInboxMonitorHealthy(inboxPath) {
46
+ if (!inboxPath)
47
+ return null;
48
+ try {
49
+ // `-f` matches against the full command line so we catch the
50
+ // `tail -n 0 -F <inboxPath>` form. `-l` lists matches; we only
51
+ // need the exit code (0 = match, 1 = no match) and a sanity check
52
+ // on stdout (some pgrep variants exit 0 with empty stdout under
53
+ // permission errors — treat empty stdout as "no match" for safety).
54
+ const res = spawnSync('pgrep', ['-f', inboxPath], {
55
+ encoding: 'utf-8',
56
+ timeout: 2_000,
57
+ });
58
+ if (res.error)
59
+ return null;
60
+ if (res.status === 0 && res.stdout.trim().length > 0)
61
+ return true;
62
+ if (res.status === 1)
63
+ return false;
64
+ // pgrep exits 2 for syntax error, 3 for fatal — treat as unknown.
65
+ return null;
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }
71
+ /**
72
+ * Render the `borg:stream-status` markdown body per drone-4's 18:30:51
73
+ * contract. Pure function — no I/O, no clock reads. Caller assembles
74
+ * the inputs.
75
+ */
76
+ export function renderStreamStatus(inputs) {
77
+ const { status, inboxMonitorHealthy, inboxPath, droneLabel, cubeName, humanAgo } = inputs;
78
+ const isNotStarted = status.reconnectAttempts === 0 &&
79
+ status.lastWireActivityAt === null &&
80
+ !status.connected;
81
+ // Top-line verdict — 5 states + override per drone-4 contract.
82
+ // Precedence: disconnected > no-inbox-Monitor (wire-down upstream
83
+ // cause; State 5 only applies when wire is healthy).
84
+ let summary;
85
+ if (isNotStarted) {
86
+ summary = '**Stream not started.**';
87
+ }
88
+ else if (!status.connected) {
89
+ summary = `**Stream disconnected (reconnect attempt ${status.reconnectAttempts}).**`;
90
+ }
91
+ else if (inboxMonitorHealthy === false) {
92
+ summary = '**Stream connected (no inbox-Monitor — wake path broken).**';
93
+ }
94
+ else if (status.lastContentEventAt === null) {
95
+ // State 2: wire works, no content yet. Collapses two underlying
96
+ // conditions per drone-4 contract — fresh connect pre-first-content
97
+ // and quiet cube post-reconnect. The body's heartbeat field
98
+ // distinguishes them (populated vs `_(none)_`).
99
+ summary = '**Stream connected, awaiting first content event.**';
100
+ }
101
+ else {
102
+ summary = `**Stream connected, last content ${humanAgo(new Date(status.lastContentEventAt))}.**`;
103
+ }
104
+ const lines = [];
105
+ lines.push(summary);
106
+ lines.push('');
107
+ lines.push('# Log-stream status');
108
+ lines.push('');
109
+ if (isNotStarted) {
110
+ lines.push('- **state**: _(stream not started)_');
111
+ }
112
+ else {
113
+ lines.push(`- **connected**: ${status.connected}`);
114
+ }
115
+ // Body shape per drone-4 contract: three timestamp lines (content,
116
+ // heartbeat, wire) — looks redundant in the common case where they
117
+ // coincide, but the asymmetric "content quiet, heartbeats alive" case
118
+ // is exactly the diagnostic scenario this surface exists to support.
119
+ lines.push(`- **last content event**: ${status.lastContentEventAt
120
+ ? `${status.lastContentEventAt} (${humanAgo(new Date(status.lastContentEventAt))})`
121
+ : '_(none yet)_'}`);
122
+ lines.push(`- **last heartbeat at**: ${status.lastHeartbeatAt
123
+ ? `${status.lastHeartbeatAt} (${humanAgo(new Date(status.lastHeartbeatAt))})`
124
+ : '_(none)_'}`);
125
+ lines.push(`- **last wire activity**: ${status.lastWireActivityAt
126
+ ? `${status.lastWireActivityAt} (${humanAgo(new Date(status.lastWireActivityAt))})`
127
+ : '_(none)_'}`);
128
+ lines.push(`- **last persisted event id**: ${status.lastPersistedEventId ?? '_(none)_'}`);
129
+ lines.push(`- **reconnect attempts**: ${status.reconnectAttempts}`);
130
+ // State-5 body line + self-arm instruction. Only fires when we
131
+ // POSITIVELY detected wake-path breakage AND the wire is up — the
132
+ // disconnected case takes precedence above and would never reach
133
+ // here. When `inboxMonitorHealthy === null` (couldn't determine) we
134
+ // stay silent; surfacing an uncertain failure mode is worse UX than
135
+ // omitting it.
136
+ if (status.connected && inboxMonitorHealthy === false) {
137
+ lines.push(`- **inbox-monitor**: _(no watcher detected — wake path broken)_`);
138
+ if (inboxPath && droneLabel && cubeName) {
139
+ lines.push('');
140
+ lines.push('## Real-time wake-up (do this now)');
141
+ lines.push('No process is tailing this drone\'s inbox file — this session won\'t wake on real-time cube activity, only on its fallback timer, and will miss live coordination from other drones. Arm an inbox Monitor:');
142
+ lines.push('');
143
+ lines.push(`> Monitor command: \`tail -n 0 -F ${inboxPath}\` — persistent, 1h timeout, description "borg inbox for ${droneLabel} on cube ${cubeName}".`);
144
+ }
145
+ }
146
+ return lines.join('\n');
147
+ }
148
+ //# sourceMappingURL=stream-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-status.js","sourceRoot":"","sources":["../src/stream-status.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAkGD,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAE9C,CAAC;AAEF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAEzD;AAED,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAE5C"}
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AA8JD,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAE9C,CAAC;AAEF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAEzD;AAED,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAE5C"}