@mu-crew/mu 4.1.1 → 4.2.0
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/{chunk-B74N2EAS.js → chunk-3ZLI6YTV.js} +8 -4
- package/dist/chunk-3ZLI6YTV.js.map +1 -0
- package/dist/{chunk-DEYBQDTO.js → chunk-RVWNQLFE.js} +2 -2
- package/dist/{chunk-L7I3BLXP.js → chunk-SFV5RPZW.js} +1512 -411
- package/dist/chunk-SFV5RPZW.js.map +1 -0
- package/dist/{chunk-LBBZAG5C.js → chunk-UL2QE43S.js} +20 -20
- package/dist/chunk-UL2QE43S.js.map +1 -0
- package/dist/{cli-H2PWJAJN.js → cli-72EJ3CKW.js} +146 -31
- package/dist/cli-72EJ3CKW.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/{errors-G5IVXSMY.js → errors-LY4OZVQU.js} +8 -2
- package/dist/extension/mu-pi.js +1 -1
- package/dist/index.d.ts +2554 -2277
- package/dist/index.js +58 -4
- package/dist/index.js.map +1 -1
- package/dist/{tui-EN2CDP6G.js → tui-3ZPLSLDW.js} +13 -14
- package/dist/tui-3ZPLSLDW.js.map +1 -0
- package/docs/ARCHITECTURE.md +15 -8
- package/docs/VOCABULARY.md +14 -6
- package/docs/guide/remote.md +113 -4
- package/docs/guide/sql.md +1 -1
- package/docs/reference/env.md +1 -0
- package/package.json +1 -1
- package/skills/mu/recipes/remote-workers.md +7 -6
- package/dist/chunk-B74N2EAS.js.map +0 -1
- package/dist/chunk-L7I3BLXP.js.map +0 -1
- package/dist/chunk-LBBZAG5C.js.map +0 -1
- package/dist/cli-H2PWJAJN.js.map +0 -1
- package/dist/tui-EN2CDP6G.js.map +0 -1
- /package/dist/{chunk-DEYBQDTO.js.map → chunk-RVWNQLFE.js.map} +0 -0
- /package/dist/{errors-G5IVXSMY.js.map → errors-LY4OZVQU.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/cli-table3/src/debug.js","../node_modules/cli-table3/node_modules/ansi-regex/index.js","../node_modules/cli-table3/node_modules/strip-ansi/index.js","../node_modules/cli-table3/node_modules/is-fullwidth-code-point/index.js","../node_modules/emoji-regex/index.js","../node_modules/cli-table3/node_modules/string-width/index.js","../node_modules/cli-table3/src/utils.js","../node_modules/@colors/colors/lib/styles.js","../node_modules/@colors/colors/lib/system/has-flag.js","../node_modules/@colors/colors/lib/system/supports-colors.js","../node_modules/@colors/colors/lib/custom/trap.js","../node_modules/@colors/colors/lib/custom/zalgo.js","../node_modules/@colors/colors/lib/maps/america.js","../node_modules/@colors/colors/lib/maps/zebra.js","../node_modules/@colors/colors/lib/maps/rainbow.js","../node_modules/@colors/colors/lib/maps/random.js","../node_modules/@colors/colors/lib/colors.js","../node_modules/@colors/colors/safe.js","../node_modules/cli-table3/src/cell.js","../node_modules/cli-table3/src/layout-manager.js","../node_modules/cli-table3/src/table.js","../node_modules/cli-table3/index.js","../node_modules/picocolors/picocolors.js","../src/messages.ts","../src/agents/spawn.ts","../src/agents.ts","../src/agent-state.ts","../src/agents/transport.ts","../src/ctl/client.ts","../src/ctl/protocol.ts","../src/ctl/path.ts","../src/db.ts","../src/capture.ts","../src/db-recovery.ts","../src/tasks/status.ts","../src/logs.ts","../src/hlc.ts","../src/segment-line.ts","../src/mux.ts","../src/exec-file.ts","../node_modules/signal-exit/src/signals.ts","../node_modules/signal-exit/src/index.ts","../src/output.ts","../src/mux/tmux.ts","../src/shell-quote.ts","../src/mux/types.ts","../src/mux/herdr.ts","../src/mux/detect.ts","../src/tmux.ts","../src/hosts.ts","../src/op-context.ts","../src/agents/reap.ts","../src/reconcile.ts","../src/revision.ts","../src/tasks/errors.ts","../src/tasks/core.ts","../src/tasks/queries.ts","../src/tasks/edges.ts","../src/workstream.ts","../src/compact.ts","../src/worktree.ts","../src/vcs/git.ts","../src/tasks/id.ts","../src/tasks/edit.ts","../src/tasks/lifecycle.ts","../src/tasks/claim.ts","../src/agents/abort.ts","../src/remote-agent.ts","../src/remote-recovery.ts","../src/wait-cursor.ts","../src/compare.ts","../src/wait-registration.ts","../src/wait-owed.ts","../src/agents/close-recovery.ts","../src/agents/gate.ts","../src/agents/lock.ts","../src/file-lock.ts","../src/agents/close.ts","../src/agents/delegate.ts","../src/agents/observe.ts","../src/delegates.ts","../src/delegate-verdict.ts","../src/agents/receipts.ts","../src/agents/task-spawn.ts","../src/agents/spawn-lock.ts","../src/agents/staging.ts","../src/agents/errors.ts"],"sourcesContent":["let messages = [];\nlet level = 0;\n\nconst debug = (msg, min) => {\n if (level >= min) {\n messages.push(msg);\n }\n};\n\ndebug.WARN = 1;\ndebug.INFO = 2;\ndebug.DEBUG = 3;\n\ndebug.reset = () => {\n messages = [];\n};\n\ndebug.setDebugLevel = (v) => {\n level = v;\n};\n\ndebug.warn = (msg) => debug(msg, debug.WARN);\ndebug.info = (msg) => debug(msg, debug.INFO);\ndebug.debug = (msg) => debug(msg, debug.DEBUG);\n\ndebug.debugMessages = () => messages;\n\nmodule.exports = debug;\n","'use strict';\n\nmodule.exports = ({onlyFirst = false} = {}) => {\n\tconst pattern = [\n\t\t'[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]+)*|[a-zA-Z\\\\d]+(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]*)*)?\\\\u0007)',\n\t\t'(?:(?:\\\\d{1,4}(?:;\\\\d{0,4})*)?[\\\\dA-PR-TZcf-ntqry=><~]))'\n\t].join('|');\n\n\treturn new RegExp(pattern, onlyFirst ? undefined : 'g');\n};\n","'use strict';\nconst ansiRegex = require('ansi-regex');\n\nmodule.exports = string => typeof string === 'string' ? string.replace(ansiRegex(), '') : string;\n","/* eslint-disable yoda */\n'use strict';\n\nconst isFullwidthCodePoint = codePoint => {\n\tif (Number.isNaN(codePoint)) {\n\t\treturn false;\n\t}\n\n\t// Code points are derived from:\n\t// http://www.unix.org/Public/UNIDATA/EastAsianWidth.txt\n\tif (\n\t\tcodePoint >= 0x1100 && (\n\t\t\tcodePoint <= 0x115F || // Hangul Jamo\n\t\t\tcodePoint === 0x2329 || // LEFT-POINTING ANGLE BRACKET\n\t\t\tcodePoint === 0x232A || // RIGHT-POINTING ANGLE BRACKET\n\t\t\t// CJK Radicals Supplement .. Enclosed CJK Letters and Months\n\t\t\t(0x2E80 <= codePoint && codePoint <= 0x3247 && codePoint !== 0x303F) ||\n\t\t\t// Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A\n\t\t\t(0x3250 <= codePoint && codePoint <= 0x4DBF) ||\n\t\t\t// CJK Unified Ideographs .. Yi Radicals\n\t\t\t(0x4E00 <= codePoint && codePoint <= 0xA4C6) ||\n\t\t\t// Hangul Jamo Extended-A\n\t\t\t(0xA960 <= codePoint && codePoint <= 0xA97C) ||\n\t\t\t// Hangul Syllables\n\t\t\t(0xAC00 <= codePoint && codePoint <= 0xD7A3) ||\n\t\t\t// CJK Compatibility Ideographs\n\t\t\t(0xF900 <= codePoint && codePoint <= 0xFAFF) ||\n\t\t\t// Vertical Forms\n\t\t\t(0xFE10 <= codePoint && codePoint <= 0xFE19) ||\n\t\t\t// CJK Compatibility Forms .. Small Form Variants\n\t\t\t(0xFE30 <= codePoint && codePoint <= 0xFE6B) ||\n\t\t\t// Halfwidth and Fullwidth Forms\n\t\t\t(0xFF01 <= codePoint && codePoint <= 0xFF60) ||\n\t\t\t(0xFFE0 <= codePoint && codePoint <= 0xFFE6) ||\n\t\t\t// Kana Supplement\n\t\t\t(0x1B000 <= codePoint && codePoint <= 0x1B001) ||\n\t\t\t// Enclosed Ideographic Supplement\n\t\t\t(0x1F200 <= codePoint && codePoint <= 0x1F251) ||\n\t\t\t// CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane\n\t\t\t(0x20000 <= codePoint && codePoint <= 0x3FFFD)\n\t\t)\n\t) {\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\nmodule.exports = isFullwidthCodePoint;\nmodule.exports.default = isFullwidthCodePoint;\n","\"use strict\";\n\nmodule.exports = function () {\n // https://mths.be/emoji\n return /\\uD83C\\uDFF4\\uDB40\\uDC67\\uDB40\\uDC62(?:\\uDB40\\uDC65\\uDB40\\uDC6E\\uDB40\\uDC67|\\uDB40\\uDC73\\uDB40\\uDC63\\uDB40\\uDC74|\\uDB40\\uDC77\\uDB40\\uDC6C\\uDB40\\uDC73)\\uDB40\\uDC7F|\\uD83D\\uDC68(?:\\uD83C\\uDFFC\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C\\uDFFB|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFF\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB-\\uDFFE])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFE\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB-\\uDFFD])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFD\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB\\uDFFC])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\u200D(?:\\u2764\\uFE0F\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83D\\uDC68|(?:\\uD83D[\\uDC68\\uDC69])\\u200D(?:\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC67\\u200D(?:\\uD83D[\\uDC66\\uDC67]))|\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC67\\u200D(?:\\uD83D[\\uDC66\\uDC67])|(?:\\uD83D[\\uDC68\\uDC69])\\u200D(?:\\uD83D[\\uDC66\\uDC67])|[\\u2695\\u2696\\u2708]\\uFE0F|\\uD83D[\\uDC66\\uDC67]|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|(?:\\uD83C\\uDFFB\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFF\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFE\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFD\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFC\\u200D[\\u2695\\u2696\\u2708])\\uFE0F|\\uD83C\\uDFFB\\u200D(?:\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C[\\uDFFB-\\uDFFF])|(?:\\uD83E\\uDDD1\\uD83C\\uDFFB\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1|\\uD83D\\uDC69\\uD83C\\uDFFC\\u200D\\uD83E\\uDD1D\\u200D\\uD83D\\uDC69)\\uD83C\\uDFFB|\\uD83E\\uDDD1(?:\\uD83C\\uDFFF\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1(?:\\uD83C[\\uDFFB-\\uDFFF])|\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1)|(?:\\uD83E\\uDDD1\\uD83C\\uDFFE\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1|\\uD83D\\uDC69\\uD83C\\uDFFF\\u200D\\uD83E\\uDD1D\\u200D(?:\\uD83D[\\uDC68\\uDC69]))(?:\\uD83C[\\uDFFB-\\uDFFE])|(?:\\uD83E\\uDDD1\\uD83C\\uDFFC\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1|\\uD83D\\uDC69\\uD83C\\uDFFD\\u200D\\uD83E\\uDD1D\\u200D\\uD83D\\uDC69)(?:\\uD83C[\\uDFFB\\uDFFC])|\\uD83D\\uDC69(?:\\uD83C\\uDFFE\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB-\\uDFFD\\uDFFF])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFC\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB\\uDFFD-\\uDFFF])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFB\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFC-\\uDFFF])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFD\\u200D(?:\\uD83E\\uDD1D\\u200D\\uD83D\\uDC68(?:\\uD83C[\\uDFFB\\uDFFC\\uDFFE\\uDFFF])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\u200D(?:\\u2764\\uFE0F\\u200D(?:\\uD83D\\uDC8B\\u200D(?:\\uD83D[\\uDC68\\uDC69])|\\uD83D[\\uDC68\\uDC69])|\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD])|\\uD83C\\uDFFF\\u200D(?:\\uD83C[\\uDF3E\\uDF73\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E[\\uDDAF-\\uDDB3\\uDDBC\\uDDBD]))|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D(?:\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC67\\u200D(?:\\uD83D[\\uDC66\\uDC67]))|(?:\\uD83E\\uDDD1\\uD83C\\uDFFD\\u200D\\uD83E\\uDD1D\\u200D\\uD83E\\uDDD1|\\uD83D\\uDC69\\uD83C\\uDFFE\\u200D\\uD83E\\uDD1D\\u200D\\uD83D\\uDC69)(?:\\uD83C[\\uDFFB-\\uDFFD])|\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D(?:\\uD83D[\\uDC66\\uDC67])|(?:\\uD83D\\uDC41\\uFE0F\\u200D\\uD83D\\uDDE8|\\uD83D\\uDC69(?:\\uD83C\\uDFFF\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFE\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFC\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFB\\u200D[\\u2695\\u2696\\u2708]|\\uD83C\\uDFFD\\u200D[\\u2695\\u2696\\u2708]|\\u200D[\\u2695\\u2696\\u2708])|(?:(?:\\u26F9|\\uD83C[\\uDFCB\\uDFCC]|\\uD83D\\uDD75)\\uFE0F|\\uD83D\\uDC6F|\\uD83E[\\uDD3C\\uDDDE\\uDDDF])\\u200D[\\u2640\\u2642]|(?:\\u26F9|\\uD83C[\\uDFCB\\uDFCC]|\\uD83D\\uDD75)(?:\\uD83C[\\uDFFB-\\uDFFF])\\u200D[\\u2640\\u2642]|(?:\\uD83C[\\uDFC3\\uDFC4\\uDFCA]|\\uD83D[\\uDC6E\\uDC71\\uDC73\\uDC77\\uDC81\\uDC82\\uDC86\\uDC87\\uDE45-\\uDE47\\uDE4B\\uDE4D\\uDE4E\\uDEA3\\uDEB4-\\uDEB6]|\\uD83E[\\uDD26\\uDD37-\\uDD39\\uDD3D\\uDD3E\\uDDB8\\uDDB9\\uDDCD-\\uDDCF\\uDDD6-\\uDDDD])(?:(?:\\uD83C[\\uDFFB-\\uDFFF])\\u200D[\\u2640\\u2642]|\\u200D[\\u2640\\u2642])|\\uD83C\\uDFF4\\u200D\\u2620)\\uFE0F|\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D(?:\\uD83D[\\uDC66\\uDC67])|\\uD83C\\uDFF3\\uFE0F\\u200D\\uD83C\\uDF08|\\uD83D\\uDC15\\u200D\\uD83E\\uDDBA|\\uD83D\\uDC69\\u200D\\uD83D\\uDC66|\\uD83D\\uDC69\\u200D\\uD83D\\uDC67|\\uD83C\\uDDFD\\uD83C\\uDDF0|\\uD83C\\uDDF4\\uD83C\\uDDF2|\\uD83C\\uDDF6\\uD83C\\uDDE6|[#\\*0-9]\\uFE0F\\u20E3|\\uD83C\\uDDE7(?:\\uD83C[\\uDDE6\\uDDE7\\uDDE9-\\uDDEF\\uDDF1-\\uDDF4\\uDDF6-\\uDDF9\\uDDFB\\uDDFC\\uDDFE\\uDDFF])|\\uD83C\\uDDF9(?:\\uD83C[\\uDDE6\\uDDE8\\uDDE9\\uDDEB-\\uDDED\\uDDEF-\\uDDF4\\uDDF7\\uDDF9\\uDDFB\\uDDFC\\uDDFF])|\\uD83C\\uDDEA(?:\\uD83C[\\uDDE6\\uDDE8\\uDDEA\\uDDEC\\uDDED\\uDDF7-\\uDDFA])|\\uD83E\\uDDD1(?:\\uD83C[\\uDFFB-\\uDFFF])|\\uD83C\\uDDF7(?:\\uD83C[\\uDDEA\\uDDF4\\uDDF8\\uDDFA\\uDDFC])|\\uD83D\\uDC69(?:\\uD83C[\\uDFFB-\\uDFFF])|\\uD83C\\uDDF2(?:\\uD83C[\\uDDE6\\uDDE8-\\uDDED\\uDDF0-\\uDDFF])|\\uD83C\\uDDE6(?:\\uD83C[\\uDDE8-\\uDDEC\\uDDEE\\uDDF1\\uDDF2\\uDDF4\\uDDF6-\\uDDFA\\uDDFC\\uDDFD\\uDDFF])|\\uD83C\\uDDF0(?:\\uD83C[\\uDDEA\\uDDEC-\\uDDEE\\uDDF2\\uDDF3\\uDDF5\\uDDF7\\uDDFC\\uDDFE\\uDDFF])|\\uD83C\\uDDED(?:\\uD83C[\\uDDF0\\uDDF2\\uDDF3\\uDDF7\\uDDF9\\uDDFA])|\\uD83C\\uDDE9(?:\\uD83C[\\uDDEA\\uDDEC\\uDDEF\\uDDF0\\uDDF2\\uDDF4\\uDDFF])|\\uD83C\\uDDFE(?:\\uD83C[\\uDDEA\\uDDF9])|\\uD83C\\uDDEC(?:\\uD83C[\\uDDE6\\uDDE7\\uDDE9-\\uDDEE\\uDDF1-\\uDDF3\\uDDF5-\\uDDFA\\uDDFC\\uDDFE])|\\uD83C\\uDDF8(?:\\uD83C[\\uDDE6-\\uDDEA\\uDDEC-\\uDDF4\\uDDF7-\\uDDF9\\uDDFB\\uDDFD-\\uDDFF])|\\uD83C\\uDDEB(?:\\uD83C[\\uDDEE-\\uDDF0\\uDDF2\\uDDF4\\uDDF7])|\\uD83C\\uDDF5(?:\\uD83C[\\uDDE6\\uDDEA-\\uDDED\\uDDF0-\\uDDF3\\uDDF7-\\uDDF9\\uDDFC\\uDDFE])|\\uD83C\\uDDFB(?:\\uD83C[\\uDDE6\\uDDE8\\uDDEA\\uDDEC\\uDDEE\\uDDF3\\uDDFA])|\\uD83C\\uDDF3(?:\\uD83C[\\uDDE6\\uDDE8\\uDDEA-\\uDDEC\\uDDEE\\uDDF1\\uDDF4\\uDDF5\\uDDF7\\uDDFA\\uDDFF])|\\uD83C\\uDDE8(?:\\uD83C[\\uDDE6\\uDDE8\\uDDE9\\uDDEB-\\uDDEE\\uDDF0-\\uDDF5\\uDDF7\\uDDFA-\\uDDFF])|\\uD83C\\uDDF1(?:\\uD83C[\\uDDE6-\\uDDE8\\uDDEE\\uDDF0\\uDDF7-\\uDDFB\\uDDFE])|\\uD83C\\uDDFF(?:\\uD83C[\\uDDE6\\uDDF2\\uDDFC])|\\uD83C\\uDDFC(?:\\uD83C[\\uDDEB\\uDDF8])|\\uD83C\\uDDFA(?:\\uD83C[\\uDDE6\\uDDEC\\uDDF2\\uDDF3\\uDDF8\\uDDFE\\uDDFF])|\\uD83C\\uDDEE(?:\\uD83C[\\uDDE8-\\uDDEA\\uDDF1-\\uDDF4\\uDDF6-\\uDDF9])|\\uD83C\\uDDEF(?:\\uD83C[\\uDDEA\\uDDF2\\uDDF4\\uDDF5])|(?:\\uD83C[\\uDFC3\\uDFC4\\uDFCA]|\\uD83D[\\uDC6E\\uDC71\\uDC73\\uDC77\\uDC81\\uDC82\\uDC86\\uDC87\\uDE45-\\uDE47\\uDE4B\\uDE4D\\uDE4E\\uDEA3\\uDEB4-\\uDEB6]|\\uD83E[\\uDD26\\uDD37-\\uDD39\\uDD3D\\uDD3E\\uDDB8\\uDDB9\\uDDCD-\\uDDCF\\uDDD6-\\uDDDD])(?:\\uD83C[\\uDFFB-\\uDFFF])|(?:\\u26F9|\\uD83C[\\uDFCB\\uDFCC]|\\uD83D\\uDD75)(?:\\uD83C[\\uDFFB-\\uDFFF])|(?:[\\u261D\\u270A-\\u270D]|\\uD83C[\\uDF85\\uDFC2\\uDFC7]|\\uD83D[\\uDC42\\uDC43\\uDC46-\\uDC50\\uDC66\\uDC67\\uDC6B-\\uDC6D\\uDC70\\uDC72\\uDC74-\\uDC76\\uDC78\\uDC7C\\uDC83\\uDC85\\uDCAA\\uDD74\\uDD7A\\uDD90\\uDD95\\uDD96\\uDE4C\\uDE4F\\uDEC0\\uDECC]|\\uD83E[\\uDD0F\\uDD18-\\uDD1C\\uDD1E\\uDD1F\\uDD30-\\uDD36\\uDDB5\\uDDB6\\uDDBB\\uDDD2-\\uDDD5])(?:\\uD83C[\\uDFFB-\\uDFFF])|(?:[\\u231A\\u231B\\u23E9-\\u23EC\\u23F0\\u23F3\\u25FD\\u25FE\\u2614\\u2615\\u2648-\\u2653\\u267F\\u2693\\u26A1\\u26AA\\u26AB\\u26BD\\u26BE\\u26C4\\u26C5\\u26CE\\u26D4\\u26EA\\u26F2\\u26F3\\u26F5\\u26FA\\u26FD\\u2705\\u270A\\u270B\\u2728\\u274C\\u274E\\u2753-\\u2755\\u2757\\u2795-\\u2797\\u27B0\\u27BF\\u2B1B\\u2B1C\\u2B50\\u2B55]|\\uD83C[\\uDC04\\uDCCF\\uDD8E\\uDD91-\\uDD9A\\uDDE6-\\uDDFF\\uDE01\\uDE1A\\uDE2F\\uDE32-\\uDE36\\uDE38-\\uDE3A\\uDE50\\uDE51\\uDF00-\\uDF20\\uDF2D-\\uDF35\\uDF37-\\uDF7C\\uDF7E-\\uDF93\\uDFA0-\\uDFCA\\uDFCF-\\uDFD3\\uDFE0-\\uDFF0\\uDFF4\\uDFF8-\\uDFFF]|\\uD83D[\\uDC00-\\uDC3E\\uDC40\\uDC42-\\uDCFC\\uDCFF-\\uDD3D\\uDD4B-\\uDD4E\\uDD50-\\uDD67\\uDD7A\\uDD95\\uDD96\\uDDA4\\uDDFB-\\uDE4F\\uDE80-\\uDEC5\\uDECC\\uDED0-\\uDED2\\uDED5\\uDEEB\\uDEEC\\uDEF4-\\uDEFA\\uDFE0-\\uDFEB]|\\uD83E[\\uDD0D-\\uDD3A\\uDD3C-\\uDD45\\uDD47-\\uDD71\\uDD73-\\uDD76\\uDD7A-\\uDDA2\\uDDA5-\\uDDAA\\uDDAE-\\uDDCA\\uDDCD-\\uDDFF\\uDE70-\\uDE73\\uDE78-\\uDE7A\\uDE80-\\uDE82\\uDE90-\\uDE95])|(?:[#\\*0-9\\xA9\\xAE\\u203C\\u2049\\u2122\\u2139\\u2194-\\u2199\\u21A9\\u21AA\\u231A\\u231B\\u2328\\u23CF\\u23E9-\\u23F3\\u23F8-\\u23FA\\u24C2\\u25AA\\u25AB\\u25B6\\u25C0\\u25FB-\\u25FE\\u2600-\\u2604\\u260E\\u2611\\u2614\\u2615\\u2618\\u261D\\u2620\\u2622\\u2623\\u2626\\u262A\\u262E\\u262F\\u2638-\\u263A\\u2640\\u2642\\u2648-\\u2653\\u265F\\u2660\\u2663\\u2665\\u2666\\u2668\\u267B\\u267E\\u267F\\u2692-\\u2697\\u2699\\u269B\\u269C\\u26A0\\u26A1\\u26AA\\u26AB\\u26B0\\u26B1\\u26BD\\u26BE\\u26C4\\u26C5\\u26C8\\u26CE\\u26CF\\u26D1\\u26D3\\u26D4\\u26E9\\u26EA\\u26F0-\\u26F5\\u26F7-\\u26FA\\u26FD\\u2702\\u2705\\u2708-\\u270D\\u270F\\u2712\\u2714\\u2716\\u271D\\u2721\\u2728\\u2733\\u2734\\u2744\\u2747\\u274C\\u274E\\u2753-\\u2755\\u2757\\u2763\\u2764\\u2795-\\u2797\\u27A1\\u27B0\\u27BF\\u2934\\u2935\\u2B05-\\u2B07\\u2B1B\\u2B1C\\u2B50\\u2B55\\u3030\\u303D\\u3297\\u3299]|\\uD83C[\\uDC04\\uDCCF\\uDD70\\uDD71\\uDD7E\\uDD7F\\uDD8E\\uDD91-\\uDD9A\\uDDE6-\\uDDFF\\uDE01\\uDE02\\uDE1A\\uDE2F\\uDE32-\\uDE3A\\uDE50\\uDE51\\uDF00-\\uDF21\\uDF24-\\uDF93\\uDF96\\uDF97\\uDF99-\\uDF9B\\uDF9E-\\uDFF0\\uDFF3-\\uDFF5\\uDFF7-\\uDFFF]|\\uD83D[\\uDC00-\\uDCFD\\uDCFF-\\uDD3D\\uDD49-\\uDD4E\\uDD50-\\uDD67\\uDD6F\\uDD70\\uDD73-\\uDD7A\\uDD87\\uDD8A-\\uDD8D\\uDD90\\uDD95\\uDD96\\uDDA4\\uDDA5\\uDDA8\\uDDB1\\uDDB2\\uDDBC\\uDDC2-\\uDDC4\\uDDD1-\\uDDD3\\uDDDC-\\uDDDE\\uDDE1\\uDDE3\\uDDE8\\uDDEF\\uDDF3\\uDDFA-\\uDE4F\\uDE80-\\uDEC5\\uDECB-\\uDED2\\uDED5\\uDEE0-\\uDEE5\\uDEE9\\uDEEB\\uDEEC\\uDEF0\\uDEF3-\\uDEFA\\uDFE0-\\uDFEB]|\\uD83E[\\uDD0D-\\uDD3A\\uDD3C-\\uDD45\\uDD47-\\uDD71\\uDD73-\\uDD76\\uDD7A-\\uDDA2\\uDDA5-\\uDDAA\\uDDAE-\\uDDCA\\uDDCD-\\uDDFF\\uDE70-\\uDE73\\uDE78-\\uDE7A\\uDE80-\\uDE82\\uDE90-\\uDE95])\\uFE0F|(?:[\\u261D\\u26F9\\u270A-\\u270D]|\\uD83C[\\uDF85\\uDFC2-\\uDFC4\\uDFC7\\uDFCA-\\uDFCC]|\\uD83D[\\uDC42\\uDC43\\uDC46-\\uDC50\\uDC66-\\uDC78\\uDC7C\\uDC81-\\uDC83\\uDC85-\\uDC87\\uDC8F\\uDC91\\uDCAA\\uDD74\\uDD75\\uDD7A\\uDD90\\uDD95\\uDD96\\uDE45-\\uDE47\\uDE4B-\\uDE4F\\uDEA3\\uDEB4-\\uDEB6\\uDEC0\\uDECC]|\\uD83E[\\uDD0F\\uDD18-\\uDD1F\\uDD26\\uDD30-\\uDD39\\uDD3C-\\uDD3E\\uDDB5\\uDDB6\\uDDB8\\uDDB9\\uDDBB\\uDDCD-\\uDDCF\\uDDD1-\\uDDDD])/g;\n};\n","'use strict';\nconst stripAnsi = require('strip-ansi');\nconst isFullwidthCodePoint = require('is-fullwidth-code-point');\nconst emojiRegex = require('emoji-regex');\n\nconst stringWidth = string => {\n\tif (typeof string !== 'string' || string.length === 0) {\n\t\treturn 0;\n\t}\n\n\tstring = stripAnsi(string);\n\n\tif (string.length === 0) {\n\t\treturn 0;\n\t}\n\n\tstring = string.replace(emojiRegex(), ' ');\n\n\tlet width = 0;\n\n\tfor (let i = 0; i < string.length; i++) {\n\t\tconst code = string.codePointAt(i);\n\n\t\t// Ignore control characters\n\t\tif (code <= 0x1F || (code >= 0x7F && code <= 0x9F)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Ignore combining characters\n\t\tif (code >= 0x300 && code <= 0x36F) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Surrogates\n\t\tif (code > 0xFFFF) {\n\t\t\ti++;\n\t\t}\n\n\t\twidth += isFullwidthCodePoint(code) ? 2 : 1;\n\t}\n\n\treturn width;\n};\n\nmodule.exports = stringWidth;\n// TODO: remove this in the next major version\nmodule.exports.default = stringWidth;\n","const stringWidth = require('string-width');\n\nfunction codeRegex(capture) {\n return capture ? /\\u001b\\[((?:\\d*;){0,5}\\d*)m/g : /\\u001b\\[(?:\\d*;){0,5}\\d*m/g;\n}\n\nfunction strlen(str) {\n let code = codeRegex();\n let stripped = ('' + str).replace(code, '');\n let split = stripped.split('\\n');\n return split.reduce(function (memo, s) {\n return stringWidth(s) > memo ? stringWidth(s) : memo;\n }, 0);\n}\n\nfunction repeat(str, times) {\n return Array(times + 1).join(str);\n}\n\nfunction pad(str, len, pad, dir) {\n let length = strlen(str);\n if (len + 1 >= length) {\n let padlen = len - length;\n switch (dir) {\n case 'right': {\n str = repeat(pad, padlen) + str;\n break;\n }\n case 'center': {\n let right = Math.ceil(padlen / 2);\n let left = padlen - right;\n str = repeat(pad, left) + str + repeat(pad, right);\n break;\n }\n default: {\n str = str + repeat(pad, padlen);\n break;\n }\n }\n }\n return str;\n}\n\nlet codeCache = {};\n\nfunction addToCodeCache(name, on, off) {\n on = '\\u001b[' + on + 'm';\n off = '\\u001b[' + off + 'm';\n codeCache[on] = { set: name, to: true };\n codeCache[off] = { set: name, to: false };\n codeCache[name] = { on: on, off: off };\n}\n\n//https://github.com/Marak/colors.js/blob/master/lib/styles.js\naddToCodeCache('bold', 1, 22);\naddToCodeCache('italics', 3, 23);\naddToCodeCache('underline', 4, 24);\naddToCodeCache('inverse', 7, 27);\naddToCodeCache('strikethrough', 9, 29);\n\nfunction updateState(state, controlChars) {\n let controlCode = controlChars[1] ? parseInt(controlChars[1].split(';')[0]) : 0;\n if ((controlCode >= 30 && controlCode <= 39) || (controlCode >= 90 && controlCode <= 97)) {\n state.lastForegroundAdded = controlChars[0];\n return;\n }\n if ((controlCode >= 40 && controlCode <= 49) || (controlCode >= 100 && controlCode <= 107)) {\n state.lastBackgroundAdded = controlChars[0];\n return;\n }\n if (controlCode === 0) {\n for (let i in state) {\n /* istanbul ignore else */\n if (Object.prototype.hasOwnProperty.call(state, i)) {\n delete state[i];\n }\n }\n return;\n }\n let info = codeCache[controlChars[0]];\n if (info) {\n state[info.set] = info.to;\n }\n}\n\nfunction readState(line) {\n let code = codeRegex(true);\n let controlChars = code.exec(line);\n let state = {};\n while (controlChars !== null) {\n updateState(state, controlChars);\n controlChars = code.exec(line);\n }\n return state;\n}\n\nfunction unwindState(state, ret) {\n let lastBackgroundAdded = state.lastBackgroundAdded;\n let lastForegroundAdded = state.lastForegroundAdded;\n\n delete state.lastBackgroundAdded;\n delete state.lastForegroundAdded;\n\n Object.keys(state).forEach(function (key) {\n if (state[key]) {\n ret += codeCache[key].off;\n }\n });\n\n if (lastBackgroundAdded && lastBackgroundAdded != '\\u001b[49m') {\n ret += '\\u001b[49m';\n }\n if (lastForegroundAdded && lastForegroundAdded != '\\u001b[39m') {\n ret += '\\u001b[39m';\n }\n\n return ret;\n}\n\nfunction rewindState(state, ret) {\n let lastBackgroundAdded = state.lastBackgroundAdded;\n let lastForegroundAdded = state.lastForegroundAdded;\n\n delete state.lastBackgroundAdded;\n delete state.lastForegroundAdded;\n\n Object.keys(state).forEach(function (key) {\n if (state[key]) {\n ret = codeCache[key].on + ret;\n }\n });\n\n if (lastBackgroundAdded && lastBackgroundAdded != '\\u001b[49m') {\n ret = lastBackgroundAdded + ret;\n }\n if (lastForegroundAdded && lastForegroundAdded != '\\u001b[39m') {\n ret = lastForegroundAdded + ret;\n }\n\n return ret;\n}\n\nfunction truncateWidth(str, desiredLength) {\n if (str.length === strlen(str)) {\n return str.substr(0, desiredLength);\n }\n\n while (strlen(str) > desiredLength) {\n str = str.slice(0, -1);\n }\n\n return str;\n}\n\nfunction truncateWidthWithAnsi(str, desiredLength) {\n let code = codeRegex(true);\n let split = str.split(codeRegex());\n let splitIndex = 0;\n let retLen = 0;\n let ret = '';\n let myArray;\n let state = {};\n\n while (retLen < desiredLength) {\n myArray = code.exec(str);\n let toAdd = split[splitIndex];\n splitIndex++;\n if (retLen + strlen(toAdd) > desiredLength) {\n toAdd = truncateWidth(toAdd, desiredLength - retLen);\n }\n ret += toAdd;\n retLen += strlen(toAdd);\n\n if (retLen < desiredLength) {\n if (!myArray) {\n break;\n } // full-width chars may cause a whitespace which cannot be filled\n ret += myArray[0];\n updateState(state, myArray);\n }\n }\n\n return unwindState(state, ret);\n}\n\nfunction truncate(str, desiredLength, truncateChar) {\n truncateChar = truncateChar || '…';\n let lengthOfStr = strlen(str);\n if (lengthOfStr <= desiredLength) {\n return str;\n }\n desiredLength -= strlen(truncateChar);\n\n let ret = truncateWidthWithAnsi(str, desiredLength);\n\n ret += truncateChar;\n\n const hrefTag = '\\x1B]8;;\\x07';\n\n if (str.includes(hrefTag) && !ret.includes(hrefTag)) {\n ret += hrefTag;\n }\n\n return ret;\n}\n\nfunction defaultOptions() {\n return {\n chars: {\n top: '─',\n 'top-mid': '┬',\n 'top-left': '┌',\n 'top-right': '┐',\n bottom: '─',\n 'bottom-mid': '┴',\n 'bottom-left': '└',\n 'bottom-right': '┘',\n left: '│',\n 'left-mid': '├',\n mid: '─',\n 'mid-mid': '┼',\n right: '│',\n 'right-mid': '┤',\n middle: '│',\n },\n truncate: '…',\n colWidths: [],\n rowHeights: [],\n colAligns: [],\n rowAligns: [],\n style: {\n 'padding-left': 1,\n 'padding-right': 1,\n head: ['red'],\n border: ['grey'],\n compact: false,\n },\n head: [],\n };\n}\n\nfunction mergeOptions(options, defaults) {\n options = options || {};\n defaults = defaults || defaultOptions();\n let ret = Object.assign({}, defaults, options);\n ret.chars = Object.assign({}, defaults.chars, options.chars);\n ret.style = Object.assign({}, defaults.style, options.style);\n return ret;\n}\n\n// Wrap on word boundary\nfunction wordWrap(maxLength, input) {\n let lines = [];\n let split = input.split(/(\\s+)/g);\n let line = [];\n let lineLength = 0;\n let whitespace;\n for (let i = 0; i < split.length; i += 2) {\n let word = split[i];\n let newLength = lineLength + strlen(word);\n if (lineLength > 0 && whitespace) {\n newLength += whitespace.length;\n }\n if (newLength > maxLength) {\n if (lineLength !== 0) {\n lines.push(line.join(''));\n }\n line = [word];\n lineLength = strlen(word);\n } else {\n line.push(whitespace || '', word);\n lineLength = newLength;\n }\n whitespace = split[i + 1];\n }\n if (lineLength) {\n lines.push(line.join(''));\n }\n return lines;\n}\n\n// Wrap text (ignoring word boundaries)\nfunction textWrap(maxLength, input) {\n let lines = [];\n let line = '';\n function pushLine(str, ws) {\n if (line.length && ws) line += ws;\n line += str;\n while (line.length > maxLength) {\n lines.push(line.slice(0, maxLength));\n line = line.slice(maxLength);\n }\n }\n let split = input.split(/(\\s+)/g);\n for (let i = 0; i < split.length; i += 2) {\n pushLine(split[i], i && split[i - 1]);\n }\n if (line.length) lines.push(line);\n return lines;\n}\n\nfunction multiLineWordWrap(maxLength, input, wrapOnWordBoundary = true) {\n let output = [];\n input = input.split('\\n');\n const handler = wrapOnWordBoundary ? wordWrap : textWrap;\n for (let i = 0; i < input.length; i++) {\n output.push.apply(output, handler(maxLength, input[i]));\n }\n return output;\n}\n\nfunction colorizeLines(input) {\n let state = {};\n let output = [];\n for (let i = 0; i < input.length; i++) {\n let line = rewindState(state, input[i]);\n state = readState(line);\n let temp = Object.assign({}, state);\n output.push(unwindState(temp, line));\n }\n return output;\n}\n\n/**\n * Credit: Matheus Sampaio https://github.com/matheussampaio\n */\nfunction hyperlink(url, text) {\n const OSC = '\\u001B]';\n const BEL = '\\u0007';\n const SEP = ';';\n\n return [OSC, '8', SEP, SEP, url || text, BEL, text, OSC, '8', SEP, SEP, BEL].join('');\n}\n\nmodule.exports = {\n strlen: strlen,\n repeat: repeat,\n pad: pad,\n truncate: truncate,\n mergeOptions: mergeOptions,\n wordWrap: multiLineWordWrap,\n colorizeLines: colorizeLines,\n hyperlink,\n};\n","/*\nThe MIT License (MIT)\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\nvar styles = {};\nmodule['exports'] = styles;\n\nvar codes = {\n reset: [0, 0],\n\n bold: [1, 22],\n dim: [2, 22],\n italic: [3, 23],\n underline: [4, 24],\n inverse: [7, 27],\n hidden: [8, 28],\n strikethrough: [9, 29],\n\n black: [30, 39],\n red: [31, 39],\n green: [32, 39],\n yellow: [33, 39],\n blue: [34, 39],\n magenta: [35, 39],\n cyan: [36, 39],\n white: [37, 39],\n gray: [90, 39],\n grey: [90, 39],\n\n brightRed: [91, 39],\n brightGreen: [92, 39],\n brightYellow: [93, 39],\n brightBlue: [94, 39],\n brightMagenta: [95, 39],\n brightCyan: [96, 39],\n brightWhite: [97, 39],\n\n bgBlack: [40, 49],\n bgRed: [41, 49],\n bgGreen: [42, 49],\n bgYellow: [43, 49],\n bgBlue: [44, 49],\n bgMagenta: [45, 49],\n bgCyan: [46, 49],\n bgWhite: [47, 49],\n bgGray: [100, 49],\n bgGrey: [100, 49],\n\n bgBrightRed: [101, 49],\n bgBrightGreen: [102, 49],\n bgBrightYellow: [103, 49],\n bgBrightBlue: [104, 49],\n bgBrightMagenta: [105, 49],\n bgBrightCyan: [106, 49],\n bgBrightWhite: [107, 49],\n\n // legacy styles for colors pre v1.0.0\n blackBG: [40, 49],\n redBG: [41, 49],\n greenBG: [42, 49],\n yellowBG: [43, 49],\n blueBG: [44, 49],\n magentaBG: [45, 49],\n cyanBG: [46, 49],\n whiteBG: [47, 49],\n\n};\n\nObject.keys(codes).forEach(function(key) {\n var val = codes[key];\n var style = styles[key] = [];\n style.open = '\\u001b[' + val[0] + 'm';\n style.close = '\\u001b[' + val[1] + 'm';\n});\n","/*\nMIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n'use strict';\n\nmodule.exports = function(flag, argv) {\n argv = argv || process.argv;\n\n var terminatorPos = argv.indexOf('--');\n var prefix = /^-{1,2}/.test(flag) ? '' : '--';\n var pos = argv.indexOf(prefix + flag);\n\n return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos);\n};\n","/*\nThe MIT License (MIT)\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n'use strict';\n\nvar os = require('os');\nvar hasFlag = require('./has-flag.js');\n\nvar env = process.env;\n\nvar forceColor = void 0;\nif (hasFlag('no-color') || hasFlag('no-colors') || hasFlag('color=false')) {\n forceColor = false;\n} else if (hasFlag('color') || hasFlag('colors') || hasFlag('color=true')\n || hasFlag('color=always')) {\n forceColor = true;\n}\nif ('FORCE_COLOR' in env) {\n forceColor = env.FORCE_COLOR.length === 0\n || parseInt(env.FORCE_COLOR, 10) !== 0;\n}\n\nfunction translateLevel(level) {\n if (level === 0) {\n return false;\n }\n\n return {\n level: level,\n hasBasic: true,\n has256: level >= 2,\n has16m: level >= 3,\n };\n}\n\nfunction supportsColor(stream) {\n if (forceColor === false) {\n return 0;\n }\n\n if (hasFlag('color=16m') || hasFlag('color=full')\n || hasFlag('color=truecolor')) {\n return 3;\n }\n\n if (hasFlag('color=256')) {\n return 2;\n }\n\n if (stream && !stream.isTTY && forceColor !== true) {\n return 0;\n }\n\n var min = forceColor ? 1 : 0;\n\n if (process.platform === 'win32') {\n // Node.js 7.5.0 is the first version of Node.js to include a patch to\n // libuv that enables 256 color output on Windows. Anything earlier and it\n // won't work. However, here we target Node.js 8 at minimum as it is an LTS\n // release, and Node.js 7 is not. Windows 10 build 10586 is the first\n // Windows release that supports 256 colors. Windows 10 build 14931 is the\n // first release that supports 16m/TrueColor.\n var osRelease = os.release().split('.');\n if (Number(process.versions.node.split('.')[0]) >= 8\n && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {\n return Number(osRelease[2]) >= 14931 ? 3 : 2;\n }\n\n return 1;\n }\n\n if ('CI' in env) {\n if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(function(sign) {\n return sign in env;\n }) || env.CI_NAME === 'codeship') {\n return 1;\n }\n\n return min;\n }\n\n if ('TEAMCITY_VERSION' in env) {\n return (/^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0\n );\n }\n\n if ('TERM_PROGRAM' in env) {\n var version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);\n\n switch (env.TERM_PROGRAM) {\n case 'iTerm.app':\n return version >= 3 ? 3 : 2;\n case 'Hyper':\n return 3;\n case 'Apple_Terminal':\n return 2;\n // No default\n }\n }\n\n if (/-256(color)?$/i.test(env.TERM)) {\n return 2;\n }\n\n if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {\n return 1;\n }\n\n if ('COLORTERM' in env) {\n return 1;\n }\n\n if (env.TERM === 'dumb') {\n return min;\n }\n\n return min;\n}\n\nfunction getSupportLevel(stream) {\n var level = supportsColor(stream);\n return translateLevel(level);\n}\n\nmodule.exports = {\n supportsColor: getSupportLevel,\n stdout: getSupportLevel(process.stdout),\n stderr: getSupportLevel(process.stderr),\n};\n","module['exports'] = function runTheTrap(text, options) {\n var result = '';\n text = text || 'Run the trap, drop the bass';\n text = text.split('');\n var trap = {\n a: ['\\u0040', '\\u0104', '\\u023a', '\\u0245', '\\u0394', '\\u039b', '\\u0414'],\n b: ['\\u00df', '\\u0181', '\\u0243', '\\u026e', '\\u03b2', '\\u0e3f'],\n c: ['\\u00a9', '\\u023b', '\\u03fe'],\n d: ['\\u00d0', '\\u018a', '\\u0500', '\\u0501', '\\u0502', '\\u0503'],\n e: ['\\u00cb', '\\u0115', '\\u018e', '\\u0258', '\\u03a3', '\\u03be', '\\u04bc',\n '\\u0a6c'],\n f: ['\\u04fa'],\n g: ['\\u0262'],\n h: ['\\u0126', '\\u0195', '\\u04a2', '\\u04ba', '\\u04c7', '\\u050a'],\n i: ['\\u0f0f'],\n j: ['\\u0134'],\n k: ['\\u0138', '\\u04a0', '\\u04c3', '\\u051e'],\n l: ['\\u0139'],\n m: ['\\u028d', '\\u04cd', '\\u04ce', '\\u0520', '\\u0521', '\\u0d69'],\n n: ['\\u00d1', '\\u014b', '\\u019d', '\\u0376', '\\u03a0', '\\u048a'],\n o: ['\\u00d8', '\\u00f5', '\\u00f8', '\\u01fe', '\\u0298', '\\u047a', '\\u05dd',\n '\\u06dd', '\\u0e4f'],\n p: ['\\u01f7', '\\u048e'],\n q: ['\\u09cd'],\n r: ['\\u00ae', '\\u01a6', '\\u0210', '\\u024c', '\\u0280', '\\u042f'],\n s: ['\\u00a7', '\\u03de', '\\u03df', '\\u03e8'],\n t: ['\\u0141', '\\u0166', '\\u0373'],\n u: ['\\u01b1', '\\u054d'],\n v: ['\\u05d8'],\n w: ['\\u0428', '\\u0460', '\\u047c', '\\u0d70'],\n x: ['\\u04b2', '\\u04fe', '\\u04fc', '\\u04fd'],\n y: ['\\u00a5', '\\u04b0', '\\u04cb'],\n z: ['\\u01b5', '\\u0240'],\n };\n text.forEach(function(c) {\n c = c.toLowerCase();\n var chars = trap[c] || [' '];\n var rand = Math.floor(Math.random() * chars.length);\n if (typeof trap[c] !== 'undefined') {\n result += trap[c][rand];\n } else {\n result += c;\n }\n });\n return result;\n};\n","// please no\nmodule['exports'] = function zalgo(text, options) {\n text = text || ' he is here ';\n var soul = {\n 'up': [\n '̍', '̎', '̄', '̅',\n '̿', '̑', '̆', '̐',\n '͒', '͗', '͑', '̇',\n '̈', '̊', '͂', '̓',\n '̈', '͊', '͋', '͌',\n '̃', '̂', '̌', '͐',\n '̀', '́', '̋', '̏',\n '̒', '̓', '̔', '̽',\n '̉', 'ͣ', 'ͤ', 'ͥ',\n 'ͦ', 'ͧ', 'ͨ', 'ͩ',\n 'ͪ', 'ͫ', 'ͬ', 'ͭ',\n 'ͮ', 'ͯ', '̾', '͛',\n '͆', '̚',\n ],\n 'down': [\n '̖', '̗', '̘', '̙',\n '̜', '̝', '̞', '̟',\n '̠', '̤', '̥', '̦',\n '̩', '̪', '̫', '̬',\n '̭', '̮', '̯', '̰',\n '̱', '̲', '̳', '̹',\n '̺', '̻', '̼', 'ͅ',\n '͇', '͈', '͉', '͍',\n '͎', '͓', '͔', '͕',\n '͖', '͙', '͚', '̣',\n ],\n 'mid': [\n '̕', '̛', '̀', '́',\n '͘', '̡', '̢', '̧',\n '̨', '̴', '̵', '̶',\n '͜', '͝', '͞',\n '͟', '͠', '͢', '̸',\n '̷', '͡', ' ҉',\n ],\n };\n var all = [].concat(soul.up, soul.down, soul.mid);\n\n function randomNumber(range) {\n var r = Math.floor(Math.random() * range);\n return r;\n }\n\n function isChar(character) {\n var bool = false;\n all.filter(function(i) {\n bool = (i === character);\n });\n return bool;\n }\n\n\n function heComes(text, options) {\n var result = '';\n var counts;\n var l;\n options = options || {};\n options['up'] =\n typeof options['up'] !== 'undefined' ? options['up'] : true;\n options['mid'] =\n typeof options['mid'] !== 'undefined' ? options['mid'] : true;\n options['down'] =\n typeof options['down'] !== 'undefined' ? options['down'] : true;\n options['size'] =\n typeof options['size'] !== 'undefined' ? options['size'] : 'maxi';\n text = text.split('');\n for (l in text) {\n if (isChar(l)) {\n continue;\n }\n result = result + text[l];\n counts = {'up': 0, 'down': 0, 'mid': 0};\n switch (options.size) {\n case 'mini':\n counts.up = randomNumber(8);\n counts.mid = randomNumber(2);\n counts.down = randomNumber(8);\n break;\n case 'maxi':\n counts.up = randomNumber(16) + 3;\n counts.mid = randomNumber(4) + 1;\n counts.down = randomNumber(64) + 3;\n break;\n default:\n counts.up = randomNumber(8) + 1;\n counts.mid = randomNumber(6) / 2;\n counts.down = randomNumber(8) + 1;\n break;\n }\n\n var arr = ['up', 'mid', 'down'];\n for (var d in arr) {\n var index = arr[d];\n for (var i = 0; i <= counts[index]; i++) {\n if (options[index]) {\n result = result + soul[index][randomNumber(soul[index].length)];\n }\n }\n }\n }\n return result;\n }\n // don't summon him\n return heComes(text, options);\n};\n\n","module['exports'] = function(colors) {\n return function(letter, i, exploded) {\n if (letter === ' ') return letter;\n switch (i%3) {\n case 0: return colors.red(letter);\n case 1: return colors.white(letter);\n case 2: return colors.blue(letter);\n }\n };\n};\n","module['exports'] = function(colors) {\n return function(letter, i, exploded) {\n return i % 2 === 0 ? letter : colors.inverse(letter);\n };\n};\n","module['exports'] = function(colors) {\n // RoY G BiV\n var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta'];\n return function(letter, i, exploded) {\n if (letter === ' ') {\n return letter;\n } else {\n return colors[rainbowColors[i++ % rainbowColors.length]](letter);\n }\n };\n};\n\n","module['exports'] = function(colors) {\n var available = ['underline', 'inverse', 'grey', 'yellow', 'red', 'green',\n 'blue', 'white', 'cyan', 'magenta', 'brightYellow', 'brightRed',\n 'brightGreen', 'brightBlue', 'brightWhite', 'brightCyan', 'brightMagenta'];\n return function(letter, i, exploded) {\n return letter === ' ' ? letter :\n colors[\n available[Math.round(Math.random() * (available.length - 2))]\n ](letter);\n };\n};\n","/*\n\nThe MIT License (MIT)\n\nOriginal Library\n - Copyright (c) Marak Squires\n\nAdditional functionality\n - Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\nvar colors = {};\nmodule['exports'] = colors;\n\ncolors.themes = {};\n\nvar util = require('util');\nvar ansiStyles = colors.styles = require('./styles');\nvar defineProps = Object.defineProperties;\nvar newLineRegex = new RegExp(/[\\r\\n]+/g);\n\ncolors.supportsColor = require('./system/supports-colors').supportsColor;\n\nif (typeof colors.enabled === 'undefined') {\n colors.enabled = colors.supportsColor() !== false;\n}\n\ncolors.enable = function() {\n colors.enabled = true;\n};\n\ncolors.disable = function() {\n colors.enabled = false;\n};\n\ncolors.stripColors = colors.strip = function(str) {\n return ('' + str).replace(/\\x1B\\[\\d+m/g, '');\n};\n\n// eslint-disable-next-line no-unused-vars\nvar stylize = colors.stylize = function stylize(str, style) {\n if (!colors.enabled) {\n return str+'';\n }\n\n var styleMap = ansiStyles[style];\n\n // Stylize should work for non-ANSI styles, too\n if (!styleMap && style in colors) {\n // Style maps like trap operate as functions on strings;\n // they don't have properties like open or close.\n return colors[style](str);\n }\n\n return styleMap.open + str + styleMap.close;\n};\n\nvar matchOperatorsRe = /[|\\\\{}()[\\]^$+*?.]/g;\nvar escapeStringRegexp = function(str) {\n if (typeof str !== 'string') {\n throw new TypeError('Expected a string');\n }\n return str.replace(matchOperatorsRe, '\\\\$&');\n};\n\nfunction build(_styles) {\n var builder = function builder() {\n return applyStyle.apply(builder, arguments);\n };\n builder._styles = _styles;\n // __proto__ is used because we must return a function, but there is\n // no way to create a function with a different prototype.\n builder.__proto__ = proto;\n return builder;\n}\n\nvar styles = (function() {\n var ret = {};\n ansiStyles.grey = ansiStyles.gray;\n Object.keys(ansiStyles).forEach(function(key) {\n ansiStyles[key].closeRe =\n new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g');\n ret[key] = {\n get: function() {\n return build(this._styles.concat(key));\n },\n };\n });\n return ret;\n})();\n\nvar proto = defineProps(function colors() {}, styles);\n\nfunction applyStyle() {\n var args = Array.prototype.slice.call(arguments);\n\n var str = args.map(function(arg) {\n // Use weak equality check so we can colorize null/undefined in safe mode\n if (arg != null && arg.constructor === String) {\n return arg;\n } else {\n return util.inspect(arg);\n }\n }).join(' ');\n\n if (!colors.enabled || !str) {\n return str;\n }\n\n var newLinesPresent = str.indexOf('\\n') != -1;\n\n var nestedStyles = this._styles;\n\n var i = nestedStyles.length;\n while (i--) {\n var code = ansiStyles[nestedStyles[i]];\n str = code.open + str.replace(code.closeRe, code.open) + code.close;\n if (newLinesPresent) {\n str = str.replace(newLineRegex, function(match) {\n return code.close + match + code.open;\n });\n }\n }\n\n return str;\n}\n\ncolors.setTheme = function(theme) {\n if (typeof theme === 'string') {\n console.log('colors.setTheme now only accepts an object, not a string. ' +\n 'If you are trying to set a theme from a file, it is now your (the ' +\n 'caller\\'s) responsibility to require the file. The old syntax ' +\n 'looked like colors.setTheme(__dirname + ' +\n '\\'/../themes/generic-logging.js\\'); The new syntax looks like '+\n 'colors.setTheme(require(__dirname + ' +\n '\\'/../themes/generic-logging.js\\'));');\n return;\n }\n for (var style in theme) {\n (function(style) {\n colors[style] = function(str) {\n if (typeof theme[style] === 'object') {\n var out = str;\n for (var i in theme[style]) {\n out = colors[theme[style][i]](out);\n }\n return out;\n }\n return colors[theme[style]](str);\n };\n })(style);\n }\n};\n\nfunction init() {\n var ret = {};\n Object.keys(styles).forEach(function(name) {\n ret[name] = {\n get: function() {\n return build([name]);\n },\n };\n });\n return ret;\n}\n\nvar sequencer = function sequencer(map, str) {\n var exploded = str.split('');\n exploded = exploded.map(map);\n return exploded.join('');\n};\n\n// custom formatter methods\ncolors.trap = require('./custom/trap');\ncolors.zalgo = require('./custom/zalgo');\n\n// maps\ncolors.maps = {};\ncolors.maps.america = require('./maps/america')(colors);\ncolors.maps.zebra = require('./maps/zebra')(colors);\ncolors.maps.rainbow = require('./maps/rainbow')(colors);\ncolors.maps.random = require('./maps/random')(colors);\n\nfor (var map in colors.maps) {\n (function(map) {\n colors[map] = function(str) {\n return sequencer(colors.maps[map], str);\n };\n })(map);\n}\n\ndefineProps(colors, init());\n","//\n// Remark: Requiring this file will use the \"safe\" colors API,\n// which will not touch String.prototype.\n//\n// var colors = require('colors/safe');\n// colors.red(\"foo\")\n//\n//\nvar colors = require('./lib/colors');\nmodule['exports'] = colors;\n","const { info, debug } = require('./debug');\nconst utils = require('./utils');\n\nclass Cell {\n /**\n * A representation of a cell within the table.\n * Implementations must have `init` and `draw` methods,\n * as well as `colSpan`, `rowSpan`, `desiredHeight` and `desiredWidth` properties.\n * @param options\n * @constructor\n */\n constructor(options) {\n this.setOptions(options);\n\n /**\n * Each cell will have it's `x` and `y` values set by the `layout-manager` prior to\n * `init` being called;\n * @type {Number}\n */\n this.x = null;\n this.y = null;\n }\n\n setOptions(options) {\n if (['boolean', 'number', 'bigint', 'string'].indexOf(typeof options) !== -1) {\n options = { content: '' + options };\n }\n options = options || {};\n this.options = options;\n let content = options.content;\n if (['boolean', 'number', 'bigint', 'string'].indexOf(typeof content) !== -1) {\n this.content = String(content);\n } else if (!content) {\n this.content = this.options.href || '';\n } else {\n throw new Error('Content needs to be a primitive, got: ' + typeof content);\n }\n this.colSpan = options.colSpan || 1;\n this.rowSpan = options.rowSpan || 1;\n if (this.options.href) {\n Object.defineProperty(this, 'href', {\n get() {\n return this.options.href;\n },\n });\n }\n }\n\n mergeTableOptions(tableOptions, cells) {\n this.cells = cells;\n\n let optionsChars = this.options.chars || {};\n let tableChars = tableOptions.chars;\n let chars = (this.chars = {});\n CHAR_NAMES.forEach(function (name) {\n setOption(optionsChars, tableChars, name, chars);\n });\n\n this.truncate = this.options.truncate || tableOptions.truncate;\n\n let style = (this.options.style = this.options.style || {});\n let tableStyle = tableOptions.style;\n setOption(style, tableStyle, 'padding-left', this);\n setOption(style, tableStyle, 'padding-right', this);\n this.head = style.head || tableStyle.head;\n this.border = style.border || tableStyle.border;\n\n this.fixedWidth = tableOptions.colWidths[this.x];\n this.lines = this.computeLines(tableOptions);\n\n this.desiredWidth = utils.strlen(this.content) + this.paddingLeft + this.paddingRight;\n this.desiredHeight = this.lines.length;\n }\n\n computeLines(tableOptions) {\n const tableWordWrap = tableOptions.wordWrap || tableOptions.textWrap;\n const { wordWrap = tableWordWrap } = this.options;\n if (this.fixedWidth && wordWrap) {\n this.fixedWidth -= this.paddingLeft + this.paddingRight;\n if (this.colSpan) {\n let i = 1;\n while (i < this.colSpan) {\n this.fixedWidth += tableOptions.colWidths[this.x + i];\n i++;\n }\n }\n const { wrapOnWordBoundary: tableWrapOnWordBoundary = true } = tableOptions;\n const { wrapOnWordBoundary = tableWrapOnWordBoundary } = this.options;\n return this.wrapLines(utils.wordWrap(this.fixedWidth, this.content, wrapOnWordBoundary));\n }\n return this.wrapLines(this.content.split('\\n'));\n }\n\n wrapLines(computedLines) {\n const lines = utils.colorizeLines(computedLines);\n if (this.href) {\n return lines.map((line) => utils.hyperlink(this.href, line));\n }\n return lines;\n }\n\n /**\n * Initializes the Cells data structure.\n *\n * @param tableOptions - A fully populated set of tableOptions.\n * In addition to the standard default values, tableOptions must have fully populated the\n * `colWidths` and `rowWidths` arrays. Those arrays must have lengths equal to the number\n * of columns or rows (respectively) in this table, and each array item must be a Number.\n *\n */\n init(tableOptions) {\n let x = this.x;\n let y = this.y;\n this.widths = tableOptions.colWidths.slice(x, x + this.colSpan);\n this.heights = tableOptions.rowHeights.slice(y, y + this.rowSpan);\n this.width = this.widths.reduce(sumPlusOne, -1);\n this.height = this.heights.reduce(sumPlusOne, -1);\n\n this.hAlign = this.options.hAlign || tableOptions.colAligns[x];\n this.vAlign = this.options.vAlign || tableOptions.rowAligns[y];\n\n this.drawRight = x + this.colSpan == tableOptions.colWidths.length;\n }\n\n /**\n * Draws the given line of the cell.\n * This default implementation defers to methods `drawTop`, `drawBottom`, `drawLine` and `drawEmpty`.\n * @param lineNum - can be `top`, `bottom` or a numerical line number.\n * @param spanningCell - will be a number if being called from a RowSpanCell, and will represent how\n * many rows below it's being called from. Otherwise it's undefined.\n * @returns {String} The representation of this line.\n */\n draw(lineNum, spanningCell) {\n if (lineNum == 'top') return this.drawTop(this.drawRight);\n if (lineNum == 'bottom') return this.drawBottom(this.drawRight);\n let content = utils.truncate(this.content, 10, this.truncate);\n if (!lineNum) {\n info(`${this.y}-${this.x}: ${this.rowSpan - lineNum}x${this.colSpan} Cell ${content}`);\n } else {\n // debug(`${lineNum}-${this.x}: 1x${this.colSpan} RowSpanCell ${content}`);\n }\n let padLen = Math.max(this.height - this.lines.length, 0);\n let padTop;\n switch (this.vAlign) {\n case 'center':\n padTop = Math.ceil(padLen / 2);\n break;\n case 'bottom':\n padTop = padLen;\n break;\n default:\n padTop = 0;\n }\n if (lineNum < padTop || lineNum >= padTop + this.lines.length) {\n return this.drawEmpty(this.drawRight, spanningCell);\n }\n let forceTruncation = this.lines.length > this.height && lineNum + 1 >= this.height;\n return this.drawLine(lineNum - padTop, this.drawRight, forceTruncation, spanningCell);\n }\n\n /**\n * Renders the top line of the cell.\n * @param drawRight - true if this method should render the right edge of the cell.\n * @returns {String}\n */\n drawTop(drawRight) {\n let content = [];\n if (this.cells) {\n //TODO: cells should always exist - some tests don't fill it in though\n this.widths.forEach(function (width, index) {\n content.push(this._topLeftChar(index));\n content.push(utils.repeat(this.chars[this.y == 0 ? 'top' : 'mid'], width));\n }, this);\n } else {\n content.push(this._topLeftChar(0));\n content.push(utils.repeat(this.chars[this.y == 0 ? 'top' : 'mid'], this.width));\n }\n if (drawRight) {\n content.push(this.chars[this.y == 0 ? 'topRight' : 'rightMid']);\n }\n return this.wrapWithStyleColors('border', content.join(''));\n }\n\n _topLeftChar(offset) {\n let x = this.x + offset;\n let leftChar;\n if (this.y == 0) {\n leftChar = x == 0 ? 'topLeft' : offset == 0 ? 'topMid' : 'top';\n } else {\n if (x == 0) {\n leftChar = 'leftMid';\n } else {\n leftChar = offset == 0 ? 'midMid' : 'bottomMid';\n if (this.cells) {\n //TODO: cells should always exist - some tests don't fill it in though\n let spanAbove = this.cells[this.y - 1][x] instanceof Cell.ColSpanCell;\n if (spanAbove) {\n leftChar = offset == 0 ? 'topMid' : 'mid';\n }\n if (offset == 0) {\n let i = 1;\n while (this.cells[this.y][x - i] instanceof Cell.ColSpanCell) {\n i++;\n }\n if (this.cells[this.y][x - i] instanceof Cell.RowSpanCell) {\n leftChar = 'leftMid';\n }\n }\n }\n }\n }\n return this.chars[leftChar];\n }\n\n wrapWithStyleColors(styleProperty, content) {\n if (this[styleProperty] && this[styleProperty].length) {\n try {\n let colors = require('@colors/colors/safe');\n for (let i = this[styleProperty].length - 1; i >= 0; i--) {\n colors = colors[this[styleProperty][i]];\n }\n return colors(content);\n } catch (e) {\n return content;\n }\n } else {\n return content;\n }\n }\n\n /**\n * Renders a line of text.\n * @param lineNum - Which line of text to render. This is not necessarily the line within the cell.\n * There may be top-padding above the first line of text.\n * @param drawRight - true if this method should render the right edge of the cell.\n * @param forceTruncationSymbol - `true` if the rendered text should end with the truncation symbol even\n * if the text fits. This is used when the cell is vertically truncated. If `false` the text should\n * only include the truncation symbol if the text will not fit horizontally within the cell width.\n * @param spanningCell - a number of if being called from a RowSpanCell. (how many rows below). otherwise undefined.\n * @returns {String}\n */\n drawLine(lineNum, drawRight, forceTruncationSymbol, spanningCell) {\n let left = this.chars[this.x == 0 ? 'left' : 'middle'];\n if (this.x && spanningCell && this.cells) {\n let cellLeft = this.cells[this.y + spanningCell][this.x - 1];\n while (cellLeft instanceof ColSpanCell) {\n cellLeft = this.cells[cellLeft.y][cellLeft.x - 1];\n }\n if (!(cellLeft instanceof RowSpanCell)) {\n left = this.chars['rightMid'];\n }\n }\n let leftPadding = utils.repeat(' ', this.paddingLeft);\n let right = drawRight ? this.chars['right'] : '';\n let rightPadding = utils.repeat(' ', this.paddingRight);\n let line = this.lines[lineNum];\n let len = this.width - (this.paddingLeft + this.paddingRight);\n if (forceTruncationSymbol) line += this.truncate || '…';\n let content = utils.truncate(line, len, this.truncate);\n content = utils.pad(content, len, ' ', this.hAlign);\n content = leftPadding + content + rightPadding;\n return this.stylizeLine(left, content, right);\n }\n\n stylizeLine(left, content, right) {\n left = this.wrapWithStyleColors('border', left);\n right = this.wrapWithStyleColors('border', right);\n if (this.y === 0) {\n content = this.wrapWithStyleColors('head', content);\n }\n return left + content + right;\n }\n\n /**\n * Renders the bottom line of the cell.\n * @param drawRight - true if this method should render the right edge of the cell.\n * @returns {String}\n */\n drawBottom(drawRight) {\n let left = this.chars[this.x == 0 ? 'bottomLeft' : 'bottomMid'];\n let content = utils.repeat(this.chars.bottom, this.width);\n let right = drawRight ? this.chars['bottomRight'] : '';\n return this.wrapWithStyleColors('border', left + content + right);\n }\n\n /**\n * Renders a blank line of text within the cell. Used for top and/or bottom padding.\n * @param drawRight - true if this method should render the right edge of the cell.\n * @param spanningCell - a number of if being called from a RowSpanCell. (how many rows below). otherwise undefined.\n * @returns {String}\n */\n drawEmpty(drawRight, spanningCell) {\n let left = this.chars[this.x == 0 ? 'left' : 'middle'];\n if (this.x && spanningCell && this.cells) {\n let cellLeft = this.cells[this.y + spanningCell][this.x - 1];\n while (cellLeft instanceof ColSpanCell) {\n cellLeft = this.cells[cellLeft.y][cellLeft.x - 1];\n }\n if (!(cellLeft instanceof RowSpanCell)) {\n left = this.chars['rightMid'];\n }\n }\n let right = drawRight ? this.chars['right'] : '';\n let content = utils.repeat(' ', this.width);\n return this.stylizeLine(left, content, right);\n }\n}\n\nclass ColSpanCell {\n /**\n * A Cell that doesn't do anything. It just draws empty lines.\n * Used as a placeholder in column spanning.\n * @constructor\n */\n constructor() {}\n\n draw(lineNum) {\n if (typeof lineNum === 'number') {\n debug(`${this.y}-${this.x}: 1x1 ColSpanCell`);\n }\n return '';\n }\n\n init() {}\n\n mergeTableOptions() {}\n}\n\nclass RowSpanCell {\n /**\n * A placeholder Cell for a Cell that spans multiple rows.\n * It delegates rendering to the original cell, but adds the appropriate offset.\n * @param originalCell\n * @constructor\n */\n constructor(originalCell) {\n this.originalCell = originalCell;\n }\n\n init(tableOptions) {\n let y = this.y;\n let originalY = this.originalCell.y;\n this.cellOffset = y - originalY;\n this.offset = findDimension(tableOptions.rowHeights, originalY, this.cellOffset);\n }\n\n draw(lineNum) {\n if (lineNum == 'top') {\n return this.originalCell.draw(this.offset, this.cellOffset);\n }\n if (lineNum == 'bottom') {\n return this.originalCell.draw('bottom');\n }\n debug(`${this.y}-${this.x}: 1x${this.colSpan} RowSpanCell for ${this.originalCell.content}`);\n return this.originalCell.draw(this.offset + 1 + lineNum);\n }\n\n mergeTableOptions() {}\n}\n\nfunction firstDefined(...args) {\n return args.filter((v) => v !== undefined && v !== null).shift();\n}\n\n// HELPER FUNCTIONS\nfunction setOption(objA, objB, nameB, targetObj) {\n let nameA = nameB.split('-');\n if (nameA.length > 1) {\n nameA[1] = nameA[1].charAt(0).toUpperCase() + nameA[1].substr(1);\n nameA = nameA.join('');\n targetObj[nameA] = firstDefined(objA[nameA], objA[nameB], objB[nameA], objB[nameB]);\n } else {\n targetObj[nameB] = firstDefined(objA[nameB], objB[nameB]);\n }\n}\n\nfunction findDimension(dimensionTable, startingIndex, span) {\n let ret = dimensionTable[startingIndex];\n for (let i = 1; i < span; i++) {\n ret += 1 + dimensionTable[startingIndex + i];\n }\n return ret;\n}\n\nfunction sumPlusOne(a, b) {\n return a + b + 1;\n}\n\nlet CHAR_NAMES = [\n 'top',\n 'top-mid',\n 'top-left',\n 'top-right',\n 'bottom',\n 'bottom-mid',\n 'bottom-left',\n 'bottom-right',\n 'left',\n 'left-mid',\n 'mid',\n 'mid-mid',\n 'right',\n 'right-mid',\n 'middle',\n];\n\nmodule.exports = Cell;\nmodule.exports.ColSpanCell = ColSpanCell;\nmodule.exports.RowSpanCell = RowSpanCell;\n","const { warn, debug } = require('./debug');\nconst Cell = require('./cell');\nconst { ColSpanCell, RowSpanCell } = Cell;\n\n(function () {\n function next(alloc, col) {\n if (alloc[col] > 0) {\n return next(alloc, col + 1);\n }\n return col;\n }\n\n function layoutTable(table) {\n let alloc = {};\n table.forEach(function (row, rowIndex) {\n let col = 0;\n row.forEach(function (cell) {\n cell.y = rowIndex;\n // Avoid erroneous call to next() on first row\n cell.x = rowIndex ? next(alloc, col) : col;\n const rowSpan = cell.rowSpan || 1;\n const colSpan = cell.colSpan || 1;\n if (rowSpan > 1) {\n for (let cs = 0; cs < colSpan; cs++) {\n alloc[cell.x + cs] = rowSpan;\n }\n }\n col = cell.x + colSpan;\n });\n Object.keys(alloc).forEach((idx) => {\n alloc[idx]--;\n if (alloc[idx] < 1) delete alloc[idx];\n });\n });\n }\n\n function maxWidth(table) {\n let mw = 0;\n table.forEach(function (row) {\n row.forEach(function (cell) {\n mw = Math.max(mw, cell.x + (cell.colSpan || 1));\n });\n });\n return mw;\n }\n\n function maxHeight(table) {\n return table.length;\n }\n\n function cellsConflict(cell1, cell2) {\n let yMin1 = cell1.y;\n let yMax1 = cell1.y - 1 + (cell1.rowSpan || 1);\n let yMin2 = cell2.y;\n let yMax2 = cell2.y - 1 + (cell2.rowSpan || 1);\n let yConflict = !(yMin1 > yMax2 || yMin2 > yMax1);\n\n let xMin1 = cell1.x;\n let xMax1 = cell1.x - 1 + (cell1.colSpan || 1);\n let xMin2 = cell2.x;\n let xMax2 = cell2.x - 1 + (cell2.colSpan || 1);\n let xConflict = !(xMin1 > xMax2 || xMin2 > xMax1);\n\n return yConflict && xConflict;\n }\n\n function conflictExists(rows, x, y) {\n let i_max = Math.min(rows.length - 1, y);\n let cell = { x: x, y: y };\n for (let i = 0; i <= i_max; i++) {\n let row = rows[i];\n for (let j = 0; j < row.length; j++) {\n if (cellsConflict(cell, row[j])) {\n return true;\n }\n }\n }\n return false;\n }\n\n function allBlank(rows, y, xMin, xMax) {\n for (let x = xMin; x < xMax; x++) {\n if (conflictExists(rows, x, y)) {\n return false;\n }\n }\n return true;\n }\n\n function addRowSpanCells(table) {\n table.forEach(function (row, rowIndex) {\n row.forEach(function (cell) {\n for (let i = 1; i < cell.rowSpan; i++) {\n let rowSpanCell = new RowSpanCell(cell);\n rowSpanCell.x = cell.x;\n rowSpanCell.y = cell.y + i;\n rowSpanCell.colSpan = cell.colSpan;\n insertCell(rowSpanCell, table[rowIndex + i]);\n }\n });\n });\n }\n\n function addColSpanCells(cellRows) {\n for (let rowIndex = cellRows.length - 1; rowIndex >= 0; rowIndex--) {\n let cellColumns = cellRows[rowIndex];\n for (let columnIndex = 0; columnIndex < cellColumns.length; columnIndex++) {\n let cell = cellColumns[columnIndex];\n for (let k = 1; k < cell.colSpan; k++) {\n let colSpanCell = new ColSpanCell();\n colSpanCell.x = cell.x + k;\n colSpanCell.y = cell.y;\n cellColumns.splice(columnIndex + 1, 0, colSpanCell);\n }\n }\n }\n }\n\n function insertCell(cell, row) {\n let x = 0;\n while (x < row.length && row[x].x < cell.x) {\n x++;\n }\n row.splice(x, 0, cell);\n }\n\n function fillInTable(table) {\n let h_max = maxHeight(table);\n let w_max = maxWidth(table);\n debug(`Max rows: ${h_max}; Max cols: ${w_max}`);\n for (let y = 0; y < h_max; y++) {\n for (let x = 0; x < w_max; x++) {\n if (!conflictExists(table, x, y)) {\n let opts = { x: x, y: y, colSpan: 1, rowSpan: 1 };\n x++;\n while (x < w_max && !conflictExists(table, x, y)) {\n opts.colSpan++;\n x++;\n }\n let y2 = y + 1;\n while (y2 < h_max && allBlank(table, y2, opts.x, opts.x + opts.colSpan)) {\n opts.rowSpan++;\n y2++;\n }\n let cell = new Cell(opts);\n cell.x = opts.x;\n cell.y = opts.y;\n warn(`Missing cell at ${cell.y}-${cell.x}.`);\n insertCell(cell, table[y]);\n }\n }\n }\n }\n\n function generateCells(rows) {\n return rows.map(function (row) {\n if (!Array.isArray(row)) {\n let key = Object.keys(row)[0];\n row = row[key];\n if (Array.isArray(row)) {\n row = row.slice();\n row.unshift(key);\n } else {\n row = [key, row];\n }\n }\n return row.map(function (cell) {\n return new Cell(cell);\n });\n });\n }\n\n function makeTableLayout(rows) {\n let cellRows = generateCells(rows);\n layoutTable(cellRows);\n fillInTable(cellRows);\n addRowSpanCells(cellRows);\n addColSpanCells(cellRows);\n return cellRows;\n }\n\n module.exports = {\n makeTableLayout: makeTableLayout,\n layoutTable: layoutTable,\n addRowSpanCells: addRowSpanCells,\n maxWidth: maxWidth,\n fillInTable: fillInTable,\n computeWidths: makeComputeWidths('colSpan', 'desiredWidth', 'x', 1),\n computeHeights: makeComputeWidths('rowSpan', 'desiredHeight', 'y', 1),\n };\n})();\n\nfunction makeComputeWidths(colSpan, desiredWidth, x, forcedMin) {\n return function (vals, table) {\n let result = [];\n let spanners = [];\n let auto = {};\n table.forEach(function (row) {\n row.forEach(function (cell) {\n if ((cell[colSpan] || 1) > 1) {\n spanners.push(cell);\n } else {\n result[cell[x]] = Math.max(result[cell[x]] || 0, cell[desiredWidth] || 0, forcedMin);\n }\n });\n });\n\n vals.forEach(function (val, index) {\n if (typeof val === 'number') {\n result[index] = val;\n }\n });\n\n //spanners.forEach(function(cell){\n for (let k = spanners.length - 1; k >= 0; k--) {\n let cell = spanners[k];\n let span = cell[colSpan];\n let col = cell[x];\n let existingWidth = result[col];\n let editableCols = typeof vals[col] === 'number' ? 0 : 1;\n if (typeof existingWidth === 'number') {\n for (let i = 1; i < span; i++) {\n existingWidth += 1 + result[col + i];\n if (typeof vals[col + i] !== 'number') {\n editableCols++;\n }\n }\n } else {\n existingWidth = desiredWidth === 'desiredWidth' ? cell.desiredWidth - 1 : 1;\n if (!auto[col] || auto[col] < existingWidth) {\n auto[col] = existingWidth;\n }\n }\n\n if (cell[desiredWidth] > existingWidth) {\n let i = 0;\n while (editableCols > 0 && cell[desiredWidth] > existingWidth) {\n if (typeof vals[col + i] !== 'number') {\n let dif = Math.round((cell[desiredWidth] - existingWidth) / editableCols);\n existingWidth += dif;\n result[col + i] += dif;\n editableCols--;\n }\n i++;\n }\n }\n }\n\n Object.assign(vals, result, auto);\n for (let j = 0; j < vals.length; j++) {\n vals[j] = Math.max(forcedMin, vals[j] || 0);\n }\n };\n}\n","const debug = require('./debug');\nconst utils = require('./utils');\nconst tableLayout = require('./layout-manager');\n\nclass Table extends Array {\n constructor(opts) {\n super();\n\n const options = utils.mergeOptions(opts);\n Object.defineProperty(this, 'options', {\n value: options,\n enumerable: options.debug,\n });\n\n if (options.debug) {\n switch (typeof options.debug) {\n case 'boolean':\n debug.setDebugLevel(debug.WARN);\n break;\n case 'number':\n debug.setDebugLevel(options.debug);\n break;\n case 'string':\n debug.setDebugLevel(parseInt(options.debug, 10));\n break;\n default:\n debug.setDebugLevel(debug.WARN);\n debug.warn(`Debug option is expected to be boolean, number, or string. Received a ${typeof options.debug}`);\n }\n Object.defineProperty(this, 'messages', {\n get() {\n return debug.debugMessages();\n },\n });\n }\n }\n\n toString() {\n let array = this;\n let headersPresent = this.options.head && this.options.head.length;\n if (headersPresent) {\n array = [this.options.head];\n if (this.length) {\n array.push.apply(array, this);\n }\n } else {\n this.options.style.head = [];\n }\n\n let cells = tableLayout.makeTableLayout(array);\n\n cells.forEach(function (row) {\n row.forEach(function (cell) {\n cell.mergeTableOptions(this.options, cells);\n }, this);\n }, this);\n\n tableLayout.computeWidths(this.options.colWidths, cells);\n tableLayout.computeHeights(this.options.rowHeights, cells);\n\n cells.forEach(function (row) {\n row.forEach(function (cell) {\n cell.init(this.options);\n }, this);\n }, this);\n\n let result = [];\n\n for (let rowIndex = 0; rowIndex < cells.length; rowIndex++) {\n let row = cells[rowIndex];\n let heightOfRow = this.options.rowHeights[rowIndex];\n\n if (rowIndex === 0 || !this.options.style.compact || (rowIndex == 1 && headersPresent)) {\n doDraw(row, 'top', result);\n }\n\n for (let lineNum = 0; lineNum < heightOfRow; lineNum++) {\n doDraw(row, lineNum, result);\n }\n\n if (rowIndex + 1 == cells.length) {\n doDraw(row, 'bottom', result);\n }\n }\n\n return result.join('\\n');\n }\n\n get width() {\n let str = this.toString().split('\\n');\n return str[0].length;\n }\n}\n\nTable.reset = () => debug.reset();\n\nfunction doDraw(row, lineNum, result) {\n let line = [];\n row.forEach(function (cell) {\n line.push(cell.draw(lineNum));\n });\n let str = line.join('');\n if (str.length) result.push(str);\n}\n\nmodule.exports = Table;\n","module.exports = require('./src/table');","let p = process || {}, argv = p.argv || [], env = p.env || {}\nlet isColorSupported =\n\t!(!!env.NO_COLOR || argv.includes(\"--no-color\")) &&\n\t(!!env.FORCE_COLOR || argv.includes(\"--color\") || p.platform === \"win32\" || ((p.stdout || {}).isTTY && env.TERM !== \"dumb\") || !!env.CI)\n\nlet formatter = (open, close, replace = open) =>\n\tinput => {\n\t\tlet string = \"\" + input, index = string.indexOf(close, open.length)\n\t\treturn ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close\n\t}\n\nlet replaceClose = (string, close, replace, index) => {\n\tlet result = \"\", cursor = 0\n\tdo {\n\t\tresult += string.substring(cursor, index) + replace\n\t\tcursor = index + close.length\n\t\tindex = string.indexOf(close, cursor)\n\t} while (~index)\n\treturn result + string.substring(cursor)\n}\n\nlet createColors = (enabled = isColorSupported) => {\n\tlet f = enabled ? formatter : () => String\n\treturn {\n\t\tisColorSupported: enabled,\n\t\treset: f(\"\\x1b[0m\", \"\\x1b[0m\"),\n\t\tbold: f(\"\\x1b[1m\", \"\\x1b[22m\", \"\\x1b[22m\\x1b[1m\"),\n\t\tdim: f(\"\\x1b[2m\", \"\\x1b[22m\", \"\\x1b[22m\\x1b[2m\"),\n\t\titalic: f(\"\\x1b[3m\", \"\\x1b[23m\"),\n\t\tunderline: f(\"\\x1b[4m\", \"\\x1b[24m\"),\n\t\tinverse: f(\"\\x1b[7m\", \"\\x1b[27m\"),\n\t\thidden: f(\"\\x1b[8m\", \"\\x1b[28m\"),\n\t\tstrikethrough: f(\"\\x1b[9m\", \"\\x1b[29m\"),\n\n\t\tblack: f(\"\\x1b[30m\", \"\\x1b[39m\"),\n\t\tred: f(\"\\x1b[31m\", \"\\x1b[39m\"),\n\t\tgreen: f(\"\\x1b[32m\", \"\\x1b[39m\"),\n\t\tyellow: f(\"\\x1b[33m\", \"\\x1b[39m\"),\n\t\tblue: f(\"\\x1b[34m\", \"\\x1b[39m\"),\n\t\tmagenta: f(\"\\x1b[35m\", \"\\x1b[39m\"),\n\t\tcyan: f(\"\\x1b[36m\", \"\\x1b[39m\"),\n\t\twhite: f(\"\\x1b[37m\", \"\\x1b[39m\"),\n\t\tgray: f(\"\\x1b[90m\", \"\\x1b[39m\"),\n\n\t\tbgBlack: f(\"\\x1b[40m\", \"\\x1b[49m\"),\n\t\tbgRed: f(\"\\x1b[41m\", \"\\x1b[49m\"),\n\t\tbgGreen: f(\"\\x1b[42m\", \"\\x1b[49m\"),\n\t\tbgYellow: f(\"\\x1b[43m\", \"\\x1b[49m\"),\n\t\tbgBlue: f(\"\\x1b[44m\", \"\\x1b[49m\"),\n\t\tbgMagenta: f(\"\\x1b[45m\", \"\\x1b[49m\"),\n\t\tbgCyan: f(\"\\x1b[46m\", \"\\x1b[49m\"),\n\t\tbgWhite: f(\"\\x1b[47m\", \"\\x1b[49m\"),\n\n\t\tblackBright: f(\"\\x1b[90m\", \"\\x1b[39m\"),\n\t\tredBright: f(\"\\x1b[91m\", \"\\x1b[39m\"),\n\t\tgreenBright: f(\"\\x1b[92m\", \"\\x1b[39m\"),\n\t\tyellowBright: f(\"\\x1b[93m\", \"\\x1b[39m\"),\n\t\tblueBright: f(\"\\x1b[94m\", \"\\x1b[39m\"),\n\t\tmagentaBright: f(\"\\x1b[95m\", \"\\x1b[39m\"),\n\t\tcyanBright: f(\"\\x1b[96m\", \"\\x1b[39m\"),\n\t\twhiteBright: f(\"\\x1b[97m\", \"\\x1b[39m\"),\n\n\t\tbgBlackBright: f(\"\\x1b[100m\", \"\\x1b[49m\"),\n\t\tbgRedBright: f(\"\\x1b[101m\", \"\\x1b[49m\"),\n\t\tbgGreenBright: f(\"\\x1b[102m\", \"\\x1b[49m\"),\n\t\tbgYellowBright: f(\"\\x1b[103m\", \"\\x1b[49m\"),\n\t\tbgBlueBright: f(\"\\x1b[104m\", \"\\x1b[49m\"),\n\t\tbgMagentaBright: f(\"\\x1b[105m\", \"\\x1b[49m\"),\n\t\tbgCyanBright: f(\"\\x1b[106m\", \"\\x1b[49m\"),\n\t\tbgWhiteBright: f(\"\\x1b[107m\", \"\\x1b[49m\"),\n\t}\n}\n\nmodule.exports = createColors()\nmodule.exports.createColors = createColors\n","// mu — the message table: most error and hint lines an agent reads, in ONE place.\n//\n// A line is `MESSAGES[\"<domain>.<what>\"]`, a function of the facts it names, rendered\n// with `say(key, ...facts)`. The key is stable; the wording is free to change (t_errors\n// hill-climbs one line at a time). Classification, exit codes, typed error classes,\n// structured fields and guards never read the prose: they live at the throw site.\n// Leaf module: it imports nothing, so any file may use it.\n\nexport const MESSAGES = {\n // ── task errors (src/tasks/errors.ts, id.ts, claim.ts, task-auto.ts) ──\n \"task.not_found\": (id: string) => `no such task: ${id}`,\n \"task.id_invalid\": (attempted: string) =>\n `invalid task id: ${JSON.stringify(attempted)} (expected /^[a-z][a-z0-9_-]{0,63}$/)`,\n \"task.slug_empty\": (title: string) =>\n `title yields empty slug: ${JSON.stringify(title)} (no ASCII letter or digit to derive an id from); pass one: mu task add <id> -t \"...\"`,\n \"task.exists\": (id: string) => `task already exists: ${id}`,\n \"task.not_in_workstream\": (id: string, expected: string, actual: string) =>\n `task ${id} is in workstream ${actual}, not ${expected}; pass -w ${actual}`,\n \"task.owned\": (id: string, owner: string) => `task ${id} is already owned by ${owner}`,\n \"task.owned_sql\": () =>\n \"a claim in this SQL would take an owned task; release it first: mu task release <id> -w <ws>\",\n \"task.claimer_unregistered\": (name: string, pane: string | null) =>\n `claimer '${name}'${pane !== null ? ` (pane ${pane})` : \"\"} is not a registered mu agent (no row in agents table)`,\n \"task.cycle\": (from: string, to: string, path: readonly string[]) =>\n path.length > 1\n ? `adding edge ${from} -> ${to} would create a cycle: ${[from, ...path].join(\" -> \")}`\n : `adding edge ${from} -> ${to} would create a cycle`,\n \"task.cross_workstream_edge\": (blocker: string, bws: string, dependent: string, dws: string) =>\n `cross-workstream edge: blocker '${blocker}' is in workstream '${bws}', dependent '${dependent}' is in workstream '${dws}'`,\n \"task.close_reason_needed\": (verb: \"close\" | \"park\", id: string, substate: string) =>\n verb === \"close\"\n ? `closing ${id} as ${substate} needs a reason (--why \"...\")`\n : `parking ${id} needs a reason (--why \"...\")`,\n \"task.close_needs_evidence\": (id: string, ws: string) =>\n `closing ${id} needs evidence: mu task close ${id} -w ${ws} --evidence \"<command + result>\"`,\n \"task.close_needs_evidence_sql\": () =>\n 'a close in this SQL has no close note; close with: mu task close <id> -w <ws> --evidence \"<command + result>\"',\n \"task.open_blockers\": (id: string, blockers: readonly string[]) =>\n `task ${id} has open blockers: ${blockers.join(\", \")}`,\n \"task.open_blockers_sql\": () =>\n \"a task in this SQL closed as done with open blockers; inspect with: mu task tree <id> -w <ws>\",\n \"task.park_state\": (id: string, status: \"IN_PROGRESS\" | \"CLOSED\") =>\n status === \"IN_PROGRESS\"\n ? `cannot park ${id}: it is IN_PROGRESS (release it first)`\n : `cannot park ${id}: it is CLOSED (open it first)`,\n \"task.in_triage\": (id: string) =>\n `task ${id} is in triage (OPEN/triage); accept it or claim with --force`,\n \"task.parked\": (id: string) =>\n `task ${id} is parked (OPEN/parked); unpark it or claim with --force`,\n \"task.human\": (id: string, ws: string, action: string) =>\n `task ${id} is a human task: ${action} refused; it resolves only by an explicit \\`mu task close ${id} -w ${ws}\\``,\n \"task.invalid_substate\": (status: string, substate: string, expected: readonly string[]) =>\n `invalid substate for ${status}: ${JSON.stringify(substate)} (expected one of: ${expected.join(\", \")})`,\n \"task.note_range\": (id: string, n: number, total: number) =>\n total === 0\n ? `${id} has no notes; note ${n} does not exist`\n : `note ${n} is not one of ${id}'s notes (1..${total})`,\n \"task.claim_self_and_for\": () => \"--self and --for are mutually exclusive\",\n \"task.claim_no_claimer\": () =>\n \"no claimer: pass --for <worker> (dispatch), --self (orchestrator), or run in a mu-spawned pane\",\n \"task.claim_no_agent\": () =>\n \"no agent name (pass opts.agentName, run inside an mu-spawned pane with $MU_AGENT_NAME set, or pass --self for an anonymous claim)\",\n \"task.auto_cli_required\": () =>\n \"--cli <key> is required (the model key `mu next` spawns); or --off\",\n \"task.auto_reserved_ws\": (ws: string) =>\n `workstream '${ws}' is the delegate queue; it is never auto-dispatched`,\n \"task.auto_cli_key\": (cli: string) =>\n `--cli must be a model key like pi or pi-big (got ${JSON.stringify(cli)})`,\n \"task.auto_max\": (max: number) => `--max must be an integer >= 1 (got ${max})`,\n \"task.auto_no_blockers\": (umbrella: string) => `${umbrella} has no open blockers to authorise`,\n \"task.auto_none_given\": () => \"no tasks given\",\n\n // ── agent errors (src/agents/errors.ts) ──\n \"agent.cli_not_found\": (cli: string, binary: string, envVar: string) =>\n `--cli ${cli} resolved to binary \"${binary}\" which is not on PATH (and not an executable absolute/relative path). Refusing to spawn — would create a pane that dies immediately on \"command not found\". For a custom alias, set ${envVar} to its real path.`,\n \"agent.exists\": (name: string) => `agent already exists in this workstream: ${name}`,\n \"agent.name_exhausted\": (name: string, reason: string) =>\n `no free agent name after ${name}: ${reason}`,\n \"agent.not_found\": (name: string, ws: string | undefined) =>\n ws === undefined ? `no such agent: ${name}` : `no such agent: ${name} (in workstream ${ws})`,\n \"agent.not_in_workstream\": (name: string, expected: string, actual: string) =>\n `agent ${name} is in workstream ${actual}, not ${expected}; pass -w ${actual}`,\n \"agent.scrollback\": (text: string) =>\n `\\n\\n--- pane scrollback ---\\n${text}\\n--- end scrollback ---`,\n \"agent.died_cause_remote\": (host: string | undefined) =>\n `The pane is a remote transport${host === undefined ? \"\" : ` (host ${host})`}, so the likely causes are remote: the remote binary is missing, or its env (PATH, provider keys) is absent because a non-interactive shell skips ~/.zshrc / ~/.bashrc (the profile's shell template should run \\`$SHELL -ilc\\`); or the host refused the socket forward (check AllowStreamLocalForwarding).`,\n \"agent.died_cause_local\": () =>\n \"Most common cause: the spawned CLI exited immediately (e.g. a wrapper CLI blocking on its instance lock; set MU_<UPPER_CLI>_COMMAND to a non-blocking variant to bypass).\",\n \"agent.died_on_spawn\": (\n name: string,\n when: string,\n pane: string,\n cause: string,\n detail: string,\n ) => `agent ${name} died ${when} (pane ${pane}). ${cause}${detail}`,\n \"agent.startup_error\": (name: string, when: string, pane: string, line: string, scroll: string) =>\n `agent ${name} reported a startup error ${when} (pane ${pane}). The pane is alive but the spawned CLI parked at an error prompt instead of becoming a working agent.\\n\\nMatched line: ${line}${scroll}`,\n \"agent.ctl_unreachable\": (name: string, kind: string, socket: string) =>\n `agent ${name} has no control socket (ctl: ${kind}) at ${socket}; mu cannot send to or wait on it exactly`,\n \"agent.send_indeterminate\": (name: string, op: string, reason: string, msgId?: string) =>\n `agent ${name}: ${op} was written to its control socket but no reply arrived (${reason}); delivery unknown${msgId === undefined ? \"\" : `, msgId ${msgId}`}. Never resend blindly`,\n \"agent.restarted\": (name: string, expected: string, actual: string | undefined) =>\n `agent ${name} restarted (incarnation ${expected} → ${actual ?? \"unknown\"}); its earlier run is gone: re-send the brief`,\n \"agent.pane_still_alive\": (\n name: string,\n ws: string,\n pane: string,\n state: true | \"unknown\",\n reason?: string,\n ) =>\n state === true\n ? `agent ${name}: pane ${pane} is still alive after the kill; its row is kept. Close the pane in your multiplexer, then preview: mu agent close ${name} -w ${ws}`\n : `agent ${name}: pane ${pane} could not be checked${reason === undefined ? \"\" : ` (${reason})`}; its row, tasks and worktree are kept. Retry once the multiplexer answers, or if you know the pane is gone preview with --force: mu agent close ${name} -w ${ws} --force`,\n \"agent.replaced\": (name: string, ws: string, during: \"closed\" | \"sent to\" | \"collected\") =>\n during === \"closed\"\n ? `agent ${name} was replaced while it was being closed; the replacement was left alone. Preview it: mu agent close ${name} -w ${ws}`\n : during === \"collected\"\n ? `agent ${name} was replaced while its commits were being collected; the replacement's record was left alone. Look at it: mu agent list -w ${ws}`\n : `agent ${name} was replaced before the prompt was written; nothing was sent to the replacement. Look at it: mu agent list -w ${ws}`,\n \"agent.lock_busy\": (name: string, ws: string) =>\n `agent ${name} is being changed by another mu process (its lock is held); nothing was done. Retry: mu agent close ${name} -w ${ws}`,\n \"agent.pane_dead\": (name: string, pane: string, msgId?: string) =>\n `agent ${name} is dead: its pane ${pane} no longer exists, so its control socket is gone${msgId === undefined ? \"\" : `; a send (msgId ${msgId}) was written first, so delivery is unknown`}`,\n \"agent.abort_needs_ctl\": (name: string, cli: string) =>\n `agent ${name} runs ${cli}, not pi: abort needs the mu pi extension; close the agent instead`,\n \"agent.abort_timeout\": (name: string, ms: number) =>\n `agent ${name} was still busy ${ms}ms after the abort`,\n \"agent.fresh_needs_ctl\": (name: string, cli: string) =>\n `agent ${name} runs ${cli} without a control socket: --fresh needs the mu pi extension`,\n \"agent.extension_outdated\": (name: string, version: string, feature: boolean, op: string) =>\n `agent ${name}'s mu pi extension (${version}) predates ${feature ? \"feature\" : \"op\"} ${op}: its pi loaded an older mu build; reload or respawn it`,\n \"agent.busy\": (name: string, command: string) =>\n `agent ${name} is busy: ${command} would abandon its running turn`,\n \"agent.slash_unsupported\": (name: string, supported: readonly string[], text: string) =>\n `agent ${name} runs pi: over the control socket mu runs only ${supported.join(\", \")}; ${JSON.stringify(text.split(\"\\n\")[0])} is not one of them; type it in the pane yourself`,\n \"agent.empty_send\": (name: string) =>\n `agent ${name} runs pi: an empty message cannot go over the control socket; press Enter in the pane yourself`,\n \"agent.send_unsupported\": (name: string, cli: string) =>\n `agent ${name} runs ${cli}, not pi: tmux has no reliable send for it; spawn it on herdr (MU_MUX=herdr), start it with the prompt as an argument (--command \"${cli} '<prompt>'\"), or use pi`,\n \"agent.send_refused\": (reason: string) => `control socket refused the send: ${reason}`,\n \"agent.attempt_busy\": (task: string, key: string) =>\n `spawn attempt ${key} of task ${task} is running in another mu process; nothing was done. Retry when it finishes (the replay returns its outcome)`,\n \"agent.attempt_failed\": (task: string, key: string, reason: string) =>\n `attempt ${key} of task ${task} cannot run: ${reason}; nothing was sent`,\n \"agent.attempt_stopped\": (task: string, key: string, reason: string) =>\n `attempt ${key} of task ${task} was stopped: ${reason}`,\n \"agent.task_state\": (task: string, reason: string) => `task ${task} ${reason}; nothing was sent`,\n \"agent.receipt_conflict\": (task: string, key: string, savedName: string) =>\n `attempt ${key} of task ${task} already ran with a different request (agent ${savedName}); a second prompt is a new attempt: pass --attempt <new key>`,\n \"agent.trust_dialog\": (name: string) =>\n `agent ${name} is showing Claude's folder-trust dialog (default \"No, exit\"); the task prompt was not sent and the spawn was rolled back`,\n // ── task verbs (src/cli/tasks/*) ──\n \"task.add_titles\": (ids: readonly string[], titles: number) =>\n `${ids.length} id(s) (${ids.join(\" \")}) need ${ids.length} -t/--title, got ${titles}. If text was split by an apostrophe inside '...', pass long text with a quoted heredoc: --note - <<'EOF'`,\n \"task.add_nothing\": () => \"task add: nothing to add\",\n \"task.add_truncated\": (id: string) =>\n `hint: id '${id}' truncated from a longer slug; pass <id> positional to override (mu task add <id> --title ... ).\\n`,\n \"task.note_twice\": (names: readonly string[]) =>\n `note text given twice (${names.join(\" and \")}): pass it once, positionally or via -m/--message/--note/--text`,\n \"task.note_required\": () =>\n 'note text required: mu task note <id> \"...\" (or -m/--message/--note/--text \"...\")',\n \"task.note_kind_twice\": () => \"--report and --kind both set the note kind: pass one\",\n \"task.note_unseen\": (owner: string, ws: string) =>\n `${owner} will not see this note: send it (mu agent send ${owner} -w ${ws} --steer, or --interrupt if the note makes the current work wasted)`,\n \"task.notes_all_from\": () =>\n \"--all/--from pick a page of the whole history; they do not combine with --tail/--since/--since-claim\",\n \"task.notes_all_is_from\": () => \"--all is --from 1; pass one of them\",\n \"task.notes_since_twice\": () =>\n \"--since and --since-claim are mutually exclusive (both define a cutoff); pick one\",\n \"task.notes_tail\": (tail: unknown) =>\n `--tail must be a positive integer (got ${JSON.stringify(tail)})`,\n \"task.notes_since\": (since: unknown) =>\n `--since must be an ISO 8601 timestamp (got ${JSON.stringify(since)})`,\n \"task.update_nothing\": () =>\n \"nothing to update; pass at least one of --title, --impact, --effort-days\",\n \"task.by_required\": () => \"-b/--by requires at least one blocker task id\",\n \"task.claim_and_wait\": () =>\n \"--and-wait needs --for <worker>: a dispatch has something to wait on; --self and a worker's own claim would wait on the caller's own work\",\n \"task.claim_actor\": () => \"--actor only meaningful with --self (it overrides the actor name)\",\n \"task.wait_ids\": () => \"mu task wait: at least one task id is required\",\n \"task.close_note_alias\": () => \"--note is an alias of --evidence: pass one of them\",\n \"task.close_uncommitted\": (path: string, commit: string) =>\n `uncommitted changes in ${path}; don't forget to commit: ${commit}`,\n \"task.list_owner_mine\": () => \"--owner and --mine pick the owner two ways; pass one of them\",\n\n // ── agent verbs (src/cli/agents.ts, agent-collect.ts, src/agents/*) ──\n \"agent.spawn_cwd_worktree\": () => \"--cwd conflicts with --worktree (the worktree is the cwd)\",\n \"agent.spawn_needs_worktree\": (flag: string) => `--${flag} requires --worktree`,\n \"agent.spawn_gate_flag\": (flag: string) =>\n `--${flag} cannot be used with a remote command gate (--host with a non-pi --command): it runs one command and reports its exit; wait on it`,\n \"agent.spawn_gate_worktree\": () =>\n \"--worktree cannot be used with a remote command gate (--host with a non-pi --command): a gate runs in --cwd, else the profile's default repo\",\n \"agent.spawn_attempt_task\": () => \"--attempt needs --task\",\n \"agent.spawn_task_default\": (task: string, ws: string, title: string) =>\n `Task ${task} (workstream ${ws}): ${title}. Read: mu task notes ${task} -w ${ws}`,\n \"agent.spawn_name_hint\": (name: string) =>\n `hint: agent name \"${name}\" does not match the smallest-unused-suffix convention (<role>-<n>; e.g. worker-1, reviewer-2). Accepted; consider renaming if you spawn additional workers.\\n`,\n \"agent.spawn_trust_warning\": (name: string, skipped: boolean) =>\n `${name} is showing Claude's folder-trust dialog (default \"No, exit\")${skipped ? \"; --send skipped\" : \"\"}`,\n \"agent.send_interrupt_excl\": (flag: string) => `--interrupt and ${flag} are mutually exclusive`,\n \"agent.send_interrupt_slash\": () => \"--interrupt sends a prompt, not a slash command\",\n \"agent.send_interrupt_empty\": () => \"--interrupt needs a non-empty prompt\",\n \"agent.send_timeout\": () => \"--timeout only applies with --interrupt\",\n \"agent.send_force\": () => \"--force only applies with --fresh or a /new, /reload, /compact\",\n \"agent.send_fresh_steer\": () => \"--fresh and --steer are mutually exclusive\",\n \"agent.send_wait_sig\": () => \"--wait needs the wait's signal handlers\",\n \"agent.send_wait_slash\": () =>\n \"--wait waits for the run a prompt starts; a slash command starts none\",\n \"agent.send_undelivered\": (why: string) =>\n `${why}; not waiting for a run that may never have started`,\n \"agent.check_not_accepted\": (name: string, msgId: string) =>\n `${name}: message ${msgId} was not accepted (an evicted or in-flight send reads the same): read the pane before any resend`,\n \"agent.wait_names\": () => \"mu agent wait: at least one agent name is required\",\n \"agent.wait_after_runs_pi\": (ref: string, cli: string) =>\n `--after-runs needs a pi agent (control socket); ${ref} runs ${cli}. Drop --after-runs to wait on its pane state.`,\n \"agent.wait_inc_one\": () => \"--inc names one pi process: wait on one agent at a time\",\n \"agent.wait_inc_pi\": (ref: string, cli: string) =>\n `--inc needs a pi agent (control socket); ${ref} runs ${cli}. Drop --inc.`,\n \"agent.wait_unknown\": (names: string, reasons: string) =>\n `mu agent wait: state unknown for ${names} (${reasons}); waiting until --timeout\\n`,\n \"agent.collect_cwd\": () =>\n \"agent collect fetches into the git repo of the current directory: cd into it\",\n \"agent.ctl_refused\": (what: string, error: unknown) => `control socket refused ${what}: ${error}`,\n \"agent.pi_refused\": (cmd: string, error: unknown) => `pi refused /${cmd}: ${error}`,\n // ── db, mux, sync, host, remote, workstream, worktree (src/*.ts, src/mux/*) ──\n \"db.test_real_db\": (realDb: string) =>\n `openDb refused: tests must NEVER write to the user DB (${realDb}). Set MU_DB_PATH to a per-test temp path (test/_runCli.ts does this automatically) or pass an explicit { path } argument. The leak source is the call site of openDb in this stack frame.`,\n \"db.schema_old\": (detected: number, required: number) =>\n `Detected v${detected} schema; v${required} is required. mu ships NO in-place migration — your v${detected} DB is untouched. Back it up or move it aside, then start a fresh v${required} DB.`,\n \"db.schema_new\": (detected: number, supported: number, stamp: \"schema\" | \"capture\") =>\n stamp === \"schema\"\n ? `DB is v${detected}; this mu understands up to v${supported}. Upgrade mu.`\n : `DB's capture triggers are revision ${detected}; this mu understands up to ${supported}. Upgrade mu.`,\n \"db.sqlite_old\": (version: string) =>\n `SQLite ${version} is too old; mu needs >= 3.42 (unixepoch('subsec') for the op clock). The DB was not touched.`,\n \"workstream.not_found\": (ws: string, near: readonly string[] = [], init = false) =>\n `no such workstream: ${ws}${near.length > 0 ? ` (did you mean ${near.join(\", \")}?)` : \"\"}${\n init ? `; \\`mu workstream init ${ws}\\` creates it` : \"\"\n }`,\n \"workstream.torn_down\": (ws: string, at: string) =>\n `workstream ${ws} is torn down (at ${at}); \\`mu workstream init ${ws}\\` to reuse the name`,\n \"workstream.exists\": (ws: string) => `workstream already exists: ${ws}`,\n \"workstream.name_invalid\": (attempted: string, reservedPrefix: boolean) =>\n `invalid workstream name ${JSON.stringify(attempted)}: ${\n reservedPrefix\n ? `the 'mu-' prefix is reserved (mu adds it to the tmux session name, so '${attempted}' would be double-prefixed as 'mu-${attempted}'). Drop the 'mu-' from the name.`\n : `use [a-z][a-z0-9_-]{0,31}`\n }`,\n \"workstream.name_reserved\": (attempted: string) =>\n `workstream name ${JSON.stringify(attempted)} is reserved: it is the off-the-cuff bucket and auto-creates on first spawn. Don't 'init' it.`,\n \"workstream.changed\": (ws: string, expected: number, actual: number, preview: string) =>\n `workstream ${ws} changed since preview (rev ${expected} → ${actual}); preview again: ${preview}`,\n \"workstream.has_agents\": (ws: string, agents: readonly string[]) =>\n `torn-down workstream ${ws} still has ${agents.length} local agent row${agents.length === 1 ? \"\" : \"s\"} (${agents.join(\", \")}); close each once its pane is gone (preview, then apply with --if): mu agent close ${agents[0]} -w ${ws}`,\n \"workstream.panes_live\": (ws: string, agents: readonly string[]) =>\n `workstream ${ws} has live panes outside its session (${agents.join(\", \")}); close them first (preview, then apply with --if): mu agent close ${agents[0]} -w ${ws}`,\n \"workstream.session_live\": (ws: string, session: string) =>\n `torn-down workstream ${ws} still has a live mux session ${session}; kill it first: mu workstream teardown ${ws}`,\n \"worktree.vcs_required\": (root: string) =>\n `--worktree requires a git repository; ${root} is not inside one`,\n \"worktree.dirty\": (agent: string, path: string, shown: readonly string[], more: number) =>\n `agent ${agent} has uncommitted work in ${path}; refusing to close: ${\n shown.length > 0 ? shown.join(\", \") : \"git status unreadable\"\n }${more > 0 ? ` (+${more} more)` : \"\"}`,\n \"worktree.path_not_empty\": (agent: string, path: string, why: string) =>\n `worktree dir already on disk for agent ${agent} (${path}): ${why}; refusing to overwrite`,\n \"worktree.branch_exists\": (agent: string, ws: string, path: string, branch: string) =>\n `agent ${agent}: branch ${branch} already exists at another commit; ${path} was kept and nothing was moved. Rename that branch, then preview: mu agent close ${agent} -w ${ws}`,\n \"worktree.held\": (\n agent: string,\n ws: string,\n path: string,\n writer: { pid: number; command: string } | undefined,\n ) =>\n writer === undefined\n ? `agent ${agent}: nothing could prove that no process is writing in ${path} (no /proc, no lsof); it was kept. If you know none is, preview with --force: mu agent close ${agent} -w ${ws} --force`\n : `agent ${agent}: process ${writer.pid}${writer.command === \"\" ? \"\" : ` (${writer.command})`} has a file in ${path} open for writing; it was kept. Stop it and preview again, or to remove the tree under it preview with --force: mu agent close ${agent} -w ${ws} --force`,\n \"worktree.holder_left\": (path: string, h: { pid: number; command: string; writer: boolean }) =>\n `process ${h.pid}${h.command === \"\" ? \"\" : ` (${h.command})`} was still ${h.writer ? \"writing in\" : \"inside\"} ${path} (${h.writer ? \"a file open for writing; --force\" : \"its cwd or a file open for reading\"}); the tree was removed under it`,\n \"worktree.holders_unproven\": (path: string) =>\n `nothing could check for processes in ${path} (no /proc, no lsof); it was removed without git's --force`,\n \"worktree.holders_hidden\": (path: string, pids: readonly number[]) =>\n `could not inspect ${pids.length} process${pids.length === 1 ? \"\" : \"es\"} of yours (${pids.slice(0, 5).join(\", \")}${pids.length > 5 ? \", ...\" : \"\"}; /proc refused: non-dumpable or another namespace); mu cannot say whether ${pids.length === 1 ? \"it was\" : \"they were\"} in ${path}`,\n \"worktree.unmerged_repo_gone\": (path: string) =>\n `worktree ${path} has unmerged commits and its repo is gone; nothing can keep them (use --discard to drop them)`,\n \"revision.changed\": (subject: string, expected: number, current: number, preview: string) =>\n `${subject} changed since preview (rev ${expected} → ${current}); preview again: ${preview}`,\n \"mux.pane_not_found\": (backend: string, pane: string) => `${backend} pane not found: ${pane}`,\n \"mux.none_found\": (tried: readonly string[]) =>\n `no supported multiplexer found (tried: ${tried.join(\", \")}); install tmux ≥ 3.0 (task, DAG and sql verbs work without one)`,\n \"mux.tmux_failed\": (args: readonly string[], exit: number | null, detail: string) =>\n `tmux ${args.join(\" \")} failed (exit ${exit}): ${detail}`,\n \"mux.herdr_failed\": (args: readonly string[], exit: number | null, detail: string) =>\n `herdr ${args.join(\" \")} failed (exit ${exit}): ${detail}`,\n \"mux.herdr_syntax\": (args: readonly string[], firstLine: string) =>\n `herdr rejected the command line (exit 2) — this is a bug in mu, not a herdr outage. Ran: herdr ${args.join(\" \")}. herdr said: ${firstLine}`,\n \"mux.herdr_unsupported_cli\": (cli: string, detail: string) =>\n `herdr does not recognise --cli ${cli} as an interactive agent kind, so it cannot classify that pane's status. herdr said: ${detail}`,\n \"mux.herdr_command_override\": (cli: string, what: string) =>\n `${what} cannot be honoured on the herdr backend: 'herdr agent start --kind ${cli}' resolves the executable itself and has no override flag. mu refuses rather than starting a different binary than you asked for.`,\n \"mux.herdr_group_close\": (workspaceId: string, session: string, detail: string) =>\n `herdr refused to close workspace ${workspaceId} (${session}): it has linked worktree workspaces, which mu did not create and will not close on your behalf. herdr said: ${detail}`,\n \"mux.herdr_no_panes\": (tab: string, session: string) =>\n `spawnAgent: tab ${tab} in session ${session} has no panes to split (it vanished mid-spawn?)`,\n \"mux.unknown_backend\": (name: string) => `unknown mux backend: ${name}`,\n \"sync.peer_not_found\": (ref: string, known: readonly string[]) =>\n `no peer matches ${JSON.stringify(ref)}${\n known.length === 0 ? \" (no peers discovered)\" : ` (known peers: ${known.join(\", \")})`\n }`,\n \"sync.peer_ambiguous\": (ref: string, candidates: readonly string[]) =>\n `peer ref ${JSON.stringify(ref)} matches ${candidates.length} peers (${candidates.join(\", \")}); pass more characters`,\n \"sync.source_missing\": (path: string) => `--from: no such file: ${path}`,\n \"sync.source_too_new\": (path: string, detected: number, supported: number) =>\n `--from: ${path} is schema v${detected}; this mu understands up to v${supported}. Upgrade mu.`,\n \"host.not_found\": (host: string) => `no host profile named ${host}`,\n \"host.exists\": (host: string) =>\n `host profile ${host} already exists: remove it first (mu host rm ${host})`,\n \"host.in_use\": (host: string, holders: readonly string[]) =>\n `host ${host} still holds channels (${holders.join(\", \")}): close those agents first`,\n \"host.spawn_unsupported\": (host: string, mux: string) =>\n `--host ${host} needs a multiplexer that runs a shell command in its pane; ${mux} starts agents itself and cannot run the profile's shell template (use tmux)`,\n \"host.check_failed\": (host: string, failed: readonly string[]) =>\n `host ${host} check failed: ${failed.join(\", \")}`,\n \"host.channel_lost\": (host: string, holder: string) => `host ${host}: channel ${holder} was lost`,\n \"remote.prepare\": (host: string, what: string, detail: string) =>\n `host ${host}: ${what}${detail === \"\" ? \"\" : `: ${detail}`}`,\n \"remote.worktree_kept\": (agent: string, detail: string) =>\n `agent ${agent}: remote worktree kept: ${detail}`,\n \"remote.no_worktree\": (agent: string) => `agent ${agent} has no remote worktree`,\n \"remote.collect_unsupported\": (agent: string, why: string) =>\n `agent ${agent}: nothing to collect: ${why}`,\n \"remote.collect_failed\": (host: string, detail: string) =>\n `host ${host}: collect failed: ${detail}`,\n \"remote.recovery_refused\": (ws: string, agent: string, detail: string) =>\n `agent ${ws}/${agent}: remote recovery refused: ${detail}`,\n \"rebuild.target_exists\": (path: string) => `rebuild target already exists: ${path}`,\n \"rebuild.target_is_source\": (path: string) => `rebuild target is the source DB: ${path}`,\n \"rebuild.no_identity\": () => \"source DB has no machine_identity row; not a mu DB\",\n \"log.group_ambiguous\": (prefix: string, count: number, shown: readonly string[], more: boolean) =>\n `group id ${JSON.stringify(prefix)} is ambiguous: matches ${count} groups (${shown.join(\", \")}${more ? \", …\" : \"\"})`,\n \"log.group_not_found\": (prefix: string) => `no op group matching ${JSON.stringify(prefix)}`,\n \"log.kind_reserved\": (kind: string, reserved: readonly string[]) =>\n `--kind ${JSON.stringify(kind)} is reserved: ${reserved.join(\", \")} name projectable op entities, and a log line under one would be synced and replayed as a real ${kind} change`,\n \"delegate.conflict\": (callId: string, field: string) =>\n `delegate call ${callId} already exists with a different ${field}; a call id names one request. Use a new call id for a changed request`,\n \"delegate.state\": (callId: string, from: string, to: string) =>\n `delegate call ${callId} is ${from}; it cannot go to ${to}`,\n \"delegate.not_found\": (callId: string) => `no such delegate call: ${callId}`,\n \"wait.wave_not_found\": (wave: string, yours: readonly (string | null)[]) => {\n const names = [...new Set(yours.filter((w): w is string => w !== null))].sort();\n return `no such wave: ${wave} (your waves: ${names.length > 0 ? names.join(\", \") : \"none\"})`;\n },\n \"wait.resume_not_found\": (id: string, days: number) =>\n `no such wait resume handle: ${id} (a handle is kept ${days} days; name the refs again with \\`mu wait <ref>...\\`)`,\n \"task.brief_missing\": (task: string, reason: string) =>\n `task ${task} cannot be briefed: ${reason}`,\n} as const satisfies Record<string, (...facts: never[]) => string>;\n\nexport type MessageKey = keyof typeof MESSAGES;\n\n/** The line for `key`, filled with the facts it names. */\nexport function say<K extends MessageKey>(\n key: K,\n ...facts: Parameters<(typeof MESSAGES)[K]>\n): string {\n return (MESSAGES[key] as (...f: Parameters<(typeof MESSAGES)[K]>) => string)(...facts);\n}\n","// mu — spawnAgent + supporting helpers (resolveCliCommand,\n// awaitSpawnLiveness, defaultSpawnLivenessMs,\n// prestageWorktree, finalizeAgentRow, rollbackSpawn).\n//\n// spawnAgent's flow is documented inline. The interesting bit is the\n// `--worktree` cycle (the pane starts IN the worktree, so the worktree\n// exists before the pane, while the agent name must already be claimed) —\n// see prestageWorktree.\n\nimport { execFile } from \"node:child_process\";\nimport { existsSync, mkdirSync, rmSync, statSync } from \"node:fs\";\nimport { basename, dirname, resolve } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { promisify } from \"node:util\";\nimport {\n type AgentRow,\n deleteAgent,\n getAgent,\n insertAgent,\n isValidAgentName,\n MAX_AGENT_NAME_LEN,\n pendingPaneIdFor,\n} from \"../agents.js\";\nimport { type CtlProbe, ctlProbe } from \"../ctl/client.js\";\nimport { CTL_SOCK_ENV, ctlSocketPath } from \"../ctl/path.js\";\nimport {\n type Db,\n defaultDbPath,\n defaultStateDir,\n tornDownAtOf,\n WorkstreamTornDownError,\n} from \"../db.js\";\nimport {\n admitHostChannel,\n bindHostChannel,\n getHost,\n type HostLease,\n type HostProfile,\n HostProfileError,\n HostSpawnUnsupportedError,\n releaseHostChannel,\n releaseHostChannelsForAgent,\n} from \"../hosts.js\";\nimport { emitEvent } from \"../logs.js\";\nimport { say } from \"../messages.js\";\nimport type { CommandSource } from \"../mux/types.js\";\nimport { activeMux } from \"../mux.js\";\nimport { isJsonMode } from \"../output.js\";\nimport {\n localPaneAlive,\n prepareRemote,\n type RemoteSite,\n remoteShellCommand,\n removeRemoteWorktree,\n} from \"../remote-agent.js\";\nimport { recoveriesFor } from \"../remote-recovery.js\";\nimport { resolveActorIdentity } from \"../tasks/claim.js\";\n// `sleep` is the shared poll-sleep TEST SEAM (setSleepForTests), not a\n// multiplexer operation, so it stays on the tmux module rather than\n// joining the MuxBackend contract.\nimport { sleep } from \"../tmux.js\";\nimport { discardWorktree, git, gitToplevel, owningRoot } from \"../vcs/git.js\";\nimport { isScratchWorkstream } from \"../workstream.js\";\nimport {\n createWorktree,\n getWorktreeAt,\n reclaimWorktreePath,\n registerWorktree,\n releaseWorktree,\n WorktreeVcsRequiredError,\n worktreePath,\n} from \"../worktree.js\";\nimport {\n AgentDiedOnSpawnError,\n AgentExistsError,\n AgentNameExhaustedError,\n AgentReplacedError,\n AgentSpawnCliNotFoundError,\n AgentSpawnStartupError,\n} from \"./errors.js\";\nimport { gateWrapper, newGateToken } from \"./gate.js\";\nimport { withAgentLock } from \"./lock.js\";\nimport { withSpawnLock } from \"./spawn-lock.js\";\nimport { reclaimDeadStagings } from \"./staging.js\";\n\n/**\n * Smallest-unused-suffix naming convention for agent names: a role\n * (lowercase alpha + digits) followed by `-<n>` where `<n>` is one or\n * more digits. Examples that pass: `worker-1`, `reviewer-2`, `scout-12`.\n * Examples that warn: `worker-tests`, `alice`, `db-leader`, `x-y-1`.\n *\n * The dogfood report was operators (LLMs included) drifting to descriptive names like\n * `worker-tests` after a few spawns, breaking the convention silently.\n * The hint surfaced by `maybeWarnNonConventionalAgentName` is a lint, not\n * a rule — `isValidAgentName` still accepts the broader\n * `^[a-z][a-z0-9_-]{0,31}$` shape.\n */\nconst AGENT_NAME_CONVENTION_RE = /^[a-z][a-z0-9]*(?:-[0-9]+)$/;\n\n/**\n * Stderr lint when an agent name doesn't match the smallest-unused-suffix\n * convention. Mirrors the slugify-truncation stderr hint in cmdTaskAdd\n * (commit 28a13af): stderr-only, exit 0, suppressed under --json so\n * machine consumers stay clean. The spawn already succeeded by the time\n * this runs — we're just nudging the operator toward `<role>-<n>`.\n */\nfunction maybeWarnNonConventionalAgentName(name: string): void {\n if (AGENT_NAME_CONVENTION_RE.test(name)) return;\n if (isJsonMode()) return;\n process.stderr.write(say(\"agent.spawn_name_hint\", name));\n}\n\n/**\n * Resolve the actual executable to launch in an agent's pane for a given\n * `cli`. Honours the env var `MU_<UPPER_CLI>_COMMAND` (e.g. `MU_PI_COMMAND=\n * pi-alt` makes `--cli pi` actually exec `pi-alt`). Falls back to the cli\n * name itself, which is what users expect when their `pi` binary is on\n * `$PATH` under that exact name.\n *\n * Used by `spawnAgent` to pick the spawned command, and by reconcile's\n * orphan detector so externally-spawned panes running the resolved binary\n * are still recognised as agents.\n */\nexport function resolveCliCommand(cli: string): string {\n const envName = envVarNameForCli(cli);\n const override = process.env[envName];\n return override && override.trim() !== \"\" ? override : cli;\n}\n\n/**\n * Compute the `MU_<UPPER_CLI>_COMMAND` env var name mu consults when\n * resolving `--cli <key>`. Hyphens in the cli key become underscores\n * (env var names can't contain `-`); this matches the operator-aliases\n * convention documented in the mu skill (e.g. `--cli pi-meta` →\n * `MU_PI_META_COMMAND`).\n */\nexport function envVarNameForCli(cli: string): string {\n return `MU_${cli.toUpperCase().replace(/-/g, \"_\")}_COMMAND`;\n}\n\n/**\n * Resolve `--cli <key>` to its actual command string AND tell the\n * caller whether the resolution came from a `MU_<UPPER_CLI>_COMMAND`\n * env var or fell through to the bare cli name. The CLI uses this to\n * surface env-var attribution in the spawn-success line so config\n * issues are visible without `mu agent show`.\n */\nexport function resolveCliCommandWithSource(cli: string): {\n command: string;\n envVar: string;\n resolvedFromEnv: boolean;\n} {\n const envVar = envVarNameForCli(cli);\n const override = process.env[envVar];\n if (override !== undefined && override.trim() !== \"\") {\n return { command: override, envVar, resolvedFromEnv: true };\n }\n return { command: cli, envVar, resolvedFromEnv: false };\n}\n\n// ─── Pre-flight PATH check ──\n//\n// Operator typo'd `mu agent spawn worker-1 --cli pi-meta` on a host\n// where `pi-meta` wasn't on PATH; the spawn appeared to succeed but\n// the pane died with `command not found` and the existing 1.5s\n// liveness check sometimes missed it (shells stay alive past a failed\n// exec). Pre-flight the PATH resolution so a typo never:\n// 1. creates an orphan worktree\n// 2. creates an orphan tmux pane\n// 3. inserts a half-spawned DB row\n// The check fires AFTER `resolveCliCommand` so `MU_<UPPER>_COMMAND`\n// overrides are honoured AND the diagnostic mentions the env var by\n// name. Hookable via `setCommandResolverForTests` so the test suite\n// can simulate \"binary present\" / \"binary absent\" without polluting\n// the real PATH.\n\nexport interface CommandResolutionResult {\n ok: boolean;\n /** First whitespace-separated token of the command — the binary\n * whose presence on PATH we checked. */\n binary: string;\n /** Absolute path of the resolved binary on PATH, when ok=true. */\n resolvedPath?: string;\n}\n\nexport type CommandResolver = (command: string) => Promise<CommandResolutionResult>;\n\nconst execFileP = promisify(execFile);\n\n/** Default resolver: shell-out to `command -v <binary>` (POSIX-portable\n * equivalent of `which`). Returns ok=false when the lookup exits\n * non-zero. Always returns the parsed `binary` field so the typed\n * error can quote what we actually searched for. */\nasync function defaultCommandResolver(command: string): Promise<CommandResolutionResult> {\n const binary = parseFirstToken(command);\n if (binary === \"\") return { ok: false, binary };\n try {\n // `command -v` is the POSIX builtin lookup. Spawned via /bin/sh\n // -c so the builtin is available (it's not an external program).\n const { stdout } = await execFileP(\"/bin/sh\", [\"-c\", `command -v -- ${shellQuote(binary)}`], {\n env: process.env,\n });\n const resolvedPath = stdout.trim();\n if (resolvedPath === \"\") return { ok: false, binary };\n return { ok: true, binary, resolvedPath };\n } catch {\n return { ok: false, binary };\n }\n}\n\n/** Single-quote a token for /bin/sh -c. Only used on the binary name,\n * which `parseFirstToken` already restricted to a non-whitespace run\n * — no embedded single-quotes expected. Escape defensively anyway. */\nfunction shellQuote(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n\n/** First whitespace-separated token of a command string (\"pi-meta\n * --no-solo\" → \"pi-meta\"). Returns \"\" on an empty / whitespace-only\n * input. */\nfunction parseFirstToken(command: string): string {\n const trimmed = command.trim();\n if (trimmed === \"\") return \"\";\n const match = trimmed.match(/^\\S+/);\n return match ? match[0] : \"\";\n}\n\nlet activeCommandResolver: CommandResolver = defaultCommandResolver;\n\n/** Override the PATH resolver. Tests use this to simulate \"binary\n * absent\" / \"binary present\" without depending on what's actually\n * installed. Production callers should never touch this. */\nexport function setCommandResolverForTests(resolver: CommandResolver): void {\n activeCommandResolver = resolver;\n}\n\n/** Restore the default PATH resolver. */\nexport function resetCommandResolverForTests(): void {\n activeCommandResolver = defaultCommandResolver;\n}\n\n/**\n * Verify the first token of `command` resolves to a binary on PATH.\n * Public so tests can call it directly; spawnAgent calls it before\n * the worktree is created so a bad --cli never creates an orphan worktree.\n */\nexport async function checkCommandResolvable(command: string): Promise<CommandResolutionResult> {\n return activeCommandResolver(command);\n}\n\nexport interface SpawnAgentOptions {\n name: string;\n workstream: string;\n /** Defaults to \"pi\". Any CLI is accepted: pi is driven over its control\n * socket; others run `MU_<CLI>_COMMAND` (or the cli name) and get\n * text by herdr `agent prompt` (a send to them on tmux is refused). */\n cli?: string;\n /** The actual command to run in the pane. Defaults to the cli value. */\n command?: string;\n /** Window name to group this agent under. Defaults to the agent's name\n * (so each agent gets its own window). Multiple agents sharing a `tab`\n * share a window with multiple panes. */\n tab?: string;\n /** \"full-access\" (default) or \"read-only\". The schema stores it; today\n * the role isn't enforced (deferred to a future capabilities pass). */\n role?: string;\n /** Initial working directory of the pane, recorded as `agents.cwd`.\n * Defaults to the caller's cwd. Ignored when `worktree: true`: the\n * worktree path is the cwd then. */\n cwd?: string;\n /** Override the tmux session name. Defaults to `mu-<workstream>`. */\n tmuxSession?: string;\n /** Run the agent in its own `git worktree add --detach` at\n * `<state dir>/worktrees/<workstream>/<name>`; its path is the cwd and\n * its base commit is recorded as `agents.base`. A root outside a git\n * repo throws WorktreeVcsRequiredError. */\n worktree?: boolean;\n /** Commit / branch the worktree starts at (only with `worktree: true`). */\n from?: string;\n /** Repo the worktree is added to (only with `worktree: true`). Defaults\n * to the git toplevel of the caller's cwd. */\n root?: string;\n /** Run on this host profile (`mu host add`): the pane runs the profile's\n * `shell` template, which starts the remote pi and forwards its ctl socket\n * here; `cwd` and `worktree` name REMOTE paths (the worktree is made by the\n * profile's `exec`). One channel is held from before the first remote\n * command until the pane dies. Refused on a mux that cannot run a shell\n * command (herdr). With `host`, `root` is a REMOTE repo (default the\n * profile's `repo`); a `worktree` needs one of them. */\n host?: string;\n /** Run the control-socket handshake for pi agents (default true).\n * `false` skips it and reports `ctl: \"skipped\"`. */\n ctl?: boolean;\n /** When `name` is taken in the workstream, take the next free one\n * (see `nextFreeAgentName`) instead of failing with AgentExistsError. */\n nextFree?: boolean;\n /** Abort (the CLI's SIGINT/SIGTERM): kills a running `git worktree add` and\n * rolls the spawn back like a thrown error, up to its end. */\n signal?: AbortSignal;\n /**\n * Called synchronously, inside the spawn lock, the moment the agent row\n * exists for the new pane (nothing awaited between the row write and this\n * call). A durable journal of the created registry identity (`agents.id` +\n * pane): a throw rolls the spawn back like a failed finalize.\n */\n onIdentity?: (agent: AgentRow) => void;\n /** Where a local pi agent keeps its session (`PI_CODING_AGENT_SESSION_DIR`\n * in the pane env) instead of pi's per-cwd default. Set for delegates, so\n * their sessions stay out of the caller's `/resume` list. */\n piSessionDir?: string;\n}\n\n/** How many taken names a `nextFree` spawn skips past before it gives up. */\nconst NEXT_FREE_ATTEMPTS = 32;\n\n/** How many names `nextFreeAgentName` looks up before it gives up. */\nconst NEXT_FREE_LOOKUPS = 1000;\n\n/**\n * `name` when it is free in `workstream`, else the next free name: a\n * trailing `-<n>` counts up (`delegate-1` → `delegate-2`), and a name\n * without one gets `-2`, `-3`, … (`delegate-review` → `delegate-review-2`).\n * The stem is cut so a candidate stays within the 32-char name limit.\n * A name whose worktree dir is still on disk counts as taken: a dead\n * agent's worktree outlives its row (kept as evidence), and spawning\n * that name with --worktree would refuse on the dir instead of moving on.\n * Throws AgentNameExhaustedError after NEXT_FREE_LOOKUPS taken names,\n * or when no valid candidate is left (the suffix alone outgrows it).\n */\nexport function nextFreeAgentName(db: Db, name: string, workstream: string): string {\n const free = (n: string) =>\n getAgent(db, n, workstream) === undefined && !existsSync(worktreePath(workstream, n));\n if (free(name)) return name;\n const m = /^(.*)-(\\d+)$/.exec(name);\n const [stem, first] = m ? [m[1] ?? \"\", BigInt(m[2] ?? \"1\")] : [name, 1n];\n for (let i = 1n; i <= BigInt(NEXT_FREE_LOOKUPS); i++) {\n const suffix = `-${first + i}`;\n const candidate = `${stem.slice(0, MAX_AGENT_NAME_LEN - suffix.length)}${suffix}`;\n if (!isValidAgentName(candidate)) {\n throw new AgentNameExhaustedError(name, `no valid name left (tried ${candidate})`);\n }\n if (free(candidate)) return candidate;\n }\n throw new AgentNameExhaustedError(name, `the next ${NEXT_FREE_LOOKUPS} names are taken`);\n}\n\n/** Outcome of the spawn-time control-socket handshake. */\nexport type SpawnCtl = \"ok\" | \"missing\" | \"refused\" | \"skipped\";\n\n/** A ctl probe's outcome as spawn reports it. */\nexport function probeToSpawnCtl(kind: CtlProbe[\"kind\"]): Exclude<SpawnCtl, \"skipped\"> {\n return kind === \"ok\" ? \"ok\" : kind === \"missing\" ? \"missing\" : \"refused\";\n}\n\n/** What spawnAgent returns: the registered row plus the handshake outcome. */\nexport type SpawnedAgent = AgentRow & {\n ctl: SpawnCtl;\n ctlSocket: string;\n /**\n * The pi process the handshake's hello/status named. A send right after\n * the spawn carries it (`expectIncarnation`), so a replacement that binds\n * the same socket path is refused instead of handed the prompt. Absent\n * when the handshake did not run or the extension predates incarnations.\n */\n ctlIncarnation?: string;\n /** Set when the startup scan saw a Claude trust dialog parked in the pane. */\n trustDialog?: true;\n};\n\n/**\n * True when the agent runs pi, so the mu pi extension should answer on\n * its control socket: `cli` is \"pi\", or the command's argv0 basename is\n * `pi` / `pi-meta`.\n */\nexport function speaksMuCtl(cli: string, command: string): boolean {\n if (cli === \"pi\") return true;\n const argv0 = basename(parseFirstToken(command));\n return argv0 === \"pi\" || argv0 === \"pi-meta\";\n}\n\n/**\n * True when a REMOTE spawn is a command gate, not a worker: an explicit\n * `--command` that is not pi. An explicit `--cli pi` and a `pi` / `pi-meta`\n * argv0 stay workers (an opaque wrapper around pi needs `--cli pi`). Decided\n * before any effect; `--cli` omitted classifies by the command alone, so\n * `--host dev --command 'npm test'` is a gate even though `cli` defaults to pi.\n */\nexport function isCommandGate(opts: { host?: string; cli?: string; command?: string }): boolean {\n if (opts.host === undefined || opts.command === undefined) return false;\n if (opts.cli === \"pi\") return false;\n const argv0 = basename(parseFirstToken(opts.command));\n return argv0 !== \"pi\" && argv0 !== \"pi-meta\";\n}\n\n/**\n * Handshake budget in ms after the agent is live. 0 disables. Override\n * via `MU_SPAWN_CTL_MS`.\n */\nexport function defaultSpawnCtlMs(): number {\n const raw = process.env.MU_SPAWN_CTL_MS;\n if (raw === undefined) return 30_000;\n const parsed = Number.parseInt(raw, 10);\n if (Number.isNaN(parsed) || parsed < 0) return 30_000;\n return parsed;\n}\n\n/** Cadence of `onMiss` (pane-alive check + capture: ~2 forks per call). */\nconst CTL_POLL_INTERVAL_MS = 250;\n/** Cadence of the socket-path stat, which costs no fork. */\nconst CTL_STAT_INTERVAL_MS = 50;\n\n/** Clock + sleep the ctl handshake runs on. Real by default. */\ninterface HandshakeClock {\n now(): number;\n delay(ms: number): Promise<void>;\n}\nlet handshakeClock: HandshakeClock = { now: () => Date.now(), delay: (ms) => delay(ms) };\n\n/** TEST SEAM: drive the handshake on a virtual clock so deadline timing is counted, not elapsed. */\nexport function setHandshakeClockForTests(clock: HandshakeClock): void {\n handshakeClock = clock;\n}\n\nexport function resetHandshakeClockForTests(): void {\n handshakeClock = { now: () => Date.now(), delay: (ms) => delay(ms) };\n}\n\n/**\n * Poll the control socket until the extension answers or the budget\n * runs out. Returns the last probe outcome. The socket path is stat'd\n * every ~50 ms and probed as soon as it exists, so readiness is seen\n * within ~50 ms of pi binding it. `onMiss` (the pane-alive check) keeps\n * its 250 ms cadence plus one final check at the deadline, and may\n * throw to abort (the pane died); otherwise this never throws. Uses the\n * `handshakeClock` (real by default), not the `sleep` seam: tests stub\n * that to a no-op, which would turn this into a busy loop.\n */\nasync function awaitCtlHandshake(\n sock: string,\n onMiss?: () => Promise<void>,\n signal?: AbortSignal,\n): Promise<{ ctl: Exclude<SpawnCtl, \"skipped\">; incarnation?: string }> {\n const budgetMs = defaultSpawnCtlMs();\n const deadline = handshakeClock.now() + budgetMs;\n let last: Exclude<SpawnCtl, \"skipped\"> = \"missing\";\n let lastMissAt = Number.NEGATIVE_INFINITY;\n let first = true;\n for (;;) {\n signal?.throwIfAborted();\n if (first || existsSync(sock)) {\n first = false;\n const remaining = deadline - handshakeClock.now();\n const probe = await ctlProbe(\n sock,\n Math.max(1, Math.min(remaining, CTL_POLL_INTERVAL_MS * 4)),\n );\n if (probe.kind === \"ok\") {\n return {\n ctl: \"ok\",\n ...(probe.incarnation !== undefined ? { incarnation: probe.incarnation } : {}),\n };\n }\n last = probeToSpawnCtl(probe.kind);\n }\n // The final check at the deadline always runs, throttle or not: a pane\n // that dies in the last <250 ms keeps the scrollback onMiss captured.\n const atDeadline = handshakeClock.now() >= deadline;\n if (onMiss && (atDeadline || handshakeClock.now() - lastMissAt >= CTL_POLL_INTERVAL_MS)) {\n lastMissAt = handshakeClock.now();\n await onMiss();\n }\n const left = deadline - handshakeClock.now();\n if (left <= 0) return { ctl: last };\n await handshakeClock.delay(Math.min(CTL_STAT_INTERVAL_MS, left));\n }\n}\n\n/**\n * Spawn a new agent in its tmux pane and register it in the DB.\n *\n * Phases:\n * 1. Validate name + uniqueness.\n * 2. If --worktree: prestageWorktree() (placeholder agent row +\n * worktree dir + registry row).\n * 3. mux.spawnAgent() in the worktree (or opts.cwd, default the\n * caller's cwd); the scratch session is ensured first.\n * 4. finalizeAgentRow() — patch the placeholder to the real pane id,\n * cwd and base (worktree path), or insert a fresh agent row.\n * 5. Liveness: awaitSpawnLiveness() (fixed sleep, then pane + scan\n * check), or for a tmux pi agent the ctl handshake with a pane\n * check per tick and the scan at the end. A backend with\n * `spawnAgentWaitsReady` (herdr) is ready when spawnAgent settles.\n * 6. ctl handshake for herdr pi agents (outside the rollback).\n *\n * Failure between any of (3)–(5) calls rollbackSpawn() to undo the\n * pane + row + worktree. The caller-visible error is preserved.\n */\nexport async function spawnAgent(db: Db, opts: SpawnAgentOptions): Promise<SpawnedAgent> {\n // A --worktree spawn that died before its pane (SIGKILL) frees its name here.\n await reclaimDeadStagings(db, opts.workstream);\n if (opts.nextFree === true) {\n // A parallel spawn can take the picked name between the pick and the\n // insert (the in-lock re-check throws before any side effect): pick again.\n for (let attempt = 1; ; attempt++) {\n const name = nextFreeAgentName(db, opts.name, opts.workstream);\n try {\n return await spawnAgent(db, { ...opts, name, nextFree: false });\n } catch (err) {\n if (!(err instanceof AgentExistsError) || attempt >= NEXT_FREE_ATTEMPTS) throw err;\n }\n }\n }\n if (!isValidAgentName(opts.name)) {\n throw new TypeError(\n `invalid agent name: ${JSON.stringify(opts.name)} (expected /^[a-z][a-z0-9_-]{0,31}$/)`,\n );\n }\n // A torn-down workstream takes no new agents. Refuse BEFORE any side\n // effect (worktree, session, pane): the failure would otherwise surface at\n // insertAgent, after the pane exists.\n const tornDownAt = tornDownAtOf(db, opts.workstream);\n if (tornDownAt !== null) throw new WorkstreamTornDownError(opts.workstream, tornDownAt);\n // Per-workstream uniqueness check: v5 allows the same agent name in\n // different workstreams. Scope the existence check to the spawn's\n // workstream so two operators spawning 'worker-1' in wsA and wsB\n // both succeed. A fast path only:\n // a parallel spawn of the same name can pass it too, so the check is\n // repeated inside the spawn lock, and insertAgent maps the UNIQUE\n // violation to AgentExistsError as the last line.\n if (getAgent(db, opts.name, opts.workstream) !== undefined) {\n throw new AgentExistsError(opts.name);\n }\n\n const session = opts.tmuxSession ?? `mu-${opts.workstream}`;\n const windowName = opts.tab ?? opts.name;\n const cli = opts.cli ?? \"pi\";\n const resolved = resolveCliCommandWithSource(cli);\n // A remote command runs on the host: the local PATH and local\n // $MU_<CLI>_COMMAND knobs say nothing about it.\n // Admission (below) re-reads it inside the transaction that counts the cap:\n // from then on the ADMITTED snapshot is the one every template runs from.\n let profile = opts.host === undefined ? undefined : await requireHostSpawn(db, opts);\n // A command gate: decided here, before any effect, and recorded on its row.\n const gateToken = isCommandGate(opts) ? newGateToken() : undefined;\n if (gateToken !== undefined && opts.worktree) {\n throw new HostProfileError(\n \"--worktree cannot be used with a remote command gate (--host with a non-pi --command): a gate runs in --cwd, else the profile's default repo\",\n );\n }\n const command = opts.command ?? (profile ? cli : resolved.command);\n // Where `command` came from. Backends that resolve the executable\n // themselves may not silently ignore an operator's choice, and need to\n // know WHICH knob to name (see `SpawnAgentPaneOptions.commandSource`).\n const commandSource =\n opts.command !== undefined\n ? \"explicit\"\n : !profile && resolved.resolvedFromEnv\n ? \"env\"\n : \"cli-key\";\n\n // Pre-flight PATH resolution. Catches `--cli does-not-exist` (and\n // typos in `MU_<UPPER>_COMMAND` overrides) before any side effect.\n // See `checkCommandResolvable` / `AgentSpawnCliNotFoundError` for\n // the rationale; in short: prevents orphan worktrees + orphan\n // panes + half-spawned DB rows on a typo.\n //\n // We do NOT pre-flight an explicit `--command \"...\"` value: the\n // operator who passed --command gave us the literal string they\n // want spawned (often a wrapper like `pi-meta --no-solo` whose\n // first token IS on PATH but with arg-quoting that the resolver\n // would mis-parse; or a shell snippet like `bash -lc '...'`). For\n // those, the existing post-spawn liveness check is the safety net.\n if (opts.command === undefined && !profile) {\n const check = await checkCommandResolvable(command);\n if (!check.ok) {\n throw new AgentSpawnCliNotFoundError(cli, check.binary, envVarNameForCli(cli));\n }\n }\n\n // Who is spawning: read from the PARENT's env, before the child's env\n // below replaces it, and recorded by both row writes (placeholder insert\n // and finalize). Never guessed from task ownership.\n const spawner = spawnerFromEnv();\n\n // Worktree pre-stage. See `prestageWorktree` for the ordering\n // rationale. Yields the worktree (its path is the pane's cwd) or\n // undefined when --worktree wasn't requested.\n let staged: StagedWorktree | undefined;\n // A remote spawn holds its channel lease from here until the pane dies\n // (bound to the agent's id + pane when the row exists): reserved BEFORE any\n // remote command, so every exec below rides it and a full host refuses now.\n let lease: HostLease | undefined;\n let site: RemoteSite | undefined;\n try {\n if (profile) {\n ({ lease, profile } = await admitHostChannel(\n db,\n profile.name,\n `spawn:${opts.workstream}/${opts.name}`,\n { paneAlive: localPaneAlive },\n ));\n if (opts.worktree) staged = await prestageRemote(db, opts, cli, spawner, lease, profile);\n else\n site = await prepareRemote(db, lease, profile, {\n workstream: opts.workstream,\n name: opts.name,\n worktree: false,\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n ...remoteRoot(opts, profile),\n });\n } else if (opts.worktree) {\n staged = await prestageWorktree(db, opts, cli, spawner);\n }\n } catch (err) {\n if (lease !== undefined) releaseHostChannel(db, lease); // no pane was ever opened under it\n emitSpawnFailed(db, opts, \"worktree\", err);\n throw err;\n }\n // Without a worktree the pane starts in --cwd, else the caller's cwd,\n // and the row records it. A remote agent's cwd is a REMOTE path: the\n // local pane never starts in it.\n const paneCwd = staged?.path ?? site?.cwd ?? resolve(opts.cwd ?? process.cwd());\n\n // Inject identity env vars into the pane so anything running inside\n // (pi extensions, claim-protocol scripts, status segments) can branch\n // on 'I am a mu-managed worker' without scraping pane titles or DB\n // lookups. Set via tmux `-e KEY=VALUE` (per-pane; doesn't pollute the\n // tmux server's global env).\n //\n // These are NOT exposed via SpawnAgentOptions — mu identity is not\n // user-tunable. Adding more keys here means every spawned pane sees\n // them automatically.\n //\n // MU_CTL_SOCK goes to every CLI (harmless for non-pi). Its directory\n // must exist before the pane starts: for a remote agent, ssh's\n // `-L <local>:<remote>` binds the LOCAL path and does not mkdir. A\n // socket file left by a previous agent of this name is removed inside\n // the spawn lock below, once this spawn owns the name, since ssh\n // refuses to bind over it.\n //\n // The base is the DB's directory: in production that is exactly\n // ctlSocketPath's own default (MU_DB_PATH dir or the state dir), and\n // a test DB in a temp dir keeps its sockets there too.\n const ctlSocket = ctlSocketPath(opts.workstream, opts.name, dirname(db.name));\n mkdirSync(dirname(ctlSocket), { recursive: true, mode: 0o700 });\n // Exactly these six (plus SSH_AUTH_SOCK and piSessionDir below). tmux\n // panes inherit the tmux server's env, not ours: pin the DB and state dir this spawn used,\n // absolute and always (the default ones too), so the worker's `mu` hits\n // the same taskgraph from any cwd.\n // A remote agent's identity travels in the filled shell template (`{env}`:\n // five whitelisted variables, never the local DB, state or sync dir); the\n // local pane (the transport) is given none of it.\n const paneEnv: Record<string, string> = profile\n ? {}\n : {\n MU_MANAGED_AGENT: \"1\",\n MU_AGENT_NAME: opts.name,\n MU_WORKSTREAM: opts.workstream,\n [CTL_SOCK_ENV]: ctlSocket,\n MU_DB_PATH: resolve(db.name !== \"\" && db.name !== \":memory:\" ? db.name : defaultDbPath()),\n MU_STATE_DIR: resolve(defaultStateDir()),\n };\n // pi reads its session dir from this env (its --session-dir still wins).\n // Local pi only: a remote pi has no business with a local path.\n if (!profile && opts.piSessionDir !== undefined && speaksMuCtl(cli, command)) {\n paneEnv.PI_CODING_AGENT_SESSION_DIR = resolve(opts.piSessionDir);\n }\n // mu sessions are created detached and may never be attached, so tmux's\n // update-environment never refreshes them and a pane would inherit a\n // stale SSH_AUTH_SOCK. Forward the caller's. File-type check only (is it\n // a socket?), not a liveness probe: mu stays ssh-free. Best-effort.\n const sshSock = process.env.SSH_AUTH_SOCK;\n if (sshSock) {\n try {\n if (statSync(sshSock).isSocket()) paneEnv.SSH_AUTH_SOCK = sshSock;\n } catch {\n // missing or unreadable: skip forwarding\n }\n }\n\n const hasWorktree = staged !== undefined;\n\n // Single outer try wrapping every step that can throw AFTER the\n // worktree has been prestaged: pane create/reuse,\n // agent-row finalize, liveness check. Earlier shape had pane creation\n // outside the try, so a tmux failure (e.g. no\n // workstream session and tmux refusing to create one) left the\n // prestaged worktree + placeholder agent row behind as an\n // orphan.\n //\n // paneId is undefined until spawnAgent creates the pane; rollbackSpawn\n // skips killPane in that case. The inner try/catches that previously\n // wrapped finalize and liveness were folded into this single catch\n // (clarity > belt-and-suspenders; rollbackSpawn is idempotent and\n // best-effort regardless).\n let paneId: string | undefined;\n let agent: AgentRow;\n // Whether the agent row is this spawn's to delete on rollback. A\n // spawn that lost a same-name race must not delete the winner's row.\n let ownedIncarnation: number | undefined = staged?.incarnation;\n const wantsCtl =\n gateToken === undefined &&\n opts.ctl !== false &&\n speaksMuCtl(cli, command) &&\n defaultSpawnCtlMs() !== 0;\n let ctl: SpawnCtl | undefined;\n let ctlIncarnation: string | undefined;\n // Last phase entered, recorded in agent.spawn_failed if we roll back.\n let phase: SpawnPhase = \"pane\";\n let trustDialog = false;\n // Settles when the backend considers the agent started (see spawnAgentWaitsReady).\n let readiness: Promise<unknown> = Promise.resolve();\n try {\n opts.signal?.throwIfAborted();\n // Cross-process critical section: the topology check-then-act inside\n // `ensureSession` / `spawnAgent` (session exists? window exists? →\n // new-session / new-window / split-window) plus the agent-row\n // finalize. Serialised per mux SESSION so a parallel fan-out\n // (`for n in …; do mu agent spawn … & done`) can't race six\n // `new-session -d -s mu-scratch` calls into five-rolled-back-losers.\n // Keyed on the session name: spawns into different sessions never\n // contend. See spawn-lock.ts.\n //\n // The lock covers the pane's CREATION, not its readiness: spawnAgent\n // calls `onPaneCreated` the moment the pane exists, the row is\n // finalized, and the lock is released while the backend is still\n // waiting for the agent (herdr: up to 30s, past the lock's own\n // 15s acquire / 30s stale budget). The liveness wait below is\n // equally outside the lock: holding it would serialise the very\n // parallelism the operator asked for.\n const created = await withSpawnLock(session, async () => {\n // Re-check under the lock: a parallel spawn of the same name may\n // have inserted its row since the fast-path check. (With a\n // worktree, the placeholder row already claimed the name.)\n if (!hasWorktree && getAgent(db, opts.name, opts.workstream) !== undefined) {\n throw new AgentExistsError(opts.name);\n }\n // A staged spawn holds the name through its placeholder row, which\n // the agent lock no longer covers: a close of the placeholder frees\n // the name, and a replacement may own it (and its socket) by now.\n // Unlink only while the placeholder this spawn inserted is still the\n // row, in the same step (nothing awaited between check and unlink).\n if (staged !== undefined) {\n const cur = getAgent(db, opts.name, opts.workstream);\n if (\n cur === undefined ||\n cur.incarnation !== staged.incarnation ||\n cur.paneId !== pendingPaneIdFor(opts.name)\n ) {\n throw new AgentReplacedError(opts.name, opts.workstream);\n }\n }\n // The name is ours: no live agent owns a socket at this path.\n rmSync(ctlSocket, { force: true });\n const mux = await activeMux();\n // `scratch` is never `workstream init`-ed: ensure its session (with\n // the placeholder `_mu` window) so it outlives its last agent.\n if (isScratchWorkstream(opts.workstream)) await mux.ensureSession(session);\n // Resolves with the pane id at creation; `done` settles when the\n // backend considers the agent started.\n let onCreated: (pid: string) => void = () => {};\n const createdPane = new Promise<string>((res) => {\n onCreated = res;\n });\n const done = mux.spawnAgent({\n session,\n window: windowName,\n name: opts.name,\n cli,\n command: profile\n ? remoteShellCommand(profile, {\n workstream: opts.workstream,\n name: opts.name,\n command: gateToken === undefined ? command : gateWrapper(command, gateToken),\n localSock: ctlSocket,\n cwd: paneCwd,\n })\n : command,\n commandSource,\n ...(profile ? {} : { cwd: paneCwd }),\n env: paneEnv,\n onPaneCreated: onCreated,\n // A gate's pane outlives its command: the result is read after it ends.\n ...(gateToken !== undefined ? { retainOnExit: true } : {}),\n });\n // Observe a rejection immediately: it is awaited after the lock.\n done.catch(() => {});\n const pid = await Promise.race([createdPane, done]);\n // Capture the pane id on the OUTER scope as soon as it exists so a\n // throw later in the lock (finalizeAgentRow INSERT failure) still\n // routes through rollbackSpawn -> killPane. Assigning only via the\n // returned object meant a finalize failure left paneId undefined\n // and rollbackSpawn skipped killPane, leaking the pane.\n paneId = pid;\n readiness = done;\n phase = \"finalize\";\n const row = finalizeAgentRow(db, {\n opts,\n cli,\n paneId: pid,\n cwd: paneCwd,\n staged,\n command,\n commandSource,\n spawner,\n host: profile?.name,\n gateToken,\n });\n ownedIncarnation = row.incarnation;\n // The lease now rides this pane (registry id + pane): freed when it dies.\n if (\n lease !== undefined &&\n !bindHostChannel(db, lease, { agentId: row.incarnation, paneId: pid })\n ) {\n throw new Error(say(\"host.channel_lost\", lease.host, lease.holder));\n }\n opts.onIdentity?.(row);\n return { pid, row };\n });\n paneId = created.pid;\n agent = created.row;\n phase = \"liveness\";\n // Liveness check: wait briefly, then verify the pane is still alive.\n // Catches the silent-spawn-failure class of bugs where the CLI dies\n // immediately (lock conflict, bad credentials, etc.). On failure,\n // surface a typed error with whatever scrollback the mux still has.\n //\n // A backend with `spawnAgentWaitsReady` (herdr) starts the agent\n // inside spawnAgent and returns only once the MUX has detected it and\n // considers it ready for input — strictly stronger than what the\n // scrollback poll can prove, so MU_SPAWN_LIVENESS_MS is subsumed and\n // deliberately not consulted. Both branches live outside the spawn\n // lock on purpose — they are the slow part (1.5s+ here, up to 30s\n // there). Either throwing routes through the same `rollbackSpawn`,\n // so a pane that never became an agent never keeps its agent row.\n //\n // A tmux pi agent skips the fixed sleep: the ctl handshake is the\n // readiness signal, so the pane check rides on each handshake tick\n // and the startup-error scan runs once the handshake ends. A\n // handshake timeout with a live, clean pane is still NOT a\n // rollback (see below). MU_SPAWN_LIVENESS_MS=0 disables the checks\n // here too.\n if ((await activeMux()).spawnAgentWaitsReady) {\n await readiness;\n } else if (wantsCtl) {\n const pid = paneId;\n const check = defaultSpawnLivenessMs() !== 0;\n const when = `during the ctl handshake (up to ${defaultSpawnCtlMs()}ms after spawn)`;\n // Capture every tick and keep the last good buffer: on real tmux\n // capture-pane fails once the pane is gone, so a capture taken\n // after the death check would always come back empty.\n let lastScrollback: string | undefined;\n const assertPaneAlive = async (): Promise<void> => {\n const mux = await activeMux();\n const sb = await mux.capture(pid, { lines: 50 }).catch(() => undefined);\n lastScrollback = sb ?? lastScrollback;\n if (await mux.paneAlive(pid)) return;\n throw new AgentDiedOnSpawnError(\n opts.name,\n pid,\n lastScrollback,\n command,\n when,\n profile?.name,\n );\n };\n const hs = await awaitCtlHandshake(\n ctlSocket,\n check ? assertPaneAlive : undefined,\n opts.signal,\n );\n ctl = hs.ctl;\n ctlIncarnation = hs.incarnation;\n // Known gap: pi binds the socket in session_start (init), before\n // it renders startup diagnostics, so an ok on the first tick can\n // scan a pane that has not printed its error yet.\n //\n // An ok handshake proves the CLI started, so only provider/auth\n // patterns apply: a shell exec-failure line in the tail is then\n // transcript text (a resumed `--session` re-renders old tool\n // output such as `grep: x: No such file or directory`).\n if (check) {\n trustDialog = await checkSpawnHealth(\n pid,\n opts.name,\n command,\n when,\n ctl === \"ok\",\n profile?.name,\n );\n }\n } else if (gateToken === undefined) {\n trustDialog = await awaitSpawnLiveness(paneId, opts.name, command, profile?.name);\n }\n opts.signal?.throwIfAborted();\n // A gate is not scanned for startup errors or liveness: a command that ends at\n // once is a result (the retained pane), and a dead transport reads as exit-less.\n } catch (err) {\n // Record first: a throwing cleanup must neither skip the record nor\n // mask the original error.\n emitSpawnFailed(db, opts, phase, err);\n try {\n await rollbackSpawn(db, opts.name, paneId, staged, ownedIncarnation, opts.workstream, lease);\n } catch (cleanupErr) {\n if (err instanceof Error && err.cause === undefined) {\n try {\n err.cause = cleanupErr;\n } catch {\n // frozen error: keep original as-is\n }\n }\n }\n throw err;\n }\n // Control-socket handshake when the tmux path above did not run it.\n // Outside the rollback: a timeout means only control is missing; the\n // pane and pi are fine. The caller reports it (see\n // AgentCtlUnreachableError).\n if (ctl === undefined) {\n if (wantsCtl) {\n const hs = await awaitCtlHandshake(ctlSocket);\n ctl = hs.ctl;\n ctlIncarnation = hs.incarnation;\n } else ctl = \"skipped\";\n }\n // `agents` is machine-local (it holds pane_id), so no capture trigger\n // covers it and this emit is the ONLY record. Typed intent so it\n // renders through the same formatter as captured ops.\n emitEvent(\n db,\n opts.workstream,\n \"agent.spawn\",\n `agent spawn ${opts.name} (cli=${cli}, role=${opts.role ?? \"full-access\"}, pane=${paneId}, ctl=${ctl}${profile ? `, host=${profile.name}` : \"\"})`,\n await resolveActorIdentity(),\n );\n // Lint-grade stderr nudge when the operator picked a name that\n // doesn't fit the <role>-<n> smallest-unused-suffix convention. The\n // spawn already succeeded; this is advice, not an error. Done LAST\n // so the hint trails the spawn's own stdout output and so a partial\n // failure (rolled back above) never emits it.\n maybeWarnNonConventionalAgentName(opts.name);\n return {\n ...agent,\n ctl,\n ctlSocket,\n ...(ctlIncarnation !== undefined ? { ctlIncarnation } : {}),\n ...(trustDialog ? { trustDialog: true as const } : {}),\n };\n}\n\n/** A worktree spawn has made and registered. */\nexport interface StagedWorktree {\n path: string;\n base: string;\n root: string;\n /** The registry row's `createdAt`: rollback frees the worktree only while\n * the row at `path` is still this one (the registry has no owner column). */\n createdAt: string;\n /** The placeholder row's incarnation: finalize and rollback act on it only. */\n incarnation: number;\n /** Set for a worktree on a REMOTE host (`path` is a remote path, `root` the repo\n * there, absolute): rollback removes it through the profile's `exec`, never through the local registry. */\n host?: string;\n}\n\n/**\n * Stage 1 of `--worktree` spawn: claim the name with a placeholder agent\n * row, then make the worktree the pane will start in.\n *\n * Why placeholder-first? The pane starts IN the worktree, so the worktree\n * must exist before the pane, yet the name has to be claimed against a\n * parallel spawn of the same name while it is made. The agent row needs a\n * pane_id (NOT NULL), so a placeholder claims the name and the real pane\n * id is patched in later (see `PENDING_PANE_PREFIX`).\n *\n * A leftover worktree at the path is reclaimed only if it is mu's own\n * clean, unused one (`reclaimWorktreePath`); anything else refuses.\n *\n * Throws after best-effort rollback (the placeholder row, a half-made\n * worktree) when creation fails.\n */\nasync function prestageWorktree(\n db: Db,\n opts: SpawnAgentOptions,\n cli: string,\n spawner: string | null,\n): Promise<StagedWorktree> {\n // The agent lock covers the whole staging: it reclaims, creates and\n // registers disk state that a concurrent `agent close` of this name would\n // be removing. Fail closed: a busy lock refuses the spawn before any effect.\n return withAgentLock(db, opts.workstream, opts.name, () =>\n prestageLocked(db, opts, cli, spawner),\n );\n}\n\nasync function prestageLocked(\n db: Db,\n opts: SpawnAgentOptions,\n cli: string,\n spawner: string | null,\n): Promise<StagedWorktree> {\n const path = worktreePath(opts.workstream, opts.name);\n const dir = opts.root ?? process.cwd();\n const top = await gitToplevel(dir);\n if (top === undefined) throw new WorktreeVcsRequiredError(dir);\n // The registry records the main checkout, even when the caller runs\n // inside a linked one (which may be removed before this worktree)...\n const root = (await owningRoot(top)) ?? top;\n // ...but the start revision is the CALLER's: HEAD (or --from) resolved in\n // the checkout it works in, not in the main one. Objects and refs are\n // shared, so the pinned sha is valid from `root`.\n const from = await git([\"rev-parse\", \"--verify\", `${opts.from ?? \"HEAD\"}^{commit}`], top);\n const placeholder = insertAgent(db, {\n name: opts.name,\n workstream: opts.workstream,\n cli,\n paneId: pendingPaneIdFor(opts.name),\n role: opts.role,\n tab: opts.tab ?? null,\n cwd: path,\n spawner,\n });\n let creating = false;\n try {\n const reclaimed = await reclaimWorktreePath(db, {\n agent: opts.name,\n workstream: opts.workstream,\n path,\n });\n for (const w of reclaimed) {\n emitEvent(db, opts.workstream, \"agent.spawn\", `agent spawn ${opts.name}: reused path: ${w}`);\n }\n creating = true; // from here anything at `path` is this staging's\n const { base } = await createWorktree({ root, path, from, signal: opts.signal });\n const createdAt = new Date().toISOString();\n registerWorktree(db, {\n path,\n agent: opts.name,\n workstream: opts.workstream,\n root,\n base,\n createdAt,\n });\n return { path, base, root, createdAt, incarnation: placeholder.incarnation };\n } catch (err) {\n try {\n if (creating) await discardWorktree(root, path); // a killed `git worktree add` leaves half\n // Only the placeholder this spawn inserted, never a replacement.\n deleteAgent(db, opts.name, opts.workstream, { incarnation: placeholder.incarnation });\n } catch {\n // best-effort: never mask the worktree error\n }\n throw err;\n }\n}\n\n/** The remote repo of a `--host` spawn: `--root`, else the profile's default. */\nfunction remoteRoot(opts: SpawnAgentOptions, profile: HostProfile): { root?: string } {\n const root = opts.root ?? profile.repo ?? undefined;\n return root === undefined ? {} : { root };\n}\n\n/** The profile `--host` names, once the spawn is known to be runnable on it. Nothing is touched. */\nasync function requireHostSpawn(db: Db, opts: SpawnAgentOptions): Promise<HostProfile> {\n const host = opts.host ?? \"\";\n const profile = getHost(db, host);\n if (opts.worktree && opts.root === undefined && profile.repo === null) {\n throw new HostProfileError(\n `host ${host} has no default repo: pass --root <remote repo path> with --worktree`,\n );\n }\n const mux = await activeMux();\n if (!mux.runsShellCommand) throw new HostSpawnUnsupportedError(host, mux.name);\n return profile;\n}\n\n/**\n * `--worktree` on a host, the remote twin of prestageLocked: a placeholder row\n * claims the name (host recorded), then ONE exec under the spawn's lease makes\n * the detached worktree. Only a worktree this exec made is ever removed.\n */\nasync function prestageRemote(\n db: Db,\n opts: SpawnAgentOptions,\n cli: string,\n spawner: string | null,\n lease: HostLease,\n profile: HostProfile,\n): Promise<StagedWorktree> {\n return withAgentLock(db, opts.workstream, opts.name, async () => {\n const placeholder = insertAgent(db, {\n name: opts.name,\n workstream: opts.workstream,\n cli,\n paneId: pendingPaneIdFor(opts.name),\n role: opts.role,\n tab: opts.tab ?? null,\n cwd: null,\n spawner,\n host: profile.name,\n });\n try {\n const made = await prepareRemote(db, lease, profile, {\n workstream: opts.workstream,\n name: opts.name,\n worktree: true,\n ...(opts.from !== undefined ? { from: opts.from } : {}),\n ...remoteRoot(opts, profile),\n // An unused leftover of a prepare whose answer was lost is taken over;\n // never while a removed agent's recovery record may name that tree.\n reclaim: !recoveriesFor(db, opts.workstream, opts.name).some(\n (r) => r.host === profile.name,\n ),\n });\n return {\n path: made.cwd,\n base: made.base ?? \"\",\n root: made.repo ?? \"\",\n createdAt: new Date().toISOString(),\n incarnation: placeholder.incarnation,\n host: profile.name,\n };\n } catch (err) {\n try {\n deleteAgent(db, opts.name, opts.workstream, { incarnation: placeholder.incarnation });\n } catch {\n // best-effort: never mask the remote error\n }\n throw err;\n }\n });\n}\n\n/**\n * Who is calling spawn, for `agents.spawner`: `<MU_WORKSTREAM>/<MU_AGENT_NAME>`\n * for a managed agent (the pair, since a bare name repeats across\n * workstreams), else `pi:<PI_SESSION_ID>` for a pi session, else null.\n * Reads the env, not a shell: it works the same however spawn was invoked.\n */\nexport function spawnerFromEnv(env: NodeJS.ProcessEnv = process.env): string | null {\n const { MU_MANAGED_AGENT: managed, MU_WORKSTREAM: ws, MU_AGENT_NAME: name } = env;\n if (managed === \"1\" && ws && name) return `${ws}/${name}`;\n const session = env.PI_SESSION_ID;\n return session ? `pi:${session}` : null;\n}\n\n/**\n * Stage 2 of spawn (after the real pane exists): patch the placeholder\n * row to the real pane id, cwd and base (worktree), or insert a fresh\n * agent row (no worktree). Throws if the patch UPDATE silently affects no\n * row (the placeholder vanished mid-spawn; reconcile's pending-pane\n * prune skip guards against that).\n */\nfunction finalizeAgentRow(\n db: Db,\n args: {\n opts: SpawnAgentOptions;\n cli: string;\n paneId: string;\n cwd: string;\n staged: StagedWorktree | undefined;\n command: string;\n commandSource: CommandSource;\n spawner: string | null;\n host: string | undefined;\n gateToken: string | undefined;\n },\n): AgentRow {\n const { opts, cli, paneId, cwd, staged, command, commandSource, spawner, host, gateToken } = args;\n if (staged === undefined) {\n return insertAgent(db, {\n name: opts.name,\n workstream: opts.workstream,\n cli,\n paneId,\n role: opts.role,\n tab: opts.tab ?? null,\n cwd,\n command,\n commandSource,\n spawner,\n host: host ?? null,\n gateToken: gateToken ?? null,\n });\n }\n // Scope the patch to the spawn's workstream so a same-named worker\n // in another workstream isn't repointed at this pane.\n // And to the placeholder this spawn inserted (by incarnation, still\n // pending): a row replaced since is not ours to repoint.\n const patched = db\n .prepare(\n `UPDATE agents SET pane_id = ?, cwd = ?, base = ?, command = ?, command_source = ?, spawner = ?, host = ?, repo = ?, updated_at = ?\n WHERE id = ? AND pane_id = ?\n AND name = ?\n AND workstream_id = (SELECT id FROM workstreams WHERE name = ?)`,\n )\n .run(\n paneId,\n staged.path,\n staged.base,\n command,\n commandSource,\n spawner,\n host ?? null,\n staged.host !== undefined ? staged.root : null,\n new Date().toISOString(),\n staged.incarnation,\n pendingPaneIdFor(opts.name),\n opts.name,\n opts.workstream,\n );\n const row = getAgent(db, opts.name, opts.workstream);\n if (patched.changes === 0 || !row || row.incarnation !== staged.incarnation)\n throw new Error(`spawnAgent: agent vanished after worktree stage: ${opts.name}`);\n return row;\n}\n\n/**\n * Roll back a failed spawn. Idempotent and best-effort: every step\n * swallows its own errors so a partial-cleanup substrate (already-killed\n * pane, no agent row) never masks the original failure.\n *\n * `paneId` is `undefined` when spawnAgent itself threw before returning a\n * pane id — there's nothing to kill. `staged` is set when prestageWorktree\n * succeeded: once the pane is proven gone, the worktree this spawn made goes\n * through the close rule (`releaseWorktree`; its pane may have worked in it):\n * clean and merged is removed, commits are kept on `mu/<ws>/<name>-<sha12>`\n * first, and dirty files or a writer keep the tree and its registry row for\n * `mu agent close <name>`; each outcome but the plain removal is logged. A pane NOT proven gone\n * keeps the row and the worktree (the row rule): `mu agent close` finishes\n * them once it is. deleteAgent is idempotent (no-op on a missing row).\n *\n * `ownedIncarnation` is undefined when the spawn failed before inserting\n * its own row (e.g. it lost a same-name race); the row then belongs to\n * another agent and is left alone. Otherwise only that incarnation is\n * deleted, never a replacement under the same name.\n */\ntype SpawnPhase = \"worktree\" | \"pane\" | \"finalize\" | \"liveness\";\n\n/** Terminal record for a failed spawn. Best-effort; never throws. */\nfunction emitSpawnFailed(db: Db, opts: SpawnAgentOptions, phase: SpawnPhase, err: unknown): void {\n try {\n const errName = err instanceof Error ? err.constructor.name : typeof err;\n emitEvent(\n db,\n opts.workstream,\n \"agent.spawn_failed\",\n `agent spawn failed ${opts.name} (phase=${phase}, error=${errName})`,\n );\n } catch {\n // logging is best-effort\n }\n}\n\nexport async function rollbackSpawn(\n db: Db,\n name: string,\n paneId: string | undefined,\n staged: StagedWorktree | undefined,\n ownedIncarnation: number | undefined,\n workstream: string,\n /** The spawn's host channel lease, while it is still the reservation (before or after its bind). */\n lease?: HostLease,\n): Promise<void> {\n // Is the pane (the host transport) proven gone? A channel is freed only on that proof.\n let paneGone = paneId === undefined;\n if (paneId !== undefined) {\n // Best-effort: rollback runs on an already-failing path and must not\n // mask the original error, even if the mux itself went away.\n const mux = await activeMux().catch(() => undefined);\n // The mux is in hand before the check, and the kill is issued in the\n // same step: a row of another incarnation on this very pane id (a\n // replacement that reused it) means the pane is no longer ours.\n // A pane id registered to ANY other incarnation (any name, any\n // workstream) is not ours either: leave it alone and say so.\n const foreign = db\n .prepare(\"SELECT 1 FROM agents WHERE pane_id = ? AND id IS NOT ? LIMIT 1\")\n .get(paneId, ownedIncarnation ?? null);\n if (foreign === undefined) {\n await mux?.killPane(paneId).catch(() => {});\n paneGone = mux !== undefined && (await mux.paneAlive(paneId).catch(() => true)) === false;\n } else {\n paneGone = true; // another agent holds the id: ours is not that pane\n\n try {\n emitEvent(\n db,\n workstream,\n \"agent.spawn_failed\",\n `agent spawn rollback ${name}: pane ${paneId} now belongs to another agent, left alone`,\n );\n } catch {\n // best-effort\n }\n }\n }\n if (paneGone) {\n try {\n if (lease !== undefined) releaseHostChannel(db, lease);\n if (paneId !== undefined && ownedIncarnation !== undefined) {\n releaseHostChannelsForAgent(db, ownedIncarnation, paneId);\n }\n } catch {\n // best-effort: the next admission reclaims a channel whose pane is dead\n }\n }\n // The remote tree this rollback proved gone: the row's delete then owes no recovery record.\n let remoteGone = false;\n if (staged?.host !== undefined) {\n // A worktree on a remote host: its own exec, under its own channel, once\n // the pane's is free. Only while the name is still this spawn's.\n const remote = staged;\n try {\n if (!paneGone) throw new Error(\"pane not proven gone\");\n await withAgentLock(db, workstream, name, async () => {\n const cur = getAgent(db, name, workstream);\n if (cur !== undefined && cur.incarnation !== remote.incarnation) return;\n remoteGone = await removeRemoteWorktree(\n db,\n remote.host ?? \"\",\n `rollback:${workstream}/${name}`,\n remote,\n );\n });\n } catch {\n try {\n emitEvent(\n db,\n workstream,\n \"agent.spawn_failed\",\n `agent spawn rollback ${name}: remote worktree ${staged.path} on ${staged.host} was not removed`,\n );\n } catch {\n // best-effort\n }\n }\n } else if (staged !== undefined && paneGone) {\n // Only once the pane is proven gone: a surviving pane may be running in\n // the tree (the row is kept below, so `mu agent close` finishes it).\n // The worker may have worked before the spawn failed: the tree goes\n // through the close rule, never a forced removal. Commits are kept on a\n // branch first; dirty files or a writer keep the tree and its registry\n // row (the record `mu agent close` finishes).\n const say = (what: string): void => {\n try {\n emitEvent(db, workstream, \"agent.spawn_failed\", `agent spawn rollback ${name}: ${what}`);\n } catch {\n // best-effort\n }\n };\n try {\n // Under the agent lock, and only while the name is still this spawn's\n // (or gone) AND the registry row at the path is the one this spawn\n // wrote: a replacement staged there, or a newer orphan, owns it now.\n await withAgentLock(db, workstream, name, async () => {\n const cur = getAgent(db, name, workstream);\n if (cur !== undefined && cur.incarnation !== staged.incarnation) return;\n const reg = getWorktreeAt(db, staged.path);\n if (reg !== undefined && (reg.createdAt !== staged.createdAt || reg.base !== staged.base))\n return;\n const done = await releaseWorktree(\n db,\n reg ?? { ...staged, agent: name, workstream, lastCollectedHead: null },\n );\n if (done.action === \"kept-branch\")\n say(`worktree ${staged.path} had commits; kept on branch ${done.branch}, tree removed`);\n for (const w of done.warnings ?? []) say(w);\n });\n } catch (err) {\n const why = err instanceof Error ? (err.message.split(\"\\n\")[0] ?? \"\") : String(err);\n say(\n `worktree ${staged.path} kept (${why}); once handled: mu agent close ${name} -w ${workstream}`,\n );\n }\n }\n // A row whose pane is not proven gone is kept (the row rule, as in close),\n // with its worktree: the pane may still run in it. A host row's death would\n // also free the channel the live pane (the transport) holds.\n if (ownedIncarnation !== undefined && !paneGone) {\n try {\n emitEvent(\n db,\n workstream,\n \"agent.spawn_failed\",\n `agent spawn rollback ${name}: pane ${paneId} not proven gone, row${staged === undefined ? \"\" : \" and worktree\"}${getAgent(db, name, workstream)?.host ? \" and host channel\" : \"\"} kept; once it is gone: mu agent close ${name} -w ${workstream}`,\n );\n } catch {\n // best-effort\n }\n return;\n }\n // Only the row this spawn inserted: never a replacement under the name. A remote\n // tree this rollback removed (or found gone) leaves no `remote_recovery` record:\n // the record is for a worktree someone must still deal with.\n if (ownedIncarnation !== undefined)\n deleteAgent(db, name, workstream, { incarnation: ownedIncarnation }, { preserve: !remoteGone });\n}\n\n/**\n * Default liveness window in milliseconds. 0 disables the check (useful\n * for fast tests that don't want to wait). Override via env var\n * `MU_SPAWN_LIVENESS_MS`.\n */\nexport function defaultSpawnLivenessMs(): number {\n const raw = process.env.MU_SPAWN_LIVENESS_MS;\n if (raw === undefined) return 1500;\n const parsed = Number.parseInt(raw, 10);\n if (Number.isNaN(parsed) || parsed < 0) return 1500;\n return parsed;\n}\n\n/**\n * Curated list of patterns that indicate the spawned CLI hit a fatal\n * provider/auth error during startup and is now parked at an error\n * prompt instead of becoming a working agent.\n *\n * Kept short and case-insensitive on purpose: every entry must match a\n * real, observed dogfood failure mode. Don't add patterns speculatively\n * — the false-positive cost is to roll back a healthy spawn, which the\n * operator then has to re-attempt without the scan (`MU_SPAWN_LIVENESS_MS=0`).\n *\n * Mitigation against scrollback noise from harmless prior-session text:\n * `checkSpawnHealth` only scans the LAST `STARTUP_ERROR_TAIL_LINES`\n * lines of the capture, and after an ok ctl handshake it skips\n * `EXEC_FAILURE_PATTERN` (a resumed pi session re-renders old tool\n * output, which often ends in `No such file or directory`).\n */\nconst AUTH_ERROR_PATTERNS: readonly RegExp[] = [\n /No API key found for [\\w-]+/i,\n /Error: invalid API key/i,\n /Authentication failed/i,\n /401 Unauthorized/i,\n /Could not authenticate/i,\n];\n\n/**\n * The spawned command failed to exec: post-spawn detection of the\n * \"binary not found at exec time\" failure mode. The pre-flight check\n * above catches the common typo BEFORE any side effect, but a few\n * edge cases still slip through and only surface in the pane:\n * - `--command \"...\"` skips the pre-flight (operator opt-out).\n * - PATH inside the spawned shell differs from PATH in mu's\n * process (login shell rc files, /etc/paths.d, etc.).\n * - Race: binary on PATH at spawn time, gone 1.5s later.\n *\n * Anchored to lines that LOOK like a shell error rather than prose\n * mentioning the marker:\n * require the marker at end-of-line, optionally followed by a single\n * `: <name>` token (the zsh form: `zsh: command not found: pi-meta`).\n * This still trips the canonical cases —\n * `bash: pi-meta: command not found`\n * `zsh: command not found: pi-meta`\n * `sh: pi-meta: No such file or directory`\n * — but rejects banner prose like\n * `I noticed earlier you saw 'command not found'`\n * `type \\`mu\\` — command not found? install with …`\n * that previously triggered a full spawn rollback. The pre-flight\n * PATH check remains the deterministic safety net for typo'd `--cli`.\n */\nconst EXEC_FAILURE_PATTERN =\n /^(?:.*: )?(?:command not found|No such file or directory)(?::\\s*\\S+)?$/i;\n\n/**\n * Number of trailing lines of the post-liveness scrollback to scan for\n * the startup-error patterns. The capture is `lines: 50`; tailing the last\n * 30 keeps the scan focused on the spawned CLI's own startup output\n * (the pane is brand-new, so anything earlier than that is the shell\n * banner / our own command-line, both safe).\n */\nconst STARTUP_ERROR_TAIL_LINES = 30;\n\n/**\n * Scan the tail of a freshly-captured pane buffer for known startup-\n * failure patterns. Returns the matched line on first hit, or undefined\n * if the buffer is clean. `cliStarted` (the CLI answered the ctl\n * handshake) drops the exec-failure pattern: the CLI demonstrably ran.\n *\n * Exported for the test suite; not part of the SDK surface.\n */\nexport function detectSpawnStartupError(\n scrollback: string,\n cliStarted = false,\n): string | undefined {\n const patterns = cliStarted\n ? AUTH_ERROR_PATTERNS\n : [...AUTH_ERROR_PATTERNS, EXEC_FAILURE_PATTERN];\n const lines = scrollback.split(/\\r?\\n/);\n const tail = lines.slice(Math.max(0, lines.length - STARTUP_ERROR_TAIL_LINES));\n for (const line of tail) {\n for (const pattern of patterns) {\n if (pattern.test(line)) return line;\n }\n }\n return undefined;\n}\n\nasync function awaitSpawnLiveness(\n paneId: string,\n agentName: string,\n command: string,\n host?: string,\n): Promise<boolean> {\n const ms = defaultSpawnLivenessMs();\n if (ms === 0) return false;\n await sleep(ms);\n return checkSpawnHealth(paneId, agentName, command, undefined, false, host);\n}\n\n/**\n * Claude's \"Is this a project you trust?\" dialog, recorded from claude\n * 2.1.x (test/fixtures/claude-trust-dialog.txt). It is unnumbered and\n * defaults to \"No, exit\", so the Enter that ends a send makes claude\n * quit. Matched on the short option line, which survives line wraps.\n *\n * NOT an error: the pane and agent are kept, so this is a warning that\n * spawn reports and that skips the initial --send. Startup scan only: it\n * does not protect a later `mu agent send`, and the herdr spawn path\n * never runs this scan. No keypress is ever sent for the operator.\n */\nconst CLAUDE_TRUST_DIALOG = /Yes, I trust this folder/i;\n\n/** True when the tail of `scrollback` shows Claude's folder-trust dialog. */\nexport function detectClaudeTrustDialog(scrollback: string): boolean {\n const lines = scrollback.split(/\\r?\\n/);\n const tail = lines.slice(Math.max(0, lines.length - STARTUP_ERROR_TAIL_LINES));\n return tail.some((line) => CLAUDE_TRUST_DIALOG.test(line));\n}\n\n/**\n * One liveness verdict: throw AgentDiedOnSpawnError when the pane is\n * gone, AgentSpawnStartupError when its scrollback tail shows a known\n * startup failure. Returns true (non-fatal) when Claude's trust dialog is\n * showing.\n */\nasync function checkSpawnHealth(\n paneId: string,\n agentName: string,\n command: string,\n /** When the failure happened, for the error text; default: the liveness window. */\n when?: string,\n /** The CLI answered the ctl handshake; see detectSpawnStartupError. */\n cliStarted = false,\n /** The host profile the pane's transport reaches, when remote. */\n host?: string,\n): Promise<boolean> {\n // Capture-pane first so we have something to attach to the error if the\n // pane is in the process of being torn down (the buffer survives a beat\n // longer than the pane's existence in some tmux builds).\n const mux = await activeMux();\n const scrollback = await mux.capture(paneId, { lines: 50 }).catch(() => undefined);\n if (!(await mux.paneAlive(paneId))) {\n throw new AgentDiedOnSpawnError(agentName, paneId, scrollback, command, when, host);\n }\n // Pane is alive — but \"alive\" doesn't mean \"working\". Scan the tail of\n // the capture for known provider/auth startup errors. The pane stays at\n // an error prompt forever otherwise, and the orchestrator only\n // discovers the dud minutes later when `mu task wait` stalls.\n if (scrollback !== undefined) {\n const matchedLine = detectSpawnStartupError(scrollback, cliStarted);\n if (matchedLine !== undefined) {\n throw new AgentSpawnStartupError(agentName, paneId, matchedLine, scrollback, when);\n }\n return detectClaudeTrustDialog(scrollback);\n }\n return false;\n}\n","// mu — agent registry CRUD + send / read / list, and the re-exports of the\n// src/agents/ cluster (spawnAgent and closeAgent live in agents/spawn.ts and\n// agents/close.ts).\n//\n// Layering inside this file:\n//\n// - Types & raw-row mapping (RawAgentRow / rowFromDb)\n// - CRUD primitives (insertAgent, getAgent, listAgents,\n// deleteAgent)\n// - Verbs (sendToAgent, readAgent, listLiveAgents)\n//\n// The verbs compose the CRUD primitives with the mux and reconciliation\n// layers. They are deliberately thin.\n\nimport { dirname } from \"node:path\";\nimport {\n agentKey,\n type CtlLink,\n type RuntimeState,\n readAgentStates,\n type StateReading,\n type StateSource,\n} from \"./agent-state.js\";\nimport { reapAgentRow } from \"./agents/reap.js\";\nimport { type Db, resolveWorkstreamId, tryResolveWorkstreamId } from \"./db.js\";\nimport type { CommandSource } from \"./mux/types.js\";\nimport { withOpContext } from \"./op-context.js\";\nimport { type ReconcileMode, type ReconcileReport, reconcile } from \"./reconcile.js\";\n\n// Re-export the cluster modules so external callers continue to\n// `import { AgentNotFoundError, spawnAgent, ... } from \"./agents.js\"`.\nexport {\n type AbortAgentOptions,\n type AbortResult,\n abortAgent,\n DEFAULT_ABORT_TIMEOUT_MS,\n type InterruptResult,\n interruptAgent,\n} from \"./agents/abort.js\";\nexport {\n type CloseAgentOptions,\n type CloseAgentResult,\n type ClosePreview,\n closeAgent,\n previewClose,\n} from \"./agents/close.js\";\nexport { type DelegateOutcome, delegateOutcome } from \"./agents/delegate.js\";\nexport {\n AgentAbortNeedsCtlError,\n AgentAbortTimeoutError,\n AgentBusyError,\n AgentCtlUnreachableError,\n AgentDiedOnSpawnError,\n AgentEmptySendError,\n AgentExistsError,\n AgentExtensionOutdatedError,\n AgentFreshNeedsCtlError,\n AgentLockBusyError,\n AgentNameExhaustedError,\n AgentNotFoundError,\n AgentNotInWorkstreamError,\n AgentPaneDeadError,\n AgentPaneStillAliveError,\n AgentReplacedError,\n AgentRestartedError,\n AgentSendIndeterminateError,\n AgentSendUnsupportedError,\n AgentSlashCommandUnsupportedError,\n AgentSpawnCliNotFoundError,\n AgentSpawnStartupError,\n SpawnAttemptBusyError,\n SpawnAttemptFailedError,\n SpawnAttemptGuardError,\n SpawnReceiptConflictError,\n SpawnTaskStateError,\n SpawnTrustDialogError,\n} from \"./agents/errors.js\";\nexport { withAgentLock } from \"./agents/lock.js\";\nexport {\n type AgentObservation,\n type ObservedAgent,\n type ObservedWatch,\n observationFromReading,\n observeAgentStates,\n settledCloseInput,\n watchAgentRun,\n} from \"./agents/observe.js\";\nexport type { SpawnReceipt } from \"./agents/receipts.js\";\nexport {\n type CommandResolutionResult,\n type CommandResolver,\n checkCommandResolvable,\n defaultSpawnCtlMs,\n defaultSpawnLivenessMs,\n envVarNameForCli,\n nextFreeAgentName,\n resetCommandResolverForTests,\n resolveCliCommand,\n resolveCliCommandWithSource,\n type SpawnAgentOptions,\n type SpawnCtl,\n type SpawnedAgent,\n setCommandResolverForTests,\n spawnAgent,\n speaksMuCtl,\n} from \"./agents/spawn.js\";\nexport {\n type AutoAttemptRequest,\n pinBrief,\n spawnAutoAttempt,\n spawnForTask,\n type TaskSpawnOutcome,\n type TaskSpawnRequest,\n} from \"./agents/task-spawn.js\";\nexport {\n agentCtlSocket,\n CTL_SLASH_COMMANDS,\n checkMessage,\n expectsCtl,\n isSlashCommand,\n type MessageCheck,\n parseSessionCommand,\n requireFeature,\n respawnCommand,\n type SendResult,\n sendViaTransport,\n type Transport,\n type TransportSendOptions,\n} from \"./agents/transport.js\";\n\nimport { AgentExistsError, AgentNotFoundError, AgentReplacedError } from \"./agents/errors.js\";\nimport {\n agentCtlSocket,\n recordSend,\n type SendResult,\n sendViaTransport,\n type TransportSendOptions,\n} from \"./agents/transport.js\";\nimport { unlinkCtlSocket } from \"./ctl/path.js\";\nimport type { CtlTool } from \"./ctl/protocol.js\";\nimport { activeMux, type CaptureOptions, type MuxPane } from \"./mux.js\";\nimport { resolveActorIdentity } from \"./tasks/claim.js\";\nimport { ensureWorkstream, isScratchWorkstream } from \"./workstream.js\";\n\nexport interface AgentRow {\n /**\n * The registry incarnation: the row's surrogate id. AUTOINCREMENT never\n * reuses one, so a name that is deleted and created again (or a pane id\n * that is reused) is always a NEW incarnation. Every destructive agent\n * write compares it (`deleteAgent`'s `expected`, `agent close --if`).\n * Not pi's `incarnation` (a string, the `--inc` of `agent wait`).\n */\n incarnation: number;\n name: string;\n /** Foreign-name reference to the owning workstream. */\n workstreamName: string;\n cli: string;\n paneId: string;\n role: string;\n /** Window name; null when the agent has its own window named after itself. */\n tab: string | null;\n /** Directory the pane started in (its worktree under `--worktree`); null when spawned without a cwd. */\n cwd: string | null;\n /** Commit the worktree was created at; null without `--worktree`. */\n base: string | null;\n /** The command the pane was started with (machine-local); null for a row older than this column. */\n command: string | null;\n /** Where `command` came from; null with it. */\n commandSource: CommandSource | null;\n /** Who spawned it: `<workstream>/<agent>` for a managed caller, else\n * `pi:<PI_SESSION_ID>`; null when unknown (older rows, no identity). */\n spawner: string | null;\n /** The remote host profile it runs on; null for a local agent. */\n host: string | null;\n /** HEAD last collected from its remote worktree; null until one is. */\n collectedHead: string | null;\n /** A remote worktree's repo on its host (absolute, chosen at spawn); null otherwise. */\n repo: string | null;\n /** Set for a remote command gate (`spawn --host` of a non-pi command): its spawn-unique token, the key of the remote result record. Null for every other agent. */\n gateToken: string | null;\n /** ISO 8601 timestamp. */\n createdAt: string;\n /** ISO 8601 timestamp. */\n updatedAt: string;\n}\n\nexport interface LiveAgent extends AgentRow {\n state: RuntimeState;\n source: StateSource;\n /** Control-socket link: ok / missing / refused for pi agents, n/a otherwise. */\n ctl?: CtlLink;\n /** ISO 8601 time when the source entered this state. */\n since: string | null;\n reason?: string;\n idle?: boolean;\n /** The running tool of a pi agent (ctl read); null = none, absent = unknown. Not in `AgentOutput`. */\n tool?: CtlTool | null;\n}\n\n/** Default idle threshold for the derived `idle` flag (`mu state`, TUI).\n * Deliberately looser than `mu task wait --stuck-after` (2 min), which\n * acts on the stall rather than just displaying it. */\nconst DEFAULT_IDLE_THRESHOLD_MS = 300_000;\n\n/**\n * Read the operator-tunable idle threshold (`MU_IDLE_THRESHOLD_MS`).\n * Returns the default on any unparsable / negative value rather than\n * throwing — env-var typos shouldn't crash `mu state`.\n */\nexport function idleThresholdMs(): number {\n const env = process.env.MU_IDLE_THRESHOLD_MS;\n if (env === undefined || env === \"\") return DEFAULT_IDLE_THRESHOLD_MS;\n const n = Number.parseInt(env, 10);\n if (!Number.isFinite(n) || n < 0) return DEFAULT_IDLE_THRESHOLD_MS;\n return n;\n}\n\n/**\n * Decide whether an agent is in the 'idle but assigned' state. Pure\n * read on (agents, tasks); no side effects. Exported so `listLiveAgents`,\n * the renderers, and tests can share one source of truth.\n *\n * Scratch agents own no task, so for them idle past the threshold is\n * enough: a leftover delegate pane is then flagged in `mu state -w\n * scratch` / `mu agent list` instead of piling up unseen.\n */\nexport function computeAgentIdle(db: Db, agent: LiveAgent, now: number = Date.now()): boolean {\n if (agent.state !== \"needs_input\" || agent.since === null) return false;\n const threshold = idleThresholdMs();\n if (threshold <= 0) return false;\n const since = Date.parse(agent.since);\n if (!Number.isFinite(since)) return false;\n if (now - since < threshold) return false;\n if (isScratchWorkstream(agent.workstreamName)) return true;\n const wsId = tryResolveWorkstreamId(db, agent.workstreamName);\n if (wsId === null) return false;\n const row = db\n .prepare(\n `SELECT COUNT(*) AS n\n FROM tasks t\n JOIN agents a ON a.id = t.owner_id\n WHERE a.name = ? AND a.workstream_id = ? AND t.status = 'IN_PROGRESS'`,\n )\n .get(agent.name, wsId) as { n: number };\n return row.n > 0;\n}\n\nexport interface InsertAgentInput {\n name: string;\n workstream: string;\n paneId: string;\n /** Defaults to \"pi\" via schema DEFAULT. */\n cli?: string;\n /** Defaults to \"full-access\" via schema DEFAULT. */\n role?: string;\n tab?: string | null;\n cwd?: string | null;\n base?: string | null;\n /** The resolved command and where it came from, kept so an outdated\n * extension can be respawned exactly. */\n command?: string | null;\n commandSource?: CommandSource | null;\n /** Who spawned it (see AgentRow.spawner); never guessed from task ownership. */\n spawner?: string | null;\n host?: string | null;\n collectedHead?: string | null;\n repo?: string | null;\n gateToken?: string | null;\n}\n\ninterface RawAgentRow {\n id: number;\n name: string;\n /** Joined from workstreams.name. */\n workstream: string;\n cli: string;\n pane_id: string;\n role: string;\n tab: string | null;\n cwd: string | null;\n base: string | null;\n command: string | null;\n command_source: string | null;\n spawner: string | null;\n host: string | null;\n collected_head: string | null;\n repo: string | null;\n gate_token: string | null;\n created_at: string;\n updated_at: string;\n}\n\n/** SELECT clause that joins agents to workstreams, exposing the\n * operator-facing workstream name as `workstream`. Used by every\n * read path. */\nconst SELECT_AGENT_COLS = `\n a.id AS id,\n a.name AS name,\n ws.name AS workstream,\n a.cli AS cli,\n a.pane_id AS pane_id,\n a.role AS role,\n a.tab AS tab,\n a.cwd AS cwd,\n a.base AS base,\n a.command AS command,\n a.command_source AS command_source,\n a.spawner AS spawner,\n a.host AS host,\n a.collected_head AS collected_head,\n a.repo AS repo,\n a.gate_token AS gate_token,\n a.created_at AS created_at,\n a.updated_at AS updated_at\n`;\n\nconst AGENT_FROM_JOIN = \"FROM agents a JOIN workstreams ws ON ws.id = a.workstream_id\";\n\nfunction rowFromDb(row: RawAgentRow): AgentRow {\n return {\n incarnation: row.id,\n name: row.name,\n workstreamName: row.workstream,\n cli: row.cli,\n paneId: row.pane_id,\n role: row.role,\n tab: row.tab,\n cwd: row.cwd,\n base: row.base,\n command: row.command,\n commandSource:\n row.command_source === \"explicit\" ||\n row.command_source === \"env\" ||\n row.command_source === \"cli-key\"\n ? row.command_source\n : null,\n spawner: row.spawner,\n host: row.host,\n collectedHead: row.collected_head,\n repo: row.repo,\n gateToken: row.gate_token,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\n/** Resolve an agent's surrogate id by (workstream, name). Returns\n * null on miss. Sees agents of a torn-down workstream too: their rows\n * outlive the teardown while their pane lives, and cleanup must reach them. */\nfunction agentIdByName(db: Db, name: string, workstream: string): number | null {\n const row = db\n .prepare(\n `SELECT a.id AS id FROM agents a JOIN workstreams ws ON ws.id = a.workstream_id\n WHERE a.name = ? AND ws.name = ?`,\n )\n .get(name, workstream) as { id: number } | undefined;\n return row ? row.id : null;\n}\n\nexport function insertAgent(db: Db, input: InsertAgentInput): AgentRow {\n // Auto-create the workstreams row if missing so the FK on\n // agents.workstream_id is always satisfied. Preserves the ergonomics\n // where you could spawn without an explicit `mu workstream init`.\n ensureWorkstream(db, input.workstream);\n const workstreamId = resolveWorkstreamId(db, input.workstream);\n const now = new Date().toISOString();\n try {\n db.prepare(\n `INSERT INTO agents (name, workstream_id, cli, pane_id, status, role, tab, cwd, base, command, command_source, spawner, host, collected_head, repo, gate_token, created_at, updated_at)\n VALUES (@name, @workstreamId, COALESCE(@cli, 'pi'), @paneId, 'spawning',\n COALESCE(@role, 'full-access'), @tab, @cwd, @base, @command, @commandSource,\n @spawner, @host, @collectedHead, @repo, @gateToken, @now, @now)`,\n ).run({\n name: input.name,\n workstreamId,\n cli: input.cli ?? null,\n paneId: input.paneId,\n role: input.role ?? null,\n tab: input.tab ?? null,\n cwd: input.cwd ?? null,\n base: input.base ?? null,\n command: input.command ?? null,\n commandSource: input.commandSource ?? null,\n spawner: input.spawner ?? null,\n host: input.host ?? null,\n collectedHead: input.collectedHead ?? null,\n repo: input.repo ?? null,\n gateToken: input.gateToken ?? null,\n now,\n });\n } catch (err) {\n // UNIQUE (workstream_id, name): a concurrent spawn took the\n // name between the caller's existence check and this insert.\n if ((err as { code?: unknown }).code === \"SQLITE_CONSTRAINT_UNIQUE\") {\n throw new AgentExistsError(input.name);\n }\n throw err;\n }\n const row = getAgent(db, input.name, input.workstream);\n if (!row) throw new Error(`agents.insertAgent: row not found after insert: ${input.name}`);\n return row;\n}\n\n/**\n * Look up an agent by its tmux pane id (e.g. `%4`). Returns undefined if\n * no agent currently owns that pane. Used by `mu me` and friends to\n * answer \"which agent am I?\" from `$TMUX_PANE` without the LLM having to\n * remember its own name.\n *\n * Note: `pane_id` is not declared UNIQUE in the schema (a managed agent\n * could in theory be re-spawned into the same recycled pane id) but in\n * practice tmux pane ids are unique within a server's lifetime, and\n * reconcile prunes ghosts. We return the first match.\n */\nexport function getAgentByPane(db: Db, paneId: string): AgentRow | undefined {\n const row = db\n .prepare(`SELECT ${SELECT_AGENT_COLS} ${AGENT_FROM_JOIN} WHERE a.pane_id = ? LIMIT 1`)\n .get(paneId) as RawAgentRow | undefined;\n return row ? rowFromDb(row) : undefined;\n}\n\nexport function getAgent(db: Db, name: string, workstream: string): AgentRow | undefined {\n // v5: agents.name is per-workstream unique, not globally unique.\n // Workstream is required so the same name in two workstreams\n // resolves unambiguously.\n const wsId = tryResolveWorkstreamId(db, workstream);\n if (wsId === null) return undefined;\n const row = db\n .prepare(\n `SELECT ${SELECT_AGENT_COLS} ${AGENT_FROM_JOIN} WHERE a.name = ? AND a.workstream_id = ?`,\n )\n .get(name, wsId) as RawAgentRow | undefined;\n return row ? rowFromDb(row) : undefined;\n}\n\n/**\n * Like `getAgent`, but also finds an agent whose workstream is torn down\n * (a teardown that kept its row because the pane lived, or a peer's\n * teardown that reached this machine). For cleanup only: every other verb\n * treats a torn-down workstream as gone.\n */\nexport function getAgentForCleanup(db: Db, name: string, workstream: string): AgentRow | undefined {\n const row = db\n .prepare(`SELECT ${SELECT_AGENT_COLS} ${AGENT_FROM_JOIN} WHERE a.name = ? AND ws.name = ?`)\n .get(name, workstream) as RawAgentRow | undefined;\n return row ? rowFromDb(row) : undefined;\n}\n\nexport function listAgents(db: Db, opts: { workstream?: string } = {}): AgentRow[] {\n if (opts.workstream === undefined) {\n const rows = db\n .prepare(`SELECT ${SELECT_AGENT_COLS} ${AGENT_FROM_JOIN} ORDER BY ws.name, a.name`)\n .all() as RawAgentRow[];\n return rows.map(rowFromDb);\n }\n const wsId = tryResolveWorkstreamId(db, opts.workstream);\n if (wsId === null) return [];\n const rows = db\n .prepare(\n `SELECT ${SELECT_AGENT_COLS} ${AGENT_FROM_JOIN} WHERE a.workstream_id = ? ORDER BY a.name`,\n )\n .all(wsId) as RawAgentRow[];\n return rows.map(rowFromDb);\n}\n\n/**\n * Placeholder pane-id prefix used during the `--worktree` pre-stage in\n * spawnAgent (src/agents/spawn.ts).\n *\n * The worktree is created before the pane exists (the pane starts in it),\n * and the name must be claimed against a parallel spawn of the same name\n * while that happens. So spawn inserts the agent row with a placeholder\n * pane_id, creates the worktree, then the real pane, then patches pane_id.\n *\n * Because no real pane has this prefix, a naive mutating reconcile pass\n * would treat the placeholder row as a ghost and prune it mid-spawn.\n * Reconcile guards against it explicitly via isPendingPaneId().\n */\nexport const PENDING_PANE_PREFIX = \"%pending-\";\n\n/** Build the placeholder pane id for an agent during worktree pre-stage. */\nexport function pendingPaneIdFor(agentName: string): string {\n return `${PENDING_PANE_PREFIX}${agentName}`;\n}\n\n/** True iff `paneId` is a `--worktree` pre-stage placeholder (not yet patched\n * to the real tmux pane id). */\nexport function isPendingPaneId(paneId: string): boolean {\n return paneId.startsWith(PENDING_PANE_PREFIX);\n}\n\n/**\n * Delete an agent row. Returns true if a row was matched. Idempotent;\n * deleting an agent that doesn't exist returns false without throwing.\n *\n * Reaper side-effect: any task that was IN_PROGRESS owned by this\n * agent gets flipped back to OPEN with a `[reaper]` task_note, and a\n * remote worker's worktree is recorded in `remote_recovery` first, all in\n * one transaction (src/agents/reap.ts). The FK on `tasks.owner` is\n * `ON DELETE SET NULL` so the owner column resets automatically; the\n * extra step here is the status revert. Without this an agent that\n * crashed (or was explicitly closed mid-task) leaves the task graph\n * in a wrong state — IN_PROGRESS forever, with no owner to release.\n */\nexport function deleteAgent(\n db: Db,\n name: string,\n workstream: string,\n /**\n * Compare-and-swap, checked inside the reaper transaction: delete only\n * if the row still has this pane id (a bare string) and/or this\n * incarnation. Same name but another pane or incarnation means the agent\n * was replaced: it is kept (false), with its row, socket and tasks.\n */\n expected?: string | AgentIdentity,\n /**\n * `preserve: false` skips the remote recovery record: only for a close that\n * has itself just removed (or found gone) the worktree. Every other\n * deleter keeps what the row says about it (src/remote-recovery.ts).\n */\n opts: { preserve?: boolean } = {},\n): boolean {\n const deleted = deleteAgentRow(db, name, workstream, expected, opts);\n if (deleted) unlinkCtlSocket(db, name, workstream);\n return deleted;\n}\n\n/** Which incarnation of a name a destructive write means. */\nexport interface AgentIdentity {\n paneId?: string;\n incarnation?: number;\n}\n\nfunction deleteAgentRow(\n db: Db,\n name: string,\n workstream: string,\n expected: string | AgentIdentity | undefined,\n opts: { preserve?: boolean },\n): boolean {\n const want: AgentIdentity =\n typeof expected === \"string\" ? { paneId: expected } : (expected ?? {});\n // Wrap the whole reaper sequence (snapshot stuck tasks → DELETE\n // agent → per-task UPDATE + addNote + emitEvent) in a single\n // synchronous better-sqlite3 transaction. Without this, a throw\n // mid-loop (FK race after workstream teardown, addNote/emitEvent\n // regression, OOM, …) would leave the agent row deleted (FK\n // CASCADE already SET NULL on tasks.owner_id) but only PART of\n // the reaper trail written: leftover IN_PROGRESS tasks with no\n // owner and no `[reaper]` note explaining how they got there.\n // Reconcile / `mu task wait --stuck-after` would then surface\n // them as ownerless zombies with no breadcrumb.\n // `task.reap` intent so the tasks-trigger ops this produces are\n // attributable. Without it the reaper's status revert landed as\n // intent=NULL typed ops (measured), unrenderable by the one formatter\n // v2-log-verb builds — the same defect as the prose events, in the\n // other direction.\n return withOpContext(db, { intent: \"task.reap\", actor: \"reaper\", group: \"new\" }, () =>\n db\n .transaction(() => {\n // Snapshot the stuck tasks BEFORE the DELETE; the FK CASCADE\n // (SET NULL on owner_id) makes the post-delete query\n // indistinguishable from \"never owned by this agent.\"\n const agentId = agentIdByName(db, name, workstream);\n if (agentId === null) {\n // Already gone — idempotent return. (Could happen if reconcile\n // pruned a ghost concurrently.) The DELETE is a no-op.\n return false;\n }\n // Same name, different pane or incarnation: the agent was replaced; keep it.\n if (want.incarnation !== undefined && agentId !== want.incarnation) return false;\n if (want.paneId !== undefined) {\n const cur = db.prepare(\"SELECT pane_id FROM agents WHERE id = ?\").get(agentId) as\n | { pane_id: string }\n | undefined;\n if (cur?.pane_id !== want.paneId) return false;\n }\n return reapAgentRow(db, agentId, name, {\n preserve: opts.preserve !== false,\n });\n })\n .immediate(),\n );\n}\n\n// ────────────────────────────────────────────────────────────────────────\n// High-level verbs (spawn, send, read, list, close)\n// ────────────────────────────────────────────────────────────────────────\n\n/** Allowed agent name shape: lowercase alpha first, then alnum/underscore/\n * hyphen. Mirrors docs/reference/naming.md. */\nconst AGENT_NAME_RE = /^[a-z][a-z0-9_-]{0,31}$/;\n/** Longest name AGENT_NAME_RE accepts. */\nexport const MAX_AGENT_NAME_LEN = 32;\n\nexport function isValidAgentName(name: string): boolean {\n return AGENT_NAME_RE.test(name);\n}\n\n/**\n * Send text to an agent and submit it. A pi agent gets it through its\n * control socket (AgentCtlUnreachableError when that does not answer —\n * never a silent paste), `/new` / `/reload` / `/compact` included; a\n * non-pi CLI gets one atomic herdr `agent prompt`; on tmux it is refused\n * (AgentSendUnsupportedError). See src/agents/transport.ts.\n */\nexport async function sendToAgent(\n db: Db,\n name: string,\n text: string,\n opts: TransportSendOptions & {\n workstream: string;\n /**\n * The registry id + pane the caller means (a just-spawned agent): the\n * name now holding another one is refused (AgentReplacedError), the\n * prompt never goes to a replacement.\n */\n expect?: { incarnation: number; paneId: string };\n },\n): Promise<SendResult> {\n const agent = getAgent(db, name, opts.workstream);\n if (!agent) throw new AgentNotFoundError(name);\n if (\n opts.expect !== undefined &&\n (agent.incarnation !== opts.expect.incarnation || agent.paneId !== opts.expect.paneId)\n ) {\n throw new AgentReplacedError(name, opts.workstream, \"sent to\");\n }\n const sent = await sendViaTransport(agent, text, {\n ...opts,\n socket: opts.socket ?? agentCtlSocket(db, agent),\n });\n const source = await resolveActorIdentity();\n recordSend(\n db,\n agent,\n opts.fresh ? \"fresh\" : opts.mode === \"steer\" ? \"steer\" : \"plain\",\n Buffer.byteLength(text),\n {\n transport: sent.transport,\n command: sent.command,\n state: sent.state,\n since: sent.since,\n },\n source,\n );\n return sent;\n}\n\n/**\n * Read scrollback from an agent's pane. With no options, returns the full\n * scrollback (`-S - -E -`); with `lines: N`, returns only the last N lines.\n */\nexport async function readAgent(\n db: Db,\n name: string,\n opts: CaptureOptions & { workstream: string },\n): Promise<string> {\n const agent = getAgent(db, name, opts.workstream);\n if (!agent) throw new AgentNotFoundError(name);\n // Load-bearing: the scrollback IS the output of this verb.\n return (await activeMux()).capture(agent.paneId, opts);\n}\n\nexport interface ListLiveAgentsOptions {\n workstream: string;\n tmuxSession?: string;\n /**\n * Which kind of reconciliation pass to run. Forwarded to\n * `reconcile()`'s same-name option. Default `\"full\"` (the\n * documented mutating behaviour `mu agent list` has always had,\n * now also used by `mu state`).\n *\n * `mu doctor` passes `\"report-only\"`: count drift, mutate nothing.\n *\n * Mid-spawn placeholders (pane id `%pending-<name>`) are protected\n * directly in reconcile's prune loop, independent of mode\n * (see PENDING_PANE_PREFIX).\n *\n * BREAKING: this replaces the previous `dryRun?: boolean`\n * option. Migration: `dryRun: true` → `mode: \"report-only\"`;\n * default (`dryRun: false` / unset) → `mode: \"full\"`.\n */\n mode?: ReconcileMode;\n}\n\nexport interface LiveAgentsView {\n /** All registered agents in the workstream, post-reconcile. */\n agents: LiveAgent[];\n /** Panes in the tmux session that look like agents but aren't registered. */\n orphans: MuxPane[];\n /** Diagnostic numbers from the reconcile pass; useful for `mu doctor`. */\n report: ReconcileReport;\n}\n\n/**\n * Return the live, reality-reconciled view of agents in a workstream.\n * `mu state` and `mu agent list` call this with the default `mode: \"full\"`\n * (mutating); the read-only diagnostic (`mu doctor`) calls it with\n * `mode: \"report-only\"` to mutate nothing at all.\n */\nexport async function listLiveAgents(db: Db, opts: ListLiveAgentsOptions): Promise<LiveAgentsView> {\n const report = await reconcile(db, {\n workstream: opts.workstream,\n ...(opts.tmuxSession !== undefined ? { tmuxSession: opts.tmuxSession } : {}),\n ...(opts.mode !== undefined ? { mode: opts.mode } : {}),\n });\n return { agents: await readLiveAgents(db, opts.workstream), orphans: report.orphans, report };\n}\n\n/**\n * The registered agents of a workstream with their computed runtime state\n * (ctl probe, idle flag), WITHOUT reconciling: no mux read, nothing reaped,\n * no write. The read-only half of {@link listLiveAgents}; `stateSnapshot`\n * (and so `mu state --me` and the dashboard) uses it.\n */\nexport async function readLiveAgents(\n db: Db,\n workstream: string,\n /** Only the agent of this name (`mu me` reads itself, not its neighbours' sockets). */\n only?: string,\n /**\n * A reading cache keyed by `agentKey` (the dashboard's slow tier). With `probe: false`\n * an agent already in the cache is NOT probed (no socket, no subprocess): only agents\n * missing from it are, and their readings are added. `probe: true` re-reads every agent\n * and refreshes the cache. Absent: probe every agent, cache nothing.\n */\n states?: { cache: Map<string, StateReading>; probe: boolean },\n): Promise<LiveAgent[]> {\n const baseAgents = listAgents(db, { workstream }).filter(\n (a) => only === undefined || a.name === only,\n );\n const stateDir = dirname(db.name);\n let readings: ReadonlyMap<string, StateReading>;\n if (states === undefined) readings = await readAgentStates(baseAgents, { stateDir });\n else {\n const due = states.probe\n ? baseAgents\n : baseAgents.filter((a) => !states.cache.has(agentKey(a)));\n if (due.length > 0) {\n for (const [k, r] of await readAgentStates(due, { stateDir })) states.cache.set(k, r);\n }\n readings = states.cache;\n }\n const now = Date.now();\n return baseAgents.map((agent) => {\n const reading = readings.get(agentKey(agent)) ?? {\n state: \"unknown\" as const,\n source: \"none\" as const,\n since: null,\n alive: true,\n reason: \"state unavailable\",\n };\n const live: LiveAgent = {\n ...agent,\n state: reading.state,\n source: reading.source,\n ctl: reading.ctl ?? \"n/a\",\n since: reading.since === null ? null : new Date(reading.since).toISOString(),\n ...(reading.reason !== undefined ? { reason: reading.reason } : {}),\n ...(reading.tool !== undefined ? { tool: reading.tool } : {}),\n };\n return computeAgentIdle(db, live, now) ? { ...live, idle: true } : live;\n });\n}\n","import { accessSync, constants, existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { delimiter, join } from \"node:path\";\nimport { expectsCtl } from \"./agents/transport.js\";\nimport { ctlProbe } from \"./ctl/client.js\";\nimport { ctlSocketPath } from \"./ctl/path.js\";\nimport type { CtlBlocked, CtlState, CtlTool } from \"./ctl/protocol.js\";\nimport { execFileCapture } from \"./exec-file.js\";\nimport { activeMux } from \"./mux/detect.js\";\nimport { tmux } from \"./tmux.js\";\n\nexport type RuntimeState = \"busy\" | \"needs_input\" | \"needs_permission\" | \"unknown\";\nexport type StateSource = \"murmur\" | \"herdr\" | \"ctl\" | \"none\";\n/** How a pi agent's control socket answered; \"n/a\" for non-pi agents. */\nexport type CtlLink = \"ok\" | \"missing\" | \"refused\" | \"n/a\";\n\nexport interface StateReading {\n state: RuntimeState;\n source: StateSource;\n since: number | null;\n alive: boolean;\n reason?: string;\n /** Set for agents that expect a control socket. */\n ctl?: Exclude<CtlLink, \"n/a\">;\n /** ctl only: pi holds queued messages, so an idle reading is about to\n * turn busy. */\n pending?: boolean;\n /** ctl only: pi's settled-run count (`mu agent wait --after-runs`). */\n runs?: number;\n /** ctl only: the pi process's incarnation string; absent from older extensions. */\n incarnation?: string;\n /** ctl only: the extension dialog pi is waiting on (state needs_permission). */\n blocked?: CtlBlocked;\n /** ctl only: the running tool, null when none; absent from older extensions (unknown). */\n tool?: CtlTool | null;\n}\n\nexport interface StateAgentRef {\n name: string;\n workstreamName: string;\n paneId: string;\n /** When set and it names pi, the control socket is the state source. */\n cli?: string;\n /** A remote command gate (see src/agents/gate.ts): no control socket, whatever `cli` says. */\n gateToken?: string | null;\n}\n\n/** Per-agent budget for the control-socket status read (one connection). */\nconst CTL_STATE_PROBE_MS = 1000;\n\n/** ctl's idle maps to needs_input, the same as murmur's idle; an open\n * extension dialog (`blocked`) maps to needs_permission. */\nexport function ctlRuntimeState(state: CtlState, blocked?: CtlBlocked): RuntimeState {\n if (blocked !== undefined) return \"needs_permission\";\n return state === \"busy\" ? \"busy\" : \"needs_input\";\n}\n\n/** The reason line for a dialog-blocked pi: `dialog <kind>: <title>`. */\nexport function blockedReason(blocked: CtlBlocked): string {\n return `dialog ${blocked.kind}${blocked.title !== undefined ? `: ${blocked.title}` : \"\"}`;\n}\n\nexport const UNKNOWN_REASON = {\n murmurMissing: \"murmur not installed\",\n extensionMissing: \"murmur pi extension not linked\",\n noRow: \"murmur has no row\",\n stale: \"remote snapshot stale\",\n herdrNone: \"herdr reports no state\",\n paneGone: \"pane gone\",\n ctlMissing: \"ctl missing\",\n ctlRefused: \"ctl refused\",\n} as const;\n\nexport type MurmurRunner = () => Promise<string | null>;\n\nconst MURMUR_CACHE_MS = 10_000;\nlet murmurRunnerForTests: MurmurRunner | null = null;\nlet murmurCache: { at: number; stdout: string | null } | undefined;\n\nexport function agentKey(a: { name: string; workstreamName: string }): string {\n return `${a.workstreamName}/${a.name}`;\n}\n\nexport function ambiguousReason(n: number): string {\n return `ambiguous: ${n} hosts`;\n}\n\nfunction murmurOnPath(): boolean {\n for (const dir of (process.env.PATH ?? \"\").split(delimiter)) {\n if (dir.length === 0) continue;\n try {\n accessSync(join(dir, \"murmur\"), constants.X_OK);\n return true;\n } catch {\n // Keep scanning PATH.\n }\n }\n return false;\n}\n\nfunction murmurExtensionLinked(): boolean {\n const piDir = process.env.PI_CODING_AGENT_DIR ?? join(homedir(), \".pi\", \"agent\");\n return existsSync(join(piDir, \"extensions\", \"murmur.ts\"));\n}\n\nexport function murmurAvailable(): boolean {\n return murmurOnPath() && murmurExtensionLinked();\n}\n\nconst defaultMurmurRunner: MurmurRunner = async () => {\n try {\n const result = await execFileCapture(\"murmur\", [\"status\", \"--json\"], { timeoutMs: 5_000 });\n return result.exitCode === 0 ? result.stdout : null;\n } catch {\n return null;\n }\n};\n\nexport function setMurmurRunnerForTests(run: MurmurRunner | null): void {\n murmurRunnerForTests = run;\n}\n\nexport function resetAgentStateCacheForTests(): void {\n murmurCache = undefined;\n}\n\nfunction unknown(reason: string, alive = true, source: StateSource = \"none\"): StateReading {\n return { state: \"unknown\", source, since: null, alive, reason };\n}\n\nfunction mapMurmurState(token: string, since: number | null): StateReading {\n let state: RuntimeState;\n switch (token) {\n case \"working\":\n state = \"busy\";\n break;\n case \"blocked\":\n state = \"needs_permission\";\n break;\n case \"idle\":\n case \"done\":\n case \"error\":\n case \"crashed\":\n state = \"needs_input\";\n break;\n default:\n return unknown(`unrecognised murmur state ${token}`, true, \"murmur\");\n }\n return { state, source: \"murmur\", since, alive: true };\n}\n\nfunction parseSince(value: string | undefined): number | null {\n return value !== undefined && /^\\d+$/.test(value) ? Number(value) : null;\n}\n\nasync function readMurmur(now: number): Promise<string | null> {\n if (murmurCache !== undefined && now - murmurCache.at < MURMUR_CACHE_MS) {\n return murmurCache.stdout;\n }\n let stdout: string | null;\n try {\n stdout = await (murmurRunnerForTests ?? defaultMurmurRunner)();\n } catch {\n stdout = null;\n }\n murmurCache = { at: now, stdout };\n return stdout;\n}\n\ninterface MurmurPane {\n local?: unknown;\n agent_name?: unknown;\n workstream?: unknown;\n activity?: unknown;\n attention?: unknown;\n freshness?: unknown;\n updated_at?: unknown;\n}\n\nfunction remotePanes(stdout: string): MurmurPane[] {\n try {\n const parsed: unknown = JSON.parse(stdout);\n if (typeof parsed !== \"object\" || parsed === null || !(\"panes\" in parsed)) return [];\n const panes = parsed.panes;\n if (!Array.isArray(panes)) return [];\n return panes.filter((pane): pane is MurmurPane => typeof pane === \"object\" && pane !== null);\n } catch {\n return [];\n }\n}\n\nfunction remoteReading(agent: StateAgentRef, panes: readonly MurmurPane[]): StateReading {\n const matches = panes.filter(\n (pane) =>\n pane.local === false &&\n pane.agent_name === agent.name &&\n pane.workstream === agent.workstreamName,\n );\n if (matches.length === 0) {\n return unknown(\n murmurExtensionLinked() ? UNKNOWN_REASON.noRow : UNKNOWN_REASON.extensionMissing,\n );\n }\n if (matches.length > 1) return unknown(ambiguousReason(matches.length));\n const row = matches[0];\n if (row === undefined) return unknown(UNKNOWN_REASON.noRow);\n if (row.freshness !== \"fresh\") return unknown(UNKNOWN_REASON.stale);\n\n const kinds = Array.isArray(row.attention)\n ? new Set(\n row.attention.flatMap((entry) =>\n typeof entry === \"object\" &&\n entry !== null &&\n \"kind\" in entry &&\n typeof entry.kind === \"string\"\n ? [entry.kind]\n : [],\n ),\n )\n : new Set<string>();\n const state: RuntimeState =\n kinds.has(\"crashed\") || kinds.has(\"error\")\n ? \"needs_input\"\n : kinds.has(\"blocked\")\n ? \"needs_permission\"\n : kinds.has(\"done\")\n ? \"needs_input\"\n : row.activity === \"running\"\n ? \"busy\"\n : \"needs_input\";\n return {\n state,\n source: \"murmur\",\n since: typeof row.updated_at === \"number\" ? row.updated_at : null,\n alive: true,\n };\n}\n\nasync function readHerdrStates(\n agents: readonly StateAgentRef[],\n mux: Awaited<ReturnType<typeof activeMux>>,\n): Promise<Map<string, StateReading>> {\n const readings = new Map<string, StateReading>();\n for (const agent of agents) {\n try {\n const status = await mux.paneStatus?.(agent.paneId);\n if (status !== undefined) {\n readings.set(agentKey(agent), {\n state: status,\n source: \"herdr\",\n since: null,\n alive: true,\n });\n continue;\n }\n const alive = await mux.paneAlive(agent.paneId);\n readings.set(\n agentKey(agent),\n alive\n ? unknown(UNKNOWN_REASON.herdrNone, true, \"herdr\")\n : unknown(UNKNOWN_REASON.paneGone, false),\n );\n } catch (error) {\n readings.set(\n agentKey(agent),\n unknown(`herdr: ${error instanceof Error ? error.message : String(error)}`),\n );\n }\n }\n return readings;\n}\n\n/**\n * Read the runtime state of each agent. Order per agent: control socket\n * (pi agents) → murmur pane option → murmur remote → herdr. A pi agent\n * whose socket does not answer reads `unknown` with reason `ctl missing`\n * or `ctl refused`, never a murmur reading, so the gap stays visible.\n * `stateDir` roots the derived socket path (spawn uses the DB's directory).\n * A remote command gate has neither: it reads from its pane (see `readGatePanes`).\n */\nexport async function readAgentStates(\n agents: readonly StateAgentRef[],\n opts: { now?: number; stateDir?: string } = {},\n): Promise<Map<string, StateReading>> {\n const gates = agents.filter((a) => a.gateToken !== undefined && a.gateToken !== null);\n if (gates.length === 0) return readNonGateStates(agents, opts);\n const readings = await readNonGateStates(\n agents.filter((a) => !gates.includes(a)),\n opts,\n );\n for (const [key, reading] of await readGatePanes(gates)) readings.set(key, reading);\n return readings;\n}\n\n/**\n * A gate's display reading, from its pane alone (never a host exec): running\n * reads busy; an ended or gone pane reads unknown with the reason. The wait\n * path reads the exit code itself (`readGate`).\n */\nasync function readGatePanes(gates: readonly StateAgentRef[]): Promise<Map<string, StateReading>> {\n const readings = new Map<string, StateReading>();\n let mux: Awaited<ReturnType<typeof activeMux>> | undefined;\n let failure = \"the multiplexer cannot report a pane's exit\";\n try {\n mux = await activeMux();\n } catch (error) {\n failure = `mux: ${error instanceof Error ? error.message : String(error)}`;\n }\n for (const gate of gates) {\n const key = agentKey(gate);\n try {\n const pane = await mux?.paneResult?.(gate.paneId);\n if (pane === undefined) readings.set(key, unknown(failure));\n else if (pane.state === \"running\") {\n readings.set(key, { state: \"busy\", source: \"none\", since: null, alive: true });\n } else if (pane.state === \"absent\")\n readings.set(key, unknown(UNKNOWN_REASON.paneGone, false));\n else {\n const how = pane.code !== null ? `exited ${pane.code}` : `killed by signal ${pane.signal}`;\n readings.set(key, unknown(how, false));\n }\n } catch (error) {\n readings.set(key, unknown(`mux: ${error instanceof Error ? error.message : String(error)}`));\n }\n }\n return readings;\n}\n\nasync function readNonGateStates(\n agents: readonly StateAgentRef[],\n opts: { now?: number; stateDir?: string },\n): Promise<Map<string, StateReading>> {\n const ctlAgents = agents.filter(\n (a) =>\n a.cli !== undefined &&\n expectsCtl(\n { cli: a.cli, name: a.name, workstreamName: a.workstreamName, gateToken: a.gateToken },\n ctlSocketPath(a.workstreamName, a.name, opts.stateDir),\n ),\n );\n const probes = await Promise.all(\n ctlAgents.map((a) =>\n ctlProbe(ctlSocketPath(a.workstreamName, a.name, opts.stateDir), CTL_STATE_PROBE_MS, {\n hello: false,\n }),\n ),\n );\n const readings = new Map<string, StateReading>();\n const failed = new Map<string, \"missing\" | \"refused\">();\n ctlAgents.forEach((agent, i) => {\n const probe = probes[i];\n if (probe?.kind === \"ok\") {\n const { blocked } = probe.status;\n readings.set(agentKey(agent), {\n state: ctlRuntimeState(probe.status.state, blocked),\n source: \"ctl\",\n since: blocked?.since ?? probe.status.since,\n alive: true,\n ...(blocked !== undefined ? { reason: blockedReason(blocked), blocked } : {}),\n ctl: \"ok\",\n pending: probe.status.pending,\n runs: probe.status.runs,\n ...(probe.incarnation !== undefined ? { incarnation: probe.incarnation } : {}),\n ...(probe.status.tool !== undefined ? { tool: probe.status.tool } : {}),\n });\n } else {\n failed.set(agentKey(agent), probe?.kind === \"missing\" ? \"missing\" : \"refused\");\n }\n });\n const rest = agents.filter((a) => !readings.has(agentKey(a)));\n if (rest.length === 0) return readings;\n // A ctl-failed agent keeps only the base reading's liveness, so it never\n // needs the murmur remote read (whose rows are always alive).\n for (const [key, reading] of await readBaseStates(rest, opts, new Set(failed.keys()))) {\n const ctl = failed.get(key);\n if (ctl === undefined) readings.set(key, reading);\n else if (!reading.alive) readings.set(key, { ...reading, ctl });\n else {\n const reason = ctl === \"missing\" ? UNKNOWN_REASON.ctlMissing : UNKNOWN_REASON.ctlRefused;\n readings.set(key, { ...unknown(reason), ctl });\n }\n }\n return readings;\n}\n\nasync function readBaseStates(\n agents: readonly StateAgentRef[],\n opts: { now?: number },\n livenessOnly: ReadonlySet<string> = new Set(),\n): Promise<Map<string, StateReading>> {\n const readings = new Map<string, StateReading>();\n let mux: Awaited<ReturnType<typeof activeMux>>;\n try {\n mux = await activeMux();\n } catch (error) {\n const reason = `mux: ${error instanceof Error ? error.message : String(error)}`;\n for (const agent of agents) readings.set(agentKey(agent), unknown(reason));\n return readings;\n }\n if (mux.paneStatus !== undefined) return await readHerdrStates(agents, mux);\n\n let stdout: string;\n try {\n stdout = await tmux([\n \"list-panes\",\n \"-a\",\n \"-F\",\n \"#{pane_id}\\t#{@murmur_pane_state}\\t#{@murmur_pane_since}\",\n ]);\n } catch (error) {\n const reason = `tmux: ${error instanceof Error ? error.message : String(error)}`;\n for (const agent of agents) readings.set(agentKey(agent), unknown(reason));\n return readings;\n }\n\n const local = new Map<string, { token: string; since: number | null }>();\n for (const line of stdout.split(\"\\n\")) {\n if (line.length === 0) continue;\n const [paneId, token = \"\", since] = line.split(\"\\t\");\n if (paneId !== undefined) local.set(paneId, { token, since: parseSince(since) });\n }\n\n const remoteCandidates: StateAgentRef[] = [];\n for (const agent of agents) {\n const pane = local.get(agent.paneId);\n if (pane === undefined) {\n readings.set(agentKey(agent), unknown(UNKNOWN_REASON.paneGone, false));\n } else if (livenessOnly.has(agentKey(agent))) {\n readings.set(agentKey(agent), unknown(UNKNOWN_REASON.noRow));\n } else if (pane.token.length > 0) {\n readings.set(agentKey(agent), mapMurmurState(pane.token, pane.since));\n } else {\n remoteCandidates.push(agent);\n }\n }\n\n if (remoteCandidates.length === 0) return readings;\n const remoteStdout = await readMurmur(opts.now ?? Date.now());\n if (remoteStdout === null) {\n const reason = murmurAvailable()\n ? UNKNOWN_REASON.noRow\n : murmurOnPath()\n ? UNKNOWN_REASON.extensionMissing\n : UNKNOWN_REASON.murmurMissing;\n for (const agent of remoteCandidates) readings.set(agentKey(agent), unknown(reason));\n return readings;\n }\n\n const panes = remotePanes(remoteStdout);\n for (const agent of remoteCandidates) readings.set(agentKey(agent), remoteReading(agent, panes));\n return readings;\n}\n","// mu — send transport: how `mu agent send` reaches an agent.\n//\n// A pi agent (speaksMuCtl) is reached through its control socket, served\n// by the mu pi extension inside the pane's own pi. `/new`, `/reload` and\n// `/compact` become the ctl `command` op; any other slash command is\n// refused (pi.sendUserMessage would hand it to the model as text).\n// A non-pi agent goes to `mux.sendToPane` when the backend has one (herdr's\n// atomic `agent prompt`), else AgentSendUnsupportedError (tmux). No\n// silent fallback: a pi agent whose socket does not answer is an\n// AgentCtlUnreachableError, never a paste.\n\nimport { existsSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AgentRow } from \"../agents.js\";\nimport {\n CtlDeliveryUnknownError,\n CtlUnknownOpError,\n CtlVersionError,\n CtlWriteVetoedError,\n ctlRequest,\n ctlServes,\n errCode,\n newMsgId,\n} from \"../ctl/client.js\";\nimport { ctlSocketPath } from \"../ctl/path.js\";\nimport {\n CTL_COMMANDS,\n type CtlCommandName,\n type CtlFeature,\n type CtlReply,\n type CtlRequest,\n type CtlState,\n INCARNATION_MISMATCH,\n} from \"../ctl/protocol.js\";\nimport type { Db } from \"../db.js\";\nimport { emitEvent } from \"../logs.js\";\nimport { say } from \"../messages.js\";\nimport { activeMux, attachShellLine, type SendOptions } from \"../mux.js\";\nimport { shellWord } from \"../shell-quote.js\";\nimport {\n AgentBusyError,\n AgentCtlUnreachableError,\n AgentEmptySendError,\n AgentExtensionOutdatedError,\n AgentFreshNeedsCtlError,\n AgentPaneDeadError,\n AgentReplacedError,\n AgentSendIndeterminateError,\n AgentSendRefusedError,\n AgentSendUnsupportedError,\n AgentSlashCommandUnsupportedError,\n} from \"./errors.js\";\nimport { resolveCliCommand, speaksMuCtl } from \"./spawn.js\";\n\nexport type Transport = \"ctl\" | \"mux\";\n\nexport type SendResult = {\n transport: Transport;\n state?: CtlState;\n /**\n * ctl only: pi's completed-run count. For a plain send it is measured\n * before dispatch (the `mu agent wait --after-runs` baseline); for\n * `--fresh` it is the new session's count once its run started.\n * Absent from an extension that predates it.\n */\n runs?: number;\n /** ctl only: when pi entered `state` (epoch ms), from the same status. */\n since?: number;\n /** ctl only: pi's session file, from the same status. */\n sessionFile?: string;\n /** Set when the text ran as a pi session command over ctl. */\n command?: CtlCommandName;\n /** ctl send/fresh/interrupt: the id this send carried; `mu agent check` asks about it later. */\n msgId?: string;\n /** ctl only: the pi process's incarnation, the `--inc` for `mu agent wait`. */\n incarnation?: string;\n /** Set when the reply never arrived and a `status {msgId}` probe confirmed the send landed. */\n receipt?: \"confirmed-after-timeout\";\n};\n\nexport type TransportSendOptions = SendOptions & {\n /** How a busy pi queues the message. Default followUp. ctl only. */\n mode?: \"steer\" | \"followUp\";\n /** Control socket path. Default: agentCtlSocket(db, agent). */\n socket?: string;\n /** Start a new pi session and send the text into it, as one ctl op. */\n fresh?: boolean;\n /** With fresh or a session command: abandon a running turn instead of refusing. */\n force?: boolean;\n /**\n * Internal: a msgId the caller reserved (and journaled) BEFORE the send, so\n * a crash leaves a receipt a later `status {msgId}` can ask about. ctl\n * send/fresh only; absent, the send mints its own. Never reuse one that was\n * already written: a saved id is checked, never resent.\n */\n msgId?: string;\n /**\n * Internal: the ctl incarnation the caller's own handshake saw (a spawn's\n * hello). The send is refused, nothing written, when the socket's pi is\n * another process (AgentReplacedError); the extension re-checks it\n * atomically with the dispatch (`expectIncarnation`). ctl send/fresh only.\n */\n expectIncarnation?: string;\n /**\n * Internal, opt-in (a stall action): bound the ctl round trips and fence the\n * write. `signal` aborts the hello and the request (an abort before the\n * write writes nothing; after it the delivery is indeterminate and probed,\n * never resent); `timeoutMs` bounds each ctl request; `beforeWrite` runs\n * synchronously on connect, immediately before the one write: false or a\n * throw writes nothing and the send throws CtlWriteVetoedError. ctl\n * send only; a route that cannot honour it (mux, session command) refuses rather than skip it.\n */\n ctlGuard?: CtlGuard;\n};\n\n/** See TransportSendOptions.ctlGuard. */\nexport interface CtlGuard {\n signal?: AbortSignal;\n timeoutMs?: number;\n beforeWrite?: () => boolean;\n}\n\n/** The agent's derived control socket, rooted at the DB's directory (as spawn does). */\nexport function agentCtlSocket(db: Db, agent: AgentRow): string {\n return ctlSocketPath(agent.workstreamName, agent.name, dirname(db.name));\n}\n\n/**\n * True when the agent runs pi, so sends go through its control socket.\n * The cli key decides when it names pi (or MU_<KEY>_COMMAND here runs\n * pi). Otherwise the agent's own socket file decides: spawn removes any\n * stale file before the pane starts, so a file at the derived path was\n * bound by this agent's extension (or its ssh forward). That covers\n * `--cli helper --command \"pi-meta ...\"`, whose command is not stored,\n * without a schema change. `sock` defaults to the derived path; pass\n * agentCtlSocket(db, agent) when a DB is at hand. A command gate (`gateToken`)\n * never speaks ctl: the discriminator beats both rules.\n */\nexport function expectsCtl(\n agent: Pick<AgentRow, \"cli\" | \"name\" | \"workstreamName\"> & { gateToken?: string | null },\n sock: string = ctlSocketPath(agent.workstreamName, agent.name),\n): boolean {\n // A remote command gate runs no pi, whatever its `cli` says or a forward leaves behind.\n if (agent.gateToken != null) return false;\n return speaksMuCtl(agent.cli, resolveCliCommand(agent.cli)) || existsSync(sock);\n}\n\n/** The slash commands a pi agent runs over ctl, as typed. */\nexport const CTL_SLASH_COMMANDS = CTL_COMMANDS.map((n) => `/${n}`);\n\n/**\n * `text` as a pi session command: `/new`, `/reload`, or `/compact` with\n * optional instructions. undefined for anything else (a plain prompt, or\n * another slash command: see isSlashCommand).\n */\nexport function parseSessionCommand(\n text: string,\n): { name: CtlCommandName; instructions?: string } | undefined {\n const t = text.trim();\n if (t === \"/new\") return { name: \"new\" };\n if (t === \"/reload\") return { name: \"reload\" };\n const m = /^\\/compact(?:\\s+([\\s\\S]*))?$/.exec(t);\n if (!m) return undefined;\n const instructions = m[1]?.trim();\n return instructions ? { name: \"compact\", instructions } : { name: \"compact\" };\n}\n\n/** True when `text` reads as a TUI slash command (`/word ...`), not a path or prose. */\nexport function isSlashCommand(text: string): boolean {\n return /^\\/[A-Za-z][\\w:-]*(?:\\s|$)/.test(text.trimStart());\n}\n\n/**\n * The recovery inputs of an outdated-extension error that only mu can\n * compute: the mux's own /reload line (when its backend can type one) and\n * the agent's spawn command, rebuilt from its row. Each is omitted when it\n * cannot be filled exactly (a hint mu cannot fill is not printed).\n */\nexport async function outdatedRecovery(\n agent: AgentRow,\n): Promise<{ muxReload?: string; respawn?: string }> {\n let muxReload: string | undefined;\n try {\n const mux = await activeMux();\n if (mux.reloadCommands) muxReload = attachShellLine(mux.reloadCommands(agent.paneId));\n } catch {\n // no reachable mux: the respawn step still stands\n }\n const respawn = respawnCommand(agent);\n return {\n ...(muxReload !== undefined ? { muxReload } : {}),\n ...(respawn !== undefined ? { respawn } : {}),\n };\n}\n\n/**\n * The `mu agent spawn` line that recreates `agent`, or undefined for a row\n * older than the stored command. An explicit --command is replayed\n * verbatim; an env or cli-key command is replayed as --cli only (the same\n * resolution happens again). A worktree agent respawns with --worktree (a\n * remote one with --root, its recorded repo).\n */\nexport function respawnCommand(agent: AgentRow): string | undefined {\n if (agent.command === null || agent.commandSource === null) return undefined;\n const parts = [\n \"mu agent spawn\",\n shellWord(agent.name),\n \"-w\",\n shellWord(agent.workstreamName),\n \"--cli\",\n shellWord(agent.cli),\n ];\n if (agent.commandSource === \"explicit\") parts.push(\"--command\", shellWord(agent.command));\n if (agent.host !== null) parts.push(\"--host\", shellWord(agent.host));\n if (agent.role !== \"full-access\") parts.push(\"--role\", shellWord(agent.role));\n if (agent.tab !== null) parts.push(\"--tab\", shellWord(agent.tab));\n if (agent.base !== null) {\n parts.push(\"--worktree\");\n // A remote worktree's repo was chosen at spawn: without it the respawn lands in the default.\n if (agent.host !== null && agent.repo !== null) parts.push(\"--root\", shellWord(agent.repo));\n } else if (agent.cwd !== null) parts.push(\"--cwd\", shellWord(agent.cwd));\n return parts.join(\" \");\n}\n\n/**\n * Map a CtlUnknownOpError to AgentExtensionOutdatedError, asking the\n * socket's `hello` (best effort) for the extension's build version.\n */\nexport async function extensionOutdated(\n agent: AgentRow,\n sock: string,\n e: CtlUnknownOpError,\n): Promise<AgentExtensionOutdatedError> {\n let extVersion: string | undefined;\n try {\n const hello = await ctlRequest(sock, { op: \"hello\" });\n if (hello.ok) extVersion = hello.extVersion;\n } catch {\n // The refusal already proved the socket answers; the version is a nicety.\n }\n return new AgentExtensionOutdatedError(\n agent.name,\n agent.workstreamName,\n e.op,\n extVersion,\n e.ops,\n await outdatedRecovery(agent),\n );\n}\n\n/**\n * Before a verb relies on `feature` (msgId for send/fresh/interrupt,\n * incarnation for `wait --inc`): ask the extension's `hello` which features\n * it serves. A pi that loaded an older mu build lacks them: refuse before\n * anything is written, with the reload/respawn ladder. One hello per verb\n * per agent; the reply is returned for the caller.\n */\nexport async function requireFeature(\n agent: AgentRow,\n sock: string,\n feature: CtlFeature,\n guard?: CtlGuard,\n): Promise<string | undefined> {\n return (await fencedHello(agent, sock, { feature, guard })).inc;\n}\n\n/**\n * The one incarnation fence every side-effecting ctl op (send, fresh,\n * interrupt, command) goes through. One hello, then:\n * - `feature` (if any) must be served, else AgentExtensionOutdatedError;\n * - an explicit `expect` that is not the hello's incarnation is refused\n * (AgentReplacedError, nothing written);\n * - `bound` is the field to put on the request: the explicit `expect`, else\n * the hello's own incarnation, so a pi that binds the socket after the\n * hello refuses the write. An op the extension may not fence (`needsFence`:\n * interrupt, command; an older extension ignores the field there) gets the\n * implicit fence only when hello lists `fence`, and an explicit one is\n * refused (op `fence`) rather than silently dropped.\n */\nexport async function fencedHello(\n agent: AgentRow,\n sock: string,\n o: { feature?: CtlFeature; expect?: string; needsFence?: boolean; guard?: CtlGuard },\n): Promise<{ inc: string | undefined; bound: { expectIncarnation?: string } }> {\n // The write fence is for the send alone: the hello is a read.\n const hello = await ctlRequestFor(agent, sock, { op: \"hello\" }, withGuard(o.guard, false));\n if (!hello.ok) throw new Error(say(\"agent.ctl_refused\", \"hello\", hello.error));\n const outdated = async (feature: string) =>\n new AgentExtensionOutdatedError(\n agent.name,\n agent.workstreamName,\n feature,\n hello.extVersion,\n hello.ops,\n { ...(await outdatedRecovery(agent)), feature: true },\n );\n if (o.feature !== undefined && !ctlServes(hello, o.feature)) throw await outdated(o.feature);\n const inc = hello.incarnation;\n const fenced = o.needsFence !== true || ctlServes(hello, \"fence\");\n if (o.expect !== undefined) {\n // The hello already names another pi (or none): refuse before any write.\n if (inc !== o.expect) throw new AgentReplacedError(agent.name, agent.workstreamName, \"sent to\");\n if (!fenced) throw await outdated(\"fence\");\n return { inc, bound: { expectIncarnation: o.expect } };\n }\n return { inc, bound: inc !== undefined && fenced ? { expectIncarnation: inc } : {} };\n}\n\n/**\n * One ctl request to `agent`, with the failure mapping every ctl verb\n * shares: a version mismatch rethrows, an unknown op becomes\n * AgentExtensionOutdatedError, anything else AgentCtlUnreachableError\n * (missing on ENOENT, else refused).\n */\nexport async function ctlRequestFor(\n agent: AgentRow,\n sock: string,\n req: CtlRequest,\n guard?: Pick<CtlGuard, \"signal\" | \"timeoutMs\">,\n): Promise<CtlReply> {\n try {\n return await ctlRequest(sock, req, withGuard(guard));\n } catch (e) {\n throw await ctlFailure(agent, sock, e);\n }\n}\n\nconst withGuard = (g?: CtlGuard, fence = true) => ({\n ...(g?.signal !== undefined ? { signal: g.signal } : {}),\n ...(g?.timeoutMs !== undefined ? { timeoutMs: g.timeoutMs } : {}),\n ...(fence && g?.beforeWrite !== undefined ? { beforeWrite: g.beforeWrite } : {}),\n});\n\n/** The error ctlRequestFor raises for a failed ctl request (see there). */\nexport async function ctlFailure(\n agent: AgentRow,\n sock: string,\n e: unknown,\n /** The msgId the failed request carried: lets an ambiguous delivery name its receipt. */\n msgId?: string,\n incarnation?: string,\n): Promise<unknown> {\n if (e instanceof CtlVersionError) return e;\n if (e instanceof CtlUnknownOpError) return extensionOutdated(agent, sock, e);\n // A silent socket on a vanished pane is a dead agent, not a link problem.\n // A request that was WRITTEN before the pane died may still have landed:\n // the error keeps its msgId as that evidence (a dead pane does not prove\n // the prompt was never delivered).\n if (await paneGone(agent.paneId)) {\n return new AgentPaneDeadError(\n agent.name,\n agent.workstreamName,\n agent.paneId,\n e instanceof CtlDeliveryUnknownError ? msgId : undefined,\n );\n }\n if (e instanceof CtlDeliveryUnknownError) {\n return new AgentSendIndeterminateError(\n agent.name,\n agent.workstreamName,\n e.op,\n e.cause.message,\n msgId,\n incarnation,\n agent.incarnation,\n );\n }\n return new AgentCtlUnreachableError(\n agent.name,\n agent.workstreamName,\n sock,\n errCode(e) === \"ENOENT\" ? \"missing\" : \"refused\",\n agent.host,\n );\n}\n\n/** The one `status {msgId}` probe a failed send gets, and `mu agent check`. */\nconst MSG_PROBE_MS = 5000;\n\nexport type MessageCheck =\n | { state: \"accepted\"; id: string; runs?: number; at?: number; incarnation?: string }\n | { state: \"not-accepted\"; id: string }\n | { state: \"unreachable\"; id: string; reason: string };\n\n/**\n * Ask the extension whether it accepted the send/fresh/interrupt that\n * carried `msgId`: one `status {msgId}` request. Never throws: a socket\n * that is silent, missing, or an extension that does not answer with a\n * `msg` is `unreachable`, which is not the same as `not-accepted`.\n */\nexport async function checkMessage(\n sock: string,\n msgId: string,\n timeoutMs: number = MSG_PROBE_MS,\n): Promise<MessageCheck> {\n try {\n const r = await ctlRequest(sock, { op: \"status\", msgId }, { timeoutMs });\n if (!r.ok) return { state: \"unreachable\", id: msgId, reason: r.error };\n if (r.msg === undefined) {\n return { state: \"unreachable\", id: msgId, reason: \"the extension does not report receipts\" };\n }\n if (!r.msg.accepted) return { state: \"not-accepted\", id: msgId };\n return {\n state: \"accepted\",\n id: msgId,\n ...(r.msg.runs !== undefined ? { runs: r.msg.runs } : {}),\n ...(r.msg.at !== undefined ? { at: r.msg.at } : {}),\n ...(r.incarnation !== undefined ? { incarnation: r.incarnation } : {}),\n };\n } catch (e) {\n return { state: \"unreachable\", id: msgId, reason: e instanceof Error ? e.message : String(e) };\n }\n}\n\n/**\n * A side-effecting ctl request carrying a fresh msgId. When the reply\n * never arrives (written, then silence) it asks `status {msgId}` ONCE:\n * accepted => the send landed (`receipt`); anything else =>\n * AgentSendIndeterminateError naming the msgId. It never resends.\n */\nexport async function ctlSendWithReceipt(\n agent: AgentRow,\n sock: string,\n req: Extract<CtlRequest, { msgId?: string }>,\n /** The incarnation the preflight hello named: the error carries it when delivery stays unknown. */\n incarnation?: string,\n /** A msgId the caller reserved before the send (see TransportSendOptions.msgId). */\n reservedMsgId?: string,\n guard?: CtlGuard,\n): Promise<{\n reply?: Extract<CtlReply, { ok: true }> | { ok: false; error: string };\n msgId: string;\n confirmed?: Extract<MessageCheck, { state: \"accepted\" }>;\n}> {\n const msgId = reservedMsgId ?? newMsgId();\n try {\n return { reply: await ctlRequest(sock, { ...req, msgId }, withGuard(guard)), msgId };\n } catch (e) {\n // The fence said no before the write: nothing was sent, and it is not a link failure.\n if (e instanceof CtlWriteVetoedError) throw e;\n if (!(e instanceof CtlDeliveryUnknownError)) {\n throw await ctlFailure(agent, sock, e, msgId, incarnation);\n }\n // The probe is its own bounded request: an abort of the send must not skip it.\n const check = await checkMessage(sock, msgId, guard?.timeoutMs);\n if (check.state === \"accepted\") return { msgId, confirmed: check };\n throw await ctlFailure(agent, sock, e, msgId, incarnation);\n }\n}\n\n/** True only when the mux positively reports the pane gone (a mux error is \"unknown\"). */\nasync function paneGone(paneId: string): Promise<boolean> {\n try {\n return !(await (await activeMux()).paneAlive(paneId));\n } catch {\n return false;\n }\n}\n\n/** How `mu agent send` delivered: the `mode=` of an `agent.send` op. */\nexport type SendMode = \"plain\" | \"steer\" | \"interrupt\" | \"fresh\";\n\n/**\n * Record a delivered send as an `agent.send` op. `agents` is machine-local\n * and a send mutates no table, so this emit is the only record that a\n * running worker was told something, and when. `fields` carries pi's\n * pre-send state (`since` as ISO) so an audit can see a worker stuck in\n * one long turn when a plain/steer send queued behind it.\n */\nexport function recordSend(\n db: Db,\n agent: Pick<AgentRow, \"name\" | \"workstreamName\">,\n mode: SendMode,\n bytes: number,\n fields: Record<string, string | number | boolean | undefined>,\n /** Who sent it (resolveActorIdentity); lands in `ops.actor`. */\n source = \"system\",\n): void {\n const detail = Object.entries({ mode, ...fields })\n .filter(([, v]) => v !== undefined)\n .map(([k, v]) => `${k}=${k === \"since\" ? new Date(Number(v)).toISOString() : v}`)\n .join(\" \");\n emitEvent(\n db,\n agent.workstreamName,\n \"agent.send\",\n `agent send ${agent.name} (${detail}, ${bytes} bytes)`,\n source,\n );\n}\n\nexport async function sendViaTransport(\n agent: AgentRow,\n text: string,\n // Required: only the caller knows the DB whose directory roots the socket.\n opts: TransportSendOptions & { socket: string },\n): Promise<SendResult> {\n const sock = opts.socket;\n if (!expectsCtl(agent, sock)) {\n if (opts.ctlGuard?.beforeWrite !== undefined) {\n throw new AgentSendUnsupportedError(agent.name, agent.workstreamName, agent.cli);\n }\n if (opts.fresh) throw new AgentFreshNeedsCtlError(agent.name, agent.workstreamName, agent.cli);\n // Load-bearing: a send that cannot reach a pane is a failed send.\n const mux = await activeMux();\n if (!mux.sendToPane) {\n throw new AgentSendUnsupportedError(agent.name, agent.workstreamName, agent.cli);\n }\n await mux.sendToPane(agent.paneId, text, opts);\n return { transport: \"mux\" };\n }\n if (text === \"\") throw new AgentEmptySendError(agent.name, agent.workstreamName);\n if (!opts.fresh) {\n const cmd = parseSessionCommand(text);\n if (cmd) {\n // The command route has no write fence: refuse rather than skip it.\n if (opts.ctlGuard?.beforeWrite !== undefined) {\n throw new AgentSendUnsupportedError(agent.name, agent.workstreamName, agent.cli);\n }\n return runSessionCommand(agent, sock, cmd, opts.force === true, opts.expectIncarnation);\n }\n if (isSlashCommand(text)) {\n throw new AgentSlashCommandUnsupportedError(\n agent.name,\n agent.workstreamName,\n text,\n CTL_SLASH_COMMANDS,\n );\n }\n }\n // Receipts need an extension that remembers msgIds: refuse before writing.\n const { inc, bound } = await fencedHello(agent, sock, {\n feature: \"msgId\",\n ...(opts.expectIncarnation !== undefined ? { expect: opts.expectIncarnation } : {}),\n guard: opts.ctlGuard,\n });\n const expect = bound.expectIncarnation;\n const sent = await ctlSendWithReceipt(\n agent,\n sock,\n opts.fresh\n ? { op: \"fresh\", text, ...(opts.force ? { force: true } : {}), ...bound }\n : { op: \"send\", text, mode: opts.mode ?? \"followUp\", ...bound },\n inc,\n opts.msgId,\n opts.ctlGuard,\n );\n const { reply, msgId } = sent;\n if (reply !== undefined && !reply.ok) {\n // The extension's own check: bound at the socket, atomic with the dispatch.\n if (expect !== undefined && reply.error === INCARNATION_MISMATCH) {\n throw new AgentReplacedError(agent.name, agent.workstreamName, \"sent to\");\n }\n if (opts.fresh && reply.error === \"busy\") {\n throw new AgentBusyError(agent.name, agent.workstreamName);\n }\n throw new AgentSendRefusedError(reply.error);\n }\n if (reply === undefined) {\n // No reply, but status {msgId} says it landed: the run count is the\n // one the reply would have carried; state and since are unknown.\n const c = sent.confirmed;\n return {\n transport: \"ctl\",\n msgId,\n receipt: \"confirmed-after-timeout\",\n ...(c?.runs !== undefined ? { runs: c.runs } : {}),\n ...(c?.incarnation !== undefined ? { incarnation: c.incarnation } : {}),\n };\n }\n return {\n transport: \"ctl\",\n msgId,\n ...(reply.incarnation !== undefined ? { incarnation: reply.incarnation } : {}),\n ...(reply.state !== undefined ? { state: reply.state } : {}),\n ...(reply.runs !== undefined ? { runs: reply.runs } : {}),\n ...(reply.since !== undefined ? { since: reply.since } : {}),\n ...(reply.sessionFile !== undefined ? { sessionFile: reply.sessionFile } : {}),\n };\n}\n\n/** `/new`, `/reload` or `/compact` inside pi, through the ctl `command` op. */\nasync function runSessionCommand(\n agent: AgentRow,\n sock: string,\n cmd: { name: CtlCommandName; instructions?: string },\n force: boolean,\n expect?: string,\n): Promise<SendResult> {\n const { bound } = await fencedHello(agent, sock, {\n needsFence: true,\n ...(expect !== undefined ? { expect } : {}),\n });\n const reply = await ctlRequestFor(agent, sock, {\n op: \"command\",\n name: cmd.name,\n ...(cmd.instructions !== undefined ? { instructions: cmd.instructions } : {}),\n ...(force ? { force: true } : {}),\n ...bound,\n });\n if (!reply.ok) {\n if (expect !== undefined && reply.error === INCARNATION_MISMATCH) {\n throw new AgentReplacedError(agent.name, agent.workstreamName, \"sent to\");\n }\n if (reply.error === \"busy\") {\n throw new AgentBusyError(agent.name, agent.workstreamName, `/${cmd.name}`);\n }\n throw new Error(say(\"agent.pi_refused\", cmd.name, reply.error));\n }\n return {\n transport: \"ctl\",\n command: cmd.name,\n ...(reply.state !== undefined ? { state: reply.state } : {}),\n };\n}\n","/**\n * Client for the per-agent control socket served by the mu pi extension.\n * One request per connection: connect, write one line, read one line, end.\n */\nimport { randomUUID } from \"node:crypto\";\nimport { createConnection } from \"node:net\";\nimport {\n CTL_PROTOCOL_VERSION,\n type CtlFeature,\n type CtlReply,\n type CtlRequest,\n type CtlStatus,\n encode,\n LineDecoder,\n UNKNOWN_OP_PREFIX,\n} from \"./protocol.js\";\n\n/** Default client timeout for non-`wait` requests. */\nexport const CTL_DEFAULT_TIMEOUT_MS = 5000;\n/** Client timeout for `fresh` and `command`: the new session must start its run, or pi reload. */\nexport const CTL_FRESH_TIMEOUT_MS = 60_000;\n/** Slack added to a `wait` request's own timeoutMs for the client timeout. */\nexport const CTL_WAIT_SLACK_MS = 5000;\n\nexport type CtlProbe =\n | {\n kind: \"ok\";\n status: CtlStatus;\n /** From hello: the ops the extension serves. Absent: it predates reporting them. */\n ops?: string[];\n /** From hello: the mu version the extension was built from. */\n extVersion?: string;\n /** From hello: the optional features the extension serves. Absent: it predates reporting them. */\n features?: string[];\n /** The pi process's incarnation (status reply, else hello's); absent from older extensions. */\n incarnation?: string;\n }\n | { kind: \"missing\" }\n | { kind: \"refused\"; error: string }\n | { kind: \"version\"; got: unknown };\n\nexport class CtlVersionError extends Error {\n constructor(readonly got: unknown) {\n super(`control socket speaks protocol v${String(got)}; mu expects v${CTL_PROTOCOL_VERSION}`);\n this.name = \"CtlVersionError\";\n }\n}\n\n/**\n * The `beforeWrite` fence of a request said no (or threw): NOTHING was written,\n * so unlike CtlDeliveryUnknownError this is a definite \"not delivered\".\n */\nexport class CtlWriteVetoedError extends Error {\n constructor(override readonly cause?: unknown) {\n super(\n `control socket write vetoed before it happened${\n cause instanceof Error ? `: ${cause.message}` : \"\"\n }`,\n );\n this.name = \"CtlWriteVetoedError\";\n }\n}\n\nexport class CtlTimeoutError extends Error {\n constructor(readonly timeoutMs: number) {\n super(`control socket did not reply within ${timeoutMs}ms`);\n this.name = \"CtlTimeoutError\";\n }\n}\n\n/**\n * A side-effecting request (send, fresh, interrupt, command) was written\n * to the socket, then the connection timed out, errored or closed with no\n * reply. pi may or may not have acted on it. `cause` is the raw failure.\n */\nexport class CtlDeliveryUnknownError extends Error {\n constructor(\n readonly op: string,\n override readonly cause: Error,\n ) {\n super(`control socket ${op} request was written but no reply arrived: ${cause.message}`);\n this.name = \"CtlDeliveryUnknownError\";\n }\n}\n\n/** Ops that change pi's state: a failure after the write is ambiguous. */\nconst SIDE_EFFECT_OPS: ReadonlySet<string> = new Set([\"send\", \"fresh\", \"interrupt\", \"command\"]);\n\n/**\n * The extension answered \"unknown op\": it was loaded before mu learned\n * `op`. `ops` lists what it serves (absent from extensions that predate\n * reporting them).\n */\nexport class CtlUnknownOpError extends Error {\n constructor(\n readonly op: string,\n readonly ops?: readonly string[],\n ) {\n super(`control socket does not serve op ${op}`);\n this.name = \"CtlUnknownOpError\";\n }\n}\n\nfunction clientTimeout(req: CtlRequest, override?: number): number | undefined {\n if (override !== undefined) return override;\n if (req.op === \"fresh\" || req.op === \"command\") return CTL_FRESH_TIMEOUT_MS;\n if (req.op !== \"wait\" && req.op !== \"interrupt\") return CTL_DEFAULT_TIMEOUT_MS;\n // An unbounded wait (or interrupt) is held until pi settles.\n return req.timeoutMs === undefined ? undefined : req.timeoutMs + CTL_WAIT_SLACK_MS;\n}\n\nfunction parseReply(line: string): CtlReply {\n const msg: unknown = JSON.parse(line);\n const v = typeof msg === \"object\" && msg !== null ? (msg as { v?: unknown }).v : undefined;\n if (v !== CTL_PROTOCOL_VERSION) throw new CtlVersionError(v);\n return msg as CtlReply;\n}\n\n/**\n * Send one request and resolve with its reply. Rejects with the socket\n * error (its `code` intact), CtlTimeoutError, CtlDeliveryUnknownError\n * (side-effecting op failed after the write), CtlVersionError, or\n * CtlUnknownOpError (an ok:false \"unknown op\" reply).\n * Aborting `signal` closes the connection and rejects (CtlDeliveryUnknownError\n * when a side-effecting request was already written: an abort is not an undo).\n * `beforeWrite` (opt-in) runs synchronously on connect, right before the one\n * write: returning false or throwing writes nothing and rejects with\n * CtlWriteVetoedError. Nothing awaits between the fence and the write.\n */\nexport function ctlRequest(\n sock: string,\n req: CtlRequest,\n opts?: { timeoutMs?: number; signal?: AbortSignal; beforeWrite?: () => boolean },\n): Promise<CtlReply> {\n const timeoutMs = clientTimeout(req, opts?.timeoutMs);\n return new Promise((resolve, reject) => {\n const conn = createConnection(sock);\n // Set when conn.write is called. A write callback is not a delivery ack, so never cleared.\n let written = false;\n const ambiguous = (err: Error): Error =>\n written && SIDE_EFFECT_OPS.has(req.op) ? new CtlDeliveryUnknownError(req.op, err) : err;\n const dec = new LineDecoder();\n let done = false;\n const finish = (err: Error | null, reply?: CtlReply): void => {\n if (done) return;\n done = true;\n if (timer) clearTimeout(timer);\n conn.destroy();\n if (err) reject(err);\n else if (reply) resolve(reply);\n };\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => finish(ambiguous(new CtlTimeoutError(timeoutMs))), timeoutMs);\n const signal = opts?.signal;\n if (signal?.aborted) finish(ambiguous(new Error(\"control socket request aborted\")));\n signal?.addEventListener(\n \"abort\",\n () => finish(ambiguous(new Error(\"control socket request aborted\"))),\n { once: true },\n );\n conn.setEncoding(\"utf8\");\n conn.on(\"connect\", () => {\n if (done) return;\n if (opts?.beforeWrite !== undefined) {\n let go = false;\n try {\n go = opts.beforeWrite();\n } catch (e) {\n finish(new CtlWriteVetoedError(e));\n return;\n }\n if (!go) {\n finish(new CtlWriteVetoedError());\n return;\n }\n }\n written = true;\n conn.write(encode(req));\n });\n conn.on(\"data\", (chunk: string) => {\n const line = dec.push(chunk)[0];\n if (line === undefined) return;\n try {\n const reply = parseReply(line);\n if (!reply.ok && reply.error.startsWith(UNKNOWN_OP_PREFIX)) {\n finish(new CtlUnknownOpError(req.op, reply.ops));\n } else finish(null, reply);\n } catch (e) {\n finish(e instanceof Error ? e : new Error(String(e)));\n }\n });\n conn.on(\"error\", (e) => finish(ambiguous(e)));\n conn.on(\"close\", () => finish(ambiguous(new Error(\"control socket closed without a reply\"))));\n });\n}\n\n/** A fresh msgId for a send/fresh/interrupt: 36 characters, within the extension's limit. */\nexport function newMsgId(): string {\n return randomUUID();\n}\n\n/** Whether a hello reply lists `feature`. An older extension lists none. */\nexport function ctlServes(hello: CtlReply, feature: CtlFeature): boolean {\n return hello.ok && (hello.features?.includes(feature) ?? false);\n}\n\n/** A Node system error's `code` (ENOENT, ECONNREFUSED, ...), if any. */\nexport function errCode(e: unknown): string | undefined {\n const code = typeof e === \"object\" && e !== null ? (e as { code?: unknown }).code : undefined;\n return typeof code === \"string\" ? code : undefined;\n}\n\n/**\n * hello + status (status only with `hello: false`, one connection).\n * `timeoutMs` bounds the whole probe, not each request. ENOENT → missing;\n * a version mismatch → version; any other failure (ECONNREFUSED,\n * ENOTSOCK, timeout, bad reply) → refused.\n */\nexport async function ctlProbe(\n sock: string,\n timeoutMs = CTL_DEFAULT_TIMEOUT_MS,\n opts: { hello?: boolean } = {},\n): Promise<CtlProbe> {\n const deadline = Date.now() + timeoutMs;\n try {\n let hello: CtlReply | undefined;\n if (opts.hello !== false) {\n hello = await ctlRequest(sock, { op: \"hello\" }, { timeoutMs });\n if (!hello.ok) return { kind: \"refused\", error: hello.error };\n }\n const left = Math.max(1, deadline - Date.now());\n const st = await ctlRequest(sock, { op: \"status\" }, { timeoutMs: left });\n if (!st.ok) return { kind: \"refused\", error: st.error };\n const { state, since, runs, pending, blocked, tool } = st;\n if (state === undefined || since === undefined || runs === undefined || pending === undefined) {\n return { kind: \"refused\", error: \"status reply is missing fields\" };\n }\n return {\n kind: \"ok\",\n status: {\n state,\n since,\n runs,\n pending,\n ...(blocked !== undefined ? { blocked } : {}),\n ...(tool !== undefined ? { tool } : {}),\n },\n ...(hello?.ok && hello.ops !== undefined ? { ops: hello.ops } : {}),\n ...(hello?.ok && hello.extVersion !== undefined ? { extVersion: hello.extVersion } : {}),\n ...(hello?.ok && hello.features !== undefined ? { features: hello.features } : {}),\n ...(st.incarnation !== undefined || (hello?.ok && hello.incarnation !== undefined)\n ? { incarnation: st.incarnation ?? (hello?.ok ? hello.incarnation : undefined) }\n : {}),\n };\n } catch (e) {\n if (e instanceof CtlVersionError) return { kind: \"version\", got: e.got };\n if (errCode(e) === \"ENOENT\") return { kind: \"missing\" };\n return { kind: \"refused\", error: e instanceof Error ? e.message : String(e) };\n }\n}\n","/**\n * mu control socket protocol: JSON lines over a unix socket, one request\n * per connection. Shared by mu's client and the mu pi extension, so this\n * file imports nothing from mu — the extension loads it standalone.\n */\n\nexport const CTL_PROTOCOL_VERSION = 1;\n\nexport type CtlState = \"busy\" | \"idle\";\n\n/**\n * pi is waiting on a blocking extension dialog (ui_prompt_start without\n * its ui_prompt_end): a confirm, select, input, editor or custom prompt.\n * `kind` and `title` are the innermost open dialog's; `since` is when the\n * first one opened (ms epoch).\n */\nexport type CtlBlocked = { kind: string; title?: string; since: number };\n\nexport type CtlRequest =\n | { op: \"hello\" }\n /** With msgId, also reply `msg`: whether this extension accepted that send/fresh/interrupt. */\n | { op: \"status\"; msgId?: string }\n /**\n * `msgId` (send, fresh, interrupt; a string of 1-CTL_MSGID_MAX_LENGTH\n * characters) lets the caller ask `status` later whether the request\n * was accepted, when no reply arrived.\n */\n | {\n op: \"send\";\n text: string;\n mode?: \"steer\" | \"followUp\";\n msgId?: string;\n /** Refused before acting (INCARNATION_MISMATCH) when it is not the extension's current incarnation. */\n expectIncarnation?: string;\n }\n /**\n * Resolve once a run past afterRuns settles. With returnOnBlocked, also\n * resolve (ended \"blocked\", runs unchanged) when a dialog is open or\n * opens. Older extensions ignore the flag and hold until the settle.\n */\n | {\n op: \"wait\";\n afterRuns?: number;\n timeoutMs?: number;\n returnOnBlocked?: boolean;\n /** Refused at once (INCARNATION_MISMATCH) when it is not the extension's current one. */\n incarnation?: string;\n }\n | { op: \"abort\" }\n /**\n * Make a busy pi act on `text` now: abort the running turn, wait for\n * agent_settled (up to timeoutMs), then send `text` as a new run. Idle:\n * just send. Replies `timeout` and sends nothing when pi does not settle.\n */\n | {\n op: \"interrupt\";\n text: string;\n timeoutMs?: number;\n msgId?: string;\n /** As on `send`: another incarnation is refused before the abort. */\n expectIncarnation?: string;\n }\n /** New session + prompt as one operation. Refused with error \"busy\" unless force. */\n | {\n op: \"fresh\";\n text: string;\n force?: boolean;\n msgId?: string;\n /** As on `send`: another incarnation is refused before any state changes. */\n expectIncarnation?: string;\n }\n /**\n * Run one of pi's session commands inside pi (sendUserMessage cannot run\n * built-in slash commands). Refused with error \"busy\" unless force.\n */\n | {\n op: \"command\";\n name: CtlCommandName;\n instructions?: string;\n force?: boolean;\n /** As on `send`: another incarnation is refused before any session change. */\n expectIncarnation?: string;\n };\n\n/** Session commands the `command` op runs: `/new`, `/reload`, `/compact`. */\nexport const CTL_COMMANDS = [\"new\", \"reload\", \"compact\"] as const;\nexport type CtlCommandName = (typeof CTL_COMMANDS)[number];\n\n/**\n * Every op this protocol defines. The extension reports the ops it serves\n * in its `hello` reply (and in an unknown-op error), so mu can tell an\n * extension loaded by an older pi process from a broken one.\n */\nexport const CTL_OPS = [\n \"hello\",\n \"status\",\n \"send\",\n \"wait\",\n \"abort\",\n \"interrupt\",\n \"fresh\",\n \"command\",\n] as const satisfies readonly CtlRequest[\"op\"][];\n\n/**\n * Optional capabilities, listed in the `hello` reply's `features`. Ops stay\n * as they are: a feature is a field an old client never sends and ignores.\n * `fence`: `expectIncarnation` is honoured on every side-effecting op\n * (send, fresh, interrupt, command); an extension without it ignores the\n * field on interrupt and command, so a caller never relies on it there.\n */\nexport const CTL_FEATURES = [\"incarnation\", \"msgId\", \"fence\"] as const;\nexport type CtlFeature = (typeof CTL_FEATURES)[number];\n\n/** How many accepted msgIds the extension remembers (oldest evicted). */\nexport const CTL_MSGID_MEMORY = 64;\n/** Longest msgId the extension accepts. */\nexport const CTL_MSGID_MAX_LENGTH = 64;\n\n/** Error text of a `wait`, `send` or `fresh` that named another pi process's incarnation. */\nexport const INCARNATION_MISMATCH = \"incarnation mismatch\";\n\n/** The tool pi is executing (innermost, latest started); `since` is ms epoch. */\nexport type CtlTool = { name: string; since: number };\n\nexport type CtlStatus = {\n state: CtlState;\n since: number;\n runs: number;\n pending: boolean;\n /** The pi session file (where the transcript is written); absent for an ephemeral pi or an older extension. */\n sessionFile?: string;\n /** Set while pi waits on an extension dialog; absent from older extensions. */\n blocked?: CtlBlocked;\n /** The running tool, `null` when none; absent from older extensions (unknown, not \"none\"). */\n tool?: CtlTool | null;\n};\n\nexport type CtlReply =\n | ({ v: 1; ok: true } & Partial<CtlStatus> & {\n agent?: string;\n workstream?: string;\n piVersion?: string;\n /** hello only: the ops this extension serves. Absent: predates reporting. */\n ops?: string[];\n /** hello only: the optional features this extension serves. Absent: none. */\n features?: string[];\n /**\n * hello, status, send, fresh, interrupt, wait: minted once per pi\n * process per socket; stable across /new and /reload, new after pi\n * restarts. Absent from older extensions.\n */\n incarnation?: string;\n /** status with msgId only: whether that msgId was accepted, and the reply's `runs`/time if so. */\n msg?: { id: string; accepted: boolean; runs?: number; at?: number };\n /** hello only: the mu package version the extension was built from. */\n extVersion?: string;\n /** wait only: \"blocked\" when a dialog ended the wait before a settle (returnOnBlocked). */\n ended?: \"settled\" | \"blocked\";\n /** wait only: text of the settled run's final assistant message (\"\" when none). */\n lastText?: string;\n /** wait only: true when `lastText` lost its head to the 64 KiB tail cap. Absent otherwise. */\n lastTextTruncated?: boolean;\n /** wait only: the error that ended the settled run (retries exhausted). */\n lastError?: string;\n /** wait only: the settled pi's session file, where its full transcript lives. */\n sessionFile?: string;\n /**\n * abort, interrupt: pi was busy, so a turn was aborted. For abort,\n * absent from older extensions (which always call abort).\n */\n wasBusy?: boolean;\n })\n | {\n v: 1;\n ok: false;\n error: string;\n ops?: string[];\n /** With INCARNATION_MISMATCH: the extension's current incarnation. */\n incarnation?: string;\n };\n\n/** Error text of a reply to an op the extension does not serve. */\nexport const UNKNOWN_OP_PREFIX = \"unknown op: \";\n\n/** One frame. JSON.stringify escapes \"\\n\" inside strings, so the frame is one line. */\nexport function encode(msg: object): string {\n return `${JSON.stringify(msg)}\\n`;\n}\n\n/** Splits a stream into lines on \"\\n\" only (never U+2028/U+2029). */\nexport class LineDecoder {\n private buf = \"\";\n\n push(chunk: string): string[] {\n this.buf += chunk;\n const parts = this.buf.split(\"\\n\");\n this.buf = parts.pop() ?? \"\";\n return parts;\n }\n}\n","/**\n * Per-agent control socket path. Derived from (state dir, workstream,\n * agent) on every call; never stored. The mu pi extension serves the\n * socket at `$MU_CTL_SOCK`, and mu connects to the same derived path.\n */\nimport { createHash } from \"node:crypto\";\nimport { rmSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { type Db, defaultStateDir } from \"../db.js\";\n\n/** Env var spawn injects so the pi extension knows where to listen. */\nexport const CTL_SOCK_ENV = \"MU_CTL_SOCK\";\n\n/** macOS sun_path is 104 bytes including the trailing NUL. */\nexport const MAX_SOCK_PATH = 103;\n\n/** `<dir>/<ws>/<agent>.sock`, or `<dir>/h/<hash>.sock` past MAX_SOCK_PATH. */\nfunction sockPathUnder(dir: string, workstream: string, agent: string): string {\n const readable = join(dir, workstream, `${agent}.sock`);\n if (Buffer.byteLength(readable) <= MAX_SOCK_PATH) return readable;\n const h = createHash(\"sha1\").update(`${workstream}/${agent}`).digest(\"hex\").slice(0, 16);\n return join(dir, \"h\", `${h}.sock`);\n}\n\nexport function ctlSocketPath(workstream: string, agent: string, stateDir?: string): string {\n const dbPath = process.env.MU_DB_PATH;\n const base = stateDir ?? (dbPath ? dirname(dbPath) : defaultStateDir());\n return sockPathUnder(join(base, \"sock\"), workstream, agent);\n}\n\n/**\n * Remove an agent's local control socket file. For a remote agent ssh's\n * `-L` forward leaves that file behind when the connection dies; it\n * probes as `refused`, never `ok`, but it is litter. A local pi removes\n * its own on quit. Best-effort: callers have already deleted the row.\n */\nexport function unlinkCtlSocket(db: Db, name: string, workstream: string): void {\n if (db.memory) return;\n try {\n rmSync(ctlSocketPath(workstream, name, dirname(db.name)), { force: true });\n } catch {\n /* best-effort */\n }\n}\n\n/**\n * Default socket path ON THE REMOTE HOST for a remote pi agent:\n * `/tmp/mu-<uid>/<ws>/<agent>.sock`, shortened by the same rule. `uid`\n * is the local one (mu cannot know the remote's); the extension creates\n * the directory.\n */\nexport function remoteCtlSocketPath(workstream: string, agent: string, uid: number): string {\n return sockPathUnder(`/tmp/mu-${uid}`, workstream, agent);\n}\n","// mu — DB module.\n//\n// Opens <state-dir>/mu.db (or the MU_DB_PATH override; see defaultDbPath),\n// enables WAL + foreign keys, applies the schema idempotently, and\n// exposes the live Database handle.\n//\n// Schema (v13; EXPECTED_TABLES below is the exact list, 26 tables), by group:\n// - entity (portable: they sync): workstreams, tasks, task_edges, task_notes.\n// tasks carries substate (status qualifier; a composite FK\n// (status, substate) -> task_substates, DEFERRABLE INITIALLY DEFERRED,\n// checked at COMMIT so apply's one-field-at-a-time UPDATEs pass), kind,\n// wave, scored, dispatch_host; task_notes carries kind.\n// - machine-local entity: agents (with cwd, base, spawner, host,\n// collected_head), worktrees, task_auto, delegate_calls, human_needs,\n// wait_cursors, wait_registrations, wait_resumes, wait_action_receipts,\n// agent_settles, spawn_receipts, host_profiles, host_channels,\n// remote_recovery\n// - ops log: ops (the single append-only record of every change:\n// VISION.md § 2b)\n// - sync: sync_peers (per-peer watermarks),\n// sync_fingerprints (caught-up fingerprints)\n// - meta: schema_version, machine_identity, op_ctx (op context),\n// op_dying (delete-key stash)\n// - lookup: task_substates (legal (status, substate) pairs, seeded\n// from code when missing)\n// - views: ready, blocked, blockers, goals\n// PORTABLE_TABLES / MACHINE_LOCAL_TABLES classify every table.\n//\n// v9 dropped v8's separate change-recording mechanisms (`agent_logs`,\n// `snapshots`, `workstream_sync`, the `archived_*` tables) for the one\n// **ops log**; sync and history are queries or replays over it\n// (docs/VOCABULARY.md § op, ops log, watermark).\n//\n// The surrogate-INTEGER-PK discipline introduced in v5 is unchanged:\n// per docs/architecture/sdk.md § Surrogate-PK and SDK-boundary discipline,\n// every entity table has an INTEGER PK; FKs reference INTEGER ids;\n// the operator-facing TEXT name is per-scope unique via\n// UNIQUE (<scope_id>, <name>). `ops` is the deliberate exception: it\n// holds the NATURAL key (`ws/local_id`) in `ops.key`, never a\n// surrogate id, which is exactly why keys don't collide across\n// machines.\n//\n// IMPORTANT: there is no migration ladder. openDb accepts only\n// CURRENT_SCHEMA_VERSION (13) and completes a v13 file that lacks later\n// additions in ONE transaction (upgradeSchema: columns, tables, triggers\n// and both stamps together). Every older DB is rejected with\n// SchemaTooOldError (exit 4), and a DB newer than this build with\n// SchemaTooNewError (exit 4).\n\nimport { randomUUID } from \"node:crypto\";\nimport { mkdirSync } from \"node:fs\";\nimport { homedir, hostname } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport Database, { type Database as DatabaseType, type Statement } from \"better-sqlite3\";\nimport {\n CAPTURE_VERSION,\n CaptureTooNewError,\n installCaptureLocked,\n sqliteTooOld,\n storedCaptureVersion,\n} from \"./capture.js\";\nimport { LEGACY_RECOVERY_TRIGGERS, REMOTE_RECOVERY_DDL } from \"./db-recovery.js\";\nimport { say } from \"./messages.js\";\nimport { defaultStateDir, xdgStateHome } from \"./state-dir.js\";\nimport { TASK_SUBSTATE_ROWS } from \"./tasks/status.js\";\n\nexport { defaultStateDir };\n\nexport type Db = DatabaseType;\n\nconst statementCache = new WeakMap<Db, Map<string, Statement>>();\n\n/**\n * `db.prepare(sql)`, compiled once per connection and reused.\n *\n * better-sqlite3 has no statement cache, so a hot loop that calls\n * `db.prepare` per row pays SQL compilation every time. Ingest applies\n * thousands of ops and prepared ~10 statements per op, which made SQL\n * compilation most of a large catch-up's cost. Use this on per-op paths;\n * one-off queries keep plain `db.prepare`. `sql` must come from a fixed\n * template (the cache never evicts). Not for a statement a caller\n * `.iterate()`s while re-entering the same SQL: a busy statement throws.\n */\nexport function prepareCached(db: Db, sql: string): Statement {\n let byDb = statementCache.get(db);\n if (byDb === undefined) {\n byDb = new Map();\n statementCache.set(db, byDb);\n }\n let stmt = byDb.get(sql);\n if (stmt === undefined) {\n stmt = db.prepare(sql);\n byDb.set(sql, stmt);\n }\n return stmt;\n}\n\nexport interface OpenDbOptions {\n /**\n * Absolute path to the SQLite file. Defaults to MU_DB_PATH env var or\n * the XDG state path (see `defaultDbPath`). Use a per-test temp path\n * in tests.\n */\n path?: string;\n\n /**\n * If true, opens the DB read-only. Used by `mu sql` and similar read-only\n * surfaces to enforce no-mutation guarantees at the connection level.\n */\n readonly?: boolean;\n}\n\n/**\n * Resolve the canonical DB path:\n * MU_DB_PATH > <state-dir>/mu.db\n */\nexport function defaultDbPath(): string {\n if (process.env.MU_DB_PATH) return process.env.MU_DB_PATH;\n return join(defaultStateDir(), \"mu.db\");\n}\n\n/**\n * Open the mu database. Creates the parent directory and applies the schema\n * idempotently when it is missing or differs from this build (an\n * up-to-date DB opens without a write). Safe to call from many short-lived processes\n * concurrently — WAL mode handles cross-process writes.\n */\nexport function openDb(options: OpenDbOptions = {}): Db {\n const path = options.path ?? defaultDbPath();\n refuseUserDbDuringTests(path);\n mkdirSync(dirname(path), { recursive: true });\n\n const db = new Database(path, { readonly: options.readonly ?? false });\n\n if (!options.readonly) {\n // Wait up to 5s for a competing writer's lock instead of throwing\n // SQLITE_BUSY immediately. Every `mu` invocation is a separate\n // short-lived process and a parallel fan-out (`for n in …; do mu\n // agent spawn … & done`) opens the same DB from N processes at\n // once — without this, the losers of a write-lock race die with\n // 'database is locked' and roll back their agent. WAL handles\n // concurrent readers; busy_timeout handles concurrent writers.\n // busy_timeout only covers a lock taken at BEGIN, so every write\n // transaction runs as `db.transaction(fn).immediate()` (or `BEGIN\n // IMMEDIATE`). A deferred one that reads first and then writes gets\n // SQLITE_BUSY_SNAPSHOT at once if another process committed in\n // between, and busy_timeout does not retry that.\n db.pragma(\"busy_timeout = 5000\");\n // The capture triggers need unixepoch('subsec') (SQLite 3.42): below\n // it every HLC would be zero-time. Refuse before touching the file.\n const sqliteVersion = (db.prepare(\"SELECT sqlite_version() AS v\").get() as { v: string }).v;\n if (sqliteTooOld(sqliteVersion)) {\n closeQuietly(db);\n throw new SqliteTooOldError(sqliteVersion);\n }\n // Detect schema version BEFORE any DDL so a real v<12 DB is not\n // silently stamped by the CREATE-IF-NOT-EXISTS in the schema, and\n // before `journal_mode = WAL`, which rewrites the file header:\n // a refused DB must be left byte-for-byte untouched.\n // One read transaction: a process creating this DB can commit\n // between two bare reads, and \"no schema_version table, then a\n // workstreams table\" read as a pre-versioning v1 DB.\n const { version: detectedVersion, capture: detectedCapture } = db.transaction(() => ({\n version: detectExistingSchemaVersion(db),\n capture: storedCaptureVersion(db),\n }))();\n try {\n refuseUnusableStamps(detectedVersion, detectedCapture);\n setWalMode(db);\n db.pragma(\"foreign_keys = ON\");\n // Skip the DDL write transaction when the DB already matches this\n // build (schema, capture stamp and stored triggers): the upgrade\n // takes the write lock and rewrites the views, which bumps the\n // schema cookie on every open, so every `mu` call, reads included,\n // queued behind any writer and forced every other connection to\n // re-parse the schema (f_opendb_schema_write).\n if (\n detectedVersion !== CURRENT_SCHEMA_VERSION ||\n detectedCapture !== CAPTURE_VERSION ||\n !schemaIsCurrent(db)\n ) {\n upgradeSchema(db);\n }\n seedMachineIdentity(db);\n } catch (err) {\n closeQuietly(db);\n throw err;\n }\n } else {\n db.pragma(\"foreign_keys = ON\");\n }\n\n return db;\n}\n\nfunction closeQuietly(db: Db): void {\n try {\n db.close();\n } catch {\n // best effort\n }\n}\n\n/**\n * Hard guard: refuse to open\n * the user's REAL default mu.db when running under vitest. Tests\n * MUST point at a per-test temp DB (via MU_DB_PATH or the explicit\n * `{ path }` option). A test that forgets to override either one\n * silently mutated the dev box's live state — we observed a stray\n * 'demo' workstream row replicated from test/tui-acceptance.integration.test.ts\n * into ~/.local/state/mu/mu.db (now ~/.local/state/mu-next/mu.db). The guard throws a useful diagnostic\n * the moment the offending openDb() call is made; the failing test's\n * stack trace then names the leak source directly.\n *\n * Test mode = `process.env.VITEST` is defined OR `NODE_ENV === \"test\"`.\n * vitest sets VITEST=\"true\" in every fork; the NODE_ENV branch is for\n * other runners that may invoke openDb during tests.\n *\n * The user's REAL DB path is computed from HOME / XDG_STATE_HOME\n * directly (NOT from defaultDbPath() — which would honour MU_DB_PATH\n * and produce the temp path the test set, defeating the check).\n * MU_STATE_DIR is deliberately not consulted: test/_setup.ts deletes\n * the user's MU_* vars in every fork, so any MU_STATE_DIR seen here was\n * set by a test to a temp dir (test/disk-recon.test.ts opens\n * <MU_STATE_DIR>/mu.db), and guarding it would refuse that temp DB.\n * Production code paths (the `mu` CLI binary) never set VITEST, so\n * the guard is a complete no-op outside the test runner.\n */\nfunction refuseUserDbDuringTests(path: string): void {\n const inTest = process.env.VITEST !== undefined || process.env.NODE_ENV === \"test\";\n if (!inTest) return;\n const home = process.env.HOME ?? homedir();\n // The 4.x default (<state home>/mu-next) and 3.x's: a test must reach neither.\n const realDbs = [\"mu-next\", \"mu\"].map((dir) => resolve(join(xdgStateHome(home), dir, \"mu.db\")));\n const realDb = realDbs.find((p) => p === resolve(path));\n if (realDb !== undefined) {\n throw new Error(say(\"db.test_real_db\", realDb));\n }\n}\n\n// ─── Resolve helpers (operator-facing name -> surrogate id) ───────────\n//\n// docs/architecture/sdk.md § Surrogate-PK and SDK-boundary discipline:\n//\n// PUBLIC SDK functions take operator-facing names (workstream + local\n// id + agent name). Internal helpers take surrogate ids. Resolution\n// happens at the public-function entry, exactly once.\n//\n// `resolveWorkstreamId` throws a typed error from this leaf module —\n// `WorkstreamNotFoundError` is defined here, so there is no cycle.\n\nexport class WorkstreamNotFoundError extends Error {\n override readonly name: string = \"WorkstreamNotFoundError\";\n /** `near` are live workstreams with a similar name; `init` says `mu workstream init` is the fix\n * (the name is valid and not reserved). Both only shape the message. */\n constructor(\n public readonly workstream: string,\n hints: { near?: readonly string[]; init?: boolean } = {},\n ) {\n super(say(\"workstream.not_found\", workstream, hints.near, hints.init));\n }\n}\n\n/** A verb named a **torn down** workstream (`workstreams.torn_down_at`\n * set). It is a kind of not-found (exit 3), but says why and how to get\n * the name back: `workstream init` previews, then `--if <rev>` reuses it. */\nexport class WorkstreamTornDownError extends WorkstreamNotFoundError {\n override readonly name: string = \"WorkstreamTornDownError\";\n constructor(\n workstream: string,\n public readonly tornDownAt: string,\n ) {\n super(workstream);\n this.message = say(\"workstream.torn_down\", workstream, tornDownAt);\n }\n}\n\n/** When `workstream` is torn down: its `torn_down_at`; else null (live or\n * unknown). */\nexport function tornDownAtOf(db: Db, workstream: string): string | null {\n const row = db.prepare(\"SELECT torn_down_at FROM workstreams WHERE name = ?\").get(workstream) as\n | { torn_down_at: string | null }\n | undefined;\n return row?.torn_down_at ?? null;\n}\n\n/** Resolve a workstream name to its INTEGER surrogate id. Throws\n * WorkstreamNotFoundError on miss, and WorkstreamTornDownError when the\n * row exists torn down (ingest, which must still find it, queries\n * `workstreams` directly). Pure: no auto-create — callers\n * that want the auto-create-or-resolve semantics use\n * `ensureWorkstream` from src/workstream.ts (which returns void;\n * follow up with `resolveWorkstreamId` if the id is needed).\n */\nexport function resolveWorkstreamId(db: Db, workstream: string): number {\n const row = db\n .prepare(\"SELECT id, torn_down_at FROM workstreams WHERE name = ?\")\n .get(workstream) as { id: number; torn_down_at: string | null } | undefined;\n if (!row) throw new WorkstreamNotFoundError(workstream);\n if (row.torn_down_at !== null) throw new WorkstreamTornDownError(workstream, row.torn_down_at);\n return row.id;\n}\n\n/** Resolve a workstream name to its id, returning null on miss instead\n * of throwing. A torn-down workstream is a miss too. Tolerant on purpose:\n * agent and reaper paths use it, and a peer's teardown can reach a machine\n * that still has agent rows (and live panes) in that workstream. */\nexport function tryResolveWorkstreamId(db: Db, workstream: string): number | null {\n const row = db\n .prepare(\"SELECT id FROM workstreams WHERE name = ? AND torn_down_at IS NULL\")\n .get(workstream) as { id: number } | undefined;\n return row ? row.id : null;\n}\n\n/** Like `tryResolveWorkstreamId` for user-facing task reads: null when the\n * name is unknown (callers decide), but a torn-down workstream THROWS\n * `WorkstreamTornDownError`, so every verb says why instead of \"no tasks\". */\nexport function tryResolveLiveWorkstreamId(db: Db, workstream: string): number | null {\n const row = db\n .prepare(\"SELECT id, torn_down_at FROM workstreams WHERE name = ?\")\n .get(workstream) as { id: number; torn_down_at: string | null } | undefined;\n if (!row) return null;\n if (row.torn_down_at !== null) throw new WorkstreamTornDownError(workstream, row.torn_down_at);\n return row.id;\n}\n\n/**\n * Thrown by openDb when the on-disk DB is older than the current\n * schema. There is no in-place migration ladder; the old DB is left\n * untouched. Maps to exit code 4 (conflict) in cli.ts handle().\n */\nexport class SchemaTooOldError extends Error {\n override readonly name = \"SchemaTooOldError\";\n constructor(\n public readonly detectedVersion: number,\n public readonly requiredVersion: number,\n ) {\n super(say(\"db.schema_old\", detectedVersion, requiredVersion));\n }\n}\n\n/**\n * Thrown by openDb when the on-disk DB was written by a NEWER mu.\n * The DB is left untouched. Maps to exit code 4 (conflict).\n */\nexport class SchemaTooNewError extends Error {\n override readonly name = \"SchemaTooNewError\";\n constructor(\n public readonly detectedVersion: number,\n public readonly supportedVersion: number,\n /** Which stamp was newer: the table schema, or the capture triggers. */\n public readonly stamp: \"schema\" | \"capture\" = \"schema\",\n ) {\n super(say(\"db.schema_new\", detectedVersion, supportedVersion, stamp));\n }\n}\n\n/**\n * Thrown by openDb when the linked SQLite is older than 3.42: the capture\n * triggers mint HLCs with `unixepoch('subsec')`, which older versions\n * return NULL for. Maps to exit code 4 (conflict). Nothing was touched.\n */\nexport class SqliteTooOldError extends Error {\n override readonly name = \"SqliteTooOldError\";\n constructor(public readonly sqliteVersion: string) {\n super(say(\"db.sqlite_old\", sqliteVersion));\n }\n}\n\n/** How long openDb retries the switch to WAL while another process holds the lock. */\nconst WAL_SWITCH_RETRY_MS = 5000;\n\n/**\n * `journal_mode = WAL`, retried on SQLITE_BUSY. On a fresh file the\n * switch needs an exclusive lock, and SQLite can return SQLITE_BUSY\n * for it without calling the busy handler, so busy_timeout does not\n * cover it: N processes opening a new DB at once lost one with\n * \"database is locked\". Once the file is WAL the switch is a no-op.\n */\nfunction setWalMode(db: Db): void {\n const deadline = Date.now() + WAL_SWITCH_RETRY_MS;\n const pause = new Int32Array(new SharedArrayBuffer(4));\n for (;;) {\n try {\n db.pragma(\"journal_mode = WAL\");\n return;\n } catch (err) {\n const code = (err as { code?: unknown }).code;\n const busy = typeof code === \"string\" && code.startsWith(\"SQLITE_BUSY\");\n if (!busy || Date.now() >= deadline) throw err;\n Atomics.wait(pause, 0, 0, 10 + Math.floor(Math.random() * 20));\n }\n }\n}\n\n/**\n * Sniff an existing DB's schema version BEFORE applySchema runs, so we\n * can distinguish:\n * - Brand-new DB: no tables at all -> returns null (fresh, will be\n * stamped to CURRENT_SCHEMA_VERSION by applySchema).\n * - Pre-versioning DB (had the original tables before schema_version existed):\n * workstreams exists, schema_version doesn't -> returns 1.\n * - Already-versioned DB: schema_version row present -> returns its\n * value.\n */\nfunction detectExistingSchemaVersion(db: Db): number | null {\n const hasVersionTable = db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='schema_version'\")\n .get() as { name: string } | undefined;\n if (hasVersionTable) {\n const row = db.prepare(\"SELECT version FROM schema_version WHERE id = 1\").get() as\n | { version: number }\n | undefined;\n return row?.version ?? null;\n }\n // No schema_version table. Check whether any of the original\n // tables exist; if so this is a pre-versioning DB.\n const hasWorkstreams = db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='workstreams'\")\n .get() as { name: string } | undefined;\n if (hasWorkstreams) return 1;\n return null;\n}\n\n/** Seed the singleton machine_identity row (id=1) on first open.\n * No-op once a row exists. The machine_id it writes is the identity\n * every op is stamped with (`ops.machine_id`) and the name of this\n * machine's segment. */\nfunction seedMachineIdentity(db: Db): void {\n const row = db.prepare(\"SELECT COUNT(*) AS count FROM machine_identity\").get() as {\n count: number;\n };\n if (row.count !== 0) return;\n db.prepare(\n `INSERT OR IGNORE INTO machine_identity (id, machine_id, hostname, created_at)\n VALUES (1, ?, ?, ?)`,\n ).run(randomUUID(), hostname(), new Date().toISOString());\n}\n\n/** Refuse a file this build must not touch, from the stamps read before\n * any write: a newer schema or capture revision (a later mu wrote it) or\n * a schema older than MIN_ACCEPTED_SCHEMA_VERSION. */\nfunction refuseUnusableStamps(version: number | null, capture: number | null): void {\n if (version !== null && version > CURRENT_SCHEMA_VERSION) {\n // A newer mu wrote this DB. Its writes would fail here in confusing\n // ways (unknown columns, constraints this build does not know).\n throw new SchemaTooNewError(version, CURRENT_SCHEMA_VERSION);\n }\n if (capture !== null && capture > CAPTURE_VERSION) {\n // Same for the stored triggers: a newer mu's capture rules are not\n // ours to replace or run. (An OLDER stamp is upgraded in place.)\n throw new SchemaTooNewError(capture, CAPTURE_VERSION, \"capture\");\n }\n if (version !== null && version < MIN_ACCEPTED_SCHEMA_VERSION) {\n // Loud-fail: leave the old file untouched; the message says how to preserve it.\n throw new SchemaTooOldError(version, MIN_ACCEPTED_SCHEMA_VERSION);\n }\n}\n\n/**\n * Bring the file to this build in ONE transaction: the schema DDL, the\n * added columns, the schema stamp, the machine identity, the capture\n * triggers and the capture stamp commit together or not at all. Another\n * connection therefore never sees new columns under old capture rules,\n * and a failure anywhere leaves the old columns, triggers and stamps as\n * they were.\n *\n * Idempotent: tables use CREATE TABLE IF NOT EXISTS; views are dropped and\n * recreated so the latest definition wins; a column a v13 DB lacks is\n * added by ALTER (ADDED_COLUMNS). `BEGIN IMMEDIATE` takes the write lock\n * first (paired with busy_timeout in openDb), so two processes opening\n * one fresh DB cannot interleave a DROP VIEW between the other's DROP and\n * CREATE. Both stamps are re-read under that lock: a concurrent opener\n * that already upgraded makes this a no-op, and a newer mu that stamped\n * the file meanwhile is refused with the file untouched.\n *\n * Exported for the upgrade tests, which wrap `db` to inject a failure.\n */\nexport function upgradeSchema(db: Db): void {\n db.exec(\"BEGIN IMMEDIATE\");\n try {\n const version = detectExistingSchemaVersion(db);\n refuseUnusableStamps(version, storedCaptureVersion(db));\n if (version !== CURRENT_SCHEMA_VERSION || !schemaIsCurrent(db)) applySchemaDdl(db);\n // Stamp after the DDL, in the same transaction. A fresh DB gets its\n // row here; an older capture stamp is raised to this build.\n db.prepare(\n `INSERT INTO schema_version (id, version) VALUES (1, ?)\n ON CONFLICT (id) DO UPDATE SET version = excluded.version`,\n ).run(CURRENT_SCHEMA_VERSION);\n // The triggers mint HLCs from this row.\n seedMachineIdentity(db);\n installCaptureLocked(db);\n db.exec(\"COMMIT\");\n } catch (err) {\n try {\n db.exec(\"ROLLBACK\");\n } catch {}\n if (err instanceof CaptureTooNewError) {\n throw new SchemaTooNewError(err.stored, CAPTURE_VERSION, \"capture\");\n }\n throw err;\n }\n}\n\n/** A v13 file from before host profiles stopped requiring a repo: `repo` is NOT NULL. */\nfunction hostProfilesRepoRequired(db: Db): boolean {\n const row = db\n .prepare(\"SELECT \\\"notnull\\\" AS nn FROM pragma_table_info('host_profiles') WHERE name = 'repo'\")\n .get() as { nn: number } | undefined;\n return row?.nn === 1;\n}\n\n/** The DDL half of upgradeSchema; the caller owns the transaction. */\nfunction applySchemaDdl(db: Db): void {\n // No migration (the profile names a machine now): an older file's profiles\n // are dropped, and its recovery triggers replaced by the _v2 ones below.\n if (hostProfilesRepoRequired(db)) db.exec(\"DROP TABLE host_profiles\");\n for (const t of LEGACY_RECOVERY_TRIGGERS) db.exec(`DROP TRIGGER IF EXISTS ${t}`);\n db.exec(CURRENT_SCHEMA);\n // Columns a v13 DB written before they existed still lacks.\n for (const [table, column, ddl] of ADDED_COLUMNS) {\n if (!hasColumn(db, table, column)) db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${ddl}`);\n }\n // Seed the legal (status, substate) pairs from code. INSERT OR\n // IGNORE keeps it idempotent; the table is machine-local and never\n // synced, so every machine derives it from the same constant.\n const seed = db.prepare(\n \"INSERT OR IGNORE INTO task_substates (status, substate, is_default) VALUES (?, ?, ?)\",\n );\n for (const [status, substate, isDefault] of TASK_SUBSTATE_ROWS) {\n seed.run(status, substate, isDefault);\n }\n}\n\n/** Names CURRENT_SCHEMA creates with IF NOT EXISTS, and the exact SQL\n * SQLite stores for each view (the CREATE statement minus its `;`). */\ninterface ExpectedObjects {\n tables: string[];\n triggers: string[];\n indexes: string[];\n views: Map<string, string>;\n}\nlet expectedCache: ExpectedObjects | undefined;\nfunction expectedObjects(): ExpectedObjects {\n if (expectedCache !== undefined) return expectedCache;\n const names = (re: RegExp): string[] =>\n [...CURRENT_SCHEMA.matchAll(re)].map((m) => m[1]).filter((n) => n !== undefined);\n const views = new Map<string, string>();\n for (const sql of [READY_VIEW_SQL, BLOCKED_VIEW_SQL, BLOCKERS_VIEW_SQL, GOALS_VIEW_SQL]) {\n const m = /CREATE VIEW (\\w+)[^;]*/.exec(sql);\n if (m?.[1] !== undefined) views.set(m[1], m[0]);\n }\n expectedCache = {\n tables: names(/CREATE TABLE IF NOT EXISTS (\\w+)/g),\n triggers: names(/CREATE TRIGGER IF NOT EXISTS (\\w+)/g),\n indexes: names(/CREATE (?:UNIQUE )?INDEX IF NOT EXISTS (\\w+)/g),\n views,\n };\n return expectedCache;\n}\n\n/** The task kinds (`tasks.kind`): `work` is the default, `delegate` a\n * task-backed delegate call, `human` one only a person can close. Synced\n * per field; a value this build does not know is dropped by the fold, so\n * a newer peer's kind never trips the CHECK during ingest. */\nexport const TASK_KINDS = [\"work\", \"delegate\", \"human\"] as const;\nexport type TaskKind = (typeof TASK_KINDS)[number];\n\nconst sqlList = (xs: readonly string[]): string => xs.map((x) => `'${x}'`).join(\", \");\nconst TASK_KIND_DDL = `TEXT NOT NULL DEFAULT 'work' CHECK (kind IN (${sqlList(TASK_KINDS)}))`;\n\n/** The states of a delegate call (`delegate_calls.state`). */\nexport const DELEGATE_CALL_STATES = [\n \"queued\",\n \"starting\",\n \"running\",\n \"recording\",\n \"done\",\n \"failed\",\n \"refused\",\n \"cancelled\",\n] as const;\n\n/** The states of a stall action (`wait_action_receipts.state`). */\nexport const WAIT_ACTION_STATES = [\n \"reserved\",\n \"sending\",\n \"sent\",\n \"unknown\",\n \"refused\",\n \"released\",\n] as const;\nexport type WaitActionState = (typeof WAIT_ACTION_STATES)[number];\n\n/** The stall actions a wait may take (`wait_action_receipts.action`). */\nexport const WAIT_ACTIONS = [\"steer\", \"release\"] as const;\nexport type WaitAction = (typeof WAIT_ACTIONS)[number];\n\n/** The states of a task-bound spawn attempt (`spawn_receipts.state`). */\nexport const SPAWN_RECEIPT_STATES = [\n \"reserved\",\n \"pane\",\n \"claimed\",\n \"sending\",\n \"sent\",\n \"unknown\",\n \"failed\",\n] as const;\nexport type SpawnReceiptState = (typeof SPAWN_RECEIPT_STATES)[number];\n\n/**\n * Columns added to a table after a v13 DB may already exist, as\n * `[table, column, DDL]`. `CREATE TABLE IF NOT EXISTS` leaves an existing\n * table alone, so applySchema adds each missing one with `ALTER TABLE ADD\n * COLUMN` (idempotent, inside the schema transaction), and schemaIsCurrent\n * reports a DB without one as not current. The DDL must stay a plain\n * nullable/defaulted column: SQLite adds nothing else in place.\n */\nconst ADDED_COLUMNS: readonly (readonly [table: string, column: string, ddl: string])[] = [\n [\"agents\", \"command\", \"TEXT\"],\n [\"agents\", \"command_source\", \"TEXT\"],\n // Schema 13: the loop's storage. kind/wave are portable (synced);\n // spawner/host/collected_head are machine-local agent metadata.\n [\"tasks\", \"kind\", TASK_KIND_DDL],\n [\"tasks\", \"wave\", \"TEXT\"],\n [\"agents\", \"spawner\", \"TEXT\"],\n [\"agents\", \"host\", \"TEXT\"],\n [\"agents\", \"collected_head\", \"TEXT\"],\n // The remote command gate's spawn-unique token (machine-local): its marker and result key.\n [\"agents\", \"gate_token\", \"TEXT\"],\n // A remote worktree's repo, chosen per spawn (a host profile names a machine).\n [\"agents\", \"repo\", \"TEXT\"],\n [\"wait_registrations\", \"baselines_json\", \"TEXT NOT NULL DEFAULT '{}'\"],\n [\"task_auto\", \"enabled\", \"INTEGER NOT NULL DEFAULT 1 CHECK (enabled IN (0, 1))\"],\n ...[\"request\", \"verdict\", \"agent\"].map((c) => [\"delegate_calls\", c, \"TEXT\"] as const),\n // The template's process group, recorded before it runs (hosts.ts).\n [\"host_channels\", \"pgid\", \"INTEGER\"],\n [\"host_channels\", \"pgid_start\", \"TEXT\"],\n];\n\nfunction hasColumn(db: Db, table: string, column: string): boolean {\n return (\n db.prepare(\"SELECT 1 AS x FROM pragma_table_info(?) WHERE name = ?\").get(table, column) !==\n undefined\n );\n}\n\n/** True when applySchema would change nothing: every table, index and\n * seeded substate row exists, and every view's stored SQL equals this\n * build's definition. Reads only, so openDb on an up-to-date DB takes\n * no write lock and leaves PRAGMA schema_version alone. */\nfunction schemaIsCurrent(db: Db): boolean {\n const rows = db.prepare(\"SELECT type, name, sql FROM sqlite_master\").all() as {\n type: string;\n name: string;\n sql: string | null;\n }[];\n const have = new Map(rows.map((r) => [`${r.type}:${r.name}`, r.sql]));\n const expected = expectedObjects();\n if (expected.tables.some((t) => !have.has(`table:${t}`))) return false;\n if (expected.triggers.some((t) => !have.has(`trigger:${t}`))) return false;\n if (ADDED_COLUMNS.some(([t, c]) => !hasColumn(db, t, c))) return false;\n if (LEGACY_RECOVERY_TRIGGERS.some((t) => have.has(`trigger:${t}`))) return false;\n if (hostProfilesRepoRequired(db)) return false;\n if (expected.indexes.some((i) => !have.has(`index:${i}`))) return false;\n for (const [name, sql] of expected.views) {\n if (have.get(`view:${name}`) !== sql) return false;\n }\n const pairs = new Set(\n (\n db.prepare(\"SELECT status, substate FROM task_substates\").all() as {\n status: string;\n substate: string;\n }[]\n ).map((r) => `${r.status}/${r.substate}`),\n );\n return TASK_SUBSTATE_ROWS.every(([status, substate]) => pairs.has(`${status}/${substate}`));\n}\n\n/** The schema version a fresh DB starts at. v12 adds the kernel columns\n * (torn_down_at, cwd, base, scored, dispatch_host, kind), task_auto and\n * the blockers view on top of v11's task substates; v13 adds the loop's\n * storage (tasks.kind/wave, agents.spawner/host/collected_head and four\n * machine-local tables). See CHANGELOG.md. */\nexport const CURRENT_SCHEMA_VERSION = 13;\n\n/** The lowest schema version `openDb` will accept. There is no ladder:\n * anything older throws `SchemaTooOldError` (exit 4) and is left\n * untouched on disk. */\nconst MIN_ACCEPTED_SCHEMA_VERSION = 13;\n\n/** The note kinds (`task_notes.kind`). Set once at INSERT, never changed:\n * a local UPDATE of it raises, and a peer's update cannot match a row. */\nexport const NOTE_KINDS = [\"brief\", \"report\", \"verdict\", \"close\", \"note\"] as const;\nexport type NoteKind = (typeof NOTE_KINDS)[number];\n\n/** Impact and effort a task gets when its creator gave neither (and the\n * SQL DEFAULTs of `tasks.impact` / `tasks.effort_days`). Such a task is\n * unscored (`tasks.scored = 0`). */\nexport const DEFAULT_IMPACT = 50;\nexport const DEFAULT_EFFORT_DAYS = 1;\n\n/** Tables a healthy DB must contain. Single source of truth so\n * `mu doctor` and any other consumer don't drift. Adding a new table\n * = one new entry here AND a CREATE TABLE in CURRENT_SCHEMA, plus a\n * CURRENT_SCHEMA_VERSION bump (sync_fingerprints went in without one:\n * additive, and an older mu ignores it). Sorted; exactly 26 entries. */\nexport const EXPECTED_TABLES: readonly string[] = [\n \"agent_settles\",\n \"agents\",\n \"delegate_calls\",\n \"host_channels\",\n \"host_profiles\",\n \"human_needs\",\n \"machine_identity\",\n \"op_ctx\",\n \"op_dying\",\n \"ops\",\n \"remote_recovery\",\n \"schema_version\",\n \"spawn_receipts\",\n \"sync_fingerprints\",\n \"sync_peers\",\n \"task_auto\",\n \"task_edges\",\n \"task_notes\",\n \"task_substates\",\n \"tasks\",\n \"wait_action_receipts\",\n \"wait_cursors\",\n \"wait_registrations\",\n \"wait_resumes\",\n \"workstreams\",\n \"worktrees\",\n];\n\n// ─── Syncability — which state crosses machines ───────────────────────\n//\n// Whether an op syncs is a STATIC function of its entity, so it lives\n// here as a constant rather than as a `local` column on `ops`. A\n// per-row decision is a per-row opportunity to get it wrong, and it\n// would cost a column plus a branch at every write site. Downstream\n// sync code READS these; it does not re-decide.\n//\n// Vocabulary (docs/VOCABULARY.md § portable): **portable** tables are\n// syncable across machines; **machine-local** tables never leave the\n// box. Machine-local ops are still RECORDED — `mu log` and the TUI\n// Recent card still show agent spawn/close — they simply never ship.\n// \"Not synced\" is not \"not logged\".\n\n/** Op entities that cross machines. Everything else is machine-local.\n * Readonly tuple (not `string[]`) so `SyncedEntity` is a real union\n * and downstream code gets compile-time checking, not raw strings. */\nexport const SYNCED_ENTITIES = [\"workstream\", \"task\", \"edge\", \"note\", \"message\"] as const;\n\n/** One of the op entities that sync. Derived from the tuple, so\n * adding an entity is a one-line change with no type to keep in step. */\nexport type SyncedEntity = (typeof SYNCED_ENTITIES)[number];\n\n/** Op entities this build KNOWS are machine-local: their payloads name\n * a pane id or an absolute path, so a peer sending one is a real bug\n * and `applyOp` rejects it loudly.\n *\n * WHY THIS LIST EXISTS SEPARATELY FROM \"not in SYNCED_ENTITIES\"\n * ------------------------------------------------------------\n * \"Unknown\" and \"known-local\" are different failures and were\n * conflated, which wedged a real fleet. A peer running a LATER (or\n * earlier) mu wrote `entity:\"marker\"` ops — legal on the writer, whose\n * SYNCED_ENTITIES included it. The reader treated every non-synced\n * entity as a bad peer, so `ingestSegment` recorded a defect and\n * stopped at that line FOREVER: 87% of a 20,305-line segment never\n * applied, and `mu sync --repair` (which only resets the watermark)\n * marched straight back into the same wall.\n *\n * So the rule is asymmetric on purpose: an entity we know must never\n * travel is a defect; an entity we simply do not recognise is tolerated\n * forward-compatibly — recorded in `ops`, projected nowhere, exactly\n * like 'message'. Reader vocabulary may lag writer vocabulary; that is\n * a fact of a mixed fleet, not a corruption. */\nexport const MACHINE_LOCAL_ENTITIES = [\"agent\", \"workspace\", \"event\", \"broadcast\"] as const;\n\nexport type MachineLocalEntity = (typeof MACHINE_LOCAL_ENTITIES)[number];\n\n/** **Portable** tables: their rows mean the same thing on any machine,\n * so their ops ship. Mirrors docs/VOCABULARY.md § portable exactly. */\nexport const PORTABLE_TABLES = [\"task_edges\", \"task_notes\", \"tasks\", \"workstreams\"] as const;\n\nexport type PortableTable = (typeof PORTABLE_TABLES)[number];\n\n/** **Machine-local** tables. Never bulk-copied to a peer, because a\n * row's meaning does not survive the trip:\n *\n * agents holds `pane_id` ('%17') — meaningless elsewhere.\n * worktrees holds absolute paths — /home/... vs /Users/...\n * on a mixed macOS/Linux fleet.\n * machine_identity IS the per-machine identity.\n * op_ctx the capture context row; defaults at rest.\n * op_dying capture's delete-key stash; empty at rest.\n * schema_version local bookkeeping.\n * sync_peers local bookkeeping (per-peer watermarks).\n * sync_fingerprints local cache of what the last clean ingest saw.\n * task_substates seeded identically on every machine from\n * TASK_SUBSTATE_ROWS; code, not data.\n * task_auto per-task auto-dispatch state (cli, runs, last\n * spawn): about THIS machine's agents.\n * delegate_calls one row per task-backed delegate call: the caller,\n * call_id and pane-side state of THIS machine.\n * wait_cursors per caller and ref, the last wait result consumed.\n * wait_registrations per caller, the refs a wait still owes it, and\n * whether one is in flight (generation CAS), plus the\n * unconsumed run baselines of its agent refs.\n human_needs which caller recorded a `human` task (`mu human-needed`).\n Rebuild cannot restore it (UNREBUILDABLE_TABLES).\n * agent_settles settled runs already applied (settle replay).\n * host_profiles ssh-free command templates per remote host.\n * host_channels the connection slots a host's `max_sessions` counts:\n * one row per live holder (invocation pid or agent pane).\n * wait_resumes one row per `mu wait` result that left something owed:\n * the full condition set behind `mu wait --resume <id>`.\n * wait_action_receipts one row per stall action a wait took on a task\n * (task id, owner registry id, ctl incarnation, action):\n * the exclusion that keeps a nudge to ONE and the record\n * of a release. No FK: it must outlive the task and agent.\n * spawn_receipts one row per task-bound spawn attempt: the replay and\n * crash-recovery journal (reservation, pane identity,\n * claim, send state). No FK to `agents`: it must\n * outlive the agent it names.\n * remote_recovery a deleted remote worker row's worktree, written by\n * triggers (src/db-recovery.ts). No FK; rebuild loses it.\n * ops see below — the carrier, not cargo.\n *\n * `ops` is listed here deliberately rather than omitted. It is not\n * **portable** in the copy-the-table sense: the table is never\n * wholesale-copied. Individual op ROWS ship, one at a time, filtered\n * by SYNCED_ENTITIES and carried by per-machine **segments** — and\n * `seq` is a local-only append cursor that means nothing on a peer.\n * So for the only question this list answers — \"is this table's\n * content copied across machines?\" — the answer for `ops` is no.\n *\n * Consequence that falls out with no special case: `tasks.owner_id`\n * is an FK into `agents`, and `agents` is machine-local. Therefore\n * OWNERSHIP DOES NOT SYNC. The deleted db-sync.ts reached the same\n * conclusion via an `includeOwners` flag; here it is structural. */\nexport const MACHINE_LOCAL_TABLES = [\n \"agent_settles\",\n \"agents\",\n \"delegate_calls\",\n \"host_channels\",\n \"host_profiles\",\n \"human_needs\",\n \"machine_identity\",\n \"op_ctx\",\n \"op_dying\",\n \"ops\",\n \"remote_recovery\",\n \"schema_version\",\n \"spawn_receipts\",\n \"sync_fingerprints\",\n \"sync_peers\",\n \"task_auto\",\n \"task_substates\",\n \"wait_action_receipts\",\n \"wait_cursors\",\n \"wait_registrations\",\n \"wait_resumes\",\n \"worktrees\",\n] as const;\n\nexport type MachineLocalTable = (typeof MACHINE_LOCAL_TABLES)[number];\n\n// ─── View DDL — single source of truth ────────────────────────────────\n//\n// The three views (ready, blocked, goals) get DROPped + CREATEd by\n// applySchema whenever openDb finds them missing or different from\n// these definitions (schemaIsCurrent). Each constant is self-contained:\n// DROP IF EXISTS + CREATE. Running DROP twice in a row is harmless,\n// so callers that already DROP up-front can still re-execute these\n// without churn.\n//\n// Exported as named constants so consumers can reference the canonical\n// shape (e.g. one-shot migration scripts under scripts/) without\n// duplicating SQL.\n\nexport const READY_VIEW_SQL = `\nDROP VIEW IF EXISTS ready;\nCREATE VIEW ready AS\n SELECT t.*\n FROM tasks t\n JOIN workstreams w ON w.id = t.workstream_id AND w.torn_down_at IS NULL\n WHERE t.status = 'OPEN'\n AND t.substate NOT IN ('parked', 'triage')\n AND NOT EXISTS (\n SELECT 1\n FROM task_edges e\n JOIN tasks b ON e.from_task_id = b.id\n WHERE e.to_task_id = t.id\n AND b.status <> 'CLOSED'\n );\n`;\n\nexport const BLOCKED_VIEW_SQL = `\nDROP VIEW IF EXISTS blocked;\nCREATE VIEW blocked AS\n SELECT t.*\n FROM tasks t\n JOIN workstreams w ON w.id = t.workstream_id AND w.torn_down_at IS NULL\n WHERE t.status = 'OPEN'\n AND EXISTS (\n SELECT 1\n FROM task_edges e\n JOIN tasks b ON e.from_task_id = b.id\n WHERE e.to_task_id = t.id\n AND b.status <> 'CLOSED'\n );\n`;\n\n// The direct OPEN blockers of each task: one row per (task, blocker) edge\n// whose blocker is not CLOSED. `ready` is the tasks with no row here;\n// `blocked` the OPEN tasks with one.\nexport const BLOCKERS_VIEW_SQL = `\nDROP VIEW IF EXISTS blockers;\nCREATE VIEW blockers AS\n SELECT e.to_task_id AS task_id,\n t.local_id AS task_local_id,\n b.id AS blocker_id,\n b.local_id AS blocker_local_id,\n b.status AS blocker_status\n FROM task_edges e\n JOIN tasks b ON b.id = e.from_task_id\n JOIN tasks t ON t.id = e.to_task_id\n JOIN workstreams w ON w.id = t.workstream_id AND w.torn_down_at IS NULL\n WHERE b.status <> 'CLOSED';\n`;\n\n// A goal is an active endpoint of the DAG — a task with no dependents\n// that we're still working toward. CLOSED is excluded: a finished\n// leaf is not an active goal. Parked tasks STAY goals: tracks are\n// built from goals, and a parked track is still a track.\nexport const GOALS_VIEW_SQL = `\nDROP VIEW IF EXISTS goals;\nCREATE VIEW goals AS\n SELECT t.*\n FROM tasks t\n JOIN workstreams w ON w.id = t.workstream_id AND w.torn_down_at IS NULL\n WHERE t.status <> 'CLOSED'\n AND NOT EXISTS (\n SELECT 1 FROM task_edges WHERE from_task_id = t.id\n );\n`;\n\n// ─── SCHEMA (v13) ───────────────────────────────────────────────────────\n//\n// Per docs/architecture/sdk.md § Surrogate-PK and SDK-boundary discipline.\n// Every entity table has:\n// - INTEGER PRIMARY KEY AUTOINCREMENT (surrogate identity)\n// - <scope>_id INTEGER NOT NULL REFERENCES <parent>(id) ON DELETE CASCADE\n// - <name> TEXT NOT NULL (operator-facing, immutable once written)\n// - UNIQUE (<scope>_id, <name>)\n//\n// Foreign keys are INTEGER. The natural keys (`workstreams.name`,\n// `tasks.local_id`) are immutable: the capture KEY_COLUMNS guard refuses\n// an UPDATE of them (src/capture.ts), because ops address rows by them. `ops` is the\n// documented exception: it has NO foreign keys at all and addresses\n// rows by their NATURAL key, because ops outlive the rows (and the\n// workstreams) they record.\n\nconst CURRENT_SCHEMA = `\n-- ─── Schema versioning ────────────────────────────────────────────────\n--\n-- Single-row table tracking which schema version this DB is at. Migrations\n-- read and update this; the row is INSERT-OR-IGNOREd by applySchema with\n-- the current version on a fresh DB.\n--\n-- capture_version stamps the revision of the capture triggers stored in\n-- this file (CAPTURE_VERSION, src/capture.ts). It is separate from\n-- \"version\" on purpose: \"version\" means tables/columns are\n-- incompatible, and openDb refuses an older DB outright, while an older\n-- capture revision is upgraded in place (installCapture replaces every\n-- trigger and the stamp in one transaction). A DB created before the\n-- column existed gets it from installCapture's ALTER (DEFAULT 0).\nCREATE TABLE IF NOT EXISTS schema_version (\n id INTEGER PRIMARY KEY CHECK (id = 1),\n version INTEGER NOT NULL,\n capture_version INTEGER NOT NULL DEFAULT 0\n);\n\n-- op_ctx: the op context the capture triggers read (src/capture.ts, the\n-- header; src/op-context.ts). One row (seeded by installCapture), written\n-- only by the context wrappers inside a transaction they own, so at rest\n-- it always holds the defaults. now_ms is the trigger scratchpad for one\n-- HLC tick.\nCREATE TABLE IF NOT EXISTS op_ctx (\n id INTEGER PRIMARY KEY CHECK (id = 1),\n group_id TEXT,\n actor TEXT,\n intent TEXT,\n applying INTEGER NOT NULL DEFAULT 0,\n now_ms INTEGER NOT NULL DEFAULT 0\n);\n\n-- op_dying: natural keys of workstream/task rows mid-DELETE, so cascaded\n-- children can still resolve their keys (see src/capture.ts, THE DELETE\n-- SUBTLETY). Empty at rest: an AFTER DELETE trigger removes each entry.\nCREATE TABLE IF NOT EXISTS op_dying (\n kind TEXT NOT NULL,\n id INTEGER NOT NULL,\n key TEXT NOT NULL,\n PRIMARY KEY (kind, id)\n);\n\n-- machine_identity: one durable identity per DB/machine, seeded by\n-- openDb after schema creation. hostname is advisory only.\n--\n-- last_wall / last_counter are the persisted hybrid logical clock\n-- (src/hlc.ts, VOCABULARY § HLC). They live here because every mu\n-- invocation is a fresh process — an in-memory counter would reset\n-- constantly and mint duplicate HLCs, which UNIQUE (machine_id, hlc)\n-- on the ops table would then reject.\nCREATE TABLE IF NOT EXISTS machine_identity (\n id INTEGER PRIMARY KEY CHECK (id = 1),\n machine_id TEXT NOT NULL,\n hostname TEXT,\n created_at TEXT NOT NULL,\n last_wall INTEGER NOT NULL DEFAULT 0,\n last_counter INTEGER NOT NULL DEFAULT 0\n);\n\n-- ─── Tables ───────────────────────────────────────────────────────────\n\n-- workstreams: top of the hierarchy. name stays globally unique\n-- because it IS a tmux session name; no <scope_id> column because\n-- there's no parent.\nCREATE TABLE IF NOT EXISTS workstreams (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT UNIQUE NOT NULL,\n created_at TEXT NOT NULL, -- ISO 8601\n -- Soft teardown: set = torn down. Views and user-facing reads skip such\n -- rows; ingest still sees them (UNIQUE(name) must hold). Synced.\n torn_down_at TEXT\n);\n\n\n-- agents: one row per managed pane. Per-workstream unique on name.\nCREATE TABLE IF NOT EXISTS agents (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n workstream_id INTEGER NOT NULL REFERENCES workstreams (id) ON DELETE CASCADE,\n name TEXT NOT NULL, -- per-workstream unique\n cli TEXT NOT NULL DEFAULT 'pi',\n pane_id TEXT NOT NULL,\n status TEXT NOT NULL, -- DEPRECATED (2.0): always 'spawning'; runtime state lives in murmur. Drop at the first v11 migration.\n role TEXT NOT NULL DEFAULT 'full-access',\n tab TEXT,\n cwd TEXT, -- worktree path the pane runs in (machine-local)\n base TEXT, -- commit that worktree was created from (machine-local)\n command TEXT, -- the resolved command the pane runs (machine-local); NULL: row predates it\n command_source TEXT, -- 'explicit' | 'env' | 'cli-key': where command came from (machine-local)\n spawner TEXT, -- who spawned it: '<workstream>/<agent>' or 'pi:<session>' (machine-local); NULL: unknown\n host TEXT, -- the remote host profile it runs on (machine-local); NULL: local\n collected_head TEXT, -- HEAD last collected from a remote worktree (machine-local)\n repo TEXT, -- a remote worktree's repo on its host, made absolute at spawn (machine-local); NULL: none\n gate_token TEXT, -- remote command gate: spawn-unique token, also the key of its remote result record (machine-local); NULL: not a gate\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE (workstream_id, name),\n CHECK (status IN (\n 'spawning', 'busy', 'needs_input', 'needs_permission',\n 'free', 'unreachable', 'terminated'\n )),\n CHECK (role IN ('full-access', 'read-only'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_agents_workstream ON agents (workstream_id);\nCREATE INDEX IF NOT EXISTS idx_agents_status ON agents (status);\n\n-- task_substates: the legal (status, substate) pairs. Seeded from\n-- TASK_SUBSTATE_ROWS (src/tasks/status.ts) by applySchema; exactly one\n-- default per status.\nCREATE TABLE IF NOT EXISTS task_substates (\n status TEXT NOT NULL,\n substate TEXT NOT NULL,\n is_default INTEGER NOT NULL DEFAULT 0 CHECK (is_default IN (0, 1)),\n PRIMARY KEY (status, substate)\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS idx_task_substates_one_default\n ON task_substates (status) WHERE is_default = 1;\n\n-- tasks: per-workstream unique on local_id (TRULY local now —\n-- different workstreams may reuse the same local_id).\nCREATE TABLE IF NOT EXISTS tasks (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n workstream_id INTEGER NOT NULL REFERENCES workstreams (id) ON DELETE CASCADE,\n local_id TEXT NOT NULL, -- per-workstream unique\n title TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'OPEN',\n -- OPEN | IN_PROGRESS | CLOSED — see VOCABULARY.md.\n substate TEXT NOT NULL,\n -- Qualifies status. No DEFAULT on purpose: a writer that forgets it\n -- must fail loudly rather than silently pick one.\n -- NOT NULL with defaults until flag day: a peer's partial op must be\n -- able to create the row. \\`scored\\` says whether they were given.\n impact INTEGER NOT NULL DEFAULT 50,\n effort_days REAL NOT NULL DEFAULT 1,\n scored INTEGER NOT NULL DEFAULT 0 CHECK (scored IN (0, 1)),\n dispatch_host TEXT, -- host \\`mu next\\` dispatches this task to (synced)\n kind TEXT NOT NULL DEFAULT 'work' -- work | delegate | human (synced)\n CHECK (kind IN (${sqlList(TASK_KINDS)})),\n wave TEXT, -- label grouping one fan-out of delegate calls (synced)\n owner_id INTEGER REFERENCES agents (id) ON DELETE SET NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE (workstream_id, local_id),\n CHECK (impact BETWEEN 1 AND 100),\n CHECK (effort_days > 0),\n FOREIGN KEY (status, substate) REFERENCES task_substates (status, substate)\n DEFERRABLE INITIALLY DEFERRED\n);\n\nCREATE INDEX IF NOT EXISTS idx_tasks_workstream ON tasks (workstream_id);\nCREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks (status);\nCREATE INDEX IF NOT EXISTS idx_tasks_owner ON tasks (owner_id);\n\n-- task_edges: composite PK by pair. INTEGER FKs into tasks.id.\nCREATE TABLE IF NOT EXISTS task_edges (\n from_task_id INTEGER NOT NULL REFERENCES tasks (id) ON DELETE CASCADE,\n to_task_id INTEGER NOT NULL REFERENCES tasks (id) ON DELETE CASCADE,\n created_at TEXT NOT NULL,\n PRIMARY KEY (from_task_id, to_task_id),\n CHECK (from_task_id <> to_task_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_task_edges_to ON task_edges (to_task_id);\n\n-- task_notes: append-only context. author stays free-text\n-- (\"orchestrator\", \"user\", \"π - mu\", \"system\") — not always a\n-- registered agent.\nCREATE TABLE IF NOT EXISTS task_notes (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n task_id INTEGER NOT NULL REFERENCES tasks (id) ON DELETE CASCADE,\n author TEXT,\n content TEXT NOT NULL,\n created_at TEXT NOT NULL,\n -- Set once at INSERT (a local UPDATE raises: src/capture.ts).\n kind TEXT NOT NULL DEFAULT 'note'\n CHECK (kind IN ('brief', 'report', 'verdict', 'close', 'note'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_task_notes_task ON task_notes (task_id);\n\n-- task_auto: per-task auto-dispatch state (machine-local, never synced).\nCREATE TABLE IF NOT EXISTS task_auto (\n task_id INTEGER PRIMARY KEY REFERENCES tasks (id) ON DELETE CASCADE,\n cli TEXT NOT NULL,\n worktree INTEGER NOT NULL DEFAULT 0 CHECK (worktree IN (0, 1)),\n max_runs INTEGER NOT NULL DEFAULT 1 CHECK (max_runs > 0),\n runs INTEGER NOT NULL DEFAULT 0,\n last_spawn TEXT,\n created_at TEXT NOT NULL,\n -- 0 after \\`mu task auto --off\\`: the row (runs, last_spawn) outlives revoked permission.\n enabled INTEGER NOT NULL DEFAULT 1 CHECK (enabled IN (0, 1))\n);\n\n-- delegate_calls: one row per task-backed delegate call (machine-local); the brief is a task note.\nCREATE TABLE IF NOT EXISTS delegate_calls (\n task_id INTEGER PRIMARY KEY REFERENCES tasks (id) ON DELETE CASCADE,\n caller TEXT NOT NULL,\n call_id TEXT NOT NULL UNIQUE,\n state TEXT NOT NULL\n CHECK (state IN (${sqlList(DELEGATE_CALL_STATES)})),\n record_workstream TEXT,\n record_task TEXT,\n record_label TEXT,\n error TEXT,\n updated_at TEXT NOT NULL,\n request TEXT, -- spawn request (JSON)\n verdict TEXT, agent TEXT -- parsed label of a done answer; the agent that ran it\n);\n-- The dashboard's attention scan reads refused and recently failed calls each tick.\nCREATE INDEX IF NOT EXISTS idx_delegate_calls_state ON delegate_calls (state, updated_at);\n\n-- human_needs: the caller that recorded a kind=human task (machine-local).\n-- The task, its reason brief and its close are portable; who asked is not\n-- (a caller names a managed agent or pi session of THIS machine).\nCREATE TABLE IF NOT EXISTS human_needs (\n task_id INTEGER PRIMARY KEY REFERENCES tasks (id) ON DELETE CASCADE,\n caller TEXT NOT NULL\n);\n\n-- wait_cursors: per caller and ref, the last consumed incarnation and\n-- runs (machine-local), so a settled run is reported once.\nCREATE TABLE IF NOT EXISTS wait_cursors (\n caller TEXT NOT NULL,\n ref TEXT NOT NULL,\n incarnation TEXT,\n runs INTEGER,\n PRIMARY KEY (caller, ref)\n);\n\n-- wait_registrations: per caller, the typed refs a wait still owes it\n-- (machine-local; src/wait-registration.ts owns the JSON shape). state\n-- 'waiting' = a wait is in flight; generation is bumped by each wait that\n-- starts, so a finished older wait cannot overwrite a newer one. No foreign\n-- keys: a ref outliving its task or agent is still owed its answer. Never\n-- holds consumed runs: that is wait_cursors.\nCREATE TABLE IF NOT EXISTS wait_registrations (\n caller TEXT PRIMARY KEY,\n refs_json TEXT NOT NULL,\n state TEXT NOT NULL CHECK (state IN ('armed', 'waiting')),\n generation INTEGER NOT NULL DEFAULT 0 CHECK (generation >= 0),\n updated_at TEXT NOT NULL,\n -- Per agent ref, the UNCONSUMED run baseline a producer registered\n -- ({afterRuns, incarnation, agentId}); never a consumed cursor.\n baselines_json TEXT NOT NULL DEFAULT '{}'\n);\n\n-- agent_settles: one row per (agent, incarnation, runs) already applied\n-- (machine-local). No foreign keys on purpose: the evidence that a settled\n-- run took effect must outlive the agent and the task. agents.id is\n-- AUTOINCREMENT, so a deleted agent's id is never reused.\nCREATE TABLE IF NOT EXISTS agent_settles (\n agent_id INTEGER NOT NULL,\n incarnation TEXT NOT NULL,\n runs INTEGER NOT NULL,\n task_id INTEGER,\n PRIMARY KEY (agent_id, incarnation, runs)\n);\n\n-- spawn_receipts: one row per task-bound spawn attempt (machine-local). The\n-- journal agent spawn --task writes BEFORE each external effect and that a\n-- replay reads back. agent_id/pane_id name the registry incarnation it\n-- created and carry NO foreign key on purpose: the receipt must outlive the\n-- agent (a deleted or replaced name is \"stale\", never the replacement).\n-- state: reserved (nothing happened yet) < pane (agent row + pane exist)\n-- < claimed (task owned by agent_id) < sending (the send MAY have been\n-- written: never resend) < sent | unknown; failed = definitely unsent and\n-- rolled back. attempt_key is 'manual:<k>' for a manual spawn.\nCREATE TABLE IF NOT EXISTS spawn_receipts (\n task_id INTEGER NOT NULL REFERENCES tasks (id) ON DELETE CASCADE,\n attempt_key TEXT NOT NULL,\n name TEXT NOT NULL,\n workstream TEXT NOT NULL,\n request_sha TEXT NOT NULL,\n msg_id TEXT NOT NULL,\n agent_id INTEGER,\n pane_id TEXT,\n transport TEXT CHECK (transport IN ('ctl', 'mux')),\n incarnation TEXT,\n runs INTEGER,\n state TEXT NOT NULL\n CHECK (state IN (${sqlList(SPAWN_RECEIPT_STATES)})),\n detail TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY (task_id, attempt_key)\n);\n\n-- wait_resumes: the stored condition set of a wait that ended with something\n-- still owed (machine-local; src/wait-resume.ts owns the JSON shape). The\n-- result prints only 'mu wait --resume <id>': the refs (with the run baseline\n-- and pi incarnation each was seen at), mode, filters, deadline and the callers\n-- it ran for live here, so a resume is lossless and its size does not grow with\n-- the wait. No foreign keys: a handle outlives the tasks and agents it names.\nCREATE TABLE IF NOT EXISTS wait_resumes (\n id TEXT PRIMARY KEY,\n callers_json TEXT NOT NULL,\n spec_json TEXT NOT NULL,\n created_at TEXT NOT NULL\n);\n\n-- wait_action_receipts: one row per stall action a wait took (machine-local,\n-- never captured or synced). The identity is the TASK (tasks.id), the OWNER\n-- (agents.id) and pi's ctl incarnation, plus the action: NOT the wait\n-- generation, the task revision or the caller, so every caller, restart and\n-- generation shares one exclusion. No foreign keys: the row is evidence that\n-- an effect may have happened and must outlive the task and the agent.\n-- incarnation '' = ctl named none. state: reserved (nothing written) <\n-- sending (the write MAY have happened: never resend) < sent | unknown;\n-- refused = a guard stopped it, nothing written; released = a release took\n-- effect (written in the release's own transaction).\nCREATE TABLE IF NOT EXISTS wait_action_receipts (\n task_id INTEGER NOT NULL,\n owner_id INTEGER NOT NULL,\n incarnation TEXT NOT NULL DEFAULT '',\n action TEXT NOT NULL CHECK (action IN (${sqlList(WAIT_ACTIONS)})),\n caller TEXT NOT NULL,\n task_ref TEXT NOT NULL,\n owner_ref TEXT NOT NULL,\n pane_id TEXT NOT NULL,\n preview_revision INTEGER NOT NULL,\n msg_id TEXT,\n state TEXT NOT NULL CHECK (state IN (${sqlList(WAIT_ACTION_STATES)})),\n runs INTEGER,\n detail TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY (task_id, owner_id, incarnation, action)\n);\n\n-- host_profiles: ssh-free command templates for a remote host\n-- (machine-local; mu never connects, it expands these).\nCREATE TABLE IF NOT EXISTS host_profiles (\n name TEXT PRIMARY KEY,\n shell TEXT NOT NULL,\n exec TEXT NOT NULL,\n fetch TEXT NOT NULL,\n repo TEXT, -- default remote repo for spawns without --root; NULL: none\n max_sessions INTEGER CHECK (max_sessions > 0)\n);\n\n-- host_channels: the connection slots of a host (machine-local). One row\n-- per holder. 'transient' rides an invocation (exec, fetch, check) and is\n-- reclaimed only when its pid is proven gone; 'attached' rides an agent's\n-- pane (registry id + pane, no pid) and is reclaimed only when that pane is\n-- proven dead. 'pgid' is the template's process group, recorded before the\n-- command starts: a transient row stays held while that group lives, whatever\n-- became of the holder pid (SIGKILL included). 'token' makes every release a\n-- compare-and-set. No FK: the\n-- row must outlive neither its host nor guess at its holder.\nCREATE TABLE IF NOT EXISTS host_channels (\n host TEXT NOT NULL,\n holder TEXT NOT NULL,\n kind TEXT NOT NULL CHECK (kind IN ('transient', 'attached')),\n token TEXT NOT NULL,\n pid INTEGER,\n pid_start TEXT,\n pgid INTEGER,\n pgid_start TEXT,\n agent_id INTEGER,\n pane_id TEXT,\n opened_at TEXT NOT NULL,\n PRIMARY KEY (host, holder),\n CHECK (kind = 'transient' AND pid IS NOT NULL\n OR kind = 'attached' AND agent_id IS NOT NULL AND pane_id IS NOT NULL)\n);\n\n${REMOTE_RECOVERY_DDL}\n-- ─── The ops log (VISION.md § 2b, VOCABULARY.md § op / ops log) ──────\n--\n-- The single append-only record of every change. Sync and\n-- history are all queries or replays over this one table.\n--\n-- Deliberately FK-free. An op must stay readable after the row (and\n-- the workstream) it records is gone — a tombstone op for a destroyed\n-- workstream is the whole point — so 'key' holds the NATURAL key\n-- ('<workstream>/<local_id>'), never a surrogate id. That is also why\n-- keys don't collide across machines.\n--\n-- seq local-only append cursor (AUTOINCREMENT never recycles)\n-- hlc the ORDERING key across machines (VOCABULARY § HLC)\n-- machine_id which peer wrote this op\n-- group_id the op group: all ops of one operator action\n-- actor who caused it (may not be a registered worker)\n-- intent semantic label ('task.close', 'agent.spawn')\n-- entity/key what it addresses ('task', 'mu/ops-log')\n-- op 'put' (semantic partial update) | 'del' (tombstone)\n-- payload JSON of ONLY the columns that changed\n--\n-- UNIQUE (machine_id, hlc) is load-bearing: it makes ingest idempotent\n-- for free, which is what lets 'mu sync --repair' be nothing more than\n-- \"re-read that peer's segment from zero\".\nCREATE TABLE IF NOT EXISTS ops (\n seq INTEGER PRIMARY KEY AUTOINCREMENT,\n hlc TEXT NOT NULL,\n machine_id TEXT NOT NULL,\n group_id TEXT NOT NULL,\n actor TEXT,\n intent TEXT,\n entity TEXT NOT NULL,\n key TEXT NOT NULL,\n op TEXT NOT NULL CHECK (op IN ('put','del')),\n payload TEXT NOT NULL,\n created_at TEXT NOT NULL,\n UNIQUE (machine_id, hlc)\n);\n\n-- Four indexes, one per read shape that actually exists:\n-- hlc — replay/rebuild walks the log in HLC order.\n-- entity,key — \"what happened to this task\" (history + per-field merge).\n-- group_id — 'mu log --group <group>' gathers one action's ops.\n-- machine_id,entity,hlc — sync flush seeks this machine's SYNCED ops\n-- past the segment's last hlc, so a trailing run of\n-- machine-local ops (agent.*) costs nothing per flush.\n-- (Other machine_id lookups ride the UNIQUE (machine_id, hlc) index;\n-- seq is the PK. No speculative index beyond these.)\nCREATE INDEX IF NOT EXISTS idx_ops_hlc ON ops (hlc);\nCREATE INDEX IF NOT EXISTS idx_ops_entity_key ON ops (entity, key);\nCREATE INDEX IF NOT EXISTS idx_ops_group ON ops (group_id);\nCREATE INDEX IF NOT EXISTS idx_ops_machine_entity_hlc ON ops (machine_id, entity, hlc);\n\n-- sync_peers: one row per known peer, holding its watermark — how far\n-- into that peer's segment we have applied. One integer suffices\n-- because segments are append-only and ordered. Rows are created on\n-- demand at first ingest; there is no membership list to configure.\n-- A Syncthing conflict copy gets its own row, keyed by its file stem.\n-- last_seen_at is the ISO time of the last watermark write.\nCREATE TABLE IF NOT EXISTS sync_peers (\n machine_id TEXT PRIMARY KEY,\n last_applied_seq INTEGER NOT NULL DEFAULT 0,\n last_seen_at TEXT\n);\n\n-- sync_fingerprints: the caught-up fingerprint, '<size> <mtimeMs>\n-- <manifest sha256>' of a peer segment, recorded with the watermark\n-- when ingest read that segment cleanly to its end (src/segments.ts\n-- segmentCaughtUp). Keyed like sync_peers; a watermark write without a\n-- clean read deletes the row. A cache: losing it costs one full read.\n-- The value may carry tab-separated resume fields after the key\n-- (src/segment-resume.ts): byte offset and sha256 state for ingest\n-- to read only appended bytes.\n-- Additive, so no schema bump: an older mu ignores it, and any\n-- watermark it writes can no longer match a stale fingerprint.\nCREATE TABLE IF NOT EXISTS sync_fingerprints (\n machine_id TEXT PRIMARY KEY,\n fingerprint TEXT NOT NULL\n);\n\n-- worktrees: the machine-local registry of git worktrees mu created for\n-- agents. NOT keyed to agents: the row outlives the agent so a reused\n-- name can tell \"my own clean leftover\" from foreign work (base,\n-- last_collected_head). deleteAgent never touches it; closing the\n-- worktree (src/worktree.ts) does.\nCREATE TABLE IF NOT EXISTS worktrees (\n path TEXT PRIMARY KEY,\n agent TEXT NOT NULL,\n workstream TEXT NOT NULL,\n root TEXT NOT NULL, -- the repo checkout the worktree was added from\n base TEXT NOT NULL, -- commit the worktree was created at\n last_collected_head TEXT, -- HEAD last brought back (remote collect)\n created_at TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS idx_worktrees_workstream ON worktrees (workstream, agent);\n\n-- ─── Views (replaced when stale so the latest definition wins) ────────\n-- See READY_VIEW_SQL / BLOCKED_VIEW_SQL / BLOCKERS_VIEW_SQL / GOALS_VIEW_SQL\n-- above for the canonical DDL — interpolated here so applySchema is one\n-- db.exec(). Every view skips torn-down workstreams.\n${READY_VIEW_SQL}\n${BLOCKED_VIEW_SQL}\n${BLOCKERS_VIEW_SQL}\n${GOALS_VIEW_SQL}\n`;\n","// mu — op capture: SQLite triggers that record every change to a\n// portable table as an op, inside the SAME TRANSACTION as the mutation.\n//\n// WHY TRIGGERS AND NOT HAND-EMITTED OPS\n// -------------------------------------\n// Capture fires inside the same transaction as the row change, in the\n// same file. So capture is ATOMIC with the change: the two cannot\n// drift, not even on power loss mid-write. Either both landed or\n// neither did.\n//\n// Hand-emitted ops (an `emitOp(...)` next to each mutation) were\n// rejected because they can be FORGOTTEN. A forgotten op is no\n// longer \"sync missed something\" — sync, rebuild and history are\n// ALL projections of this one log, so one missing op is silent\n// corruption of all of them at once. A future SDK function that mutates\n// `tasks` must not be ABLE to skip capture. Triggers make that\n// structural rather than a convention someone has to remember.\n//\n// WHY THE TRIGGERS LIVE IN THE DB FILE (and what that costs)\n// ----------------------------------------------------------\n// The triggers are ordinary main-schema triggers, stored in the file.\n// So a plain write from ANY connection, `sqlite3` included, is captured:\n// a safety net, not a supported path (plain sqlite3 defaults to\n// foreign_keys=0, so cascades are skipped; mu writes go through the SDK).\n//\n// Per-invocation context (intent / actor / group / the echo guard) lives\n// in `op_ctx`, a one-row MAIN table. 3.x kept it in a per-connection\n// TEMP table, which a main trigger cannot reference; with it in main,\n// two connections share one row, and that needs two rules:\n//\n// * ONLY the context wrappers (src/op-context.ts) write `op_ctx`, and\n// they do it inside a transaction THEY OWN: BEGIN IMMEDIATE, set the\n// row, run, reset it, COMMIT. The row is therefore never committed\n// with a context in it: a concurrent writer blocks on the lock\n// instead of being stamped with someone else's intent (or, worse,\n// `applying = 1`, which would silently drop its ops), and a crash\n// rolls the context back with everything else.\n// * The triggers read `applying` with COALESCE(..., 0): a missing row\n// captures with no context rather than capturing nothing.\n//\n// Consequences of persistence:\n//\n// * The trigger set is versioned. `schema_version.capture_version`\n// stamps the revision (CAPTURE_VERSION below); `installCapture`\n// replaces every `_cap_*` trigger and the stamp in ONE BEGIN\n// IMMEDIATE when the stamp is older, refuses (the caller throws\n// SchemaTooNewError) when it is newer, and does nothing, taking no\n// lock, when equal. Change a generator => bump CAPTURE_VERSION\n// (test/capture-persistent.test.ts pins the DDL's sha256).\n// * Stored trigger text equals the generated text exactly (no IF NOT\n// EXISTS, no trailing `;`), so `captureTriggersCurrent` and doctor\n// can compare sqlite_master against the generator.\n// * Triggers run on whatever SQLite opens the file, so they abort with\n// a clear message below 3.42 (`unixepoch('subsec')` would mint\n// zero-time HLCs there) instead of writing corrupt ops.\n// * A main trigger may INSERT into a qualified-or-not main table; the\n// `_op_dying` stash became the main table `op_dying` for the same\n// reason as `op_ctx` (a main trigger cannot see temp tables).\n//\n// SEMANTIC PARTIAL UPDATES — ONLY CHANGED COLUMNS\n// -----------------------------------------------\n// The UPDATE triggers compare `NEW.<col> IS NOT OLD.<col>` per column\n// and build the payload from just the columns that actually changed, so\n// `task.close` carries `{\"status\":\"CLOSED\"}` and nothing else. This is\n// the single detail that makes per-field merge FREE: \"apply in HLC\n// order\" then converges without column version vectors.\n//\n// Dumping the whole row instead would look identical in every\n// single-machine test and silently regress the design from field-level\n// to row-level last-writer-wins. mu runs autonomous agent crews, so a\n// devserver crew closing a task while the operator edits that task's\n// impact on a laptop is concurrent multi-machine writing BY\n// CONSTRUCTION. Field-level merge keeps both edits; row-level LWW\n// discards one at random. `IS NOT` (not `<>`) because `<>` is NULL for\n// a NULL operand, which would drop every set-to-NULL and\n// NULL-to-a-value transition — e.g. releasing a claim\n// (`owner_id -> NULL`) would never be captured.\n\nimport { createHash } from \"node:crypto\";\n\n// TYPE-ONLY import: db.ts imports this module, so a value import would\n// be a runtime cycle (and an import cycle here shows up as `node\n// dist/cli.js` printing nothing at all). `typeof PORTABLE_TABLES` is a\n// type position, so this is erased at compile time.\nimport type { PORTABLE_TABLES } from \"./db.js\";\n\n/** Sentinel key segment for a natural key whose parent row could not be\n * resolved. Should be unreachable — the dying-ancestor stash below\n * exists precisely so cascades can still resolve — but a capture that\n * records a degraded key is strictly better than one that records\n * nothing, so this FAILS SAFE rather than failing silent. */\nconst UNRESOLVED = \"<unresolved>\";\n\n// ─── Revision, SQLite floor, context tables ──────────────────────────\n\n/**\n * The revision of the trigger set stored in the file, stamped in\n * `schema_version.capture_version`. BUMP IT whenever any generator in\n * this file changes the SQL it emits: an older stamp makes the next\n * writable `openDb` replace every capture trigger (one BEGIN IMMEDIATE,\n * with the stamp), and a newer stamp makes it refuse (SchemaTooNewError)\n * instead of running triggers it cannot vouch for.\n * test/capture-persistent.test.ts pins the sha256 of the generated DDL,\n * so forgetting the bump fails a test.\n *\n * Separate from CURRENT_SCHEMA_VERSION on purpose: that number says\n * \"tables and columns are incompatible\" and refuses older DBs outright;\n * a capture revision is upgradeable in place, so it must not be folded\n * into it (an older schema number is refused before any trigger work).\n */\nexport const CAPTURE_VERSION = 5;\n\n/** Lowest SQLite that mints correct HLCs: `unixepoch('subsec')` arrived\n * in 3.42; before it the call yields NULL and every op gets a zero-time\n * HLC. */\nexport const MIN_SQLITE = { major: 3, minor: 42 } as const;\n\n/** True when `version` (\"3.41.2\") is below MIN_SQLITE. Numeric per part,\n * never a string compare (\"3.9\" > \"3.42\" as text). */\nexport function sqliteTooOld(version: string): boolean {\n const [major = 0, minor = 0] = version.split(\".\").map((p) => Number.parseInt(p, 10) || 0);\n return major < MIN_SQLITE.major || (major === MIN_SQLITE.major && minor < MIN_SQLITE.minor);\n}\n\n/** The same test, inside SQL: every EMITTING trigger runs it first, so a\n * connection on an old SQLite (a stray `sqlite3` binary) aborts the\n * write instead of minting zero-time HLCs. */\nconst SQLITE_TOO_OLD_SQL = (() => {\n const v = \"sqlite_version()\";\n const afterMajor = `substr(${v}, instr(${v}, '.') + 1)`;\n const major = `CAST(${v} AS INTEGER)`;\n const minor = `CAST(${afterMajor} AS INTEGER)`;\n return `(${major} < ${MIN_SQLITE.major} OR (${major} = ${MIN_SQLITE.major} AND ${minor} < ${MIN_SQLITE.minor}))`;\n})();\n\nconst SQLITE_TOO_OLD_MESSAGE = `mu: SQLite >= ${MIN_SQLITE.major}.${MIN_SQLITE.minor} required (unixepoch subsec)`;\n\n// ─── The op context tables ────────────────────────────────────────────\n//\n// `op_ctx` and `op_dying` are MAIN tables created by applySchema\n// (src/db.ts), because a main trigger cannot reference the temp schema.\n//\n// op_ctx the **op context** (docs/VOCABULARY.md): group_id /\n// actor / intent / applying, plus `now_ms`, a scratchpad\n// holding \"now\" for the current trigger firing. The HLC\n// advance compares `now` against `last_wall` and reuses the\n// SAME `now` to write it; calling unixepoch() twice could\n// straddle a millisecond boundary and mint a non-monotonic\n// pair. Exactly ONE row, id = 1, seeded with defaults, so a\n// mutation outside any SDK context is still CAPTURED, just\n// with a null intent. Fail safe, never fail silent. Only\n// src/op-context.ts writes the context columns, inside a\n// transaction it owns; at rest they are always defaults.\n//\n// op_dying natural keys of rows that are mid-DELETE: see the DELETE\n// section below. Keyed by (kind, id). Empty at rest: each\n// stash row is removed by an AFTER DELETE trigger.\n\n// ─── Shared SQL fragments ─────────────────────────────────────────────\n\n/** Echo guard. Every trigger carries it. `applying = 1` means we are\n * INGESTING a peer's op, where writing a fresh local op would be an\n * echo that propagates back and never terminates. v2-sync sets it. */\nconst NOT_APPLYING = \"COALESCE((SELECT applying FROM op_ctx WHERE id = 1), 0) = 0\";\n\n/** Advance the persisted HLC by one tick, then read it back formatted.\n * Mirrors `nextHlc` in src/hlc.ts EXACTLY — same monotonic rule (if\n * now > last_wall take now with counter 0, else hold the wall and step\n * the counter) and same `%015d.%06d.%s` serialization. It is\n * reimplemented in SQL rather than called from JS because a trigger\n * cannot call back into JS, and the whole point is that capture\n * happens inside the mutation's transaction.\n *\n * Kept honest by test/capture.test.ts, which asserts the SQL-minted\n * HLC parses with `parseHlc` and interleaves monotonically with\n * JS-minted ones. If the format changes in one place the other fails. */\nconst ADVANCE_CLOCK = `\n SELECT RAISE(ABORT, '${SQLITE_TOO_OLD_MESSAGE}') WHERE ${SQLITE_TOO_OLD_SQL};\n UPDATE op_ctx SET now_ms = CAST(unixepoch('subsec') * 1000 AS INTEGER) WHERE id = 1;\n UPDATE machine_identity\n SET last_wall = MAX(last_wall, (SELECT now_ms FROM op_ctx WHERE id = 1)),\n last_counter = CASE WHEN (SELECT now_ms FROM op_ctx WHERE id = 1) > last_wall\n THEN 0 ELSE last_counter + 1 END\n WHERE id = 1;`;\n\n/** The just-advanced HLC, formatted. Must be read AFTER ADVANCE_CLOCK. */\nconst HLC = `(SELECT printf('%015d.%06d.%s', last_wall, last_counter, machine_id)\n FROM machine_identity WHERE id = 1)`;\n\n/** Column list shared by every op INSERT. */\nconst OP_COLS = \"(hlc, machine_id, group_id, actor, intent, entity, key, op, payload, created_at)\";\n\n/** The context/identity columns, in OP_COLS order after `hlc`.\n * `group_id` falls back to a per-op random hex string so the column is\n * never NULL: an op outside any SDK context is its own group of one,\n * which is exactly right. */\nconst OP_CTX_VALUES = `\n (SELECT machine_id FROM machine_identity WHERE id = 1),\n COALESCE((SELECT group_id FROM op_ctx WHERE id = 1), lower(hex(randomblob(8)))),\n (SELECT actor FROM op_ctx WHERE id = 1),\n (SELECT intent FROM op_ctx WHERE id = 1)`;\n\n/** ISO-8601 wall time, matching what the SDK writes elsewhere.\n * Advisory only — `hlc` is the ordering key, this is for humans. */\nconst CREATED_AT = `strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`;\n\n// ─── Natural keys ─────────────────────────────────────────────────────\n//\n// `ops.key` is ALWAYS the natural key, never a surrogate id. This is\n// exactly why mu's keys don't collide across machines the way an\n// AUTOINCREMENT rowid would: two machines both minting `tasks.id = 7`\n// is inevitable and meaningless, whereas `demo/fix-auth` denotes the\n// same task everywhere.\n//\n// workstream <name> demo\n// task <workstream>/<local_id> demo/fix-auth\n// note <workstream>/<local_id>#<id> demo/fix-auth#12\n// edge <blocker> -> <blocked> demo/a->demo/b\n//\n// Notes keep their surrogate `id` as a suffix because a note has no\n// natural identity of its own — same author and text twice is two\n// notes. Notes are append-only (a local edit raises), so the suffix only\n// needs to be locally unique, and `<task-key>#<id>` is. A rebuild can\n// reassign ids, so a tombstone also names the note it kills.\n\n/** Workstream name for a workstream id, or the dying-stash value if the\n * workstream row is already gone (FK cascade). */\nconst wsKey = (idExpr: string): string => `COALESCE(\n (SELECT w.name FROM workstreams w WHERE w.id = ${idExpr}),\n (SELECT d.key FROM op_dying d WHERE d.kind = 'workstream' AND d.id = ${idExpr}),\n '${UNRESOLVED}')`;\n\n/** `<workstream>/<local_id>` for a task id, falling back to the dying\n * stash when the task row itself is already gone. */\nconst taskKey = (idExpr: string): string => `COALESCE(\n (SELECT ${wsKey(\"t.workstream_id\")} || '/' || t.local_id\n FROM tasks t WHERE t.id = ${idExpr}),\n (SELECT d.key FROM op_dying d WHERE d.kind = 'task' AND d.id = ${idExpr}),\n '${UNRESOLVED}')`;\n\n// ─── Per-table trigger DDL ────────────────────────────────────────────\n\n/** Build the changed-columns-only payload expression for an UPDATE.\n *\n * One row per column that changed, folded into an object:\n *\n * (SELECT json_group_object(k, v) FROM (\n * SELECT 'impact' AS k, NEW.impact AS v WHERE NEW.impact IS NOT OLD.impact\n * UNION ALL SELECT 'title', NEW.title WHERE NEW.title IS NOT OLD.title ...))\n *\n * With six columns and one change that yields a 1-key object, keys in\n * column order. The text grows linearly with the column count: an earlier\n * form nested one CASE around the previous expression, which repeated it\n * twice per column, so each added column doubled every UPDATE trigger\n * (two columns took _cap_tasks_upd from 274 KB to 1.09 MB, and every `mu`\n * process parses it on open). */\nfunction changedPayload(cols: readonly string[]): string {\n const rows = cols.map(\n (col, i) =>\n `${i === 0 ? \"SELECT\" : \"UNION ALL SELECT\"} '${col}'${i === 0 ? \" AS k\" : \"\"}, NEW.${col}${i === 0 ? \" AS v\" : \"\"} WHERE NEW.${col} IS NOT OLD.${col}`,\n );\n return `(SELECT json_group_object(k, v) FROM (${rows.join(\"\\n \")}))`;\n}\n\n/** Whole-row payload for an INSERT: an insert changes every column by\n * definition, so there is nothing to diff against. */\nfunction fullPayload(cols: readonly string[]): string {\n const pairs = cols.map((c) => `'${c}', NEW.${c}`).join(\", \");\n return `json_object(${pairs})`;\n}\n\n/** Whole-row payload for a DELETE, from `OLD.*`.\n *\n * Tombstones are normally EMPTY (`'{}'`): the key identifies the row\n * and the puts before it describe it, so carrying the body again would\n * just bloat the log. Notes are the exception, and the reason is their\n * key.\n *\n * A note's key embeds its rowid (`<ws>/<task>#<id>`), which is NOT\n * portable — a rebuild, a v8/v9 reprojection, or any path that\n * reinserts a note assigns a fresh one (see src/drift.ts, which\n * deliberately matches notes on the task-key PREFIX for exactly this\n * reason). When that happens the historical `put` stays under the old\n * key while a later `del` is emitted under the current one, and\n * nothing joins the two.\n *\n * A reader folding the puts for a key to reconstruct a tombstoned row\n * would see `{}` for a note in that state (drift-641). A\n * self-describing note tombstone closes that hole: the op that removed\n * the row also carries what the row WAS, so nothing depends on finding\n * a matching put. */\nfunction fullOldPayload(cols: readonly string[]): string {\n const pairs = cols.map((c) => `'${c}', OLD.${c}`).join(\", \");\n return `json_object(${pairs})`;\n}\n\n/** A note tombstone's payload. `{}` only when the NEWEST put under the\n * same key describes the very row being deleted (same author, content and\n * created_at): apply's delete reads the identity from that put, and a\n * workstream teardown then does not write each note twice. Otherwise the\n * full row: no put under the key (a reprojection gave the note a new\n * rowid, drift-641), or one that names ANOTHER note (a rebuild reassigned\n * ids, so a deleted note's key now belongs to a different row). */\nfunction noteTombstonePayload(keyExpr: string, cols: readonly string[]): string {\n return `CASE WHEN (\n SELECT json_extract(p.payload, '$.author') IS OLD.author\n AND json_extract(p.payload, '$.content') IS OLD.content\n AND json_extract(p.payload, '$.created_at') IS OLD.created_at\n FROM ops p WHERE p.entity = 'note' AND p.key = ${keyExpr} AND p.op = 'put'\n ORDER BY p.seq DESC LIMIT 1\n ) THEN '{}' ELSE ${fullOldPayload(cols)} END`;\n}\n\n/** `WHEN` clause restricting an UPDATE trigger to real changes. A\n * no-op UPDATE (SET x = x, or rewriting identical values) produces NO\n * op at all, which keeps the log free of churn that would otherwise\n * make every `mu log` read noisy and every sync flush bigger. */\nfunction anyChanged(cols: readonly string[]): string {\n return cols.map((c) => `NEW.${c} IS NOT OLD.${c}`).join(\"\\n OR \");\n}\n\n/** Emit one op. `keyExpr`/`payloadExpr` are SQL expressions. */\nfunction emitOp(\n entity: string,\n opKind: \"put\" | \"del\",\n keyExpr: string,\n payloadExpr: string,\n): string {\n return `${ADVANCE_CLOCK}\n INSERT INTO ops ${OP_COLS} VALUES (\n ${HLC},${OP_CTX_VALUES},\n '${entity}',\n ${keyExpr},\n '${opKind}',\n ${payloadExpr},\n ${CREATED_AT}\n );`;\n}\n\n/** Columns captured per portable table. Deliberately EXCLUDES surrogate\n * ids and FK columns that are already encoded in the natural key\n * (`tasks.workstream_id`, `task_notes.task_id`, the edge endpoints),\n * because shipping a peer our local rowids would be worse than\n * useless. Changing one of those would re-key the row, which no op\n * can express, so KEY_COLUMNS below refuses it instead. `tasks.owner_id` IS captured: it is an FK into the\n * machine-local `agents` table, so it never syncs (see\n * MACHINE_LOCAL_TABLES), but it must still be captured for local\n * history of a claim/release. */\nconst CAPTURED_COLUMNS = {\n workstreams: [\"name\", \"created_at\", \"torn_down_at\"],\n tasks: [\n \"local_id\",\n \"title\",\n \"status\",\n \"substate\",\n \"impact\",\n \"effort_days\",\n \"scored\",\n \"dispatch_host\",\n \"kind\",\n \"wave\",\n \"owner_id\",\n \"created_at\",\n \"updated_at\",\n ],\n task_notes: [\"author\", \"content\", \"created_at\", \"kind\"],\n task_edges: [\"created_at\"],\n} as const satisfies Record<(typeof PORTABLE_TABLES)[number], readonly string[]>;\n\n/** Columns that make up (or resolve to) each table's natural key.\n *\n * An UPDATE of one of these moves the row to a different `ops.key`\n * (`a/t1` -> `b/t1`), and every op already in the log stays filed under\n * the old key. The UPDATE triggers above diff only CAPTURED_COLUMNS, so\n * such an update used to emit NOTHING: no tombstone for the old key, no\n * put for the new one. Sync, rebuild and `mu doctor` then disagree\n * with the live row. Children re-key with it (a task's notes and edges\n * embed its key), so capturing a move would mean re-emitting a subtree.\n *\n * Natural keys are immutable instead: apply (NEVER_APPLY)\n * already never writes these columns, and a raw\n * `mu sql` UPDATE is refused here with an explicit error rather than\n * committing a row the log cannot explain. The guard is NOT gated on\n * the echo guard: no mu path re-keys a row, ingest included. */\nconst KEY_COLUMNS = {\n workstreams: [\"name\"],\n tasks: [\"workstream_id\", \"local_id\"],\n task_notes: [\"id\", \"task_id\"],\n task_edges: [\"from_task_id\", \"to_task_id\"],\n} as const satisfies Record<(typeof PORTABLE_TABLES)[number], readonly string[]>;\n\n/** One stored trigger. `sql` is exactly the text SQLite keeps in\n * sqlite_master (`CREATE TRIGGER <name> … END`, no `;`), so the stored\n * trigger can be compared to the generator byte for byte. */\nexport interface CaptureTrigger {\n name: string;\n sql: string;\n}\n\n/** `CREATE TRIGGER <name>\\n<rest>\\nEND`. `rest` is the timing/event/WHEN\n * header followed by `BEGIN … ` up to (not including) END. */\nfunction trigger(name: string, rest: string): CaptureTrigger {\n return { name, sql: `CREATE TRIGGER ${name}\\n${rest.trim()}\\nEND` };\n}\n\n/** BEFORE UPDATE trigger refusing a natural-key change on `table`. */\nfunction keyGuard(table: keyof typeof KEY_COLUMNS): CaptureTrigger {\n const cols = KEY_COLUMNS[table];\n const msg =\n `mu: ${table}.${cols.join(\"/\")} is part of the natural key that every op is filed under; ` +\n \"changing it would desync the ops log and sync. \" +\n \"Add a new row (mu task add / mu workstream init) instead of moving or renaming one.\";\n return trigger(\n `_cap_${table}_key`,\n `BEFORE UPDATE OF ${cols.join(\", \")} ON ${table}\n WHEN ${anyChanged(cols)}\nBEGIN\n SELECT RAISE(ABORT, '${msg.replaceAll(\"'\", \"''\")}');`,\n );\n}\n\n/** Existing-row predicate for the BEFORE INSERT guard: the row `NEW` would\n * collide with, by surrogate id or by natural key.\n *\n * SQLite reports NEW.id / NEW.rowid = -1 for an omitted id (the real one is\n * assigned after BEFORE triggers), so -1 cannot be told from an explicit -1.\n * The id check skips it: otherwise one raw `id = -1` row would make every\n * later omitted-id insert look like a collision. An explicit -1 REPLACE is\n * then caught only by the natural-key check. */\nconst INSERT_COLLISION = {\n workstreams: \"SELECT 1 FROM workstreams WHERE (NEW.id <> -1 AND id = NEW.id) OR name = NEW.name\",\n tasks:\n \"SELECT 1 FROM tasks WHERE (NEW.id <> -1 AND id = NEW.id) OR (workstream_id = NEW.workstream_id AND local_id = NEW.local_id)\",\n task_notes: \"SELECT 1 FROM task_notes WHERE NEW.id <> -1 AND id = NEW.id\",\n // task_edges has a composite key, so its hidden rowid is a second identity.\n // (The other three tables' `id` IS the rowid.)\n task_edges:\n \"SELECT 1 FROM task_edges WHERE (NEW.rowid <> -1 AND rowid = NEW.rowid) OR (from_task_id = NEW.from_task_id AND to_task_id = NEW.to_task_id)\",\n} as const satisfies Record<keyof typeof KEY_COLUMNS, string>;\n\n/** BEFORE INSERT trigger refusing an insert that collides with an existing\n * row's id or natural key. `INSERT OR REPLACE` would otherwise delete that\n * row without firing the DELETE trigger (no tombstone) and re-file it under\n * a new key. It also aborts `INSERT OR IGNORE` (BEFORE triggers run before\n * constraints), so mu inserts with `WHERE NOT EXISTS` instead. */\nfunction insertGuard(table: keyof typeof KEY_COLUMNS): CaptureTrigger {\n const msg =\n `mu: ${table} row already exists; replacing it would change the natural key that every op is filed under ` +\n \"and leave no tombstone in the ops log. DELETE it, then INSERT, or add a new row.\";\n return trigger(\n `_cap_${table}_insguard`,\n `BEFORE INSERT ON ${table}\n WHEN EXISTS (${INSERT_COLLISION[table]})\nBEGIN\n SELECT RAISE(ABORT, '${msg.replaceAll(\"'\", \"''\")}');`,\n );\n}\n\n/** The id column each table's INSERT guard and id check read. `NEW.rowid`\n * for task_edges: its key is composite, so the hidden rowid is the id. */\nconst ID_EXPR = {\n workstreams: \"NEW.id\",\n tasks: \"NEW.id\",\n task_notes: \"NEW.id\",\n task_edges: \"NEW.rowid\",\n} as const satisfies Record<keyof typeof KEY_COLUMNS, string>;\n\n/** AFTER INSERT trigger refusing an explicit id <= 0 (local writes only).\n *\n * BEFORE triggers report -1 for an omitted id, so the BEFORE guard above\n * cannot tell an explicit -1 from an omission. By AFTER INSERT SQLite has\n * assigned the real id (always positive for an omitted one), so an id <= 0\n * here was named by the writer. Refusing them keeps -1 free to mean\n * \"omitted\" in the guard, and aborts the statement, rolling back the row\n * and the op the capture trigger just minted. */\nfunction positiveIdGuard(table: keyof typeof KEY_COLUMNS): CaptureTrigger {\n return trigger(\n `_cap_${table}_posid`,\n `AFTER INSERT ON ${table}\n WHEN ${NOT_APPLYING} AND ${ID_EXPR[table]} <= 0\nBEGIN\n SELECT RAISE(ABORT, '${GUARD_NONPOSITIVE_ID}');`,\n );\n}\n\n/** AFTER INSERT trigger refusing an explicit id above 2^53-1 (local writes only).\n *\n * An explicit id near INT64_MAX moves the table's AUTOINCREMENT counter\n * there, and every later omitted-id insert then fails \"database or disk is\n * full\" with no mu-side repair (`sqlite_sequence` is protected). Ids past\n * 2^53-1 also lose precision as JSON numbers. Aborts the statement, so the\n * counter bump rolls back with the row. */\nfunction hugeIdGuard(table: keyof typeof KEY_COLUMNS): CaptureTrigger {\n return trigger(\n `_cap_${table}_hugeid`,\n `AFTER INSERT ON ${table}\n WHEN ${NOT_APPLYING} AND ${ID_EXPR[table]} > ${MAX_SAFE_ID}\nBEGIN\n SELECT RAISE(ABORT, '${GUARD_HUGE_ID}');`,\n );\n}\n\n/** BEFORE UPDATE triggers: a note is append-only, an edge's `created_at`\n * is set once. A note's identity is (author, content, created_at), so an\n * edit would replay as a SECOND note (and a `{kind}`-only put matches no\n * row at all); an edge's fold reads only its first put, so a changed\n * `created_at` is captured but never replayed. Either way live and a\n * rebuild or peer diverge, so local writes refuse them. Gated on\n * `applying = 0`: ingest accepts what the log says, and a RAISE there\n * would roll back the segment and stall sync. A no-op rewrite passes. */\nconst NOTE_APPEND_ONLY_GUARD = trigger(\n \"_cap_task_notes_once\",\n `BEFORE UPDATE OF author, content, created_at, kind ON task_notes\n WHEN ${NOT_APPLYING}\n AND (NEW.author IS NOT OLD.author OR NEW.content IS NOT OLD.content\n OR NEW.created_at IS NOT OLD.created_at OR NEW.kind IS NOT OLD.kind)\nBEGIN\n SELECT RAISE(ABORT, 'mu: task_notes are append-only: author, content, created_at and kind are set once when the note is written; add a new note instead of changing it.');`,\n);\n\nconst EDGE_CREATED_GUARD = trigger(\n \"_cap_task_edges_created\",\n `BEFORE UPDATE OF created_at ON task_edges\n WHEN ${NOT_APPLYING} AND NEW.created_at IS NOT OLD.created_at\nBEGIN\n SELECT RAISE(ABORT, 'mu: task_edges.created_at is set once when the edge is added; remove the edge and add it again instead of changing it.');`,\n);\n\n// ─── Local-write guards (README Kernel § Schema) ──────────────────────\n//\n// Three rules hold for LOCAL writes only: a claim cannot steal an owned\n// task, a close needs evidence, a close to `done` refuses open\n// blockers. Each is gated on `applying = 0`, because ingest and import\n// accept what the log says: peers can merge into states no local write\n// allows (a close and its evidence are separate ops), and a RAISE during\n// ingest would roll back the segment and stall sync forever. `mu doctor`\n// reports such states instead.\n//\n// The RAISE texts are exported: the SDK maps them to typed errors\n// (TaskAlreadyOwnedError, CloseNeedsEvidenceError,\n// TaskHasOpenBlockersError) by exact message.\n\n/** `owner_id` moved from one agent to another without a release. */\nexport const GUARD_ALREADY_OWNED = \"mu: task already owned; release it first\";\n/** A task went CLOSED with no `kind = 'close'` note in the same op group. */\nexport const GUARD_NEEDS_EVIDENCE = 'mu: close needs evidence (--evidence \"<command + result>\")';\n/** A task went CLOSED/done while a blocker is still OPEN or IN_PROGRESS. */\nexport const GUARD_OPEN_BLOCKERS = \"mu: task has open blockers\";\n/** The largest explicit id a local INSERT may name: 2^53-1, JS's max safe integer. */\nconst MAX_SAFE_ID = Number.MAX_SAFE_INTEGER;\n/** An INSERT named an id above MAX_SAFE_ID (see hugeIdGuard). */\nexport const GUARD_HUGE_ID = `mu: explicit ids above 2^53-1 are refused`;\n/** An INSERT named an id <= 0 (see positiveIdGuard). */\nexport const GUARD_NONPOSITIVE_ID = \"mu: explicit non-positive ids are refused\";\n\n/** WHEN fragment: this UPDATE closes the task (OPEN/IN_PROGRESS -> CLOSED,\n * or a CLOSED task reclassified to another substate). */\nconst CLOSES_TASK =\n \"NEW.status = 'CLOSED' AND (OLD.status <> 'CLOSED' OR NEW.substate IS NOT OLD.substate)\";\n\n/** The three guards. Pure; spliced into buildTriggers. */\nfunction localGuards(): CaptureTrigger[] {\n const raise = (msg: string): string => `SELECT RAISE(ABORT, '${msg.replaceAll(\"'\", \"''\")}');`;\n // Evidence = a surviving `close` note of THIS task, filed in the\n // current op group. Identity is an exact compare of the note's op key\n // (`<task key>#<note id>`); a LIKE over the key would let task `a_b`\n // be satisfied by `axb`'s note, since `_` is a wildcard and ids allow it.\n const hasEvidence = `EXISTS (\n SELECT 1 FROM task_notes n\n JOIN ops o ON o.entity = 'note' AND o.op = 'put'\n AND o.key = ${taskKey(\"NEW.id\")} || '#' || n.id\n WHERE n.task_id = NEW.id AND n.kind = 'close'\n AND o.group_id = (SELECT group_id FROM op_ctx WHERE id = 1)\n )`;\n return [\n trigger(\n \"_cap_tasks_claim_cas\",\n `BEFORE UPDATE OF owner_id ON tasks\n WHEN ${NOT_APPLYING}\n AND OLD.owner_id IS NOT NULL AND NEW.owner_id IS NOT NULL AND NEW.owner_id IS NOT OLD.owner_id\nBEGIN\n ${raise(GUARD_ALREADY_OWNED)}`,\n ),\n trigger(\n \"_cap_tasks_close_evidence\",\n `BEFORE UPDATE OF status, substate ON tasks\n WHEN ${NOT_APPLYING}\n AND ${CLOSES_TASK}\n AND NOT ${hasEvidence}\nBEGIN\n ${raise(GUARD_NEEDS_EVIDENCE)}`,\n ),\n trigger(\n \"_cap_tasks_close_blockers\",\n `BEFORE UPDATE OF status, substate ON tasks\n WHEN ${NOT_APPLYING}\n AND ${CLOSES_TASK}\n AND NEW.substate = 'done'\n AND EXISTS (SELECT 1 FROM blockers WHERE task_id = NEW.id)\nBEGIN\n ${raise(GUARD_OPEN_BLOCKERS)}`,\n ),\n ];\n}\n\n/**\n * THE DELETE SUBTLETY\n * -------------------\n * Every other op can resolve its natural key lazily, because the row is\n * still there. DELETE cannot: by the time anything downstream looks,\n * the row is gone. So the key is captured INLINE, in the trigger, while\n * the row still exists.\n *\n * That alone is not enough, because of FK CASCADE. Empirically (this\n * was the thing most worth checking): SQLite FK `ON DELETE CASCADE`\n * DOES fire triggers on the cascaded child rows — and it does so\n * regardless of the `recursive_triggers` pragma, which governs only\n * trigger-initiated recursion, not FK actions. Good: destroying a\n * workstream captures its tasks, notes and edges without any explicit\n * walk in the SDK.\n *\n * The trap is ORDERING. With AFTER DELETE triggers, cascaded children\n * fire after the parent row is already deleted, so joining to the\n * parent to build the child's key yields nothing:\n *\n * DELETE FROM workstreams WHERE id = 1\n * -> edge op key \"<unresolved>-><unresolved>\"\n * -> note op key \"<unresolved>#100\"\n * -> task op key \"<unresolved>/t1\"\n *\n * Two mechanisms fix it together:\n *\n * 1. BEFORE DELETE, not AFTER. The row and its ancestors are all\n * still present when the trigger body runs, so `OLD.*` plus a\n * normal join resolves the key.\n * 2. The `op_dying` stash. BEFORE DELETE fixes the FIRST level only:\n * cascade children still fire after their parent's row is gone.\n * So each parent's BEFORE DELETE trigger records its own natural\n * key into `op_dying` before emitting, and the child key\n * resolvers (`wsKey` / `taskKey`) consult the stash when the live\n * join misses. SQLite fires a cascade's child AFTER DELETE triggers\n * before the parent's, so the parent's AFTER DELETE trigger removes\n * its stash row (`_cap_*_undie`): the table is empty at rest even\n * when a plain connection did the delete. INSERT OR REPLACE keyed\n * on (kind, id) covers a row whose stash outlived a crashed delete\n * (the rollback removes it too, so this is belt and braces).\n *\n * The alternative — having the parent trigger emit ops for its whole\n * subtree and suppressing the cascade triggers — also works and was\n * prototyped, but it duplicates the subtree walk in SQL four times and\n * breaks the moment a new FK is added. The stash is smaller and\n * self-maintaining.\n */\nconst DYING_STASH = (kind: \"workstream\" | \"task\", keyExpr: string): string =>\n `INSERT OR REPLACE INTO op_dying (kind, id, key) VALUES ('${kind}', OLD.id, ${keyExpr});`;\n\n/** Emitting trigger: `timing event ON table WHEN guard [AND extra]`. */\nfunction emitting(\n name: string,\n header: string,\n extraWhen: string | undefined,\n body: string,\n): CaptureTrigger {\n const when = extraWhen === undefined ? NOT_APPLYING : `${NOT_APPLYING}\\n AND (${extraWhen})`;\n return trigger(\n name,\n `${header}\n WHEN ${when}\nBEGIN\n ${body}`,\n );\n}\n\n/** Every capture trigger, in creation order. Pure. */\nfunction buildTriggers(): CaptureTrigger[] {\n const wsCols = CAPTURED_COLUMNS.workstreams;\n const taskCols = CAPTURED_COLUMNS.tasks;\n const noteCols = CAPTURED_COLUMNS.task_notes;\n const edgeCols = CAPTURED_COLUMNS.task_edges;\n\n const taskKeyNew = `${wsKey(\"NEW.workstream_id\")} || '/' || NEW.local_id`;\n const taskKeyOld = `${wsKey(\"OLD.workstream_id\")} || '/' || OLD.local_id`;\n const noteKeyNew = `${taskKey(\"NEW.task_id\")} || '#' || NEW.id`;\n const noteKeyOld = `${taskKey(\"OLD.task_id\")} || '#' || OLD.id`;\n const edgeKeyNew = `${taskKey(\"NEW.from_task_id\")} || '->' || ${taskKey(\"NEW.to_task_id\")}`;\n const edgeKeyOld = `${taskKey(\"OLD.from_task_id\")} || '->' || ${taskKey(\"OLD.to_task_id\")}`;\n\n const tables = [\"workstreams\", \"tasks\", \"task_notes\", \"task_edges\"] as const;\n return [\n // natural-key guards (see KEY_COLUMNS)\n ...tables.map(keyGuard),\n ...tables.map(insertGuard),\n ...tables.map(positiveIdGuard),\n ...tables.map(hugeIdGuard),\n NOTE_APPEND_ONLY_GUARD,\n EDGE_CREATED_GUARD,\n ...localGuards(),\n // The singleton op_ctx row must survive: the HLC clock reads\n // `now_ms` from it, and a missing row would NULL last_wall.\n trigger(\n \"_cap_op_ctx_nodelete\",\n `BEFORE DELETE ON op_ctx\nBEGIN\n SELECT RAISE(ABORT, 'mu: op_ctx is the op context row; it is never deleted.');`,\n ),\n\n // workstreams\n emitting(\n \"_cap_workstreams_ins\",\n \"AFTER INSERT ON workstreams\",\n undefined,\n emitOp(\"workstream\", \"put\", \"NEW.name\", fullPayload(wsCols)),\n ),\n emitting(\n \"_cap_workstreams_upd\",\n \"AFTER UPDATE ON workstreams\",\n anyChanged(wsCols),\n emitOp(\"workstream\", \"put\", \"NEW.name\", changedPayload(wsCols)),\n ),\n emitting(\n \"_cap_workstreams_del\",\n \"BEFORE DELETE ON workstreams\",\n undefined,\n `${DYING_STASH(\"workstream\", \"OLD.name\")}\n ${emitOp(\"workstream\", \"del\", \"OLD.name\", \"'{}'\")}`,\n ),\n undieTrigger(\"workstreams\", \"workstream\"),\n\n // tasks\n emitting(\n \"_cap_tasks_ins\",\n \"AFTER INSERT ON tasks\",\n undefined,\n emitOp(\"task\", \"put\", taskKeyNew, fullPayload(taskCols)),\n ),\n emitting(\n \"_cap_tasks_upd\",\n \"AFTER UPDATE ON tasks\",\n anyChanged(taskCols),\n emitOp(\"task\", \"put\", taskKeyNew, changedPayload(taskCols)),\n ),\n emitting(\n \"_cap_tasks_del\",\n \"BEFORE DELETE ON tasks\",\n undefined,\n `${DYING_STASH(\"task\", taskKeyOld)}\n ${emitOp(\"task\", \"del\", taskKeyOld, \"'{}'\")}`,\n ),\n undieTrigger(\"tasks\", \"task\"),\n\n // task_notes\n emitting(\n \"_cap_task_notes_ins\",\n \"AFTER INSERT ON task_notes\",\n undefined,\n emitOp(\"note\", \"put\", noteKeyNew, fullPayload(noteCols)),\n ),\n emitting(\n \"_cap_task_notes_upd\",\n \"AFTER UPDATE ON task_notes\",\n anyChanged(noteCols),\n emitOp(\"note\", \"put\", noteKeyNew, changedPayload(noteCols)),\n ),\n emitting(\n \"_cap_task_notes_del\",\n \"BEFORE DELETE ON task_notes\",\n undefined,\n emitOp(\"note\", \"del\", noteKeyOld, noteTombstonePayload(noteKeyOld, noteCols)),\n ),\n\n // task_edges\n emitting(\n \"_cap_task_edges_ins\",\n \"AFTER INSERT ON task_edges\",\n undefined,\n emitOp(\"edge\", \"put\", edgeKeyNew, fullPayload(edgeCols)),\n ),\n emitting(\n \"_cap_task_edges_upd\",\n \"AFTER UPDATE ON task_edges\",\n anyChanged(edgeCols),\n emitOp(\"edge\", \"put\", edgeKeyNew, changedPayload(edgeCols)),\n ),\n emitting(\n \"_cap_task_edges_del\",\n \"BEFORE DELETE ON task_edges\",\n undefined,\n emitOp(\"edge\", \"del\", edgeKeyOld, \"'{}'\"),\n ),\n ];\n}\n\n/** AFTER DELETE: drop this row's `op_dying` stash entry. SQLite fires a\n * cascade's child AFTER triggers before the parent's, and every child\n * key was resolved in a BEFORE trigger, so nothing needs the entry any\n * more. Keeps `op_dying` empty at rest, whoever did the delete. */\nfunction undieTrigger(table: string, kind: \"workstream\" | \"task\"): CaptureTrigger {\n return emitting(\n `_cap_${table}_undie`,\n `AFTER DELETE ON ${table}`,\n undefined,\n `DELETE FROM op_dying WHERE kind = '${kind}' AND id = OLD.id;`,\n );\n}\n\n/** The capture triggers, built once at module load. */\nexport const CAPTURE_TRIGGERS: readonly CaptureTrigger[] = buildTriggers();\n\n/** Every capture trigger as `CREATE TRIGGER …;` statements, in order. */\nexport const CAPTURE_TRIGGER_DDL = CAPTURE_TRIGGERS.map((t) => `${t.sql};`).join(\"\\n\\n\");\n\n/**\n * How many `total_changes()` the capture triggers themselves added while\n * stamping the ops of `groupId`. `mu sql --confirm-rows` subtracts this\n * from its delta so it can count user rows on the SAME capture-on run it\n * commits (no probe-then-rerun).\n *\n * Mirrors the trigger bodies above: every `emitOp` is exactly 3 changes\n * (the `op_ctx.now_ms` UPDATE, the `machine_identity` UPDATE, the ops\n * INSERT), and every workstream/task tombstone also writes 2 stash rows\n * (`DYING_STASH` in, `undieTrigger` out). Change a trigger body and this\n * must change too; test/sql-capture.test.ts pins it with cascading\n * deletes.\n */\nexport function captureBookkeepingChanges(db: CaptureDb, groupId: string): number {\n const row = db\n .prepare(\n `SELECT COUNT(*) AS ops,\n COALESCE(SUM(op = 'del' AND entity IN ('workstream', 'task')), 0) AS stashed\n FROM ops WHERE group_id = ?`,\n )\n .get(groupId) as { ops: number; stashed: number };\n return 3 * row.ops + 2 * row.stashed;\n}\n\n// ─── Installation ─────────────────────────────────────────────────────\n\n/** Names of the stored capture triggers (`_cap_` prefix; `_` escaped\n * because it is a LIKE wildcard). */\nconst STORED_TRIGGERS_SQL =\n \"SELECT name, sql FROM sqlite_master WHERE type = 'trigger' AND name LIKE '\\\\_cap\\\\_%' ESCAPE '\\\\' ORDER BY name\";\n\nconst sha256 = (text: string): string => createHash(\"sha256\").update(text).digest(\"hex\");\n\n/** sha256 over `name\\nsql\\n` of each trigger, sorted by name. */\nfunction checksum(triggers: readonly CaptureTrigger[]): string {\n const sorted = [...triggers].sort((a, b) => (a.name < b.name ? -1 : 1));\n return sha256(sorted.map((t) => `${t.name}\\n${t.sql}\\n`).join(\"\"));\n}\n\n/** Checksum of the triggers this build would install. */\nexport const GENERATED_TRIGGER_CHECKSUM = checksum(CAPTURE_TRIGGERS);\n\n/** The capture revision stamped in this file: 0 when the stamp is\n * missing (a DB from before the column existed), null when there is no\n * schema_version row at all (a fresh file). */\nexport function storedCaptureVersion(db: CaptureDb): number | null {\n const cols = db.prepare(\"SELECT name FROM pragma_table_info('schema_version')\").all() as {\n name: string;\n }[];\n if (!cols.some((c) => c.name === \"capture_version\")) {\n const hasTable = db\n .prepare(\"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'schema_version'\")\n .get();\n return hasTable === undefined ? null : 0;\n }\n const row = db.prepare(\"SELECT capture_version FROM schema_version WHERE id = 1\").get() as\n | { capture_version: number }\n | undefined;\n return row === undefined ? null : row.capture_version;\n}\n\n/** What `mu doctor` reports: the stamp, and the checksum of the trigger\n * SQL actually stored in the file next to the one this build generates. */\nexport function captureTriggerChecksums(db: CaptureDb): { stored: string; generated: string } {\n const stored = db.prepare(STORED_TRIGGERS_SQL).all() as CaptureTrigger[];\n return { stored: checksum(stored), generated: GENERATED_TRIGGER_CHECKSUM };\n}\n\n/** True when the stored triggers are byte-for-byte what this build\n * generates (same names, same SQL). */\nexport function captureTriggersCurrent(db: CaptureDb): boolean {\n const { stored, generated } = captureTriggerChecksums(db);\n return stored === generated;\n}\n\n/** Thrown by `installCapture` when the file's capture stamp is NEWER than\n * this build's: a later mu wrote triggers this one cannot vouch for, and\n * replacing them would silently downgrade every other machine's rules.\n * openDb turns it into SchemaTooNewError. */\nexport class CaptureTooNewError extends Error {\n override readonly name = \"CaptureTooNewError\";\n constructor(public readonly stored: number) {\n super(`capture revision ${stored} is newer than this build's ${CAPTURE_VERSION}`);\n }\n}\n\n/**\n * Make the capture triggers in this file current. Called once by\n * `openDb` on every non-readonly open, after the schema is applied.\n *\n * stamp == CAPTURE_VERSION nothing: no DDL, no write lock.\n * stamp > CAPTURE_VERSION CaptureTooNewError; the file is untouched.\n * stamp < CAPTURE_VERSION (or missing) drop every `_cap_*` trigger,\n * create the generated set, seed `op_ctx`,\n * and stamp: ONE BEGIN IMMEDIATE, so no\n * connection ever sees half a trigger set\n * and a crash leaves the old set and the old\n * stamp together. The stamp is re-read under\n * the lock: a concurrent opener that won the\n * race makes this a no-op, and a newer one\n * is still refused.\n */\nexport function installCapture(db: CaptureDb): void {\n if (db.inTransaction) throw new Error(\"installCapture must run outside a transaction\");\n const quick = storedCaptureVersion(db);\n if (quick === CAPTURE_VERSION) return;\n if (quick !== null && quick > CAPTURE_VERSION) throw new CaptureTooNewError(quick);\n\n db.exec(\"BEGIN IMMEDIATE\");\n try {\n installCaptureLocked(db);\n db.exec(\"COMMIT\");\n } catch (err) {\n try {\n db.exec(\"ROLLBACK\");\n } catch {}\n throw err;\n }\n}\n\n/**\n * The body of `installCapture` for a caller that already holds the write\n * lock inside its own transaction (db.ts `upgradeSchema`, which commits\n * the schema columns, the triggers and both stamps together). Re-reads the\n * stamp: equal is a no-op, newer throws CaptureTooNewError, older (or\n * missing) replaces every `_cap_*` trigger, seeds `op_ctx` and stamps.\n * Never begins, commits or rolls back.\n */\nexport function installCaptureLocked(db: CaptureDb): void {\n if (!db.inTransaction) throw new Error(\"installCaptureLocked must run inside a transaction\");\n const locked = storedCaptureVersion(db);\n if (locked !== null && locked > CAPTURE_VERSION) throw new CaptureTooNewError(locked);\n if (locked === CAPTURE_VERSION) return;\n const old = db.prepare(STORED_TRIGGERS_SQL).all() as { name: string }[];\n for (const t of old) db.exec(`DROP TRIGGER IF EXISTS \"${t.name}\"`);\n for (const t of CAPTURE_TRIGGERS) db.exec(t.sql);\n db.prepare(\"INSERT OR IGNORE INTO op_ctx (id) VALUES (1)\").run();\n db.prepare(\"UPDATE schema_version SET capture_version = ? WHERE id = 1\").run(CAPTURE_VERSION);\n}\n\n/** The slice of better-sqlite3's Database that capture needs. Declared\n * structurally rather than importing `Db` from db.ts, because db.ts\n * imports THIS module — a nominal import would be a cycle, and an\n * import cycle here silently breaks `node dist/cli.js`. */\nexport interface CaptureDb {\n readonly inTransaction: boolean;\n exec(sql: string): unknown;\n prepare(sql: string): {\n run(...params: readonly unknown[]): unknown;\n get(...params: readonly unknown[]): unknown;\n all(...params: readonly unknown[]): unknown[];\n };\n}\n\n/** One `mu doctor` row for the capture layer: the SQLite in use (>= 3.42),\n * the capture revision stamped in the file, and the sha256 of the stored\n * trigger SQL against the generated DDL. `sqliteVersion` is injectable\n * for tests. Shared by `mu doctor` and the TUI's doctor card. */\nexport function captureDoctorCheck(\n db: CaptureDb,\n sqliteVersion?: string,\n): { status: \"ok\" | \"warn\" | \"fail\"; detail: string } {\n const version =\n sqliteVersion ?? (db.prepare(\"SELECT sqlite_version() AS v\").get() as { v: string }).v;\n const stamp = storedCaptureVersion(db);\n const { stored, generated } = captureTriggerChecksums(db);\n const short = generated.slice(0, 12);\n if (sqliteTooOld(version)) {\n return {\n status: \"fail\",\n detail: `sqlite ${version} is below ${MIN_SQLITE.major}.${MIN_SQLITE.minor}: capture triggers abort every write`,\n };\n }\n if (stamp !== CAPTURE_VERSION) {\n return {\n status: \"fail\",\n detail: `capture ${stamp ?? \"unstamped\"} (code expects ${CAPTURE_VERSION}); sqlite ${version}`,\n };\n }\n if (stored !== generated) {\n return {\n status: \"fail\",\n detail: `capture ${stamp}; stored trigger checksum ${stored.slice(0, 12)} differs from generated ${short} (edited behind mu's back?); sqlite ${version}`,\n };\n }\n return { status: \"ok\", detail: `capture ${stamp}, triggers ${short}, sqlite ${version}` };\n}\n","// mu — the DDL of `remote_recovery`: a table and the two triggers that fill it.\n//\n// A finalized remote worker's agent row (host, worktree path and base all\n// recorded) is the only record of where its worktree lives. THE DATABASE\n// keeps what the row said, not the code that deletes it: an AFTER DELETE\n// trigger on `agents` writes the record from OLD.*, so it fires for every\n// deleter: the reaper, teardown, `mu sql DELETE FROM agents`, and the\n// `agents.workstream_id` CASCADE of a workstream delete (a peer's tombstone,\n// reinit, `mu sql DELETE FROM workstreams`). The record lives in the deleter's\n// transaction: a rollback takes it back.\n//\n// A cascade deletes the parent first, so the agent trigger can no longer read\n// the workstream's name: a BEFORE DELETE trigger on `workstreams` records its\n// agents while the parent is still there, and the agent trigger then finds\n// the record already written (INSERT OR IGNORE, keyed by incarnation).\n//\n// One row per ORIGINAL registry incarnation (`agent_id` = `agents.id`, never\n// reused): a name or workstream created again later is a different record.\n// `aside` is the exact path `closeRemoteWorktree` parks the tree at,\n// `<cwd>.mu-removing-<agent_id>` (asideOf, src/remote-agent.ts; a test pins\n// the two together). No foreign key and no op: machine-local, never synced,\n// rebuilt by nothing (src/rebuild.ts reports it lost). Local rows (no host)\n// and unfinalized ones leave nothing. This file is DDL only; the reader is\n// src/remote-recovery.ts. It imports nothing: db.ts splices it into\n// CURRENT_SCHEMA.\n\n/** Which deleter, as far as the op context says: a teardown, else the agent row was simply deleted. */\nconst REASON = `CASE COALESCE((SELECT intent FROM op_ctx WHERE id = 1), '')\n WHEN 'workstream.teardown' THEN 'teardown'\n ELSE 'reap' END`;\n\n/** Agent columns that make a row an owned remote worktree (`a` is the row's alias, or OLD). */\nconst OWNED = (a: string): string =>\n `${a}.host IS NOT NULL AND ${a}.cwd IS NOT NULL AND ${a}.cwd <> ''\n AND ${a}.base IS NOT NULL AND ${a}.base <> ''`;\n\nconst COLUMNS = `agent_id, workstream, workstream_id, workstream_created_at, name, pane_id, host, cwd,\n base, collected_head, aside, host_exec, host_repo, reason, preserved_at`;\n\nconst NOW = \"strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\";\n\n/** Trigger names an older v13 file may still hold; dropped by the upgrade (their bodies read the profile's repo). */\nexport const LEGACY_RECOVERY_TRIGGERS = [\n \"remote_recovery_agent_del\",\n \"remote_recovery_workstream_del\",\n];\n\nexport const REMOTE_RECOVERY_DDL = `\n-- remote_recovery: what a finalized remote worker row said about its\n-- worktree, written by triggers when the row is deleted (machine-local; see\n-- src/db-recovery.ts). No foreign key on purpose: it must outlive the agent,\n-- its workstream and its host profile. host_exec pins the profile's\n-- identity when the profile existed; host_repo is the worktree's repo. A receipt of the resource,\n-- not a live channel.\nCREATE TABLE IF NOT EXISTS remote_recovery (\n agent_id INTEGER PRIMARY KEY,\n workstream TEXT NOT NULL,\n workstream_id INTEGER NOT NULL,\n workstream_created_at TEXT NOT NULL,\n name TEXT NOT NULL,\n pane_id TEXT NOT NULL,\n host TEXT NOT NULL,\n cwd TEXT NOT NULL,\n base TEXT NOT NULL,\n collected_head TEXT,\n aside TEXT NOT NULL,\n host_exec TEXT,\n host_repo TEXT,\n reason TEXT NOT NULL CHECK (reason IN ('reap', 'teardown', 'workstream-delete')),\n preserved_at TEXT NOT NULL\n);\n\nCREATE TRIGGER IF NOT EXISTS remote_recovery_agent_del_v2\nAFTER DELETE ON agents\nWHEN ${OWNED(\"OLD\")}\n AND EXISTS (SELECT 1 FROM workstreams WHERE id = OLD.workstream_id)\nBEGIN\n INSERT OR IGNORE INTO remote_recovery (${COLUMNS})\n SELECT OLD.id, ws.name, ws.id, ws.created_at, OLD.name, OLD.pane_id, OLD.host, OLD.cwd,\n OLD.base, OLD.collected_head, OLD.cwd || '.mu-removing-' || OLD.id,\n (SELECT exec FROM host_profiles WHERE name = OLD.host),\n OLD.repo,\n ${REASON}, ${NOW}\n FROM workstreams ws WHERE ws.id = OLD.workstream_id;\nEND;\n\nCREATE TRIGGER IF NOT EXISTS remote_recovery_workstream_del_v2\nBEFORE DELETE ON workstreams\nBEGIN\n INSERT OR IGNORE INTO remote_recovery (${COLUMNS})\n SELECT a.id, OLD.name, OLD.id, OLD.created_at, a.name, a.pane_id, a.host, a.cwd,\n a.base, a.collected_head, a.cwd || '.mu-removing-' || a.id,\n (SELECT exec FROM host_profiles WHERE name = a.host),\n a.repo,\n 'workstream-delete', ${NOW}\n FROM agents a\n WHERE a.workstream_id = OLD.id AND ${OWNED(\"a\")};\nEND;\n`;\n","// mu — TaskStatus enum + helpers.\n//\n// Single source of truth for \"what statuses and substates can a task\n// have\". The schema (db.ts) seeds the task_substates lookup table from\n// TASK_SUBSTATE_ROWS, and a composite FK from tasks (status, substate)\n// into it is the only guard on both columns. Add a status or substate\n// here only.\n\nexport type TaskStatus = \"OPEN\" | \"IN_PROGRESS\" | \"CLOSED\";\n\n/** Every legal task status, in canonical order (matches the seeded\n * task_substates rows). Exported so CLI surfaces (`--status` validators,\n * --help text, error messages) name them all in one place; missing\n * one used to silently lie about the supported set. */\nexport const TASK_STATUSES: readonly TaskStatus[] = [\"OPEN\", \"IN_PROGRESS\", \"CLOSED\"];\n\nexport function isTaskStatus(s: string): s is TaskStatus {\n return (TASK_STATUSES as readonly string[]).includes(s);\n}\n\n/** Pipe-separated list of every legal status, e.g.\n * 'OPEN | IN_PROGRESS | CLOSED'. Single source of truth for\n * --help text and error messages so adding a new status doesn't\n * leave stale lists rotting in the CLI surface. */\nexport const TASK_STATUS_LIST = TASK_STATUSES.join(\" | \");\n\n/** Legal substates per status. `substate` qualifies `status` and never\n * touches edge semantics: only `status === \"CLOSED\"` satisfies a\n * `blocks` edge. Open: `parked` = set aside on purpose; `triage` = a\n * proposed task (e.g. a review finding) not yet accepted as work. Both\n * stay out of `ready` and `claim`. Closed: `rejected` = the proposal\n * was declined; `wontfix` = valid, but not worth doing. */\nexport const TASK_SUBSTATES = {\n OPEN: [\"todo\", \"parked\", \"triage\"],\n IN_PROGRESS: [\"active\"],\n CLOSED: [\"done\", \"rejected\", \"wontfix\", \"duplicate\", \"superseded\"],\n} as const satisfies Record<TaskStatus, readonly string[]>;\n\nexport type TaskSubstate = (typeof TASK_SUBSTATES)[TaskStatus][number];\n\n/** The substate a status takes when none is given. Never null: an\n * absent value must not carry meaning. */\nexport const DEFAULT_SUBSTATE: {\n readonly [S in TaskStatus]: (typeof TASK_SUBSTATES)[S][number];\n} = { OPEN: \"todo\", IN_PROGRESS: \"active\", CLOSED: \"done\" };\n\nexport interface TaskPair {\n status: TaskStatus;\n substate: TaskSubstate;\n}\n\n/** Rows for seeding task_substates: [status, substate, isDefault]. */\nexport const TASK_SUBSTATE_ROWS: ReadonlyArray<readonly [TaskStatus, TaskSubstate, 0 | 1]> =\n TASK_STATUSES.flatMap((status) =>\n TASK_SUBSTATES[status].map(\n (substate) => [status, substate, substate === DEFAULT_SUBSTATE[status] ? 1 : 0] as const,\n ),\n );\n\nexport function isValidPair(status: string, substate: string): boolean {\n if (!isTaskStatus(status)) return false;\n return (TASK_SUBSTATES[status] as readonly string[]).includes(substate);\n}\n\n/** Retired v9 statuses and the pair each one now means. */\nconst LEGACY_STATUS_PAIRS: Readonly<Record<string, TaskPair>> = {\n REJECTED: { status: \"CLOSED\", substate: \"rejected\" },\n DEFERRED: { status: \"OPEN\", substate: \"parked\" },\n};\n\n/** REJECTED -> {CLOSED, rejected}; DEFERRED -> {OPEN, parked}; else null. */\nexport function mapLegacyStatus(value: string): TaskPair | null {\n const pair = LEGACY_STATUS_PAIRS[value];\n return pair ? { ...pair } : null;\n}\n\n/** Map a stored/remote pair onto a legal one. Legacy status -> mapped pair\n * (ignores substate arg). Unknown status -> null. Known status with\n * unknown/missing/mismatched substate -> {status, DEFAULT_SUBSTATE[status]}. */\nexport function resolvePair(status: string, substate: unknown): TaskPair | null {\n const legacy = mapLegacyStatus(status);\n if (legacy) return legacy;\n if (!isTaskStatus(status)) return null;\n if (typeof substate === \"string\" && isValidPair(status, substate)) {\n return { status, substate: substate as TaskSubstate };\n }\n return { status, substate: DEFAULT_SUBSTATE[status] };\n}\n\n/** \"OPEN\" for default pairs, \"OPEN/parked\" otherwise. Shared by CLI + TUI. */\nexport function formatPair(pair: TaskPair): string {\n return pair.substate === DEFAULT_SUBSTATE[pair.status]\n ? pair.status\n : `${pair.status}/${pair.substate}`;\n}\n","// mu — the log surface over the **ops log**: appendLog / listLogs / latestSeq /\n// emitEvent / lastClaimActor / lastClaimEventAt.\n//\n// `ops` is the single append-only record of every change (VISION.md § 2b); a\n// log row is an op, read through the column mapping below:\n// kind -> ops.entity ('message' | 'event' | ...)\n// source -> ops.actor\n// workstream -> ops.key (natural key; '' = machine-wide)\n// payload -> ops.payload\n// seq -> ops.seq (AUTOINCREMENT cursor)\n//\n// `ops.hlc` is minted by `nextHlc` (src/hlc.ts). `group_id` is a fresh uuid per\n// entry, not the ambient **op context** group: these are hand-written log\n// lines and event breadcrumbs, each its own user-visible action. Rows written\n// through the capture triggers get the ambient group.\n\nimport { randomUUID } from \"node:crypto\";\nimport { type Db, SYNCED_ENTITIES } from \"./db.js\";\nimport { nextHlc } from \"./hlc.js\";\nimport { say } from \"./messages.js\";\nimport { singleLinePayload } from \"./segment-line.js\";\n\nexport type LogKind = \"message\" | \"event\" | \"broadcast\" | string;\n\nexport interface LogRow {\n /** Monotonic AUTOINCREMENT id. Use as the cursor for `--since`. */\n seq: number;\n /** Workstream this entry belongs to, or `null` for machine-wide. */\n workstreamName: string | null;\n /** Free TEXT: agent name, \"system\", \"user\", or anything a caller picks.\n * Captured ops that ran outside any actor context have no actor, and\n * render as \"system\" rather than the string \"null\". */\n source: string;\n /** Structured intent ('task.close', 'agent.spawn', ...). Null only for\n * operator-authored prose lines (`mu log \"<text>\"` / a `--kind` ledger),\n * which name no state change. The formatter in src/log-render.ts\n * renders from this — never from the payload text. */\n intent: string | null;\n /** Op group: every op of one operator action shares it. Surfaced so\n * `mu log` can print it and `mu log --group <id>` can filter to it. */\n group: string;\n /** 'put' (semantic partial update) or 'del' (tombstone). The formatter\n * needs it to tell \"edge removed\" from \"row touched\". */\n op: string;\n /** Free TEXT: \"message\" (default), \"event\" (auto state changes),\n * \"broadcast\" (explicit cross-agent), or any caller-defined value. */\n kind: LogKind;\n /** Free utf-8 string. May be JSON if the kind suggests structure. */\n payload: string;\n /** ISO 8601 timestamp set at insert time. */\n createdAt: string;\n}\n\ninterface RawLogRow {\n seq: number;\n /** `ops.key` verbatim (the natural key). '' means machine-wide. */\n workstream: string | null;\n /** `ops.actor`, which IS nullable: a captured op outside any actor\n * context has none. Normalised in `rowFromDb`. */\n source: string | null;\n intent: string | null;\n group_id: string;\n op: string;\n kind: string;\n payload: string;\n created_at: string;\n}\n\n/** SELECT clause mapping op columns back onto the log row shape.\n * `ops.key` already holds the operator-facing workstream name (the\n * natural key), so there is no join to do; '' means machine-wide and\n * is normalised back to NULL in `rowFromDb`. */\nconst SELECT_LOG_COLS = `\n l.seq AS seq,\n l.key AS workstream,\n l.actor AS source,\n l.intent AS intent,\n l.group_id AS group_id,\n l.op AS op,\n l.entity AS kind,\n l.payload AS payload,\n l.created_at AS created_at\n`;\n\nconst LOG_FROM_JOIN = \"FROM ops l\";\n\n// `mu log` reads EVERY op, no entity filter: docs/VOCABULARY.md § log entry\n// defines it as a rendered op, not a distinct table. A peer's synced ops\n// appear too, which machine-local prose events could not do. src/log-render.ts\n// renders each row from `intent`; captured payloads stay raw JSON.\n//\n// `latestSeq` deliberately shares this same \"no filter\" shape. When the\n// two disagreed, `mu log --tail` started its cursor past rows the\n// non-tail view had shown and silently skipped them.\n\n/** Scope a log query to one workstream.\n *\n * `ops.key` is the NATURAL key, so it is the bare workstream name for\n * workstream-scoped rows ('demo') and a qualified ref for everything\n * inside it ('demo/t1', 'demo/t1#1', 'demo/t2->demo/t1'). Matching\n * only `key = 'demo'` would therefore hide every task, note, and edge\n * op in the workstream — which is most of them. Exact-or-prefix is the\n * smallest predicate that reads \"belongs to this workstream\". */\nexport function workstreamScopeSql(column = \"l.key\"): string {\n return `(${column} = ? OR ${column} LIKE ? ESCAPE '\\\\')`;\n}\n\n/** Bind params for `workstreamScopeSql`. The LIKE pattern escapes the\n * operator-supplied name so a workstream containing '%' or '_' cannot\n * widen the match. */\nexport function workstreamScopeParams(workstream: string): [string, string] {\n const escaped = workstream.replace(/[\\\\%_]/g, (c) => `\\\\${c}`);\n return [workstream, `${escaped}/%`];\n}\n\n/** Every distinct `ops.entity`, read by skip-scanning idx_ops_entity_key\n * (one seek per entity, ~a dozen). `entity IN (…) AND key …` lets SQLite\n * seek (entity, key) without knowing the entity: the only index on key\n * leads with entity, and a bare `key` predicate scans all of ops. */\nexport const OPS_ENTITIES_SQL = `WITH RECURSIVE e(entity) AS (\n SELECT MIN(entity) FROM ops\n UNION ALL\n SELECT (SELECT MIN(entity) FROM ops WHERE entity > e.entity) FROM e WHERE e.entity IS NOT NULL\n ) SELECT entity FROM e WHERE entity IS NOT NULL`;\n\n/** Index-seekable superset of `workstreamScopeSql`: keys from '<ws>' up\n * to (not including) '<ws>0', '0' being the byte after '/'. AND it with\n * the exact-or-LIKE scope, never use it alone. */\nconst INDEXED_SCOPE_SQL = `l.entity IN (${OPS_ENTITIES_SQL}) AND l.key >= ? AND l.key < ?`;\n\n/** Above this many ops a workstream is \"busy\": its newest rows are\n * near the end of ops, so walking seq backwards finds them fast, while\n * the index seek would read and sort every one of its ops. Below it the\n * seek wins, and a quiet or unknown workstream no longer scans all of\n * ops looking for rows that are not there (f_ops_key_scan). */\nconst SMALL_SCOPE_OPS = 2000;\n\n/** Extra predicate + params that make a workstream-scoped ops read an\n * index seek, or null when the workstream is busy and the seq walk is\n * already cheap. The predicate only narrows to rows the scope already\n * matches, so the row set is unchanged. */\nfunction indexedScope(db: Db, workstream: string): { sql: string; params: string[] } | null {\n const params = [workstream, `${workstream}0`];\n const { n } = db\n .prepare(`SELECT COUNT(*) AS n FROM (SELECT 1 FROM ops l WHERE ${INDEXED_SCOPE_SQL} LIMIT ?)`)\n .get(...params, SMALL_SCOPE_OPS) as { n: number };\n return n < SMALL_SCOPE_OPS ? { sql: INDEXED_SCOPE_SQL, params } : null;\n}\n\n/** `workstreamScopeSql` (column `l.key`) plus, for a small workstream,\n * the indexed bound. Same row set, fewer rows visited. */\nexport function scopeFor(db: Db, workstream: string): { sql: string; params: string[] } {\n const scope = { sql: workstreamScopeSql(), params: workstreamScopeParams(workstream) };\n const indexed = indexedScope(db, workstream);\n if (indexed === null) return scope;\n return {\n sql: `${scope.sql} AND ${indexed.sql}`,\n params: [...scope.params, ...indexed.params],\n };\n}\n\n/** `workstreamScopeSql` limited to the newest SMALL_SCOPE_OPS ops: a\n * bounded seq-range read, enough for an active workstream's latest\n * rows. Callers that find too few fall back to `scopeFor`. */\nfunction recentScope(workstream: string): { sql: string; params: unknown[] } {\n return {\n sql: `${workstreamScopeSql()} AND l.seq > (SELECT COALESCE(MAX(seq), 0) FROM ops) - ?`,\n params: [...workstreamScopeParams(workstream), SMALL_SCOPE_OPS],\n };\n}\n\n/**\n * Hide parent-row TOUCH ops from the log surface.\n *\n * Adding a note or an edge bumps its task's `updated_at` so\n * `--sort recency` works. That UPDATE fires the tasks capture trigger,\n * producing a second op in the same group whose payload is ONLY\n * `updated_at` — no new information, and it renders as a duplicate of\n * the note/edge line the operator actually cares about. A `task note`\n * therefore appeared twice in `mu log`.\n *\n * These rows stay in `ops` (they are real state changes, and per-field\n * merge needs them); they are just not LOG LINES. The predicate is\n * shared by `listLogs` and `latestSeq` — those two MUST return the same\n * row set, or `--tail` starts its cursor past rows the non-tail view\n * already showed (hit in R4 and again in R7).\n *\n * `json_extract` is not used: SQLite's JSON1 is compiled in by default\n * for better-sqlite3, but a plain LENGTH test needs no extension and is\n * cheaper. A payload with only `updated_at` is always short.\n */\nconst TOUCH_OP_FILTER = `NOT (\n l.intent IS NOT NULL\n AND l.op = 'put'\n AND l.payload LIKE '{\"updated_at\":%'\n AND LENGTH(l.payload) < 45\n)`;\n\n/** Sentinel stored in `ops.key` for machine-wide entries (ops.key is\n * NOT NULL). Exported so the few call sites that query `ops` directly\n * agree with this module. */\nexport const MACHINE_WIDE_KEY = \"\";\n\n// ─── group-id prefix resolution ───────────────────────────────────\n//\n// Group ids are uuids, which nobody types. `mu log` prints 8-char\n// prefixes, so `mu log --group` accepts them. An unmatched prefix is an\n// error, not zero rows: \"no entries\" reads as \"this group did nothing\".\n// Same affordance git gives for abbreviated shas, and the same shape as\n// `src/tasks/id.ts`'s resolve-or-raise helpers.\n\n/** Raised when a group-id prefix matches more than one group.\n * Astronomically unlikely with uuids, but silently picking one of two\n * candidate groups is not an acceptable failure mode. */\nexport class GroupIdAmbiguousError extends Error {\n constructor(\n readonly prefix: string,\n readonly candidates: readonly string[],\n ) {\n super(\n say(\n \"log.group_ambiguous\",\n prefix,\n candidates.length,\n candidates.slice(0, 4).map((c) => c.slice(0, 12)),\n candidates.length > 4,\n ),\n );\n this.name = \"GroupIdAmbiguousError\";\n }\n}\n\n/** Raised when a group-id prefix matches no group. Exit 3. */\nexport class GroupNotFoundError extends Error {\n constructor(readonly prefix: string) {\n super(say(\"log.group_not_found\", prefix));\n this.name = \"GroupNotFoundError\";\n }\n}\n\n/**\n * Resolve a possibly-abbreviated group id to the full one.\n *\n * Returns null when nothing matches, so callers choose their own\n * not-found error (`mu log` raises `GroupNotFoundError`). Throws `GroupIdAmbiguousError` when a\n * prefix matches several groups — that is a genuine conflict the\n * operator must resolve, not something to guess at.\n *\n * An EXACT match always wins over prefix matching, so a full uuid can\n * never be shadowed by a longer id that happens to start with it.\n */\nexport function groupIdFromPrefix(db: Db, prefix: string): string | null {\n if (prefix === \"\") return null;\n const rows = db\n .prepare(\n // The range lets idx_ops_group seek; LIKE alone scanned it all.\n // char(0x10FFFF) sorts after any continuation of the prefix.\n `SELECT DISTINCT group_id AS groupId FROM ops\n WHERE group_id = @exact\n OR (group_id >= @exact AND group_id < @exact || char(1114111)\n AND group_id LIKE @prefix || '%' ESCAPE '\\\\')`,\n )\n .all({ exact: prefix, prefix: prefix.replace(/[\\\\%_]/g, (c) => `\\\\${c}`) }) as {\n groupId: string;\n }[];\n const exact = rows.find((r) => r.groupId === prefix);\n if (exact !== undefined) return exact.groupId;\n const first = rows[0];\n if (rows.length === 1 && first !== undefined) return first.groupId;\n if (rows.length === 0) return null;\n throw new GroupIdAmbiguousError(\n prefix,\n rows.map((r) => r.groupId),\n );\n}\n\n/** This machine's identity — the peer id every op is stamped with. */\nfunction machineId(db: Db): string {\n const row = db.prepare(\"SELECT machine_id FROM machine_identity WHERE id = 1\").get() as\n | { machine_id: string }\n | undefined;\n return row?.machine_id ?? \"unknown\";\n}\n\nfunction rowFromDb(row: RawLogRow): LogRow {\n return {\n seq: row.seq,\n workstreamName: row.workstream === MACHINE_WIDE_KEY ? null : row.workstream,\n source: row.source ?? \"system\",\n intent: row.intent,\n group: row.group_id,\n op: row.op,\n kind: row.kind,\n payload: row.payload,\n createdAt: row.created_at,\n };\n}\n\nexport interface AppendLogOptions {\n /** Workstream this entry belongs to. `null` for machine-wide. */\n workstream: string | null;\n /** Who emitted this. Agent name, \"system\", \"user\", or arbitrary. */\n source: string;\n /** Defaults to \"message\". */\n kind?: LogKind;\n /** Free utf-8. Multi-line allowed. */\n payload: string;\n /** Structured intent. Set by `emitEvent` for the local-only changes\n * no trigger can see. Stays null for operator-authored `mu log\n * write` lines, which are prose by nature and have no state change\n * to name. */\n intent?: string;\n}\n\n/** Kinds a log line may not use: the entities that sync AND project\n * into a portable table. A log line's kind is stored as `ops.entity`,\n * so `mu log \"x\" --kind task` wrote a prose op that sync, rebuild and\n * apply then read as a real task op (\"malformed task key\"), wedging\n * `mu rebuild` and every peer's ingest. 'message' syncs but projects\n * nowhere, so it stays allowed (it is the default). */\nconst RESERVED_LOG_KINDS: ReadonlySet<string> = new Set(\n SYNCED_ENTITIES.filter((e) => e !== \"message\"),\n);\n\n/** Raised by `appendLog` for a kind in RESERVED_LOG_KINDS. Usage lane\n * (exit 2): the operator picked a tag that names a projectable entity. */\nexport class LogKindReservedError extends Error {\n override readonly name = \"LogKindReservedError\";\n constructor(readonly kind: string) {\n super(say(\"log.kind_reserved\", kind, [...RESERVED_LOG_KINDS]));\n }\n}\n\n/**\n * Append a log entry. Returns the inserted row (with assigned `seq`).\n * Constant-time. Safe to call from any state-changing verb, inside or\n * outside a transaction (it nests as a savepoint).\n *\n * The HLC mint and the INSERT share one BEGIN IMMEDIATE transaction so\n * ops commit in hlc order: flushSegment publishes `hlc > lastPublished`,\n * and an op minted earlier but committed after a later one was flushed\n * would never be published.\n *\n * A JSON payload with line breaks is stored minified. A segment line\n * holds one op on one physical line and passes valid JSON through\n * verbatim, and a raw CR/LF in JSON can only be insignificant\n * whitespace, so nothing is lost.\n */\nexport function appendLog(db: Db, opts: AppendLogOptions): LogRow {\n const kind = opts.kind ?? \"message\";\n if (RESERVED_LOG_KINDS.has(kind)) throw new LogKindReservedError(kind);\n const createdAt = new Date().toISOString();\n // `ops.key` is the NATURAL key, so the workstream NAME goes in\n // verbatim — no resolution, and the op stays readable after the\n // workstream is destroyed (which is the point of an ops log).\n const key = opts.workstream ?? MACHINE_WIDE_KEY;\n const group = randomUUID();\n const payload = singleLinePayload(opts.payload);\n const insert = db.transaction(() =>\n db\n .prepare(\n `INSERT INTO ops (hlc, machine_id, group_id, actor, intent, entity, key, op, payload, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, 'put', ?, ?)`,\n )\n .run(\n nextHlc(db),\n machineId(db),\n group,\n opts.source,\n opts.intent ?? null,\n kind,\n key,\n payload,\n createdAt,\n ),\n );\n const result = insert.immediate();\n return {\n seq: Number(result.lastInsertRowid),\n workstreamName: opts.workstream,\n source: opts.source,\n intent: opts.intent ?? null,\n group,\n op: \"put\",\n kind,\n payload,\n createdAt,\n };\n}\n\nexport interface ListLogsOptions {\n /** Filter by workstream. `undefined` = every workstream + machine-wide.\n * `null` = ONLY machine-wide entries. */\n workstream?: string | null;\n /** Strictly > this seq. Use to resume a tail. */\n since?: number;\n /** At most this seq (with `since`: the exact range `since+1..upTo`). */\n upTo?: number;\n /** Cap the result. With `since`, returns the FIRST N matching (oldest\n * first). Without `since`, returns the LAST N (most recent),\n * re-sorted oldest-first. */\n limit?: number;\n source?: string;\n /** Filter by `ops.entity` (`kind` on a log row). */\n kind?: string;\n /** Filter by structured `ops.intent`, e.g. 'task.close'. */\n intent?: string;\n /** Filter to one op group (`ops.group_id`). */\n group?: string;\n}\n\n/**\n * List log entries. Always returns oldest-first. Use `since` for\n * cursor-based reads (the canonical tail pattern); use `limit` alone\n * for \"show me the most recent N\" reads.\n */\nexport function listLogs(db: Db, opts: ListLogsOptions = {}): LogRow[] {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (opts.workstream === null) {\n conditions.push(\"l.key = ?\");\n params.push(MACHINE_WIDE_KEY);\n }\n if (opts.since !== undefined) {\n conditions.push(\"l.seq > ?\");\n params.push(opts.since);\n }\n if (opts.upTo !== undefined) {\n conditions.push(\"l.seq <= ?\");\n params.push(opts.upTo);\n }\n if (opts.source === \"system\") {\n // rowFromDb renders a NULL actor as \"system\", so the filter must\n // match what the listing shows.\n conditions.push(\"(l.actor = ? OR l.actor IS NULL)\");\n params.push(opts.source);\n } else if (opts.source !== undefined) {\n conditions.push(\"l.actor = ?\");\n params.push(opts.source);\n }\n if (opts.kind !== undefined) {\n conditions.push(\"l.entity = ?\");\n params.push(opts.kind);\n }\n if (opts.intent !== undefined) {\n conditions.push(\"l.intent = ?\");\n params.push(opts.intent);\n }\n if (opts.group !== undefined) {\n conditions.push(\"l.group_id = ?\");\n params.push(opts.group);\n }\n // Same predicate as latestSeq — see TOUCH_OP_FILTER.\n conditions.push(TOUCH_OP_FILTER);\n const ws = opts.workstream ?? null;\n\n // Two query shapes:\n // - When `since` is set, ascending order is what we want directly.\n // - When `limit` is set without `since`, fetch the most-recent N\n // (descending) then reverse so the caller still sees oldest-first.\n if (opts.limit !== undefined && opts.since === undefined) {\n const limit = opts.limit;\n const newest = (scope: { sql: string; params: unknown[] }) =>\n db\n .prepare(\n `SELECT ${SELECT_LOG_COLS} ${LOG_FROM_JOIN} WHERE ${[scope.sql, ...conditions].join(\" AND \")} ORDER BY l.seq DESC LIMIT ?`,\n )\n .all(...scope.params, ...params, limit) as RawLogRow[];\n // An active workstream fills the limit from the newest ops; try\n // that cheap seq range first and fall back to scopeFor only when the\n // workstream is quiet. The first `limit` rows by seq DESC are the\n // same either way.\n let rowsDesc = newest(ws === null ? { sql: \"1\", params: [] } : recentScope(ws));\n if (ws !== null && rowsDesc.length < limit) rowsDesc = newest(scopeFor(db, ws));\n return rowsDesc.reverse().map(rowFromDb);\n }\n\n if (ws !== null) {\n const scope = scopeFor(db, ws);\n conditions.unshift(scope.sql);\n params.unshift(...scope.params);\n }\n const where = `WHERE ${conditions.join(\" AND \")}`;\n\n let sql = `SELECT ${SELECT_LOG_COLS} ${LOG_FROM_JOIN} ${where} ORDER BY l.seq ASC`;\n if (opts.limit !== undefined) {\n sql += \" LIMIT ?\";\n params.push(opts.limit);\n }\n const rows = db.prepare(sql).all(...params) as RawLogRow[];\n return rows.map(rowFromDb);\n}\n\n/** True when some visible op (one `listLogs` can return) has a seq in `from..to`, whatever its scope. */\nexport function anyVisibleBetween(db: Db, from: number, to: number): boolean {\n if (from > to) return false;\n return (\n db\n .prepare(`SELECT 1 FROM ops l WHERE l.seq BETWEEN ? AND ? AND ${TOUCH_OP_FILTER} LIMIT 1`)\n .get(from, to) !== undefined\n );\n}\n\n/**\n * Return the latest seq currently in the table (or 0 if empty). Used\n * by `mu log --tail` to start the cursor at \"now\" so the subscriber\n * only sees NEW entries unless they explicitly pass `--since 0`.\n */\nexport function latestSeq(db: Db, workstream?: string): number {\n // MUST stay consistent with listLogs' row set — this is the cursor\n // INTO it. When the two disagreed (a filter here that listLogs did\n // not apply, or vice versa) `--tail` started past rows the non-tail\n // view had already shown and silently skipped them.\n if (workstream === undefined) {\n const row = db.prepare(`SELECT MAX(seq) AS s FROM ops l WHERE ${TOUCH_OP_FILTER}`).get() as {\n s: number | null;\n };\n return row.s ?? 0;\n }\n const max = (scope: { sql: string; params: unknown[] }) =>\n (\n db\n .prepare(`SELECT MAX(seq) AS s FROM ops l WHERE ${scope.sql} AND ${TOUCH_OP_FILTER}`)\n .get(...scope.params) as { s: number | null }\n ).s;\n return max(recentScope(workstream)) ?? max(scopeFor(db, workstream)) ?? 0;\n}\n\n/**\n * Record a change that NO capture trigger can see.\n *\n * The triggers in src/capture.ts cover the four **portable** tables\n * (workstreams, tasks, task_edges, task_notes), so every task and\n * workstream mutation is already an op with a real `intent` and a real\n * natural key. Anything that mutates one of those tables must NOT call\n * this: it would write a second, prose, intent-less copy of a change the\n * trigger already captured with a real intent.\n *\n * What legitimately remains is state that lives OUTSIDE those tables:\n *\n * agent.* spawn / close / free / adopt / kick — `agents` is\n * machine-local (it holds `pane_id`), so there is no\n * trigger and never will be. The `worktrees` registry is\n * machine-local too (absolute paths); its changes ride the\n * agent.spawn / agent.close lines.\n * agent.stall a pure observation; nothing is mutated.\n *\n * `intent` is REQUIRED (and typed), not optional, because the whole\n * point is that these rows render through the same formatter as\n * captured ops. An intent-less op cannot be rendered without\n * prefix-matching prose, which is the brittleness\n * (`classifyEventVerb`, `CLAIM_EVENT_PREFIX`) the ops log deletes.\n *\n * These entities are deliberately NOT in SYNCED_ENTITIES: every one of\n * them describes something about THIS machine (a pane id, a filesystem\n * path) that is meaningless on a peer. They are still recorded, so\n * `mu log` and the TUI show them locally.\n */\nexport function emitEvent(\n db: Db,\n workstream: string | null,\n intent: LocalIntent,\n payload: string,\n source = \"system\",\n): void {\n appendLog(db, { workstream, source, kind: entityForIntent(intent), payload, intent });\n}\n\n/**\n * Intents for changes no trigger can capture. Closed union rather than\n * `string` so a typo is a compile error and the set stays auditable —\n * `mu log`'s formatter (src/log-render.ts) switches on exactly these.\n */\nexport type LocalIntent =\n | \"agent.spawn\"\n | \"agent.spawn_failed\"\n | \"agent.close\"\n | \"agent.adopt\"\n | \"agent.kick\"\n | \"agent.send\"\n | \"agent.abort\"\n | \"agent.stall\";\n\n/** Entity for a local intent: the token before the dot. Keeps\n * `entity`/`intent` consistent by construction instead of asking each\n * call site to pass both and agree. */\nfunction entityForIntent(intent: LocalIntent): string {\n const dot = intent.indexOf(\".\");\n return dot === -1 ? intent : intent.slice(0, dot);\n}\n\n// ─── claim attribution ─────────────────────────────────────────────\n//\n// mu once stored claim attribution as PROSE and re-parsed it: a\n// tab-delimited `task.claim<TAB><id><TAB>actor=<a><TAB>...` prefix was\n// bolted onto the payload precisely because prefix-matching the prose\n// was brittle. Two helpers then\n// existed only to put that prefix on and take it back off.\n//\n// The ops log makes all of it unnecessary. `withOpContext` seeds\n// op_ctx.actor, the capture trigger copies it into `ops.actor`, and\n// the intent is `task.claim`. So attribution is two indexed columns,\n// not a string to parse — including on the `--self` path, where\n// tasks.owner_id stays NULL by design and the payload therefore\n// CANNOT name the actor. Reading ops.actor is the whole fix.\n\n/** The most recent `task.claim` op for a task: its actor and when.\n *\n * `ops.key` is the natural key, so the task's own ops are keyed\n * '<ws>/<localId>' exactly — no LIKE, no wildcard escaping, and no\n * way for `foo` to cross-match `foo_2`. Unbounded by design: the old\n * limit=100 ceiling silently dropped attribution on long-lived\n * workstreams. */\nfunction lastClaimOp(\n db: Db,\n workstream: string,\n localId: string,\n): { actor: string | null; created_at: string } | null {\n const row = db\n .prepare(\n `SELECT actor, created_at FROM ops\n WHERE entity = 'task' AND key = ? AND intent = 'task.claim'\n ORDER BY seq DESC LIMIT 1`,\n )\n .get(`${workstream}/${localId}`) as { actor: string | null; created_at: string } | undefined;\n return row ?? null;\n}\n\n/**\n * Actor of the most recent claim of this task. Surfaces \"who is working\n * on this\" when `tasks.owner_id IS NULL` — the `--self` anonymous-claim\n * path. Null when the task was never claimed.\n */\nexport function lastClaimActor(db: Db, workstream: string, localId: string): string | null {\n return lastClaimOp(db, workstream, localId)?.actor ?? null;\n}\n\n/**\n * Find the `created_at` timestamp of the most recent claim of a task.\n *\n * Used by `mu task notes --since-claim` to slice the note timeline at\n * the most recent claim, so an operator dispatching a worker sees only\n * the post-claim notes (the spec was written before the claim; the\n * worker's progress lands after).\n *\n * Returns null when the task was never claimed — `--since-claim` then\n * degrades gracefully to no filter.\n */\nexport function lastClaimEventAt(db: Db, workstream: string, localId: string): string | null {\n return lastClaimOp(db, workstream, localId)?.created_at ?? null;\n}\n\n// ─── what an op IS ────────────────────────────────────────────────────\n//\n// Read `intent` (+ `key` + named payload fields), as src/log-render.ts does.\n// Never string-match a payload to decide what an op is: rewording breaks it.\n","// mu — the hybrid logical clock that orders every op (VOCABULARY § HLC).\n//\n// WHY NOT A WALL-CLOCK TIMESTAMP\n// ------------------------------\n// `ops` are merged across machines by last-writer-wins on `hlc`. If that\n// key were `new Date().toISOString()`, a laptop that sleeps for three\n// days and wakes with a clock skewed BEHIND the devserver would stamp\n// every new edit with a time that already passed — so on merge the\n// laptop's fresh work looks older than the devserver's stale work and is\n// silently discarded. No error, no conflict, just missing edits. That is\n// the #1 way homegrown sync corrupts data.\n//\n// An HLC uses wall time as a HINT and a logical counter as the truth:\n// the pair only ever increases, on this machine, forever. A backwards\n// clock jump costs ordering PRECISION (ops bunch up on one millisecond)\n// but never ordering CORRECTNESS.\n//\n// SERIALIZATION FORMAT\n// --------------------\n// A single lexicographically sortable TEXT, because `ORDER BY hlc` must\n// equal causal order and SQLite compares TEXT bytewise:\n//\n// <wall_ms:15 digits>.<counter:6 digits>.<machine_id>\n//\n// Example (wall=1780000000123, counter=7):\n//\n// 001780000000123.000007.9f1c8a2e-4b6d-4f0a-9c31-2f7c5d3e8a10\n//\n// - Both numeric parts are ZERO-PADDED to a fixed width. Without the\n// padding \"9\" would sort after \"10\" and the whole ordering guarantee\n// collapses.\n// - 15 digits of wall_ms covers every representable JS timestamp\n// (max 8_640_000_000_000_000 is 16 digits, but that is year 275760;\n// 15 digits runs to year 318857 — enough, and checked below).\n// - 6 digits of counter allows 1_000_000 ops inside one millisecond\n// before the clock advances. Overflow throws rather than wrapping,\n// because wrapping would silently regress the order.\n// - The separator is `.` — it cannot appear in a uuid (hex + `-` only),\n// so parsing is unambiguous and a machine_id can never spill into a\n// numeric field. It sorts below every digit and hex letter, so the\n// field boundary itself never perturbs the order.\n// - machine_id is the LAST field and is a tiebreak only: two machines\n// that mint the same (wall, counter) get a stable, arbitrary but\n// total order instead of comparing equal.\n//\n// PERSISTENCE\n// -----------\n// Every mu invocation is a separate short-lived process, so an\n// in-memory counter would reset constantly and mint duplicates. The\n// clock state lives in the singleton `machine_identity` row\n// (`last_wall`, `last_counter`), which is also where `machine_id`\n// already lives — one row, one read, one write.\n\nimport { type Db, prepareCached } from \"./db.js\";\n\n/** Zero-pad width for the wall-clock millisecond field. */\nconst WALL_WIDTH = 15;\n/** Zero-pad width for the logical counter field. */\nconst COUNTER_WIDTH = 6;\n/** Field separator. Cannot appear in a uuid. */\nconst SEP = \".\";\n/** Largest value each fixed-width field can hold. */\nconst MAX_WALL = 10 ** WALL_WIDTH - 1;\nconst MAX_COUNTER = 10 ** COUNTER_WIDTH - 1;\n\n/** A parsed HLC. Never construct by hand — use `parseHlc` or `formatHlc`. */\nexport interface Hlc {\n /** Wall-clock hint, milliseconds since the epoch. */\n wallMs: number;\n /** Logical counter; breaks ties within one `wallMs`. */\n counter: number;\n /** The machine that minted this HLC (`machine_identity.machine_id`). */\n machineId: string;\n}\n\n/** Thrown when a TEXT value is not a well-formed HLC. */\nexport class HlcParseError extends Error {\n constructor(readonly value: string) {\n super(`Malformed HLC: ${JSON.stringify(value)}`);\n this.name = \"HlcParseError\";\n }\n}\n\n/** Thrown when a field would not fit its fixed width. A counter\n * overflow means >1e6 ops landed in one millisecond; wrapping would\n * silently regress causal order, so we fail loudly instead. */\nexport class HlcOverflowError extends Error {\n constructor(\n readonly field: \"wall\" | \"counter\",\n readonly value: number,\n ) {\n super(\n field === \"counter\"\n ? `HLC counter overflow (${value} > ${MAX_COUNTER}): more than ${MAX_COUNTER + 1} ops in one millisecond`\n : `HLC wall-clock overflow (${value} > ${MAX_WALL}): system clock is far in the future`,\n );\n this.name = \"HlcOverflowError\";\n }\n}\n\n/** Thrown when the singleton `machine_identity` row is missing. */\nexport class MachineIdentityMissingError extends Error {\n constructor() {\n super(\"machine_identity row (id = 1) is missing; the DB was not opened via openDb()\");\n this.name = \"MachineIdentityMissingError\";\n }\n}\n\n/** Serialize `(wall_ms, counter, machine_id)` to the sortable TEXT form.\n * See the module comment for the exact shape and an example. */\nexport function formatHlc(hlc: Hlc): string {\n const { wallMs, counter, machineId } = hlc;\n if (!Number.isInteger(wallMs) || wallMs < 0) throw new HlcParseError(String(wallMs));\n if (!Number.isInteger(counter) || counter < 0) throw new HlcParseError(String(counter));\n if (wallMs > MAX_WALL) throw new HlcOverflowError(\"wall\", wallMs);\n if (counter > MAX_COUNTER) throw new HlcOverflowError(\"counter\", counter);\n if (machineId.length === 0 || machineId.includes(SEP)) throw new HlcParseError(machineId);\n return `${String(wallMs).padStart(WALL_WIDTH, \"0\")}${SEP}${String(counter).padStart(\n COUNTER_WIDTH,\n \"0\",\n )}${SEP}${machineId}`;\n}\n\n/** Inverse of `formatHlc`. Throws `HlcParseError` on anything else —\n * including the legacy placeholder `<iso>|<uuid>` shape. */\nexport function parseHlc(value: string): Hlc {\n const parts = value.split(SEP);\n if (parts.length !== 3) throw new HlcParseError(value);\n const [wall, counter, machineId] = parts;\n if (wall === undefined || counter === undefined || machineId === undefined) {\n throw new HlcParseError(value);\n }\n if (wall.length !== WALL_WIDTH || counter.length !== COUNTER_WIDTH || machineId.length === 0) {\n throw new HlcParseError(value);\n }\n if (!/^\\d+$/.test(wall) || !/^\\d+$/.test(counter)) throw new HlcParseError(value);\n return { wallMs: Number(wall), counter: Number(counter), machineId };\n}\n\n/** Total order over serialized HLCs: -1 / 0 / 1. Identical to bytewise\n * string comparison (that is the whole point of the format), so\n * `ORDER BY hlc` in SQL and `.sort(compareHlc)` in JS agree. */\nexport function compareHlc(a: string, b: string): -1 | 0 | 1 {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n}\n\ninterface ClockRow {\n machine_id: string;\n last_wall: number;\n last_counter: number;\n}\n\n/**\n * Mint the next HLC for this machine and persist the advance.\n *\n * now = wall clock ms\n * if now > last_wall: wall = now, counter = 0\n * else: wall = last_wall, counter = last_counter + 1\n *\n * The `else` branch is the monotonicity guarantee: when the clock\n * stalls, jumps backwards, or two ops land in the same millisecond, the\n * counter carries the order instead.\n *\n * ATOMICITY — a SINGLE `UPDATE … RETURNING` statement, not an explicit\n * transaction. SQLite makes one statement atomic and takes the write\n * lock for its duration, so the read-modify-write cannot interleave\n * with a competing `mu` process; `busy_timeout = 5000` (set by openDb)\n * makes the loser wait rather than fail. A read-then-write pair inside\n * BEGIN DEFERRED would be upgrade-deadlock prone under the parallel\n * spawn fan-out, and BEGIN IMMEDIATE would be a strictly bigger lock\n * for the same effect. `receiveHlc` cannot use this trick (its\n * three-way max is not expressible as one clean statement) so it does\n * take BEGIN IMMEDIATE.\n *\n * @param now Injectable clock, for tests. Defaults to `Date.now()`.\n */\nexport function nextHlc(db: Db, now: number = Date.now()): string {\n const row = db\n .prepare(\n `UPDATE machine_identity\n SET last_wall = MAX(last_wall, @now),\n last_counter = CASE WHEN @now > last_wall THEN 0 ELSE last_counter + 1 END\n WHERE id = 1\n RETURNING machine_id, last_wall, last_counter`,\n )\n .get({ now: Math.floor(now) }) as ClockRow | undefined;\n if (!row) throw new MachineIdentityMissingError();\n return formatHlc({ wallMs: row.last_wall, counter: row.last_counter, machineId: row.machine_id });\n}\n\n/**\n * Advance the local clock past a peer's HLC while INGESTING their op,\n * and return the local HLC that now dominates it. This is what makes\n * \"laptop edits after seeing the devserver's op\" order correctly: the\n * laptop's next mint is guaranteed greater than anything it has seen,\n * even if its own wall clock is days behind.\n *\n * wall = max(local_wall, remote_wall, now)\n *\n * The counter has four explicit cases, by which of the three won:\n * - `now` strictly won -> counter = 0 (fresh millisecond)\n * - local and remote tie at max -> counter = max(local_c, remote_c) + 1\n * - only local is at max -> counter = local_c + 1\n * - only remote is at max -> counter = remote_c + 1\n *\n * A remote HLC from the PAST therefore never drags the local clock\n * backwards — `max` keeps `local_wall`, and the counter still steps.\n *\n * ATOMICITY — BEGIN IMMEDIATE (`.immediate()`), because the three-way\n * max needs the old row in JS before the new value can be computed, so\n * unlike `nextHlc` it genuinely is a read-then-write pair.\n *\n * @param now Injectable clock, for tests. Defaults to `Date.now()`.\n */\nexport function receiveHlc(db: Db, remoteHlc: string, now: number = Date.now()): string {\n const remote = parseHlc(remoteHlc);\n const wallNow = Math.floor(now);\n const read = prepareCached(\n db,\n \"SELECT machine_id, last_wall, last_counter FROM machine_identity WHERE id = 1\",\n );\n const write = prepareCached(\n db,\n \"UPDATE machine_identity SET last_wall = @wall, last_counter = @counter WHERE id = 1\",\n );\n\n const advance = (): string => {\n const row = read.get() as ClockRow | undefined;\n if (!row) throw new MachineIdentityMissingError();\n const wall = Math.max(row.last_wall, remote.wallMs, wallNow);\n const localAtMax = row.last_wall === wall;\n const remoteAtMax = remote.wallMs === wall;\n let counter: number;\n if (!localAtMax && !remoteAtMax) {\n counter = 0; // `now` strictly won: a genuinely fresh millisecond.\n } else if (localAtMax && remoteAtMax) {\n counter = Math.max(row.last_counter, remote.counter) + 1;\n } else if (localAtMax) {\n counter = row.last_counter + 1;\n } else {\n counter = remote.counter + 1;\n }\n if (counter > MAX_COUNTER) throw new HlcOverflowError(\"counter\", counter);\n write.run({ wall, counter });\n return formatHlc({ wallMs: wall, counter, machineId: row.machine_id });\n };\n\n // Inside a caller's transaction (ingest applies a whole segment in\n // one) the write lock is already held, so a savepoint per op would buy\n // nothing.\n if (db.inTransaction) return advance();\n return db.transaction(advance).immediate();\n}\n","// mu — the segment line: its version rules, framing, encode and decode.\n// Split out of segments.ts (1500-LOC cap); segments.ts re-exports the\n// public names. Pure: no filesystem, no DB.\n\nimport { crc32 } from \"node:zlib\";\n\n/** The segment line format this build WRITES. Bumped only on a breaking\n * shape change. */\nexport const SEGMENT_FORMAT_VERSION = 2;\n\n/** The line versions this build READS. The version is checked per line,\n * and a line of any other version (v1 included) is REFUSED rather than\n * guessed at. */\nexport const SEGMENT_READ_VERSIONS: readonly number[] = [2];\n\n/** One serialized op, as it appears on a line of a segment. */\nexport interface SegmentLine {\n v: number;\n hlc: string;\n machine: string;\n group: string;\n intent: string | null;\n actor: string | null;\n entity: string;\n key: string;\n op: \"put\" | \"del\";\n payload: unknown;\n crc: string;\n}\n\n/** Why a segment line was rejected. Reported, never silently swallowed. */\nexport type SegmentDefectKind =\n | \"torn-write\"\n | \"manifest-mismatch\"\n | \"crc-mismatch\"\n | \"non-monotonic-hlc\"\n | \"unknown-version\"\n | \"malformed-shape\"\n | \"entity-not-synced\"\n | \"duplicate-op\";\n\nexport interface SegmentDefect {\n kind: SegmentDefectKind;\n /** 1-based line number within the segment. */\n line: number;\n detail: string;\n /** The format version found, for an `unknown-version` defect. */\n version?: number;\n}\n\n// ─── framing ──────────────────────────────────────────────────────────\n\n/**\n * Canonical serialization the crc is computed over.\n *\n * Field order is FIXED here rather than taken from object key order, so\n * two machines (or two Node versions) cannot disagree about the bytes and\n * produce a spurious mismatch. `payload` is embedded as its stored JSON\n * TEXT, verbatim, for the same reason: re-serializing a parsed object\n * risks key reordering and number reformatting.\n */\nfunction canonicalBytes(line: Omit<SegmentLine, \"crc\">, payloadText: string): string {\n return [\n String(line.v),\n line.hlc,\n line.machine,\n line.group,\n line.intent ?? \"\",\n line.actor ?? \"\",\n line.entity,\n line.key,\n line.op,\n payloadText,\n ].join(\"\\u001f\"); // Unit Separator: cannot occur in any of these fields\n}\n\nfunction computeCrc(line: Omit<SegmentLine, \"crc\">, payloadText: string): string {\n return crc32(canonicalBytes(line, payloadText)).toString(16).padStart(8, \"0\");\n}\n\n/**\n * `ops.payload` is TEXT that is *usually* JSON but is not guaranteed to\n * be: `appendLog` has always accepted a bare prose payload (entity\n * 'message' via `mu log \"text\"`), and pre-1.0 rows carry plenty of it.\n * Embedding such text raw produced `\"payload\":Added 5 tasks, ...` — a\n * line that is not JSON at all, which every later read then reported as\n * a torn write, on every single mu invocation, forever (the segment is\n * regenerated from `ops`, so the repair re-emitted the same bad bytes).\n *\n * So: pass valid JSON through (minus line breaks, see singleLinePayload),\n * and encode anything else as a JSON string. A stored JSON string SCALAR\n * (`mu log '\"hello\"'`) is encoded too: passed through, it would read back\n * as a string and `storedPayloadFor` could not tell it from wrapped prose.\n */\nfunction payloadTextFor(payload: string): string {\n let value: unknown;\n try {\n value = JSON.parse(payload);\n } catch {\n return JSON.stringify(payload);\n }\n if (typeof value === \"string\") return JSON.stringify(payload);\n return singleLinePayload(payload);\n}\n\n/** `payload` with its line breaks removed when it is JSON spanning\n * several lines, else unchanged (prose keeps its newlines: the segment\n * JSON-escapes it). Not JSON.stringify(JSON.parse()): that rounds big\n * numbers and merges duplicate keys. JSON strings cannot hold a raw\n * CR/LF, so each one, with the whitespace around it, sits between\n * tokens, and two adjacent JSON tokens are never both literals.\n *\n * `appendLog` stores new rows this way; the encoder applies it again so\n * a row stored before that fix still fits on one segment line. */\nexport function singleLinePayload(payload: string): string {\n if (!/[\\r\\n]/.test(payload)) return payload;\n try {\n JSON.parse(payload);\n } catch {\n return payload;\n }\n return payload.replace(/[ \\t\\r\\n]*[\\r\\n][ \\t\\r\\n]*/g, \"\");\n}\n\n/** Serialize one op row to a segment line (without its trailing newline). */\nexport function encodeSegmentLine(\n op: {\n hlc: string;\n machineId: string;\n groupId: string;\n intent: string | null;\n actor: string | null;\n entity: string;\n key: string;\n op: \"put\" | \"del\";\n payload: string;\n },\n /** Test seam: forge a line of another version (the crc covers `v`). */\n version: number = SEGMENT_FORMAT_VERSION,\n): string {\n const base: Omit<SegmentLine, \"crc\"> = {\n v: version,\n hlc: op.hlc,\n machine: op.machineId,\n group: op.groupId,\n intent: op.intent,\n actor: op.actor,\n entity: op.entity,\n key: op.key,\n op: op.op,\n payload: null, // replaced below; kept out of the crc input shape\n };\n const payloadText = payloadTextFor(op.payload);\n // A raw CR/LF would split one op over several physical lines, which\n // every reader reports as a torn write. payloadTextFor removes them;\n // this is defensive.\n if (/[\\r\\n]/.test(payloadText))\n throw new Error(`segment line: payload of op ${op.hlc} contains a line break`);\n const crc = computeCrc(base, payloadText);\n // Assemble by hand so `payload` is embedded as raw JSON rather than\n // being re-encoded, keeping the bytes the crc covered.\n return `{\"v\":${base.v},\"hlc\":${JSON.stringify(base.hlc)},\"machine\":${JSON.stringify(\n base.machine,\n )},\"group\":${JSON.stringify(base.group)},\"intent\":${JSON.stringify(\n base.intent,\n )},\"actor\":${JSON.stringify(base.actor)},\"entity\":${JSON.stringify(\n base.entity,\n )},\"key\":${JSON.stringify(base.key)},\"op\":${JSON.stringify(\n base.op,\n )},\"payload\":${payloadText},\"crc\":${JSON.stringify(crc)}}`;\n}\n\n/** Outcome of decoding one line. */\nexport type DecodeResult =\n | { ok: true; line: SegmentLine; payloadText: string }\n | { ok: false; kind: SegmentDefectKind; detail: string; version?: number };\n\n/**\n * Decode and verify one line.\n *\n * Layers 1 and 2 both live here. Layer 1 (JSON.parse) is what actually\n * fires in practice — a truncated transfer leaves a partial line, which\n * cannot parse. Layer 2 (crc) only catches damage that leaves valid JSON,\n * i.e. bit rot inside a string or number.\n */\nexport function decodeLine(\n raw: string,\n readVersions: readonly number[] = SEGMENT_READ_VERSIONS,\n): DecodeResult {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n // LAYER 1: torn write. The dominant failure mode, and free.\n //\n // But only call it TORN when the line actually looks cut off. A\n // complete line that does not parse has a different cause (a writer\n // bug, or a hand edit) and a different remediation, and mislabelling\n // it sends the reader hunting for a crash-during-write that never\n // happened.\n const detail = err instanceof Error ? err.message : String(err);\n return looksComplete(raw)\n ? { ok: false, kind: \"malformed-shape\", detail: `complete line is not valid JSON: ${detail}` }\n : { ok: false, kind: \"torn-write\", detail };\n }\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return { ok: false, kind: \"malformed-shape\", detail: \"line is not a JSON object\" };\n }\n const obj = parsed as Record<string, unknown>;\n\n if (typeof obj.v !== \"number\") {\n return { ok: false, kind: \"malformed-shape\", detail: \"missing numeric 'v'\" };\n }\n if (!readVersions.includes(obj.v)) {\n // Refuse rather than guess: another version may mean different\n // things by the same field names.\n return {\n ok: false,\n kind: \"unknown-version\",\n detail: `segment format v${obj.v}, this mu understands ${readVersions.map((v) => `v${v}`).join(\", \")}`,\n version: obj.v,\n };\n }\n for (const field of [\"hlc\", \"machine\", \"group\", \"entity\", \"key\", \"op\", \"crc\"]) {\n if (typeof obj[field] !== \"string\") {\n return { ok: false, kind: \"malformed-shape\", detail: `missing string '${field}'` };\n }\n }\n const opKind = obj.op;\n if (opKind !== \"put\" && opKind !== \"del\") {\n return { ok: false, kind: \"malformed-shape\", detail: `bad op '${String(opKind)}'` };\n }\n if (!(\"payload\" in obj)) {\n return { ok: false, kind: \"malformed-shape\", detail: \"missing 'payload'\" };\n }\n\n // Recover the payload's ORIGINAL text from the raw line so the crc is\n // computed over the same bytes the writer covered. Re-serializing the\n // parsed value could reorder keys and would false-positive.\n const payloadText = extractPayloadText(raw);\n if (payloadText === null) {\n return { ok: false, kind: \"malformed-shape\", detail: \"could not locate payload text\" };\n }\n\n const line: SegmentLine = {\n v: obj.v,\n hlc: obj.hlc as string,\n machine: obj.machine as string,\n group: obj.group as string,\n intent: typeof obj.intent === \"string\" ? obj.intent : null,\n actor: typeof obj.actor === \"string\" ? obj.actor : null,\n entity: obj.entity as string,\n key: obj.key as string,\n op: opKind,\n payload: obj.payload,\n crc: obj.crc as string,\n };\n\n // LAYER 2: crc over the canonical bytes. Belt-and-braces.\n const expected = computeCrc({ ...line, payload: null }, payloadText);\n if (expected !== line.crc) {\n return {\n ok: false,\n kind: \"crc-mismatch\",\n detail: `crc ${line.crc} != computed ${expected} (bit rot?)`,\n };\n }\n return { ok: true, line, payloadText: storedPayloadFor(line, payloadText) };\n}\n\n/**\n * The text to store back into `ops.payload`, undoing the wrapping\n * `payloadTextFor` applied on the way out, so a peer's ops table holds\n * the bytes the origin's does and `mu log` renders a prose message as\n * prose rather than as a quoted string.\n *\n * The inverse is exact because the wrap rule is: wrap iff the stored\n * text is NOT valid JSON or is a JSON string. So unwrap iff the line's\n * payload is a string whose contents are NOT valid JSON or ARE a JSON\n * string. Anything else was passed through and must stay that way: a\n * line written before string scalars were wrapped carries the stored\n * `\"123\"` as the string `123`, which this keeps as `\"123\"`.\n */\nfunction storedPayloadFor(line: SegmentLine, payloadText: string): string {\n if (typeof line.payload !== \"string\") return payloadText;\n try {\n return typeof JSON.parse(line.payload) === \"string\" ? line.payload : payloadText;\n } catch {\n return line.payload;\n }\n}\n\n/** Whether a line carries the trailing framing `encodeSegmentLine`\n * always writes. A transfer caught in flight cannot: it stops wherever\n * the bytes stopped. */\nfunction looksComplete(raw: string): boolean {\n return raw.trimEnd().endsWith(\"}\") && raw.includes(',\"crc\":\"');\n}\n\n/** Slice out the raw `\"payload\":<json>` text, between its key and the\n * trailing `,\"crc\":`. Written by `encodeSegmentLine`, so the anchors are\n * exact rather than heuristic. */\nfunction extractPayloadText(raw: string): string | null {\n const start = raw.indexOf('\"payload\":');\n if (start < 0) return null;\n const end = raw.lastIndexOf(',\"crc\":');\n if (end <= start) return null;\n return raw.slice(start + '\"payload\":'.length, end);\n}\n","// mu — multiplexer backend hub.\n//\n// Concrete backends live in the cohesive src/mux/ cluster: one file per\n// backend plus shared types and detection. This root file is the public\n// `import { ... } from \"./mux.js\"` surface.\n//\n// A \"mux\" is the terminal multiplexer that owns panes. Exactly one is\n// active per mu invocation, resolved by `activeMux()`. Everything\n// backend-specific — topology, the send protocol, capture, pane-id\n// validation, identity fallback — lives behind `MuxBackend`.\n//\n// See docs/VOCABULARY.md § \"mux backend\" and docs/architecture/mux.md\n// § \"One mux session per workstream\".\n\nexport {\n type AttachTarget,\n activeMux,\n attachShellLine,\n type CaptureOptions,\n detectMux,\n type EnsureSessionResult,\n HerdrCommandOverrideError,\n HerdrError,\n HerdrSyntaxError,\n HerdrUnsupportedCliError,\n HerdrWorkspaceGroupCloseError,\n herdrBackend,\n isHerdrStatusUsable,\n MU_PLACEHOLDER_WINDOW,\n type MuxBackend,\n type MuxBackendName,\n type MuxCommand,\n type MuxDiagnostics,\n MuxError,\n type MuxHealth,\n type MuxPane,\n type MuxPaneStatus,\n muxByName,\n NoMultiplexerError,\n PaneNotFoundError,\n type PaneResult,\n resetHerdrExecutor,\n resetMux,\n type SendOptions,\n type SendWarning,\n type SpawnAgentPaneOptions,\n setHerdrExecutor,\n setMuxForTests,\n tmuxAttachMode,\n tmuxBackend,\n} from \"./mux/index.js\";\n","// Run a binary and capture its output, never rejecting on a non-zero exit.\n// Shared by the tmux, herdr and murmur-status executors. Uses\n// node:child_process rather than execa: execa's ~110 modules cost 25-40 ms\n// of import time on every process that touches a multiplexer.\n\nimport { type ChildProcess, execFile, spawn } from \"node:child_process\";\nimport { setTimeout as sleep } from \"node:timers/promises\";\nimport { onExit } from \"signal-exit\";\n\nexport interface ExecFileResult {\n stdout: string;\n stderr: string;\n /** Numeric exit code; null on spawn failure (ENOENT), signal, or timeout. */\n exitCode: number | null;\n}\n\n/** execa's default `maxBuffer` (100 MiB); execFile's own default is 1 MiB. */\nconst MAX_BUFFER = 100 * 1024 * 1024;\n\n/** Drop one trailing LF or CRLF (what execa does), not all trailing whitespace. */\nfunction stripFinalNewline(s: string): string {\n if (s.endsWith(\"\\r\\n\")) return s.slice(0, -2);\n if (s.endsWith(\"\\n\")) return s.slice(0, -1);\n return s;\n}\n\n// execa killed in-flight children when the parent exited or was signalled\n// (`cleanup: true`, via signal-exit); a bare execFile does not, so an orphaned\n// tmux client or murmur process would outlive mu and its timeout timer. Reuse\n// signal-exit (what execa used) so every catchable signal is covered and the\n// parent still terminates correctly next to other signal-exit users. The hook\n// is installed only while a child is live.\nconst live = new Set<ChildProcess>();\nlet removeExitHook: (() => void) | undefined;\n\n/** Children spawned as their own process group leader (`execGroupCapture`). */\nconst groups = new WeakSet<ChildProcess>();\n\nfunction killLive(): void {\n for (const c of live) {\n if (groups.has(c) && c.pid !== undefined) signalGroup(c.pid, \"SIGKILL\");\n else c.kill(\"SIGKILL\");\n }\n}\n\n/** Signal a whole process group; false once no member is left (or it was never ours to signal). */\nfunction signalGroup(pgid: number, sig: NodeJS.Signals | 0): boolean {\n try {\n process.kill(-pgid, sig);\n return true;\n } catch {\n return false;\n }\n}\n\n/** TERM the group, give it `graceMs`, then KILL; resolves once no member is left. */\nasync function reapGroup(pgid: number, graceMs: number): Promise<void> {\n if (!signalGroup(pgid, 0)) return;\n signalGroup(pgid, \"SIGTERM\");\n for (let waited = 0; waited < graceMs && signalGroup(pgid, 0); waited += 10) await sleep(10);\n while (signalGroup(pgid, \"SIGKILL\")) await sleep(10);\n}\n\nfunction install(): void {\n removeExitHook = onExit(killLive);\n}\n\nfunction uninstall(): void {\n removeExitHook?.();\n removeExitHook = undefined;\n}\n\n/**\n * Register `child` for kill-on-parent-exit. Returns the release. A plain\n * child releases itself on close/error; a group (`holdUntil`) is released by\n * its caller once the reap has finished, so the hook still covers the\n * interval where the shell is gone but the group is being reaped.\n */\nfunction track(child: ChildProcess, holdUntil = false): () => void {\n if (live.size === 0) install();\n live.add(child);\n const done = (): void => {\n if (!live.delete(child)) return;\n if (live.size === 0) uninstall();\n };\n if (!holdUntil) {\n child.once(\"close\", done);\n child.once(\"error\", done);\n }\n return done;\n}\n\nexport function execFileCapture(\n cmd: string,\n args: readonly string[],\n opts: { timeoutMs?: number } = {},\n): Promise<ExecFileResult> {\n return new Promise((resolve) => {\n const child = execFile(\n cmd,\n [...args],\n {\n encoding: \"utf8\",\n maxBuffer: MAX_BUFFER,\n ...(opts.timeoutMs !== undefined ? { timeout: opts.timeoutMs, killSignal: \"SIGKILL\" } : {}),\n },\n (err, stdout, stderr) => {\n const code = err && \"code\" in err && typeof err.code === \"number\" ? err.code : null;\n resolve({\n stdout: stripFinalNewline(stdout ?? \"\"),\n stderr: stripFinalNewline(stderr ?? \"\"),\n exitCode: err ? code : 0,\n });\n },\n );\n // execa closes stdin when no input is given; do the same so children\n // that read stdin see EOF instead of hanging.\n child.stdin?.end();\n track(child);\n });\n}\n\n/**\n * Like execFileCapture, but the command owns a process group and everything it\n * started: on timeout, when the command exits (a leftover background job\n * included) and when the parent exits, the whole group is terminated (TERM,\n * then KILL after `graceMs`) BEFORE the promise settles. For a shell template\n * whose descendants (a transport) must not outlive the call. The child is\n * detached from the controlling terminal. A descendant that setsid()s away is\n * out of reach. The parent-exit hook stays installed until the reap is done,\n * not just until the shell closes.\n *\n * `onSpawn(pgid)` runs before the command starts (it is gated on a byte of\n * stdin, so a parent that dies, SIGKILL included, before `onSpawn` returns\n * leaves nothing running): record the group so a lease can outlive this\n * process for as long as the group does. If it throws, the group is reaped\n * and the result is a failure.\n */\nexport function execGroupCapture(\n cmd: string,\n args: readonly string[],\n opts: {\n timeoutMs?: number;\n graceMs?: number;\n onSpawn?: (pgid: number) => void;\n /** The command's working directory (default: this process's). */\n cwd?: string;\n /** Abort: the group is reaped (TERM, then KILL) and the result is a failure. */\n signal?: AbortSignal;\n } = {},\n): Promise<ExecFileResult> {\n return new Promise((resolve) => {\n const gated = opts.onSpawn !== undefined;\n const spawnOpts = {\n detached: true,\n stdio: [\"pipe\", \"pipe\", \"pipe\"] as [\"pipe\", \"pipe\", \"pipe\"],\n ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),\n };\n const child = gated\n ? spawn(\"/bin/sh\", [\"-c\", 'IFS= read -r _ && exec \"$0\" \"$@\"', cmd, ...args], spawnOpts)\n : spawn(cmd, [...args], spawnOpts);\n const out: Buffer[] = [];\n const err: Buffer[] = [];\n child.stdout?.on(\"data\", (d: Buffer) => out.push(d));\n child.stderr?.on(\"data\", (d: Buffer) => err.push(d));\n child.stdin?.on(\"error\", () => {});\n groups.add(child);\n const release = track(child, true);\n let timedOut = false;\n let settled = false;\n const finish = (code: number | null): void => {\n if (settled) return;\n settled = true;\n if (timer) clearTimeout(timer);\n const done = (): void => {\n release();\n child.stdout?.destroy();\n child.stderr?.destroy();\n resolve({\n stdout: stripFinalNewline(Buffer.concat(out).toString(\"utf8\")),\n stderr: stripFinalNewline(Buffer.concat(err).toString(\"utf8\")),\n exitCode: timedOut ? null : code,\n });\n };\n if (child.pid === undefined) done();\n else void reapGroup(child.pid, opts.graceMs ?? 500).then(done);\n };\n const timer =\n opts.timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n timedOut = true;\n finish(null);\n }, opts.timeoutMs);\n child.once(\"error\", () => finish(null)); // spawn failure (ENOENT): no group to reap\n child.once(\"exit\", (code) => finish(code));\n if (opts.signal?.aborted) finish(null);\n else opts.signal?.addEventListener(\"abort\", () => finish(null), { once: true });\n if (opts.onSpawn !== undefined && child.pid !== undefined) {\n try {\n opts.onSpawn(child.pid);\n child.stdin?.end(\"\\n\"); // open the gate: the command starts now\n } catch {\n finish(null);\n child.stdin?.end();\n }\n } else child.stdin?.end();\n });\n}\n","/**\n * This is not the set of all possible signals.\n *\n * It IS, however, the set of all signals that trigger\n * an exit on either Linux or BSD systems. Linux is a\n * superset of the signal names supported on BSD, and\n * the unknown signals just fail to register, so we can\n * catch that easily enough.\n *\n * Windows signals are a different set, since there are\n * signals that terminate Windows processes, but don't\n * terminate (or don't even exist) on Posix systems.\n *\n * Don't bother with SIGKILL. It's uncatchable, which\n * means that we can't fire any callbacks anyway.\n *\n * If a user does happen to register a handler on a non-\n * fatal signal like SIGWINCH or something, and then\n * exit, it'll end up firing `process.emit('exit')`, so\n * the handler will be fired anyway.\n *\n * SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised\n * artificially, inherently leave the process in a\n * state from which it is not safe to try and enter JS\n * listeners.\n */\nexport const signals: NodeJS.Signals[] = []\nsignals.push('SIGHUP', 'SIGINT', 'SIGTERM')\n\nif (process.platform !== 'win32') {\n signals.push(\n 'SIGALRM',\n 'SIGABRT',\n 'SIGVTALRM',\n 'SIGXCPU',\n 'SIGXFSZ',\n 'SIGUSR2',\n 'SIGTRAP',\n 'SIGSYS',\n 'SIGQUIT',\n 'SIGIOT'\n // should detect profiler and enable/disable accordingly.\n // see #21\n // 'SIGPROF'\n )\n}\n\nif (process.platform === 'linux') {\n signals.push('SIGIO', 'SIGPOLL', 'SIGPWR', 'SIGSTKFLT')\n}\n","// Note: since nyc uses this module to output coverage, any lines\n// that are in the direct sync flow of nyc's outputCoverage are\n// ignored, since we can never get coverage for them.\n// grab a reference to node's real process object right away\nimport { signals } from './signals.js'\nexport { signals }\n\n// just a loosened process type so we can do some evil things\ntype ProcessRE = NodeJS.Process & {\n reallyExit: (code?: number | undefined | null) => any\n emit: (ev: string, ...a: any[]) => any\n}\n\nconst processOk = (process: any): process is ProcessRE =>\n !!process &&\n typeof process === 'object' &&\n typeof process.removeListener === 'function' &&\n typeof process.emit === 'function' &&\n typeof process.reallyExit === 'function' &&\n typeof process.listeners === 'function' &&\n typeof process.kill === 'function' &&\n typeof process.pid === 'number' &&\n typeof process.on === 'function'\n\nconst kExitEmitter = Symbol.for('signal-exit emitter')\nconst global: typeof globalThis & { [kExitEmitter]?: Emitter } = globalThis\nconst ObjectDefineProperty = Object.defineProperty.bind(Object)\n\n/**\n * A function that takes an exit code and signal as arguments\n *\n * In the case of signal exits *only*, a return value of true\n * will indicate that the signal is being handled, and we should\n * not synthetically exit with the signal we received. Regardless\n * of the handler return value, the handler is unloaded when an\n * otherwise fatal signal is received, so you get exactly 1 shot\n * at it, unless you add another onExit handler at that point.\n *\n * In the case of numeric code exits, we may already have committed\n * to exiting the process, for example via a fatal exception or\n * unhandled promise rejection, so it is impossible to stop safely.\n */\nexport type Handler = (\n code: number | null | undefined,\n signal: NodeJS.Signals | null\n) => true | void\ntype ExitEvent = 'afterExit' | 'exit'\ntype Emitted = { [k in ExitEvent]: boolean }\ntype Listeners = { [k in ExitEvent]: Handler[] }\n\n// teeny special purpose ee\nclass Emitter {\n emitted: Emitted = {\n afterExit: false,\n exit: false,\n }\n\n listeners: Listeners = {\n afterExit: [],\n exit: [],\n }\n\n count: number = 0\n id: number = Math.random()\n\n constructor() {\n if (global[kExitEmitter]) {\n return global[kExitEmitter]\n }\n ObjectDefineProperty(global, kExitEmitter, {\n value: this,\n writable: false,\n enumerable: false,\n configurable: false,\n })\n }\n\n on(ev: ExitEvent, fn: Handler) {\n this.listeners[ev].push(fn)\n }\n\n removeListener(ev: ExitEvent, fn: Handler) {\n const list = this.listeners[ev]\n const i = list.indexOf(fn)\n /* c8 ignore start */\n if (i === -1) {\n return\n }\n /* c8 ignore stop */\n if (i === 0 && list.length === 1) {\n list.length = 0\n } else {\n list.splice(i, 1)\n }\n }\n\n emit(\n ev: ExitEvent,\n code: number | null | undefined,\n signal: NodeJS.Signals | null\n ): boolean {\n if (this.emitted[ev]) {\n return false\n }\n this.emitted[ev] = true\n let ret: boolean = false\n for (const fn of this.listeners[ev]) {\n ret = fn(code, signal) === true || ret\n }\n if (ev === 'exit') {\n ret = this.emit('afterExit', code, signal) || ret\n }\n return ret\n }\n}\n\nabstract class SignalExitBase {\n abstract onExit(cb: Handler, opts?: { alwaysLast?: boolean }): () => void\n abstract load(): void\n abstract unload(): void\n}\n\nconst signalExitWrap = <T extends SignalExitBase>(handler: T) => {\n return {\n onExit(cb: Handler, opts?: { alwaysLast?: boolean }) {\n return handler.onExit(cb, opts)\n },\n load() {\n return handler.load()\n },\n unload() {\n return handler.unload()\n },\n }\n}\n\nclass SignalExitFallback extends SignalExitBase {\n onExit() {\n return () => {}\n }\n load() {}\n unload() {}\n}\n\nclass SignalExit extends SignalExitBase {\n // \"SIGHUP\" throws an `ENOSYS` error on Windows,\n // so use a supported signal instead\n /* c8 ignore start */\n #hupSig = process.platform === 'win32' ? 'SIGINT' : 'SIGHUP'\n /* c8 ignore stop */\n #emitter = new Emitter()\n #process: ProcessRE\n #originalProcessEmit: ProcessRE['emit']\n #originalProcessReallyExit: ProcessRE['reallyExit']\n\n #sigListeners: { [k in NodeJS.Signals]?: () => void } = {}\n #loaded: boolean = false\n\n constructor(process: ProcessRE) {\n super()\n this.#process = process\n // { <signal>: <listener fn>, ... }\n this.#sigListeners = {}\n for (const sig of signals) {\n this.#sigListeners[sig] = () => {\n // If there are no other listeners, an exit is coming!\n // Simplest way: remove us and then re-send the signal.\n // We know that this will kill the process, so we can\n // safely emit now.\n const listeners = this.#process.listeners(sig)\n let { count } = this.#emitter\n // This is a workaround for the fact that signal-exit v3 and signal\n // exit v4 are not aware of each other, and each will attempt to let\n // the other handle it, so neither of them do. To correct this, we\n // detect if we're the only handler *except* for previous versions\n // of signal-exit, and increment by the count of listeners it has\n // created.\n /* c8 ignore start */\n const p = process as unknown as {\n __signal_exit_emitter__?: { count: number }\n }\n if (\n typeof p.__signal_exit_emitter__ === 'object' &&\n typeof p.__signal_exit_emitter__.count === 'number'\n ) {\n count += p.__signal_exit_emitter__.count\n }\n /* c8 ignore stop */\n if (listeners.length === count) {\n this.unload()\n const ret = this.#emitter.emit('exit', null, sig)\n /* c8 ignore start */\n const s = sig === 'SIGHUP' ? this.#hupSig : sig\n if (!ret) process.kill(process.pid, s)\n /* c8 ignore stop */\n }\n }\n }\n\n this.#originalProcessReallyExit = process.reallyExit\n this.#originalProcessEmit = process.emit\n }\n\n onExit(cb: Handler, opts?: { alwaysLast?: boolean }) {\n /* c8 ignore start */\n if (!processOk(this.#process)) {\n return () => {}\n }\n /* c8 ignore stop */\n\n if (this.#loaded === false) {\n this.load()\n }\n\n const ev = opts?.alwaysLast ? 'afterExit' : 'exit'\n this.#emitter.on(ev, cb)\n return () => {\n this.#emitter.removeListener(ev, cb)\n if (\n this.#emitter.listeners['exit'].length === 0 &&\n this.#emitter.listeners['afterExit'].length === 0\n ) {\n this.unload()\n }\n }\n }\n\n load() {\n if (this.#loaded) {\n return\n }\n this.#loaded = true\n\n // This is the number of onSignalExit's that are in play.\n // It's important so that we can count the correct number of\n // listeners on signals, and don't wait for the other one to\n // handle it instead of us.\n this.#emitter.count += 1\n\n for (const sig of signals) {\n try {\n const fn = this.#sigListeners[sig]\n if (fn) this.#process.on(sig, fn)\n } catch (_) {}\n }\n\n this.#process.emit = (ev: string, ...a: any[]) => {\n return this.#processEmit(ev, ...a)\n }\n this.#process.reallyExit = (code?: number | null | undefined) => {\n return this.#processReallyExit(code)\n }\n }\n\n unload() {\n if (!this.#loaded) {\n return\n }\n this.#loaded = false\n\n signals.forEach(sig => {\n const listener = this.#sigListeners[sig]\n /* c8 ignore start */\n if (!listener) {\n throw new Error('Listener not defined for signal: ' + sig)\n }\n /* c8 ignore stop */\n try {\n this.#process.removeListener(sig, listener)\n /* c8 ignore start */\n } catch (_) {}\n /* c8 ignore stop */\n })\n this.#process.emit = this.#originalProcessEmit\n this.#process.reallyExit = this.#originalProcessReallyExit\n this.#emitter.count -= 1\n }\n\n #processReallyExit(code?: number | null | undefined) {\n /* c8 ignore start */\n if (!processOk(this.#process)) {\n return 0\n }\n this.#process.exitCode = code || 0\n /* c8 ignore stop */\n\n this.#emitter.emit('exit', this.#process.exitCode, null)\n return this.#originalProcessReallyExit.call(\n this.#process,\n this.#process.exitCode\n )\n }\n\n #processEmit(ev: string, ...args: any[]): any {\n const og = this.#originalProcessEmit\n if (ev === 'exit' && processOk(this.#process)) {\n if (typeof args[0] === 'number') {\n this.#process.exitCode = args[0]\n /* c8 ignore start */\n }\n /* c8 ignore start */\n const ret = og.call(this.#process, ev, ...args)\n /* c8 ignore start */\n this.#emitter.emit('exit', this.#process.exitCode, null)\n /* c8 ignore stop */\n return ret\n } else {\n return og.call(this.#process, ev, ...args)\n }\n }\n}\n\nconst process = globalThis.process\n// wrap so that we call the method on the actual handler, without\n// exporting it directly.\nexport const {\n /**\n * Called when the process is exiting, whether via signal, explicit\n * exit, or running out of stuff to do.\n *\n * If the global process object is not suitable for instrumentation,\n * then this will be a no-op.\n *\n * Returns a function that may be used to unload signal-exit.\n */\n onExit,\n\n /**\n * Load the listeners. Likely you never need to call this, unless\n * doing a rather deep integration with signal-exit functionality.\n * Mostly exposed for the benefit of testing.\n *\n * @internal\n */\n load,\n\n /**\n * Unload the listeners. Likely you never need to call this, unless\n * doing a rather deep integration with signal-exit functionality.\n * Mostly exposed for the benefit of testing.\n *\n * @internal\n */\n unload,\n} = signalExitWrap(\n processOk(process) ? new SignalExit(process) : new SignalExitFallback()\n)\n","// mu — output helpers: colour, tables, JSON-mode detection, usage lines.\n//\n// A result's follow-up is its `next` plan (src/next-hints.ts), finalised\n// once in src/cli/handle.ts; nothing here builds a hint.\n\nimport Table from \"cli-table3\";\nimport tableUtils from \"cli-table3/src/utils.js\";\nimport type { Command } from \"commander\";\nimport picocolors from \"picocolors\";\n\n/**\n * Should we emit ANSI color escapes from this process?\n *\n * picocolors ships an `isColorSupported` flag, but it bakes its env\n * inspection (NO_COLOR / FORCE_COLOR / isTTY) ONCE at module-load\n * time. That makes the function untestable without dynamic re-imports\n * — and worse, it loses colors whenever stdout is a pipe, most\n * painfully under `watch --color mu state` and `tmux display-popup -E\n * 'mu state' | cat`, where the surrounding pane is a real terminal but\n * our own stdout is a pipe.\n *\n * We therefore re-implement the decision from scratch at call time,\n * reading every signal directly from `process.env` / `process.stdout`\n * so tests can flip env vars and observe the result without the\n * vi.resetModules + vi.doMock dance.\n *\n * Order of precedence (first match wins):\n * - `NO_COLOR` set (cross-tool opt-out, https://no-color.org/) →\n * OFF, even when TMUX/MU_FORCE_COLOR/FORCE_COLOR are set. We\n * treat any defined value (including \"\") as set, matching the\n * no-color.org convention and picocolors' own behavior.\n * - `MU_FORCE_COLOR` truthy → ON (mu-specific override). Values\n * \"\", \"0\", and \"false\" are explicit opt-outs, matching chalk's\n * FORCE_COLOR convention.\n * - `FORCE_COLOR` truthy → ON (the standard env var picocolors /\n * chalk consult). Values \"\", \"0\", and \"false\" opt out.\n * - `TMUX` set → ON (the load-bearing fix for `watch` inside tmux:\n * the surrounding pane is a real terminal even though our stdout\n * is a pipe).\n * - Fall back to the standard TTY heuristic: stdout is a TTY AND\n * TERM !== \"dumb\". This mirrors what picocolors itself does in\n * `isColorSupported` for the happy-path case.\n *\n * See task hud_colors_stripped_under_watch_and for the original repro.\n */\nfunction envForceTrue(key: string): boolean {\n const v = process.env[key];\n if (v === undefined) return false;\n if (v === \"\" || v === \"0\" || v.toLowerCase() === \"false\") return false;\n return true;\n}\n\nexport function colorEnabled(): boolean {\n if (process.env.NO_COLOR !== undefined) return false;\n if (envForceTrue(\"MU_FORCE_COLOR\")) return true;\n if (envForceTrue(\"FORCE_COLOR\")) return true;\n if (process.env.TMUX !== undefined) return true;\n return Boolean(process.stdout.isTTY) && process.env.TERM !== \"dumb\";\n}\n\n/**\n * The single picocolors instance the rest of the codebase imports.\n * Built once at module load with `colorEnabled()` baked in, so every\n * caller (cli.ts, src/cli/*.ts) renders consistently regardless of\n * isTTY heuristics. Any other module that needs `pc` should import\n * this one rather than reaching for `picocolors` directly.\n */\n// picocolors is still used as the renderer (createColors honors the\n// flag we pass), but the *decision* of whether to render is ours.\nexport const pc = picocolors.createColors(colorEnabled());\n\n// Printable ASCII plus the width-1 punctuation mu prints (dashes,\n// quotes, \"…\", \"∞\"), after stripping picocolors' SGR codes. Such a line\n// renders as itself with width = stripped length, skipping per-grapheme\n// segmentation (~95 ms on 1901 rows). Anything else (unbalanced SGR,\n// zero-width/format characters, wide text, tabs, CR, other escapes) goes\n// through cli-table3's own strlen and colorizeLines, so it is\n// byte-identical by construction: cli-table3 bundles an older\n// string-width that measures soft hyphen and U+200B differently, and\n// closes SGR left open at each line end.\nconst NARROW = /^[\\x20-\\x7e\\u2010-\\u2027\\u221e]*$/;\n// biome-ignore lint/suspicious/noControlCharactersInRegex: matching SGR escapes is the point\nconst SGR = /\\u001b\\[(?:\\d*;){0,5}\\d*m/g;\ninterface BoxCell {\n lines: string[];\n widths: number[];\n width: number;\n}\n// Mirrors cli-table3's Cell: lines = colorizeLines(content.split(\"\\n\")),\n// width = widest line. Splitting on \"\\n\" only (not CR) is what it does.\nfunction boxCell(c: string): BoxCell {\n if (NARROW.test(c)) return { lines: [c], widths: [c.length], width: c.length };\n const raw = c.split(\"\\n\");\n const lines = tableUtils.colorizeLines(raw);\n const widths = raw.map((l) => {\n const plain = l.replace(SGR, \"\"); // cli-table3's strlen strip regex\n return NARROW.test(plain) ? plain.length : tableUtils.strlen(l);\n });\n return { lines, widths, width: Math.max(...widths) };\n}\n\n/**\n * Render a bordered table byte-identical to `muTable({ head }).toString()`\n * (default style, auto widths), in linear time.\n *\n * cli-table3's layout pass (`fillInTable` → `conflictExists`) scans\n * every earlier row for every cell, so a 1901-row `mu task list` spent\n * ~1.5 s there. Plain cells take a fast path; the rest use cli-table3's\n * own width and SGR-closing helpers (see boxCell). A row is as tall as\n * its tallest cell; shorter cells get blank lines below, as in cli-table3.\n */\nexport function renderBoxTable(\n head: readonly string[],\n rows: readonly (readonly string[])[],\n): string {\n const all = [head, ...rows];\n const widths = head.map(() => 0);\n const cells = all.map((r) =>\n r.map((c, i) => {\n const cell = boxCell(c);\n if (cell.width > (widths[i] ?? 0)) widths[i] = cell.width;\n return cell;\n }),\n );\n const rule = (l: string, m: string, r: string) =>\n l + widths.map((w) => \"─\".repeat(w + 2)).join(m) + r;\n const sep = rule(\"├\", \"┼\", \"┤\");\n const out: string[] = [rule(\"┌\", \"┬\", \"┐\")];\n for (let y = 0; y < all.length; y++) {\n if (y > 0) out.push(sep);\n const r = cells[y] ?? [];\n let height = 1;\n for (const cell of r) if (cell.lines.length > height) height = cell.lines.length;\n for (let n = 0; n < height; n++) {\n let line = \"│\";\n for (let x = 0; x < widths.length; x++) {\n const cell = r[x];\n const pad = (widths[x] ?? 0) - (cell?.widths[n] ?? 0);\n line += ` ${cell?.lines[n] ?? \"\"}${\" \".repeat(pad)} │`;\n }\n out.push(line);\n }\n }\n out.push(rule(\"└\", \"┴\", \"┘\"));\n return out.join(\"\\n\");\n}\n\n/**\n * Build a cli-table3 Table with the mu-standard safety belt:\n * `wordWrap: false` (cells wider than their column truncate with `…`\n * instead of wrapping to a second visual row), per-column max widths\n * applied only where the caller asks (`null` = auto), and a default\n * borderless style mirroring the state/agent/workstream tables.\n *\n * Callers should pre-truncate values they care about via the\n * `truncate()` / `truncateFront()` helpers in cli.ts (the proactive\n * path); `wordWrap: false` is the safety belt for the cells they\n * miss. This is load-bearing for renderers with fixed row budgets:\n * a single wrapped cell silently blows out the promised section height.\n *\n * Surfaced live by a worktree table blowing the terminal width on\n * the `path` column (tables_truncate_long_cols_audit). Don't try to\n * cap every column — apply `colWidths` only on the column(s) the\n * operator is least likely to read in full and most likely to be\n * long. Don't add a `--full` / `--no-truncate` flag per verb either;\n * `--json` already emits the full value.\n */\nexport function muTable(opts: {\n head: string[];\n /** Per-column max widths in cells (`null` = auto width). When\n * supplied, the array length must match `head`. cli-table3\n * truncates with `…` because we set `wordWrap: false`. */\n colWidths?: (number | null)[];\n /** Style override; defaults to `{ head: [], border: [] }` (mu's\n * borderless look). Pass `{ head: [] }` to keep cli-table3's\n * default border styling. */\n style?: { head?: string[]; border?: string[] };\n}): InstanceType<typeof Table> {\n return new Table({\n head: opts.head,\n ...(opts.colWidths !== undefined ? { colWidths: opts.colWidths } : {}),\n style: opts.style ?? { head: [], border: [] },\n wordWrap: false,\n });\n}\n\n/**\n * Detect whether the current invocation requested `--json`. Used by the\n * error handler to decide between human prose on stderr and one JSON\n * document on stdout. Reads `process.argv` directly because commander has\n * already consumed it by the time the handler runs, and threading it\n * through every verb wrapper would be invasive.\n *\n * Tolerates `--json=...` form (commander supports both) but mu's verbs\n * only use the bare `--json` flag.\n */\nexport function isJsonMode(): boolean {\n const argv = process.argv;\n return (\n argv.some((a) => a === \"--json\" || a.startsWith(\"--json=\")) ||\n ((isSqlVerbArgv(argv) || isAgentListArgv(argv)) && !argv.includes(\"--table\")) ||\n isStateVerbArgv(argv) ||\n isWaitVerbArgv(argv) ||\n // `mu next` prints ONE JSON result for every outcome; its failures too.\n verbWords(argv)[0] === \"next\"\n );\n}\n\n/** The first one or two words of the invocation, found the way the parser does:\n * the first words that are not an option or the value of `-w`, so\n * `mu -w state task list` is a `task` verb. */\nfunction verbWords(argv: readonly string[]): string[] {\n const words: string[] = [];\n for (let i = 2; i < argv.length && words.length < 2; i++) {\n const a = argv[i] as string;\n if (a === \"-w\" || a === \"--workstream\") i++;\n else if (!a.startsWith(\"-\")) words.push(a);\n }\n return words;\n}\n\n/**\n * Is this invocation `mu sql` or `mu db query`? Those two print JSON unless\n * `--table`.\n */\nexport function isSqlVerbArgv(argv: readonly string[]): boolean {\n const words = verbWords(argv);\n return words[0] === \"sql\" || (words[0] === \"db\" && words[1] === \"query\");\n}\n\n/** Is this invocation `mu agent list`? It prints JSON unless `--table`. */\nexport function isAgentListArgv(argv: readonly string[]): boolean {\n const [first, second] = verbWords(argv);\n return first === \"agent\" && second === \"list\";\n}\n\n/**\n * Is this invocation `mu state` or a bare `mu me` (its `--me` alias)? They\n * print one JSON document, errors included (parse-time and handler), with no\n * `--json` needed. `mu me tasks` / `mu me next` are other verbs and keep the\n * explicit flag. Every other verb needs `--json`.\n */\nexport function isStateVerbArgv(argv: readonly string[]): boolean {\n const [first, second] = verbWords(argv);\n return first === \"state\" || (first === \"me\" && second !== \"tasks\" && second !== \"next\");\n}\n\n/**\n * Is this invocation `mu wait`, its alias `mu task wait`, or a producer that enters\n * the wait (`mu agent send --wait`, `mu task claim --and-wait`)? The wait prints one JSON\n * document for every outcome, errors and parse-time errors included, with no\n * `--json` needed. Found the way the parser finds the verb, so `mu -w x task list`\n * is not a wait and `mu -w x wait` is.\n */\nexport function isWaitVerbArgv(argv: readonly string[]): boolean {\n const [first, second] = verbWords(argv);\n return (\n first === \"wait\" ||\n (first === \"task\" && second === \"wait\") ||\n // `send --wait` / `claim --and-wait` enter the same wait: one JSON document too.\n (first === \"agent\" && second === \"send\" && argv.includes(\"--wait\")) ||\n (first === \"task\" && second === \"claim\" && argv.includes(\"--and-wait\"))\n );\n}\n\n// ─── Usage rendering for the validation-error contract ──────────────\n//\n// Every operator-error path (commander-thrown CommanderError, handler-\n// thrown UsageError, typed *Invalid* errors) gets the same surface:\n// (1) the error line, (2) the failing subcommand's accepted syntax. The\n// human path prints commander's own helpInformation(); the --json path\n// carries at most three short lines (never the whole help as JSON), so\n// the one error document stays small.\n\n/** Walk parent chain so renderings include the full path (\"mu task add\"). */\nfunction commandFullName(cmd: Command): string {\n const parts: string[] = [];\n let cur: Command | null = cmd;\n while (cur) {\n parts.unshift(cur.name());\n cur = cur.parent;\n }\n return parts.join(\" \");\n}\n\nconst USAGE_LINE_MAX = 200;\n\n/** The failing verb's accepted syntax in at most 3 lines: synopsis, options,\n * subcommands. Options list long flags only; a long list ends in \"…\". */\nexport function usageLines(cmd: Command): string[] {\n const clip = (s: string) =>\n s.length > USAGE_LINE_MAX ? `${s.slice(0, USAGE_LINE_MAX - 1)}…` : s;\n const lines = [`${commandFullName(cmd)} ${cmd.usage()}`];\n const flags = cmd.options.filter((o) => !o.hidden).map((o) => o.flags);\n if (flags.length > 0) lines.push(clip(`options: ${flags.join(\", \")}`));\n const subs = cmd.commands.map((c) => c.name());\n if (subs.length > 0) lines.push(clip(`commands: ${subs.join(\", \")}`));\n return lines;\n}\n\n/** Render the human --help block (commander's own `helpInformation()`)\n * to stderr. Single source of truth for the post-error help dump. */\nexport function printUsageHuman(cmd: Command): void {\n // helpInformation() returns the full \"Usage: ...\\n\\n<desc>\\n\\nOptions:\\n ...\" block.\n // Print to stderr (errors only) so success-path stdout is never polluted.\n process.stderr.write(`\\n${cmd.helpInformation()}`);\n}\n","// mu — tmux substrate.\n//\n// Single source of truth for all tmux interactions. Every tmux invocation\n// goes through `tmux(args)`, which wraps child_process and produces structured\n// `TmuxError`s carrying args + stderr.\n//\n// tmux has no `sendToPane`: a bracketed paste cannot be confirmed\n// (cut in 4.0). pi agents use the control socket\n// (src/agents/transport.ts); herdr has its own atomic `agent prompt`.\n\nimport { basename } from \"node:path\";\nimport { execFileCapture } from \"../exec-file.js\";\nimport { say } from \"../messages.js\";\nimport {\n type AttachTarget,\n type CaptureOptions,\n type EnsureSessionResult,\n MU_PLACEHOLDER_WINDOW,\n type MuxBackend,\n type MuxCommand,\n MuxError,\n type MuxHealth,\n type MuxPane,\n PaneNotFoundError,\n type PaneResult,\n type SpawnAgentPaneOptions,\n} from \"./types.js\";\n\n// Re-exported so the historical `import { ... } from \"./tmux.js\"` surface\n// keeps resolving these names.\nexport {\n type AttachTarget,\n type CaptureOptions,\n type MuxCommand,\n MuxError,\n type MuxHealth,\n PaneNotFoundError,\n};\n\n/** Back-compat alias: tmux-specific name predating the MuxBackend extraction. */\nexport type TmuxPane = MuxPane;\n\n// ─── Error type ────────────────────────────────────────────────────────\n\nexport class TmuxError extends MuxError {\n constructor(\n public readonly args: readonly string[],\n public readonly stderr: string,\n public readonly stdout: string,\n public readonly exitCode: number | null,\n ) {\n const detail = stderr.trim() || stdout.trim() || \"no output\";\n super(say(\"mux.tmux_failed\", args, exitCode, detail));\n this.name = \"TmuxError\";\n }\n}\n\n// ─── Pane ID validation ────────────────────────────────────────────────\n\n/**\n * Stable tmux pane IDs are of the form `%N` (e.g. \"%15\"). They never change\n * for the lifetime of the pane. **Pane indexes** (0, 1, 2…) are volatile and\n * shift when other panes close — never store or pass them.\n */\nexport const PANE_ID_RE = /^%\\d+$/;\n\nexport function isValidPaneId(s: string): boolean {\n return PANE_ID_RE.test(s);\n}\n\nexport function assertValidPaneId(s: string): void {\n if (!isValidPaneId(s)) {\n throw new TypeError(`invalid tmux pane id: ${JSON.stringify(s)} (expected /^%\\\\d+$/)`);\n }\n}\n\n// ─── Executor (swappable for tests) ────────────────────────────────────\n\nexport interface TmuxExecResult {\n stdout: string;\n stderr: string;\n exitCode: number | null;\n}\n\nexport type TmuxExecutor = (args: readonly string[]) => Promise<TmuxExecResult>;\n\n/**\n * Optional global-flag prefix to splice in front of every tmux args\n * vector. When `MU_TMUX_SOCKET=<name>` is set, this returns\n * `[\"-L\", name, \"-f\", \"/dev/null\"]`:\n *\n * `-L <name>` routes every call through a private tmux server with\n * the given socket name (Linux: `/tmp/tmux-<uid>/<name>`,\n * macOS: `$TMPDIR/tmux-<uid>/<name>`) instead of the user's default\n * `/tmp/tmux-<uid>/default`. Set by the test harness so the integration suite\n * can never observe — or contaminate — the user's interactive\n * tmux server.\n *\n * `-f /dev/null` skips the user's `~/.tmux.conf`. This matters\n * because tmux auto-starts the server on the first client call if\n * none is running (e.g. after a test’s last `kill-session`\n * shuts the server down). A typical user config uses `run-shell`\n * for status-bar plugins (TPM, hostname/network probes), and each\n * such hook adds ~1–4s to that auto-start. Without `-f /dev/null`\n * a single integration test grows from 3s to 48s on a configured\n * dev box. The suite drives tmux through the documented protocol,\n * not through bound keys, so the user's config is irrelevant.\n *\n * Read fresh on every call so a setupFiles hook that mutates\n * `process.env.MU_TMUX_SOCKET` mid-run takes effect immediately.\n *\n * The test suite sets this; a user may too (docs/reference/env.md).\n */\nfunction tmuxGlobalFlags(): readonly string[] {\n const socket = process.env.MU_TMUX_SOCKET;\n if (socket === undefined || socket.length === 0) return [];\n return [\"-L\", socket, \"-f\", \"/dev/null\"];\n}\n\nconst realExecutor: TmuxExecutor = (args) =>\n execFileCapture(\"tmux\", [...tmuxGlobalFlags(), ...args]);\n\nlet currentExecutor: TmuxExecutor = realExecutor;\n\n/**\n * Install a custom executor (for tests). Returns the previous executor so\n * tests can restore it cleanly. Production code should never call this.\n */\nexport function setTmuxExecutor(executor: TmuxExecutor): TmuxExecutor {\n const previous = currentExecutor;\n currentExecutor = executor;\n return previous;\n}\n\n/** Restore the real (child_process-backed) executor. */\nexport function resetTmuxExecutor(): void {\n currentExecutor = realExecutor;\n}\n\n/**\n * Run an arbitrary tmux command. The single point of contact with the\n * tmux binary; every higher-level operation in this module goes through it.\n *\n * Throws `TmuxError` on non-zero exit. Returns stdout on success.\n */\nexport async function tmux(args: readonly string[]): Promise<string> {\n const result = await currentExecutor(args);\n if (result.exitCode !== 0) {\n throw new TmuxError([...args], result.stderr, result.stdout, result.exitCode);\n }\n return result.stdout;\n}\n\n// ─── Sleep helper (testable) ──────────────────────────────────────────\n\nlet currentSleep: (ms: number) => Promise<void> = (ms) =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\nexport function setSleepForTests(\n impl: (ms: number) => Promise<void>,\n): (ms: number) => Promise<void> {\n const previous = currentSleep;\n currentSleep = impl;\n return previous;\n}\n\nexport function resetSleep(): void {\n currentSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Test-aware sleep — honours `setSleepForTests`. Public so other modules\n * (notably `agents.ts` for spawn liveness polling) get free no-op-ing in\n * tests without re-implementing the swap. */\nexport function sleep(ms: number): Promise<void> {\n return currentSleep(ms);\n}\n\n// ─── Sessions ──────────────────────────────────────────────────────────\n\n/**\n * The `-t` form that names session `name` EXACTLY. A bare `-t mu-auth`\n * falls back to prefix matching, so it resolves to `mu-auth-refactor`\n * when `mu-auth` does not exist, and a teardown of workstream `auth`\n * kills another workstream's session. `=` disables the prefix and\n * pattern fallback. The trailing `:` makes it a session target for\n * pane- and window-scoped verbs too: `list-panes -s -t =mu-auth`\n * still prefix-matches through the pane lookup, but\n * `-t =mu-auth:` does not (verified on tmux 3.7c).\n */\nfunction exactSessionTarget(name: string): string {\n return `=${name}:`;\n}\n\n/**\n * stderr shapes that mean \"no tmux server is running\", so there is no\n * session, window or pane to find. tmux prints \"no server running on\n * <path>\" when the socket file exists but nothing listens, and \"error\n * connecting to <path> (No such file or directory)\" when the socket file\n * does not exist at all (fresh boot, cleared /tmp, new TMUX_TMPDIR).\n * Other \"error connecting\" causes, such as permission denied, stay\n * real errors.\n */\nconst NO_SERVER_RE = /no server running|error connecting to .*\\(No such file or directory\\)/i;\n\nasync function sessionExists(name: string): Promise<boolean> {\n const result = await currentExecutor([\"has-session\", \"-t\", exactSessionTarget(name)]);\n return result.exitCode === 0;\n}\n\n/**\n * A detached session otherwise gets tmux's default-size (80x24), so\n * `mu agent read` captures wrap at 80. Never resize-window: it pins\n * window-size to manual.\n */\nconst DETACHED_SIZE = [\"-x\", \"200\", \"-y\", \"50\"];\n\n/** `[id, name]` of every window in `session`. */\nasync function listWindows(session: string): Promise<{ id: string; name: string }[]> {\n const out = await tmux([\n \"list-windows\",\n \"-t\",\n exactSessionTarget(session),\n \"-F\",\n \"#{window_id}\\t#{window_name}\",\n ]);\n const windows: { id: string; name: string }[] = [];\n for (const line of out.split(\"\\n\")) {\n if (line.length === 0) continue;\n const [id, name] = line.split(\"\\t\");\n if (!id || name === undefined) continue;\n windows.push({ id, name });\n }\n return windows;\n}\n\n/**\n * Create `session` with its placeholder `_mu` window when it is missing,\n * and re-add the window when the session exists without it (the operator\n * killed it, or the session predates it). Without `_mu`, closing the last\n * agent kills the last window and tmux destroys the session.\n */\nexport async function ensureSession(session: string): Promise<EnsureSessionResult> {\n if (!(await sessionExists(session))) {\n await tmux([\"new-session\", \"-d\", ...DETACHED_SIZE, \"-s\", session, \"-n\", MU_PLACEHOLDER_WINDOW]);\n return { created: true, repaired: false };\n }\n const windows = await listWindows(session).catch(() => []);\n if (windows.some((w) => w.name === MU_PLACEHOLDER_WINDOW)) {\n return { created: false, repaired: false };\n }\n await tmux([\n \"new-window\",\n \"-d\",\n \"-t\",\n exactSessionTarget(session),\n \"-n\",\n MU_PLACEHOLDER_WINDOW,\n process.env.SHELL ?? \"/bin/sh\",\n ]);\n return { created: false, repaired: true };\n}\n\n/**\n * Idempotent: succeeds even if the session is already gone.\n *\n * Four swallowed shapes:\n * - \"can't find session: <name>\" — session never existed.\n * - \"session not found\" — alternate phrasing on some tmux builds.\n * - \"no server running on <path>\" (or \"error connecting to <path> (No\n * such file or directory)\", see NO_SERVER_RE) — the tmux server itself has exited\n * (typical when the test suite runs against a private `tmux -L\n * <socket>` server and the just-killed session was its last; tmux\n * quietly shuts the server down). Without this, killSession would\n * throw on the very next idempotent call — only visible under\n * the test harness's private socket.\n * - \"no current target\" — the server is UP but has zero\n * sessions, so `-t <name>` has no session list to resolve against\n * and tmux never gets as far as \"can't find session\". Reachable\n * whenever the server outlives its last session: the suite's\n * private server (`exit-empty off`, see test/_global-teardown.ts)\n * and any user whose ~/.tmux.conf sets `exit-empty off`. Same\n * meaning as \"can't find session\" for our purposes — the session\n * we were asked to kill is gone.\n */\nexport async function killSession(name: string): Promise<void> {\n const args = [\"kill-session\", \"-t\", exactSessionTarget(name)];\n const result = await currentExecutor(args);\n if (\n result.exitCode !== 0 &&\n !/can't find session|session not found|no current target/i.test(result.stderr) &&\n !NO_SERVER_RE.test(result.stderr)\n ) {\n throw new TmuxError(args, result.stderr, result.stdout, result.exitCode);\n }\n}\n\n// ─── Panes ─────────────────────────────────────────────────────────────\n\n/** What a retained pane runs until its `remain-on-exit` is armed and the real command replaces it. */\nconst RETAIN_PLACEHOLDER = \"exec sleep 60\";\n\n/**\n * Create the agent's pane and run `opts.command` in it, one tmux call:\n * - session doesn't exist → new session+window+pane\n * - session exists, no such window → new window for this agent\n * - session and window both exist → split the window to add a pane\n * Returns the pane's stable id (`%15`).\n */\nexport async function spawnAgent(opts: SpawnAgentPaneOptions): Promise<string> {\n const retain = opts.retainOnExit === true;\n const tail = (args: string[]): string[] => {\n // A retained pane starts as a placeholder and is respawned into the real\n // command once its remain-on-exit is armed (see `created`).\n if (!retain) {\n if (opts.cwd) args.push(\"-c\", opts.cwd);\n appendEnvFlags(args, opts.env);\n }\n args.push(\"-P\", \"-F\", \"#{pane_id}\", retain ? RETAIN_PLACEHOLDER : opts.command);\n return args;\n };\n const created = async (args: string[]): Promise<string> => {\n const paneId = (await tmux(args)).trim();\n assertValidPaneId(paneId);\n if (retain) {\n // The pane option is set while only the placeholder runs, so the real\n // command can never end before retention is armed (no set-after-spawn\n // race), and only THIS pane is touched, never a session or global default.\n try {\n await tmux([\"set-option\", \"-p\", \"-t\", paneId, \"remain-on-exit\", \"on\"]);\n const respawn = [\"respawn-pane\", \"-k\", \"-t\", paneId];\n if (opts.cwd) respawn.push(\"-c\", opts.cwd);\n appendEnvFlags(respawn, opts.env);\n respawn.push(opts.command);\n await tmux(respawn);\n } catch (err) {\n await killPane(paneId).catch(() => {});\n throw err;\n }\n }\n opts.onPaneCreated?.(paneId);\n return paneId;\n };\n\n if (!(await sessionExists(opts.session))) {\n return created(\n tail([\"new-session\", \"-d\", ...DETACHED_SIZE, \"-s\", opts.session, \"-n\", opts.window]),\n );\n }\n const matching = (await listWindows(opts.session)).find((w) => w.name === opts.window);\n if (matching) {\n // tmux splits a WINDOW: target it as `=<session>:<window_id>`. A bare\n // `<session>:<name>` falls back to tmux's session prefix match, so if\n // `mu-auth` vanishes between list-windows and here, `mu-auth:Backend`\n // splits `mu-auth-refactor`'s Backend window. `=` makes the session\n // exact and the stable window id (from the listing above) must live\n // in that session, so a vanished session or window fails instead of\n // landing elsewhere.\n return created(tail([\"split-window\", \"-h\", \"-d\", \"-t\", `=${opts.session}:${matching.id}`]));\n }\n return created(\n tail([\"new-window\", \"-d\", \"-t\", exactSessionTarget(opts.session), \"-n\", opts.window]),\n );\n}\n\n/**\n * List ALL panes in a tmux session (across every window).\n *\n * Note `list-panes -t <session>` (no -s) lists panes in the current\n * *window* of that session, not the whole session — a common gotcha.\n * `-s` is the flag that says \"all panes in this session.\"\n *\n * Returns `[]` (not throws) when the session doesn't exist or has no\n * panes. tmux destroys a session as soon as its last pane closes, so the\n * \"session was just here a moment ago\" case is normal during reconcile.\n * tmux's error wording in this case varies (\"can't find session\",\n * \"can't find window\", or \"no current target\" when the server is up\n * with zero sessions), so we match any of them. Every other failure\n * throws.\n */\nexport async function listPanes(session: string): Promise<MuxPane[]> {\n const args = [\n \"list-panes\",\n \"-s\",\n \"-t\",\n exactSessionTarget(session),\n \"-F\",\n \"#{window_id}\\t#{pane_id}\\t#{pane_current_command}\",\n ];\n const result = await currentExecutor(args);\n if (result.exitCode !== 0) {\n if (\n /can't find (session|window)|no sessions|no current target/i.test(result.stderr) ||\n NO_SERVER_RE.test(result.stderr)\n ) {\n return [];\n }\n throw new TmuxError(args, result.stderr, result.stdout, result.exitCode);\n }\n const panes: MuxPane[] = [];\n for (const line of result.stdout.split(\"\\n\")) {\n if (line.length === 0) continue;\n const [windowId, paneId, command] = line.split(\"\\t\");\n if (!windowId || !paneId || command === undefined) continue;\n panes.push({ paneId, command, windowId });\n }\n return panes;\n}\n\n/**\n * Push one `-e KEY=VALUE` flag per entry into `args`, validating that\n * keys are non-empty and contain no `=` (tmux would error obscurely\n * otherwise; throwing TypeError keeps the failure at the call site).\n * No-op when `env` is undefined or empty.\n *\n * Iteration order follows Object.entries (insertion order); tests\n * shouldn't depend on a specific ordering, only on the presence of\n * each `-e KEY=VALUE` pair in the captured args.\n */\nfunction appendEnvFlags(args: string[], env: Record<string, string> | undefined): void {\n if (!env) return;\n for (const [k, v] of Object.entries(env)) {\n if (k.length === 0) {\n throw new TypeError(\"tmux env key must be non-empty\");\n }\n if (k.includes(\"=\")) {\n throw new TypeError(`tmux env key must not contain '=': ${JSON.stringify(k)}`);\n }\n args.push(\"-e\", `${k}=${v}`);\n }\n}\n\n/** Idempotent: succeeds even if the pane is already gone. */\nexport async function killPane(paneId: string): Promise<void> {\n assertValidPaneId(paneId);\n const result = await currentExecutor([\"kill-pane\", \"-t\", paneId]);\n if (\n result.exitCode !== 0 &&\n !/can't find pane/i.test(result.stderr) &&\n !NO_SERVER_RE.test(result.stderr)\n ) {\n throw new TmuxError([\"kill-pane\", \"-t\", paneId], result.stderr, result.stdout, result.exitCode);\n }\n}\n\nexport async function paneAlive(paneId: string): Promise<boolean> {\n if (!isValidPaneId(paneId)) return false;\n // tmux's `display-message -t <bogus>` exits 0 but emits empty output; we\n // must check that the echoed pane id matches what we asked for.\n const args = [\"display-message\", \"-t\", paneId, \"-p\", \"#{pane_id}\"];\n const result = await currentExecutor(args);\n if (result.exitCode !== 0) {\n // Only \"the pane or server is gone\" means false. Any other failure\n // (permission denied, a broken socket) is unknown, not dead: callers\n // that gate destructive work on liveness must not read it as gone.\n if (/can't find pane|pane not found|no current target/i.test(result.stderr)) return false;\n if (NO_SERVER_RE.test(result.stderr)) return false;\n throw new TmuxError(args, result.stderr, result.stdout, result.exitCode);\n }\n return result.stdout.trim() === paneId;\n}\n\n/**\n * The pane's run state: running, exited (a retained pane keeps its row, with\n * `#{pane_dead_status}` / `#{pane_dead_signal}`) or absent. Only \"the pane or\n * server is gone\" is absent; any other failure throws, as `paneAlive` does.\n */\nexport async function paneResult(paneId: string): Promise<PaneResult> {\n if (!isValidPaneId(paneId)) return { state: \"absent\" };\n const args = [\n \"display-message\",\n \"-t\",\n paneId,\n \"-p\",\n \"#{pane_id}|#{pane_dead}|#{pane_dead_status}|#{pane_dead_signal}\",\n ];\n const result = await currentExecutor(args);\n if (result.exitCode !== 0) {\n if (/can't find pane|pane not found|no current target/i.test(result.stderr)) {\n return { state: \"absent\" };\n }\n if (NO_SERVER_RE.test(result.stderr)) return { state: \"absent\" };\n throw new TmuxError(args, result.stderr, result.stdout, result.exitCode);\n }\n const [id, dead, status, signal] = result.stdout.trim().split(\"|\");\n if (id !== paneId) return { state: \"absent\" };\n if (dead !== \"1\") return { state: \"running\" };\n const num = (s: string | undefined): number | null =>\n s !== undefined && /^\\d+$/.test(s) ? Number(s) : null;\n return { state: \"exited\", code: num(status), signal: num(signal) };\n}\n\n/**\n * Name of the tmux session this process is running inside, or\n * undefined outside tmux. Gated on `$TMUX` so a call from a plain\n * shell doesn't get whatever session the server happens to consider\n * current. A `$TMUX` naming another server (an outer tmux around mu's\n * private one) is outside too.\n */\nexport async function currentSessionName(): Promise<string | undefined> {\n if (!tmuxServerIsCurrent()) return undefined;\n const result = await currentExecutor([\"display-message\", \"-p\", \"#S\"]);\n if (result.exitCode !== 0) return undefined;\n const name = result.stdout.trim();\n return name === \"\" ? undefined : name;\n}\n\n// ─── Capture ───────────────────────────────────────────────────────────\n\n/**\n * Read pane scrollback as plain text (no ANSI escapes).\n *\n * - No options: full scrollback (`-S - -E -`)\n * - `lines: 0`: visible pane only\n * - `lines: N`: last N lines, ending at the last non-blank row\n *\n * `-S -N` counts from the TOP of the visible screen, so tmux returns the\n * N rows above the screen plus every visible row, blank rows below the\n * cursor included. That range always holds the last N non-blank-ended\n * lines, so drop the trailing blank rows and keep the last N.\n */\nexport async function capture(paneId: string, opts: CaptureOptions = {}): Promise<string> {\n assertValidPaneId(paneId);\n const args = [\"capture-pane\", \"-t\", paneId, \"-p\"];\n if (opts.lines === undefined) {\n args.push(\"-S\", \"-\", \"-E\", \"-\");\n } else if (opts.lines > 0) {\n args.push(\"-S\", `-${opts.lines}`);\n return lastLines(await tmux(args), opts.lines);\n }\n return tmux(args);\n}\n\n/** The last `n` lines of `text` after dropping trailing blank lines.\n * Keeps a trailing newline when `text` had one (tmux prints one). */\nfunction lastLines(text: string, n: number): string {\n const lines = text.split(\"\\n\");\n let end = lines.length;\n while (end > 0 && (lines[end - 1] ?? \"\").trim() === \"\") end--;\n if (end === 0) return \"\";\n const kept = lines.slice(Math.max(0, end - n), end).join(\"\\n\");\n return text.endsWith(\"\\n\") ? `${kept}\\n` : kept;\n}\n\n// ─── Backend record ────────────────────────────────────────────────────\n\n/**\n * True iff tmux can be reached right now. `tmux -V` rather than a PATH\n * probe: a tmux binary that cannot execute (broken install, missing\n * libtinfo) is not an available backend, and the version call is the\n * cheapest thing that proves the binary actually runs.\n *\n * Deliberately does NOT require `$TMUX` — mu creates its own detached\n * sessions, so a usable tmux server is enough. `$TMUX` only tells us\n * whether the CALLER is inside a pane, which is a detection-precedence\n * signal (see ./detect.ts), not an availability one.\n */\nasync function tmuxAvailable(): Promise<boolean> {\n try {\n await tmux([\"-V\"]);\n return true;\n } catch {\n return false;\n }\n}\n\n// ─── Attach ────────────────────────────────────────────────────\n//\n// From INSIDE a tmux client the right verb is `switch-client`, which\n// repoints the existing client and returns immediately. From outside it\n// is ONE `attach-session -t <session>:<window>`: the window half of the\n// target selects the window the client opens on. (A separate\n// `select-window` after the attach would run only once the blocking\n// client detached.) Every step carries the same `-L <socket>` as `tmux()`\n// does, so the line printed for a private `MU_TMUX_SOCKET` reaches the\n// server that holds the session, not the user's default one.\n\nfunction attachTargetSpec(target: AttachTarget): string {\n return target.window === undefined ? target.session : `${target.session}:${target.window}`;\n}\n\n/**\n * Is `$TMUX` a client of the server mu drives? With no `MU_TMUX_SOCKET`, tmux itself follows\n * `$TMUX`, so yes. With `-L <socket>`, only when `$TMUX` (`<socket path>,<pid>,<session>`)\n * names that socket file. False when `$TMUX` is unset or names an outer tmux around mu's\n * private server.\n */\nfunction tmuxServerIsCurrent(): boolean {\n const path = process.env.TMUX?.split(\",\")[0];\n if (path === undefined || path === \"\") return false;\n const socket = process.env.MU_TMUX_SOCKET;\n return socket === undefined || socket.length === 0 || basename(path) === socket;\n}\n\n/** Inside a client of some OTHER tmux server than the one mu drives. */\nconst inAnotherTmux = (): boolean => Boolean(process.env.TMUX) && !tmuxServerIsCurrent();\n\n/** How the caller gets back after an attach from here: `$TMUX` on mu's server (`switch`),\n * on another one (`nested`: the outer tmux needs a doubled prefix), or none (`plain`). */\nexport function tmuxAttachMode(): \"switch\" | \"nested\" | \"plain\" {\n if (!process.env.TMUX) return \"plain\";\n return inAnotherTmux() ? \"nested\" : \"switch\";\n}\n\nexport async function attachCommands(target: AttachTarget): Promise<readonly MuxCommand[]> {\n const spec = attachTargetSpec(target);\n const socket = process.env.MU_TMUX_SOCKET;\n const route = socket === undefined || socket.length === 0 ? [] : [\"-L\", socket];\n const attach = { command: \"tmux\", args: [...route, \"attach-session\", \"-t\", spec] };\n if (target.outside === true) return [attach];\n // A client of ANOTHER server (an outer tmux around mu's private one) cannot be switched,\n // and tmux refuses an attach with `$TMUX` set: open a deliberately nested client.\n if (inAnotherTmux()) return [{ ...attach, nested: true }];\n if (target.inside === true) return [{ ...attach, args: [...route, \"switch-client\", \"-t\", spec] }];\n return [attach];\n}\n\n/**\n * Version probe + the two ambient env facts tmux exposes. Returns DATA;\n * `mu doctor` owns every string the user sees, so a second backend\n * reporting different env vars needs no doctor change.\n */\nexport async function healthCheck(): Promise<MuxHealth> {\n let version: string | null = null;\n try {\n version = (await tmux([\"-V\"])).trim();\n } catch {\n version = null;\n }\n return {\n name: \"tmux\",\n ok: version !== null,\n version,\n env: [\n { name: \"$TMUX\", value: process.env.TMUX ?? null },\n { name: \"$TMUX_PANE\", value: process.env.TMUX_PANE ?? null },\n ],\n remediation: \"install tmux ≥ 3.0\",\n };\n}\n\n/**\n * The tmux implementation of `MuxBackend`. A frozen record of the\n * module's functions — no state of its own, so swapping backends is a\n * pointer assignment (see ./detect.ts).\n */\nexport const tmuxBackend: MuxBackend = Object.freeze({\n name: \"tmux\" as const,\n spawnAgentWaitsReady: false,\n runsShellCommand: true,\n available: tmuxAvailable,\n\n isValidPaneId,\n assertValidPaneId,\n\n ensureSession,\n killSession,\n\n spawnAgent,\n listPanes,\n paneAlive,\n paneResult,\n killPane,\n capture,\n\n attachCommands,\n\n currentSessionName,\n healthCheck,\n});\n","// mu — shared POSIX single-quote helper.\n//\n// Wrap a token in single quotes for safe interpolation into a /bin/sh\n// command we render for the user to copy-paste (e.g. next-step hints).\n// Embedded single-quotes are escaped via the canonical close-reopen\n// idiom: ' → '\"'\"'.\n\n/** A shell word for `s`: itself when it needs no quoting, else single-quoted. */\nexport function shellWord(s: string): string {\n return /^[\\w@%+=:,./-]+$/.test(s) ? s : shellQuote(s);\n}\n\nexport function shellQuote(s: string): string {\n return `'${s.replace(/'/g, `'\"'\"'`)}'`;\n}\n","// mu — shared multiplexer backend contracts and typed errors.\n//\n// A \"mux\" is the terminal multiplexer that owns panes. mu supports one\n// active backend per invocation, chosen by `detectMux()` in ./detect.js.\n// Everything backend-specific lives behind `MuxBackend`:\n//\n// - session / window / pane topology, behind `ensureSession` and\n// `spawnAgent` (a spawn is ONE backend operation: tmux creates and\n// runs in one step, herdr creates a shell pane and starts the agent)\n// - the send protocol (herdr only: atomic `agent prompt`)\n// - scrollback capture\n// - PANE ID VALIDATION — tmux `%15` vs herdr `w1:p1`, which is why\n// there is no global pane-id regex\n//\n// Agent identity is `$MU_AGENT_NAME`; no backend reads or writes pane\n// titles.\n//\n// Same shape as src/vcs/: a types module, one file per impl, and an\n// index that dispatches. See docs/VOCABULARY.md § \"mux backend\".\n\nimport { say } from \"../messages.js\";\nimport { shellWord } from \"../shell-quote.js\";\n\n/** The multiplexers mu can drive. */\nexport type MuxBackendName = \"herdr\" | \"tmux\";\n\n/** Runtime states a mux backend can report directly for one pane. */\nexport type MuxPaneStatus = \"busy\" | \"needs_input\" | \"needs_permission\";\n\n// ─── Domain types ──────────────────────────────────────────────────────\n//\n// Deliberately narrow: these carry only the fields mu actually reads.\n// A backend that knows more about a pane keeps that to itself.\n\nexport interface MuxPane {\n /** Backend-specific stable pane id (tmux `%15`). Never a volatile index. */\n paneId: string;\n /** Current foreground command (e.g. \"claude\", \"node\", \"bash\"). */\n command: string;\n /** Window this pane lives in. */\n windowId?: string;\n}\n\n/** Name of the placeholder shell window every `mu-<ws>` session keeps,\n * so the session outlives its last agent pane. */\nexport const MU_PLACEHOLDER_WINDOW = \"_mu\";\n\n/** What `ensureSession` did. */\nexport interface EnsureSessionResult {\n /** The session did not exist and was created. */\n created: boolean;\n /** The session existed but its `_mu` window was missing and was re-added. */\n repaired: boolean;\n}\n\n/**\n * What `spawnAgent` needs. mu has already resolved the command it would\n * run; a backend that starts agents itself (herdr) needs both that string\n * and the `--cli` key it came from, because those select different routes.\n */\nexport interface SpawnAgentPaneOptions {\n /** Mux session (tmux session / herdr workspace label), e.g. `mu-auth`. */\n session: string;\n /** Window (tmux window / herdr tab) the agent's pane lives in: created\n * when missing, otherwise the pane is split into it. */\n window: string;\n /** mu's agent name. Backends with their own agent registry use it as\n * the mux-level handle too. */\n name: string;\n /** mu's `--cli` key, e.g. \"pi\". A backend that classifies agent kinds\n * natively maps this onto its own kind vocabulary. */\n cli: string;\n /** Fully resolved command string mu would run. */\n command: string;\n /**\n * Where `command` came from. A backend that resolves the executable\n * ITSELF must not silently discard an operator's explicit choice, and\n * needs to know which one it is so the diagnostic can name the right\n * thing to change:\n *\n * \"cli-key\" — just the `--cli` value; nothing to honour, proceed.\n * \"env\" — a `MU_<UPPER_CLI>_COMMAND` override.\n * \"explicit\" — an explicit `--command \"…\"`.\n */\n commandSource: CommandSource;\n /** Initial working directory for the pane. */\n cwd?: string;\n /** Identity and state env for the pane (tmux `-e`, herdr `--env`). */\n env: Record<string, string>;\n /**\n * Called as soon as the pane exists, before any readiness wait. The\n * caller records the pane id under its topology lock and lets the lock\n * go while a slow readiness wait (herdr: up to 30s) is still running.\n * The returned promise settles when the agent is started.\n */\n onPaneCreated?: (paneId: string) => void;\n /**\n * Keep the pane (its row and scrollback) after its command ends, armed\n * BEFORE the command can run, so an immediate exit is still readable with\n * `paneResult`. Honoured only by a backend with `paneResult`; the pane then\n * lives until `killPane`. Never changes a session or global default.\n */\n retainOnExit?: boolean;\n}\n\n/**\n * A pane's terminal result as the mux itself reports it. `exited` carries the\n * LOCAL command's status (a remote command's status is not this: see\n * src/agents/gate.ts); `code` xor `signal` is set.\n */\nexport type PaneResult =\n | { state: \"running\" }\n | { state: \"exited\"; code: number | null; signal: number | null }\n | { state: \"absent\" };\n\n/** Where an attach should land the user. */\nexport interface AttachTarget {\n /** Mux session name, e.g. `mu-auth`. */\n session: string;\n /** Window inside that session (the agent's `tab`, or its name). */\n window?: string;\n /** True when the caller is already inside a client of this mux, which\n * on tmux means `switch-client` rather than `attach-session`. */\n inside?: boolean;\n /** True when the steps are for a shell OUTSIDE any client of this mux (the line a\n * dashboard copies): they must open a client, whatever the ambient env says.\n * Wins over `inside` and over a backend's own env detection. */\n outside?: boolean;\n}\n\n/** One argv the caller may execute to hand the terminal to the mux. */\n/** Where a spawn's command came from: the cli key itself, `MU_<CLI>_COMMAND`, or `--command`. */\nexport type CommandSource = \"cli-key\" | \"env\" | \"explicit\";\n\nexport interface MuxCommand {\n command: string;\n args: readonly string[];\n /** Best-effort step: a non-zero exit is not a failure of the attach\n * as a whole (tmux's post-attach `select-window`, for instance). */\n optional?: boolean;\n /** Why an `optional` step may fail (shown when it does). */\n reason?: string;\n /** A client deliberately nested inside another tmux server's client: run it with\n * `$TMUX` removed (tmux refuses to nest otherwise). The shell line spells it `env -u TMUX`. */\n nested?: boolean;\n}\n\n/** What a backend can say about its own health. Deliberately DATA, not\n * prose: `mu doctor` owns all rendering (human and --json). */\nexport interface MuxHealth {\n /** Backend name, echoed so doctor can label the row. */\n name: MuxBackendName;\n /** True iff the backend answered a version probe. */\n ok: boolean;\n /** Version string as the backend reports it, or null when unreachable. */\n version: string | null;\n /** Ambient env facts this backend cares about, in display order\n * (tmux: $TMUX / $TMUX_PANE). Values are null when unset. */\n env: readonly { name: string; value: string | null }[];\n /** Remediation line shown when `ok` is false. */\n remediation: string;\n}\n\nexport interface SendOptions {\n /** 0 drops herdr's `--wait` (submit and return); any other value is ignored. */\n readinessMs?: number;\n /** Called when the send could not be confirmed as submitted. */\n onUndelivered?: (warning: SendWarning) => void;\n}\n\n/** Why a send could not be confirmed as submitted. */\nexport interface SendWarning {\n paneId: string;\n /** 'paste-vanished' — pane looked calm, but the text never registered. */\n reason: \"paste-vanished\";\n message: string;\n}\n\nexport interface CaptureOptions {\n /**\n * Number of trailing lines to capture. Omitted = full scrollback.\n * 0 = visible pane only.\n */\n lines?: number;\n}\n\n// ─── Attach line ───────────────────────────────────────────────────────\n\n/**\n * One copy-pasteable shell line for `steps`, joined with `&&` so a\n * failed required step stops everything after it. An `optional` step is\n * rendered `{ step || true; }`: its own failure never fails the line\n * and never stops what follows. Callers catch what `attachCommands`\n * throws (herdr: no such workspace) and omit the line.\n */\nexport function attachShellLine(steps: readonly MuxCommand[]): string {\n return steps\n .map((step) => {\n const words = [\n ...(step.nested === true ? [\"env\", \"-u\", \"TMUX\"] : []),\n step.command,\n ...step.args,\n ]\n .map(shellWord)\n .join(\" \");\n return step.optional === true ? `{ ${words} || true; }` : words;\n })\n .join(\" && \");\n}\n\n// ─── Errors ────────────────────────────────────────────────────────────\n\n/**\n * Base class for \"the multiplexer itself failed\". Each backend\n * subclasses it (tmux → `TmuxError`) so `handle()` can map the whole\n * family to exit code 5 (substrate unavailable) with one `instanceof`.\n */\nexport class MuxError extends Error {\n override name: string = \"MuxError\";\n}\n\n/**\n * Thrown when a verb references a pane id that doesn't exist on the\n * running multiplexer. Distinct from `MuxError` (which wraps any mux\n * command failure) so callers can map it to a specific exit code\n * (`mu` maps it to 5 alongside other mux issues, but the message is\n * more actionable than raw backend stderr).\n *\n * The backend-specific half of the remediation comes from the backend\n * that raised it: showing a herdr user `tmux info | head` would be\n * worse than showing no hint at all. Callers that construct this error\n * already hold the active backend, so passing it is free; the\n * no-backend form degrades to mu's own verbs only.\n */\nexport class PaneNotFoundError extends Error {\n override readonly name = \"PaneNotFoundError\";\n constructor(\n public readonly paneId: string,\n backend?: MuxDiagnostics,\n ) {\n super(say(\"mux.pane_not_found\", backend?.name ?? \"mux\", paneId));\n }\n}\n\n/** The slice of a backend `PaneNotFoundError` needs. Structural so the\n * error type doesn't depend on the whole backend contract. */\nexport interface MuxDiagnostics {\n readonly name: MuxBackendName;\n}\n\n/**\n * Thrown by `detectMux()` when no supported multiplexer is available.\n * Maps to exit 5 (substrate unavailable) — the same bucket as \"tmux is\n * installed but the server is unreachable\", because from the caller's\n * point of view both mean \"mu cannot reach a pane right now\".\n */\nexport class NoMultiplexerError extends Error {\n override readonly name = \"NoMultiplexerError\";\n constructor(public readonly tried: readonly string[]) {\n super(say(\"mux.none_found\", tried));\n }\n}\n\n// ─── The backend contract ──────────────────────────────────────────────\n\n/**\n * One multiplexer implementation. Methods mirror the operations mu\n * actually performs; nothing is here speculatively.\n *\n * Implementations must be stateless value objects (a frozen record of\n * functions), so swapping the active backend is a pointer assignment\n * and tests can install a fake without teardown ordering hazards.\n */\nexport interface MuxBackend {\n readonly name: MuxBackendName;\n /** True when `spawnAgent` returns only once the MUX considers the agent\n * ready for input (herdr's `agent start` blocks until it detects the\n * agent). spawn.ts then skips its own liveness/readiness polling. A\n * capability flag, never a backend-name check. */\n readonly spawnAgentWaitsReady: boolean;\n /** True when `spawnAgent` runs `opts.command` as a shell command line in\n * the pane (tmux). herdr starts a known agent kind itself, so it cannot\n * run a host profile's shell template (`spawn --host`). A capability\n * flag, never a backend-name check. */\n readonly runsShellCommand: boolean;\n\n /** True iff this backend can drive panes on this machine right now.\n * Consulted by `detectMux()` in precedence order. */\n available(): Promise<boolean>;\n\n // — pane id validation (shape is backend-specific) —\n isValidPaneId(s: string): boolean;\n assertValidPaneId(s: string): void;\n\n // — sessions —\n /** Create `session` with its placeholder `_mu` window when missing;\n * re-add a missing `_mu` window to an existing one. Load-bearing:\n * mux errors propagate. */\n ensureSession(session: string): Promise<EnsureSessionResult>;\n /** Idempotent. herdr closes the workspace and refuses (surfacing\n * `HerdrWorkspaceGroupCloseError`) when it has linked worktree\n * workspaces mu did not create. */\n killSession(session: string): Promise<void>;\n\n // — panes —\n /** Create the agent's pane (new window, or a split of the existing\n * `opts.window`; the session is created when missing) and run the\n * agent in it. Returns the pane id. tmux: one step running\n * `opts.command`. herdr: a bare shell pane, then `agent start --kind`\n * with a busy retry; refuses `commandSource` ≠ \"cli-key\" with\n * `HerdrCommandOverrideError` before touching herdr and closes the\n * bare pane when the start fails. */\n spawnAgent(opts: SpawnAgentPaneOptions): Promise<string>;\n /** Every pane in `session`. `[]` when the session (or server) is gone;\n * any other failure throws, so a caller that prunes on absence never\n * reads an unreachable mux as \"zero panes\". */\n listPanes(session: string): Promise<MuxPane[]>;\n /** False only when the mux reports the pane (or server) gone; throws\n * when the probe itself fails, so liveness gates fail closed. */\n paneAlive(paneId: string): Promise<boolean>;\n killPane(paneId: string): Promise<void>;\n capture(paneId: string, opts?: CaptureOptions): Promise<string>;\n\n // — attach —\n /** Ordered argv steps that land the user on `target` (some optional,\n * see `MuxCommand.reason`). May throw when the target cannot be\n * resolved (herdr: no workspace carries the label). Join with\n * `attachShellLine` for a printable line. */\n attachCommands(target: AttachTarget): Promise<readonly MuxCommand[]>;\n\n // — optional capabilities —\n /** The pane's runtime state as the mux itself reports it, or undefined\n * when the pane is gone or unclassified. herdr only: for non-pi agents. */\n paneStatus?(paneId: string): Promise<MuxPaneStatus | undefined>;\n /** tmux only: whether the pane runs, exited (a retained pane: `retainOnExit`)\n * or is gone. Unlike `paneAlive` (handle existence), an exited pane is NOT\n * running here. Throws when the probe itself fails: unknown, never a result. */\n paneResult?(paneId: string): Promise<PaneResult>;\n /** herdr only: atomic `agent prompt`. tmux has no reliable paste (cut in\n * 4.0), so callers branch on the method's presence, never on\n * `mux.name`, and refuse when it is absent. */\n sendToPane?(paneId: string, text: string, opts?: SendOptions): Promise<void>;\n /** The argv steps that type pi's `/reload` into `paneId` from outside, for\n * an agent whose extension cannot take `/reload` over ctl. herdr only\n * (its `agent prompt`); tmux has no reliable paste, so it omits this and\n * callers branch on presence. */\n reloadCommands?(paneId: string): readonly MuxCommand[];\n\n /**\n * Name of the session the CALLER is running inside, or undefined when\n * outside one.\n * Suggestion only (the no-scope hint, the TUI start workstream); never routes a verb.\n */\n currentSessionName(): Promise<string | undefined>;\n /** Version + ambient facts for `mu doctor`. Never throws: an\n * unreachable backend reports `ok: false`. */\n healthCheck(): Promise<MuxHealth>;\n}\n","// mu — herdr substrate (TOPOLOGY half).\n//\n// Single source of truth for all herdr interactions. Every herdr\n// invocation goes through `herdr(args)`, which wraps child_process and produces\n// structured `HerdrError`s carrying args + the server's JSON error.\n//\n// ─── The mapping ──────────────────────────────────────────────────────\n//\n// herdr's own \"session\" is SERVER-level (one socket per named session),\n// so it is NOT the workstream unit. The locked mapping (see\n// docs/architecture/mux.md § \"One mux session per workstream\") is:\n//\n// mu workstream = herdr WORKSPACE, labelled `mu-<name>`\n// mu window = herdr TAB\n// mu agent = herdr PANE\n//\n// mu addresses workspaces BY LABEL (the session name), because that is\n// the only handle mu persists. herdr addresses them by opaque id (`w1`).\n// Every session-taking method therefore resolves label → id first; see\n// `resolveWorkspaceId`.\n//\n// ─── Protocol notes ───────────────────────────────────────────────────\n//\n// - Every command emits JSON on stdout under `.result`. IDs are READ\n// from creation responses, never predicted or constructed. herdr's\n// skill doc is explicit about this and closed ids are not reused.\n// - `--no-focus` on EVERY mutating call. mu must never steal the\n// user's focus out from under them.\n// - Server errors are JSON on STDERR with exit 1 → `HerdrError`\n// (a `MuxError`, exit 5: the substrate said no).\n// - SYNTAX errors exit 2 → `HerdrSyntaxError`, which is deliberately\n// NOT a `MuxError`. A herdr CLI that renamed a flag under us is a\n// BUG IN MU, and must not masquerade as \"herdr is down\".\n//\n// ─── Scope ────────────────────────────────────────────────────────────\n//\n// This module implements ALL of `MuxBackend` for herdr: sessions\n// (`ensureSession`, `killSession`), panes (`spawnAgent`, `listPanes`,\n// `paneAlive`, `killPane`, `capture`), pane-id validation, availability,\n// send, native pane status and attach.\n//\n// ─── Two exceptions to \"everything is JSON\" ───────────────────────────\n//\n// `herdr status` and `herdr pane read` both emit PLAIN TEXT. They go\n// through `currentExecutor` directly rather than `herdr()`, which would\n// reject their unparseable stdout as CLI drift.\n//\n// ─── Why spawn is two steps ───────────────────────────────────────────\n//\n// herdr has NO create-and-run form: `workspace create` / `tab create` /\n// `pane split` always start a plain shell, and `agent start` never\n// creates, splits or moves layout — it requires an ALREADY-EXISTING\n// pane sitting at its interactive prompt. `spawnAgent` therefore makes a\n// bare pane and then runs `agent start`; callers never see the two\n// halves.\n\nimport { execFileCapture } from \"../exec-file.js\";\nimport { say } from \"../messages.js\";\nimport { isJsonMode } from \"../output.js\";\nimport { sleep } from \"./tmux.js\";\nimport {\n type AttachTarget,\n type CaptureOptions,\n type EnsureSessionResult,\n MU_PLACEHOLDER_WINDOW,\n type MuxBackend,\n type MuxCommand,\n MuxError,\n type MuxHealth,\n type MuxPane,\n type MuxPaneStatus,\n type SendOptions,\n type SendWarning,\n type SpawnAgentPaneOptions,\n} from \"./types.js\";\n\n// ─── Error types ───────────────────────────────────────────────────────\n\n/**\n * \"herdr itself failed\" — the server returned a JSON error, or the\n * binary could not be reached. A `MuxError`, so `handle()` maps the\n * whole family to exit 5 with one `instanceof`. Mirrors `TmuxError`.\n */\nexport class HerdrError extends MuxError {\n constructor(\n public readonly args: readonly string[],\n public readonly stderr: string,\n public readonly stdout: string,\n public readonly exitCode: number | null,\n /** herdr's machine-readable error code (e.g. `pane_not_found`), when\n * the stderr payload parsed as the documented JSON envelope. */\n public readonly code?: string,\n ) {\n const detail = parseErrorEnvelope(stderr)?.message ?? (stderr.trim() || stdout.trim());\n super(say(\"mux.herdr_failed\", args, exitCode, detail || \"no output\"));\n this.name = \"HerdrError\";\n }\n}\n\n/**\n * herdr rejected our ARGUMENTS (exit 2). Deliberately not a `MuxError`:\n * the substrate is healthy and mu asked it something ungrammatical.\n * That is a bug in this file — most likely CLI drift after a herdr\n * upgrade — and must surface as one instead of being swallowed into\n * the \"herdr is down\" bucket, where it would waste hours.\n */\nexport class HerdrSyntaxError extends Error {\n override readonly name = \"HerdrSyntaxError\";\n constructor(\n public readonly args: readonly string[],\n public readonly output: string,\n ) {\n super(say(\"mux.herdr_syntax\", args, output.trim().split(\"\\n\")[0] ?? \"(no output)\"));\n }\n}\n\n/**\n * `mu agent spawn --cli <key>` named something herdr does not recognise\n * as an interactive agent kind.\n *\n * A REFUSAL, not a fallback. herdr's `pane run <command>` would happily\n * start the binary, but herdr would then never classify that pane, and\n * on this backend herdr's report is mu's runtime state source. A pane\n * mu can start but never observe is the same family of failure as a pane mu records\n * with nothing running in it: it looks fine and lies forever.\n *\n * Not a `MuxError`: the substrate is healthy and answered precisely.\n * This is an operator asking for something the active backend cannot\n * do, which `handle()` maps to exit 2 alongside the usage family.\n *\n * herdr is the AUTHORITY on the kind list — mu does not hardcode one,\n * it forwards `--cli` and translates herdr's rejection. A herdr release\n * that adds a kind therefore works without a mu change.\n */\nexport class HerdrUnsupportedCliError extends Error {\n override readonly name = \"HerdrUnsupportedCliError\";\n constructor(\n public readonly cli: string,\n public readonly detail: string,\n ) {\n super(say(\"mux.herdr_unsupported_cli\", cli, detail));\n }\n}\n\n/**\n * The operator pinned an exact command line — `--command \"…\"` or\n * `MU_<UPPER_CLI>_COMMAND` — and herdr cannot honour it.\n *\n * `herdr agent start --kind <k>` resolves the canonical executable\n * ITSELF; there is no \"use this binary instead\" flag. Args after `--`\n * are passed to the agent, NOT used to choose it (verified against\n * 0.8.0: `agent start x --kind pi -- --model m` reports `argv:[\"pi\"]`;\n * 0.9.0 still exposes no override flag), so forwarding an override\n * there would append a binary\n * NAME as an argument and start the wrong thing while reporting success.\n *\n * Accepting the override and not honouring it is the one outcome ruled\n * out, so mu refuses and names the variable.\n */\nexport class HerdrCommandOverrideError extends Error {\n override readonly name = \"HerdrCommandOverrideError\";\n constructor(\n public readonly cli: string,\n public readonly command: string,\n /** The `MU_<UPPER_CLI>_COMMAND` var, when that is where the override\n * came from; undefined for an explicit `--command`. */\n public readonly envVar?: string,\n ) {\n super(\n say(\n \"mux.herdr_command_override\",\n cli,\n envVar === undefined ? `--command ${JSON.stringify(command)}` : `${envVar}=${command}`,\n ),\n );\n }\n}\n\n/** herdr's refusal (0.9.0+) to close a workspace that has linked\n * worktree workspaces without explicit group intent. */\nconst GROUP_CLOSE_REQUIRED_CODE = \"workspace_group_close_required\";\n\n/**\n * `mu workstream destroy` asked herdr to close the workstream's\n * workspace, and herdr refused because worktree workspaces are linked\n * to it (herdr 0.9.0+).\n *\n * mu does NOT retry with `--group`. Those sibling workspaces are not\n * mu's: they were created by `herdr worktree`, they host panes mu never\n * spawned, and mu has no way to know whether the user still wants them.\n * Closing them to satisfy a teardown would destroy unsaved work with no\n * undo, which is the one outcome ruled out.\n *\n * Not a `MuxError`: the substrate is healthy and answered precisely.\n * This is a decision only the operator can make, so it lands in the\n * usage lane (exit 2) beside the other herdr refusals. Thrown BEFORE\n * any DB rows are deleted — `teardownWorkstream` kills the mux session\n * first for exactly this reason — so the workstream is left intact and\n * the command is safe to re-run.\n */\nexport class HerdrWorkspaceGroupCloseError extends Error {\n override readonly name = \"HerdrWorkspaceGroupCloseError\";\n constructor(\n public readonly session: string,\n public readonly workspaceId: string,\n public readonly detail: string,\n ) {\n super(say(\"mux.herdr_group_close\", workspaceId, session, detail));\n }\n}\n\n// ─── Pane / workspace / tab ID validation ──────────────────────────────\n//\n// herdr's public ids are opaque stable handles with a documented shape:\n// workspace `w1`, tab `w1:t1`, pane `w1:p1`. Pane ids are workspace-\n// qualified, so a pane MOVED between workspaces gets a NEW id — mu must\n// re-read it from `.result.move_result.pane.pane_id`, never reuse the old.\n//\n// This is exactly why `isValidPaneId` is a backend method: a tmux `%15`\n// must be rejected here, and a herdr `w1:p1` must be rejected by tmux.\n//\n// The ORDINALS ARE NOT DECIMAL. Verified on herdr 0.8.0 by opening 38\n// panes: the sequence runs `p1 … p9, pA, pB, … pH, pJ, pK, pM, pN, pP …\n// pZ, p10, p11 …` — Crockford base32 (digits plus A-Z minus I, L, O, U).\n// Workspace and tab ordinals use the same alphabet (`wA` after `w9`).\n// A decimal-only pattern therefore works for exactly nine panes and then\n// starts rejecting live ids, which on the spawn path is a TypeError on\n// the 10th agent in a workstream. Matched as an opaque `[0-9A-Z]+` run\n// rather than by spelling out the alphabet: mu's job is to tell a herdr\n// id from a tmux one, not to re-derive herdr's numbering.\n\nconst HERDR_ORDINAL = \"[0-9A-Z]+\";\nexport const PANE_ID_RE = new RegExp(`^w${HERDR_ORDINAL}:p${HERDR_ORDINAL}$`);\nconst WORKSPACE_ID_RE = new RegExp(`^w${HERDR_ORDINAL}$`);\n\nexport function isValidPaneId(s: string): boolean {\n return PANE_ID_RE.test(s);\n}\n\nexport function assertValidPaneId(s: string): void {\n if (!isValidPaneId(s)) {\n throw new TypeError(\n `invalid herdr pane id: ${JSON.stringify(s)} (expected ${PANE_ID_RE.source})`,\n );\n }\n}\n\n// ─── Executor (swappable for tests) ────────────────────────────────────\n\nexport interface HerdrExecResult {\n stdout: string;\n stderr: string;\n exitCode: number | null;\n}\n\nexport type HerdrExecutor = (args: readonly string[]) => Promise<HerdrExecResult>;\n\n/**\n * Optional `--session <name>` prefix spliced in front of every args\n * vector. When `MU_HERDR_SESSION=<name>` is set, mu drives a NAMED\n * herdr server (its own socket under\n * `~/.config/herdr/sessions/<name>/herdr.sock`) instead of the user's\n * default one. Mirrors `MU_TMUX_SOCKET`: it is the isolation seam any\n * integration test must use so the suite can never observe — or\n * destroy — the user's real panes.\n *\n * Read fresh on every call so a setup hook mutating the env mid-run\n * takes effect immediately.\n */\nfunction herdrGlobalFlags(): readonly string[] {\n const session = process.env.MU_HERDR_SESSION;\n if (session === undefined || session.length === 0) return [];\n return [\"--session\", session];\n}\n\nconst realExecutor: HerdrExecutor = (args) =>\n execFileCapture(\"herdr\", [...herdrGlobalFlags(), ...args]);\n\nlet currentExecutor: HerdrExecutor = realExecutor;\n\n/**\n * Install a custom executor (for tests). Returns the previous executor\n * so tests can restore it cleanly. Production code never calls this.\n * Required: the fast test tier may not shell out.\n */\nexport function setHerdrExecutor(executor: HerdrExecutor): HerdrExecutor {\n const previous = currentExecutor;\n currentExecutor = executor;\n return previous;\n}\n\n/** Restore the real (child_process-backed) executor. */\nexport function resetHerdrExecutor(): void {\n currentExecutor = realExecutor;\n}\n\n// ─── JSON envelope ─────────────────────────────────────────────────────\n\n/** herdr's error payload: `{\"error\":{\"code\":\"…\",\"message\":\"…\"},\"id\":\"…\"}`. */\ninterface HerdrErrorEnvelope {\n code: string;\n message: string;\n}\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction asString(v: unknown): string | undefined {\n return typeof v === \"string\" ? v : undefined;\n}\n\nfunction parseErrorEnvelope(stderr: string): HerdrErrorEnvelope | undefined {\n const trimmed = stderr.trim();\n if (trimmed.length === 0) return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n return undefined;\n }\n if (!isRecord(parsed)) return undefined;\n const err = parsed.error;\n if (!isRecord(err)) return undefined;\n const code = asString(err.code);\n const message = asString(err.message);\n if (code === undefined) return undefined;\n return { code, message: message ?? code };\n}\n\n/**\n * Run a herdr command and return the parsed `.result` object.\n *\n * The single point of contact with the herdr binary; every higher-level\n * operation in this module goes through it.\n *\n * Throws `HerdrSyntaxError` on exit 2 (mu bug), `HerdrError` on any\n * other non-zero exit (substrate failure).\n */\nexport async function herdr(args: readonly string[]): Promise<Record<string, unknown>> {\n const result = await currentExecutor(args);\n if (result.exitCode === 2) {\n throw new HerdrSyntaxError([...args], result.stderr || result.stdout);\n }\n if (result.exitCode !== 0) {\n throw new HerdrError(\n [...args],\n result.stderr,\n result.stdout,\n result.exitCode,\n parseErrorEnvelope(result.stderr)?.code,\n );\n }\n const trimmed = result.stdout.trim();\n if (trimmed.length === 0) return {};\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n // A zero exit with unparseable stdout means the CLI stopped speaking\n // JSON — same class of problem as exit 2, but we cannot prove it is\n // ours, so keep it in the substrate bucket.\n throw new HerdrError([...args], result.stderr, result.stdout, result.exitCode);\n }\n if (!isRecord(parsed)) return {};\n const inner = parsed.result;\n return isRecord(inner) ? inner : {};\n}\n\n/** Like `herdr()` but returns undefined instead of throwing when the\n * server's error code is one of `tolerate`. Used for the idempotent\n * destructive verbs (\"succeeds even if it is already gone\"). */\nasync function herdrTolerating(\n args: readonly string[],\n tolerate: readonly string[],\n): Promise<Record<string, unknown> | undefined> {\n try {\n return await herdr(args);\n } catch (err) {\n if (err instanceof HerdrError && err.code !== undefined && tolerate.includes(err.code)) {\n return undefined;\n }\n throw err;\n }\n}\n\n// ─── Response shapes ───────────────────────────────────────────────────\n//\n// Narrow readers over herdr's JSON: they pull only the fields mu uses\n// and drop anything malformed, so one odd row never poisons a listing.\n\ninterface HerdrWorkspace {\n workspaceId: string;\n label: string;\n}\n\nfunction readWorkspace(v: unknown): HerdrWorkspace | undefined {\n if (!isRecord(v)) return undefined;\n const workspaceId = asString(v.workspace_id);\n if (workspaceId === undefined) return undefined;\n return { workspaceId, label: asString(v.label) ?? \"\" };\n}\n\ninterface HerdrTab {\n id: string;\n name: string;\n}\n\nfunction readTab(v: unknown): HerdrTab | undefined {\n if (!isRecord(v)) return undefined;\n const id = asString(v.tab_id);\n if (id === undefined) return undefined;\n // herdr auto-labels a tab with its ordinal (\"1\"), which is the closest\n // analogue to a tmux window name; mu labels every tab it creates.\n return { id, name: asString(v.label) ?? \"\" };\n}\n\nfunction readPane(v: unknown): MuxPane | undefined {\n if (!isRecord(v)) return undefined;\n const paneId = asString(v.pane_id);\n if (paneId === undefined) return undefined;\n return {\n paneId,\n // herdr reports no foreground command on `pane list` (that costs a\n // `pane process-info` round trip per pane), but it does report the\n // agent kind it detected (`pi`, `claude`, `codex`, ...). That is\n // what `command` is used for: reconcile's orphan recogniser matches\n // it against the agent CLIs. Empty for a plain shell.\n command: asString(v.agent) ?? \"\",\n windowId: asString(v.tab_id),\n };\n}\n\nfunction readArray(result: Record<string, unknown>, key: string): unknown[] {\n const v = result[key];\n return Array.isArray(v) ? v : [];\n}\n\n// ─── Workspaces (= mu sessions) ────────────────────────────────────────\n\nasync function listWorkspaces(): Promise<HerdrWorkspace[]> {\n const result = await herdr([\"workspace\", \"list\"]);\n const out: HerdrWorkspace[] = [];\n for (const raw of readArray(result, \"workspaces\")) {\n const ws = readWorkspace(raw);\n if (ws) out.push(ws);\n }\n return out;\n}\n\n/**\n * Resolve a mu session name (= herdr workspace LABEL) to herdr's opaque\n * workspace id. Returns undefined when no workspace carries that label.\n *\n * Labels are not unique in herdr — an unlabelled `workspace create`\n * defaults the label to the cwd's basename, so a user could plausibly\n * have two. mu only ever creates `mu-<workstream>` labels and refuses\n * duplicate workstream names, so the first match is the right one; the\n * ambiguity is inherent to addressing by label and is why every mutating\n * path resolves once and then works in ids.\n */\nasync function resolveWorkspaceId(name: string): Promise<string | undefined> {\n for (const ws of await listWorkspaces()) {\n if (ws.label === name) return ws.workspaceId;\n }\n return undefined;\n}\n\n/** Resolve or throw. Used by paths where a missing workspace is a real\n * substrate failure rather than an expected \"already gone\". */\nasync function requireWorkspaceId(name: string): Promise<string> {\n const id = await resolveWorkspaceId(name);\n if (id === undefined) {\n throw new HerdrError(\n [\"workspace\", \"list\"],\n `{\"error\":{\"code\":\"workspace_not_found\",\"message\":\"no herdr workspace labelled ${name}\"}}`,\n \"\",\n 1,\n \"workspace_not_found\",\n );\n }\n return id;\n}\n\n/**\n * Create `session`'s workspace with its placeholder `_mu` tab when it is\n * missing, and re-add the tab when the workspace exists without it.\n *\n * mu ALWAYS passes `--no-focus`, because stealing the user's focus is the\n * one thing a background agent manager must never do.\n */\nexport async function ensureSession(session: string): Promise<EnsureSessionResult> {\n const id = await resolveWorkspaceId(session);\n if (id === undefined) {\n const created = await herdr([\"workspace\", \"create\", \"--label\", session, \"--no-focus\"]);\n await labelRootTab(created, MU_PLACEHOLDER_WINDOW);\n return { created: true, repaired: false };\n }\n const tabs = readTabs(await herdr([\"tab\", \"list\", \"--workspace\", id]));\n if (tabs.some((t) => t.name === MU_PLACEHOLDER_WINDOW)) {\n return { created: false, repaired: false };\n }\n await herdr([\"tab\", \"create\", \"--workspace\", id, \"--label\", MU_PLACEHOLDER_WINDOW, \"--no-focus\"]);\n return { created: false, repaired: true };\n}\n\n/**\n * herdr labels a new workspace's implicit first tab \"1\". mu finds tabs\n * by window name (attach focuses the agent's tab, spawn reuses a tab by\n * `--tab`, init checks for `_mu`), so rename it to `windowName`, the\n * label `tab create` gives every later tab. Load-bearing: an unlabelled\n * first tab is invisible to all three lookups. On failure the new\n * workspace is closed before the error propagates.\n */\nasync function labelRootTab(\n created: Record<string, unknown>,\n windowName: string | undefined,\n): Promise<void> {\n if (windowName === undefined || windowName.length === 0) return;\n const root = created.root_pane;\n const tab = created.tab;\n const tabId =\n (isRecord(root) ? asString(root.tab_id) : undefined) ??\n (isRecord(tab) ? asString(tab.tab_id) : undefined);\n try {\n if (tabId === undefined) {\n throw new HerdrError(\n [\"workspace\", \"create\"],\n `herdr response had no root tab id: ${JSON.stringify(created)}`,\n \"\",\n 0,\n );\n }\n await herdr([\"tab\", \"rename\", tabId, windowName]);\n } catch (err) {\n await closeCreatedWorkspace(created);\n throw err;\n }\n}\n\n/**\n * Best-effort rollback for a workspace this call just created: the caller\n * never got a pane id, so spawn's rollback cannot reach it. The original\n * error is what the caller must see, so a failed close is swallowed.\n */\nasync function closeCreatedWorkspace(created: Record<string, unknown>): Promise<void> {\n const ws = created.workspace;\n const root = created.root_pane;\n const id =\n (isRecord(ws) ? asString(ws.workspace_id) : undefined) ??\n (isRecord(root) ? asString(root.workspace_id) : undefined);\n if (id === undefined) return;\n try {\n await herdrTolerating([\"workspace\", \"close\", id], [\"workspace_not_found\"]);\n } catch {\n // Best effort; the rename error propagates.\n }\n}\n\n/**\n * Idempotent: succeeds even if the workspace is already gone.\n *\n * REFUSES, and does not retry with `--group`, when herdr reports\n * `workspace_group_close_required` (0.9.0+): the workspace has linked\n * worktree workspaces mu did not create, and closing the whole group\n * would take down panes outside this workstream. herdr's own skill doc\n * calls adding `--group` to bypass that error out by name. The operator\n * decides; mu names the command.\n */\nexport async function killSession(name: string): Promise<void> {\n const id = await resolveWorkspaceId(name);\n if (id === undefined) return;\n try {\n await herdrTolerating([\"workspace\", \"close\", id], [\"workspace_not_found\"]);\n } catch (err) {\n if (err instanceof HerdrError && err.code === GROUP_CLOSE_REQUIRED_CODE) {\n throw new HerdrWorkspaceGroupCloseError(name, id, err.message);\n }\n throw err;\n }\n}\n\n// ─── Tabs (= mu windows) ───────────────────────────────────────────────\n\nfunction readTabs(result: Record<string, unknown>): HerdrTab[] {\n const out: HerdrTab[] = [];\n for (const raw of readArray(result, \"tabs\")) {\n const tab = readTab(raw);\n if (tab) out.push(tab);\n }\n return out;\n}\n\n// ─── Panes (= mu agents) ───────────────────────────────────────────────\n\n/**\n * List every pane in a workspace, addressed by mu session name (= label).\n *\n * Returns `[]` rather than throwing when the workspace is gone: herdr\n * closes a workspace when its last pane exits, so \"it was here a moment\n * ago\" is normal during reconciliation. Same contract as the tmux\n * backend; any other failure throws.\n */\nexport async function listPanes(session: string): Promise<MuxPane[]> {\n const id = await resolveWorkspaceId(session);\n if (id === undefined) return [];\n const result = await herdrTolerating(\n [\"pane\", \"list\", \"--workspace\", id],\n [\"workspace_not_found\"],\n );\n if (result === undefined) return [];\n return readPanes(result);\n}\n\nfunction readPanes(result: Record<string, unknown>): MuxPane[] {\n const out: MuxPane[] = [];\n for (const raw of readArray(result, \"panes\")) {\n const pane = readPane(raw);\n if (pane) out.push(pane);\n }\n return out;\n}\n\n/** Idempotent: succeeds even if the pane is already gone. */\nexport async function killPane(paneId: string): Promise<void> {\n assertValidPaneId(paneId);\n await herdrTolerating([\"pane\", \"close\", paneId], [\"pane_not_found\", \"workspace_not_found\"]);\n}\n\nexport async function paneAlive(paneId: string): Promise<boolean> {\n if (!isValidPaneId(paneId)) return false;\n const pane = await getPane(paneId);\n return pane !== undefined;\n}\n\n/** `pane get`, or undefined when the pane (or its workspace) is gone. */\nasync function getPane(paneId: string): Promise<MuxPane | undefined> {\n const result = await herdrTolerating(\n [\"pane\", \"get\", paneId],\n [\"pane_not_found\", \"workspace_not_found\"],\n );\n if (result === undefined) return undefined;\n return readPane(result.pane);\n}\n\n/**\n * Label of the workspace the CALLER is running inside, or undefined\n * outside a managed pane. Backs the `mu-<name>` rung of workstream\n * auto-detection.\n *\n * herdr injects `$HERDR_WORKSPACE_ID` into every pane it manages, so\n * this is one lookup rather than tmux's `display-message -p '#S'`. The\n * env var carries the opaque id; mu keys on the LABEL, so resolve it.\n */\nexport async function currentSessionName(): Promise<string | undefined> {\n const workspaceId = process.env.HERDR_WORKSPACE_ID;\n if (workspaceId === undefined || !WORKSPACE_ID_RE.test(workspaceId)) return undefined;\n for (const ws of await listWorkspaces()) {\n if (ws.workspaceId === workspaceId) return ws.label;\n }\n return undefined;\n}\n\n// ─── IO ────────────────────────────────────────────────────────────────\n//\n// THE SEND PROTOCOL IS ONE CALL. A tmux paste-then-Enter can be swallowed\n// by a TUI rendering a modal, stranding the text while `mu agent send`\n// reports exit 0 (dogfood_send_after_new_dropped); tmux therefore has no\n// send (cut in 4.0).\n//\n// `herdr agent prompt` submits the text AND an encoded Enter atomically,\n// honouring the pane's live bracketed-paste mode, so the Enter cannot be\n// separated from the paste and cannot be swallowed. There is nothing\n// left for a quiescence poll to protect against — porting one here would\n// re-add latency to work around a bug this substrate does not have.\n//\n// Do not add a scrollback poll to this file. If a send ever looks\n// unconfirmed on herdr, that is a herdr bug, and the `agent_prompt_\n// stalled` guard below is how it surfaces.\n\n// ─── Spawn ─────────────────────────────────────────────────────────────\n\n/**\n * Retry budget for `agent start` while herdr reports the target pane is\n * not yet an available shell.\n *\n * VERIFIED RACE (0.8.0): `agent start` immediately after `pane split`\n * fails `agent_pane_busy` ~100% of the time; with a 200ms gap it\n * succeeded every time. The pane exists the moment split returns, but its\n * shell has not drawn a prompt yet, and `agent start` requires an\n * interactive prompt with nothing in the foreground.\n *\n * A retry rather than a fixed pre-sleep: the condition is observable, so\n * mu polls instead of guessing a constant that is simultaneously too long\n * for a fast box and too short for a loaded one. ~3s nominal, because\n * losing the race means a rolled-back spawn while a pane that never frees\n * up is a real failure and must not be spun on forever. Counted in\n * ATTEMPTS not wall-clock, so `setSleepForTests` alone makes the loop\n * instant and deterministic in the fast tier.\n */\nconst PANE_READY_RETRY_INTERVAL_MS = 50;\nconst PANE_READY_MAX_ATTEMPTS = 60;\n\n/**\n * Create the agent's bare shell pane (workspace, tab or split as needed)\n * and turn it into a running agent, returning only once herdr considers\n * that agent ready for input.\n *\n * `herdr agent start <name> --kind <cli> --pane <id>` blocks until herdr\n * has DETECTED the expected agent in that terminal and it is\n * interactive-ready (30s default timeout, herdr's own). That subsumes\n * mu's tmux-side scrollback polling completely, which is why\n * `spawnAgentWaitsReady` is true and `src/agents/spawn.ts` skips it.\n *\n * Refusals, all deliberate (see each error class), and none leaves a\n * pane behind:\n * - an operator-pinned command → `HerdrCommandOverrideError`\n * (decided locally, before touching herdr)\n * - a `--cli` herdr does not know → `HerdrUnsupportedCliError`\n * - an agent name herdr rejects → the raw `HerdrError`\n * When the start fails the bare pane is closed before the error\n * propagates.\n *\n * Addressed BY PANE ID: the herdr-level agent NAME is cleared when the\n * occupant exits, so the pane id is the only durable handle (and the\n * only one mu persists). Matching `sendToPane`'s choice.\n */\nexport async function spawnAgent(opts: SpawnAgentPaneOptions): Promise<string> {\n if (opts.commandSource !== \"cli-key\") {\n throw new HerdrCommandOverrideError(\n opts.cli,\n opts.command,\n // Name the env var only when that is actually where the override\n // came from; \"unset MU_PI_COMMAND\" is useless advice to someone who\n // typed --command.\n opts.commandSource === \"env\" ? envVarNameForCli(opts.cli) : undefined,\n );\n }\n const paneId = await createBarePane(opts);\n try {\n opts.onPaneCreated?.(paneId);\n await startAgent(paneId, opts);\n return paneId;\n } catch (err) {\n await killPane(paneId).catch(() => {});\n throw err;\n }\n}\n\n/**\n * A bare shell pane in `opts.window` of `opts.session`'s workspace:\n * - no workspace → create it (the root tab is labelled `window`)\n * - no such tab → create the tab\n * - tab exists → split one of its panes (herdr splits panes, not\n * tabs; geometry is the user's business, any pane in the tab will do)\n */\nasync function createBarePane(opts: SpawnAgentPaneOptions): Promise<string> {\n const workspaceId = await resolveWorkspaceId(opts.session);\n if (workspaceId === undefined) {\n const args = [\"workspace\", \"create\", \"--label\", opts.session, \"--no-focus\"];\n if (opts.cwd) args.push(\"--cwd\", opts.cwd);\n appendEnvFlags(args, opts.env);\n const result = await herdr(args);\n const paneId = readCreatedPaneId(result, \"root_pane\", args);\n await labelRootTab(result, opts.window);\n return paneId;\n }\n const tab = readTabs(await herdr([\"tab\", \"list\", \"--workspace\", workspaceId])).find(\n (t) => t.name === opts.window,\n );\n if (tab === undefined) {\n const args = [\n \"tab\",\n \"create\",\n \"--workspace\",\n workspaceId,\n \"--label\",\n opts.window,\n \"--no-focus\",\n ];\n if (opts.cwd) args.push(\"--cwd\", opts.cwd);\n appendEnvFlags(args, opts.env);\n return readCreatedPaneId(await herdr(args), \"root_pane\", args);\n }\n const panes = readPanes(await herdr([\"pane\", \"list\", \"--workspace\", workspaceId]));\n const target = panes.find((p) => p.windowId === tab.id);\n if (target === undefined) {\n // An empty tab cannot exist: it vanished between the two listings.\n throw new Error(say(\"mux.herdr_no_panes\", tab.id, opts.session));\n }\n const args = [\"pane\", \"split\", target.paneId, \"--direction\", \"right\", \"--no-focus\"];\n if (opts.cwd) args.push(\"--cwd\", opts.cwd);\n appendEnvFlags(args, opts.env);\n return readCreatedPaneId(await herdr(args), \"pane\", args);\n}\n\nasync function startAgent(paneId: string, opts: SpawnAgentPaneOptions): Promise<void> {\n const args = [\"agent\", \"start\", opts.name, \"--kind\", opts.cli, \"--pane\", paneId];\n for (let attempt = 1; ; attempt += 1) {\n try {\n await herdr(args);\n return;\n } catch (err) {\n // An unknown --kind is a SYNTAX error to herdr's arg parser (exit\n // 2), because `--kind` is a closed enum. Everywhere else exit 2\n // means mu drifted from the CLI, so translate it here — an\n // operator typo must not read as \"bug in mu\".\n if (err instanceof HerdrSyntaxError) {\n throw new HerdrUnsupportedCliError(opts.cli, err.output.trim().split(\"\\n\")[0] ?? \"\");\n }\n const busy = err instanceof HerdrError && err.code === \"agent_pane_busy\";\n if (!busy || attempt >= PANE_READY_MAX_ATTEMPTS) throw err;\n await sleep(PANE_READY_RETRY_INTERVAL_MS);\n }\n }\n}\n\n/**\n * `MU_<UPPER_CLI>_COMMAND`, mirroring `envVarNameForCli` in\n * src/agents/spawn.ts. Duplicated rather than imported because the mux\n * cluster may not depend on the agent layer (imports run cluster →\n * root, never sideways into another feature); it is one string join and\n * `test/mux-herdr-spawn.test.ts` asserts the two stay identical.\n */\nfunction envVarNameForCli(cli: string): string {\n return `MU_${cli.toUpperCase().replace(/-/g, \"_\")}_COMMAND`;\n}\n\n// ─── IO (owned by mux-herdr-io) ────────────────────────────────────────\n\n/** herdr's error code for \"submitted, but the agent's lifecycle never\n * moved within its 5s guard\". Not an outage — a suspicious send. */\nconst PROMPT_STALLED_CODE = \"agent_prompt_stalled\";\n\n/** Codes meaning \"the pane hosts no RECOGNIZED agent\", so the `agent`\n * surface cannot address it and we fall back to the `pane` surface. */\nconst NO_AGENT_CODES: readonly string[] = [\"agent_not_found\", \"agent_not_recognized\"];\n\n/** Default handler for an unconfirmed send: warn on stderr. Loud by\n * design — silence is the failure mode. */\nfunction defaultUndeliveredWarning(warning: SendWarning): void {\n if (isJsonMode()) return; // the verb's document carries `delivered:false`\n console.warn(`warning: ${warning.message}`);\n}\n\n/**\n * Submit `text` to a pane and press Enter, atomically.\n *\n * WHICH SURFACE (topology note 9): `agent prompt` only accepts targets\n * herdr has RECOGNIZED as an agent — a plain shell pane is\n * `agent_not_found` there. mu therefore tries the agent surface FIRST\n * (the overwhelmingly common case: every mu-managed pane runs a coding\n * CLI, and it is the only surface that understands lifecycle state) and\n * falls back to `pane run`, herdr's atomic text+Enter for raw shells,\n * only when herdr says there is no agent. The happy path is one call;\n * the fallback path is two, and never polls.\n *\n * `opts.readinessMs === 0` drops `--wait`: submit and return without\n * waiting for a settled state. Any other value is ignored — there is no\n * readiness to budget for.\n *\n * No `--until`: `--wait` already defaults to the first settled idle /\n * done / blocked, which is precisely what mu's callers want, and herdr's\n * skill doc calls repeating those defaults a bug.\n *\n * DELIVERY CONTRACT: an unconfirmed send WARNS and keeps\n * going, never throws. herdr returns `agent_prompt_stalled` when a\n * prompt from a non-working state produces no lifecycle change within\n * 5s — a stranded paste, so it maps onto the\n * `paste-vanished` reason: the pane was calm, we submitted, and\n * nothing happened.\n */\n/** The shell steps that type `/reload` into the pane through herdr. */\nexport function reloadCommands(paneId: string): readonly MuxCommand[] {\n return [\n { command: \"herdr\", args: [...herdrGlobalFlags(), \"agent\", \"prompt\", paneId, \"/reload\"] },\n ];\n}\n\nexport async function sendToPane(\n paneId: string,\n text: string,\n opts: SendOptions = {},\n): Promise<void> {\n assertValidPaneId(paneId);\n // Unverified: herdr has no key-send primitive mu knows of, and an empty\n // `agent prompt` is untested. Refuse rather than guess.\n if (text === \"\") {\n throw new MuxError(\n \"herdr backend cannot send an empty message (no bare-Enter primitive); press Enter in the pane instead\",\n );\n }\n const wait = opts.readinessMs === 0 ? [] : [\"--wait\"];\n try {\n await herdr([\"agent\", \"prompt\", paneId, text, ...wait]);\n return;\n } catch (err) {\n if (!(err instanceof HerdrError) || err.code === undefined) throw err;\n if (err.code === PROMPT_STALLED_CODE) {\n const warn = opts.onUndelivered ?? defaultUndeliveredWarning;\n warn({\n paneId,\n reason: \"paste-vanished\",\n message: `send to ${paneId} was submitted but the agent's state never changed (herdr: ${PROMPT_STALLED_CODE}). The agent may NOT have seen it. Read the pane, or re-send.`,\n });\n return;\n }\n if (!NO_AGENT_CODES.includes(err.code)) throw err;\n }\n // No recognized agent in this pane: raw shell. `pane run` is herdr's\n // atomic text+Enter for that case. It has no lifecycle to wait on, so\n // there is nothing to confirm and nothing to warn about.\n await herdr([\"pane\", \"run\", paneId, text]);\n}\n\n/**\n * Read pane output as plain text.\n *\n * - no options → everything herdr has available, soft wraps joined\n * - `lines: 0` → the rendered viewport only (`--source visible`)\n * - `lines: N` → the last N rows, soft wraps joined\n *\n * `recent-unwrapped` is the source herdr recommends for logs and\n * transcripts: it joins soft wraps, so a wrapped line reads as one line\n * rather than as terminal-width fragments.\n *\n * KNOWN LIMIT — do not paper over this: a pane running its agent on the\n * terminal's ALTERNATE screen does not spill rows into herdr's host\n * scrollback. Rows that have left the alternate screen are GONE, so a\n * bigger `--lines` cannot recover them. If a read looks truncated, that\n * is why, and the fix is to ask the agent to write its output to a file\n * — not to raise the line count.\n *\n * `pane read` emits PLAIN TEXT, so it bypasses `herdr()` (which would\n * treat unparseable stdout as CLI drift) and reads the executor result\n * directly, mapping herdr's JSON error envelope by hand.\n */\nexport async function capture(paneId: string, opts: CaptureOptions = {}): Promise<string> {\n assertValidPaneId(paneId);\n const args = [\"pane\", \"read\", paneId];\n if (opts.lines === 0) {\n args.push(\"--source\", \"visible\");\n } else {\n args.push(\"--source\", \"recent-unwrapped\");\n if (opts.lines !== undefined) args.push(\"--lines\", String(opts.lines));\n }\n const result = await currentExecutor(args);\n if (result.exitCode === 2) throw new HerdrSyntaxError(args, result.stderr || result.stdout);\n if (result.exitCode !== 0) {\n throw new HerdrError(\n args,\n result.stderr,\n result.stdout,\n result.exitCode,\n parseErrorEnvelope(result.stderr)?.code,\n );\n }\n return result.stdout;\n}\n\n// ─── Native status ─────────────────────────────────────────────────────\n\n/**\n * herdr's five agent lifecycle states, mapped onto mu's.\n *\n * working → busy\n * blocked → needs_permission (herdr recognized an approval/question UI)\n * idle → needs_input\n * done → needs_input\n * unknown → needs_input\n *\n * `unknown` MUST NOT become `free`. herdr's skill doc is explicit that\n * unknown \"does not prove completion\"; a false `free` makes mu hand the\n * worker a second task while the first is still running. `needs_input`\n * is the safe reading of \"an agent is there and we cannot classify it\".\n * (`free` is not a detected status at all — it is set by `mu agent\n * free`, i.e. by the user, and no detector may mint it.)\n *\n * `done` is herdr's idle-after-UNSEEN-background-work, and CLI reads\n * deliberately do NOT mark a tab seen. mu polling therefore never clears\n * the user's done badge — which is the point, and why no read path in\n * this file calls a focus or seen-marking verb (only the attach steps\n * the user asks for name one).\n */\nexport function mapAgentStatus(agentStatus: string): MuxPaneStatus {\n switch (agentStatus) {\n case \"working\":\n return \"busy\";\n case \"blocked\":\n return \"needs_permission\";\n default:\n // idle / done / unknown, and any state a future herdr adds: the\n // conservative reading is \"waiting on a human\", never \"free\".\n return \"needs_input\";\n }\n}\n\n/**\n * The pane's status as HERDR classifies it, or undefined when the pane\n * is gone (or reports no state at all).\n *\n * herdr watches the terminal continuously across every agent kind it\n * knows; mu takes that report rather than reading pane text.\n */\nexport async function paneStatus(paneId: string): Promise<MuxPaneStatus | undefined> {\n if (!isValidPaneId(paneId)) return undefined;\n const result = await herdrTolerating(\n [\"pane\", \"get\", paneId],\n [\"pane_not_found\", \"workspace_not_found\"],\n );\n if (result === undefined) return undefined;\n const pane = result.pane;\n const status = isRecord(pane) ? asString(pane.agent_status) : undefined;\n if (status === undefined) return undefined;\n return mapAgentStatus(status);\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────\n\n/**\n * Push one `--env KEY=VALUE` flag per entry. Keys must be non-empty and\n * free of `=`; throwing a TypeError keeps the failure at the call site\n * instead of letting herdr reject the line as a syntax error (exit 2),\n * which would look like CLI drift.\n */\nfunction appendEnvFlags(args: string[], env: Record<string, string> | undefined): void {\n if (!env) return;\n for (const [k, v] of Object.entries(env)) {\n if (k.length === 0) throw new TypeError(\"herdr env key must be non-empty\");\n if (k.includes(\"=\")) {\n throw new TypeError(`herdr env key must not contain '=': ${JSON.stringify(k)}`);\n }\n args.push(\"--env\", `${k}=${v}`);\n }\n}\n\n/**\n * Read a pane id out of a creation response. Never predict an id: herdr\n * does not reuse closed ids and a moved pane is renumbered, so the\n * response is the only trustworthy source.\n */\nfunction readCreatedPaneId(\n result: Record<string, unknown>,\n key: string,\n args: readonly string[],\n): string {\n const pane = readPane(result[key]);\n if (pane === undefined) {\n throw new HerdrError(\n args,\n `herdr response had no ${key}.pane_id: ${JSON.stringify(result)}`,\n \"\",\n 0,\n );\n }\n assertValidPaneId(pane.paneId);\n return pane.paneId;\n}\n\n// ─── Backend record ────────────────────────────────────────────────────\n\n/**\n * True iff a `herdr status` payload describes a server mu can drive.\n *\n * Pure, and EXPORTED because test/_mux.ts gates the real-herdr\n * integration tier on the same question — one parser, not two that\n * drift (they already had, across the 0.8 → 0.9 rename below).\n *\n * WHICH COMPATIBILITY LINE. herdr 0.9.0 split the old single\n * `compatible: yes|no` into two, and they do NOT mean the same thing:\n *\n * endpoint_compatible — the stable public API generation.\n * `no` means the server predates\n * endpoint generation 1 and needs a\n * one-time upgrade before ANY verb\n * works. Load-bearing.\n * private_protocol_compatible — the internal client↔server protocol.\n * Since 0.9.0 a mismatch here only\n * disables the affected action and\n * leaves running agents untouched, so\n * it must NOT gate availability: a\n * client one release ahead of its\n * server still drives panes fine.\n *\n * The bare `compatible:` line is herdr ≤0.8.x and is still honoured, so\n * mu does not silently start trusting an old incompatible server. It\n * cannot collide with the two 0.9 lines: `^\\s*` will not consume the\n * `endpoint_` / `private_protocol_` prefixes.\n *\n * A MISSING line is fine in every case — absence of evidence is not\n * incompatibility, and herdr omits these entirely when no server runs\n * (which the `status: running` check has already rejected).\n */\nexport function isHerdrStatusUsable(stdout: string): boolean {\n if (!/^\\s*status:\\s*running\\s*$/m.test(stdout)) return false;\n if (/^\\s*endpoint_compatible:\\s*no\\s*$/m.test(stdout)) return false;\n return !/^\\s*compatible:\\s*no\\s*$/m.test(stdout);\n}\n\n/**\n * True iff herdr can be reached right now. `herdr status` rather than a\n * PATH probe, and it must report a RUNNING, COMPATIBLE server: a herdr\n * binary whose server is down cannot drive a single pane, so it is not\n * an available backend.\n *\n * Note `herdr status` is plain text, not JSON — the one exception to the\n * \"everything is JSON\" rule, so it is parsed here rather than through\n * `herdr()`.\n */\nasync function herdrAvailable(): Promise<boolean> {\n const result = await currentExecutor([\"status\"]).catch(() => undefined);\n if (result === undefined || result.exitCode !== 0) return false;\n return isHerdrStatusUsable(result.stdout);\n}\n\n// ─── Attach ─────────────────────────────────────────────────────────────\n//\n// The mu session name is a workspace LABEL inside one herdr server, so\n// attaching means FOCUSING that workspace (or the agent's tab), and\n// herdr addresses both by opaque id: resolve label → id first.\n// `herdr session attach <name>` is NOT the analogue: it attaches a\n// whole named SERVER, and pointing it at a workspace label starts a\n// new, empty server under that name.\n//\n// `MU_HERDR_SESSION` picks the server mu drives, and the user's shell\n// does not read it, so every emitted line carries the same\n// `--session <name>` prefix as `herdrGlobalFlags()`.\n//\n// Focus moves the server's view; the user only sees it through a\n// client. Inside a herdr pane (`$HERDR_ENV=1`, the signal detect.ts\n// uses) the caller's client already shows it. Outside, a second step\n// opens a client. `target.inside` is tmux's evidence (`$TMUX`) and is\n// ignored here; `target.outside` (a line for a shell outside any client) is\n// not: it always carries the client step.\n\n/** The focus argv for `target` in workspace `workspaceId`. Prefers the\n * agent's tab (`tab focus` also switches the workspace) and falls back\n * to the workspace when no tab carries that label. */\nasync function attachFocusArgs(workspaceId: string, target: AttachTarget): Promise<string[]> {\n if (target.window !== undefined) {\n const tabs = readTabs(await herdr([\"tab\", \"list\", \"--workspace\", workspaceId]));\n const tab = tabs.find((t) => t.name === target.window);\n if (tab !== undefined) return [\"tab\", \"focus\", tab.id];\n }\n return [\"workspace\", \"focus\", workspaceId];\n}\n\nfunction insideHerdrClient(): boolean {\n return process.env.HERDR_ENV === \"1\";\n}\n\n/** The attach as argv steps. Throws `HerdrError` when no workspace\n * carries the label; callers omit the attach line then. */\nexport async function attachCommands(target: AttachTarget): Promise<readonly MuxCommand[]> {\n const flags = herdrGlobalFlags();\n const focus = await attachFocusArgs(await requireWorkspaceId(target.session), target);\n const steps: MuxCommand[] = [{ command: \"herdr\", args: [...flags, ...focus] }];\n // Bare `herdr` launches a client attached to the (named) server.\n if (target.outside === true || !insideHerdrClient())\n steps.push({ command: \"herdr\", args: [...flags] });\n return steps;\n}\n\n/**\n * Version probe plus the ambient facts herdr injects into every managed\n * pane. Returns DATA; `mu doctor` owns the strings.\n *\n * `herdr status` is the one command that is NOT JSON (see the task note\n * on mux-herdr-topology), so this parses the plain-text `version:` line\n * from the CLIENT block rather than routing through `herdr()`.\n */\nexport async function healthCheck(): Promise<MuxHealth> {\n let version: string | null = null;\n try {\n const result = await currentExecutor([\"status\"]);\n if (result.exitCode === 0) {\n const match = /^\\s*version:\\s*(\\S+)\\s*$/m.exec(result.stdout);\n version = match?.[1] ?? null;\n }\n } catch {\n version = null;\n }\n return {\n name: \"herdr\",\n ok: version !== null,\n version,\n env: [\n { name: \"$HERDR_ENV\", value: process.env.HERDR_ENV ?? null },\n { name: \"$HERDR_WORKSPACE_ID\", value: process.env.HERDR_WORKSPACE_ID ?? null },\n { name: \"$HERDR_PANE_ID\", value: process.env.HERDR_PANE_ID ?? null },\n ],\n remediation: \"start the herdr server (herdr status) or install herdr\",\n };\n}\n\n/**\n * The herdr implementation of `MuxBackend`. A frozen record of the\n * module's functions — no state of its own, so swapping backends is a\n * pointer assignment (see ./detect.ts).\n */\nexport const herdrBackend: MuxBackend = Object.freeze({\n name: \"herdr\" as const,\n spawnAgentWaitsReady: true,\n runsShellCommand: false,\n available: herdrAvailable,\n\n isValidPaneId,\n assertValidPaneId,\n\n ensureSession,\n killSession,\n\n spawnAgent,\n listPanes,\n paneAlive,\n killPane,\n capture,\n\n attachCommands,\n\n reloadCommands,\n paneStatus,\n sendToPane,\n currentSessionName,\n healthCheck,\n});\n","// mu — multiplexer backend detection.\n//\n// Picks the ONE backend a given mu invocation drives. The mux backend is a\n// property of the PROCESS, so it is resolved once and cached (see\n// `activeMux`).\n\nimport { say } from \"../messages.js\";\nimport { herdrBackend } from \"./herdr.js\";\nimport { tmuxBackend } from \"./tmux.js\";\nimport { type MuxBackend, type MuxBackendName, NoMultiplexerError } from \"./types.js\";\n\n/** Every backend mu knows about, in detection-precedence order. tmux is\n * the incumbent and wins pure availability ties; herdr is selected by\n * the narrower `$HERDR_ENV` ambient signal (see `detectMux`). */\nconst BACKENDS: readonly MuxBackend[] = [tmuxBackend, herdrBackend];\n\n/** Look up a backend by name. Throws on unknown name. Backs `MU_MUX`. */\nexport function muxByName(name: MuxBackendName): MuxBackend {\n for (const backend of BACKENDS) {\n if (backend.name === name) return backend;\n }\n throw new Error(say(\"mux.unknown_backend\", name));\n}\n\n/** Valid `MU_MUX` values, for error messages. */\nconst KNOWN_NAMES: readonly string[] = BACKENDS.map((b) => b.name);\n\n/**\n * Resolve the active multiplexer backend.\n *\n * The ladder, in order:\n *\n * 1. `MU_MUX=<name>` — explicit override. Also the test seam. An\n * unknown value throws rather than silently falling through: a\n * typo'd backend name should fail loud, not quietly run on tmux.\n * 2. Ambient signal — an env var proving the CALLER is already\n * inside a managed pane of that mux ($HERDR_ENV for herdr, $TMUX\n * or $TMUX_PANE for tmux). The most specific signal wins, since a\n * mux can run nested inside another: herdr panes routinely host a\n * tmux server, so BOTH sets of vars can be present at once and\n * $HERDR_ENV — the narrower claim — is checked first.\n * 3. Availability — whichever backend's binary actually runs.\n * Ties break in BACKENDS order (tmux is the incumbent).\n * 4. Throw `NoMultiplexerError`.\n *\n * Note rungs 2 and 3 are separate on purpose. `$TMUX` says \"the caller\n * is in a tmux pane\"; `tmux -V` says \"tmux works here\". mu can spawn a\n * detached session from a plain shell, so rung 3 alone is sufficient to\n * operate — rung 2 exists only to pick the RIGHT mux when several are\n * installed.\n */\nexport async function detectMux(): Promise<MuxBackend> {\n const override = process.env.MU_MUX;\n if (override !== undefined && override.length > 0) {\n return muxByName(override as MuxBackendName);\n }\n\n // herdr FIRST. herdr can run inside tmux and vice versa, so both\n // signals can be live simultaneously; `$HERDR_ENV=1` is the narrower\n // one (herdr sets it only in panes IT manages) and must win. The\n // exact-\"1\" comparison is what `herdr --skill` mandates: any other\n // value, including \"0\" or \"true\", is not the documented contract.\n if (process.env.HERDR_ENV === \"1\") return herdrBackend;\n\n // Both vars, not just $TMUX: tmux sets $TMUX_PANE in every pane too,\n // and some setups (sudo -E, direnv, ssh with a restrictive SendEnv)\n // pass one through but not the other. Either one proves we are in a\n // tmux pane, which is what this rung is asking.\n if (process.env.TMUX || process.env.TMUX_PANE) return tmuxBackend;\n\n for (const backend of BACKENDS) {\n if (await backend.available()) return backend;\n }\n\n throw new NoMultiplexerError(KNOWN_NAMES);\n}\n\n// ─── Process-wide active backend ───────────────────────────────────────\n\nlet cached: MuxBackend | undefined;\n\n/**\n * The active backend, resolved once per process and memoized.\n *\n * Memoized because detection can shell out (`tmux -V`) and mu is a\n * short-lived CLI that touches the mux many times per invocation; the\n * answer cannot change mid-process in any way that mu should react to.\n */\nexport async function activeMux(): Promise<MuxBackend> {\n if (cached === undefined) cached = await detectMux();\n return cached;\n}\n\n/**\n * Install a backend directly, bypassing detection. Returns the previous\n * value so tests can restore it. Mirrors `setTmuxExecutor`.\n *\n * Production code never calls this — use `activeMux()`.\n */\nexport function setMuxForTests(backend: MuxBackend | undefined): MuxBackend | undefined {\n const previous = cached;\n cached = backend;\n return previous;\n}\n\n/** Drop the memoized backend so the next `activeMux()` re-detects. */\nexport function resetMux(): void {\n cached = undefined;\n}\n","// mu — tmux substrate (back-compat re-export hub).\n//\n// The tmux implementation moved to src/mux/tmux.ts when the MuxBackend\n// interface was extracted, so mu could grow a second multiplexer. This\n// file re-exports it for tests and tmux-only callers\n// (`import { ... } from \"./tmux.js\"`).\n//\n// NEW CODE SHOULD IMPORT `./mux.js` and go through `activeMux()`.\n// Importing this module pins you to tmux specifically, which is correct\n// only for genuinely tmux-only concerns (the `MU_TMUX_SOCKET` test\n// isolation seam, `mu doctor`'s tmux version probe).\n\nexport * from \"./mux/tmux.js\";\n","// mu — host profiles: ssh-free command templates, and the channels they use.\n//\n// mu never connects to a host and knows no ssh flags. A profile is three\n// templates the user wrote (`shell`, `exec`, `fetch`), a `repo` path and an\n// optional `max_sessions`. mu fills the documented placeholders and runs the\n// result with `/bin/sh -c`; `host init --ssh` only PRINTS a starter to edit.\n//\n// ─── Template grammar (one pass over the ORIGINAL template) ─────────────\n// {{ and }} literal braces. A lone `{` or `}`, or an unknown name, is an\n// error: nothing is guessed. (A shell `${HOME}` is `${{HOME}}`.)\n// {name} one of env, cmd, local_sock, remote_sock, cwd. The value is\n// substituted once and never rescanned, so braces inside a\n// value are inert.\n// A small lexer tracks '...' and \"...\" so every value stays exactly the text\n// the template author asked for. Quote characters never imply a second shell;\n// a second layer is always asked for by name:\n// {name} ONE layer, the local /bin/sh. Unquoted: the value as one\n// single-quoted word. Inside '...' or \"...\": the value escaped\n// to be literal text of that string (`'` -> `'\\''`;\n// `\\ \" $ \\`` backslash-escaped), so `tool \"{cwd}\"` and\n// `tool '{cwd}'` pass the value itself.\n// {name:sh} TWO layers: the value is first quoted as one word for a second\n// shell (what the template hands command text to, e.g. ssh's\n// remote login shell), then for the layer it lands in. Atomic\n// at both layers.\n// A placeholder after a backslash, or inside $(...) / backticks within double\n// quotes, is refused (the lexer does not nest shells).\n// {env} is a run of KEY=VALUE assignment words, so it can precede a command.\n// Keys are the five remote identity variables only (never the local DB,\n// state or sync dir); each VALUE is shell-quoted (`hostEnvWords`). The words\n// are shell text, so in '...' or \"...\" they are escaped for that quote like\n// any text, and `{env:sh}` is refused (it is already text for the inner shell).\n//\n// ─── Channels ───────────────────────────────────────────────────────────\n// `max_sessions` counts every channel mu holds open to a host. A channel is\n// one `host_channels` row (machine-local), reserved BEFORE the connection is\n// opened, under BEGIN IMMEDIATE that covers reserve/count/cleanup only, never\n// the awaited template run:\n// transient rides one invocation (exec, fetch, check); released in\n// `finally` by token; reclaimed only when its pid is proven\n// gone (ESRCH, or the pid's start time changed) AND the\n// template's process group (`pgid`, recorded before the command\n// starts) is gone: kill(-pgid, 0) succeeding or EPERM holds the\n// slot, so a caller that died by SIGKILL mid-reap cannot free it\n// under a live transport. EPERM or any unknown keeps the row.\n// attached rides an agent's pane (registry id + pane, no pid): reserve,\n// `bindHostChannel` once the pane exists, and\n// `releaseHostChannelsForAgent(id, pane)` at close. Reclaimed\n// only when the pane is proven dead; a liveness probe that\n// throws, or no probe, keeps the row.\n// `spawn --host` reserves BEFORE its pane opens, binds the lease to the new\n// agent's id + pane, and `deleteAgent` (close, reconcile, rollback, teardown)\n// frees it: the pane IS the transport, so pane death is transport death.\n\nimport { randomUUID } from \"node:crypto\";\nimport { readFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { ctlProbe } from \"./ctl/client.js\";\nimport { ctlSocketPath } from \"./ctl/path.js\";\nimport type { Db } from \"./db.js\";\nimport { execGroupCapture } from \"./exec-file.js\";\nimport { say } from \"./messages.js\";\nimport { shellQuote } from \"./shell-quote.js\";\n\n// ─── Errors ─────────────────────────────────────────────────────────────\n\n/** A profile field mu refuses (name, cap, repo, template). Exit 2. */\nexport class HostProfileError extends Error {\n override readonly name: string = \"HostProfileError\";\n}\n\n/** A template mu refuses to expand. Exit 2. */\nexport class HostTemplateError extends HostProfileError {\n override readonly name: string = \"HostTemplateError\";\n}\n\nexport class HostNotFoundError extends Error {\n override readonly name = \"HostNotFoundError\";\n constructor(public readonly host: string) {\n super(say(\"host.not_found\", host));\n }\n}\n\nexport class HostExistsError extends Error {\n override readonly name = \"HostExistsError\";\n constructor(public readonly host: string) {\n super(say(\"host.exists\", host));\n }\n}\n\n/** The host is at `max_sessions`, or the holder already holds a channel. One line, names the holder. */\nexport class HostChannelBusyError extends Error {\n override readonly name = \"HostChannelBusyError\";\n constructor(\n public readonly host: string,\n public readonly holders: readonly string[],\n message: string,\n ) {\n super(message);\n }\n}\n\n/** `host rm` of a host that still holds a channel. */\nexport class HostInUseError extends Error {\n override readonly name = \"HostInUseError\";\n constructor(\n public readonly host: string,\n public readonly holders: readonly string[],\n ) {\n super(say(\"host.in_use\", host, holders));\n }\n}\n\n/** The active multiplexer cannot run a host profile's shell template. One line, exit 2. */\nexport class HostSpawnUnsupportedError extends Error {\n override readonly name = \"HostSpawnUnsupportedError\";\n constructor(\n public readonly host: string,\n public readonly mux: string,\n ) {\n super(say(\"host.spawn_unsupported\", host, mux));\n }\n}\n\n/** `host check` found a failing step. The report rides on `failureWithData`. */\nexport class HostCheckFailedError extends Error {\n override readonly name = \"HostCheckFailedError\";\n constructor(\n public readonly host: string,\n public readonly failed: readonly string[],\n ) {\n super(say(\"host.check_failed\", host, failed));\n }\n}\n\n// ─── Profiles ───────────────────────────────────────────────────────────\n\nexport interface HostProfile {\n name: string;\n shell: string;\n exec: string;\n fetch: string;\n /** Default remote repo for a spawn without `--root`; null: none. */\n repo: string | null;\n max_sessions: number | null;\n}\n\nconst HOST_NAME_RE = /^[a-z][a-z0-9_-]{0,31}$/;\n\nexport function isValidHostName(name: string): boolean {\n return HOST_NAME_RE.test(name);\n}\n\nexport function getHost(db: Db, name: string): HostProfile {\n const row = db.prepare(\"SELECT * FROM host_profiles WHERE name = ?\").get(name) as\n | HostProfile\n | undefined;\n if (row === undefined) throw new HostNotFoundError(name);\n return row;\n}\n\nexport function listHosts(db: Db): HostProfile[] {\n return db.prepare(\"SELECT * FROM host_profiles ORDER BY name\").all() as HostProfile[];\n}\n\n/** Store a profile. Validates the name, cap, default repo and every template first; stores nothing on refusal. */\nexport function addHost(db: Db, p: HostProfile): HostProfile {\n if (!isValidHostName(p.name)) {\n throw new HostProfileError(\n `invalid host name ${JSON.stringify(p.name)}: lowercase letters, digits, - and _, starting with a letter (max 32)`,\n );\n }\n if (p.max_sessions !== null && !(Number.isInteger(p.max_sessions) && p.max_sessions > 0)) {\n throw new HostProfileError(\"--max-sessions must be a positive integer\");\n }\n if (p.repo !== null && p.repo.trim() === \"\") {\n throw new HostProfileError(\"--repo must not be empty\");\n }\n for (const f of [\"shell\", \"exec\", \"fetch\"] as const) {\n try {\n validateHostTemplate(p[f]);\n } catch (e) {\n if (e instanceof HostTemplateError) throw new HostTemplateError(`--${f}: ${e.message}`);\n throw e;\n }\n }\n try {\n db.prepare(\n \"INSERT INTO host_profiles (name, shell, exec, fetch, repo, max_sessions) VALUES (@name, @shell, @exec, @fetch, @repo, @max_sessions)\",\n ).run(p);\n } catch (e) {\n if ((e as { code?: string }).code === \"SQLITE_CONSTRAINT_PRIMARYKEY\") {\n throw new HostExistsError(p.name);\n }\n throw e;\n }\n return getHost(db, p.name);\n}\n\n/**\n * Remove a profile; false when there was none. Refuses while a channel is\n * held, after reclaiming proven-dead transient ones. An attached channel is\n * freed by closing its agent, never here.\n */\nexport function removeHost(db: Db, name: string): boolean {\n return db\n .transaction(() => {\n reclaim(db, name, []);\n const held = listHostChannels(db, name).map((c) => c.holder);\n if (held.length > 0) throw new HostInUseError(name, held);\n return db.prepare(\"DELETE FROM host_profiles WHERE name = ?\").run(name).changes > 0;\n })\n .immediate();\n}\n\n/**\n * The starter for `host init <name> --ssh`: printed for the user to edit,\n * never run. The shell template is a command for the remote login shell\n * (inside quotes, so each value asks for `:sh`, quoting for that shell): cd, env, `$SHELL -ilc`.\n */\nexport function hostStarter(host: string): { shell: string; exec: string; fetch: string } {\n const ssh = \"ssh -o ControlMaster=no -o ControlPath=none\";\n return {\n // ControlMaster=no: a multiplexed ssh never binds the local end of the forward.\n shell: `${ssh} -o StreamLocalBindUnlink=yes -o ExitOnForwardFailure=yes -L {local_sock}:{remote_sock} ${host} -t 'cd {cwd:sh} && {env} \"$SHELL\" -ilc {cmd:sh}'`,\n exec: `${ssh} -o BatchMode=yes ${host} {cmd}`,\n fetch: `git fetch ssh://${host}{cwd} HEAD`,\n };\n}\n\n// ─── Template grammar ───────────────────────────────────────────────────\n\nexport const HOST_PLACEHOLDERS = [\"env\", \"cmd\", \"local_sock\", \"remote_sock\", \"cwd\"] as const;\nexport type HostPlaceholder = (typeof HOST_PLACEHOLDERS)[number];\nexport type HostTemplateValues = Partial<Record<HostPlaceholder, string>>;\n\n/**\n * The only variables a remote worker is given: its identity, never the local\n * DB, state or sync dir. `MU_REMOTE=1` tells the remote extension there is no\n * mu DB over there (it skips the close nudge; CLOSE is applied here).\n */\nexport const HOST_ENV_KEYS = [\n \"MU_MANAGED_AGENT\",\n \"MU_AGENT_NAME\",\n \"MU_WORKSTREAM\",\n \"MU_CTL_SOCK\",\n \"MU_REMOTE\",\n] as const;\n\n/** One shell-quoted value as `shellQuote` writes it: single-quoted runs and `\"'\"`. */\nconst QUOTED = `(?:'[^']*'|\"'\")+`;\nconst ENV_WORD = `(?:${HOST_ENV_KEYS.join(\"|\")})=${QUOTED}`;\nconst ENV_WORDS_RE = new RegExp(`^(?:${ENV_WORD}(?: ${ENV_WORD})*)?$`);\n\n/** `K='v'` words for `{env}`: whitelisted keys, every value shell-quoted (any text survives), nothing else. */\nexport function hostEnvWords(env: Record<string, string>): string {\n const words: string[] = [];\n for (const [k, v] of Object.entries(env)) {\n if (!(HOST_ENV_KEYS as readonly string[]).includes(k)) {\n throw new HostTemplateError(\n `{env} may carry only ${HOST_ENV_KEYS.join(\", \")}; ${k} is not forwarded`,\n );\n }\n if (v.includes(\"\\0\")) throw new HostTemplateError(`{env} value for ${k} contains a NUL byte`);\n words.push(`${k}=${shellQuote(v)}`);\n }\n return words.join(\" \");\n}\n\ntype Ctx = \"none\" | \"sq\" | \"dq\";\ntype Token = { lit: string } | { ph: HostPlaceholder; ctx: Ctx; layers: 1 | 2 };\n\nconst KNOWN = `${HOST_PLACEHOLDERS.map((p) => `{${p}}`).join(\" \")}; {name:sh} quotes for a second shell`;\n\nfunction parseTemplate(t: string): Token[] {\n const out: Token[] = [];\n let lit = \"\";\n let ctx: Ctx = \"none\";\n let subst = false; // inside $( or backticks within double quotes\n const flush = (): void => {\n if (lit !== \"\") out.push({ lit });\n lit = \"\";\n };\n for (let i = 0; i < t.length; i++) {\n const c = t[i] as string;\n const next = t[i + 1];\n if (c === \"{\") {\n if (next === \"{\") {\n lit += \"{\";\n i++;\n continue;\n }\n const end = t.indexOf(\"}\", i);\n const body = end === -1 ? \"\" : t.slice(i + 1, end);\n const colon = body.indexOf(\":\");\n const name = colon === -1 ? body : body.slice(0, colon);\n const mod = colon === -1 ? undefined : body.slice(colon + 1);\n if (!(HOST_PLACEHOLDERS as readonly string[]).includes(name)) {\n throw new HostTemplateError(\n end === -1 || name === \"\" || /\\s/.test(name)\n ? `stray { in template (write {{ for a literal brace; placeholders: ${KNOWN})`\n : `unknown placeholder {${name}} (known: ${KNOWN})`,\n );\n }\n if (mod !== undefined && mod !== \"sh\") {\n throw new HostTemplateError(`unknown modifier {${body}} (the only one is {${name}:sh})`);\n }\n if (name === \"env\" && mod !== undefined) {\n throw new HostTemplateError(\n \"{env:sh} is refused: {env} is already text for the inner shell\",\n );\n }\n if (ctx === \"dq\" && subst) {\n throw new HostTemplateError(`{${name}} inside $(...) or backticks in double quotes`);\n }\n flush();\n out.push({ ph: name as HostPlaceholder, ctx, layers: mod === undefined ? 1 : 2 });\n i = end;\n continue;\n }\n if (c === \"}\") {\n if (next !== \"}\")\n throw new HostTemplateError(\"stray } in template (write }} for a literal brace)\");\n lit += \"}\";\n i++;\n continue;\n }\n lit += c;\n if (ctx === \"sq\") {\n if (c === \"'\") ctx = \"none\";\n } else if (c === \"\\\\\") {\n if (next === undefined) continue;\n if (next === \"{\" || next === \"}\") {\n throw new HostTemplateError(\n \"a brace right after a backslash is ambiguous: quote it instead\",\n );\n }\n lit += next;\n i++;\n } else if (ctx === \"dq\") {\n if (c === '\"') {\n ctx = \"none\";\n subst = false;\n } else if (c === \"`\" || (c === \"$\" && next === \"(\")) subst = true;\n } else if (c === \"'\") ctx = \"sq\";\n else if (c === '\"') ctx = \"dq\";\n }\n flush();\n return out;\n}\n\n/** Throws HostTemplateError unless `template` is well-formed. */\nexport function validateHostTemplate(template: string): void {\n parseTemplate(template);\n}\n\n/**\n * Expand `template` in one pass. Every value is quoted for the layer it lands\n * in and stays one word (`{name:sh}` adds the second-shell layer); {env} is\n * whitelisted assignment words. A placeholder with\n * no value in this context is an error, never blanked.\n */\nexport function expandHostTemplate(template: string, values: HostTemplateValues): string {\n let out = \"\";\n for (const tok of parseTemplate(template)) {\n if (\"lit\" in tok) {\n out += tok.lit;\n continue;\n }\n const v = values[tok.ph];\n if (v === undefined) throw new HostTemplateError(`{${tok.ph}} has no value in this template`);\n if (v.includes(\"\\0\")) throw new HostTemplateError(`{${tok.ph}} value contains a NUL byte`);\n let text: string;\n if (tok.ph === \"env\") {\n if (!ENV_WORDS_RE.test(v)) {\n throw new HostTemplateError(\n `{env} must be KEY='value' words of ${HOST_ENV_KEYS.join(\", \")} (build it with hostEnvWords)`,\n );\n }\n text = v;\n } else if (tok.ctx === \"none\") {\n out += tok.layers === 2 ? shellQuote(shellQuote(v)) : shellQuote(v);\n continue;\n } else text = tok.layers === 2 ? shellQuote(v) : v;\n if (tok.ctx === \"sq\") out += text.replace(/'/g, `'\\\\''`);\n else if (tok.ctx === \"dq\") out += text.replace(/[\\\\\"$`]/g, \"\\\\$&\");\n else out += text;\n }\n return out;\n}\n\n/** A remote path as a shell word: a leading `~` becomes \"$HOME\" (quoting would stop tilde expansion). */\nexport function remotePathWord(p: string): string {\n if (p === \"~\") return '\"$HOME\"';\n if (p.startsWith(\"~/\")) return `\"$HOME\"/${shellQuote(p.slice(2))}`;\n return shellQuote(p);\n}\n\n// ─── Channels ───────────────────────────────────────────────────────────\n\nexport interface HostChannel {\n host: string;\n holder: string;\n kind: \"transient\" | \"attached\";\n token: string;\n pid: number | null;\n pid_start: string | null;\n /** The template's process group (its leader's pid), set before the command starts. */\n pgid: number | null;\n pgid_start: string | null;\n agent_id: number | null;\n pane_id: string | null;\n opened_at: string;\n}\n\n/** Proof of a reservation: release and bind are compare-and-set on `token`. */\nexport interface HostLease {\n host: string;\n holder: string;\n token: string;\n}\n\nexport interface ChannelOpts {\n /** Is this pane alive? Throwing or absent means unknown, which keeps the channel. */\n paneAlive?: (paneId: string) => Promise<boolean>;\n}\n\nexport function listHostChannels(db: Db, host?: string): HostChannel[] {\n return (\n host === undefined\n ? db.prepare(\"SELECT * FROM host_channels ORDER BY host, holder\").all()\n : db.prepare(\"SELECT * FROM host_channels WHERE host = ? ORDER BY holder\").all(host)\n ) as HostChannel[];\n}\n\n/** The pid's start time (Linux: /proc stat field 22), or null when unreadable. */\nfunction pidStart(pid: number): string | null {\n try {\n const stat = readFileSync(`/proc/${pid}/stat`, \"utf8\");\n return stat.slice(stat.lastIndexOf(\")\") + 2).split(\" \")[19] ?? null;\n } catch {\n return null;\n }\n}\n\n/** True only when the holder is certainly gone: ESRCH, or the pid now has another start time. */\nfunction pidProvenGone(pid: number, start: string | null): boolean {\n try {\n process.kill(pid, 0);\n } catch (e) {\n return (e as NodeJS.ErrnoException).code === \"ESRCH\";\n }\n if (start === null) return false;\n const now = pidStart(pid);\n return now !== null && now !== start;\n}\n\n/**\n * Is the template's process group still there? `kill(-pgid, 0)` succeeding\n * or failing with EPERM means yes. Only ESRCH, or proof that the pid was\n * reused (the leader pid is alive with another start time: a pid cannot be\n * reused while its group has members), means gone.\n */\nfunction groupAlive(pgid: number, start: string | null): boolean {\n try {\n process.kill(-pgid, 0);\n } catch (e) {\n return (e as NodeJS.ErrnoException).code !== \"ESRCH\";\n }\n if (start === null) return true;\n const now = pidStart(pgid);\n return now === null || now === start;\n}\n\n/** Attached channels whose pane is proven dead. Runs OUTSIDE any transaction. */\nasync function probeAttached(\n db: Db,\n host: string,\n paneAlive: ChannelOpts[\"paneAlive\"],\n): Promise<HostChannel[]> {\n if (paneAlive === undefined) return [];\n const dead: HostChannel[] = [];\n for (const c of listHostChannels(db, host)) {\n if (c.kind !== \"attached\" || c.pane_id === null) continue;\n try {\n if (!(await paneAlive(c.pane_id))) dead.push(c);\n } catch {\n /* unknown: keep */\n }\n }\n return dead;\n}\n\n/**\n * Delete proven-dead rows: transient by pid, and held while its template's\n * process group lives, whoever died; attached only the identity that\n * was PROBED dead. `deadPanes` is the snapshot read before the awaited probe;\n * a row matches only if holder, token, agent id and pane all equal it, and\n * the DELETE binds the snapshot's values, never the re-read row's.\n */\nfunction reclaim(db: Db, host: string, deadPanes: readonly HostChannel[]): void {\n const del = db.prepare(\n \"DELETE FROM host_channels WHERE host = ? AND holder = ? AND token = ? AND agent_id IS ? AND pane_id IS ?\",\n );\n for (const c of listHostChannels(db, host)) {\n if (c.kind === \"transient\") {\n const holderGone = c.pid !== null && pidProvenGone(c.pid, c.pid_start);\n if (holderGone && !(c.pgid !== null && groupAlive(c.pgid, c.pgid_start))) {\n del.run(host, c.holder, c.token, c.agent_id, c.pane_id);\n }\n continue;\n }\n for (const d of deadPanes) {\n if (d.holder === c.holder && d.token === c.token) {\n del.run(host, d.holder, d.token, d.agent_id, d.pane_id);\n }\n }\n }\n}\n\n/**\n * Reserve a transient channel for `holder`, or throw HostChannelBusyError\n * naming who holds the host. One holder never holds two channels, and a\n * refused call changes nothing (it can never release or steal another's).\n */\nexport async function reserveHostChannel(\n db: Db,\n host: string,\n holder: string,\n opts: ChannelOpts = {},\n): Promise<HostLease> {\n return (await admit(db, host, holder, opts)).lease;\n}\n\n/**\n * Admission: the profile is read INSIDE the BEGIN IMMEDIATE that counts, so\n * the cap enforced is the one that exists at admission (a profile removed or\n * re-added during the awaited probe is seen, or refused as not found, never\n * an orphan row). The returned profile is that snapshot; run the template\n * from it, not from a re-read.\n */\nexport async function admitHostChannel(\n db: Db,\n host: string,\n holder: string,\n opts: ChannelOpts = {},\n): Promise<{ lease: HostLease; profile: HostProfile }> {\n return admit(db, host, holder, opts);\n}\n\nasync function admit(\n db: Db,\n host: string,\n holder: string,\n opts: ChannelOpts,\n): Promise<{ lease: HostLease; profile: HostProfile }> {\n getHost(db, host); // fail fast, before probing panes\n const dead = await probeAttached(db, host, opts.paneAlive);\n const token = randomUUID();\n const profile = db\n .transaction(() => {\n const profile = getHost(db, host);\n reclaim(db, host, dead);\n const rows = listHostChannels(db, host);\n if (rows.some((r) => r.holder === holder)) {\n throw new HostChannelBusyError(\n host,\n [holder],\n `host ${host}: ${holder} already holds a channel`,\n );\n }\n const cap = profile.max_sessions;\n if (cap !== null && rows.length >= cap) {\n const names = rows.map((r) => r.holder);\n throw new HostChannelBusyError(\n host,\n names,\n `host ${host} is at --max-sessions ${cap}: held by ${names.join(\", \")}`,\n );\n }\n db.prepare(\n \"INSERT INTO host_channels (host, holder, kind, token, pid, pid_start, opened_at) VALUES (?, ?, 'transient', ?, ?, ?, ?)\",\n ).run(host, holder, token, process.pid, pidStart(process.pid), new Date().toISOString());\n return profile;\n })\n .immediate();\n return { lease: { host, holder, token }, profile };\n}\n\n/** Free a channel by token. False when it was already gone or is another's now. */\nexport function releaseHostChannel(db: Db, lease: HostLease): boolean {\n return (\n db\n .prepare(\"DELETE FROM host_channels WHERE host = ? AND holder = ? AND token = ?\")\n .run(lease.host, lease.holder, lease.token).changes > 0\n );\n}\n\n/** Transfer a transient reservation to an agent's pane (registry id + pane). False unless the lease is still live. */\nexport function bindHostChannel(\n db: Db,\n lease: HostLease,\n to: { agentId: number; paneId: string },\n): boolean {\n return (\n db\n .prepare(\n `UPDATE host_channels SET kind = 'attached', pid = NULL, pid_start = NULL, pgid = NULL, pgid_start = NULL, agent_id = ?, pane_id = ?\n WHERE host = ? AND holder = ? AND token = ? AND kind = 'transient'`,\n )\n .run(to.agentId, to.paneId, lease.host, lease.holder, lease.token).changes === 1\n );\n}\n\n/** Free the attached channels of one agent incarnation: registry id AND pane, never a name. Touches nothing else. */\nexport function releaseHostChannelsForAgent(db: Db, agentId: number, paneId: string): number {\n return db\n .prepare(\"DELETE FROM host_channels WHERE kind = 'attached' AND agent_id = ? AND pane_id = ?\")\n .run(agentId, paneId).changes;\n}\n\n/**\n * Record the template's process group on its lease (compare-and-set on the\n * token). Throws when the lease is gone, so the command never starts under a\n * channel it no longer holds.\n */\nfunction recordGroup(db: Db, lease: HostLease, pgid: number): void {\n const n = db\n .prepare(\n \"UPDATE host_channels SET pgid = ?, pgid_start = ? WHERE host = ? AND holder = ? AND token = ?\",\n )\n .run(pgid, pidStart(pgid), lease.host, lease.holder, lease.token).changes;\n if (n !== 1) throw new Error(say(\"host.channel_lost\", lease.host, lease.holder));\n}\n\n/** Hold a transient channel for the duration of `run` (given the admission snapshot of the profile and the lease); released in `finally` by token. */\nexport async function withHostChannel<T>(\n db: Db,\n host: string,\n holder: string,\n run: (profile: HostProfile, lease: HostLease) => Promise<T>,\n opts: ChannelOpts = {},\n): Promise<T> {\n const { lease, profile } = await admit(db, host, holder, opts);\n try {\n return await run(profile, lease);\n } finally {\n releaseHostChannel(db, lease);\n }\n}\n\n// ─── Running templates ──────────────────────────────────────────────────\n\n/** Per-command budget for exec and check. */\nexport const HOST_COMMAND_TIMEOUT_MS = 20_000;\n\nexport interface HostRun {\n /** null: killed by the timeout or a signal. */\n exitCode: number | null;\n stdout: string;\n stderr: string;\n}\n\n/**\n * Expand `field` of `profile` and run it with /bin/sh -c. No retry, no\n * fallback. The command is its own process group: on timeout or caller\n * termination the whole group (the template's transport included) is gone\n * before this returns, so the channel is never released under a live one.\n */\nexport async function runLeasedTemplate(\n db: Db,\n lease: HostLease,\n profile: HostProfile,\n field: \"exec\" | \"fetch\",\n values: HostTemplateValues,\n timeoutMs: number,\n /** The template's LOCAL working directory (a `--fetch` runs in the repo it fetches into). */\n localCwd?: string,\n): Promise<HostRun> {\n const expanded = expandHostTemplate(profile[field], values);\n return execGroupCapture(\"/bin/sh\", [\"-c\", expanded], {\n timeoutMs,\n ...(localCwd !== undefined ? { cwd: localCwd } : {}),\n onSpawn: (pgid) => recordGroup(db, lease, pgid),\n });\n}\n\n/** Run the profile's `exec` or `fetch` template under one transient channel. */\nexport async function runHostTemplate(\n db: Db,\n host: string,\n field: \"exec\" | \"fetch\",\n holder: string,\n values: HostTemplateValues,\n opts: ChannelOpts & { timeoutMs?: number; localCwd?: string } = {},\n): Promise<HostRun> {\n const timeoutMs = opts.timeoutMs ?? HOST_COMMAND_TIMEOUT_MS;\n return withHostChannel(\n db,\n host,\n holder,\n (profile, lease) =>\n runLeasedTemplate(db, lease, profile, field, values, timeoutMs, opts.localCwd),\n opts,\n );\n}\n\n// ─── Check ──────────────────────────────────────────────────────────────\n\nexport interface HostCheckStep {\n step: \"reachable\" | \"repo\" | \"pi\" | \"extension\" | \"ctl\";\n /** null: skipped because the host was not reachable. */\n ok: boolean | null;\n detail: string;\n}\n\nexport interface HostCheckReport {\n host: string;\n ok: boolean;\n steps: HostCheckStep[];\n}\n\nexport interface HostCheckOptions extends ChannelOpts {\n timeoutMs?: number;\n /** Also probe this agent's derived local control socket: the forward rides its pane. */\n agent?: { name: string; workstream: string };\n /** The remote repo the `repo` step checks (default the profile's); with neither it is skipped. */\n root?: string;\n}\n\nconst firstLine = (s: string): string =>\n s\n .split(\"\\n\")\n .find((l) => l.trim() !== \"\")\n ?.trim() ?? \"\";\n\n/** An interactive login shell may print rc-file noise first: the answer is the last stdout line. */\nconst lastLine = (s: string): string =>\n s\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter((l) => l !== \"\")\n .pop() ?? \"\";\n\n/**\n * Check a host through its own stored templates, under ONE channel: the\n * host answers `exec`, the repo (`root`, else the profile's default; skipped\n * with neither) is a git repo, pi runs under the login\n * shell, `pi list` names mu, and with `agent` the forwarded socket answers\n * hello. Each failure is reported; none is retried; an unreachable host\n * skips the rest. The ctl probe only reads an existing forward.\n */\nexport async function checkHost(\n db: Db,\n host: string,\n opts: HostCheckOptions = {},\n): Promise<HostCheckReport> {\n getHost(db, host);\n const timeoutMs = opts.timeoutMs ?? HOST_COMMAND_TIMEOUT_MS;\n const steps: HostCheckStep[] = [];\n const login = (cmd: string): string => `\"\\${SHELL:-sh}\" -ilc ${shellQuote(cmd)}`;\n\n await withHostChannel(\n db,\n host,\n `check:${process.pid}`,\n async (profile, lease) => {\n const root = opts.root ?? profile.repo ?? undefined;\n // One remote command through `exec`; `good` turns a clean exit into a detail, or undefined.\n const step = async (\n name: HostCheckStep[\"step\"],\n cmd: string,\n good: (r: HostRun) => string | undefined,\n unmet: string,\n ): Promise<boolean> => {\n let detail: string;\n let ok = false;\n try {\n const r = await runLeasedTemplate(\n db,\n lease,\n profile,\n \"exec\",\n // `.` without a repo: a template's `cd {cwd:sh}` stays in the login directory.\n { cmd, cwd: root ?? \".\" },\n timeoutMs,\n );\n const why = firstLine(r.stderr) || firstLine(r.stdout);\n const good1 = r.exitCode === 0 ? good(r) : undefined;\n ok = good1 !== undefined;\n detail =\n good1 ??\n (r.exitCode === null\n ? `timed out after ${timeoutMs}ms`\n : r.exitCode === 0\n ? unmet\n : `exit ${r.exitCode}${why === \"\" ? \"\" : `: ${why}`}`);\n } catch (e) {\n if (!(e instanceof HostTemplateError)) throw e;\n detail = e.message;\n }\n steps.push({ step: name, ok, detail });\n return ok;\n };\n if (await step(\"reachable\", \"true\", () => \"exec answered\", \"\")) {\n if (root === undefined) {\n steps.push({ step: \"repo\", ok: null, detail: \"skipped: no repo given (--root)\" });\n } else {\n await step(\"repo\", `git -C ${remotePathWord(root)} rev-parse --git-dir`, () => root, \"\");\n }\n await step(\n \"pi\",\n login(\"pi --version\"),\n (r) => lastLine(r.stdout) || undefined,\n \"pi printed no version\",\n );\n await step(\n \"extension\",\n login(\"pi list\"),\n (r) =>\n r.stdout\n .split(\"\\n\")\n .find((l) => /\\bmu\\b/.test(l))\n ?.trim(),\n \"pi list does not name mu\",\n );\n } else {\n for (const s of [\"repo\", \"pi\", \"extension\"] as const) {\n steps.push({ step: s, ok: null, detail: \"skipped: host not reachable\" });\n }\n }\n if (opts.agent !== undefined) {\n const { name, workstream } = opts.agent;\n const p = await ctlProbe(\n ctlSocketPath(workstream, name, dirname(db.name)),\n Math.min(timeoutMs, 5000),\n );\n const who = `${workstream}/${name}`;\n steps.push(\n p.kind === \"ok\"\n ? {\n step: \"ctl\",\n ok: true,\n detail: `${who}: extension ${p.extVersion ?? \"version unknown\"}${p.features ? ` (${p.features.join(\", \")})` : \"\"}`,\n }\n : {\n step: \"ctl\",\n ok: false,\n detail: `${who}: ${p.kind === \"refused\" ? `refused: ${p.error}` : p.kind === \"missing\" ? \"no forwarded socket\" : \"protocol version mismatch\"}`,\n },\n );\n }\n },\n opts,\n );\n return { host, ok: steps.every((s) => s.ok !== false), steps };\n}\n","// mu — the **op context** SDK seam (docs/VOCABULARY.md § op context).\n//\n// Triggers capture reliably but blindly: they see a row change, not why\n// it happened. Intent, grouping and actor are recovered by having the\n// SDK write them into the one-row `op_ctx` table, which the stored\n// triggers read as they stamp each op.\n//\n// ONE ASSIGNMENT PER PUBLIC SDK FUNCTION, not an emit per mutation.\n// That is the whole reason this is cheap enough to apply everywhere: a\n// cascade close touching 12 tasks sets the context once and gets 12\n// correctly-labelled, correctly-grouped ops for free.\n//\n// WHY A SCOPED WRAPPER RATHER THAN A SETTER\n// -----------------------------------------\n// The obvious alternative is `setOpContext(db, {...})` called at the top\n// of each SDK function. It was rejected: it leaks. Whatever intent was\n// set last stays set for the rest of the process, so the NEXT mutation\n// — possibly in a caller that never set a context, possibly in a\n// finally-block cleanup after a throw — gets mislabelled with a stale\n// intent. A wrong intent is worse than a null one, because `mu log`\n// renders it as confident prose.\n//\n// `withOpContext(db, {...}, fn)` restores the previous context in a\n// `finally`, so:\n// * a throw inside fn cannot leak the intent (tested),\n// * nesting is predictable — an inner context wins while it runs and\n// the outer one is exactly restored after,\n// * the context's lifetime is visible in the source as a block.\n//\n// Nested calls inherit the OUTER group by default, which is what makes\n// grouping work without any caller threading a group id around:\n// `closeTask` opening a group and calling `setTaskStatus` per cascaded\n// child yields one group covering all of them. An inner call that wants\n// its own group passes `group: \"new\"`.\n\nimport { randomUUID } from \"node:crypto\";\nimport { type Db, prepareCached } from \"./db.js\";\n\n/** What an op context carries. All fields optional — a partial context\n * is fine and a null intent is captured as null (fail safe). */\nexport interface OpContext {\n /** Semantic label, e.g. `task.close`. Human-grade: `mu log` renders\n * prose from it. Use `<entity>.<verb>` with entities from\n * docs/VOCABULARY.md. */\n intent?: string | undefined;\n /**\n * Intent to use ONLY when no enclosing context already set one.\n *\n * For shared internals that several public verbs funnel through.\n * `setTaskStatus` is the motivating case: called directly it is the\n * operator's action and should label itself, but called from\n * `closeTask` the OUTER verb is the operator-meaningful label and\n * must win. Without this, the inner call would report the mechanism\n * instead of the intent.\n *\n * Ignored when `intent` is also provided.\n */\n intentIfUnset?: string | undefined;\n /** Who caused it. Free text (lands in `ops.actor`): an agent name, \"user\", \"system\". */\n actor?: string | undefined;\n /**\n * Op grouping:\n * - omitted inherit the enclosing group, or start one if none.\n * - \"new\" force a fresh group even when nested.\n * - <string> use this exact group id.\n */\n group?: string | \"new\" | undefined;\n}\n\ninterface CtxRow {\n group_id: string | null;\n actor: string | null;\n intent: string | null;\n applying: number;\n}\n\n/** The context at rest: what a row holds whenever no wrapper is active,\n * and what a plain write from any connection is stamped with. */\nconst DEFAULT_CTX: CtxRow = { group_id: null, actor: null, intent: null, applying: 0 };\n\n/** Read the current context. Exported for tests and for `mu doctor`. */\nexport function currentOpContext(db: Db): {\n groupId: string | null;\n actor: string | null;\n intent: string | null;\n applying: boolean;\n} {\n const row = readCtx(db) ?? DEFAULT_CTX;\n return {\n groupId: row.group_id,\n actor: row.actor,\n intent: row.intent,\n applying: row.applying !== 0,\n };\n}\n\nfunction writeCtx(db: Db, row: CtxRow): void {\n prepareCached(\n db,\n `INSERT INTO op_ctx (id, group_id, actor, intent, applying)\n VALUES (1, @group_id, @actor, @intent, @applying)\n ON CONFLICT (id) DO UPDATE SET group_id = excluded.group_id, actor = excluded.actor,\n intent = excluded.intent, applying = excluded.applying`,\n ).run(row);\n}\n\nfunction readCtx(db: Db): CtxRow | undefined {\n return prepareCached(\n db,\n \"SELECT group_id, actor, intent, applying FROM op_ctx WHERE id = 1\",\n ).get() as CtxRow | undefined;\n}\n\n/**\n * Run `fn` with `next(previous)` as the context row, then put the\n * context back. THE one place that writes `op_ctx`.\n *\n * Outermost call (no transaction open) OWNS the transaction:\n *\n * BEGIN IMMEDIATE; write ctx; fn(); reset ctx to defaults; COMMIT\n *\n * `op_ctx` is a plain table in the file, shared by every connection, so\n * the context may only exist INSIDE a write transaction: other writers\n * wait on the lock instead of being stamped with this intent (or with\n * `applying = 1`, which would drop their ops), readers see the committed\n * defaults, and a throw or a crash rolls the context back with the data.\n * A throw in `fn` is ROLLBACK, which discards the context write too.\n *\n * Nested call (a transaction is already open, ours or a caller's): no\n * BEGIN/COMMIT; write, run, and restore the PREVIOUS row in a `finally`,\n * so an inner scope wins while it runs and the outer one is exactly\n * back after. better-sqlite3 `db.transaction()` calls inside `fn` become\n * savepoints and keep working.\n *\n * A readonly connection cannot stamp anything: `fn` just runs.\n */\nfunction withCtxRow<T>(db: Db, next: (previous: CtxRow) => CtxRow, fn: () => T): T {\n if (db.readonly) return fn();\n\n if (db.inTransaction) {\n const previous = readCtx(db) ?? DEFAULT_CTX;\n const row = next(previous);\n // Hot path (ingest calls this once per op, already suppressed).\n if (sameCtx(row, previous)) return fn();\n writeCtx(db, row);\n try {\n return fn();\n } finally {\n // The context row lives in the transaction. If fn ended it (an\n // implicit ROLLBACK such as INSERT OR ROLLBACK, a RAISE(ROLLBACK)\n // trigger, SQLITE_FULL, or a raw COMMIT) the write below would\n // AUTOCOMMIT, publishing the outer context (even `applying = 1`)\n // to every other connection. So restore only inside a live\n // transaction; otherwise leave nothing but defaults behind. The\n // outermost scope reports the ended transaction.\n if (db.inTransaction) writeCtx(db, previous);\n else resetCommittedCtx(db);\n }\n }\n\n db.exec(\"BEGIN IMMEDIATE\");\n let result: T;\n try {\n // At rest the row is defaults. Read it anyway (rather than assuming)\n // so a hand-edited row cannot leak into the scope's inheritance.\n writeCtx(db, next(DEFAULT_CTX));\n result = fn();\n if (!db.inTransaction) throw new CtxTransactionEndedError();\n writeCtx(db, DEFAULT_CTX);\n } catch (err) {\n if (db.inTransaction) {\n try {\n db.exec(\"ROLLBACK\");\n } catch {}\n } else {\n // fn ended the transaction the context lives in. After a ROLLBACK\n // the row is already defaults and nothing is written; after a\n // COMMIT it was committed too, so put it back before anyone else\n // reads it.\n resetCommittedCtx(db);\n }\n throw err;\n }\n try {\n db.exec(\"COMMIT\");\n } catch (err) {\n // A deferred FK violation fails COMMIT and leaves the transaction\n // open (still holding the lock, context row and all).\n if (db.inTransaction) {\n try {\n db.exec(\"ROLLBACK\");\n } catch {}\n }\n throw err;\n }\n return result;\n}\n\n/** Outside any transaction: make the committed context row defaults,\n * writing (an autocommit, waiting on the lock like any writer) only if\n * it is not already. A rolled-back scope needs no write at all. */\nfunction resetCommittedCtx(db: Db): void {\n const row = readCtx(db);\n if (row !== undefined && sameCtx(row, DEFAULT_CTX)) return;\n writeCtx(db, DEFAULT_CTX);\n}\n\n/** Thrown when `fn` COMMITs or ROLLBACKs the transaction its op-context\n * scope owns (a raw `COMMIT`, `END`, `ROLLBACK`). The scope cannot\n * honour its contract after that, so it fails loudly. */\nexport class CtxTransactionEndedError extends Error {\n override readonly name = \"CtxTransactionEndedError\";\n constructor() {\n super(\n \"an op-context scope's transaction was ended inside the scope (COMMIT/END/ROLLBACK); the scope owns that transaction\",\n );\n }\n}\n\nconst sameCtx = (a: CtxRow, b: CtxRow): boolean =>\n a.group_id === b.group_id &&\n a.actor === b.actor &&\n a.intent === b.intent &&\n a.applying === b.applying;\n\n/**\n * Run `fn` with the given op context applied; see `withCtxRow` for the\n * transaction it owns and how the context is restored.\n *\n * Synchronous by design. Every mutating mu SDK function is synchronous\n * (better-sqlite3 is), so an async variant would only invite\n * interleaving two contexts on one connection — and, now that the scope\n * holds the write lock, would hold it across an await. Keeping this sync\n * makes both unrepresentable.\n */\nexport function withOpContext<T>(db: Db, ctx: OpContext, fn: () => T): T {\n return withCtxRow(\n db,\n (previous) => {\n const groupId =\n ctx.group === \"new\"\n ? randomUUID()\n : ctx.group !== undefined\n ? ctx.group\n : (previous.group_id ?? randomUUID());\n return {\n group_id: groupId,\n // An explicit undefined inherits; only a provided value overrides.\n actor: ctx.actor !== undefined ? ctx.actor : previous.actor,\n intent:\n ctx.intent !== undefined ? ctx.intent : (previous.intent ?? ctx.intentIfUnset ?? null),\n applying: previous.applying,\n };\n },\n fn,\n );\n}\n\n/**\n * Run `fn` with capture SUPPRESSED — the echo guard.\n *\n * Applying a peer's op writes to `tasks`, which fires the capture\n * trigger, which mints a NEW local op, which flushes to our segment and\n * propagates back to the peer, which applies it and echoes again. This\n * sets `applying = 1` so every trigger's `WHEN` clause short-circuits\n * and the ingest writes rows WITHOUT writing ops.\n *\n * It lives here rather than in the sync module because the flag is part\n * of the op-context contract the triggers read, and having exactly one\n * writer of it is the point. Outermost, it owns a transaction like\n * `withOpContext`, so `applying = 1` is never committed: a crash cannot\n * leave capture off, and no other connection can write while it is on.\n * The previous value comes back in a `finally` (nested) or by ROLLBACK\n * (outermost), so a throw mid-ingest cannot leave capture disabled, the\n * worst failure mode: silently dropping every later local change.\n */\nexport function withCaptureSuppressed<T>(db: Db, fn: () => T): T {\n return withCtxRow(db, (previous) => ({ ...previous, applying: 1 }), fn);\n}\n","// mu — the reaper's row-level step, shared by every path that deletes an agent row.\n//\n// `reapAgentRow` runs INSIDE the caller's transaction (it opens none) and\n// does, in order: snapshot the tasks the agent holds IN_PROGRESS, DELETE the\n// row (the FK sets tasks.owner_id NULL; its trigger records a remote\n// worktree, src/db-recovery.ts), free its host channel, then reopen each snapshotted\n// task with a `[reaper]` note. A throw anywhere rolls the lot back with the\n// caller's transaction: the row stays, nothing is recorded.\n//\n// The op context is the CALLER's: `deleteAgent` opens `task.reap`, teardown\n// its own `workstream.teardown` group, and the reaper adds no group of its\n// own. The note is inserted by task id (not through `addNote`, which looks\n// the task up through a LIVE workstream): an owned task in a workstream that\n// is already torn down must still be reopened, never left IN_PROGRESS with no\n// owner.\n\nimport type { Db } from \"../db.js\";\nimport { releaseHostChannelsForAgent } from \"../hosts.js\";\nimport { withOpContext } from \"../op-context.js\";\n\nexport interface ReapOptions {\n /** False when the caller has itself dealt with the remote worktree (a close that removed it). Default true. */\n preserve?: boolean;\n}\n\n/** Delete agent row `agentId` (named `name`, for the note). False when it is already gone. */\nexport function reapAgentRow(\n db: Db,\n agentId: number,\n name: string,\n opts: ReapOptions = {},\n): boolean {\n const stuck = db\n .prepare(\n `SELECT t.id AS taskId FROM tasks t\n WHERE t.owner_id = ? AND t.status = 'IN_PROGRESS'`,\n )\n .all(agentId) as Array<{ taskId: number }>;\n const pane = db.prepare(\"SELECT pane_id FROM agents WHERE id = ?\").get(agentId) as\n | { pane_id: string }\n | undefined;\n if (pane === undefined) return false;\n // The row's AFTER DELETE trigger writes its remote recovery record (src/db-recovery.ts).\n if (db.prepare(\"DELETE FROM agents WHERE id = ?\").run(agentId).changes === 0) return false;\n // A close that has itself removed (or found gone) the tree owes no record.\n if (opts.preserve === false)\n db.prepare(\"DELETE FROM remote_recovery WHERE agent_id = ?\").run(agentId);\n // A remote agent's pane IS its host transport: the row's death frees the\n // channel it held, by registry id + pane (never a name).\n releaseHostChannelsForAgent(db, agentId, pane.pane_id);\n const reopen = db.prepare(\n \"UPDATE tasks SET status = 'OPEN', substate = CASE WHEN kind = 'human' THEN 'parked' ELSE 'todo' END, updated_at = ? WHERE id = ?\",\n );\n const note = db.prepare(\n \"INSERT INTO task_notes (task_id, author, content, created_at, kind) VALUES (?, 'reaper', ?, ?, 'note')\",\n );\n for (const t of stuck) {\n const now = new Date().toISOString();\n reopen.run(now, t.taskId);\n // The note keeps its own intent (as `addNote` gave it) inside the caller's group.\n withOpContext(db, { intent: \"task.note\", actor: \"reaper\" }, () =>\n note.run(\n t.taskId,\n `[reaper] previous owner ${name} gone (agent removed); status reverted IN_PROGRESS → OPEN, owner cleared`,\n now,\n ),\n );\n }\n return true;\n}\n","// mu — the canonical \"reality wins\" reconciliation routine.\n//\n// Two steps, in order:\n//\n// 1. Prune ghost rows whose pane no longer exists in the mux.\n// 2. Surface orphan panes that look like agents but have no DB row.\n// Never auto-register them — `mu agent list` shows orphans under a\n// separate section; the user closes the pane or ignores it.\n//\n// `mu state`, `mu agent list`, and `mu doctor` all call this. It's the only\n// place where the registry's view of the world is reconciled against tmux's\n// view.\n\nimport * as agentSdk from \"./agents.js\";\nimport type { Db } from \"./db.js\";\nimport { activeMux, type MuxPane } from \"./mux.js\";\n\n/**\n * What kind of reconciliation pass to run.\n *\n * \"full\" Default for `mu state` and `mu agent list`. Prunes\n * ghosts (deleting the registry row, which fires the\n * deleteAgent reaper that flips IN_PROGRESS tasks back\n * to OPEN with [reaper] notes), surfaces orphans.\n *\n * \"report-only\" Pure observation. Counts would-be-pruned ghosts\n * without deleting (no DB writes); surfaces orphans\n * (pure read). Used by `mu doctor` (read-only\n * diagnostic).\n *\n * Mid-spawn placeholders are protected directly in the prune loop, so read\n * paths no longer need a separate mode just to avoid racing spawn's worktree\n * pre-stage.\n */\nexport type ReconcileMode = \"full\" | \"report-only\";\n\nexport interface ReconcileOptions {\n /** The workstream whose registry rows we're reconciling. */\n workstream: string;\n /**\n * Override the tmux session name. Defaults to `mu-<workstream>`. Useful\n * for tests and for the rare case where a workstream's tmux session was\n * created with a non-default name.\n */\n tmuxSession?: string;\n /**\n * Which kind of pass to run. Default is `\"full\"` (the documented\n * mutating behaviour `mu agent list` has always had). See\n * `ReconcileMode` for the full per-mode contract.\n *\n * BREAKING: this replaces the previous `dryRun?: boolean` flag.\n * Migration: `dryRun: true` → `mode: \"report-only\"`; default\n * (`dryRun: false` / unset) → `mode: \"full\"`.\n */\n mode?: ReconcileMode;\n}\n\nexport interface ReconcileReport {\n /** Number of registry rows whose pane was gone. In `report-only` mode\n * this is the count of rows that WOULD have been pruned; in `full`\n * mode it's the count actually deleted. */\n prunedGhosts: number;\n /** Panes in the workstream's tmux session that look like agents but\n * aren't in the registry. Never auto-registered. */\n orphans: MuxPane[];\n /** Which mode this report was generated in. Lets callers switch their\n * output text (\"agents pruned\" vs \"would-be-pruned (suppressed)\")\n * without re-deriving from options. */\n mode: ReconcileMode;\n}\n\n/**\n * Pane commands that suggest \"this is an agent, surface it as an orphan.\"\n * Detection: pi only, but the orphan list will surface\n * claude/codex panes too so the user can see them.\n *\n * Also includes any env-overridden binary names (e.g. `MU_PI_COMMAND=pi-alt`\n * makes \"pi-alt\" agent-worthy) so externally-spawned panes running the\n * user's actual pi binary are still surfaced as orphans.\n */\nconst BASE_AGENT_CLIS: readonly string[] = [\"pi\", \"claude\", \"codex\"];\n\nfunction knownAgentCommands(): ReadonlySet<string> {\n const names = new Set<string>(BASE_AGENT_CLIS);\n for (const cli of BASE_AGENT_CLIS) {\n names.add(agentSdk.resolveCliCommand(cli));\n }\n return names;\n}\n\n/**\n * Build a recogniser closure that captures one snapshot of\n * knownAgentCommands() (which itself reads MU_<CLI>_COMMAND env vars).\n * Hoisted out of the orphan-surface loop so reconcile() reads each env\n * var at most once per pass instead of once per pane: dozens of panes\n * × three env vars per call = needless syscalls in a `mu state` poll\n * tick. Also pins the env-var snapshot for the loop, so test suites\n * that twiddle MU_PI_COMMAND in afterEach can't race the inner check.\n */\nfunction buildAgentPaneRecogniser(): (pane: MuxPane) => boolean {\n const known = knownAgentCommands();\n return (pane) => known.has(pane.command);\n}\n\nexport async function reconcile(db: Db, opts: ReconcileOptions): Promise<ReconcileReport> {\n const sessionName = opts.tmuxSession ?? `mu-${opts.workstream}`;\n const mode: ReconcileMode = opts.mode ?? \"full\";\n const dbAgents = agentSdk.listAgents(db, { workstream: opts.workstream });\n // Load-bearing: reconcile IS the mux read. With no reachable mux there\n // is no reality to reconcile against, and silently reporting \"zero\n // panes\" would prune every registered agent as a ghost.\n const mux = await activeMux();\n const muxPanes = await mux.listPanes(sessionName);\n const paneById = new Map(muxPanes.map((p) => [p.paneId, p]));\n\n let prunedGhosts = 0;\n const orphans: MuxPane[] = [];\n\n // 1. Prune ghosts (DB row references a pane that no longer exists).\n // `full` mode deletes (and therefore reaps); `report-only` counts\n // the would-be-prunes so callers can surface drift, but leaves the\n // row in place. Mid-spawn placeholder pane ids are protected by\n // the defensive skip that lets read paths use full mode safely.\n // Placeholder rows survive this step, but are split out so the\n // orphan exclusion only reasons about real panes.\n const survivors: agentSdk.AgentRow[] = [];\n const pendingSurvivors: agentSdk.AgentRow[] = [];\n for (const agent of dbAgents) {\n if (agentSdk.isPendingPaneId(agent.paneId)) {\n pendingSurvivors.push(agent);\n } else if (paneById.has(agent.paneId)) {\n survivors.push(agent);\n } else {\n if (mode !== \"full\") {\n prunedGhosts++;\n } else if (\n agentSdk.deleteAgent(db, agent.name, agent.workstreamName, {\n paneId: agent.paneId,\n incarnation: agent.incarnation,\n })\n ) {\n prunedGhosts++;\n }\n }\n }\n\n // 2. Surface orphan panes. `looksLikeAgentPane` is conservative:\n // pane.command must be one we recognise as an agent CLI. A bash\n // pane the user spawned for their own use is never an orphan.\n // Pure read; runs in every mode.\n const dbPaneIds = new Set(survivors.map((a) => a.paneId));\n const looksLikeAgentPane = buildAgentPaneRecogniser();\n for (const pane of muxPanes) {\n if (dbPaneIds.has(pane.paneId)) continue;\n if (looksLikeAgentPane(pane)) orphans.push(pane);\n }\n\n return { prunedGhosts, orphans, mode };\n}\n","// mu — task revisions: the `--if <rev>` fence for membership-changing and\n// destructive task verbs.\n//\n// A task's revision is DERIVED from current state, never counted: a hash\n// of the task row's portable fields, the owner, every incoming and outgoing\n// edge (each endpoint as `<workstream>/<local_id>`) and the number of\n// notes. It is computed on read (show / list / delete preview) and again\n// inside the guarded write's transaction, after sync ingest. No write path\n// has to remember to bump anything, so none can miss: a local verb, a peer\n// op applied under capture suppression, a cascade (a synced blocker delete\n// drops the edge without an edge op) or a rebuild all move it by changing\n// the state it hashes. Lookups are exact (`=`), never LIKE: `_` is a\n// wildcard there, and task ids are full of it. Another workstream's tasks\n// and sibling tasks never move it.\n//\n// The revision is a 48-bit integer taken from SHA-256, so it fits a JSON\n// number and `--if <int>`. An absent task is revision 0.\n//\n// Agents have one too (`agentRevision`, below), derived the same way. The\n// rest of the fence is in src/agents.ts (`closeAgent`) and src/agents/lock.ts.\n// `workstreamRevision` (src/workstream.ts) keeps fencing teardown.\n\nimport { createHash } from \"node:crypto\";\nimport type { Db } from \"./db.js\";\nimport { say } from \"./messages.js\";\n\n/** A guarded verb was given a revision that no longer matches. Exit 4,\n * nothing was done. One stderr line naming the fresh preview\n * command; JSON carries `expected_rev` / `current_rev`. */\nexport class RevisionMismatchError extends Error {\n override readonly name = \"RevisionMismatchError\";\n constructor(\n public readonly subject: string,\n public readonly expectedRev: number,\n public readonly currentRev: number,\n /** The read-only command that prints the current revision. */\n public readonly previewCommand: string,\n ) {\n super(say(\"revision.changed\", subject, expectedRev, currentRev, previewCommand));\n }\n}\n\n/** Throws when a supplied `expected` differs from `current`. `undefined`\n * (no `--if`) always passes. */\nexport function assertRevision(\n expected: number | undefined,\n current: number,\n ctx: { subject: string; previewCommand: string },\n): void {\n if (expected === undefined || expected === current) return;\n throw new RevisionMismatchError(ctx.subject, expected, current, ctx.previewCommand);\n}\n\nconst cmp = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0);\n\ninterface TaskStateRow {\n id: number;\n local_id: string;\n title: string;\n status: string;\n substate: string;\n impact: number;\n effort_days: number;\n scored: number;\n dispatch_host: string | null;\n kind: string;\n wave: string | null;\n created_at: string;\n updated_at: string;\n owner: string | null;\n}\n\n/** Revision of every task of `workstream` (task id → revision), or of the\n * one task `only` names. Read only. */\nfunction derive(db: Db, workstream: string, only?: string): Map<string, number> {\n const idFilter = only === undefined ? \"\" : \" AND t.local_id = @only\";\n const params: Record<string, string> = { ws: workstream };\n if (only !== undefined) params.only = only;\n const tasks = db\n .prepare(\n `SELECT t.id, t.local_id, t.title, t.status, t.substate, t.impact, t.effort_days,\n t.scored, t.dispatch_host, t.kind, t.wave, t.created_at, t.updated_at,\n CASE WHEN a.id IS NULL THEN NULL ELSE aws.name || '/' || a.name END AS owner\n FROM tasks t\n JOIN workstreams w ON w.id = t.workstream_id\n LEFT JOIN agents a ON a.id = t.owner_id\n LEFT JOIN workstreams aws ON aws.id = a.workstream_id\n WHERE w.name = @ws${idFilter}`,\n )\n .all(params) as TaskStateRow[];\n const byRow = new Map<number, { row: TaskStateRow; blockers: string[]; dependents: string[] }>();\n for (const row of tasks) byRow.set(row.id, { row, blockers: [], dependents: [] });\n if (byRow.size === 0) return new Map();\n\n // Both directions of every edge touching a task of this workstream. An\n // edge from another workstream lands on the local end (the sync apply\n // path accepts one), whichever endpoint the op key names first.\n const edges = db\n .prepare(\n `SELECT e.from_task_id AS fid, e.to_task_id AS tid,\n fw.name || '/' || f.local_id AS fkey, tw.name || '/' || t.local_id AS tkey\n FROM task_edges e\n JOIN tasks f ON f.id = e.from_task_id JOIN workstreams fw ON fw.id = f.workstream_id\n JOIN tasks t ON t.id = e.to_task_id JOIN workstreams tw ON tw.id = t.workstream_id\n WHERE (fw.name = @ws${only === undefined ? \"\" : \" AND f.local_id = @only\"})\n OR (tw.name = @ws${only === undefined ? \"\" : \" AND t.local_id = @only\"})`,\n )\n .all(params) as { fid: number; tid: number; fkey: string; tkey: string }[];\n for (const e of edges) {\n byRow.get(e.tid)?.blockers.push(e.fkey);\n byRow.get(e.fid)?.dependents.push(e.tkey);\n }\n\n const notes = new Map<number, number>();\n const noteRows = db\n .prepare(\n `SELECT n.task_id AS id, COUNT(*) AS n\n FROM task_notes n\n JOIN tasks t ON t.id = n.task_id\n JOIN workstreams w ON w.id = t.workstream_id\n WHERE w.name = @ws${idFilter} GROUP BY n.task_id`,\n )\n .all(params) as { id: number; n: number }[];\n for (const r of noteRows) notes.set(r.id, r.n);\n\n const out = new Map<string, number>();\n for (const [rowId, { row, blockers, dependents }] of byRow) {\n const { id: _rowid, ...fields } = row;\n // Canonical edge order (endpoint id, then kind), so the hash never\n // depends on the order SQLite returned the rows in.\n const edgeList: [string, string][] = [\n ...blockers.map((k): [string, string] => [k, \"blocker\"]),\n ...dependents.map((k): [string, string] => [k, \"dependent\"]),\n ];\n edgeList.sort((x, y) => cmp(x[0], y[0]) || cmp(x[1], y[1]));\n const digest = createHash(\"sha256\")\n .update(JSON.stringify([fields, edgeList, notes.get(rowId) ?? 0]))\n .digest();\n out.set(row.local_id, digest.readUIntBE(0, 6));\n }\n return out;\n}\n\n/** Revision of every task of `workstream` (task id → revision). Read only. */\nexport function taskRevisions(db: Db, workstream: string): Map<string, number> {\n return derive(db, workstream);\n}\n\n/** The revision of one task (0 when it does not exist). Read only. */\nexport function taskRevision(db: Db, workstream: string, id: string): number {\n return derive(db, workstream, id).get(id) ?? 0;\n}\n\n/** Throw `RevisionMismatchError` when `expected` is not the task's revision.\n * The task being absent is not this guard's business: the verb's own\n * not-found (or no-op) handling runs instead. `verb` picks the preview. */\nexport function assertTaskRevision(\n db: Db,\n workstream: string,\n id: string,\n expected: number | undefined,\n previewCommand = `mu task show ${id} -w ${workstream}`,\n): void {\n if (expected === undefined) return;\n const exists = db\n .prepare(\n `SELECT 1 FROM tasks t JOIN workstreams w ON w.id = t.workstream_id\n WHERE w.name = ? AND t.local_id = ?`,\n )\n .get(workstream, id);\n if (!exists) return;\n assertRevision(expected, taskRevision(db, workstream, id), {\n subject: `task ${id}`,\n previewCommand,\n });\n}\n\n/** Run `fn` with the task's revision checked in the SAME write transaction.\n * Without `expected` it just runs `fn` (no new transaction). With it, the\n * whole of `fn` (every edge of a multi-blocker block) sits behind ONE\n * check, so a batch cannot invalidate its own fence. */\nexport function withTaskFence<T>(\n db: Db,\n workstream: string,\n id: string,\n expected: number | undefined,\n fn: () => T,\n previewCommand?: string,\n): T {\n if (expected === undefined) return fn();\n return db\n .transaction(() => {\n assertTaskRevision(db, workstream, id, expected, previewCommand);\n return fn();\n })\n .immediate();\n}\n\n/** The revision of one agent (`agent close --if`), 0 when nothing of that name\n * exists. Derived on read, like the task one: a hash of the registry\n * incarnation (the row's AUTOINCREMENT id, never reused, so a name that is\n * deleted and created again can never match an old preview, even with the\n * same pane id), every column of the row (pane, cwd, host, spawner, ...), EVERY\n * task it owns in any workstream with its status (claim and release write\n * `tasks.owner_id`, not the agent row), and the registered worktree rows of\n * that (workstream, name). With no agent row but a registered worktree (an\n * orphan: a failed spawn or an earlier close left it) the hash is of those\n * rows alone, so an orphan has a revision of its own and a replaced registry\n * row moves it. Read only. */\nexport function agentRevision(\n db: Db,\n workstream: string,\n name: string,\n recoveryId?: number,\n): number {\n if (recoveryId !== undefined) return recoveryRevision(db, workstream, name, recoveryId);\n const agent = db\n .prepare(\n `SELECT a.id, a.pane_id, a.cli, a.role, a.tab, a.cwd, a.base, a.command, a.command_source,\n a.spawner, a.host, a.collected_head, a.repo, a.gate_token, a.created_at\n FROM agents a JOIN workstreams w ON w.id = a.workstream_id\n WHERE w.name = ? AND a.name = ?`,\n )\n .get(workstream, name) as ({ id: number } & Record<string, unknown>) | undefined;\n const owned = agent\n ? (db\n .prepare(\n `SELECT w.name || '/' || t.local_id AS ref, t.status, t.substate\n FROM tasks t JOIN workstreams w ON w.id = t.workstream_id\n WHERE t.owner_id = ? ORDER BY w.name, t.local_id`,\n )\n .all(agent.id) as unknown[])\n : [];\n const worktrees = db\n .prepare(\n `SELECT path, root, base, last_collected_head, created_at FROM worktrees\n WHERE workstream = ? AND agent = ? ORDER BY path`,\n )\n .all(workstream, name) as unknown[];\n if (agent === undefined && worktrees.length === 0) return recoveryRevision(db, workstream, name);\n const digest = createHash(\"sha256\")\n .update(JSON.stringify([agent ?? null, owned, worktrees]))\n .digest();\n return digest.readUIntBE(0, 6);\n}\n\n/** The revision of the remote recovery record(s) of `workstream/name` (`remote_recovery`, src/remote-recovery.ts): a hash of every column of the selected record (`recoveryId`) or, unselected, of every record of the name, so a second record moves it; plus the id of an agent that holds the name now, so a replacement does too. 0 when no record is selected. Read only. */\nfunction recoveryRevision(db: Db, workstream: string, name: string, recoveryId?: number): number {\n const rows = db\n .prepare(\n `SELECT * FROM remote_recovery WHERE workstream = ? AND name = ?${recoveryId === undefined ? \"\" : \" AND agent_id = ?\"} ORDER BY agent_id`,\n )\n .all(...(recoveryId === undefined ? [workstream, name] : [workstream, name, recoveryId]));\n if (rows.length === 0) return 0;\n const live = db\n .prepare(\n \"SELECT a.id FROM agents a JOIN workstreams w ON w.id = a.workstream_id WHERE w.name = ? AND a.name = ?\",\n )\n .get(workstream, name) as { id: number } | undefined;\n const digest = createHash(\"sha256\")\n .update(JSON.stringify([\"recovery\", rows, live?.id ?? null]))\n .digest();\n return digest.readUIntBE(0, 6);\n}\n","// mu — task error classes.\n//\n// Every task verb that can fail in a typed way has its own error class\n// here. The CLI's `classifyError()` (src/cli.ts) maps them to exit codes:\n// not found → 3 (TaskNotFoundError)\n// conflict → 4 (TaskExistsError, TaskNotInWorkstreamError,\n// TaskAlreadyOwnedError, ClaimerNotRegisteredError,\n// CrossWorkstreamEdgeError,\n// TaskParkStateError,\n// TaskParkedError, TaskInTriageError,\n// InvalidSubstateError)\n// cycle → 4 (CycleError — also a conflict)\n// usage → 2 (TaskIdInvalidError; TaskTitleSlugEmptyError in id.ts;\n// CloseNeedsEvidenceError, SubstateReasonRequiredError: a close's\n// missing --evidence / --why, on the CLI, the SDK and `mu sql --write`)\n//\n// Errors carry facts (ids, workstreams, structured fields), never commands:\n// a result's follow-up is its `next` (src/next-hints.ts).\n\nimport { say } from \"../messages.js\";\nimport { TASK_SUBSTATES, type TaskStatus, type TaskSubstate } from \"./status.js\";\n\nexport class TaskNotFoundError extends Error {\n override readonly name = \"TaskNotFoundError\";\n /** Near ids from the SAME workstream (`candidateTaskIds`), read-only\n * suggestions: filled by `handle()` after the miss, never used to write. */\n candidateIds: readonly string[] = [];\n /** `workstream` is the partition the exact lookup missed in, when known. */\n constructor(\n public readonly taskId: string,\n public readonly workstream?: string,\n /** The id the candidates are matched against, when `taskId` is the\n * operator's qualified spelling (`ws/id`). Defaults to `taskId`. */\n public readonly lookupId: string = taskId,\n ) {\n super(say(\"task.not_found\", taskId));\n }\n}\n\n/**\n * Thrown by `addTask` when `localId` violates the schema regex\n * `/^[a-z][a-z0-9_-]{0,63}$/`. Replaces a bare `TypeError` so the\n * CLI's `handle()` wrapper can map it to exit code 2 (usage, with the\n * verb's --help, like WorkstreamNameInvalidError).\n */\nexport class TaskIdInvalidError extends Error {\n override readonly name = \"TaskIdInvalidError\";\n constructor(public readonly attempted: string) {\n super(say(\"task.id_invalid\", attempted));\n }\n}\n\nexport class TaskExistsError extends Error {\n override readonly name = \"TaskExistsError\";\n constructor(public readonly taskId: string) {\n super(say(\"task.exists\", taskId));\n }\n}\n\n/**\n * Thrown when a verb is invoked with `-w/--workstream <name>` but the\n * named task lives in a different workstream. Distinguishes \"the user\n * typo'd the workstream\" from \"the task doesn't exist anywhere\"\n * (which surfaces as `TaskNotFoundError`). Maps to exit code 4\n * (conflict / wrong scope).\n */\nexport class TaskNotInWorkstreamError extends Error {\n override readonly name = \"TaskNotInWorkstreamError\";\n constructor(\n public readonly taskId: string,\n public readonly expectedWorkstream: string,\n public readonly actualWorkstream: string,\n ) {\n super(say(\"task.not_in_workstream\", taskId, expectedWorkstream, actualWorkstream));\n }\n}\n\nexport class TaskAlreadyOwnedError extends Error {\n override readonly name = \"TaskAlreadyOwnedError\";\n /** `taskId` / `currentOwner` are omitted when a raw `mu sql` write tripped\n * the guard: the SQL may not name one task, so the hints carry placeholders. */\n constructor(\n public readonly taskId = \"<id>\",\n public readonly currentOwner = \"<owner>\",\n ) {\n super(taskId === \"<id>\" ? say(\"task.owned_sql\") : say(\"task.owned\", taskId, currentOwner));\n }\n}\n\n/**\n * Thrown when `mu task claim` resolves a claimer agent name (from the\n * pane title or --for) that has no matching row in the agents table.\n *\n * The FK on `tasks.owner_id` references `agents.id`; without this guard\n * the claim attempt would fail with the unhelpful 'FOREIGN KEY constraint\n * failed' from SQLite. This typed error gives the user actionable next\n * steps (work with --self, or use --for to pick a registered agent).\n *\n * Maps to exit code 4 (conflict) via the cli.ts handler.\n */\nexport class ClaimerNotRegisteredError extends Error {\n override readonly name = \"ClaimerNotRegisteredError\";\n constructor(\n public readonly agentName: string,\n public readonly paneId: string | null,\n ) {\n super(say(\"task.claimer_unregistered\", agentName, paneId));\n }\n}\n\nexport class CycleError extends Error {\n override readonly name = \"CycleError\";\n constructor(\n public readonly from: string,\n public readonly to: string,\n /** Existing path `to -> … -> from` (task names) that the new edge would close. */\n public readonly path: readonly string[] = [],\n public readonly workstream?: string,\n ) {\n super(say(\"task.cycle\", from, to, path));\n }\n}\n\nexport class CrossWorkstreamEdgeError extends Error {\n override readonly name = \"CrossWorkstreamEdgeError\";\n constructor(\n public readonly blocker: string,\n public readonly blockerWorkstream: string,\n public readonly dependent: string,\n public readonly dependentWorkstream: string,\n ) {\n super(\n say(\"task.cross_workstream_edge\", blocker, blockerWorkstream, dependent, dependentWorkstream),\n );\n }\n}\n\n/**\n * Thrown by `closeTask` (non-`done` `--as`) and `parkTask` when no\n * non-empty `--why` was given. The reason is stored as a note, so a\n * classification with no rationale is refused before any write.\n */\nexport class SubstateReasonRequiredError extends Error {\n override readonly name = \"SubstateReasonRequiredError\";\n constructor(\n public readonly verb: \"close\" | \"park\",\n public readonly substate: TaskSubstate,\n public readonly taskId: string,\n ) {\n super(say(\"task.close_reason_needed\", verb, taskId, substate));\n }\n}\n\n/**\n * Thrown when a close lands without a `kind = 'close'` note in its op\n * group: the local-write guard `_cap_tasks_close_evidence` (src/capture.ts)\n * refused it. Raised by `closeTask` only; ingest never sees it.\n */\nexport class CloseNeedsEvidenceError extends Error {\n override readonly name = \"CloseNeedsEvidenceError\";\n /** Ids are omitted when a raw `mu sql` write tripped the guard: the SQL\n * may not name one task, so the message and hint carry placeholders. */\n constructor(\n public readonly taskId = \"<id>\",\n public readonly workstream = \"<ws>\",\n ) {\n super(\n taskId === \"<id>\"\n ? say(\"task.close_needs_evidence_sql\")\n : say(\"task.close_needs_evidence\", taskId, workstream),\n );\n }\n}\n\n/**\n * Thrown when a close to `done` finds a blocker still OPEN or\n * IN_PROGRESS (guard `_cap_tasks_close_blockers`). Classifying the task\n * as wontfix / duplicate / rejected / superseded is exempt: those do not\n * claim the work happened.\n */\nexport class TaskHasOpenBlockersError extends Error {\n override readonly name = \"TaskHasOpenBlockersError\";\n /** Ids are omitted when a raw `mu sql` write tripped the guard: the SQL\n * may not name one task, so the message and hint carry placeholders. */\n constructor(\n public readonly taskId = \"<id>\",\n public readonly workstream = \"<ws>\",\n public readonly blockerIds: readonly string[] = [],\n ) {\n super(\n taskId === \"<id>\"\n ? say(\"task.open_blockers_sql\")\n : say(\"task.open_blockers\", taskId, blockerIds),\n );\n }\n}\n\n/**\n * Thrown by `parkTask` on an IN_PROGRESS or CLOSED task. Park is one\n * transition (OPEN/todo → OPEN/parked); the owner releases, or the task\n * is reopened, first.\n */\nexport class TaskParkStateError extends Error {\n override readonly name = \"TaskParkStateError\";\n constructor(\n public readonly taskId: string,\n public readonly status: \"IN_PROGRESS\" | \"CLOSED\",\n public readonly workstream: string,\n ) {\n super(say(\"task.park_state\", taskId, status));\n }\n}\n\n/**\n * Thrown by `claimTask` on an OPEN/triage task without `force`. A triage\n * task is a proposal (often a review finding) nobody has accepted as\n * work yet; accept it, or close it rejected / duplicate.\n */\nexport class TaskInTriageError extends Error {\n override readonly name = \"TaskInTriageError\";\n constructor(\n public readonly taskId: string,\n public readonly workstream: string,\n ) {\n super(say(\"task.in_triage\", taskId));\n }\n}\n\n/**\n * Thrown by `claimTask` on an OPEN/parked task without `force`. Parked\n * means \"keep out of the scheduler\"; claiming it anyway is explicit.\n */\nexport class TaskParkedError extends Error {\n override readonly name = \"TaskParkedError\";\n constructor(\n public readonly taskId: string,\n public readonly workstream: string,\n ) {\n super(say(\"task.parked\", taskId));\n }\n}\n\n/**\n * Thrown when a verb would resolve a `human` task other than by an explicit\n * `mu task close`: unpark, claim (even --force) and a CLOSE block. A human\n * task records a decision only a person can make; nothing autonomous may\n * make it ready or close it.\n */\nexport class HumanTaskError extends Error {\n override readonly name = \"HumanTaskError\";\n constructor(\n public readonly taskId: string,\n public readonly workstream: string,\n action: string,\n ) {\n super(say(\"task.human\", taskId, workstream, action));\n }\n}\n\n/**\n * Thrown when a verb is asked for a (status, substate) pair that the\n * task_substates table does not allow, e.g. `close --as parked`.\n * Caught here rather than by the deferred FK, which would fail only at\n * commit with an opaque constraint message.\n */\nexport class InvalidSubstateError extends Error {\n override readonly name = \"InvalidSubstateError\";\n constructor(\n public readonly status: TaskStatus,\n public readonly substate: string,\n ) {\n super(say(\"task.invalid_substate\", status, substate, TASK_SUBSTATES[status]));\n }\n}\n\n/** A note selector (`--from <n>` / `--note <n>`) that is not one of the task's\n * own notes `1..total`. Exact membership: there is no fuzzy match. */\nexport class TaskNoteRangeError extends Error {\n override readonly name = \"TaskNoteRangeError\";\n constructor(\n public readonly taskId: string,\n public readonly n: number,\n public readonly total: number,\n ) {\n super(say(\"task.note_range\", taskId, n, total));\n }\n}\n","// mu — task graph shared row-shape helpers.\n//\n// This module owns the snake_case → camelCase task/note mappings and\n// surrogate-id resolution helpers consumed by the task SDK cluster.\n// It stays below the public hub (`src/tasks.ts`): cluster files import\n// from this file or sibling files, never from the hub they're re-exported\n// through.\n\nimport type { NoteKind, TaskKind } from \"../db.js\";\nimport { type Db, tryResolveLiveWorkstreamId } from \"../db.js\";\nimport type { TaskStatus, TaskSubstate } from \"./status.js\";\n\nexport interface TaskRow {\n /** Per-workstream-unique TEXT name. The operator-facing identifier. */\n name: string;\n /** Foreign-name reference to the owning workstream. */\n workstreamName: string;\n /** The real `tasks.workstream_id` (output boundary only; never invent from names). */\n workstreamId: number;\n title: string;\n status: TaskStatus;\n /** Qualifies status (e.g. OPEN/parked, CLOSED/wontfix). Never null. */\n substate: TaskSubstate;\n impact: number;\n effortDays: number;\n /** True once impact/effort were given explicitly (not defaulted). */\n scored: boolean;\n /** Host `mu next` dispatches this task to, if one was set. */\n dispatchHost: string | null;\n /** `work` (default), `delegate` or `human`. */\n kind: TaskKind;\n /** Label grouping the delegate calls of one fan-out; null when none. */\n wave: string | null;\n /** Foreign-name reference to the owning agent (NULL when unowned). */\n ownerName: string | null;\n /** The real `tasks.owner_id` (NULL when unowned). */\n ownerId: number | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface TaskNoteRow {\n /** 1-based position among the task's notes (by insertion). Task-bound and\n * local to this DB: peers may store different integer ids, so it is a\n * selector for `--from` / `--note` here, never an identity to sync. */\n n: number;\n kind: NoteKind;\n author: string | null;\n content: string;\n createdAt: string;\n}\n\nexport interface RawTaskRow {\n /** Surrogate id (v5). */\n id: number;\n local_id: string;\n workstream_id: number;\n /** Joined from workstreams.name. */\n workstream: string;\n title: string;\n status: string;\n substate: string;\n impact: number;\n effort_days: number;\n scored: number;\n dispatch_host: string | null;\n kind: string;\n wave: string | null;\n owner_id: number | null;\n /** Joined from agents.name via owner_id. NULL when unowned. */\n owner: string | null;\n created_at: string;\n updated_at: string;\n}\n\nexport interface RawTaskNoteRow {\n ord: number;\n kind: string;\n author: string | null;\n content: string;\n created_at: string;\n}\n\n// SELECT clause for v5 task reads. Joins workstreams + agents to expose\n// the operator-facing names as `workstream` and `owner`. Used by every\n// read path so callers don't see surrogate ids.\nexport const SELECT_TASK_COLS = `\n t.id AS id,\n t.local_id AS local_id,\n t.workstream_id AS workstream_id,\n ws.name AS workstream,\n t.title AS title,\n t.status AS status,\n t.substate AS substate,\n t.impact AS impact,\n t.effort_days AS effort_days,\n t.scored AS scored,\n t.dispatch_host AS dispatch_host,\n t.kind AS kind,\n t.wave AS wave,\n t.owner_id AS owner_id,\n ag.name AS owner,\n t.created_at AS created_at,\n t.updated_at AS updated_at\n`;\n\nexport const TASK_FROM_JOIN = `\n FROM tasks t\n JOIN workstreams ws ON ws.id = t.workstream_id AND ws.torn_down_at IS NULL\n LEFT JOIN agents ag ON ag.id = t.owner_id\n`;\n\nexport const SELECT_NOTE_COLS = `\n (SELECT COUNT(*) FROM task_notes m WHERE m.task_id = n.task_id AND m.id <= n.id) AS ord,\n n.kind AS kind,\n n.author AS author,\n n.content AS content,\n n.created_at AS created_at\n`;\n\nexport function rowFromDb(row: RawTaskRow): TaskRow {\n return {\n name: row.local_id,\n workstreamName: row.workstream,\n workstreamId: row.workstream_id,\n title: row.title,\n status: row.status as TaskStatus,\n substate: row.substate as TaskSubstate,\n impact: row.impact,\n effortDays: row.effort_days,\n scored: row.scored === 1,\n dispatchHost: row.dispatch_host,\n kind: row.kind as TaskKind,\n wave: row.wave,\n ownerName: row.owner,\n ownerId: row.owner_id,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport function noteFromDb(row: RawTaskNoteRow): TaskNoteRow {\n return {\n n: row.ord,\n kind: row.kind as NoteKind,\n author: row.author,\n content: row.content,\n createdAt: row.created_at,\n };\n}\n\n/** Look up a task by local_id across every workstream. Task ids are\n * unique per workstream only, so a row in `preferWorkstream` wins;\n * otherwise the first match sorted by workstream name (deterministic).\n * Used by edge verbs (addBlockEdge / reparentTask) to resolve a\n * blocker so a cross-workstream blocker can surface\n * `CrossWorkstreamEdgeError` rather than the less-actionable\n * `TaskNotFoundError`. NOT for operator-facing reads — use\n * `getTask(db, localId, workstream)` for those. */\nexport function lookupTaskAnyWorkstream(\n db: Db,\n localId: string,\n preferWorkstream?: string,\n): TaskRow | undefined {\n const row = db\n .prepare(\n `SELECT ${SELECT_TASK_COLS} ${TASK_FROM_JOIN} WHERE t.local_id = ?\n ORDER BY (ws.name = ?) DESC, ws.name LIMIT 1`,\n )\n .get(localId, preferWorkstream ?? null) as RawTaskRow | undefined;\n return row ? rowFromDb(row) : undefined;\n}\n\n/** Resolve a (workstream, localId) pair to the surrogate task id.\n * Returns null on miss. */\nexport function taskIdFor(db: Db, localId: string, workstream: string): number | null {\n const wsId = tryResolveLiveWorkstreamId(db, workstream);\n if (wsId === null) return null;\n const row = db\n .prepare(\"SELECT id FROM tasks WHERE workstream_id = ? AND local_id = ?\")\n .get(wsId, localId) as { id: number } | undefined;\n return row ? row.id : null;\n}\n\n/**\n * Bump `tasks.updated_at` on a surrogate task id. Used by every write\n * that mutates a child row (notes, edges) without touching the task\n * row itself, so `mu task list --sort recency` reflects 'last write of\n * any kind' rather than only 'last status/field change'\n * (task_updatedat_not_bumped_by_reparent). Status changes, field\n * updates, and claim/release already update `updated_at` directly in\n * their own UPDATE statements; don't double-bump from here.\n *\n * Monotonic: `updated_at` never moves backwards, so a touch carrying an\n * earlier `now` than the stored value (two writers, clock skew) is a no-op.\n *\n * Always called inside the same transaction as the child-row mutation\n * so the bump rolls back together with the mutation on error.\n */\nexport function touchTask(db: Db, taskId: number, now?: string): void {\n const ts = now ?? new Date().toISOString();\n db.prepare(\"UPDATE tasks SET updated_at = ? WHERE id = ? AND updated_at < ?\").run(ts, taskId, ts);\n}\n","// mu — task read/query primitives.\n\nimport type { Db } from \"../db.js\";\nimport { tryResolveLiveWorkstreamId } from \"../db.js\";\nimport { lastClaimEventAt } from \"../logs.js\";\nimport {\n noteFromDb,\n type RawTaskNoteRow,\n type RawTaskRow,\n rowFromDb,\n SELECT_NOTE_COLS,\n SELECT_TASK_COLS,\n TASK_FROM_JOIN,\n type TaskNoteRow,\n type TaskRow,\n taskIdFor,\n} from \"./core.js\";\nimport { TaskNoteRangeError } from \"./errors.js\";\nimport type { TaskStatus, TaskSubstate } from \"./status.js\";\n\nexport function getTask(db: Db, localId: string, workstream: string): TaskRow | undefined {\n const wsId = tryResolveLiveWorkstreamId(db, workstream);\n if (wsId === null) return undefined;\n const row = db\n .prepare(\n `SELECT ${SELECT_TASK_COLS} ${TASK_FROM_JOIN} WHERE t.workstream_id = ? AND t.local_id = ?`,\n )\n .get(wsId, localId) as RawTaskRow | undefined;\n return row ? rowFromDb(row) : undefined;\n}\n\n/**\n * The task's owner as (name, workstream), resolved through\n * `tasks.owner_id`. The owner's workstream can differ from the task's:\n * `task claim --for <ws>/<agent>` assigns an owner from another\n * workstream, and `TaskRow.ownerName` alone cannot say which.\n * Undefined when the task does not exist or has no owner.\n */\nexport function getTaskOwner(\n db: Db,\n localId: string,\n workstream: string,\n): { name: string; workstreamName: string } | undefined {\n return db\n .prepare(\n `SELECT a.name AS name, aws.name AS workstreamName\n FROM tasks t\n JOIN workstreams tws ON tws.id = t.workstream_id AND tws.torn_down_at IS NULL\n JOIN agents a ON a.id = t.owner_id\n JOIN workstreams aws ON aws.id = a.workstream_id\n WHERE t.local_id = ? AND tws.name = ?`,\n )\n .get(localId, workstream) as { name: string; workstreamName: string } | undefined;\n}\n\n/**\n * List tasks. With no `workstream` arg returns every row — used by `mu sql`\n * and by tests; CLI surfaces always pass a workstream so users only see\n * their own.\n */\nexport interface ListTasksOptions {\n /** Filter to one or more lifecycle statuses. Omitted = all statuses. */\n status?: TaskStatus | readonly TaskStatus[];\n /** Filter to one or more substates (ANDed with `status`). */\n substate?: TaskSubstate | readonly TaskSubstate[];\n /** Only tasks whose `owner_id` is this agent (the real FK, so same-named agents never mix). */\n ownerId?: number;\n}\n\n/** The agent's id by (workstream, name); null when there is no such live agent. */\nexport function agentIdByRef(db: Db, workstream: string, name: string): number | null {\n const wsId = tryResolveLiveWorkstreamId(db, workstream);\n if (wsId === null) return null;\n const row = db\n .prepare(\"SELECT id FROM agents WHERE workstream_id = ? AND name = ?\")\n .get(wsId, name) as { id: number } | undefined;\n return row === undefined ? null : row.id;\n}\n\n/** Normalise a one-or-many filter option to an array (undefined = no filter). */\nfunction asList<T extends string>(v: T | readonly T[] | undefined): readonly T[] | undefined {\n if (v === undefined) return undefined;\n return typeof v === \"string\" ? [v] : (v as readonly T[]);\n}\n\nexport function listTasks(db: Db, workstream?: string, opts: ListTasksOptions = {}): TaskRow[] {\n const statuses =\n opts.status === undefined\n ? undefined\n : Array.isArray(opts.status)\n ? (opts.status as TaskStatus[])\n : [opts.status as TaskStatus];\n\n const where: string[] = [];\n const params: unknown[] = [];\n if (workstream !== undefined) {\n const wsId = tryResolveLiveWorkstreamId(db, workstream);\n if (wsId === null) return [];\n where.push(\"t.workstream_id = ?\");\n params.push(wsId);\n }\n if (statuses !== undefined) {\n where.push(`t.status IN (${statuses.map(() => \"?\").join(\", \")})`);\n params.push(...statuses);\n }\n const substates = asList(opts.substate);\n if (substates !== undefined && substates.length > 0) {\n where.push(`t.substate IN (${substates.map(() => \"?\").join(\", \")})`);\n params.push(...substates);\n }\n if (opts.ownerId !== undefined) {\n where.push(\"t.owner_id = ?\");\n params.push(opts.ownerId);\n }\n const sql =\n where.length === 0\n ? `SELECT ${SELECT_TASK_COLS} ${TASK_FROM_JOIN} ORDER BY t.local_id`\n : `SELECT ${SELECT_TASK_COLS} ${TASK_FROM_JOIN} WHERE ${where.join(\" AND \")} ORDER BY t.local_id`;\n const rows = db.prepare(sql).all(...params) as RawTaskRow[];\n return rows.map(rowFromDb);\n}\n\n// The three views (ready, blocked, goals) project tasks.* directly,\n// so they expose v5 columns (id, workstream_id, owner_id). We wrap\n// them with the same JOINs as TASK_FROM_JOIN to translate back to the\n// operator-facing TaskRow shape (workstream + owner as TEXT names).\nconst VIEW_FROM_JOIN = (view: string) => `\n FROM ${view} v\n JOIN workstreams ws ON ws.id = v.workstream_id AND ws.torn_down_at IS NULL\n LEFT JOIN agents ag ON ag.id = v.owner_id\n`;\nconst SELECT_VIEW_COLS = `\n v.id AS id,\n v.local_id AS local_id,\n v.workstream_id AS workstream_id,\n ws.name AS workstream,\n v.title AS title,\n v.status AS status,\n v.substate AS substate,\n v.impact AS impact,\n v.effort_days AS effort_days,\n v.scored AS scored,\n v.dispatch_host AS dispatch_host,\n v.kind AS kind,\n v.wave AS wave,\n v.owner_id AS owner_id,\n ag.name AS owner,\n v.created_at AS created_at,\n v.updated_at AS updated_at\n`;\n\n/** The `ready` view of one workstream: OPEN, not parked or triage, no open blocker. */\nexport function listReady(db: Db, workstream: string): TaskRow[] {\n const wsId = tryResolveLiveWorkstreamId(db, workstream);\n if (wsId === null) return [];\n // Same order as byRoiDesc (tasks/sort.ts): scored by impact/effort desc,\n // then the unscored oldest first; local_id breaks ties.\n const rows = db\n .prepare(\n `SELECT ${SELECT_VIEW_COLS} ${VIEW_FROM_JOIN(\"ready\")} WHERE v.workstream_id = ?\n ORDER BY v.scored DESC,\n CASE WHEN v.scored = 1 THEN v.impact / v.effort_days END DESC,\n CASE WHEN v.scored = 1 THEN v.effort_days END ASC,\n CASE WHEN v.scored = 0 THEN v.created_at END ASC,\n v.local_id`,\n )\n .all(wsId) as RawTaskRow[];\n return rows.map(rowFromDb);\n}\n\nexport function listBlocked(db: Db, workstream: string): TaskRow[] {\n const wsId = tryResolveLiveWorkstreamId(db, workstream);\n if (wsId === null) return [];\n const rows = db\n .prepare(\n `SELECT ${SELECT_VIEW_COLS} ${VIEW_FROM_JOIN(\"blocked\")} WHERE v.workstream_id = ? ORDER BY v.local_id`,\n )\n .all(wsId) as RawTaskRow[];\n return rows.map(rowFromDb);\n}\n\nexport function listGoals(db: Db, workstream: string): TaskRow[] {\n const wsId = tryResolveLiveWorkstreamId(db, workstream);\n if (wsId === null) return [];\n const rows = db\n .prepare(\n `SELECT ${SELECT_VIEW_COLS} ${VIEW_FROM_JOIN(\"goals\")} WHERE v.workstream_id = ? ORDER BY v.local_id`,\n )\n .all(wsId) as RawTaskRow[];\n return rows.map(rowFromDb);\n}\n\n/** All IN_PROGRESS tasks in a workstream, most-recently-touched first.\n * Used by `mu state` to populate its in-progress slice; exposed as a\n * named SDK helper so CLI renderers don't re-derive the row-shape\n * conversion. */\nexport function listInProgress(db: Db, workstream: string): TaskRow[] {\n const wsId = tryResolveLiveWorkstreamId(db, workstream);\n if (wsId === null) return [];\n const rows = db\n .prepare(\n `SELECT ${SELECT_TASK_COLS} ${TASK_FROM_JOIN} WHERE t.workstream_id = ? AND t.status = 'IN_PROGRESS' ORDER BY t.updated_at DESC`,\n )\n .all(wsId) as RawTaskRow[];\n return rows.map(rowFromDb);\n}\n\n/** CLOSED tasks in a workstream, most recently updated first, capped at\n * `limit` (default 5). `updated_at` is a proxy for close time: there is\n * no `closed_at` column, and a later note or edge change on a CLOSED\n * task bumps `updated_at` (touchTask), moving it up. Used by `mu state`\n * for its 'recent closed'\n * slice; exposed as a named SDK helper so the CLI no longer needs the\n * raw-row type that was duplicating RawTaskRow. */\nexport function listRecentClosed(db: Db, workstream: string, limit = 5): TaskRow[] {\n const wsId = tryResolveLiveWorkstreamId(db, workstream);\n if (wsId === null) return [];\n const rows = db\n .prepare(\n `SELECT ${SELECT_TASK_COLS} ${TASK_FROM_JOIN} WHERE t.workstream_id = ? AND t.status = 'CLOSED' ORDER BY t.updated_at DESC LIMIT ?`,\n )\n .all(wsId, limit) as RawTaskRow[];\n return rows.map(rowFromDb);\n}\n\n/** Optional filter knobs for `listNotes`. Default-everything-undefined\n * preserves the historical \"return every note, oldest-first\" shape so\n * every existing caller (cmdTaskShow's notes block, agents.test.ts)\n * keeps working unchanged.\n *\n * Filters compose multiplicatively when both apply (`since` AND\n * `tail`): the timestamp filter is applied first, then `tail` slices\n * the last N of what survived. The CLI surface (`mu task notes\n * --tail / --since / --since-claim`) lives in src/cli/tasks/edit.ts;\n * the mutex between `--since` and `--since-claim` is a CLI concern,\n * not enforced here — if both arrive at the SDK, `since` wins (it's\n * the explicit one) and `sinceClaim` is ignored. The auto-resolve\n * for `sinceClaim` (look up the most recent `task.claim` op in\n * the ops log) happens here so the SDK is self-contained for scripted\n * callers. */\nexport interface ListNotesOptions {\n /** Print only the last N notes (after any timestamp filter). Must\n * be a positive integer; a value of 0 returns no rows but is not\n * an error here — CLI-side validation rejects `--tail 0`. */\n tail?: number;\n /** ISO-8601 cutoff: only notes with `created_at > since` survive.\n * Any `Date.parse`-able value; it is normalised to `toISOString()`\n * form (the stored shape) before the text comparison, so offsets\n * and second-precision cutoffs compare as instants. */\n since?: string;\n /** When true and `since` is unset, look up the `created_at` of the\n * most recent `task claim` event for this task and use it as the\n * cutoff. Falls back to no filter when no claim event exists\n * (equivalent to `--since-beginning`). */\n sinceClaim?: boolean;\n}\n\n/** List notes for a task. Operator-facing local_id; resolves to the\n * surrogate task id via taskIdFor (with optional workstream scope).\n *\n * Optional filters: see {@link ListNotesOptions}. Default behaviour\n * (no opts) is unchanged — every note, oldest-first. */\nexport function listNotes(\n db: Db,\n taskLocalId: string,\n workstream: string,\n opts: ListNotesOptions = {},\n): TaskNoteRow[] {\n const taskId = taskIdFor(db, taskLocalId, workstream);\n if (taskId === null) return [];\n // Resolve the cutoff once: explicit `since` wins; otherwise\n // `sinceClaim` resolves via lastClaimEventAt (null → no filter).\n // created_at is always `toISOString()` (UTC, millis, `Z`) and the\n // filter compares text, so normalise `since` to that same shape: a\n // raw `10:07:00Z` sorts after `10:07:00.411Z` ('Z' > '.') and an\n // offset like `+02:00` compares as local time. An unparseable value\n // passes through unchanged (the CLI rejects it before here).\n let cutoff: string | undefined = opts.since;\n if (cutoff !== undefined) {\n const ms = Date.parse(cutoff);\n if (!Number.isNaN(ms)) cutoff = new Date(ms).toISOString();\n }\n if (cutoff === undefined && opts.sinceClaim === true) {\n const at = lastClaimEventAt(db, workstream, taskLocalId);\n if (at !== null) cutoff = at;\n }\n const rows =\n cutoff !== undefined\n ? (db\n .prepare(\n `SELECT ${SELECT_NOTE_COLS} FROM task_notes n JOIN tasks t ON t.id = n.task_id\n WHERE n.task_id = ? AND n.created_at > ? ORDER BY n.id`,\n )\n .all(taskId, cutoff) as RawTaskNoteRow[])\n : (db\n .prepare(\n `SELECT ${SELECT_NOTE_COLS} FROM task_notes n JOIN tasks t ON t.id = n.task_id\n WHERE n.task_id = ? ORDER BY n.id`,\n )\n .all(taskId) as RawTaskNoteRow[]);\n const mapped = rows.map(noteFromDb);\n if (opts.tail !== undefined && opts.tail >= 0) {\n return opts.tail === 0 ? [] : mapped.slice(-opts.tail);\n }\n return mapped;\n}\n\n/** What `selectTaskNotes` returns: the notes to show (oldest first, full\n * content), how many were left out, and which of them are pinned. */\nexport interface SelectedNotes {\n notes: TaskNoteRow[];\n /** Notes of the task not in `notes`. */\n more: number;\n /** All notes the task has. */\n total: number;\n /** `n` of every note that is content, never cut: the brief, the report (or\n * the closer's fallback) and the verdicts. Everything else is ordinary. */\n pinned: number[];\n}\n\n/** Ordinary notes the default view keeps after the report. */\nexport const ORDINARY_TAIL = 3;\n\n/**\n * The default notes view, chosen from metadata alone (no content is read for\n * a note that is not shown): the first `brief`, the last `report`, every\n * `verdict`, then the last {@link ORDINARY_TAIL} ordinary notes newer than the\n * report. With no `report` the closer's last `note` stands in for it: the\n * author of the last `close` note (NULL matches NULL), so late instructions\n * from anyone else stay ordinary. Decided at read time; nothing is rewritten.\n *\n * `all` or `from` return exactly the notes with `n >= from` (`all` is\n * `from: 1`), whole. A `from` that is not one of the task's notes throws\n * {@link TaskNoteRangeError}. Content is never cut here: the CLI byte cap is a\n * rendering concern.\n */\nexport function selectTaskNotes(\n db: Db,\n taskLocalId: string,\n opts: { workstream: string; all?: boolean; from?: number },\n): SelectedNotes {\n const taskId = taskIdFor(db, taskLocalId, opts.workstream);\n if (taskId === null) return { notes: [], more: 0, total: 0, pinned: [] };\n const meta = db\n .prepare(\"SELECT id, kind, author FROM task_notes WHERE task_id = ? ORDER BY id\")\n .all(taskId) as { id: number; kind: string; author: string | null }[];\n const total = meta.length;\n // `--all` is the whole-history read, not a lookup of note 1: an empty task\n // has none and that is an empty result. Only an explicit `from` is checked.\n if (\n opts.from !== undefined &&\n (!Number.isInteger(opts.from) || opts.from < 1 || opts.from > total)\n ) {\n throw new TaskNoteRangeError(taskLocalId, opts.from, total);\n }\n const from = opts.from ?? (opts.all === true ? 1 : undefined);\n\n const kindOf = (i: number): string => meta[i]?.kind ?? \"note\";\n const lastOf = (kind: string, pred: (i: number) => boolean = () => true): number => {\n for (let i = total - 1; i >= 0; i--) if (kindOf(i) === kind && pred(i)) return i;\n return -1;\n };\n const pinned = new Set<number>();\n const brief = meta.findIndex((m) => m.kind === \"brief\");\n if (brief >= 0) pinned.add(brief);\n for (let i = 0; i < total; i++) if (kindOf(i) === \"verdict\") pinned.add(i);\n let report = lastOf(\"report\");\n if (report < 0) {\n const close = lastOf(\"close\");\n if (close >= 0) {\n const closer = meta[close]?.author ?? null;\n report = lastOf(\"note\", (i) => (meta[i]?.author ?? null) === closer);\n }\n }\n if (report >= 0) pinned.add(report);\n\n const chosen = new Set<number>();\n if (from !== undefined) {\n for (let i = from - 1; i < total; i++) chosen.add(i);\n } else {\n for (const i of pinned) chosen.add(i);\n const ordinary: number[] = [];\n for (let i = report + 1; i < total; i++) if (!pinned.has(i)) ordinary.push(i);\n for (const i of ordinary.slice(-ORDINARY_TAIL)) chosen.add(i);\n }\n\n const order = [...chosen].sort((a, b) => a - b);\n const byId = new Map<number, RawTaskNoteRow>();\n const ids = order.map((i) => meta[i]?.id ?? -1);\n // One content read for the notes shown, in bounded chunks (SQLite's\n // variable limit), never for the ones left out.\n for (let at = 0; at < ids.length; at += 500) {\n const chunk = ids.slice(at, at + 500);\n const rows = db\n .prepare(\n `SELECT n.id AS id, n.kind AS kind, n.author AS author, n.content AS content, n.created_at AS created_at\n FROM task_notes n WHERE n.id IN (${chunk.map(() => \"?\").join(\",\")})`,\n )\n .all(...chunk) as (RawTaskNoteRow & { id: number })[];\n for (const r of rows) byId.set(r.id, r);\n }\n const notes: TaskNoteRow[] = [];\n for (const i of order) {\n const raw = byId.get(meta[i]?.id ?? -1);\n if (raw) notes.push(noteFromDb({ ...raw, ord: i + 1 }));\n }\n return {\n notes,\n more: total - notes.length,\n total,\n pinned: [...pinned].sort((a, b) => a - b).map((i) => i + 1),\n };\n}\n\n/** One whole note by its `n` (1..total of this task). Throws {@link TaskNoteRangeError} on a miss. */\nexport function getTaskNote(\n db: Db,\n taskLocalId: string,\n workstream: string,\n n: number,\n): TaskNoteRow {\n const taskId = taskIdFor(db, taskLocalId, workstream);\n const total =\n taskId === null\n ? 0\n : (\n db.prepare(\"SELECT COUNT(*) AS c FROM task_notes WHERE task_id = ?\").get(taskId) as {\n c: number;\n }\n ).c;\n if (taskId === null || !Number.isInteger(n) || n < 1 || n > total) {\n throw new TaskNoteRangeError(taskLocalId, n, total);\n }\n const raw = db\n .prepare(\n `SELECT n.kind AS kind, n.author AS author, n.content AS content, n.created_at AS created_at\n FROM task_notes n WHERE n.task_id = ? ORDER BY n.id LIMIT 1 OFFSET ?`,\n )\n .get(taskId, n - 1) as Omit<RawTaskNoteRow, \"ord\"> | undefined;\n if (!raw) throw new TaskNoteRangeError(taskLocalId, n, total);\n return noteFromDb({ ...raw, ord: n });\n}\n\n/**\n * All tasks currently owned by `agent` in a given workstream\n * (v5: agents.name is per-workstream unique). Sorted by local_id.\n *\n * Defaults to **excluding CLOSED** since the verb's purpose is \"what\n * is X currently working on?\" and a closed task is no longer being\n * worked on. closeTask intentionally preserves `owner` as a\n * historical record (so audit/notes can attribute decisions); pass\n * `{ includeClosed: true }` to surface that history.\n */\nexport function listTasksByOwner(\n db: Db,\n workstream: string,\n owner: string,\n opts: { includeClosed?: boolean } = {},\n): TaskRow[] {\n // 'Live work' = not CLOSED. includeClosed re-includes CLOSED tasks\n // so historical attribution is recoverable.\n // Filter on the joined ag.name so the operator-facing owner string\n // still drives the lookup; FK is now via owner_id.\n const filter = opts.includeClosed ? \"\" : \"AND t.status <> 'CLOSED'\";\n const wsId = tryResolveLiveWorkstreamId(db, workstream);\n if (wsId === null) return [];\n const sql = `SELECT ${SELECT_TASK_COLS} ${TASK_FROM_JOIN}\n WHERE ag.name = ? AND t.workstream_id = ? ${filter}\n ORDER BY t.local_id`;\n return (db.prepare(sql).all(owner, wsId) as RawTaskRow[]).map(rowFromDb);\n}\n\n/**\n * Cross-workstream variant of `listTasksByOwner`. Returns tasks owned\n * by ANY agent of the given name across every workstream. Used by\n * `mu task owned-by --all` for the genuine cross-workstream view\n * (audit / dashboards). The bare name is the join key, so two\n * distinct same-named agents in different workstreams contribute\n * their tasks to the same result list.\n */\nexport function listTasksByOwnerCrossWorkstream(\n db: Db,\n owner: string,\n opts: { includeClosed?: boolean } = {},\n): TaskRow[] {\n const filter = opts.includeClosed ? \"\" : \"AND t.status <> 'CLOSED'\";\n const sql = `SELECT ${SELECT_TASK_COLS} ${TASK_FROM_JOIN}\n WHERE ag.name = ? ${filter}\n ORDER BY ws.name, t.local_id`;\n return (db.prepare(sql).all(owner) as RawTaskRow[]).map(rowFromDb);\n}\n","// mu — task edge reads and mutations.\n\nimport type { Db } from \"../db.js\";\nimport { withOpContext } from \"../op-context.js\";\nimport { lookupTaskAnyWorkstream, taskIdFor, touchTask } from \"./core.js\";\nimport { CrossWorkstreamEdgeError, CycleError, TaskNotFoundError } from \"./errors.js\";\nimport { getTask } from \"./queries.js\";\nimport type { TaskStatus, TaskSubstate } from \"./status.js\";\n\nexport interface TaskEdges {\n /** Tasks that must close before this one can start (blockers). */\n blockers: string[];\n /** Tasks that this one blocks (dependents). */\n dependents: string[];\n}\n\nexport interface CanonicalBlocker {\n localId: string;\n id: number;\n}\n\nexport function dedupeBlockersById(blockers: readonly CanonicalBlocker[]): CanonicalBlocker[] {\n const seen = new Set<number>();\n const canonical: CanonicalBlocker[] = [];\n for (const blocker of blockers) {\n if (seen.has(blocker.id)) continue;\n seen.add(blocker.id);\n canonical.push(blocker);\n }\n return canonical;\n}\n\nfunction sameNumberSet(left: readonly number[], right: readonly number[]): boolean {\n if (left.length !== right.length) return false;\n const rightSet = new Set(right);\n if (rightSet.size !== right.length) return false;\n return left.every((value) => rightSet.has(value));\n}\n\n/** One end of an edge with the neighbour's current status attached.\n * Used by `mu task show` to group blockers/dependents into\n * \"still gating\" vs \"satisfied\" buckets without making the renderer\n * do a second round-trip to the DB per neighbour. */\nexport interface TaskEdgeWithStatus {\n name: string;\n status: TaskStatus;\n substate: TaskSubstate;\n}\n\nexport interface TaskEdgesWithStatus {\n /** Tasks that must close before this one can start (blockers),\n * carrying each blocker's current status. */\n blockers: TaskEdgeWithStatus[];\n /** Tasks that this one blocks (dependents), carrying each\n * dependent's current status. */\n dependents: TaskEdgeWithStatus[];\n}\n\n/**\n * Direct (one-hop) edges for a task. For transitive prerequisites, use\n * `getPrerequisites()`; this helper is the immediate-neighbour view used\n * by `mu task show`.\n */\nexport function getTaskEdges(db: Db, taskLocalId: string, workstream: string): TaskEdges {\n const taskId = taskIdFor(db, taskLocalId, workstream);\n if (taskId === null) return { blockers: [], dependents: [] };\n const blockers = (\n db\n .prepare(\n `SELECT t.local_id AS id FROM task_edges e\n JOIN tasks t ON t.id = e.from_task_id\n WHERE e.to_task_id = ? ORDER BY t.local_id`,\n )\n .all(taskId) as { id: string }[]\n ).map((r) => r.id);\n const dependents = (\n db\n .prepare(\n `SELECT t.local_id AS id FROM task_edges e\n JOIN tasks t ON t.id = e.to_task_id\n WHERE e.from_task_id = ? ORDER BY t.local_id`,\n )\n .all(taskId) as { id: string }[]\n ).map((r) => r.id);\n return { blockers, dependents };\n}\n\n/**\n * Same one-hop edge view as `getTaskEdges`, but each neighbour is\n * returned as `{ name, status }` so callers can group / colour by\n * status without an N+1 round-trip. Used by `mu task show` to split\n * \"blocked by\" (still-gating) from \"satisfied\" (already-CLOSED)\n * blockers, and the symmetric split on the dependents side\n * (task_show_blocked_by_renders_closed). OPEN and IN_PROGRESS stay in\n * the still-gating bucket; CLOSED is satisfied.\n */\nexport function getTaskEdgesWithStatus(\n db: Db,\n taskLocalId: string,\n workstream: string,\n): TaskEdgesWithStatus {\n const taskId = taskIdFor(db, taskLocalId, workstream);\n if (taskId === null) return { blockers: [], dependents: [] };\n const blockers = db\n .prepare(\n `SELECT t.local_id AS name, t.status AS status, t.substate AS substate FROM task_edges e\n JOIN tasks t ON t.id = e.from_task_id\n WHERE e.to_task_id = ? ORDER BY t.local_id`,\n )\n .all(taskId) as TaskEdgeWithStatus[];\n const dependents = db\n .prepare(\n `SELECT t.local_id AS name, t.status AS status, t.substate AS substate FROM task_edges e\n JOIN tasks t ON t.id = e.to_task_id\n WHERE e.from_task_id = ? ORDER BY t.local_id`,\n )\n .all(taskId) as TaskEdgeWithStatus[];\n return { blockers, dependents };\n}\n\n/**\n * All tasks transitively reachable from `taskId` via reverse-edge\n * traversal (i.e. the set of tasks that block this one), including the\n * task itself.\n */\nexport function getPrerequisites(db: Db, taskLocalId: string, workstream: string): Set<string> {\n const taskId = taskIdFor(db, taskLocalId, workstream);\n if (taskId === null) return new Set([taskLocalId]);\n // Walk reverse edges in surrogate-id space, then translate back to\n // local_id strings. The seed must be the surrogate id; the result\n // includes the seed task itself (callers like the tracks union-find\n // rely on the inclusive set).\n const rows = db\n .prepare(\n `WITH RECURSIVE reach(node) AS (\n SELECT ?\n UNION\n SELECT from_task_id FROM task_edges, reach WHERE to_task_id = reach.node\n )\n SELECT t.local_id AS local_id FROM reach r JOIN tasks t ON t.id = r.node`,\n )\n .all(taskId) as { local_id: string }[];\n return new Set(rows.map((r) => r.local_id));\n}\n\n/**\n * Adding edge `from -> to` creates a cycle iff there's already a path\n * `to -> ... -> from`. SQL recursive CTE expresses this exactly.\n */\nexport function wouldCreateCycle(db: Db, fromId: number, toId: number): boolean {\n if (fromId === toId) return true;\n const result = db\n .prepare(\n `WITH RECURSIVE forward(node) AS (\n SELECT ?\n UNION\n SELECT to_task_id FROM task_edges, forward WHERE from_task_id = forward.node\n )\n SELECT 1 AS hit FROM forward WHERE node = ? LIMIT 1`,\n )\n .get(toId, fromId) as { hit: number } | undefined;\n return result !== undefined;\n}\n\n/**\n * Shortest existing path `toId -> … -> fromId` (task local ids, both ends\n * included), i.e. what adding edge `fromId -> toId` would close into a\n * cycle. Null when there is none. Tracks visited nodes per path, so it\n * terminates even on cycles already present (e.g. created by sync).\n */\nexport function findCyclePath(db: Db, fromId: number, toId: number): string[] | null {\n if (fromId === toId) {\n const t = db.prepare(\"SELECT local_id FROM tasks WHERE id = ?\").get(fromId) as\n | { local_id: string }\n | undefined;\n return t ? [t.local_id] : null;\n }\n // BFS with parent pointers: linear in edges, shortest by construction,\n // and terminates on cycles already present (each node is visited once).\n // A per-path recursive CTE is exponential on wide DAGs.\n const next = db.prepare(\"SELECT to_task_id AS id FROM task_edges WHERE from_task_id = ?\");\n const parent = new Map<number, number>([[toId, toId]]);\n let frontier = [toId];\n while (frontier.length > 0 && !parent.has(fromId)) {\n const nextFrontier: number[] = [];\n for (const node of frontier) {\n for (const { id } of next.all(node) as { id: number }[]) {\n if (parent.has(id)) continue;\n parent.set(id, node);\n nextFrontier.push(id);\n }\n }\n frontier = nextFrontier;\n }\n if (!parent.has(fromId)) return null;\n const ids: number[] = [];\n for (let n = fromId; ; ) {\n ids.unshift(n);\n if (n === toId) break;\n const p = parent.get(n);\n if (p === undefined) return null;\n n = p;\n }\n const name = db.prepare(\"SELECT local_id FROM tasks WHERE id = ?\");\n return ids.map(\n (id) => (name.get(id) as { local_id: string } | undefined)?.local_id ?? String(id),\n );\n}\n\n/** Build a CycleError for edge `blocker -> blocked`, with the closing path. */\nexport function cycleErrorFor(\n db: Db,\n blocker: string,\n blocked: string,\n blockerId: number,\n blockedId: number,\n workstream?: string,\n): CycleError {\n return new CycleError(\n blocker,\n blocked,\n findCyclePath(db, blockerId, blockedId) ?? [],\n workstream,\n );\n}\n\nexport interface BlockEdgeResult {\n /** True iff a row was actually inserted (vs. already present). */\n added: boolean;\n}\n\n/**\n * Add the edge `blocker → blocked` ('blocker blocks blocked').\n * Idempotent (existing edge → `added: false`). Validates:\n *\n * - both tasks exist\n * - same workstream (cross-workstream edges forbidden)\n * - no cycle (the new edge wouldn't form a path blocked → ... → blocker)\n * - blocker ≠ blocked (no self-reference)\n */\nexport function addBlockEdge(\n db: Db,\n workstream: string,\n blocked: string,\n blocker: string,\n): BlockEdgeResult {\n return withOpContext(db, { intent: \"task.block\", group: \"new\" }, () =>\n addBlockEdgeImpl(db, workstream, blocked, blocker),\n );\n}\n\nfunction addBlockEdgeImpl(\n db: Db,\n workstream: string,\n blocked: string,\n blocker: string,\n): BlockEdgeResult {\n if (blocked === blocker) {\n // Surface as a typed CycleError so the CLI maps it to exit 4 (conflict)\n // rather than letting the schema CHECK fire as a generic SQL error.\n throw new CycleError(blocker, blocked);\n }\n const blockedRow = getTask(db, blocked, workstream);\n if (!blockedRow) throw new TaskNotFoundError(blocked, workstream);\n // Resolve the blocker in the dependent's workstream first, then\n // globally so a cross-workstream blocker surfaces\n // CrossWorkstreamEdgeError (clearer than TaskNotFoundError). Cycle\n // check + same-workstream guard run after.\n const blockerRow = lookupTaskAnyWorkstream(db, blocker, blockedRow.workstreamName);\n if (!blockerRow) throw new TaskNotFoundError(blocker, blockedRow.workstreamName);\n if (blockedRow.workstreamName !== blockerRow.workstreamName) {\n throw new CrossWorkstreamEdgeError(\n blocker,\n blockerRow.workstreamName,\n blocked,\n blockedRow.workstreamName,\n );\n }\n const blockedId = taskIdFor(db, blocked, blockedRow.workstreamName);\n const blockerId = taskIdFor(db, blocker, blockerRow.workstreamName);\n if (blockedId === null || blockerId === null) throw new TaskNotFoundError(blocked);\n if (wouldCreateCycle(db, blockerId, blockedId)) {\n throw cycleErrorFor(db, blocker, blocked, blockerId, blockedId, blockedRow.workstreamName);\n }\n const now = new Date().toISOString();\n const added = db\n .transaction(() => {\n const result = db\n .prepare(\n \"INSERT INTO task_edges (from_task_id, to_task_id, created_at) SELECT ?, ?, ? \" +\n \"WHERE NOT EXISTS (SELECT 1 FROM task_edges WHERE from_task_id = ? AND to_task_id = ?)\",\n )\n .run(blockerId, blockedId, now, blockerId, blockedId);\n if (result.changes > 0) {\n // Bump the BLOCKED task — its blocker set changed. The blocker\n // itself is unaffected. Aligned with reparentTask, which also\n // bumps the FROM_TASK side (the task whose blockers shifted).\n touchTask(db, blockedId, now);\n return true;\n }\n return false;\n })\n .immediate();\n // No emitEvent: the task_edges INSERT fired the capture trigger\n // (intent='task.block', key='<ws>/<blocker>-><ws>/<blocked>').\n return { added };\n}\n\nexport interface RemoveBlockEdgeResult {\n /** True iff a row was actually deleted (vs. no such edge). */\n removed: boolean;\n}\n\n/**\n * Remove the edge `blocker → blocked`. Idempotent (no edge →\n * `removed: false`). Does NOT validate task existence — if the\n * edge is gone there's nothing to do, regardless of whether the\n * tasks are gone too.\n */\nexport function removeBlockEdge(\n db: Db,\n workstream: string,\n blocked: string,\n blocker: string,\n): RemoveBlockEdgeResult {\n return withOpContext(db, { intent: \"task.unblock\", group: \"new\" }, () =>\n removeBlockEdgeImpl(db, workstream, blocked, blocker),\n );\n}\n\nfunction removeBlockEdgeImpl(\n db: Db,\n workstream: string,\n blocked: string,\n blocker: string,\n): RemoveBlockEdgeResult {\n const blockedRow = getTask(db, blocked, workstream);\n if (!blockedRow) return { removed: false };\n const blockerRow = getTask(db, blocker, workstream);\n if (!blockerRow) return { removed: false };\n const blockedId = taskIdFor(db, blocked, blockedRow.workstreamName);\n const blockerId = taskIdFor(db, blocker, blockerRow.workstreamName);\n if (blockedId === null || blockerId === null) return { removed: false };\n const removed = db\n .transaction(() => {\n const result = db\n .prepare(\"DELETE FROM task_edges WHERE from_task_id = ? AND to_task_id = ?\")\n .run(blockerId, blockedId);\n if (result.changes > 0) {\n // Bump the BLOCKED task — its blocker set just shrank.\n touchTask(db, blockedId);\n return true;\n }\n return false;\n })\n .immediate();\n if (removed) {\n // No emitEvent: the DELETE fired the capture trigger, writing an\n // edge tombstone with intent='task.unblock'.\n }\n return { removed };\n}\n\nexport interface ReparentTaskResult {\n /** Edges removed (i.e. all incoming `to_task = taskId` edges). */\n removedEdges: number;\n /** Edges added (after duplicate blockers are canonicalised). */\n addedEdges: number;\n}\n\n/**\n * Atomically replace every incoming edge of `taskId` with new ones\n * `blocker[i] → taskId`. Pass an empty `blockers` array to clear all\n * incoming edges (the task becomes ready iff its status allows).\n *\n * Validates ALL new blockers up-front (existence + same workstream +\n * cycle check); if any fails, no DELETE happens — the call is fully\n * atomic via a single transaction.\n *\n * Cycle reasoning: removing the existing incoming edges to `taskId`\n * doesn't change `taskId`'s OUTGOING reachability, so\n * `wouldCreateCycle(db, blocker, taskId)` evaluated against the\n * pre-state gives the right answer for each new edge.\n */\nexport function reparentTask(\n db: Db,\n taskLocalId: string,\n blockers: readonly string[],\n scope: { workstream: string },\n): ReparentTaskResult {\n // One group for the whole reparent: it DELETEs the old blocker edges\n // and INSERTs the new ones, which is one operator action,\n // so it shares one op group.\n return withOpContext(db, { intent: \"task.reparent\", group: \"new\" }, () =>\n reparentTaskImpl(db, taskLocalId, blockers, scope),\n );\n}\n\nfunction reparentTaskImpl(\n db: Db,\n taskLocalId: string,\n blockers: readonly string[],\n scope: { workstream: string },\n): ReparentTaskResult {\n const task = getTask(db, taskLocalId, scope.workstream);\n if (!task) throw new TaskNotFoundError(taskLocalId, scope.workstream);\n const taskSurrogateId = taskIdFor(db, task.name, task.workstreamName);\n if (taskSurrogateId === null) throw new TaskNotFoundError(taskLocalId);\n\n // Resolve every blocker up-front to its surrogate id; do all\n // existence + same-workstream + cycle checks before any DELETE.\n // Look up blockers in the task's workstream first, then across all\n // workstreams so a blocker that exists only in a DIFFERENT workstream surfaces CrossWorkstreamEdgeError (clearer\n // than TaskNotFoundError). Duplicate blockers are an ergonomic input\n // accident from repeat/CSV forms, so silently canonicalise by\n // surrogate id while preserving first-seen order.\n const requestedBlockers: CanonicalBlocker[] = [];\n for (const blockerLocalId of blockers) {\n if (blockerLocalId === taskLocalId) {\n throw new CycleError(blockerLocalId, taskLocalId);\n }\n const blocker = lookupTaskAnyWorkstream(db, blockerLocalId, task.workstreamName);\n if (!blocker) throw new TaskNotFoundError(blockerLocalId, task.workstreamName);\n if (blocker.workstreamName !== task.workstreamName) {\n throw new CrossWorkstreamEdgeError(\n blockerLocalId,\n blocker.workstreamName,\n taskLocalId,\n task.workstreamName,\n );\n }\n const blockerId = taskIdFor(db, blocker.name, blocker.workstreamName);\n if (blockerId === null) throw new TaskNotFoundError(blockerLocalId);\n if (wouldCreateCycle(db, blockerId, taskSurrogateId)) {\n throw cycleErrorFor(\n db,\n blockerLocalId,\n taskLocalId,\n blockerId,\n taskSurrogateId,\n task.workstreamName,\n );\n }\n requestedBlockers.push({ localId: blockerLocalId, id: blockerId });\n }\n const canonicalBlockers = dedupeBlockersById(requestedBlockers);\n const blockerIds = canonicalBlockers.map((blocker) => blocker.id);\n const currentBlockerIds = (\n db\n .prepare(\"SELECT from_task_id AS id FROM task_edges WHERE to_task_id = ?\")\n .all(taskSurrogateId) as { id: number }[]\n ).map((row) => row.id);\n\n if (sameNumberSet(currentBlockerIds, blockerIds)) {\n return { removedEdges: 0, addedEdges: 0 };\n }\n\n return db\n .transaction(() => {\n const removed = db\n .prepare(\"DELETE FROM task_edges WHERE to_task_id = ?\")\n .run(taskSurrogateId);\n const insertEdge = db.prepare(\n \"INSERT INTO task_edges (from_task_id, to_task_id, created_at) VALUES (?, ?, ?)\",\n );\n const now = new Date().toISOString();\n for (const blockerId of blockerIds) {\n insertEdge.run(blockerId, taskSurrogateId, now);\n }\n // Bump the reparented task itself — its blocker set just changed.\n touchTask(db, taskSurrogateId, now);\n // No emitEvent: every edge DELETE and INSERT in this transaction\n // fired the capture trigger under intent='task.reparent'.\n return { removedEdges: removed.changes, addedEdges: blockerIds.length };\n })\n .immediate();\n}\n\nexport interface EdgeCycle {\n workstream: string;\n /** Local ids around the cycle, `a -> b -> … -> a` (first id not repeated). */\n path: string[];\n /** Local ids of an edge on it: `blocker` blocks `blocked`. Removing it breaks this cycle. */\n blocker: string;\n blocked: string;\n}\n\n/**\n * Cycles already present in task_edges. addBlockEdge refuses to make one,\n * but sync can merge two locally valid edges into one (apply never\n * rejects a peer's edge). Members block each other until one closes.\n * Returns one cycle per suggested fix; applying every fix together\n * leaves the graph acyclic.\n */\nexport function findEdgeCycles(db: Db): EdgeCycle[] {\n const rows = db\n .prepare(\n `SELECT e.from_task_id AS f, e.to_task_id AS t, w.name AS ws\n FROM task_edges e\n JOIN tasks a ON a.id = e.from_task_id\n JOIN workstreams w ON w.id = a.workstream_id\n ORDER BY w.name, e.from_task_id, e.to_task_id`,\n )\n .all() as { f: number; t: number; ws: string }[];\n // Peel nodes with no in-edges or no out-edges until stable: what is\n // left lies on, or between, cycles.\n let live = rows;\n for (;;) {\n const ins = new Set(live.map((r) => r.t));\n const outs = new Set(live.map((r) => r.f));\n const kept = live.filter((r) => ins.has(r.f) && outs.has(r.t));\n if (kept.length === live.length) break;\n live = kept;\n }\n const name = db.prepare(\"SELECT local_id FROM tasks WHERE id = ?\");\n const local = (id: number): string =>\n (name.get(id) as { local_id: string } | undefined)?.local_id ?? String(id);\n // Break cycles on an in-memory copy: find one, report it with its\n // closing edge, drop that edge, repeat. Applying every reported fix\n // therefore leaves the graph acyclic (a graph can hold exponentially\n // many cycles, so \"every cycle\" is not the contract; \"every fix\n // together breaks them all\" is). Each round is a BFS, at most one\n // round per edge.\n const out = new Map<number, Set<number>>();\n for (const r of live) {\n const set = out.get(r.f) ?? new Set<number>();\n set.add(r.t);\n out.set(r.f, set);\n }\n const wsOf = new Map(live.map((r) => [r.f, r.ws] as const));\n const shortestPath = (from: number, to: number): number[] | null => {\n const parent = new Map<number, number>([[from, from]]);\n let frontier = [from];\n while (frontier.length > 0 && !parent.has(to)) {\n const next: number[] = [];\n for (const n of frontier)\n for (const m of out.get(n) ?? []) {\n if (parent.has(m)) continue;\n parent.set(m, n);\n next.push(m);\n }\n frontier = next;\n }\n if (!parent.has(to)) return null;\n const ids: number[] = [];\n for (let n = to; ; ) {\n ids.unshift(n);\n if (n === from) return ids;\n const p = parent.get(n);\n if (p === undefined) return null;\n n = p;\n }\n };\n const cycles: EdgeCycle[] = [];\n for (const r of live) {\n for (;;) {\n if (!out.get(r.f)?.has(r.t)) break;\n const back = shortestPath(r.t, r.f); // r.t -> … -> r.f closes via r.f -> r.t\n if (back === null) break;\n cycles.push({\n workstream: wsOf.get(r.f) ?? r.ws,\n path: [r.f, ...back.slice(0, -1)].map(local),\n blocker: local(r.f),\n blocked: local(r.t),\n });\n out.get(r.f)?.delete(r.t);\n }\n }\n return cycles;\n}\n","// mu — workstream-level operations.\n//\n// One workstream = one mux session + N agents + M tasks (and their\n// edges/notes) all sharing the workstream column. This module holds the\n// workstream-level operations: ensure / list / summarize / teardown / reinit\n// (`mu workstream init`, `list`, `teardown`).\n//\n// `teardownWorkstream` is SOFT and needs a preview revision (`--if <rev>`):\n// it kills the session, deletes the\n// machine-local agent rows and sets `workstreams.torn_down_at`. Tasks,\n// edges and notes stay. It is idempotent on every leg:\n// - mux session already gone → nothing to kill\n// - no agents for this name → nothing to delete\n// - workstream never existed at all → returns all-zero counts\n//\n// Both summarize and teardown take an optional `muxSession` override so\n// tests (and the rare workstream whose mux session was created with a\n// non-default name) work without env-var gymnastics.\n\nimport { readdirSync, rmdirSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { crc32 } from \"node:zlib\";\nimport { reapAgentRow } from \"./agents/reap.js\";\nimport { WORKSTREAM_OPS_WHERE } from \"./compact.js\";\nimport { unlinkCtlSocket } from \"./ctl/path.js\";\nimport { type Db, tornDownAtOf } from \"./db.js\";\nimport { say } from \"./messages.js\";\nimport { activeMux } from \"./mux.js\";\nimport { withOpContext } from \"./op-context.js\";\nimport { listWorktrees } from \"./worktree.js\";\n\n/**\n * Allowed workstream-name shape: lowercase alpha first, then alnum,\n * underscore, or hyphen, up to 32 chars total. Mirrors the agent-name\n * rule in docs/reference/naming.md.\n *\n * Critically, this rule excludes `.` and `:` — tmux silently rewrites\n * `.` to `_` in session names (because `.` is the window/pane separator\n * in tmux's `session:window.pane` target syntax) and `:` is reserved\n * outright. A workstream name with `.` would create a session that mu\n * couldn't subsequently look up, breaking every downstream verb. We\n * fail loud at init time instead.\n */\nconst WORKSTREAM_NAME_RE = /^[a-z][a-z0-9_-]{0,31}$/;\n\n/** Reserved prefix — mu auto-prepends `mu-` to derive the tmux session\n * name (so workstream `auth` lives in tmux session `mu-auth`). A\n * workstream named `mu-auth` would produce session `mu-mu-auth`,\n * which the user almost certainly didn't intend. Fail loud rather\n * than silently double-prefix. */\nexport const RESERVED_WORKSTREAM_PREFIX = \"mu-\";\n\n/** Reserved workstream names that may only be auto-created on spawn,\n * never via `mu workstream init`. `scratch` is the off-the-cuff bucket\n * for ad-hoc agents you'll keep talking to without crew/DAG ceremony;\n * it auto-creates on first `mu agent spawn <name> -w scratch` (via\n * `ensureWorkstream`, which stays permissive) but `init` is rejected\n * loud so the operator doesn't treat it as a durable crew workstream.\n * See docs/VOCABULARY.md \"scratch workstream\". */\nexport const RESERVED_WORKSTREAM_NAMES = new Set([\"scratch\"]);\n\n// ─── Best-effort mux reads ─────────────────────────────────────────\n//\n// Every workstream READ decorates DB truth with mux liveness. The DB\n// half always works, so an unreachable mux must degrade the decoration\n// (\"no sessions\", \"not alive\") rather than fail `mu workstream list`\n// on a box where nobody is running a multiplexer right now.\n\n/** True iff the mux reports panes in `session` (a live session always\n * holds its `_mu` pane, and both backends drop a session with its last\n * pane). Best-effort: an unreachable mux reads as \"not alive\". */\nasync function sessionAlive(session: string): Promise<boolean> {\n try {\n return (await (await activeMux()).listPanes(session)).length > 0;\n } catch {\n return false;\n }\n}\n\n/** True iff `name` is a scratch/ephemeral workstream (special-cased by\n * the staleness nudge, the TUI ephemeral marker, the kept-alive\n * session on spawn, and the `teardown --empty` exemption). */\nexport function isScratchWorkstream(name: string): boolean {\n return RESERVED_WORKSTREAM_NAMES.has(name);\n}\n\n/**\n * The workstream implied by the mux session the caller sits in, or\n * null. Best-effort: this is one rung of the -w resolution ladder, so\n * an unreachable mux means \"no ambient answer\", never a thrown verb.\n */\nexport async function resolveMuxSessionWorkstreamName(): Promise<string | null> {\n try {\n const name = await (await activeMux()).currentSessionName();\n if (name?.startsWith(RESERVED_WORKSTREAM_PREFIX)) {\n return name.slice(RESERVED_WORKSTREAM_PREFIX.length);\n }\n } catch {\n // fall through: mux context is best-effort for workstream resolution\n }\n return null;\n}\n\nexport function isValidWorkstreamName(name: string): boolean {\n if (!WORKSTREAM_NAME_RE.test(name)) return false;\n if (name.startsWith(RESERVED_WORKSTREAM_PREFIX)) return false;\n return true;\n}\n\n/** A workstream name collision. Exported SDK error class mapped to exit\n * 4 (conflict) by `classifyError`; no mu verb throws it today\n * (`ensureWorkstream` is idempotent). Invalid names throw\n * `WorkstreamNameInvalidError`. */\nexport class WorkstreamExistsError extends Error {\n override readonly name: string = \"WorkstreamExistsError\";\n constructor(public readonly workstream: string) {\n super(say(\"workstream.exists\", workstream));\n }\n}\n\nexport class WorkstreamNameInvalidError extends Error {\n override readonly name = \"WorkstreamNameInvalidError\";\n constructor(public readonly attempted: string) {\n super(\n say(\"workstream.name_invalid\", attempted, attempted.startsWith(RESERVED_WORKSTREAM_PREFIX)),\n );\n }\n}\n\nfunction assertValidWorkstreamName(name: string): void {\n if (!isValidWorkstreamName(name)) throw new WorkstreamNameInvalidError(name);\n}\n\n/** Thrown by `mu workstream init` when the operator tries to create a\n * reserved workstream (e.g. `scratch`) explicitly. The name is not\n * invalid — it auto-creates on spawn — it just can't be `init`ed. */\nexport class WorkstreamNameReservedError extends Error {\n override readonly name = \"WorkstreamNameReservedError\";\n constructor(public readonly attempted: string) {\n super(say(\"workstream.name_reserved\", attempted));\n }\n}\n\n/** A destructive verb was given a preview revision that no longer matches:\n * the workstream (its ops, agents or worktrees) changed since the preview.\n * Exit 4, nothing was done. One stderr line: the message names the\n * preview command. */\nexport class WorkstreamRevisionMismatchError extends Error {\n override readonly name = \"WorkstreamRevisionMismatchError\";\n constructor(\n public readonly workstream: string,\n public readonly expected: number,\n public readonly actual: number,\n /** The command that previews again. */\n public readonly previewCommand: string = `mu workstream teardown ${workstream}`,\n ) {\n super(say(\"workstream.changed\", workstream, expected, actual, previewCommand));\n }\n}\n\n/** `workstream init --if` over a torn-down name would hard-delete rows\n * while this machine still has agent rows (so possibly live panes) in it.\n * A peer's teardown can reach a machine that still runs its agents. Exit 4. */\nexport class WorkstreamHasAgentsError extends Error {\n override readonly name = \"WorkstreamHasAgentsError\";\n constructor(\n public readonly workstream: string,\n public readonly agents: readonly string[],\n ) {\n super(say(\"workstream.has_agents\", workstream, agents));\n }\n}\n\n/** A teardown found registered panes still alive outside its session\n * (moved by hand): killing the session would not stop them, and deleting\n * their rows would orphan them. Exit 4, nothing was done. */\nexport class WorkstreamPanesLiveError extends Error {\n override readonly name = \"WorkstreamPanesLiveError\";\n constructor(\n public readonly workstream: string,\n public readonly agents: readonly string[],\n ) {\n super(say(\"workstream.panes_live\", workstream, agents));\n }\n}\n\n/** `workstream init --if` over a torn-down name found its mux session still\n * alive: the old rows are not deleted while panes may run. Exit 4. */\nexport class WorkstreamSessionLiveError extends Error {\n override readonly name = \"WorkstreamSessionLiveError\";\n constructor(\n public readonly workstream: string,\n public readonly session: string,\n ) {\n super(say(\"workstream.session_live\", workstream, session));\n }\n}\n\n/** Reject reserved names for the explicit `mu workstream init` path.\n * `ensureWorkstream` (the auto-create-on-spawn path) deliberately does\n * NOT call this — spawning into `scratch` must Just Work. A torn-down\n * `scratch` is the exception: init is how the name comes back (a spawn\n * into it is refused until then). */\nexport function assertWorkstreamInitable(name: string, db?: Db): void {\n if (!RESERVED_WORKSTREAM_NAMES.has(name)) return;\n if (db !== undefined && tornDownAtOf(db, name) !== null) return;\n throw new WorkstreamNameReservedError(name);\n}\n\n// ─── Revision ──────────────────────────────────────────────────────────\n\n/**\n * The preview **revision** of a workstream: a number that changes whenever\n * anything a destructive verb would act on changes. It hashes the newest\n * op touching the workstream's keys (0 if none), and the machine-local\n * state ops cannot see: agent names + pane ids and registered worktree\n * paths. An agent spawned after the preview therefore invalidates `--if`.\n * Read only: safe for a preview.\n */\nexport function workstreamRevision(db: Db, name: string): number {\n const maxSeq = (\n db\n .prepare(`SELECT COALESCE(MAX(seq), 0) AS n FROM ops WHERE ${WORKSTREAM_OPS_WHERE}`)\n .get({ ws: name }) as { n: number }\n ).n;\n const agents = listAgentPanes(db, name).map((a) => `${a.name}@${a.paneId}`);\n const worktrees = listWorktrees(db, name)\n .map((w) => w.path)\n .sort();\n return crc32(`${maxSeq}\\n${agents.join(\",\")}\\n${worktrees.join(\",\")}`);\n}\n\n/** The revision of a sweep, from its members' revisions (name → revision):\n * a member added, removed or changed since the preview changes it. */\nexport function sweepRevision(members: ReadonlyMap<string, number>): number {\n const parts = [...members]\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([n, r]) => `${n}:${r}`);\n return crc32(parts.join(\"\\n\"));\n}\n\n/**\n * Ensure a row exists in the `workstreams` table for `name`. Idempotent;\n * INSERT OR IGNORE so concurrent callers race safely. Called by\n * `insertAgent` and `addTask` so callers don't need to remember to call\n * `mu workstream init` before adding a task / spawning an agent (preserves the\n * spawn-without-init ergonomics now that agents.workstream and\n * tasks.workstream are real FKs into this table).\n *\n * Validates the name before inserting; throws `WorkstreamNameInvalidError`\n * for names tmux would silently mangle (containing '.' or ':') or that\n * exceed 32 chars / start with a non-letter.\n *\n * Returns true iff a row was actually inserted (vs. already present).\n */\nexport function ensureWorkstream(db: Db, name: string): boolean {\n assertValidWorkstreamName(name);\n return withOpContext(db, { intent: \"workstream.init\", group: \"new\" }, () =>\n ensureWorkstreamImpl(db, name),\n );\n}\n\nfunction ensureWorkstreamImpl(db: Db, name: string): boolean {\n const result = db\n .prepare(\n \"INSERT INTO workstreams (name, created_at) SELECT ?, ? WHERE NOT EXISTS (SELECT 1 FROM workstreams WHERE name = ?)\",\n )\n .run(name, new Date().toISOString(), name);\n const created = result.changes > 0;\n // No emitEvent: the workstreams INSERT fired the capture trigger\n // (intent='workstream.init', key=<name>).\n return created;\n}\n\nexport interface WorkstreamSummary {\n /** The workstream's own name. */\n name: string;\n /** Mux session name, defaults to `mu-<name>`. */\n muxSession: string;\n /** True iff the mux session `<muxSession>` is alive right now. */\n muxAlive: boolean;\n /** Rows in `agents` for this workstream. */\n agentCount: number;\n /** Rows in `tasks` for this workstream. */\n taskCount: number;\n /** Rows in `task_notes` whose task is in this workstream. */\n noteCount: number;\n /** Rows in `task_edges` whose `from_task` is in this workstream. */\n edgeCount: number;\n /** Registered worktrees (`worktrees` rows) of this workstream. Surfaced so\n * the teardown dry-run can warn about per-agent worktrees that need\n * cleanup. */\n worktreeCount: number;\n /** True iff a row exists in the `workstreams` table itself. False\n * for tmux-only `mu-*` sessions that mu never observed via\n * `mu workstream init`. Surfaced so teardown can clean up bare\n * registry rows (workstream row exists, no agents/tasks/etc.) —\n * otherwise such rows are orphaned forever (the previous\n * `nothingToDo` heuristic short-circuited on them). */\n registered: boolean;\n}\n\nexport interface TeardownResult {\n /** True iff killing the mux session actually killed something. */\n killedMux: boolean;\n /** Number of machine-local `agents` rows deleted (their panes are gone). */\n deletedAgents: number;\n /** Rows KEPT because their recorded pane was alive (or could not be asked)\n * after the kill: orphaned, in a torn-down workstream.\n * `mu agent close <name> -w <ws>` removes one. */\n orphanedAgents: { name: string; paneId: string; reason: \"alive\" | \"unknown\" }[];\n /** Rows that STAY (the teardown is soft): tasks, and their notes and\n * edges. Reported so the output says what a later `init --if` would\n * hard-delete. */\n tasks: number;\n notes: number;\n edges: number;\n /** Worktrees left alone: teardown never removes one. Their registry rows\n * stay; `mu agent close <agent> -w <ws>` applies the close rule to one. */\n keptWorktrees: { agent: string; path: string }[];\n}\n\nexport interface WorkstreamOptions {\n workstream: string;\n /** Override the mux session name. Defaults to `mu-<workstream>`. */\n muxSession?: string;\n}\n\nexport interface TeardownWorkstreamOptions extends WorkstreamOptions {\n /** The preview revision (`workstreamRevision`). Required: the guarantee\n * is code, not a CLI convention. A mismatch throws\n * `WorkstreamRevisionMismatchError` before anything is touched. */\n ifRevision: number;\n}\n\n/** One past **teardown**, reconstructed from the ops log. */\nexport interface TornDownWorkstream {\n /** The workstream's name. Not unique across the list: a name can be\n * torn down, recreated and torn down again, and each is its own\n * entry (the group id is the identity). */\n name: string;\n /** The teardown's op group (`mu log --group <group>`). */\n group: string;\n /** ISO timestamp of the teardown. */\n at: string;\n /** Rows the teardown removed, so the entry conveys what is at stake\n * without a second query per row. */\n tasks: number;\n notes: number;\n edges: number;\n /** True when a LATER put recreated this workstream, i.e. the\n * name was reused. Kept in the list rather than filtered out:\n * silently hiding it would make the list disagree with `mu log`. */\n recreated: boolean;\n /** `soft`: the row is still here with `torn_down_at` set (its rows stay;\n * counts are what is kept). `hard`: a pre-cut-over teardown found in the\n * log (its rows were deleted; counts are what it removed). */\n kind: \"soft\" | \"hard\";\n}\n\n/**\n * Every **teardown**, newest first: the soft ones (rows with\n * `torn_down_at` set, the current kind) and, from history, the hard ones\n * a pre-cut-over build wrote (a `workstream` del op, intent\n * `workstream.teardown`: old teardowns stay final).\n *\n * The list exists so a teardown from last month is reachable (its op\n * group id feeds `mu log --group`) without hand-written SQL over `ops`.\n * Hard entries are read straight from the log rather than from a side\n * table: the log already holds them, and a projection would be one more\n * thing that can disagree with it.\n */\nexport function listTornDownWorkstreams(db: Db): TornDownWorkstream[] {\n const soft = (\n db\n .prepare(\n `SELECT w.name AS name, w.torn_down_at AS at,\n COALESCE((SELECT o.group_id FROM ops o\n WHERE o.entity = 'workstream' AND o.key = w.name AND o.op = 'put'\n AND o.intent = 'workstream.teardown'\n ORDER BY o.hlc DESC LIMIT 1), '') AS \"group\"\n FROM workstreams w\n WHERE w.torn_down_at IS NOT NULL`,\n )\n .all() as { name: string; at: string; group: string }[]\n ).map(\n (r): TornDownWorkstream => ({\n name: r.name,\n group: r.group,\n at: r.at,\n tasks: countTasks(db, r.name),\n notes: countNotes(db, r.name),\n edges: countEdges(db, r.name),\n recreated: false,\n kind: \"soft\",\n }),\n );\n const hard = db\n .prepare(\n `SELECT o.key AS name,\n o.group_id AS \"group\",\n o.created_at AS at,\n (SELECT COUNT(*) FROM ops t\n WHERE t.group_id = o.group_id AND t.entity = 'task' AND t.op = 'del') AS tasks,\n (SELECT COUNT(*) FROM ops n\n WHERE n.group_id = o.group_id AND n.entity = 'note' AND n.op = 'del') AS notes,\n (SELECT COUNT(*) FROM ops e\n WHERE e.group_id = o.group_id AND e.entity = 'edge' AND e.op = 'del') AS edges,\n EXISTS (SELECT 1 FROM ops p\n WHERE p.entity = 'workstream' AND p.key = o.key\n AND p.op = 'put' AND p.hlc > o.hlc) AS recreated\n FROM ops o\n WHERE o.entity = 'workstream'\n AND o.op = 'del'\n AND o.intent = 'workstream.teardown'`,\n )\n .all()\n .map((r): TornDownWorkstream => {\n const row = r as Omit<TornDownWorkstream, \"recreated\" | \"kind\"> & { recreated: number };\n return { ...row, recreated: row.recreated === 1, kind: \"hard\" };\n });\n return [...soft, ...hard].sort((a, b) => (a.at < b.at ? 1 : a.at > b.at ? -1 : 0));\n}\n\n/**\n * Discover every registered workstream: the rows in the `workstreams`\n * table (canonical DB source; populated by `mu workstream init` and auto-created by\n * insertAgent / addTask), each decorated with mux liveness. A `mu-*` mux\n * session with no row is not discovered: the DB owns the workstream list.\n *\n * Returns one `WorkstreamSummary` per workstream, sorted by name.\n */\nexport async function listWorkstreams(db: Db): Promise<WorkstreamSummary[]> {\n const names = (\n db.prepare(\"SELECT name FROM workstreams WHERE torn_down_at IS NULL ORDER BY name\").all() as {\n name: string;\n }[]\n ).map((r) => r.name);\n return Promise.all(names.map((name) => summarize(db, { workstream: name })));\n}\n\n/**\n * Discover every REGISTERED workstream that has no user-meaningful\n * state attached: a row in `workstreams` with zero tasks, zero\n * agents, zero worktrees. Mux session presence and ops-log\n * entries do NOT disqualify — the session itself was created at\n * init time and contains no agent panes; the events are audit, not\n * state.\n *\n * Unregistered `mu-*` mux sessions (no `workstreams` row) are never\n * seen: the sweep iterates DB rows only. \"No DB row\" only means THIS\n * DB does not know the session: a run against a throwaway `MU_DB_PATH`\n * sees every real workstream as unregistered, and sweeping them killed\n * a live crew's agent panes. An explicit\n * `mu workstream teardown <name>` still tears one down by name.\n *\n * The `scratch` workstream is NEVER returned: its idle session is kept\n * alive on purpose (see mux.ensureSession), so the next delegate\n * does not pay for creating it. `mu workstream teardown scratch`\n * still tears it down.\n *\n * Used by `mu workstream teardown --empty` to sweep empty\n * workstreams in one command (instead of the per-name jq incantation\n * over `mu workstream list --json`). Returns one `WorkstreamSummary`\n * per match, sorted by name.\n */\nexport async function listEmptyWorkstreams(db: Db): Promise<WorkstreamSummary[]> {\n const registeredRows = db\n .prepare(\n `SELECT ws.name AS name\n FROM workstreams ws\n LEFT JOIN tasks t ON t.workstream_id = ws.id\n LEFT JOIN agents a ON a.workstream_id = ws.id\n LEFT JOIN worktrees v ON v.workstream = ws.name\n WHERE ws.torn_down_at IS NULL\n GROUP BY ws.id, ws.name\n HAVING COUNT(DISTINCT t.id) = 0\n AND COUNT(DISTINCT a.id) = 0\n AND COUNT(DISTINCT v.path) = 0\n ORDER BY ws.name`,\n )\n .all() as { name: string }[];\n return Promise.all(\n registeredRows\n .filter((r) => !isScratchWorkstream(r.name))\n .map((r) => summarizeWorkstream(db, { workstream: r.name })),\n );\n}\n\nexport async function summarizeWorkstream(\n db: Db,\n opts: WorkstreamOptions,\n): Promise<WorkstreamSummary> {\n return summarize(db, opts);\n}\n\nasync function summarize(db: Db, opts: WorkstreamOptions): Promise<WorkstreamSummary> {\n const muxSession = opts.muxSession ?? `mu-${opts.workstream}`;\n return {\n name: opts.workstream,\n muxSession,\n muxAlive: await sessionAlive(muxSession),\n agentCount: countAgents(db, opts.workstream),\n taskCount: countTasks(db, opts.workstream),\n noteCount: countNotes(db, opts.workstream),\n edgeCount: countEdges(db, opts.workstream),\n worktreeCount: listWorktrees(db, opts.workstream).length,\n registered: isRegistered(db, opts.workstream),\n };\n}\n\nfunction isRegistered(db: Db, workstream: string): boolean {\n const row = db\n .prepare(\"SELECT 1 AS x FROM workstreams WHERE name = ? AND torn_down_at IS NULL\")\n .get(workstream) as { x: number } | undefined;\n return row !== undefined;\n}\n\n/**\n * Tear down a workstream (soft): kill its mux session, delete its\n * machine-local agent rows and set `torn_down_at`. Worktrees are never\n * removed. Tasks, edges and notes STAY (a later `init --if` is what\n * hard-deletes them, after a preview). Needs the preview revision.\n *\n * ORDER IS THE GUARANTEE. Nothing is written before the session is known\n * dead: the revision check reads only; the mux probe PROPAGATES (\"could\n * not ask\" is not \"dead\"); a registered pane outside the session is asked\n * about by id and blocks the teardown while it lives; the kill comes before\n * any DB change; the DB commit is last, one op group. A failure at any step\n * leaves the workstream live and the command re-runnable.\n *\n * Idempotent: an unknown or already-torn-down name has nothing to do.\n */\nexport async function teardownWorkstream(\n db: Db,\n opts: TeardownWorkstreamOptions,\n): Promise<TeardownResult> {\n const muxSession = opts.muxSession ?? `mu-${opts.workstream}`;\n\n const revision = workstreamRevision(db, opts.workstream);\n if (revision !== opts.ifRevision) {\n throw new WorkstreamRevisionMismatchError(opts.workstream, opts.ifRevision, revision);\n }\n\n const agentsBefore = listAgentPanes(db, opts.workstream);\n const tasksBefore = countTasks(db, opts.workstream);\n const notesBefore = countNotes(db, opts.workstream);\n const edgesBefore = countEdges(db, opts.workstream);\n const worktreesBefore = listWorktrees(db, opts.workstream);\n\n // Mux session first: if killSession throws we don't want any DB state\n // changed with panes still running. (killSession is itself idempotent\n // on missing sessions — a real throw here is an unexpected mux error.)\n // Load-bearing: teardown must actually kill the session, not silently\n // report success while leaving panes running.\n const mux = await activeMux();\n // The probe PROPAGATES: \"could not ask\" is not \"dead\". Swallowing it\n // here would change DB state while panes may still run.\n const sessionPanes = new Set((await mux.listPanes(muxSession)).map((p) => p.paneId));\n // The session kill covers the panes in it. A registered pane that is NOT\n // in it (moved to another session by hand) survives the kill, so it is\n // asked about by its own id; failing to ask propagates too.\n const strays: string[] = [];\n for (const a of agentsBefore) {\n if (sessionPanes.has(a.paneId)) continue;\n if (await mux.paneAlive(a.paneId)) strays.push(a.name);\n }\n if (strays.length > 0) throw new WorkstreamPanesLiveError(opts.workstream, strays);\n const muxAliveBefore = sessionPanes.size > 0;\n if (muxAliveBefore) {\n await mux.killSession(muxSession);\n }\n\n // Worktrees are NOT touched: teardown never removes one (the registry's\n // close rule belongs to `mu agent close`). They stay registered and on\n // disk; the result lists them.\n\n // THE ROW RULE: a row is deleted only when its recorded pane is known\n // dead, asked by pane id AFTER the kill (a pane moved out of the session\n // while it was being killed survives it), and nothing is unlinked or\n // deleted for a row before that answer. Alive or unknown keeps the row\n // (orphaned: it lives in a torn-down workstream) and the result says so.\n // A dead pane stays dead (tmux never reuses an id), so the answer holds\n // through the transaction below.\n const dead: { name: string; paneId: string; incarnation: number }[] = [];\n const orphaned: TeardownResult[\"orphanedAgents\"] = [];\n for (const a of agentsBefore) {\n let reason: \"alive\" | \"unknown\" | undefined;\n try {\n if (await mux.paneAlive(a.paneId)) reason = \"alive\";\n } catch {\n reason = \"unknown\";\n }\n if (reason === undefined) dead.push(a);\n else orphaned.push({ name: a.name, paneId: a.paneId, reason });\n }\n\n // Unlink each DEAD agent's control socket (ssh -L forwards leave theirs\n // behind) BEFORE the DELETE: the agent rows are how a retry finds the\n // sockets, so an interrupted unlink must leave them in place. Then reap\n // sock/<ws>/ only if empty, never recursively: hashed long paths\n // share sock/h/ across workstreams, so a workstream named \"h\" must\n // not take the others' sockets with it. A kept row keeps its socket.\n // Only for the incarnation that was asked about: a replacement registered\n // since owns the socket path now (its transaction check below then aborts).\n const sameRow = db.prepare(\n `SELECT 1 FROM agents a JOIN workstreams ws ON ws.id = a.workstream_id\n WHERE a.id = ? AND a.name = ? AND a.pane_id = ? AND ws.name = ?`,\n );\n for (const a of dead) {\n if (sameRow.get(a.incarnation, a.name, a.paneId, opts.workstream) !== undefined)\n unlinkCtlSocket(db, a.name, opts.workstream);\n }\n if (!db.memory) {\n const sockDir = join(dirname(db.name), \"sock\", opts.workstream);\n try {\n if (readdirSync(sockDir).length === 0) rmdirSync(sockDir);\n } catch {\n // Missing or non-empty: nothing of ours left to reap.\n }\n }\n\n // The DB commit, last, in ONE op group (intent workstream.teardown):\n // delete the dead agents' rows, then set torn_down_at (one captured\n // put). Nothing cascades from either: tasks, edges and notes stay. The\n // whole revision is read again INSIDE the transaction: an op, agent or\n // worktree that appeared since the preview (a sweep member changed while\n // an earlier one was being killed, a racing spawn) aborts the commit\n // instead of being swept up unseen.\n const tornDownAt = new Date().toISOString();\n withOpContext(db, { intent: \"workstream.teardown\", group: \"new\" }, () =>\n db\n .transaction(() => {\n const now = workstreamRevision(db, opts.workstream);\n if (now !== opts.ifRevision) {\n throw new WorkstreamRevisionMismatchError(opts.workstream, opts.ifRevision, now);\n }\n // Each dead row goes through THE reaper step (src/agents/reap.ts), in\n // this transaction and group: its remote worktree is recorded and\n // what it owned reopens, exactly as a pane that died on its own.\n for (const a of dead) {\n if (!sameRow.get(a.incarnation, a.name, a.paneId, opts.workstream)) continue;\n reapAgentRow(db, a.incarnation, a.name);\n }\n db.prepare(\n \"UPDATE workstreams SET torn_down_at = ? WHERE name = ? AND torn_down_at IS NULL\",\n ).run(tornDownAt, opts.workstream);\n })\n .immediate(),\n );\n // No emitEvent: the UPDATE fired the capture trigger (op='put',\n // intent='workstream.teardown', payload {torn_down_at}).\n\n return {\n killedMux: muxAliveBefore,\n deletedAgents: dead.length,\n orphanedAgents: orphaned,\n tasks: tasksBefore,\n notes: notesBefore,\n edges: edgesBefore,\n keptWorktrees: worktreesBefore.map((w) => ({ agent: w.agent, path: w.path })),\n };\n}\n\n/** What `workstream init` would permanently delete when the name is torn\n * down, or null when it is live or unknown. */\nexport interface ReinitPreview {\n tornDownAt: string;\n tasks: number;\n notes: number;\n edges: number;\n revision: number;\n}\n\nexport function previewReinit(db: Db, name: string): ReinitPreview | null {\n const tornDownAt = tornDownAtOf(db, name);\n if (tornDownAt === null) return null;\n return {\n tornDownAt,\n tasks: countTasks(db, name),\n notes: countNotes(db, name),\n edges: countEdges(db, name),\n revision: workstreamRevision(db, name),\n };\n}\n\n/**\n * Reuse a torn-down name: hard-delete the old row (the FK cascade removes\n * its tasks, edges and notes, each captured as today's tombstones) and\n * create the new one, in ONE op group (intent workstream.init). Needs the\n * preview revision. Refuses while the old mux session is alive (the probe\n * runs first and propagates) or while this machine still has agent rows in\n * the old workstream: a peer's teardown can reach a machine whose panes live.\n */\nexport async function reinitWorkstream(\n db: Db,\n name: string,\n ifRevision: number,\n muxSession = `mu-${name}`,\n): Promise<void> {\n assertValidWorkstreamName(name);\n // The mux is asked FIRST and the probe propagates: \"could not ask\" is not\n // \"dead\", and nothing is deleted while panes may run (the teardown rule).\n if (tornDownAtOf(db, name) !== null) {\n if ((await (await activeMux()).listPanes(muxSession)).length > 0) {\n throw new WorkstreamSessionLiveError(name, muxSession);\n }\n }\n withOpContext(db, { intent: \"workstream.init\", group: \"new\" }, () =>\n db\n .transaction(() => {\n if (tornDownAtOf(db, name) === null) return;\n const revision = workstreamRevision(db, name);\n if (revision !== ifRevision) {\n throw new WorkstreamRevisionMismatchError(\n name,\n ifRevision,\n revision,\n `mu workstream init ${name}`,\n );\n }\n const agents = listAgentPanes(db, name).map((a) => a.name);\n if (agents.length > 0) throw new WorkstreamHasAgentsError(name, agents);\n // No agent row is left to cascade (checked above, same transaction):\n // the delete of each row recorded its remote worktree.\n db.prepare(\"DELETE FROM workstreams WHERE name = ?\").run(name);\n ensureWorkstreamImpl(db, name);\n })\n .immediate(),\n );\n}\n\n// ─── Counts ────────────────────────────────────────────────────────────\n\nfunction listAgentPanes(\n db: Db,\n workstream: string,\n): { name: string; paneId: string; incarnation: number }[] {\n const rows = db\n .prepare(\n `SELECT a.name, a.pane_id AS paneId, a.id AS incarnation FROM agents a\n JOIN workstreams ws ON ws.id = a.workstream_id\n WHERE ws.name = ?\n ORDER BY a.name, a.pane_id`,\n )\n .all(workstream) as { name: string; paneId: string; incarnation: number }[];\n return rows;\n}\n\nfunction countAgents(db: Db, workstream: string): number {\n const row = db\n .prepare(\n `SELECT COUNT(*) AS n FROM agents a\n JOIN workstreams ws ON ws.id = a.workstream_id\n WHERE ws.name = ?`,\n )\n .get(workstream) as { n: number };\n return row.n;\n}\n\nfunction countTasks(db: Db, workstream: string): number {\n const row = db\n .prepare(\n `SELECT COUNT(*) AS n FROM tasks t\n JOIN workstreams ws ON ws.id = t.workstream_id\n WHERE ws.name = ?`,\n )\n .get(workstream) as { n: number };\n return row.n;\n}\n\nfunction countNotes(db: Db, workstream: string): number {\n const row = db\n .prepare(\n `SELECT COUNT(*) AS n\n FROM task_notes n\n JOIN tasks t ON t.id = n.task_id\n JOIN workstreams ws ON ws.id = t.workstream_id\n WHERE ws.name = ?`,\n )\n .get(workstream) as { n: number };\n return row.n;\n}\n\nfunction countEdges(db: Db, workstream: string): number {\n // Count edges whose blocker (from_task) is in the workstream. Since\n // cross-workstream edges are forbidden by addTask, this equals the\n // edge count for the workstream subgraph.\n const row = db\n .prepare(\n `SELECT COUNT(*) AS n\n FROM task_edges e\n JOIN tasks t ON t.id = e.from_task_id\n JOIN workstreams ws ON ws.id = t.workstream_id\n WHERE ws.name = ?`,\n )\n .get(workstream) as { n: number };\n return row.n;\n}\n","// mu — keep mu.db slim: `mu db compact` and `mu db forget`.\n//\n// The ops log is append-only except for these two operator verbs. Both\n// rewrite history on THIS machine only and never touch sync segments:\n//\n// - compact: a note tombstone (`op='del'`) whose key also has a put in\n// the log carries a copy of that put's row. apply's delete reads the put, so the copy is dead weight; blank it\n// to `{}`. Capture stopped writing these copies (src/capture.ts\n// noteTombstonePayload); this applies the same rule to old rows.\n// - forget: delete every op of named, torn-down workstreams. Their rows\n// are already gone from the live tables, so rebuild and drift stay\n// consistent; what is lost is the teardown's history, on purpose.\n//\n// Neither is reached by a trigger or a sync path. The CLI backs up the\n// DB first and runs the drift check after.\n\nimport type { Db } from \"./db.js\";\nimport { OPS_ENTITIES_SQL } from \"./logs.js\";\n\n/** Note tombstones whose payload is redundant: the newest earlier put under\n * the same key describes the same note (author, content, created_at). A\n * tombstone whose key now belongs to ANOTHER note (ids reassigned by a\n * rebuild) carries the only record of what died; blanking it would make\n * apply kill the wrong note. */\nconst REDUNDANT_TOMBSTONES_SQL = `\n SELECT d.seq AS seq, length(d.payload) AS bytes\n FROM ops d\n WHERE d.entity = 'note' AND d.op = 'del' AND d.payload <> '{}'\n AND (SELECT json_extract(p.payload, '$.author') IS json_extract(d.payload, '$.author')\n AND json_extract(p.payload, '$.content') IS json_extract(d.payload, '$.content')\n AND json_extract(p.payload, '$.created_at') IS json_extract(d.payload, '$.created_at')\n FROM ops p\n WHERE p.entity = 'note' AND p.key = d.key AND p.op = 'put' AND p.seq < d.seq\n ORDER BY p.seq DESC LIMIT 1)`;\n\nexport interface CompactPlan {\n /** Note tombstones that would be blanked. */\n tombstones: number;\n /** Payload bytes those tombstones carry now. */\n bytes: number;\n}\n\nexport function planCompact(db: Db): CompactPlan {\n const r = db\n .prepare(\n `SELECT COUNT(*) AS n, COALESCE(SUM(bytes), 0) AS b FROM (${REDUNDANT_TOMBSTONES_SQL})`,\n )\n .get() as { n: number; b: number };\n return { tombstones: r.n, bytes: r.b };\n}\n\n/** Blank every redundant note tombstone, in one transaction. */\nexport function compact(db: Db): CompactPlan {\n const plan = planCompact(db);\n db.transaction(() => {\n db.prepare(\n `UPDATE ops SET payload = '{}' WHERE seq IN (SELECT seq FROM (${REDUNDANT_TOMBSTONES_SQL}))`,\n ).run();\n }).immediate();\n return plan;\n}\n\n/** The ops one workstream's history occupies: the workstream op itself,\n * and every op keyed under it (`<ws>/...`: tasks, notes, edges, agents,\n * worktrees, waves). The key range ['<ws>', '<ws>0') ('0' is the byte\n * after '/') seeks idx_ops_entity_key once per entity; the exact test\n * after it drops siblings such as '<ws>-2'. A bare `substr(key, …)` test, or\n * an OR around the range, scanned all of ops per candidate. The entity list\n * is read from the data so legacy and future entities are covered. */\nexport const WORKSTREAM_OPS_WHERE = `(entity IN (${OPS_ENTITIES_SQL}) AND key >= @ws AND key < @ws || '0'\n AND (key = @ws OR substr(key, 1, length(@ws) + 1) = @ws || '/'))`;\n\nexport interface ForgetCandidate {\n name: string;\n /** ISO time of its latest teardown. */\n tornDownAt: string;\n ops: number;\n /** Payload bytes of those ops (the on-disk share is about twice this,\n * with the row overhead and the four ops indexes). */\n bytes: number;\n}\n\n/** Why a name cannot be forgotten. */\nexport type ForgetRefusal = \"live\" | \"never-torn-down\";\n\nexport interface ForgetPlan {\n candidates: ForgetCandidate[];\n refused: { name: string; why: ForgetRefusal }[];\n}\n\n/** Every torn-down workstream that is not live again, largest first. */\nexport function listForgetCandidates(db: Db): ForgetCandidate[] {\n const names = db\n .prepare(\n `SELECT key AS name, MAX(created_at) AS at\n FROM ops\n WHERE entity = 'workstream' AND op = 'del'\n AND intent = 'workstream.teardown'\n AND key NOT IN (SELECT name FROM workstreams)\n GROUP BY key`,\n )\n .all() as { name: string; at: string }[];\n const cost = db.prepare(\n `SELECT COUNT(*) AS n, COALESCE(SUM(length(payload)), 0) AS b FROM ops WHERE ${WORKSTREAM_OPS_WHERE}`,\n );\n return names\n .map((r) => {\n const c = cost.get({ ws: r.name }) as { n: number; b: number };\n return { name: r.name, tornDownAt: r.at, ops: c.n, bytes: c.b };\n })\n .sort((a, b) => b.bytes - a.bytes);\n}\n\nexport function planForget(db: Db, names: readonly string[]): ForgetPlan {\n const all = new Map(listForgetCandidates(db).map((c) => [c.name, c]));\n const live = new Set(\n (db.prepare(\"SELECT name FROM workstreams\").all() as { name: string }[]).map((r) => r.name),\n );\n const plan: ForgetPlan = { candidates: [], refused: [] };\n for (const name of new Set(names)) {\n const c = all.get(name);\n if (c) plan.candidates.push(c);\n else plan.refused.push({ name, why: live.has(name) ? \"live\" : \"never-torn-down\" });\n }\n return plan;\n}\n\n/** Delete every op of the plan's candidates, in one transaction. Irreversible. */\nexport function forget(db: Db, plan: ForgetPlan): { ops: number } {\n const del = db.prepare(`DELETE FROM ops WHERE ${WORKSTREAM_OPS_WHERE}`);\n let ops = 0;\n db.transaction(() => {\n for (const c of plan.candidates) ops += del.run({ ws: c.name }).changes;\n }).immediate();\n return { ops };\n}\n","// mu — per-agent git worktrees: creation, the machine-local registry, and\n// the one close rule shared by `agent close`, orphan close and teardown.\n//\n// A worker's cwd IS its worktree (`spawn --worktree`). Git only; the\n// worktree is `git worktree add --detach` because a named branch would\n// break name reuse. A branch is made only to keep unmerged commits.\n//\n// The registry (`worktrees`, machine-local) is NOT keyed to the agent: it\n// outlives the agent row so a reused name can tell its own clean leftover\n// from foreign work, and so close can still finish an orphaned worktree.\n// The reaper (reconcile) never touches a worktree or the registry; cleanup\n// is `agent close` / teardown, never a side effect of listing.\n\nimport { execFile } from \"node:child_process\";\nimport { existsSync, readdirSync, readFileSync, readlinkSync, renameSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport type { Db } from \"./db.js\";\nimport { defaultStateDir } from \"./db.js\";\nimport { say } from \"./messages.js\";\nimport {\n addWorktree,\n createBranch,\n dirtyFiles,\n git,\n gitToplevel,\n headSha,\n ownCommits,\n owningRoot,\n removeWorktreeDir,\n upstreamRefs,\n} from \"./vcs/git.js\";\n\nexport { upstreamRefs } from \"./vcs/git.js\";\n\n// ─── errors ────────────────────────────────────────────────────────────\n\n/** `--worktree` was asked of a root that is not inside a git repo. Exit 4. */\nexport class WorktreeVcsRequiredError extends Error {\n override readonly name = \"WorktreeVcsRequiredError\";\n constructor(public readonly root: string) {\n super(say(\"worktree.vcs_required\", root));\n }\n}\n\n/** Most dirty paths an error lists. */\nconst MAX_DIRTY_LISTED = 10;\n\n/**\n * `agent close` (or teardown) refused: the worktree has uncommitted work.\n * `--discard` overrides. Exit 4.\n */\nexport class WorktreeDirtyError extends Error {\n override readonly name = \"WorktreeDirtyError\";\n constructor(\n public readonly agent: string,\n public readonly workstream: string,\n public readonly path: string,\n public readonly files: readonly string[],\n ) {\n const shown = files.slice(0, MAX_DIRTY_LISTED);\n const more = files.length - shown.length;\n super(say(\"worktree.dirty\", agent, path, shown, more));\n }\n}\n\n/**\n * Spawn found a worktree dir at the agent's path that is not its own clean\n * leftover (dirty, new commits, or not made by mu). Exit 4.\n */\nexport class WorktreePathNotEmptyError extends Error {\n override readonly name = \"WorktreePathNotEmptyError\";\n constructor(\n public readonly agent: string,\n public readonly workstream: string,\n public readonly path: string,\n public readonly why: string,\n ) {\n super(say(\"worktree.path_not_empty\", agent, path, why));\n }\n}\n\n/**\n * Close would keep unmerged commits on `mu/<ws>/<agent>-<sha12>`, but a branch\n * of that name already points at another commit. It is never moved; the\n * worktree and its registry row are kept. Exit 4.\n */\nexport class WorktreeBranchExistsError extends Error {\n override readonly name = \"WorktreeBranchExistsError\";\n constructor(\n public readonly agent: string,\n public readonly workstream: string,\n public readonly path: string,\n public readonly branch: string,\n ) {\n super(say(\"worktree.branch_exists\", agent, workstream, path, branch));\n }\n}\n\n/**\n * `agent close` refused to remove a worktree something may still use: a\n * process has a file in it open for writing (`holder`), or no scan could\n * prove there is none (`holder` undefined). `--force` overrides either. The\n * tree, its registry row and the agent row are kept. Exit 4.\n */\nexport class WorktreeHeldError extends Error {\n override readonly name = \"WorktreeHeldError\";\n constructor(\n public readonly agent: string,\n public readonly workstream: string,\n public readonly path: string,\n public readonly holder: WorktreeHolder | undefined,\n ) {\n super(say(\"worktree.held\", agent, workstream, path, holder));\n }\n /** The writer's pid; undefined when the refusal is an unprovable scan. */\n get pid(): number | undefined {\n return this.holder?.pid;\n }\n}\n\n// ─── paths ─────────────────────────────────────────────────────────────\n\n/** `<state dir>/worktrees`: where mu puts the worktrees it creates. */\nexport function worktreesRoot(): string {\n return join(defaultStateDir(), \"worktrees\");\n}\n\n/** The canonical path of an agent's worktree. */\nexport function worktreePath(workstream: string, agent: string): string {\n return join(worktreesRoot(), workstream, agent);\n}\n\n// ─── git-level operations ──────────────────────────────────────────────\n\n/**\n * `git -C root worktree add --detach path [from]`. Returns the commit the\n * worktree is at. The caller registers it.\n */\nexport async function createWorktree(opts: {\n root: string;\n path: string;\n from?: string;\n signal?: AbortSignal;\n}): Promise<{ base: string }> {\n return { base: await addWorktree(opts.root, opts.path, opts.from, opts.signal) };\n}\n\n/** Remove a worktree. `force` also drops uncommitted work. */\nexport async function removeWorktree(\n root: string,\n path: string,\n opts: { force?: boolean } = {},\n): Promise<void> {\n await removeWorktreeDir(root, path, opts.force === true);\n}\n\n/** The usable checkout of a worktree's repo: the recorded root, else git's own pointer. */\nasync function liveRoot(root: string, path: string): Promise<string | undefined> {\n if (root.length > 0 && (await gitToplevel(root)) !== undefined) return root;\n return owningRoot(path);\n}\n\nexport type WorktreeState = \"dirty\" | \"clean-merged\" | \"clean-unmerged\" | \"missing\";\n\n/**\n * Where a worktree stands, for the close rule:\n * missing the dir is gone\n * dirty uncommitted work, or git cannot say (unverifiable counts as dirty)\n * clean-merged clean and every commit is already upstream: HEAD is `base`,\n * or reachable from the root's HEAD / origin/HEAD / @{upstream}\n * clean-unmerged clean with commits of its own\n * `base` may be empty (a row migrated without one): then only the root's refs count.\n */\nexport async function worktreeState(\n path: string,\n base: string,\n root: string,\n): Promise<WorktreeState> {\n if (!existsSync(path)) return \"missing\";\n try {\n if ((await dirtyFiles(path)).length > 0) return \"dirty\";\n } catch {\n return \"dirty\";\n }\n try {\n const owner = (await liveRoot(root, path)) ?? path;\n const refs = (await upstreamRefs(owner, base)).filter((r) => r.length > 0);\n return (await ownCommits(path, refs)).length === 0 ? \"clean-merged\" : \"clean-unmerged\";\n } catch {\n return \"clean-unmerged\";\n }\n}\n\n// ─── the registry ──────────────────────────────────────────────────────\n\nexport interface WorktreeRow {\n path: string;\n agent: string;\n workstream: string;\n /** The checkout the worktree was added from (\"\" when unknown: migrated rows). */\n root: string;\n /** The commit the worktree was created at (\"\" when unknown). */\n base: string;\n /** HEAD last brought back by a collect; reuse and removal accept it like `base`. */\n lastCollectedHead: string | null;\n createdAt: string;\n}\n\ninterface RawWorktreeRow {\n path: string;\n agent: string;\n workstream: string;\n root: string;\n base: string;\n last_collected_head: string | null;\n created_at: string;\n}\n\nfunction fromRaw(r: RawWorktreeRow): WorktreeRow {\n return {\n path: r.path,\n agent: r.agent,\n workstream: r.workstream,\n root: r.root,\n base: r.base,\n lastCollectedHead: r.last_collected_head,\n createdAt: r.created_at,\n };\n}\n\nexport function registerWorktree(db: Db, row: Omit<WorktreeRow, \"lastCollectedHead\">): void {\n db.prepare(\n `INSERT OR REPLACE INTO worktrees (path, agent, workstream, root, base, created_at)\n VALUES (?, ?, ?, ?, ?, ?)`,\n ).run(row.path, row.agent, row.workstream, row.root, row.base, row.createdAt);\n}\n\nexport function forgetWorktree(db: Db, path: string): void {\n db.prepare(\"DELETE FROM worktrees WHERE path = ?\").run(path);\n}\n\nexport function getWorktreeAt(db: Db, path: string): WorktreeRow | undefined {\n const r = db.prepare(\"SELECT * FROM worktrees WHERE path = ?\").get(path) as\n | RawWorktreeRow\n | undefined;\n return r ? fromRaw(r) : undefined;\n}\n\n/** The registry row of an agent's worktree (newest when a name was reused). */\nexport function getWorktreeFor(db: Db, workstream: string, agent: string): WorktreeRow | undefined {\n const r = db\n .prepare(\n `SELECT * FROM worktrees WHERE workstream = ? AND agent = ?\n ORDER BY created_at DESC, rowid DESC LIMIT 1`,\n )\n .get(workstream, agent) as RawWorktreeRow | undefined;\n return r ? fromRaw(r) : undefined;\n}\n\nexport function listWorktrees(db: Db, workstream?: string): WorktreeRow[] {\n const rows =\n workstream === undefined\n ? db.prepare(\"SELECT * FROM worktrees ORDER BY workstream, agent, path\").all()\n : db\n .prepare(\"SELECT * FROM worktrees WHERE workstream = ? ORDER BY agent, path\")\n .all(workstream);\n return (rows as RawWorktreeRow[]).map(fromRaw);\n}\n\n// ─── name reuse (spawn) ────────────────────────────────────────────────\n\n/**\n * Make `path` free for a new worktree of `agent`. Nothing on disk: fine (a\n * stale registry row is forgotten). A worktree there is removed only if mu\n * made it, it is clean, and HEAD is the base (or the last collected head):\n * its own unused leftover. Anything else refuses with one line: no branch\n * is made on reuse. The close rule's scan runs first: a process writing in\n * the tree refuses (`mu agent close ... --force` removes it); a cwd or reader\n * there, or a scan that cannot run, is returned as a warning (the removal is\n * git's unforced one, which still refuses dirt).\n */\nexport async function reclaimWorktreePath(\n db: Db,\n opts: { agent: string; workstream: string; path: string },\n): Promise<string[]> {\n const { agent, workstream, path } = opts;\n const row = getWorktreeAt(db, path);\n if (existsSync(asideOfLocal(path))) {\n throw new WorktreePathNotEmptyError(\n agent,\n workstream,\n path,\n `an interrupted close parked it at ${asideOfLocal(path)}; finish it: mu agent close ${agent} -w ${workstream}`,\n );\n }\n if (!existsSync(path)) {\n if (row !== undefined) forgetWorktree(db, path);\n return [];\n }\n const refuse = (why: string) => new WorktreePathNotEmptyError(agent, workstream, path, why);\n if (row === undefined) throw refuse(\"not a worktree mu registered\");\n let files: string[];\n let head: string;\n try {\n files = await dirtyFiles(path);\n head = await headSha(path);\n } catch {\n throw refuse(\"git cannot read it\");\n }\n if (files.length > 0) throw refuse(`uncommitted work (${files.length} file(s))`);\n if (head !== row.base && head !== row.lastCollectedHead) {\n throw refuse(`commits of its own (HEAD ${head.slice(0, 12)})`);\n }\n const hidden: number[] = [];\n const holders = await worktreeHolders(path, undefined, hidden);\n const writer = holders?.find((h) => h.writer);\n if (writer !== undefined) {\n throw refuse(\n `process ${writer.pid}${writer.command === \"\" ? \"\" : ` (${writer.command})`} has a file in it open for writing; stop it, or remove the tree under it: mu agent close ${agent} -w ${workstream} --force`,\n );\n }\n const warnings = (holders ?? []).map((h) => say(\"worktree.holder_left\", path, h));\n if (holders === undefined) warnings.push(say(\"worktree.holders_unproven\", path));\n if (hidden.length > 0) warnings.push(say(\"worktree.holders_hidden\", path, hidden));\n await removeWorktreeDir((await liveRoot(row.root, path)) ?? undefined, path, false);\n forgetWorktree(db, path);\n return warnings;\n}\n\n// ─── the close rule ────────────────────────────────────────────────────\n\nexport interface ReleasedWorktree {\n path: string;\n /** What happened on disk. `gone`: the dir was already missing. */\n action: \"removed\" | \"kept-branch\" | \"discarded\" | \"gone\";\n /** The branch made to keep unmerged commits. */\n branch?: string;\n /** Processes still in the tree when it was removed (their cwd, a read-only file; or, under `force`, a writer). */\n warnings?: string[];\n}\n\n/**\n * Refuse a dirty worktree unless `discard`. Checked before any effect so a\n * caller can refuse before it kills a pane.\n */\nexport async function assertReleasable(\n row: WorktreeRow,\n opts: { discard?: boolean },\n): Promise<WorktreeState> {\n const state = await worktreeState(row.path, row.base, row.root);\n if (state === \"dirty\" && opts.discard !== true) {\n let files: string[] = [];\n try {\n files = await dirtyFiles(row.path);\n } catch {\n // unreadable: the error says so\n }\n throw new WorktreeDirtyError(row.agent, row.workstream, row.path, files);\n }\n return state;\n}\n\n/** Where `releaseWorktree` parks a tree while it proves nothing holds it. */\nexport const asideOfLocal = (path: string): string => `${path}.mu-removing`;\n\nconst exec = promisify(execFile);\n\n/** True when `target` is `dir` or under it. */\nconst under = (target: string, dir: string): boolean =>\n target === dir || target.startsWith(`${dir}/`);\n\n/**\n * A process found in a worktree. `writer`: it has a file there open for\n * writing (the one kind whose work a removal can lose); else its cwd or a\n * read-only file is there, which a close reports and goes past.\n */\nexport interface WorktreeHolder {\n pid: number;\n /** Its command name (`/proc/<pid>/comm`, lsof's `c`), \"\" when unknown. */\n command: string;\n writer: boolean;\n}\n\n/** `/proc/<pid>/fdinfo/<fd>` flags: O_WRONLY or O_RDWR. Unreadable counts as writing. */\nfunction fdWrites(fdinfo: string): boolean {\n let text: string;\n try {\n text = readFileSync(fdinfo, \"utf8\");\n } catch {\n return true;\n }\n const m = /^flags:\\s*([0-7]+)/m.exec(text);\n return m?.[1] === undefined || (Number.parseInt(m[1], 8) & 3) !== 0;\n}\n\n/** Is the process at `/proc/<pid>` this user's: its dir's owner, else the real uid in `status`. */\nfunction ownedByMe(procDir: string): boolean {\n const me = process.getuid?.();\n if (me === undefined) return true;\n try {\n if (statSync(procDir).uid === me) return true;\n } catch {\n return false; // gone\n }\n try {\n const m = /^Uid:\\s*(\\d+)/m.exec(readFileSync(join(procDir, \"status\"), \"utf8\"));\n return m?.[1] !== undefined && Number(m[1]) === me;\n } catch {\n return false;\n }\n}\n\n/**\n * Processes of this user with their cwd or an open file at or under `dir`\n * (this process excluded: a close run from inside the tree writes nothing\n * there). Reads /proc, else `lsof`; undefined when neither demonstrably ran\n * (the scan must see this very process). `probe` is a test seam.\n */\nexport async function worktreeHolders(\n dir: string,\n probe: { proc: string; lsof: string } = { proc: \"/proc\", lsof: \"lsof\" },\n /** Filled with this user's pids /proc refused to show (EACCES: non-dumpable, another namespace). */\n hidden: number[] = [],\n): Promise<WorktreeHolder[] | undefined> {\n const held = new Map<number, WorktreeHolder>();\n const add = (pid: number, command: string, writer: boolean): void => {\n const h = held.get(pid);\n if (h === undefined) held.set(pid, { pid, command, writer });\n else h.writer ||= writer;\n };\n let sawSelf = false;\n if (existsSync(join(probe.proc, \"self\"))) {\n for (const ent of readdirSync(probe.proc)) {\n if (!/^\\d+$/.test(ent)) continue;\n const pid = Number(ent);\n let denied = false;\n const link = (p: string): string | undefined => {\n try {\n return readlinkSync(p);\n } catch (err) {\n const code = (err as { code?: unknown }).code;\n denied ||= code === \"EACCES\" || code === \"EPERM\";\n return undefined; // gone, or not ours to read\n }\n };\n const cwd = link(join(probe.proc, ent, \"cwd\"));\n if (pid === process.pid) {\n sawSelf = cwd !== undefined;\n continue;\n }\n // Ours but unreadable: unknown, never \"not a holder\".\n if (denied && ownedByMe(join(probe.proc, ent))) {\n hidden.push(pid);\n continue;\n }\n let command: string | undefined;\n const name = (): string => {\n if (command === undefined) {\n try {\n command = readFileSync(join(probe.proc, ent, \"comm\"), \"utf8\").trim();\n } catch {\n command = \"\";\n }\n }\n return command;\n };\n if (cwd !== undefined && under(cwd, dir)) add(pid, name(), false);\n let fds: string[] = [];\n try {\n fds = readdirSync(join(probe.proc, ent, \"fd\"));\n } catch {\n // gone, or another user's\n }\n for (const fd of fds) {\n const t = link(join(probe.proc, ent, \"fd\", fd));\n if (t !== undefined && under(t, dir))\n add(pid, name(), fdWrites(join(probe.proc, ent, \"fdinfo\", fd)));\n }\n }\n return sawSelf ? [...held.values()] : undefined;\n }\n let out: string;\n try {\n out = (await exec(probe.lsof, [\"-w\", \"-Fpcfan\"], { maxBuffer: 256 * 1024 * 1024 })).stdout;\n } catch (err) {\n // lsof exits 1 when some files could not be read; its output still counts.\n const o = (err as { stdout?: unknown }).stdout;\n if (typeof o !== \"string\" || o === \"\") return undefined;\n out = o;\n }\n let pid = 0;\n let command = \"\";\n let field = \"\";\n let access = \"\";\n for (const l of out.split(\"\\n\")) {\n if (l.startsWith(\"p\")) {\n pid = Number(l.slice(1));\n command = \"\";\n } else if (l.startsWith(\"c\")) command = l.slice(1);\n else if (l.startsWith(\"f\")) {\n field = l.slice(1);\n access = \"\";\n } else if (l.startsWith(\"a\")) access = l.slice(1).trim();\n else if (l.startsWith(\"n\")) {\n if (pid === process.pid) sawSelf ||= field === \"cwd\";\n else if (under(l.slice(1), dir))\n // An fd (numeric field) not known to be read-only counts as writing.\n add(pid, command, /^\\d+$/.test(field) && access !== \"r\");\n }\n }\n return sawSelf ? [...held.values()] : undefined;\n}\n\n/**\n * Move a worktree (`git worktree move` while its repo lives, so git keeps\n * tracking it; a plain rename once the repo is gone).\n */\nasync function moveTree(owner: string | undefined, from: string, to: string): Promise<void> {\n if (owner === undefined) renameSync(from, to);\n else await git([\"worktree\", \"move\", from, to], owner);\n}\n\n/**\n * The one close rule (README § Worktrees):\n * dirty refuse (WorktreeDirtyError) unless `discard`, which removes it\n * clean, merged remove\n * clean, unmerged make `mu/<ws>/<agent>-<sha12>` at HEAD in the root repo, then remove\n * missing forget the row\n * The registry row is forgotten once the dir is handled. Re-checks the state\n * itself: a write between a caller's pre-check and this call still refuses.\n *\n * Quiescence before any branch or removal, the remote close rule's local\n * twin: the tree is parked at `asideOfLocal(path)` (a writer addressing the\n * old path now fails), `worktreeHolders` must prove no process has its cwd or\n * an open file in it, and the state is judged again under the park. A file\n * open for writing refuses (`WorktreeHeldError`), as does a scan that cannot\n * run; `force` overrides both. A process with only its cwd or a read-only\n * file there (a shell cd'd in, a reader, a dashboard) loses nothing: it is\n * named in `warnings` and the close goes on. Any refusal moves the tree back. A park a crash left is moved\n * back first, then the rule runs again.\n */\nexport async function releaseWorktree(\n db: Db,\n row: WorktreeRow,\n opts: { discard?: boolean; force?: boolean; probe?: { proc: string; lsof: string } } = {},\n): Promise<ReleasedWorktree> {\n const aside = asideOfLocal(row.path);\n if (existsSync(aside)) {\n if (existsSync(row.path)) {\n throw new WorktreePathNotEmptyError(\n row.agent,\n row.workstream,\n row.path,\n `a parked copy is beside it at ${aside}; move or remove one by hand`,\n );\n }\n await moveTree(await liveRoot(row.root, aside), aside, row.path);\n }\n const before = await assertReleasable(row, opts);\n const owner = await liveRoot(row.root, row.path);\n if (before === \"missing\") {\n if (owner !== undefined) await removeWorktreeDir(owner, row.path, false);\n forgetWorktree(db, row.path);\n return { path: row.path, action: \"gone\" };\n }\n await moveTree(owner, row.path, aside);\n const parked: WorktreeRow = { ...row, path: aside };\n try {\n const hidden: number[] = [];\n const holders = await worktreeHolders(aside, opts.probe, hidden);\n const writer = holders?.find((h) => h.writer);\n if ((holders === undefined || writer !== undefined) && opts.force !== true) {\n throw new WorktreeHeldError(row.agent, row.workstream, row.path, writer);\n }\n // Nothing a removal can lose: say who is still there, and go on. A process\n // /proc would not show is unknown: said too (one line), never taken as absent.\n const warnings = (holders ?? []).map((h) => say(\"worktree.holder_left\", row.path, h));\n if (hidden.length > 0) warnings.push(say(\"worktree.holders_hidden\", row.path, hidden));\n const said = warnings.length > 0 ? { warnings } : {};\n // Judged again under the park: a write that raced the first check counts.\n const state = await assertReleasable(parked, opts);\n if (state === \"missing\") throw new Error(`worktree ${aside} vanished while closing`);\n if (opts.discard === true) {\n await removeWorktreeDir(owner, aside, true);\n forgetWorktree(db, row.path);\n return { path: row.path, action: \"discarded\", ...said };\n }\n if (state === \"clean-unmerged\") {\n if (owner === undefined) throw new Error(say(\"worktree.unmerged_repo_gone\", row.path));\n const sha = await headSha(aside);\n const branch = `mu/${row.workstream}/${row.agent}-${sha.slice(0, 12)}`;\n // Create-only: a retry finds its own branch at this HEAD and goes on.\n if (!(await createBranch(owner, branch, sha))) {\n throw new WorktreeBranchExistsError(row.agent, row.workstream, row.path, branch);\n }\n await removeWorktreeDir(owner, aside, false);\n forgetWorktree(db, row.path);\n return { path: row.path, action: \"kept-branch\", branch, ...said };\n }\n // clean-merged. Without --force git itself refuses a write that raced the check.\n try {\n await removeWorktreeDir(owner, aside, false);\n } catch (err) {\n let files: string[] = [];\n try {\n files = existsSync(aside) ? await dirtyFiles(aside) : [];\n } catch {\n // fall through with an empty list\n }\n if (files.length > 0)\n throw new WorktreeDirtyError(row.agent, row.workstream, row.path, files);\n throw err;\n }\n forgetWorktree(db, row.path);\n return { path: row.path, action: \"removed\", ...said };\n } catch (err) {\n // Nothing was removed: put the tree back where its agent and registry say it is.\n if (existsSync(aside) && !existsSync(row.path)) await moveTree(owner, aside, row.path);\n // A dirty refusal names the real path, not the park.\n if (err instanceof WorktreeDirtyError && err.path === aside) {\n throw new WorktreeDirtyError(row.agent, row.workstream, row.path, err.files);\n }\n throw err;\n }\n}\n","// mu — git primitives for worktrees. Plain functions: git is the only VCS.\n//\n// A mu worktree is `git worktree add --detach` (a named branch would break\n// name reuse); everything here shells out to git and never reads .git.\n\nimport { execFile } from \"node:child_process\";\nimport { existsSync, mkdirSync, rmSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { execGroupCapture } from \"../exec-file.js\";\n\nconst exec = promisify(execFile);\n\n/** Run git in `cwd`; stdout trimmed. Throws an Error carrying git's stderr. */\nexport async function git(args: readonly string[], cwd: string): Promise<string> {\n try {\n const { stdout } = await exec(\"git\", [...args], { cwd, maxBuffer: 16 * 1024 * 1024 });\n return stdout.trim();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`git ${args.join(\" \")} failed: ${msg}`, { cause: err });\n }\n}\n\n/** `git rev-parse --show-toplevel` of `dir`, or undefined outside a work tree. */\nexport async function gitToplevel(dir: string): Promise<string | undefined> {\n try {\n const out = await git([\"rev-parse\", \"--show-toplevel\"], dir);\n return out.length > 0 ? out : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** HEAD commit of `dir`. */\nexport function headSha(dir: string): Promise<string> {\n return git([\"rev-parse\", \"HEAD\"], dir);\n}\n\n/**\n * The checkout that owns a worktree: its common git dir's parent. Undefined\n * when the link is broken (the owning repo is gone).\n */\nexport async function owningRoot(worktreePath: string): Promise<string | undefined> {\n try {\n const common = await git(\n [\"rev-parse\", \"--path-format=absolute\", \"--git-common-dir\"],\n worktreePath,\n );\n return resolve(common, \"..\");\n } catch {\n return undefined;\n }\n}\n\n/**\n * `git -C root worktree add --detach <path> [<from>]`; returns the commit\n * the worktree is at. A stale registration of `path` (dir removed by hand)\n * is pruned first, or git refuses with \"missing but already registered\".\n */\nexport async function addWorktree(\n root: string,\n path: string,\n from?: string,\n /** Abort kills git and everything it started (hooks, filters): its own process group. */\n signal?: AbortSignal,\n): Promise<string> {\n signal?.throwIfAborted();\n mkdirSync(dirname(path), { recursive: true });\n await git([\"worktree\", \"prune\"], root).catch(() => {});\n const args = [\"worktree\", \"add\", \"--detach\", path, ...(from !== undefined ? [from] : [])];\n const r = await execGroupCapture(\"git\", args, { cwd: root, signal });\n signal?.throwIfAborted();\n if (r.exitCode !== 0) throw new Error(`git ${args.join(\" \")} failed: ${r.stderr}`);\n return headSha(path);\n}\n\n/** Remove a worktree nothing ever ran in, half-made ones included: git locks\n * those `initializing`, which only a double --force removes. */\nexport async function discardWorktree(root: string | undefined, path: string): Promise<void> {\n const owner = root ?? (await owningRoot(path));\n if (owner !== undefined)\n await git([\"worktree\", \"remove\", \"--force\", \"--force\", path], owner).catch(() => {});\n rmSync(path, { recursive: true, force: true });\n if (owner !== undefined) await git([\"worktree\", \"prune\"], owner).catch(() => {});\n}\n\n/** `git worktree remove` (never `--force` unless asked); falls back to rm when the owning repo is gone. */\nexport async function removeWorktreeDir(\n root: string | undefined,\n path: string,\n force: boolean,\n): Promise<void> {\n if (!existsSync(path)) {\n if (root !== undefined) await git([\"worktree\", \"prune\"], root).catch(() => {});\n return;\n }\n const owner = root !== undefined && existsSync(root) ? root : await owningRoot(path);\n if (owner === undefined) {\n rmSync(path, { recursive: true, force: true });\n return;\n }\n await git([\"worktree\", \"remove\", ...(force ? [\"--force\"] : []), path], owner);\n}\n\n/** Dirty paths in `dir` (modified, staged, untracked-not-ignored); empty = clean. Throws on failure. */\nexport async function dirtyFiles(dir: string): Promise<string[]> {\n const { stdout } = await exec(\"git\", [\"status\", \"--porcelain\"], { cwd: dir });\n return stdout\n .split(\"\\n\")\n .filter((l) => l.length > 0)\n .map((l) => l.slice(3));\n}\n\n/**\n * Everything already upstream of the worker: `base` (recorded at spawn),\n * the root's HEAD, `origin/HEAD` when it resolves, and the root's\n * `@{upstream}` when set. The worker's own commits are\n * `git rev-list HEAD --not <these>`, so a manual rebase onto advanced\n * local main or a fetched remote does not count the base's commits as the\n * worker's. Unresolved refs are skipped; the result is deduped SHAs and\n * always starts with `base`.\n */\nexport async function upstreamRefs(root: string, base: string): Promise<string[]> {\n const refs = [base];\n for (const rev of [\"HEAD\", \"origin/HEAD\", \"@{upstream}\"]) {\n try {\n const sha = await git([\"rev-parse\", \"--verify\", \"-q\", `${rev}^{commit}`], root);\n if (sha.length > 0 && !refs.includes(sha)) refs.push(sha);\n } catch {\n /* unresolved (no remote, no upstream): nothing extra to exclude */\n }\n }\n return refs;\n}\n\n/** True iff `sha` is an ancestor of (or equal to) `root`'s HEAD. */\nexport async function isAncestor(root: string, sha: string): Promise<boolean> {\n try {\n await git([\"merge-base\", \"--is-ancestor\", sha, \"HEAD\"], root);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Commits of `dir`'s HEAD that are in none of `notRefs`, newest first. */\nexport async function ownCommits(dir: string, notRefs: readonly string[]): Promise<string[]> {\n const out = await git([\"rev-list\", \"HEAD\", \"--not\", ...notRefs], dir);\n return out.length === 0 ? [] : out.split(\"\\n\");\n}\n\n/** The commit branch `name` points at in `root`, or undefined when there is none. */\nexport async function branchSha(root: string, name: string): Promise<string | undefined> {\n try {\n const sha = await git([\"rev-parse\", \"--verify\", \"-q\", `refs/heads/${name}^{commit}`], root);\n return sha.length > 0 ? sha : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * `git branch <name> <sha>` in `root`, create-only and idempotent: a branch\n * already at `sha` (an earlier attempt's) is kept. Never moves a branch:\n * one at another commit returns false. True once the branch is at `sha`.\n */\nexport async function createBranch(root: string, name: string, sha: string): Promise<boolean> {\n const existing = await branchSha(root, name);\n if (existing !== undefined) return existing === sha;\n await git([\"branch\", name, sha], root);\n return true;\n}\n","// mu — task id validation and title slug helpers.\n\nimport type { Db } from \"../db.js\";\nimport { say } from \"../messages.js\";\nimport { getTask } from \"./queries.js\";\n\n/** Thrown when a title has no ASCII letter or digit, so no id can be\n * derived from it (any non-ASCII script, or pure punctuation). Exit 2\n * (usage) with the verb's --help; the fix is the `<id>` positional.\n * Lives here, not in errors.ts, because errors.ts imports this file. */\nexport class TaskTitleSlugEmptyError extends Error {\n override readonly name = \"TaskTitleSlugEmptyError\";\n constructor(public readonly title: string) {\n super(say(\"task.slug_empty\", title));\n }\n}\n\n/** Lowercase alpha first, then alnum / underscore / hyphen, ≤64 chars. */\nconst TASK_ID_RE = /^[a-z][a-z0-9_-]{0,63}$/;\n\nexport function isValidTaskId(id: string): boolean {\n return TASK_ID_RE.test(id);\n}\n\n/**\n * Derive a task id from a free-form title.\n *\n * \"Build the auth module\" → \"build_the_auth_module\"\n * \"FILES: foo.ts (refactor)\" → \"files_foo_ts_refactor\"\n */\n\n/**\n * Soft cap for auto-generated slugs. The collision-suffix loop in\n * idFromTitle can push past this (`_2`, `_3`, ...) without going past\n * the hard ceiling. 40 chars hits the sweet spot of 'short enough to\n * type and to look reasonable in mu task tree' without losing too\n * much of the title's meaning.\n */\nconst SLUG_SOFT_CAP = 40;\n\n/**\n * Hard ceiling for any generated id. Schema has no length limit, but\n * 64 keeps ids comfortable in tables, JSON, and tmux pane titles.\n */\nconst SLUG_HARD_CAP = 64;\n\n/**\n * Lowercase title; collapse non-alnum runs into single `_`; trim\n * leading/trailing `_`; prefix `t_` if the result starts with a digit\n * (schema requires first char letter); apply the soft cap with\n * word-boundary trim (cut at the last `_` at-or-before SLUG_SOFT_CAP\n * when one exists, else hard-truncate). Mirrors `tg`'s `id_from_title`\n * but adds the soft cap.\n *\n * Throws `TaskTitleSlugEmptyError` if `title` yields an empty slug.\n */\nexport function slugifyTitle(title: string): string {\n return slugifyTitleVerbose(title).slug;\n}\n\n/**\n * Result of `slugifyTitleVerbose`: the slug plus enough metadata for\n * the CLI to decide whether to warn the user that meaning was lost.\n *\n * slug — the same string `slugifyTitle` returns.\n * strippedLength — length of the post-strip pre-cap slug. When this\n * exceeds the SLUG_SOFT_CAP the verbose form had to\n * cut at a word boundary (or hard-truncate); the\n * cut clauses are gone with no in-band signal.\n * originalSlug — what the slug WOULD have been without the\n * SLUG_SOFT_CAP cut: full stripped slug with the\n * same `t_` digit-prefix correction and the same\n * SLUG_HARD_CAP ceiling, but no word-boundary\n * truncation. Equal to `slug` when nothing was\n * cut. The CLI surfaces this in `mu task add\n * --json` so scripted callers can detect the\n * truncation without grepping stderr.\n * truncated — true iff `slug.length < strippedLength` AFTER the\n * `t_` digit-prefix correction, i.e. real bytes were\n * dropped. False for any title that fits under the\n * soft cap or whose only diff vs the stripped slug\n * is the `t_` prefix.\n *\n * The CLI's `mu task add` uses `truncated` to print a one-line stderr\n * hint pointing at the `<id>` positional override and (under --json)\n * to surface `originalSlug` alongside `truncated:true`\n * (slugifytitle_silently_drops_clauses; task_add_slugify_silently_truncates_ids).\n */\nexport interface SlugifyResult {\n slug: string;\n strippedLength: number;\n originalSlug: string;\n truncated: boolean;\n}\n\n/**\n * Verbose sibling of `slugifyTitle`: returns the slug AND a\n * `truncated` flag so the CLI can hint to the user when the soft cap\n * dropped clauses (the meaning-shift hazard documented in\n * slugifytitle_silently_drops_clauses).\n *\n * Algorithm is byte-for-byte identical to `slugifyTitle`; this just\n * surfaces the metadata that the plain form throws away.\n */\nexport function slugifyTitleVerbose(title: string): SlugifyResult {\n const stripped = title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n if (stripped.length === 0) {\n throw new TaskTitleSlugEmptyError(title);\n }\n // Soft cap with word-boundary preference: if the slug exceeds the\n // soft cap, look for the last `_` at-or-before the cap and cut there\n // (so we never break a word). If no underscore is in the cap window\n // (ie the title is one giant word), fall back to a hard truncate at\n // the soft cap. The result is always <= SLUG_SOFT_CAP after this.\n let trimmed: string;\n if (stripped.length <= SLUG_SOFT_CAP) {\n trimmed = stripped;\n } else {\n // lastIndexOf's fromIndex is inclusive, so an `_` AT index\n // SLUG_SOFT_CAP (a word ending exactly at the cap) is found too.\n const lastSep = stripped.lastIndexOf(\"_\", SLUG_SOFT_CAP);\n trimmed = lastSep > 0 ? stripped.slice(0, lastSep) : stripped.slice(0, SLUG_SOFT_CAP);\n }\n // First char must be a letter → prefix `t_` if it isn't. v5 has no\n // global namespace and no reserved prefix; `mu_foo` is a perfectly\n // valid local_id (per-workstream unique).\n const applyPrefix = (s: string): string =>\n /^[a-z]/.test(s) ? s.slice(0, SLUG_HARD_CAP) : `t_${s}`.slice(0, SLUG_HARD_CAP);\n const slug = applyPrefix(trimmed);\n // `originalSlug` is what the slug would have been without the\n // soft-cap word-boundary cut: same prefix correction, same hard\n // cap, no word-boundary trim. Used by `mu task add --json` so\n // scripted callers can detect truncation programmatically.\n const originalSlug = applyPrefix(stripped);\n // `truncated` reflects whether real characters were dropped — the\n // `t_` prefix doesn't count as truncation. We compare the trimmed\n // length against the stripped length (both pre-prefix) so a digit-\n // led title that fit under the cap still reports truncated=false.\n return {\n slug,\n strippedLength: stripped.length,\n originalSlug,\n truncated: trimmed.length < stripped.length,\n };\n}\n\n/**\n * Generate a unique task id from a title. v5: tasks.local_id is\n * per-workstream unique, so the collision check scopes to one\n * workstream. On collision, appends `_2`, `_3`, … until unique.\n */\nexport function idFromTitle(db: Db, workstream: string, title: string): string {\n return idFromTitleVerbose(db, workstream, title).id;\n}\n\n/**\n * Result of `idFromTitleVerbose`: the unique-in-workstream id plus the\n * truncated flag from the underlying slugify pass. Used by `mu task\n * add` to decide whether to surface the stderr hint about lost clauses\n * (slugifytitle_silently_drops_clauses) and to surface the un-truncated\n * slug in `--json` (task_add_slugify_silently_truncates_ids).\n *\n * id — the unique-in-workstream task id.\n * truncated — true iff the underlying slugify pass cut real\n * characters (collision-suffixing does NOT flip\n * this).\n * originalSlug — what the slug would have been without the\n * SLUG_SOFT_CAP cut. Equal to `id` when nothing was\n * cut AND no collision suffix was appended; for\n * the truncation-detection use case the only thing\n * the CLI cares about is the lossy-vs-not\n * comparison surfaced via `truncated`.\n */\nexport interface IdFromTitleResult {\n id: string;\n truncated: boolean;\n originalSlug: string;\n}\n\n/**\n * Verbose sibling of `idFromTitle`: returns the unique id, the\n * `truncated` flag from the slugify pass, and the un-truncated\n * `originalSlug` for `--json` consumers. Collision-suffixing (`_2`,\n * `_3`, …) does not flip `truncated` — the underlying slug's lossiness\n * is what the CLI hint cares about.\n */\nexport function idFromTitleVerbose(\n db: Db,\n workstream: string,\n title: string,\n /** Ids to treat as taken besides the DB's (explicit ids of the same batch). */\n reserved?: ReadonlySet<string>,\n): IdFromTitleResult {\n const { slug: base, truncated, originalSlug } = slugifyTitleVerbose(title);\n const free = (id: string): boolean =>\n reserved?.has(id) !== true && getTask(db, id, workstream) === undefined;\n if (free(base)) return { id: base, truncated, originalSlug };\n for (let i = 2; i < 1000; i++) {\n const candidate = `${base}_${i}`.slice(0, SLUG_HARD_CAP);\n if (free(candidate)) return { id: candidate, truncated, originalSlug };\n }\n throw new Error(`could not derive a unique id from title in workstream ${workstream}: ${title}`);\n}\n\n/** Ids compared without case and separators: `Fix-Auth` ≡ `fix_auth`. */\nconst fold = (id: string): string => id.toLowerCase().replace(/[-_\\s]/g, \"\");\n\n/** Edit distance, capped: enough to tell a typo from a different id. */\nfunction within(a: string, b: string, max: number): boolean {\n if (Math.abs(a.length - b.length) > max) return false;\n let prev = Array.from({ length: b.length + 1 }, (_, j) => j);\n for (let i = 1; i <= a.length; i++) {\n const row = [i];\n for (let j = 1; j <= b.length; j++) {\n row[j] = Math.min(\n (prev[j] ?? 0) + 1,\n (row[j - 1] ?? 0) + 1,\n (prev[j - 1] ?? 0) + (a[i - 1] === b[j - 1] ? 0 : 1),\n );\n }\n prev = row;\n }\n return (prev[b.length] ?? max + 1) <= max;\n}\n\n/**\n * Task ids of ONE workstream that a wrong `id` probably meant: same after\n * folding case and `-`/`_`, one containing the other (≥ 3 chars), or a typo\n * away (≤ 2 edits, ≥ 4 chars). Read only, compared in JS (no LIKE, so `_`\n * is just a character) and never another workstream's ids. A suggestion\n * for the operator: no verb resolves an id through it.\n */\nexport function candidateTaskIds(db: Db, workstream: string, id: string, limit = 5): string[] {\n const want = fold(id);\n if (want === \"\") return [];\n const rows = db\n .prepare(\n `SELECT t.local_id AS id FROM tasks t JOIN workstreams w ON w.id = t.workstream_id\n WHERE w.name = ? ORDER BY t.local_id`,\n )\n .all(workstream) as { id: string }[];\n const hits: string[] = [];\n for (const { id: have } of rows) {\n if (have === id) continue;\n const f = fold(have);\n const near =\n f === want ||\n (want.length >= 3 && f.length >= 3 && (f.includes(want) || want.includes(f))) ||\n (want.length >= 4 && f.length >= 4 && within(f, want, 2));\n if (near) hits.push(have);\n if (hits.length === limit) break;\n }\n return hits;\n}\n","// mu — task edit/write verbs: add task, add note, update, delete.\n\nimport {\n type Db,\n DEFAULT_EFFORT_DAYS,\n DEFAULT_IMPACT,\n type NoteKind,\n resolveWorkstreamId,\n type TaskKind,\n} from \"../db.js\";\nimport { currentOpContext, withOpContext } from \"../op-context.js\";\nimport { assertTaskRevision, taskRevision } from \"../revision.js\";\nimport { ensureWorkstream } from \"../workstream.js\";\nimport { taskIdFor, touchTask } from \"./core.js\";\nimport { cycleErrorFor, dedupeBlockersById, wouldCreateCycle } from \"./edges.js\";\nimport {\n CrossWorkstreamEdgeError,\n CycleError,\n TaskExistsError,\n TaskIdInvalidError,\n TaskNotFoundError,\n} from \"./errors.js\";\nimport { type IdFromTitleResult, idFromTitleVerbose, isValidTaskId } from \"./id.js\";\nimport { getTask } from \"./queries.js\";\n\nexport interface AddTaskOptions {\n localId: string;\n workstream: string;\n title: string;\n /** 1..100; enforced by schema CHECK. Omitted = 50, and unless\n * `effortDays` is given the task is unscored. */\n impact?: number;\n /** > 0; enforced by schema CHECK. Omitted = 1 (see `impact`). */\n effortDays?: number;\n /**\n * Tasks that block this one. Edges inserted as `blocker -> newTask`.\n * Each blocker must already exist AND share this task's workstream\n * (cross-workstream edges are forbidden); cycle check guards each\n * edge. The CLI surfaces this as `--blocked-by`; the SDK key matches.\n */\n blockedBy?: string[];\n /** Start as OPEN/triage (a proposal, e.g. a review finding) instead of OPEN/todo. */\n triage?: boolean;\n /** Task kind (default `work`). `human` starts OPEN/parked, never ready. */\n kind?: TaskKind;\n /** `tasks.wave`: the label grouping one fan-out of delegate calls. */\n wave?: string;\n}\n\n/**\n * Atomically create a task and (optionally) its incoming blocked-by\n * edges.\n *\n * The task insert + every edge insert + cycle check happen inside one\n * SQLite transaction. If any blocker is missing or any edge would\n * create a cycle, the entire add rolls back.\n *\n * Cycle check for `addTask` is structurally trivial (a fresh task has\n * no outgoing edges, so `to -> ... -> from` is impossible). It's still\n * called here so the same primitive is exercised by tests.\n */\nexport function addTask(db: Db, opts: AddTaskOptions) {\n return withOpContext(db, { intent: \"task.add\", group: \"new\" }, () => addTaskImpl(db, opts));\n}\n\nfunction addTaskImpl(db: Db, opts: AddTaskOptions) {\n if (!isValidTaskId(opts.localId)) {\n throw new TaskIdInvalidError(opts.localId);\n }\n\n return db\n .transaction(() => {\n // Auto-create the workstream row so tasks.workstream_id FK is\n // satisfied (preserves spawn-without-init ergonomics).\n ensureWorkstream(db, opts.workstream);\n const wsId = resolveWorkstreamId(db, opts.workstream);\n\n // Per-workstream uniqueness: a duplicate local_id within the same\n // workstream throws TaskExistsError. Different workstreams may\n // legitimately share local_ids in v5.\n const existing = db\n .prepare(\"SELECT id FROM tasks WHERE workstream_id = ? AND local_id = ?\")\n .get(wsId, opts.localId) as { id: number } | undefined;\n if (existing) {\n throw new TaskExistsError(opts.localId);\n }\n\n const now = new Date().toISOString();\n const insertResult = db\n .prepare(\n `INSERT INTO tasks (workstream_id, local_id, title, status, substate, kind, wave, impact, effort_days, scored, created_at, updated_at)\n VALUES (?, ?, ?, 'OPEN', ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n wsId,\n opts.localId,\n opts.title,\n opts.kind === \"human\" ? \"parked\" : opts.triage === true ? \"triage\" : \"todo\",\n opts.kind ?? \"work\",\n opts.wave ?? null,\n opts.impact ?? DEFAULT_IMPACT,\n opts.effortDays ?? DEFAULT_EFFORT_DAYS,\n opts.impact !== undefined || opts.effortDays !== undefined ? 1 : 0,\n now,\n now,\n );\n const newTaskId = Number(insertResult.lastInsertRowid);\n\n if (opts.blockedBy && opts.blockedBy.length > 0) {\n const requestedBlockers = opts.blockedBy.map((blocker) => {\n const row = lookupEdgeTask(db, wsId, blocker, opts.workstream);\n if (row.workstream !== opts.workstream) {\n throw new CrossWorkstreamEdgeError(\n blocker,\n row.workstream,\n opts.localId,\n opts.workstream,\n );\n }\n if (wouldCreateCycle(db, row.id, newTaskId)) {\n throw new CycleError(blocker, opts.localId);\n }\n return { localId: blocker, id: row.id };\n });\n const canonicalBlockers = dedupeBlockersById(requestedBlockers);\n const insertEdge = db.prepare(\n \"INSERT INTO task_edges (from_task_id, to_task_id, created_at) VALUES (?, ?, ?)\",\n );\n for (const blocker of canonicalBlockers) {\n insertEdge.run(blocker.id, newTaskId, now);\n }\n }\n\n const row = getTask(db, opts.localId, opts.workstream);\n if (!row) throw new Error(`addTask: row missing after insert: ${opts.localId}`);\n // No emitEvent: the INSERT above fired the tasks capture trigger,\n // which already wrote intent='task.add' key='<ws>/<id>' with the\n // full row as payload (v2-retire-log-shim).\n return row;\n })\n .immediate();\n}\n\nexport interface AddTasksOptions {\n workstream: string;\n /** Umbrellas the NEW tasks block (`mu task add --blocks`): edges\n * `newTask -> umbrella`, each umbrella same-workstream and cycle-checked. */\n blocks?: readonly string[];\n /** Tasks that block every NEW task (`--blocked-by`). */\n blockedBy?: readonly string[];\n triage?: boolean;\n /** Applied to every task of the batch (see AddTaskOptions). */\n kind?: TaskKind;\n impact?: number;\n effortDays?: number;\n /** Author of every `note` (the brief); also the group's actor. */\n noteAuthor?: string;\n}\n\nexport interface AddTasksResult {\n /** Local ids, in input order. */\n ids: string[];\n /** Per task, in input order: the id and, for a derived one, whether the\n * slug was cut (`truncated`) and its un-cut form. */\n derived: IdFromTitleResult[];\n /** False only for an empty batch. */\n changed: boolean;\n}\n\n/**\n * Create one or more tasks, each with an optional brief (kind 'brief'),\n * their `blockedBy` edges and their outbound `blocks` edges, in ONE op\n * group and ONE transaction. A duplicate id, invalid id, missing or\n * cross-workstream blocker/umbrella or a cycle rolls back every row, edge\n * and note of the batch.\n *\n * An entry without `id` gets one derived from its title: the slug, then\n * `_2`, `_3`, … the first suffix free in the DB, among the batch's\n * explicit ids and among the ids already derived. The probe runs inside\n * the transaction, so it cannot race another writer.\n */\nexport function addTasks(\n db: Db,\n input: readonly { id?: string; title: string; note?: string }[],\n opts: AddTasksOptions,\n): AddTasksResult {\n if (input.length === 0) return { ids: [], derived: [], changed: false };\n return withOpContext(db, { intent: \"task.add\", actor: opts.noteAuthor, group: \"new\" }, () =>\n db\n .transaction((): AddTasksResult => {\n const explicit = new Set(input.flatMap((t) => (t.id !== undefined ? [t.id] : [])));\n const done: { id: string }[] = [];\n const derived: IdFromTitleResult[] = [];\n for (const entry of input) {\n const d: IdFromTitleResult =\n entry.id !== undefined\n ? { id: entry.id, truncated: false, originalSlug: entry.id }\n : idFromTitleVerbose(db, opts.workstream, entry.title, explicit);\n derived.push(d);\n const t = { ...entry, id: d.id };\n done.push(t);\n addTaskImpl(db, {\n localId: t.id,\n workstream: opts.workstream,\n title: t.title,\n ...(opts.blockedBy !== undefined ? { blockedBy: [...opts.blockedBy] } : {}),\n ...(opts.triage === true ? { triage: true } : {}),\n ...(opts.kind !== undefined ? { kind: opts.kind } : {}),\n ...(opts.impact !== undefined ? { impact: opts.impact } : {}),\n ...(opts.effortDays !== undefined ? { effortDays: opts.effortDays } : {}),\n });\n if (t.note !== undefined) {\n const noteOpts: AddNoteOptions = { workstream: opts.workstream, kind: \"brief\" };\n if (opts.noteAuthor !== undefined) noteOpts.author = opts.noteAuthor;\n insertNote(db, t.id, t.note, noteOpts, false);\n }\n }\n if (opts.blocks !== undefined && opts.blocks.length > 0) {\n addBlocksEdges(db, done, opts.blocks, opts.workstream);\n }\n return { ids: done.map((t) => t.id), derived, changed: true };\n })\n .immediate(),\n );\n}\n\n/** Edges `newTask -> umbrella` for every task of a batch. The cycle check\n * runs after the incoming `blockedBy` edges exist, so `a` blocked by U\n * and blocking U is caught. */\nfunction addBlocksEdges(\n db: Db,\n input: readonly { id: string }[],\n blocks: readonly string[],\n workstream: string,\n): void {\n const wsId = resolveWorkstreamId(db, workstream);\n const umbrellas = new Map<number, string>();\n for (const local of blocks) {\n const row = lookupEdgeTask(db, wsId, local, workstream);\n if (row.workstream !== workstream) {\n throw new CrossWorkstreamEdgeError(input[0]?.id ?? local, workstream, local, row.workstream);\n }\n umbrellas.set(row.id, local);\n }\n const now = new Date().toISOString();\n const insertEdge = db.prepare(\n \"INSERT INTO task_edges (from_task_id, to_task_id, created_at) VALUES (?, ?, ?)\",\n );\n for (const t of input) {\n const newId = taskIdFor(db, t.id, workstream);\n if (newId === null) throw new TaskNotFoundError(t.id);\n for (const [umbrellaId, umbrella] of umbrellas) {\n if (wouldCreateCycle(db, newId, umbrellaId)) {\n throw cycleErrorFor(db, t.id, umbrella, newId, umbrellaId, workstream);\n }\n insertEdge.run(newId, umbrellaId, now);\n }\n }\n for (const umbrellaId of umbrellas.keys()) touchTask(db, umbrellaId, now);\n}\n\n/** Resolve an edge endpoint named by local id: prefer the\n * same-workstream task first (v5 per-workstream local_id), then fall\n * back to a global lookup so a cross-ws endpoint still surfaces\n * CrossWorkstreamEdgeError (not TaskNotFoundError). Without the\n * same-ws preference, two tasks of the same local_id (one in this ws,\n * one elsewhere) could silently bind to the wrong row. */\nfunction lookupEdgeTask(\n db: Db,\n wsId: number,\n localId: string,\n workstream: string,\n): { id: number; workstream: string } {\n const row = (db\n .prepare(\n `SELECT t.id AS id, ws.name AS workstream FROM tasks t\n JOIN workstreams ws ON ws.id = t.workstream_id\n WHERE t.local_id = ? AND t.workstream_id = ?`,\n )\n .get(localId, wsId) ??\n db\n .prepare(\n `SELECT t.id AS id, ws.name AS workstream FROM tasks t\n JOIN workstreams ws ON ws.id = t.workstream_id\n WHERE t.local_id = ? LIMIT 1`,\n )\n .get(localId)) as { id: number; workstream: string } | undefined;\n if (!row) throw new TaskNotFoundError(localId, workstream);\n return row;\n}\n\nexport interface AddNoteOptions {\n /** Free-form author label. Convention: agent name, \"user\", or \"orchestrator\". */\n author?: string;\n /** Workstream context (operator-facing name). v5: tasks.local_id is\n * per-workstream unique, so this is required to disambiguate. */\n workstream: string;\n /** Note kind (`task_notes.kind`), set once at INSERT. Default 'note'.\n * `closeTask` files its reason/evidence notes as 'close'. */\n kind?: NoteKind;\n /** 'new' (default): the note is its own op group. 'inherit': it joins\n * the CALLER's group, actor and intent (a verdict written inside a\n * delegate's record group). Honoured by `addNote`; `insertNote` always\n * inherits. */\n group?: \"new\" | \"inherit\";\n}\n\nexport interface AddNoteResult {\n author: string | null;\n content: string;\n createdAt: string;\n kind: NoteKind;\n}\n\n/** The op context of a writer's `group` option. 'inherit' OMITS the group\n * (withOpContext reads any string other than \"new\" as a literal group\n * id) and keeps the outer actor and intent; with no outer context the\n * call labels itself and mints its own group. */\nexport function writerContext(\n db: Db,\n intent: string,\n actor: string | undefined,\n group: \"new\" | \"inherit\" | undefined,\n): { intent?: string; intentIfUnset?: string; actor: string | undefined; group?: \"new\" } {\n if (group !== \"inherit\") return { intent, actor, group: \"new\" };\n return { intentIfUnset: intent, actor: currentOpContext(db).actor ?? actor };\n}\n\nexport function addNote(\n db: Db,\n taskLocalId: string,\n content: string,\n opts: AddNoteOptions,\n): AddNoteResult {\n return withOpContext(db, writerContext(db, \"task.note\", opts.author, opts.group), () =>\n insertNote(db, taskLocalId, content, opts),\n );\n}\n\n/** addNote without its own op context: the note joins the CALLER's\n * group and intent. For verbs whose note is part of one action (the\n * `--why` of `close --as` / `park`), so both share one group.\n * Internal — not re-exported from src/tasks.ts. */\nexport function insertNote(\n db: Db,\n taskLocalId: string,\n content: string,\n opts: AddNoteOptions,\n /** False when the caller's own UPDATE bumps `updated_at` in the same\n * group: a second `task` put there would duplicate the change. */\n touch = true,\n): AddNoteResult {\n const task = getTask(db, taskLocalId, opts.workstream);\n if (!task) {\n throw new TaskNotFoundError(taskLocalId, opts.workstream);\n }\n const taskId = taskIdFor(db, task.name, task.workstreamName);\n if (taskId === null) throw new TaskNotFoundError(taskLocalId, task.workstreamName);\n const now = new Date().toISOString();\n db.transaction(() => {\n const r = db\n .prepare(\n \"INSERT INTO task_notes (task_id, author, content, created_at, kind) VALUES (?, ?, ?, ?, ?)\",\n )\n .run(taskId, opts.author ?? null, content, now, opts.kind ?? \"note\");\n // Bump the parent task so `mu task list --sort recency` surfaces\n // freshly-noted tasks (task_updatedat_not_bumped_by_reparent).\n if (touch) touchTask(db, taskId, now);\n return r;\n }).immediate();\n // No emitEvent: the task_notes INSERT fired the capture trigger\n // (intent='task.note', key='<ws>/<id>#<n>').\n return {\n author: opts.author ?? null,\n content,\n createdAt: now,\n kind: opts.kind ?? \"note\",\n };\n}\n\nexport interface DeleteTaskResult {\n /** True iff the row existed and was deleted. False on a dry-run\n * (preview) AND on the idempotent missing-row case. */\n deleted: boolean;\n /** Number of `task_edges` rows cascaded out (informational). On a\n * dry-run, this is the would-be count. */\n deletedEdges: number;\n /** Number of `task_notes` rows cascaded out (informational). On a\n * dry-run, this is the would-be count. */\n deletedNotes: number;\n /** True iff this was a dry-run (`opts.dryRun: true`). On a\n * dry-run `deleted` is false and the counts are the would-be\n * counts; the DB is unchanged. Always false on a commit / on a\n * missing-row idempotent no-op. */\n dryRun: boolean;\n /** True iff a matching task row was found at the time of the\n * call. Discriminator for the CLI: a dry-run that found nothing\n * (`present: false`) renders differently from a dry-run that\n * found an existing task with zero edges and zero notes\n * (`present: true, deletedEdges: 0, deletedNotes: 0`). */\n present: boolean;\n /** The op group the delete wrote. Null\n * when nothing was deleted (dry-run or missing row). */\n group: string | null;\n /** The task's revision when it was found (`taskRevision`): a preview\n * prints it, `--if <rev>` repeats it. Absent for a missing task. */\n revision?: number;\n}\n\nexport interface DeleteTaskOptions {\n /** The preview revision (`taskRevision`). A commit whose task changed\n * since throws `RevisionMismatchError` before any write; checked in the\n * delete's own transaction. Ignored by a dry-run and by a missing task. */\n ifRevision?: number;\n /** When true, return the cascade preview (would-be edge / note\n * counts) without mutating. The CLI uses this to power the bare\n * `mu task delete <id>` two-phase pattern (mirrors\n * `mu workstream teardown`). A dogfood report typed\n * `mu task delete X --yes` (mirroring workstream teardown) and got\n * 'unknown option --yes' — the verb took no confirmation flag at\n * all. Two failed deletes left long-named tasks lingering. */\n dryRun?: boolean;\n}\n\n/**\n * Delete a task. FK CASCADE on `task_edges` (from + to) and\n * `task_notes` cleans the joined rows automatically. Idempotent on\n * a missing task (returns `deleted: false`).\n *\n * Pre-counts the cascade victims for reporting because SQLite's\n * `changes()` only reports rows directly affected by the DELETE.\n *\n * With `opts.dryRun: true`, returns the would-be counts without\n * touching the DB (no mutation, so no op is written). The CLI bare\n * `mu task delete <id>` form uses this; `--yes` calls through with\n * `dryRun: false`.\n */\nexport function deleteTask(\n db: Db,\n localId: string,\n workstream: string,\n opts: DeleteTaskOptions = {},\n): DeleteTaskResult {\n return withOpContext(db, { intent: \"task.delete\", group: \"new\" }, () =>\n deleteTaskImpl(db, localId, workstream, opts),\n );\n}\n\nfunction deleteTaskImpl(\n db: Db,\n localId: string,\n workstream: string,\n opts: DeleteTaskOptions,\n): DeleteTaskResult {\n const dryRun = opts.dryRun === true;\n const before = getTask(db, localId, workstream);\n if (!before) {\n // Idempotent on a missing row regardless of dryRun.\n return {\n deleted: false,\n deletedEdges: 0,\n deletedNotes: 0,\n dryRun,\n present: false,\n group: null,\n };\n }\n const taskId = taskIdFor(db, localId, before.workstreamName);\n if (taskId === null) {\n return {\n deleted: false,\n deletedEdges: 0,\n deletedNotes: 0,\n dryRun,\n present: false,\n group: null,\n };\n }\n const edgesBefore = (\n db\n .prepare(\"SELECT COUNT(*) AS n FROM task_edges WHERE from_task_id = ? OR to_task_id = ?\")\n .get(taskId, taskId) as { n: number }\n ).n;\n const notesBefore = (\n db.prepare(\"SELECT COUNT(*) AS n FROM task_notes WHERE task_id = ?\").get(taskId) as {\n n: number;\n }\n ).n;\n const revision = taskRevision(db, before.workstreamName, localId);\n if (dryRun) {\n return {\n deleted: false,\n deletedEdges: edgesBefore,\n deletedNotes: notesBefore,\n dryRun: true,\n present: true,\n group: null,\n revision,\n };\n }\n assertTaskRevision(\n db,\n before.workstreamName,\n localId,\n opts.ifRevision,\n `mu task delete ${localId} -w ${before.workstreamName}`,\n );\n // No pre-mutation snapshot: v9 dropped the `snapshots` table and\n // history is the ops log.\n const result = db.prepare(\"DELETE FROM tasks WHERE id = ?\").run(taskId);\n // No emitEvent: the DELETE fired the capture trigger, which wrote a\n // tombstone op (op='del', intent='task.delete').\n const deleted = result.changes > 0;\n return {\n deleted,\n deletedEdges: edgesBefore,\n deletedNotes: notesBefore,\n dryRun: false,\n present: true,\n // deleteTask opened a fresh group around this call.\n group: deleted ? currentOpContext(db).groupId : null,\n revision,\n };\n}\n\nexport interface UpdateTaskOptions {\n title?: string;\n /** 1..100; enforced by schema CHECK. */\n impact?: number;\n /** > 0; enforced by schema CHECK. */\n effortDays?: number;\n}\n\nexport interface UpdateTaskResult {\n /** True iff at least one field actually changed. */\n updated: boolean;\n /** The fields whose values differ post-update (in `UpdateTaskOptions`'s\n * camelCase shape). Empty when `updated: false`. */\n changedFields: string[];\n}\n\n/**\n * Update scalar fields on a task. Each option is independently optional;\n * passing none is a typed no-op (returns `updated: false, changedFields: []`).\n * Fields whose new value equals the current value are skipped (no row change).\n *\n * NOT for status (use `closeTask` / `openTask` / `setTaskStatus`), owner\n * (use `claimTask` / `releaseTask`), local_id (rename is deferred), or\n * workstream (cross-workstream moves are deferred).\n */\nexport interface UpdateTaskScopeOption {\n workstream: string;\n}\n\nexport function updateTask(\n db: Db,\n localId: string,\n opts: UpdateTaskOptions,\n scope: UpdateTaskScopeOption,\n): UpdateTaskResult {\n return withOpContext(db, { intent: \"task.update\", group: \"new\" }, () =>\n updateTaskImpl(db, localId, opts, scope),\n );\n}\n\nfunction updateTaskImpl(\n db: Db,\n localId: string,\n opts: UpdateTaskOptions,\n scope: UpdateTaskScopeOption,\n): UpdateTaskResult {\n const before = getTask(db, localId, scope.workstream);\n if (!before) throw new TaskNotFoundError(localId, scope.workstream);\n const taskId = taskIdFor(db, before.name, before.workstreamName);\n if (taskId === null) throw new TaskNotFoundError(localId, before.workstreamName);\n\n const setters: string[] = [];\n const params: unknown[] = [];\n const changedFields: string[] = [];\n\n if (opts.title !== undefined && opts.title !== before.title) {\n setters.push(\"title = ?\");\n params.push(opts.title);\n changedFields.push(\"title\");\n }\n if (opts.impact !== undefined && opts.impact !== before.impact) {\n setters.push(\"impact = ?\");\n params.push(opts.impact);\n changedFields.push(\"impact\");\n }\n if (opts.effortDays !== undefined && opts.effortDays !== before.effortDays) {\n setters.push(\"effort_days = ?\");\n params.push(opts.effortDays);\n changedFields.push(\"effortDays\");\n }\n // Giving impact or effort scores the task, even at the value it already\n // has (an unscored task's 50 / 1 are defaults, not a judgement).\n if ((opts.impact !== undefined || opts.effortDays !== undefined) && !before.scored) {\n setters.push(\"scored = 1\");\n changedFields.push(\"scored\");\n }\n\n if (setters.length === 0) {\n return { updated: false, changedFields: [] };\n }\n\n setters.push(\"updated_at = ?\");\n params.push(new Date().toISOString());\n params.push(taskId);\n\n // No emitEvent: the UPDATE fired the capture trigger, whose payload is\n // a semantic partial update naming exactly the changed columns —\n // strictly more useful than the prose \"(changed: a, b)\" it replaces.\n db.prepare(`UPDATE tasks SET ${setters.join(\", \")} WHERE id = ?`).run(...params);\n return { updated: true, changedFields };\n}\n","// mu — task lifecycle verbs: setTaskStatus, closeTask, openTask.\n//\n// Lifecycle = \"transition a task from one status to another, with\n// the right captured-op and evidence-note side effects\".\n//\n// EvidenceOption is shared with claim/release (in tasks/claim.ts) and\n// re-exported here as the canonical home; claim.ts imports from this\n// file.\n\nimport { GUARD_NEEDS_EVIDENCE, GUARD_OPEN_BLOCKERS } from \"../capture.js\";\nimport type { Db, NoteKind } from \"../db.js\";\nimport { withOpContext } from \"../op-context.js\";\nimport { taskIdFor } from \"./core.js\";\nimport { getTaskEdgesWithStatus } from \"./edges.js\";\nimport { addNote, insertNote, writerContext } from \"./edit.js\";\nimport {\n CloseNeedsEvidenceError,\n HumanTaskError,\n InvalidSubstateError,\n SubstateReasonRequiredError,\n TaskHasOpenBlockersError,\n TaskNotFoundError,\n TaskParkStateError,\n} from \"./errors.js\";\nimport { getTask, listNotes } from \"./queries.js\";\nimport {\n DEFAULT_SUBSTATE,\n isValidPair,\n type TASK_SUBSTATES,\n type TaskStatus,\n type TaskSubstate,\n} from \"./status.js\";\n\nexport interface SetStatusResult {\n /** Status before the call. */\n previousStatus: TaskStatus;\n /** Status after the call (== requested status). */\n status: TaskStatus;\n /** Substate before the call. */\n previousSubstate: TaskSubstate;\n /** Substate after the call (== requested substate, or the status default). */\n substate: TaskSubstate;\n /** True iff status OR substate changed. False on idempotent no-op. */\n changed: boolean;\n}\n\n/** The substates a task can be closed as (`mu task close --as`). */\nexport type CloseSubstate = (typeof TASK_SUBSTATES)[\"CLOSED\"][number];\n\n/**\n * Optional evidence string carried on lifecycle verbs (close / open /\n * claim / release). Lands in the auto-emitted `kind='event'` payload\n * verbatim, prefixed with `evidence=`. The first inch of distinguishing\n * \"observed\" from \"claimed\" state per an internal critique: the\n * verb still trusts the caller (it's not a verifier), but the audit\n * trail records what the caller said it relied on.\n */\nexport interface EvidenceOption {\n evidence?: string;\n}\n\n/** Evidence plus the actor its note is attributed to. The CLI passes\n * `resolveActorIdentity()`; without it the note has no author and\n * renders as `<orchestrator>`. */\nexport interface AttributedEvidence extends EvidenceOption {\n author?: string;\n}\n\n/**\n * Persist `--evidence` as a task note, so it survives as a captured op.\n *\n * mu once put evidence in the prose event payload AND (for close only) in a\n * synthetic note. v2-retire-log-shim deleted the prose events, which\n * would have silently dropped evidence on open/release. The note is now\n * the single home for it: notes are portable and sync, whereas the prose\n * event was machine-local and unparseable.\n *\n * Only fires when the verb actually changed something (an idempotent\n * re-close attests nothing new) and the evidence is a non-empty string.\n */\nexport function recordEvidenceNote(\n db: Db,\n localId: string,\n workstream: string,\n label: string,\n opts: AttributedEvidence | undefined,\n): void {\n if (!opts || opts.evidence === undefined || opts.evidence === \"\") return;\n const noteOpts: { author?: string; workstream: string } = { workstream };\n if (opts.author !== undefined && opts.author !== \"\") noteOpts.author = opts.author;\n addNote(db, localId, `${label}: ${opts.evidence}`, noteOpts);\n}\n\nexport interface SetStatusOptions extends EvidenceOption {\n workstream: string;\n /** Substate to land on; defaults to DEFAULT_SUBSTATE[status]. A pair\n * outside TASK_SUBSTATES throws InvalidSubstateError before any write. */\n substate?: TaskSubstate;\n}\n\n/**\n * Flip a task's status to any of OPEN / IN_PROGRESS / CLOSED, writing\n * status and substate in ONE UPDATE (one op, one HLC — spec D7).\n * Idempotent: setting a task to its current pair is a no-op (returns\n * `changed: false`) rather than throwing. Owner is unchanged.\n */\nexport function setTaskStatus(\n db: Db,\n localId: string,\n status: TaskStatus,\n opts: SetStatusOptions,\n): SetStatusResult {\n // NOTE: no `group` here, so a nested call inherits the enclosing\n // group. A direct call with no enclosing context still gets its own\n // group (withOpContext mints one).\n //\n // `intentIfUnset` (not `intent`): when reached via closeTask, the\n // outer verb is the label the operator recognises, so it must win.\n // Only a direct setTaskStatus call labels itself.\n return withOpContext(db, { intentIfUnset: `task.set-${status.toLowerCase()}` }, () =>\n setTaskStatusImpl(db, localId, status, opts),\n );\n}\n\nfunction setTaskStatusImpl(\n db: Db,\n localId: string,\n status: TaskStatus,\n opts: SetStatusOptions,\n): SetStatusResult {\n const before = getTask(db, localId, opts.workstream);\n if (!before) throw new TaskNotFoundError(localId, opts.workstream);\n // A human task is never ready: every way back to OPEN lands it in parked.\n const substate =\n before.kind === \"human\" && status === \"OPEN\"\n ? \"parked\"\n : (opts.substate ?? DEFAULT_SUBSTATE[status]);\n if (!isValidPair(status, substate)) throw new InvalidSubstateError(status, substate);\n const base = {\n previousStatus: before.status,\n status,\n previousSubstate: before.substate,\n substate,\n };\n if (before.status === status && before.substate === substate) {\n return { ...base, changed: false };\n }\n // v5: tasks.local_id is per-workstream unique. Scope to the row's\n // workstream so the UPDATE doesn't accidentally touch a same-named\n // task in another workstream.\n try {\n db.prepare(\n `UPDATE tasks SET status = ?, substate = ?, updated_at = ?\n WHERE local_id = ?\n AND workstream_id = (SELECT id FROM workstreams WHERE name = ?)`,\n ).run(status, substate, new Date().toISOString(), localId, before.workstreamName);\n } catch (err) {\n throw mapCloseGuard(db, err, localId, before.workstreamName);\n }\n // No emitEvent: the UPDATE fired the capture trigger, whose intent is\n // the specific verb (task.close / task.open, or task.set-<status> for\n // a bare status set) and whose payload names the new status. Evidence,\n // when passed, lands as a task note — itself a captured op.\n return { ...base, changed: true };\n}\n\n/** Turn the local-write close guards' RAISE (src/capture.ts) into typed\n * errors; anything else is returned unchanged for the caller to throw.\n * Matches the exact message better-sqlite3 carries. */\nfunction mapCloseGuard(db: Db, err: unknown, localId: string, workstream: string): unknown {\n const msg = err instanceof Error ? err.message : \"\";\n if (msg === GUARD_NEEDS_EVIDENCE) return new CloseNeedsEvidenceError(localId, workstream);\n if (msg === GUARD_OPEN_BLOCKERS) {\n const ids = openBlockerIds(db, localId, workstream);\n return new TaskHasOpenBlockersError(localId, workstream, ids);\n }\n return err;\n}\n\n/** Local ids of the task's direct blockers that are not CLOSED, sorted. */\nfunction openBlockerIds(db: Db, localId: string, workstream: string): string[] {\n const id = taskIdFor(db, localId, workstream);\n if (id === null) return [];\n const rows = db\n .prepare(\"SELECT blocker_local_id AS name FROM blockers WHERE task_id = ? ORDER BY 1\")\n .all(id) as { name: string }[];\n return rows.map((r) => r.name);\n}\n\n/** Result of `closeTask` when called with `ifReady: true` and the\n * task is NOT yet ready to close (still has at least one OPEN /\n * IN_PROGRESS blocker). Distinguished from a regular `SetStatusResult`\n * by the literal `skipped` field; the CLI keys on it to switch\n * between the \"closed\" and \"waiting\" rendering paths.\n *\n * A wave umbrella\n * with N blockers stayed OPEN after every blocker reached a terminal\n * status. `--if-ready` is the cheap fix: bare `mu task close` is\n * unchanged (closes regardless), `--if-ready` is a no-op unless every\n * blocker is CLOSED. */\nexport interface CloseSkippedResult {\n /** Always 'not_ready' when set; future cause-codes can extend this\n * without reshaping the JSON payload (the literal-union narrows\n * safely in the CLI rendering path). */\n skipped: \"not_ready\";\n /** Status before the call (always the current status, no change). */\n previousStatus: TaskStatus;\n /** Status after the call (== previousStatus, since we no-op). */\n status: TaskStatus;\n /** Substate before (and after) the call. */\n previousSubstate: TaskSubstate;\n substate: TaskSubstate;\n /** Always false on a skip (no row mutated). */\n changed: false;\n /** Local ids of every blocker still in OPEN or IN_PROGRESS, sorted\n * alphabetically for deterministic rendering. Empty list is\n * impossible on this branch — the no-op only fires when ≥1\n * blocker is non-terminal. */\n blockingIds: string[];\n}\n\nexport interface CloseTaskOptions extends EvidenceOption {\n workstream: string;\n /** When true, no-op the close unless every blocker is CLOSED.\n * Returns a `CloseSkippedResult` carrying the still-blocking ids.\n * When false / omitted, behaves as bare `closeTask`\n * (closes regardless of blocker status). */\n ifReady?: boolean;\n /** Optional actor identity attributed to the synthetic `CLOSE: …`\n * note auto-inserted when `evidence` is non-empty (see closeTask\n * body). The CLI resolves this via `resolveActorIdentity()` so the\n * note carries the closing worker's name; SDK callers (tests,\n * internal use) may omit it (the note then carries no author, same\n * as a bare `addNote` without `--author`). Surfaced in mufeedback\n * task_close_evidence_does_not_append_the. */\n author?: string;\n /** Closing substate; default \"done\" (or, for an already-CLOSED task,\n * its current substate). Any CLOSED/* satisfies edges. */\n as?: CloseSubstate;\n /** The worker's report, stored verbatim as a `report` note BEFORE the\n * close notes and the status put, in the same op group. NOT evidence:\n * a `done` close still needs `evidence`. Skipped on a no-op close. */\n report?: string;\n /** 'new' (default): the close is its own op group. 'inherit': report,\n * close notes and status put join the CALLER's group, actor and intent\n * (no new op context), so a caller's group holds the whole close. */\n group?: \"new\" | \"inherit\";\n /** Required (non-empty) unless `as` is \"done\"; stored as a\n * `<AS>: <why>` note (kind 'close') in the same op group. */\n why?: string;\n // `evidence` (from EvidenceOption): required for `as: \"done\"` (a close\n // to done without it throws CloseNeedsEvidenceError before any write);\n // optional otherwise, where the `why` note is the close's evidence.\n}\n\n/** Result of a close that ran (not skipped). */\nexport interface CloseTaskResult extends SetStatusResult {\n /** Direct same-workstream dependents that entered the `ready` view\n * because of this close, sorted. Computed only when `as` is not\n * \"done\" (spec D3: a non-done close must show what it released);\n * always [] for a done close. */\n unblocked: string[];\n}\n\n/** Convenience: setTaskStatus(db, id, \"CLOSED\"). Accepts evidence.\n * Notes are skipped for the idempotent no-op (already CLOSED with the\n * same substate; a bare close without `as` keeps the current one) so\n * retry loops don't accumulate duplicates.\n *\n * With `ifReady: true`, returns a `CloseSkippedResult` (no mutation,\n * no snapshot) when any blocker is still OPEN / IN_PROGRESS. Used by\n * `mu task close --if-ready` so an orchestrator can fire-and-forget\n * the umbrella close after every blocker resolves without first\n * re-querying the graph. */\nexport function closeTask(\n db: Db,\n localId: string,\n opts: CloseTaskOptions,\n): CloseTaskResult | CloseSkippedResult {\n // Validate before any write (and before withOpContext mints a group).\n const as = opts.as ?? \"done\";\n if (!isValidPair(\"CLOSED\", as)) throw new InvalidSubstateError(\"CLOSED\", as);\n if (as !== \"done\" && (opts.why === undefined || opts.why.trim() === \"\")) {\n throw new SubstateReasonRequiredError(\"close\", as, localId);\n }\n return withOpContext(db, writerContext(db, \"task.close\", opts.author, opts.group), () =>\n closeTaskImpl(db, localId, opts),\n );\n}\n\nfunction closeTaskImpl(\n db: Db,\n localId: string,\n opts: CloseTaskOptions,\n): CloseTaskResult | CloseSkippedResult {\n const before = getTask(db, localId, opts.workstream);\n // A bare re-close (no --as) of an already-CLOSED task keeps its\n // substate, so it stays the idempotent no-op the help promises\n // instead of rewriting wontfix/rejected/duplicate to done.\n const as: CloseSubstate =\n opts.as ?? (before?.status === \"CLOSED\" ? (before.substate as CloseSubstate) : \"done\");\n const alreadyThere = before?.status === \"CLOSED\" && before.substate === as;\n const evidence = (opts.evidence ?? \"\").trim() === \"\" ? undefined : opts.evidence;\n if (opts.ifReady && before) {\n // Inspect direct blockers only — the umbrella convention is one\n // hop (umbrella -[blocked-by]→ each wave task). If any direct\n // blocker is not CLOSED, the umbrella isn't ready.\n const edges = getTaskEdgesWithStatus(db, localId, before.workstreamName);\n const blocking = edges.blockers\n .filter((e) => e.status !== \"CLOSED\")\n .map((e) => e.name)\n .sort();\n if (blocking.length > 0) {\n return {\n skipped: \"not_ready\",\n previousStatus: before.status,\n status: before.status,\n previousSubstate: before.substate,\n substate: before.substate,\n changed: false,\n blockingIds: blocking,\n };\n }\n }\n // A close to done attests the work happened: it needs evidence. Checked\n // before any write (and after the --if-ready skip, which writes nothing),\n // so the typed error leaves nothing behind. A no-op retry of an\n // already-done close attests nothing new and needs none.\n if (before && !alreadyThere && as === \"done\" && evidence === undefined) {\n throw new CloseNeedsEvidenceError(localId, before.workstreamName);\n }\n // No pre-mutation snapshot: v9 dropped the `snapshots` table and\n // history is the ops log.\n return db\n .transaction((): CloseTaskResult => {\n const track = as !== \"done\" && before !== undefined;\n const readyBefore = track ? readyDependents(db, localId, before.workstreamName) : [];\n // Notes FIRST: the close-evidence guard (src/capture.ts) wants a\n // `kind = 'close'` note in this op group by the time the status\n // UPDATE runs. They join the verb's group via insertNote. A close\n // that turns out to be a no-op writes none (`alreadyThere`).\n if (before && !alreadyThere) {\n if (opts.report !== undefined && opts.report.trim() !== \"\") {\n const reportOpts: { author?: string; workstream: string; kind: \"report\" } = {\n workstream: before.workstreamName,\n kind: \"report\",\n };\n if (opts.author !== undefined && opts.author !== \"\") reportOpts.author = opts.author;\n insertNote(db, localId, opts.report, reportOpts, false);\n }\n // touch=false: the status UPDATE below bumps updated_at in this group.\n recordReasonNote(\n db,\n localId,\n before.workstreamName,\n as,\n opts.why,\n opts.author,\n \"close\",\n false,\n );\n // mufeedback task_close_evidence_does_not_append_the: evidence must\n // reach `mu task notes <id>` / `mu task show <id>`, not just the log.\n // Since v2-retire-log-shim the note is the ONLY home for it.\n if (evidence !== undefined) {\n const noteOpts: { author?: string; workstream: string; kind: \"close\" } = {\n workstream: before.workstreamName,\n kind: \"close\",\n };\n if (opts.author !== undefined && opts.author !== \"\") noteOpts.author = opts.author;\n insertNote(db, localId, `CLOSE: ${evidence}`, noteOpts, false);\n }\n }\n const r = setTaskStatus(db, localId, \"CLOSED\", { workstream: opts.workstream, substate: as });\n if (!r.changed || !before) return { ...r, unblocked: [] };\n const unblocked = track\n ? readyDependents(db, localId, before.workstreamName).filter(\n (n) => !readyBefore.includes(n),\n )\n : [];\n return { ...r, unblocked };\n })\n .immediate();\n}\n\n/** Direct dependents of `localId` currently in the `ready` view, sorted.\n * Edges never cross workstreams, so these are all in `workstream`. */\nfunction readyDependents(db: Db, localId: string, workstream: string): string[] {\n const id = taskIdFor(db, localId, workstream);\n if (id === null) return [];\n const rows = db\n .prepare(\n `SELECT r.local_id AS name FROM task_edges e\n JOIN ready r ON r.id = e.to_task_id\n WHERE e.from_task_id = ? ORDER BY r.local_id`,\n )\n .all(id) as { name: string }[];\n return rows.map((r) => r.name);\n}\n\n/** Store a classification's `--why` as a `<SUBSTATE>: <why>` note\n * (e.g. `WONTFIX: out of scope`). Notes are captured, so it syncs,\n * and it lands in the enclosing verb's op group. No-op for an empty\n * reason (a done close needs none). */\nfunction recordReasonNote(\n db: Db,\n localId: string,\n workstream: string,\n substate: TaskSubstate,\n why: string | undefined,\n author: string | undefined,\n kind: NoteKind = \"note\",\n touch = true,\n): void {\n if (why === undefined || why.trim() === \"\") return;\n const noteOpts: { author?: string; workstream: string; kind: NoteKind } = { workstream, kind };\n if (author !== undefined && author !== \"\") noteOpts.author = author;\n const text =\n substate === \"rejected\" || substate === \"superseded\"\n ? withTitles(db, why, workstream, localId)\n : why;\n // insertNote, not addNote: the note joins the verb's group and\n // intent instead of minting its own, so both share one group.\n insertNote(db, localId, `${substate.toUpperCase()}: ${text}`, noteOpts, touch);\n}\n\n/** A token shaped like a task id, not inside a word, path, or file\n * name: never preceded by a word char, `.`, `/` or `-`, and never\n * followed by an extension (`fix.ts`) or a line number (`fix:12`). */\nconst TASK_ID_TOKEN = /(?<![\\w./-])[a-z][a-z0-9_-]{0,63}(?![\\w-]|\\.\\w|:\\d)/g;\n\n/** {@link TASK_ID_TOKEN}, plus an optional parenthetical opener right\n * after it (group 1), so the title can merge into it. */\nconst TASK_ID_WITH_PAREN = new RegExp(`(?:${TASK_ID_TOKEN.source})(\\\\s*\\\\()?`, \"g\");\n\n/** Ids in `text` naming another task in `workstream`. */\nfunction namedTaskIds(db: Db, text: string, workstream: string, self: string): string[] {\n const ids = (text.match(TASK_ID_TOKEN) ?? []).filter((t) => t !== self);\n return [...new Set(ids)].filter((t) => getTask(db, t, workstream) !== undefined);\n}\n\n/** Append each named task's title after its id, so a REJECTED /\n * SUPERSEDED note reads without looking the ids up: `f2 (title)`.\n * An id already followed by a parenthetical (the skill's REJECT form\n * `<id> (<why it fails>)`) gets one merged parenthetical instead:\n * `f2 (title; why it fails)`. Text that names no task in the\n * workstream is left as is. */\nfunction withTitles(db: Db, why: string, workstream: string, self: string): string {\n const named = new Set(namedTaskIds(db, why, workstream, self));\n if (named.size === 0) return why;\n return why.replace(TASK_ID_WITH_PAREN, (match: string, paren: string | undefined) => {\n const id = paren === undefined ? match : match.slice(0, -paren.length);\n if (!named.has(id)) return match;\n const title = getTask(db, id, workstream)?.title ?? \"\";\n return paren === undefined ? `${id} (${title})` : `${id} (${title}; `;\n });\n}\n\n/** Below this many characters a decision reason names no check. */\nexport const WEAK_REASON_CHARS = 40;\n\n/** A note line recording a verdict: `VERDICT: …`, or the header\n * `REFUTER <label> (...)` a recorded delegate answer starts with. */\nconst VERDICT_LINE = /^\\s*(VERDICT:|REFUTER\\s)/m;\n\n/**\n * Decision-time guardrail for a finding. Returns one warning (or\n * none) for accepting a task in triage (`kind: \"accept\"`, reason =\n * `--evidence`) or closing it as rejected / wontfix / duplicate\n * (reason = `--why`). Warns only when the task is OPEN/triage, the\n * reason is missing or under {@link WEAK_REASON_CHARS} chars, and no\n * note records a verdict. A duplicate whose reason names an existing\n * task is fine. Read-only: call it before the verb writes.\n */\nexport function weakDecisionWarning(\n db: Db,\n localId: string,\n workstream: string,\n kind: \"accept\" | CloseSubstate,\n reason: string | undefined,\n): string | undefined {\n if (kind === \"done\" || kind === \"superseded\") return undefined;\n const task = getTask(db, localId, workstream);\n if (task?.status !== \"OPEN\" || task.substate !== \"triage\") return undefined;\n const trimmed = (reason ?? \"\").trim();\n if (trimmed.length >= WEAK_REASON_CHARS) return undefined;\n if (kind === \"duplicate\" && namedTaskIds(db, trimmed, workstream, localId).length > 0) {\n return undefined;\n }\n if (listNotes(db, localId, workstream).some((n) => VERDICT_LINE.test(n.content))) {\n return undefined;\n }\n const flag = kind === \"accept\" ? \"--evidence\" : \"--why\";\n const what = trimmed === \"\" ? `no ${flag}` : `${flag} is ${trimmed.length} chars`;\n return `${localId}: ${kind === \"accept\" ? \"accepting\" : `closing as ${kind}`} a finding with ${what} and no verdict recorded (no VERDICT: line or REFUTER note); record what confirmed it`;\n}\n\n/** Convenience: setTaskStatus(db, id, \"OPEN\"). Owner intentionally NOT\n * cleared — use `releaseTask` for that. Accepts evidence. */\nexport function openTask(\n db: Db,\n localId: string,\n opts: AttributedEvidence & { workstream: string },\n): SetStatusResult {\n return withOpContext(db, { intent: \"task.open\", actor: opts.author, group: \"new\" }, () => {\n const before = getTask(db, localId, opts.workstream);\n const r = setTaskStatus(db, localId, \"OPEN\", {\n workstream: opts.workstream,\n ...(opts.evidence !== undefined ? { evidence: opts.evidence } : {}),\n });\n if (r.changed && before) recordEvidenceNote(db, localId, before.workstreamName, \"OPEN\", opts);\n return r;\n });\n}\n\nexport interface ParkTaskOptions extends EvidenceOption {\n workstream: string;\n /** Required, non-empty; stored as a `PARKED: <why>` note. */\n why: string;\n author?: string;\n}\n\n/**\n * OPEN/todo → OPEN/parked: keep the task out of `ready` / `next` and\n * make `claim` refuse it without `--force`. Its dependents stay blocked\n * (parked is still OPEN). Idempotent on OPEN/parked (no second note).\n * Refuses IN_PROGRESS (release first) and CLOSED (open first) — one\n * verb, one transition.\n */\nexport function parkTask(db: Db, localId: string, opts: ParkTaskOptions): SetStatusResult {\n if (opts.why.trim() === \"\") throw new SubstateReasonRequiredError(\"park\", \"parked\", localId);\n return withOpContext(db, { intent: \"task.park\", actor: opts.author, group: \"new\" }, () =>\n db\n .transaction((): SetStatusResult => {\n const before = getTask(db, localId, opts.workstream);\n if (!before) throw new TaskNotFoundError(localId, opts.workstream);\n if (before.status !== \"OPEN\") {\n throw new TaskParkStateError(localId, before.status, before.workstreamName);\n }\n const r = setTaskStatus(db, localId, \"OPEN\", {\n workstream: opts.workstream,\n substate: \"parked\",\n });\n if (r.changed) {\n recordReasonNote(db, localId, before.workstreamName, \"parked\", opts.why, opts.author);\n recordEvidenceNote(db, localId, before.workstreamName, \"PARK\", opts);\n }\n return r;\n })\n .immediate(),\n );\n}\n\n/**\n * OPEN/triage → OPEN/todo: accept a proposed task (a review finding) as\n * real work, back in `ready` / `next`. A no-op (`changed: false`) on any\n * other pair. Declining is `close --as rejected | duplicate --why`.\n */\nexport function acceptTask(\n db: Db,\n localId: string,\n opts: AttributedEvidence & { workstream: string },\n): SetStatusResult {\n return withOpContext(db, { intent: \"task.accept\", actor: opts.author, group: \"new\" }, () =>\n db\n .transaction((): SetStatusResult => {\n const before = getTask(db, localId, opts.workstream);\n if (!before) throw new TaskNotFoundError(localId, opts.workstream);\n if (before.status !== \"OPEN\" || before.substate !== \"triage\") {\n return {\n previousStatus: before.status,\n status: before.status,\n previousSubstate: before.substate,\n substate: before.substate,\n changed: false,\n };\n }\n const r = setTaskStatus(db, localId, \"OPEN\", { workstream: opts.workstream });\n recordEvidenceNote(db, localId, before.workstreamName, \"ACCEPT\", opts);\n return r;\n })\n .immediate(),\n );\n}\n\n/** OPEN/parked → OPEN/todo. A no-op (`changed: false`) on any other pair. */\nexport function unparkTask(\n db: Db,\n localId: string,\n opts: AttributedEvidence & { workstream: string },\n): SetStatusResult {\n return withOpContext(db, { intent: \"task.unpark\", actor: opts.author, group: \"new\" }, () =>\n db\n .transaction((): SetStatusResult => {\n const before = getTask(db, localId, opts.workstream);\n if (!before) throw new TaskNotFoundError(localId, opts.workstream);\n if (before.kind === \"human\")\n throw new HumanTaskError(before.name, before.workstreamName, \"unpark\");\n if (before.status !== \"OPEN\" || before.substate !== \"parked\") {\n return {\n previousStatus: before.status,\n status: before.status,\n previousSubstate: before.substate,\n substate: before.substate,\n changed: false,\n };\n }\n const r = setTaskStatus(db, localId, \"OPEN\", { workstream: opts.workstream });\n recordEvidenceNote(db, localId, before.workstreamName, \"UNPARK\", opts);\n return r;\n })\n .immediate(),\n );\n}\n","// mu — claim/release/resolveActorIdentity verbs.\n//\n// claimTask is the heart of mu's coordination protocol: an atomic\n// CAS via a single SQL UPDATE, with two flavours:\n//\n// \"worker claim\" : --for <name> sets owner_id to that agent (FK to agents.id)\n// \"anonymous claim\": --self keeps owner_id=NULL but flips status to\n// IN_PROGRESS and records the actor\n// in the ops log (ops.actor)\n//\n// resolveActorIdentity is the env-aware identity helper:\n// $MU_AGENT_NAME > $USER > 'orchestrator'. Used by --self\n// AND by the bare worker-claim path, so both flavours answer \"who am\n// I?\" identically.\n\nimport { GUARD_ALREADY_OWNED } from \"../capture.js\";\nimport type { Db } from \"../db.js\";\nimport { say } from \"../messages.js\";\nimport { withOpContext } from \"../op-context.js\";\nimport { assertTaskRevision } from \"../revision.js\";\nimport {\n ClaimerNotRegisteredError,\n HumanTaskError,\n TaskAlreadyOwnedError,\n TaskInTriageError,\n TaskNotFoundError,\n TaskParkedError,\n} from \"./errors.js\";\nimport { type AttributedEvidence, recordEvidenceNote } from \"./lifecycle.js\";\nimport { getTask } from \"./queries.js\";\nimport { DEFAULT_SUBSTATE, type TaskStatus } from \"./status.js\";\n\nexport interface ReleaseResult {\n /** The previous owner (null if the task was already unowned). */\n previousOwnerName: string | null;\n /** Status before the release. */\n previousStatus: TaskStatus;\n /** Status after the release. */\n status: TaskStatus;\n /** True iff owner OR status actually changed. */\n changed: boolean;\n}\n\nexport interface ReleaseTaskOptions extends AttributedEvidence {\n /** `--if <rev>`: the task's revision from `mu task show`. A stale one\n * throws `RevisionMismatchError` before any write. */\n ifRevision?: number;\n /** Workstream context for the task (v5: tasks.local_id is\n * per-workstream unique). */\n workstream: string;\n /** Force `status = OPEN` regardless of the current status. Without\n * this flag, `IN_PROGRESS` is also flipped to `OPEN` automatically\n * (so a released task isn't left structurally stranded with\n * `owner=NULL, status=IN_PROGRESS`); CLOSED is preserved.\n * `--reopen` is the override for the rarer \"un-close and hand\n * back to the pool\" workflow. */\n reopen?: boolean;\n /**\n * Rollback guard: release only while the task is STILL owned by this\n * registry agent id (`agents.id`) and not CLOSED, decided inside one\n * immediate transaction. A task another agent now owns, that was\n * released, or that was closed meanwhile is left alone (`changed: false`).\n */\n expectedOwnerId?: number;\n}\n\n/**\n * Release a task: clear `tasks.owner`.\n *\n * Status side-effects:\n * - IN_PROGRESS → OPEN automatically (without it, the task is\n * stranded: no owner to drive it forward, but `mu task next`\n * skips it because it's not OPEN).\n * - OPEN / CLOSED preserved.\n * - `--reopen` forces OPEN regardless of current status — the\n * escape hatch for un-closing a CLOSED owned task in one verb.\n *\n * Idempotent: releasing an already-unowned task with no `--reopen` and\n * no IN_PROGRESS status is a no-op (returns `changed: false`).\n * Throws TaskNotFoundError on missing.\n */\nexport function releaseTask(db: Db, localId: string, opts: ReleaseTaskOptions): ReleaseResult {\n return withOpContext(db, { intent: \"task.release\", actor: opts.author, group: \"new\" }, () =>\n releaseTaskImpl(db, localId, opts),\n );\n}\n\nfunction releaseTaskImpl(db: Db, localId: string, opts: ReleaseTaskOptions): ReleaseResult {\n if (opts.expectedOwnerId === undefined) return releaseTaskBody(db, localId, opts);\n // Check and write in ONE immediate transaction: nothing can re-own the task between.\n return db.transaction(() => releaseTaskBody(db, localId, opts)).immediate();\n}\n\nfunction releaseTaskBody(db: Db, localId: string, opts: ReleaseTaskOptions): ReleaseResult {\n const before = getTask(db, localId, opts.workstream);\n if (!before) throw new TaskNotFoundError(localId, opts.workstream);\n assertTaskRevision(db, before.workstreamName, localId, opts.ifRevision);\n if (\n opts.expectedOwnerId !== undefined &&\n (before.ownerId !== opts.expectedOwnerId || before.status === \"CLOSED\")\n ) {\n return {\n previousOwnerName: before.ownerName,\n previousStatus: before.status,\n status: before.status,\n changed: false,\n };\n }\n\n // Default: auto-flip IN_PROGRESS → OPEN so the released task isn't\n // left in the structurally weird owner=NULL/IN_PROGRESS limbo.\n // --reopen still wins for any status (including CLOSED).\n const newStatus: TaskStatus = opts.reopen\n ? \"OPEN\"\n : before.status === \"IN_PROGRESS\"\n ? \"OPEN\"\n : before.status;\n const ownerChanges = before.ownerName !== null;\n const statusChanges = newStatus !== before.status;\n\n if (!ownerChanges && !statusChanges) {\n return {\n previousOwnerName: before.ownerName,\n previousStatus: before.status,\n status: before.status,\n changed: false,\n };\n }\n\n // No pre-mutation snapshot: v9 dropped the `snapshots` table and\n // history is the ops log.\n\n db.prepare(\n `UPDATE tasks SET owner_id = NULL, status = ?, substate = ?, updated_at = ?\n WHERE local_id = ?\n AND workstream_id = (SELECT id FROM workstreams WHERE name = ?)`,\n ).run(\n newStatus,\n statusChanges\n ? before.kind === \"human\" && newStatus === \"OPEN\"\n ? \"parked\" // a human task is never ready\n : DEFAULT_SUBSTATE[newStatus]\n : before.substate,\n new Date().toISOString(),\n localId,\n before.workstreamName,\n );\n // No emitEvent: the UPDATE fired the capture trigger\n // (intent='task.release'), whose payload names owner_id and status —\n // the same facts the prose spelled out. Evidence goes to a note,\n // since the prose payload that used to carry it is gone.\n recordEvidenceNote(db, localId, before.workstreamName, \"RELEASE\", opts);\n return {\n previousOwnerName: before.ownerName,\n previousStatus: before.status,\n status: newStatus,\n changed: true,\n };\n}\n\n// ─── claimTask (verb) ──────────────────────────────────────────────────\n\nexport interface ClaimTaskOptions extends AttributedEvidence {\n /** `--if <rev>`: the task's revision from `mu task show`. A stale one\n * throws `RevisionMismatchError` inside the claim transaction, before\n * any write. */\n ifRevision?: number;\n /** Workstream context for both the task and the claiming agent.\n * v5: agents.name and tasks.local_id are per-workstream unique;\n * the task lookup AND the agent FK lookup scope to this\n * workstream so a same-named task or worker elsewhere can't be\n * silently picked. The CLI always passes this from the resolved\n * -w or the injected worker scope. */\n workstream: string;\n /**\n * Override the agent name. If omitted, resolved from the ambient\n * environment via `resolveWorkerIdentity()`: `$MU_AGENT_NAME` only\n * (spawn injects it; pane titles are not identity).\n *\n * Mutually exclusive with `self: true`.\n */\n agentName?: string;\n /**\n * Workstream that the claimer agent lives in. When omitted, defaults\n * to `opts.workstream` (today's same-workstream behaviour). Set by\n * the CLI when `mu task claim X -w A --for B/worker-1` qualifies the\n * `--for` ref with a different workstream prefix\n * (`task_claim_for_cross_workstream`).\n *\n * Cross-workstream ownership is structurally allowed by the schema:\n * `tasks.owner_id` is an INTEGER FK to `agents.id` with no\n * workstream qualifier on the agent side. The per-workstream UNIQUE\n * on `agents(workstream_id, name)` is what previously made the\n * SDK's name → id lookup scope to one workstream; this option\n * widens that lookup to a different workstream when the operator\n * dispatches across a workstream boundary. The agent's own\n * workstream remains unchanged — only the task's `owner_id` points\n * out-of-workstream.\n */\n agentWorkstream?: string;\n /**\n * The registry id (`agents.id`) the caller created or validated for\n * `agentName`. Re-checked INSIDE the immediate claim transaction: when the\n * name now belongs to another incarnation (deleted and recreated), the\n * claim throws ClaimerNotRegisteredError and the replacement never owns\n * the task. Absent: the name is resolved as before.\n */\n expectedAgentId?: number;\n /**\n * Anonymous claim: write `owner_id = NULL` instead of resolving an agent\n * name and checking the FK. Use when the actor is the orchestrator\n * (or a script, or a human) doing direct work in a workstream they\n * aren't a registered worker in.\n *\n * The actor name is still recorded — it ends up in `ops.actor` of\n * the captured `task.claim` op — so provenance is preserved.\n * Just not in the FK column.\n *\n * Resolution order for the actor name (used as the log source):\n * 1. `actor` if explicitly passed.\n * 2. `$MU_AGENT_NAME`.\n * 3. `$USER`.\n * 4. The literal string 'orchestrator'.\n *\n * Mutually exclusive with `agentName` (the two are alternative\n * answers to \"who's the actor for this claim?\"). Passing both is a\n * usage error.\n */\n self?: boolean;\n /**\n * Override the actor name used for the log source when `self: true`.\n * Ignored when `self: false`. Useful when the orchestrator wants to\n * attribute the work to a meaningful name rather than the pane\n * title (e.g. \"deploy-bot\" rather than \"pi-mu\").\n */\n actor?: string;\n /**\n * Claim an OPEN/parked task anyway. Without it, a parked task throws\n * TaskParkedError before any write: parking means \"keep out of the\n * scheduler\", so overriding it must be explicit.\n */\n force?: boolean;\n}\n\nexport interface ClaimResult {\n /** The agent now owning the task, or null when the claim was anonymous (--self). */\n ownerName: string | null;\n /** The actor recorded in the claim op — the agent name for a\n * registered-worker claim, or the resolved actor for --self. */\n actorName: string;\n /** The previous owner (null if it was unowned). */\n previousOwnerName: string | null;\n /** The status BEFORE the claim; post-claim is IN_PROGRESS unless was CLOSED. */\n previousStatus: TaskStatus;\n /** The status AFTER the claim. */\n status: TaskStatus;\n}\n\n/**\n * Claim a task. Two modes:\n *\n * Worker claim (default):\n * Resolve an agent name from `opts.agentName`, else $MU_AGENT_NAME,\n * else fails. The name\n * MUST exist in the agents table (`tasks.owner_id` is an FK to\n * `agents.id`). Sets `owner_id` to that agent. This is what mu-spawned\n * workers do, and what `mu task claim --for <worker>` does for\n * orchestrator dispatch.\n *\n * Anonymous claim (--self):\n * Skip the name -> agents FK lookup entirely. Sets `owner_id = NULL`.\n * Records the actor in `ops.actor` instead. This is the\n * orchestrator-doing-direct-work path — the actor is logged but\n * not registered as a worker pane.\n *\n * Status side-effect: OPEN -> IN_PROGRESS; IN_PROGRESS / CLOSED unchanged.\n *\n * Concurrency: the worker-claim path uses a single-statement CAS UPDATE\n * with `WHERE owner IS NULL OR owner = ?` so two workers racing to\n * claim the same task can't both win. The anonymous path uses\n * `WHERE owner IS NULL` (anonymous claims don't 'own' the task in any\n * exclusive sense; if it's already owned by anyone, the anonymous claim\n * is a TaskAlreadyOwnedError just like a worker claim would be).\n */\nexport async function claimTask(\n db: Db,\n localId: string,\n opts: ClaimTaskOptions,\n): Promise<ClaimResult> {\n // claimTask is async (it shells out to tmux to resolve the caller's\n // identity), and withOpContext is deliberately sync — see its doc\n // comment. So set the context around the SYNCHRONOUS mutation legs\n // inside, not around the whole async function.\n return claimTaskImpl(db, localId, opts);\n}\n\nasync function claimTaskImpl(\n db: Db,\n localId: string,\n opts: ClaimTaskOptions,\n): Promise<ClaimResult> {\n if (opts.self === true && opts.agentName !== undefined) {\n throw new Error(say(\"task.claim_self_and_for\"));\n }\n\n if (opts.self === true) {\n return claimSelf(db, localId, opts);\n }\n\n // ── Worker claim path (registered agent owns the task) ──\n const agentName = opts.agentName ?? (await resolveWorkerIdentity());\n if (!agentName) {\n throw new Error(say(\"task.claim_no_agent\"));\n }\n\n // Resolve the claiming agent to its surrogate id within the agent's\n // workstream — defaults to opts.workstream (today's same-ws path),\n // or opts.agentWorkstream when the CLI dispatched across a\n // workstream boundary via a qualified `--for <ws>/<name>` ref\n // (task_claim_for_cross_workstream).\n //\n // The schema permits cross-workstream owner_id assignment (FK to\n // agents.id only); the per-workstream UNIQUE on agents.name is the\n // only reason this SELECT was scoped narrowly before. Bare-name\n // dispatch keeps that scope to honour today's behaviour; qualified\n // dispatch widens it to the named workstream so the agent resolves\n // there.\n const claimerWorkstream = opts.agentWorkstream ?? opts.workstream;\n const claimerRow = db\n .prepare(\n `SELECT a.id AS id\n FROM agents a JOIN workstreams ws ON ws.id = a.workstream_id\n WHERE a.name = ? AND ws.name = ?`,\n )\n .get(agentName, claimerWorkstream) as { id: number } | undefined;\n if (!claimerRow) {\n const paneIdFromEnv = opts.agentName === undefined ? (process.env.TMUX_PANE ?? null) : null;\n throw new ClaimerNotRegisteredError(agentName, paneIdFromEnv);\n }\n\n return withOpContext(db, { intent: \"task.claim\", actor: agentName, group: \"new\" }, () =>\n db\n .transaction(() => {\n // Resolve the task within opts.workstream. This locks the\n // (workstream, local_id) pair for the rest of the transaction.\n const before = getTask(db, localId, opts.workstream);\n if (!before) throw new TaskNotFoundError(localId, opts.workstream);\n assertTaskRevision(db, before.workstreamName, localId, opts.ifRevision);\n assertNotParked(before, opts);\n // The name was resolved before this transaction began: re-read it now\n // and refuse an incarnation the caller did not mean.\n if (opts.expectedAgentId !== undefined) {\n const current = db\n .prepare(\n `SELECT a.id AS id FROM agents a JOIN workstreams ws ON ws.id = a.workstream_id\n WHERE a.name = ? AND ws.name = ?`,\n )\n .get(agentName, claimerWorkstream) as { id: number } | undefined;\n if (current?.id !== opts.expectedAgentId) {\n throw new ClaimerNotRegisteredError(agentName, null);\n }\n }\n\n const now = new Date().toISOString();\n let result: { changes: number };\n try {\n result = db\n .prepare(\n `UPDATE tasks\n SET owner_id = ?,\n status = CASE WHEN status = 'OPEN' THEN 'IN_PROGRESS' ELSE status END,\n -- SQLite evaluates every SET expression against the OLD\n -- row, so this CASE still sees the pre-claim status.\n substate = CASE WHEN status = 'OPEN' THEN 'active' ELSE substate END,\n updated_at = ?\n WHERE local_id = ?\n AND workstream_id = (SELECT id FROM workstreams WHERE name = ?)\n AND (owner_id IS NULL OR owner_id = ?)`,\n )\n .run(claimerRow.id, now, localId, opts.workstream, claimerRow.id);\n } catch (err) {\n // The DB-side CAS (`_cap_tasks_claim_cas`) backs the WHERE above.\n if (err instanceof Error && err.message === GUARD_ALREADY_OWNED) {\n throw new TaskAlreadyOwnedError(localId, before.ownerName ?? \"<unknown>\");\n }\n throw err;\n }\n\n if (result.changes === 0) {\n throw new TaskAlreadyOwnedError(localId, before.ownerName ?? \"<unknown>\");\n }\n\n const after = getTask(db, localId, opts.workstream);\n if (!after) throw new Error(`claimTask: row missing after update: ${localId}`);\n // The CLAIM note's author: the dispatcher when the CLI passed one\n // (`--for`), else the claiming agent.\n recordEvidenceNote(db, localId, opts.workstream, \"CLAIM\", {\n ...opts,\n author: opts.author ?? agentName,\n });\n // No emitEvent: the UPDATE fired the capture trigger under\n // intent='task.claim' with actor=agentName (withOpContext above\n // put it in op_ctx, and the trigger copies it into ops.actor).\n // The op payload carries the new owner_id; no prose\n // breadcrumb is written. `lastClaimActor` reads ops.actor.\n return {\n ownerName: agentName,\n actorName: agentName,\n previousOwnerName: before.ownerName,\n previousStatus: before.status,\n status: after.status,\n };\n })\n .immediate(),\n );\n}\n\n/** The parked-claim guard shared by the worker and --self paths. The\n * UPDATE's `status = 'OPEN'` CASE already maps parked → active, so a\n * forced claim needs nothing else. */\nfunction assertNotParked(\n task: {\n name: string;\n kind: string;\n status: TaskStatus;\n substate: string;\n workstreamName: string;\n },\n opts: ClaimTaskOptions,\n): void {\n if (task.kind === \"human\") throw new HumanTaskError(task.name, task.workstreamName, \"claim\");\n if (task.status === \"OPEN\" && task.substate === \"parked\" && opts.force !== true) {\n throw new TaskParkedError(task.name, task.workstreamName);\n }\n if (task.status === \"OPEN\" && task.substate === \"triage\" && opts.force !== true) {\n throw new TaskInTriageError(task.name, task.workstreamName);\n }\n}\n\n/**\n * Resolve the current actor's identity for attribution in task notes,\n * --self claims, and any other write that wants 'who did this?'.\n *\n * Resolution order:\n * 1. $MU_AGENT_NAME env var (set by mu spawnAgent on every managed\n * pane; surfaced from the f3d4bdd commit). Authoritative when\n * present — you're inside a mu-spawned worker, no ambiguity.\n * 2. $USER (when running outside a mu pane entirely).\n * 3. The literal 'orchestrator' as a last-resort default.\n *\n * The env var is set per-pane at spawn time and is unforgeable from\n * outside without explicit `--actor` override. Pane titles are not\n * identity: nothing reads or writes them.\n */\nexport async function resolveActorIdentity(): Promise<string> {\n const worker = await resolveWorkerIdentity();\n if (worker !== undefined) return worker;\n const user = process.env.USER;\n if (user !== undefined && user !== \"\") return user;\n return \"orchestrator\";\n}\n\n/**\n * The AGENT-identity half of the ladder, shared by `resolveActorIdentity`\n * and the bare worker-claim path. Returns undefined when the caller\n * isn't identifiable as a specific agent — the two callers disagree\n * about what to do then, which is why this stops short rather than\n * falling through to `$USER`:\n *\n * - `resolveActorIdentity` continues to `$USER` / 'orchestrator',\n * because an anonymous claim only needs an attribution string.\n * - the worker-claim path THROWS, because `tasks.owner_id` is a real\n * FK to `agents.id` and '$USER' is not an agent. Falling back there\n * would turn a clear \"who are you?\" error into a confusing\n * ClaimerNotRegisteredError naming the operator's unix login.\n *\n * Identity is `$MU_AGENT_NAME`, injected into every pane by spawnAgent.\n * It is backend-independent and unforgeable from outside the pane, and\n * the only source: pane titles are not identity.\n */\nexport async function resolveWorkerIdentity(): Promise<string | undefined> {\n const muAgent = process.env.MU_AGENT_NAME;\n return muAgent !== undefined && muAgent !== \"\" ? muAgent : undefined;\n}\n\nasync function claimSelf(db: Db, localId: string, opts: ClaimTaskOptions): Promise<ClaimResult> {\n const actor =\n opts.actor !== undefined && opts.actor !== \"\" ? opts.actor : await resolveActorIdentity();\n return withOpContext(db, { intent: \"task.claim\", actor, group: \"new\" }, () =>\n db\n .transaction(() => {\n // Scope by the operator's workstream so a same-named task\n // elsewhere can't be self-claimed by accident.\n const before = getTask(db, localId, opts.workstream);\n if (!before) throw new TaskNotFoundError(localId, opts.workstream);\n assertTaskRevision(db, before.workstreamName, localId, opts.ifRevision);\n assertNotParked(before, opts);\n\n // Anonymous claim: owner stays NULL, status flips OPEN -> IN_PROGRESS.\n // Gate on `owner_id IS NULL` so an in-flight worker claim can't be\n // silently overwritten.\n const now = new Date().toISOString();\n const result = db\n .prepare(\n `UPDATE tasks\n SET status = CASE WHEN status = 'OPEN' THEN 'IN_PROGRESS' ELSE status END,\n substate = CASE WHEN status = 'OPEN' THEN 'active' ELSE substate END,\n updated_at = ?\n WHERE local_id = ?\n AND workstream_id = (SELECT id FROM workstreams WHERE name = ?)\n AND owner_id IS NULL`,\n )\n .run(now, localId, before.workstreamName);\n\n if (result.changes === 0) {\n // Task exists but is already owned (by someone). Mirror the\n // worker-path error so callers can pattern-match consistently.\n throw new TaskAlreadyOwnedError(localId, before.ownerName ?? \"<unknown>\");\n }\n\n const after = getTask(db, localId, before.workstreamName);\n if (!after) throw new Error(`claimTask: row missing after update: ${localId}`);\n recordEvidenceNote(db, localId, before.workstreamName, \"CLAIM\", {\n ...opts,\n author: opts.author ?? actor,\n });\n // No emitEvent. This is the interesting case: the `--self` path\n // leaves tasks.owner_id NULL deliberately, so the op PAYLOAD\n // cannot name the actor — but ops.actor can and does, because\n // withOpContext seeded op_ctx with it. That is precisely what\n // `lastClaimActor` needs, and reading a column beats\n // prefix-matching prose.\n return {\n ownerName: null,\n actorName: actor,\n previousOwnerName: before.ownerName,\n previousStatus: before.status,\n status: after.status,\n };\n })\n .immediate(),\n );\n}\n","// mu — abort: stop a pi agent's current turn through its control socket.\n//\n// status → abort → wait(afterRuns). The wait keys on the run counter the\n// extension bumps on agent_settled, so an abort that settles before the\n// wait connects still resolves at once. An agent that is not busy gets no\n// abort at all: the verb is idempotent.\n//\n// interruptAgent (`mu agent send --interrupt`) is abort + send as one\n// ctl op with a msgId receipt; an extension without msgId is refused up\n// front (AgentExtensionOutdatedError), never half-served.\n\nimport { getAgent } from \"../agents.js\";\nimport { type CtlState, INCARNATION_MISMATCH } from \"../ctl/protocol.js\";\nimport type { Db } from \"../db.js\";\nimport { emitEvent } from \"../logs.js\";\nimport { say } from \"../messages.js\";\nimport { resolveActorIdentity } from \"../tasks/claim.js\";\nimport {\n AgentAbortNeedsCtlError,\n AgentAbortTimeoutError,\n AgentEmptySendError,\n AgentNotFoundError,\n AgentReplacedError,\n AgentRestartedError,\n} from \"./errors.js\";\nimport {\n agentCtlSocket,\n ctlSendWithReceipt,\n expectsCtl,\n fencedHello,\n recordSend,\n ctlRequestFor as request,\n} from \"./transport.js\";\n\nexport const DEFAULT_ABORT_TIMEOUT_MS = 30_000;\n\nexport type AbortResult = {\n agent: string;\n workstream: string;\n before: CtlState;\n after: CtlState;\n /** True when pi settled (or was never busy). */\n settled: boolean;\n /** False when the agent was not busy, so no abort was sent. */\n aborted: boolean;\n /** pi had queued messages before the abort (pi returns them to the editor). */\n pending: boolean;\n elapsedMs: number;\n};\n\nexport type AbortAgentOptions = {\n workstream: string;\n timeoutMs?: number;\n /** Control socket path. Default: derived from the agent's identity. */\n socket?: string;\n /** interrupt only: the ctl incarnation the caller saw; another pi is refused (AgentReplacedError). */\n expectIncarnation?: string;\n};\n\nexport async function abortAgent(\n db: Db,\n name: string,\n opts: AbortAgentOptions,\n): Promise<AbortResult> {\n const agent = getAgent(db, name, opts.workstream);\n if (!agent) throw new AgentNotFoundError(name, opts.workstream);\n const sock = opts.socket ?? agentCtlSocket(db, agent);\n if (!expectsCtl(agent, sock)) throw new AgentAbortNeedsCtlError(name, opts.workstream, agent.cli);\n const timeoutMs = opts.timeoutMs ?? DEFAULT_ABORT_TIMEOUT_MS;\n const started = Date.now();\n const base = { agent: name, workstream: opts.workstream };\n\n const st = await request(agent, sock, { op: \"status\" });\n if (!st.ok) throw new Error(say(\"agent.ctl_refused\", \"status\", st.error));\n const before = st.state ?? \"idle\";\n const pending = st.pending ?? false;\n if (before !== \"busy\") {\n return {\n ...base,\n before,\n after: before,\n settled: true,\n aborted: false,\n pending,\n elapsedMs: Date.now() - started,\n };\n }\n\n const ab = await request(agent, sock, { op: \"abort\" });\n if (!ab.ok) throw new Error(say(\"agent.ctl_refused\", \"the abort\", ab.error));\n // Only a real abort is logged. wasBusy=false: the run settled between the\n // status probe and the abort, so pi did nothing. Absent: older extension.\n const aborted = ab.wasBusy !== false;\n if (aborted) {\n emitEvent(\n db,\n opts.workstream,\n \"agent.abort\",\n `agent abort ${name} (state=${before}, pending=${pending})`,\n await resolveActorIdentity(),\n );\n }\n\n // The incarnation the status named: a pi that restarted since is another\n // process, whose run count means nothing here.\n const w = await request(agent, sock, {\n op: \"wait\",\n afterRuns: st.runs ?? 0,\n timeoutMs,\n ...(st.incarnation !== undefined ? { incarnation: st.incarnation } : {}),\n });\n if (!w.ok) {\n if (w.error === INCARNATION_MISMATCH && st.incarnation !== undefined) {\n throw new AgentRestartedError(name, opts.workstream, st.incarnation, w.incarnation);\n }\n if (w.error === \"timeout\") throw new AgentAbortTimeoutError(name, opts.workstream, timeoutMs);\n throw new Error(say(\"agent.ctl_refused\", \"the wait\", w.error));\n }\n return {\n ...base,\n before,\n after: w.state ?? \"idle\",\n settled: true,\n aborted,\n pending,\n elapsedMs: Date.now() - started,\n };\n}\n\nexport type InterruptResult = {\n /** pi was busy, so its turn was aborted before the send. */\n wasBusy: boolean;\n /** pi had queued messages before the abort; pi put them back in the pane's editor. */\n pending: boolean;\n /**\n * pi's run count after the aborted run settled and before the send: the\n * `mu agent wait --after-runs` baseline for the run the text starts.\n */\n runs?: number;\n /** The id the interrupt carried: `mu agent check <agent> <msgId>` asks whether it landed. */\n msgId: string;\n /** pi's incarnation: the `--inc` for `mu agent wait`. */\n incarnation?: string;\n /** Set when the reply never arrived and `status {msgId}` confirmed the interrupt landed. */\n receipt?: \"confirmed-after-timeout\";\n};\n\n/**\n * Make a pi agent act on `text` now: abort a running turn, wait for pi to\n * settle (AgentAbortTimeoutError after timeoutMs, text not sent), then\n * send `text` as a new run. Never pastes: non-pi agents get\n * AgentAbortNeedsCtlError.\n */\nexport async function interruptAgent(\n db: Db,\n name: string,\n text: string,\n opts: AbortAgentOptions,\n): Promise<InterruptResult> {\n const r = await interruptAgentImpl(db, name, text, opts);\n recordSend(\n db,\n { name, workstreamName: opts.workstream },\n \"interrupt\",\n Buffer.byteLength(text),\n { transport: \"ctl\", wasBusy: r.wasBusy },\n await resolveActorIdentity(),\n );\n return r;\n}\n\nasync function interruptAgentImpl(\n db: Db,\n name: string,\n text: string,\n opts: AbortAgentOptions,\n): Promise<InterruptResult> {\n const agent = getAgent(db, name, opts.workstream);\n if (!agent) throw new AgentNotFoundError(name, opts.workstream);\n // Refuse before the abort: an empty prompt would kill the running turn\n // and then send nothing. Here, not only in the CLI, so SDK callers get it.\n if (text === \"\") throw new AgentEmptySendError(name, opts.workstream);\n const sock = opts.socket ?? agentCtlSocket(db, agent);\n if (!expectsCtl(agent, sock)) throw new AgentAbortNeedsCtlError(name, opts.workstream, agent.cli);\n const timeoutMs = opts.timeoutMs ?? DEFAULT_ABORT_TIMEOUT_MS;\n const { inc, bound } = await fencedHello(agent, sock, {\n feature: \"msgId\",\n needsFence: true,\n ...(opts.expectIncarnation !== undefined ? { expect: opts.expectIncarnation } : {}),\n });\n const sent = await ctlSendWithReceipt(\n agent,\n sock,\n { op: \"interrupt\", text, timeoutMs, ...bound },\n inc,\n );\n const { reply: r, msgId } = sent;\n if (r === undefined) {\n // Written, no reply, but status {msgId} says pi took it: wasBusy and\n // pending are unknown, so they read false.\n const c = sent.confirmed;\n return {\n wasBusy: false,\n pending: false,\n msgId,\n receipt: \"confirmed-after-timeout\",\n ...(c?.runs !== undefined ? { runs: c.runs } : {}),\n ...(c?.incarnation !== undefined ? { incarnation: c.incarnation } : {}),\n };\n }\n if (!r.ok) {\n if (r.error === INCARNATION_MISMATCH)\n throw new AgentReplacedError(name, opts.workstream, \"sent to\");\n if (r.error === \"timeout\") throw new AgentAbortTimeoutError(name, opts.workstream, timeoutMs);\n throw new Error(say(\"agent.ctl_refused\", \"the interrupt\", r.error));\n }\n return {\n wasBusy: r.wasBusy ?? false,\n pending: r.pending ?? false,\n msgId,\n ...(r.runs !== undefined ? { runs: r.runs } : {}),\n ...(r.incarnation !== undefined ? { incarnation: r.incarnation } : {}),\n };\n}\n","// mu — the remote half of `agent spawn --host` (docs/VOCABULARY.md § remote worker).\n//\n// The PANE is the transport. The local pane runs the profile's filled `shell`\n// template, which starts the remote pi and forwards its ctl socket to the\n// derived LOCAL path; pane death is agent death, exactly as for a local agent\n// (reconcile, close and teardown need no remote case). mu never connects: every\n// remote effect here is the user's `exec` template running one short command.\n//\n// Order, all under ONE channel lease (spawn.ts holds it; at cap 1 the lease is\n// never released between steps, and an exec is reaped before the shell opens):\n// prepare (exec: resolve the cwd, or make a detached worktree) -> placeholder\n// row claims the name -> pane opens (the lease is bound to its id + pane) ->\n// ctl handshake through the forward.\n// Rollback removes only what this spawn made: the remote worktree is removed\n// only while it is still clean and still at the recorded base.\n\nimport type { AgentRow } from \"./agents.js\";\nimport { remoteCtlSocketPath } from \"./ctl/path.js\";\nimport type { Db } from \"./db.js\";\nimport {\n expandHostTemplate,\n type HostLease,\n type HostProfile,\n hostEnvWords,\n remotePathWord,\n runHostTemplate,\n runLeasedTemplate,\n withHostChannel,\n} from \"./hosts.js\";\nimport { say } from \"./messages.js\";\nimport { activeMux } from \"./mux.js\";\nimport { shellQuote, shellWord } from \"./shell-quote.js\";\nimport type { ReleasedWorktree } from \"./worktree.js\";\n\n/** A remote exec step failed or answered nothing mu can use. Exit 5 (substrate). */\nexport class RemotePrepareError extends Error {\n override readonly name = \"RemotePrepareError\";\n constructor(\n public readonly host: string,\n what: string,\n detail: string,\n ) {\n super(say(\"remote.prepare\", host, what, detail));\n }\n}\n\n/** Budget for the one remote step that may clone-sized work (a worktree add). */\nexport const REMOTE_PREPARE_TIMEOUT_MS = 120_000;\n\nconst firstLine = (s: string): string =>\n s\n .split(\"\\n\")\n .find((l) => l.trim() !== \"\")\n ?.trim() ?? \"\";\n\n/** A remote `sh -c` script as the one word the exec template's `{cmd}` carries. */\nconst script = (body: string): string => `sh -c ${shellQuote(body)}`;\n\n/** Where a remote worktree lives: under the remote user's state dir, never inside the repo. */\nfunction remoteWorktreeWord(workstream: string, name: string): string {\n return `\"$HOME\"/.local/state/mu-next/remote-worktrees/${shellWord(workstream)}/${shellWord(name)}`;\n}\n\nexport interface RemoteSite {\n /** The remote working directory the agent starts in (absolute). */\n cwd: string;\n /** The commit a worktree was made at; null without `--worktree`. */\n base: string | null;\n /** The absolute toplevel of the repo the worktree was added to; null without `--worktree`. */\n repo: string | null;\n}\n\n/** The file in a remote worktree's own git dir that says mu's prepare made it (`git worktree remove` takes it along). */\nconst PREPARED_MARK = \"mu-prepared\";\n\n/**\n * Remote lines reclaiming the tree at `$wt` (exit 4 with the reason, else fall\n * through): only mu's own unused leftover, the one a lost answer leaves. It\n * carries the prepare mark, is a worktree of `$root`, is clean and at `$base`,\n * and nothing has its cwd or an open file in it (the close rule's scan).\n */\nfunction reclaimLines(): string[] {\n return [\n `fail() { echo \"$wt already exists and is not an unused mu leftover ($*)\" >&2; exit 4; }`,\n `gd=$(git -C \"$wt\" rev-parse --absolute-git-dir 2>/dev/null) || fail \"not a git worktree\"`,\n `[ -f \"$gd/${PREPARED_MARK}\" ] || fail \"not made by mu\"`,\n `[ \"$(git -C \"$wt\" rev-parse --path-format=absolute --git-common-dir)\" = \"$(git -C \"$root\" rev-parse --path-format=absolute --git-common-dir)\" ] || fail \"not a worktree of $root\"`,\n `[ \"$(git -C \"$wt\" rev-parse --verify HEAD)\" = \"$base\" ] || fail \"HEAD is not $base\"`,\n `st=$(git -C \"$wt\" status --porcelain) || fail \"git status failed\"`,\n `[ -z \"$st\" ] || fail \"uncommitted work\"`,\n `aside=\"$wt\"`,\n ...quiescenceLines({ proc: \"/proc\", lsof: \"lsof\" }),\n ];\n}\n\n/**\n * The remote half of a spawn, under `lease`: with `worktree`, one exec makes a\n * detached `git worktree add` of `from` (default the repo's HEAD) at a fixed\n * path, marks it as prepare's own, and prints its base and absolute path;\n * otherwise one exec resolves the cwd (`cwd`, default the profile's repo; a\n * leading `~` expands remotely). The answer is a tagged line, because a login\n * shell may print noise first; no answer is an error, never a guessed path.\n *\n * A tree already at the path refuses, unless `reclaim` and it is the unused\n * leftover of an earlier prepare whose answer was lost (`reclaimLines`): that\n * one is answered as if just made, so a retry of the spawn takes it over.\n */\nexport async function prepareRemote(\n db: Db,\n lease: HostLease,\n profile: HostProfile,\n opts: {\n workstream: string;\n name: string;\n worktree: boolean;\n from?: string;\n cwd?: string;\n /** May a leftover at the path be reclaimed (false while a recovery record names it). */\n reclaim?: boolean;\n /** The remote repo: the worktree is added to it, and it is the default cwd without one. */\n root?: string;\n },\n): Promise<RemoteSite> {\n if (opts.worktree && opts.root === undefined) {\n throw new RemotePrepareError(\n profile.name,\n \"creating the remote worktree failed\",\n `host ${profile.name} has no default repo: pass --root <remote repo path>`,\n );\n }\n const root = remotePathWord(opts.root ?? \"~\");\n // The root as an absolute physical path (bare repos too: no --show-toplevel), hex-encoded so\n // no byte of it (a trailing space, a newline) is lost to the line parse. The row records it,\n // and close, rollback and recovery run against it.\n const answer = [\n `r=$(cd \"$root\" && pwd -P) || exit 5`,\n `printf 'MU_REPO %s\\\\nMU_WT %s %s\\\\n' \"$(printf '%s' \"$r\" | od -An -v -tx1 | tr -d ' \\\\n')\" \"$base\" \"$(cd \"$wt\" && pwd -P)\"`,\n ].join(\"\\n\");\n const body = opts.worktree\n ? [\n `root=${root}`,\n `wt=${remoteWorktreeWord(opts.workstream, opts.name)}`,\n `base=$(git -C \"$root\" rev-parse --verify ${shellQuote(`${opts.from ?? \"HEAD\"}^{commit}`)}) || exit 5`,\n opts.reclaim === true\n ? `if [ -e \"$wt\" ]; then\\n${reclaimLines().join(\"\\n\")}\\n${answer}\\nexit 0\\nfi`\n : `[ ! -e \"$wt\" ] || { echo \"$wt already exists\" >&2; exit 4; }`,\n `mkdir -p \"$(dirname \"$wt\")\" || exit 6`,\n `undo() { git -C \"$root\" worktree remove --force \"$wt\" >/dev/null 2>&1; rm -rf \"$wt\"; exit 7; }`,\n `git -C \"$root\" worktree add --detach \"$wt\" \"$base\" >&2 || undo`,\n `gd=$(git -C \"$wt\" rev-parse --absolute-git-dir) && : > \"$gd/${PREPARED_MARK}\" || undo`,\n answer,\n ].join(\"\\n\")\n : `cd ${remotePathWord(opts.cwd ?? opts.root ?? \"~\")} && printf 'MU_CWD %s\\\\n' \"$(pwd -P)\"`;\n const r = await runLeasedTemplate(\n db,\n lease,\n profile,\n \"exec\",\n // `.`, not `~`, without a repo: a template's `cd {cwd:sh}` stays where the login shell\n // started (a quoted `~` never expands); the script itself resolves --cwd and \"$HOME\".\n { cmd: script(body), cwd: opts.root ?? \".\" },\n REMOTE_PREPARE_TIMEOUT_MS,\n );\n const what = opts.worktree\n ? \"creating the remote worktree failed\"\n : \"the remote cwd is unreachable\";\n // No answer after the exec may have made the tree: say how a retry takes it over.\n const lost = opts.worktree\n ? `; if it made the worktree, spawning ${opts.name} again reclaims it while it is unused`\n : \"\";\n if (r.exitCode === null) {\n throw new RemotePrepareError(\n profile.name,\n what,\n `timed out after ${REMOTE_PREPARE_TIMEOUT_MS}ms${lost}`,\n );\n }\n if (r.exitCode !== 0) {\n const why = firstLine(r.stderr) || firstLine(r.stdout);\n throw new RemotePrepareError(\n profile.name,\n what,\n `exit ${r.exitCode}${why === \"\" ? \"\" : `: ${why}`}`,\n );\n }\n const lines = r.stdout.split(\"\\n\").map((l) => l.trim());\n if (opts.worktree) {\n const repo = decodeRepo(\n [...lines]\n .reverse()\n .find((l) => /^MU_REPO [0-9a-f]+$/.test(l))\n ?.slice(\"MU_REPO \".length),\n );\n for (const l of lines.reverse()) {\n const m = /^MU_WT ([0-9a-f]{40,64}) (\\/.+)$/.exec(l);\n if (m?.[1] !== undefined && m[2] !== undefined && repo !== undefined) {\n return { cwd: m[2], base: m[1], repo };\n }\n }\n } else {\n for (const l of lines.reverse()) {\n const m = /^MU_CWD (\\/.+)$/.exec(l);\n if (m?.[1] !== undefined) return { cwd: m[1], base: null, repo: null };\n }\n }\n throw new RemotePrepareError(profile.name, what, `the host's answer named no path${lost}`);\n}\n\n/** The hex-encoded absolute path of a `MU_REPO` line, or undefined when it is not one. */\nfunction decodeRepo(hex: string | undefined): string | undefined {\n if (hex === undefined || hex.length % 2 !== 0) return undefined;\n const path = Buffer.from(hex, \"hex\").toString(\"utf8\");\n return path.startsWith(\"/\") ? path : undefined;\n}\n\n/**\n * Remove a remote worktree THIS spawn made: only while it is still clean and\n * still at `base`, proven by git commands that exited 0 (a failing one is\n * unknown, never clean); anything else is left for the user and said so on stderr.\n * Best-effort, one exec under its own channel (the caller has already freed\n * the pane's). Returns whether the tree is proven gone (removed now, or\n * already absent): a tree left alone, or an answer with no `MU_RM` line, is not.\n */\nexport async function removeRemoteWorktree(\n db: Db,\n host: string,\n holder: string,\n wt: { path: string; base: string; root: string },\n): Promise<boolean> {\n const p = shellQuote(wt.path);\n const body = [\n `wt=${p}`,\n `[ -d \"$wt\" ] || { echo \"MU_RM gone\"; exit 0; }`,\n // Any git that fails is unknown, never clean: the tree is left alone.\n `unknown() { echo \"$wt: $1 failed: left alone\" >&2; echo \"MU_RM failed\"; exit 0; }`,\n `head=$(git -C \"$wt\" rev-parse --verify HEAD) || unknown \"git rev-parse HEAD\"`,\n `[ \"$head\" = ${shellQuote(wt.base)} ] || { echo \"$wt is not at its base: left alone\" >&2; echo \"MU_RM moved\"; exit 0; }`,\n `st=$(git -C \"$wt\" status --porcelain) || unknown \"git status\"`,\n `[ -z \"$st\" ] || { echo \"$wt has changes: left alone\" >&2; echo \"MU_RM dirty\"; exit 0; }`,\n // No --force: git re-checks cleanliness itself, so a write that raced the check refuses.\n `git -C ${remotePathWord(wt.root)} worktree remove \"$wt\" && echo \"MU_RM removed\"`,\n ].join(\"\\n\");\n const r = await runHostTemplate(db, host, \"exec\", holder, { cmd: script(body), cwd: wt.root });\n const said = lastMatch(r.stdout, REMOTE_RM_RE)?.[1];\n return r.exitCode === 0 && (said === \"removed\" || said === \"gone\");\n}\n\n/** `agent close` refused to remove a remote worktree: nothing was removed. Exit 4. */\nexport class RemoteCloseRefusedError extends Error {\n override readonly name = \"RemoteCloseRefusedError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n public readonly reason: \"dirty\" | \"uncollected\" | \"moved\" | \"unreadable\" | \"branch\" | \"held\",\n detail: string,\n /** The recovery record being closed (no agent row left): every hint then names it. */\n public readonly recoveryId?: number,\n ) {\n super(say(\"remote.worktree_kept\", agentName, detail));\n }\n}\n\nconst REMOTE_STATE_RE = /^MU_STATE (clean|dirty|gone)(?: ([0-9a-f]{40,64}))?$/;\nconst REMOTE_RM_RE =\n /^MU_RM (removed|gone|moved|dirty|branch-collision|branch-failed|failed|stuck|unproven|held(?: (\\d+))?)$/;\nconst lastMatch = (out: string, re: RegExp): RegExpExecArray | null => {\n for (const l of out.split(\"\\n\").reverse()) {\n const m = re.exec(l.trim());\n if (m !== null) return m;\n }\n return null;\n};\n\n/** Where `closeRemoteWorktree` parks a tree while it proves nothing holds it. */\nexport const asideOf = (path: string, incarnation: number): string =>\n `${path}.mu-removing-${incarnation}`;\n\n/**\n * Remote shell lines proving nothing holds `$aside`: no process of this user\n * has its cwd or an open file at or under it (`fail held <pid>`), and the scan\n * demonstrably ran (it must see this very shell, else `fail unproven`). Reads\n * /proc, else `lsof`, else refuses. With `force` (the caller asserts nothing\n * uses the tree) neither refuses: each is printed as `MU_WARN unproven` /\n * `MU_WARN held <pid>` and the removal goes on. `proc` and `lsof` are test seams.\n */\nfunction quiescenceLines(probe: { proc: string; lsof: string }, force = false): string[] {\n const proc = shellQuote(probe.proc);\n const lsof = shellQuote(probe.lsof);\n // Prints \"H<pid>\" per holder and \"S<pid>\" per process whose cwd it could read.\n const procAwk = `A=\"$aside\" awk 'BEGIN{a=ENVIRON[\"A\"]} { i=index($0,\" -> \"); if (i==0) next; t=substr($0,i+4); n=split(substr($0,1,i-1),f,\" \"); n=split(f[n],q,\"/\"); if (q[n]==\"cwd\") print \"S\" q[n-1]; h=(t==a || index(t,a \"/\")==1); if (h && q[n]==\"cwd\") print \"H\" q[n-1]; else if (h && q[n-1]==\"fd\") print \"H\" q[n-2] }'`;\n const lsofAwk = `A=\"$aside\" awk 'BEGIN{a=ENVIRON[\"A\"]} /^p/{p=substr($0,2)} /^f/{f=substr($0,2)} /^n/{t=substr($0,2); if (f==\"cwd\") print \"S\" p; if (t==a || index(t,a \"/\")==1) print \"H\" p}'`;\n return [\n `scan=`,\n `if [ -d ${proc}/self ]; then scan=$(find ${proc}/[0-9]*/cwd ${proc}/[0-9]*/fd -maxdepth 1 -type l -exec ls -ld {} + 2>/dev/null | ${procAwk})`,\n `elif command -v ${lsof} >/dev/null 2>&1; then scan=$(${lsof} -w -Fpfn 2>/dev/null | ${lsofAwk}); fi`,\n `printf '%s\\\\n' \"$scan\" | grep -qx \"S$$\" || ${force ? \"echo 'MU_WARN unproven'\" : \"fail unproven\"}`,\n force\n ? `printf '%s\\\\n' \"$scan\" | sed -n 's/^H//p' | sort -u | sed 's/^/MU_WARN held /'`\n : `held=$(printf '%s\\\\n' \"$scan\" | sed -n 's/^H//p' | head -n 1); [ -z \"$held\" ] || fail held \"$held\"`,\n ];\n}\n\n/**\n * The close rule for a remote worktree `spawn --host --worktree` made, run\n * AFTER the agent's pane is dead (the caller frees the channel first; at cap 1\n * the pane held it): under one lease, one exec observes the state (clean or\n * dirty, HEAD, and that the path is still a worktree of the repo the row recorded),\n * the rule is applied here, and a second exec removes WITHOUT --force.\n *\n * No git lock fences every ref backend (reftable ignores HEAD.lock), so the\n * removal proves QUIESCENCE instead: the tree is renamed to a fixed aside name\n * (`asideOf`, derived from the registry incarnation, so the intent survives a\n * crash with no record to lose), every writer addressing the old path now\n * fails, and a scan of /proc (else lsof, else refusal) proves no process has\n * its cwd or an open file under the aside. Only then are HEAD and cleanliness\n * re-checked (backend-neutral git commands), the `--keep-branch` branch made\n * create-only, and the tree removed. A holder, a doubt or any mismatch moves\n * the tree back and refuses. A retry after a crash finds the aside, moves it\n * back and runs the whole rule again; `gone` means neither path exists.\n * Never removes dirty files, whatever the flags; a HEAD that is neither the\n * base nor the last collected one refuses unless `keepBranch`, which makes (or\n * verifies) `mu/<ws>/<agent>-<sha12>` at the observed HEAD first.\n */\nexport async function closeRemoteWorktree(\n db: Db,\n agent: Pick<\n AgentRow,\n \"name\" | \"workstreamName\" | \"host\" | \"cwd\" | \"base\" | \"collectedHead\" | \"incarnation\" | \"repo\"\n >,\n opts: {\n keepBranch?: boolean;\n paneAlive?: (paneId: string) => Promise<boolean>;\n /** Runs between the observation and the removal; throws to stop (an identity re-check). */\n beforeRemove?: () => void;\n /** The removed agent's recovery record (src/remote-recovery.ts) when there is no row: refusals name it. */\n recoveryId?: number;\n /** Runs on the ADMITTED profile before any exec; throws to stop (a recovery pins the profile it was made for). */\n checkProfile?: (profile: HostProfile) => void;\n /** Test seam: where the quiescence scan looks (default /proc, then `lsof`). */\n probe?: { proc: string; lsof: string };\n /** Remove past a holder or an unprovable scan (each becomes a warning). Never past dirt or a moved HEAD. */\n force?: boolean;\n } = {},\n): Promise<ReleasedWorktree> {\n const { name, workstreamName: ws, host, cwd: path, base, collectedHead, repo } = agent;\n if (host === null || path === null || base === null || repo === null) {\n throw new Error(say(\"remote.no_worktree\", name));\n }\n const asidePath = asideOf(path, agent.incarnation);\n const probe = opts.probe ?? { proc: \"/proc\", lsof: \"lsof\" };\n const refuse = (reason: RemoteCloseRefusedError[\"reason\"], detail: string): never => {\n throw new RemoteCloseRefusedError(name, ws, reason, detail, opts.recoveryId);\n };\n return withHostChannel(\n db,\n host,\n `close:${ws}/${name}`,\n async (profile, lease) => {\n opts.checkProfile?.(profile);\n const root = shellQuote(repo);\n const wt = shellQuote(path);\n const aside = shellQuote(asidePath);\n const run = async (body: string): Promise<{ out: string; why: string }> => {\n const r = await runLeasedTemplate(\n db,\n lease,\n profile,\n \"exec\",\n { cmd: script(body), cwd: repo },\n REMOTE_PREPARE_TIMEOUT_MS,\n );\n if (r.exitCode === null) refuse(\"unreadable\", `host ${host} timed out`);\n if (r.exitCode !== 0) {\n const why = firstLine(r.stderr) || firstLine(r.stdout);\n refuse(\"unreadable\", `host ${host}: exit ${r.exitCode}${why === \"\" ? \"\" : `: ${why}`}`);\n }\n return { out: r.stdout, why: firstLine(r.stderr) };\n };\n const observed = await run(\n [\n `root=${root}`,\n `wt=${wt}`,\n `aside=${aside}`,\n // A crash after the move leaves the aside: put it back, then judge it as usual.\n `if [ -d \"$aside\" ]; then`,\n ` [ ! -e \"$wt\" ] || { echo \"$aside is parked beside $wt\" >&2; exit 9; }`,\n ` git -C \"$root\" worktree move \"$aside\" \"$wt\" >&2 || { echo \"could not move $aside back to $wt\" >&2; exit 10; }`,\n `fi`,\n `[ -d \"$wt\" ] || { echo 'MU_STATE gone'; exit 0; }`,\n `[ \"$(git -C \"$wt\" rev-parse --path-format=absolute --git-common-dir)\" = \"$(git -C \"$root\" rev-parse --path-format=absolute --git-common-dir)\" ] || { echo \"$wt is not a worktree of $root\" >&2; exit 8; }`,\n `head=$(git -C \"$wt\" rev-parse --verify HEAD) || exit 5`,\n `st=$(git -C \"$wt\" status --porcelain) || exit 6`,\n `if [ -z \"$st\" ]; then s=clean; else s=dirty; fi`,\n `printf 'MU_STATE %s %s\\\\n' \"$s\" \"$head\"`,\n ].join(\"\\n\"),\n );\n const m = lastMatch(observed.out, REMOTE_STATE_RE);\n if (m === null) return refuse(\"unreadable\", `host ${host} named no worktree state`);\n if (m[1] === \"gone\") return { path, action: \"gone\" };\n const head = m[2];\n if (head === undefined) return refuse(\"unreadable\", `host ${host} named no HEAD`);\n const short = head.slice(0, 12);\n if (m[1] === \"dirty\") {\n // A branch keeps commits, not files: no flag overrides this.\n return refuse(\"dirty\", `uncommitted work in ${path}; commit or remove it on the host`);\n }\n const known = head === base || (collectedHead !== null && head === collectedHead);\n if (!known && opts.keepBranch !== true) {\n return refuse(\n \"uncollected\",\n `HEAD ${short} was never collected (base ${base.slice(0, 12)}); collect it, or close with --keep-branch`,\n );\n }\n const branch = known ? undefined : `mu/${ws}/${name}-${short}`;\n opts.beforeRemove?.();\n // Move aside, prove nothing holds the tree, THEN re-check and remove\n // (see the header): a writer that raced the observation either left a\n // changed HEAD or dirt for the re-check, or holds the tree and refuses.\n const removed = await run(\n [\n `root=${root}`,\n `wt=${wt}`,\n `aside=${aside}`,\n `want=${shellQuote(head)}`,\n `[ -d \"$wt\" ] || { if [ -e \"$aside\" ]; then echo \"$aside is parked\" >&2; echo 'MU_RM failed'; else echo 'MU_RM gone'; fi; exit 0; }`,\n `fail() { if [ -d \"$aside\" ] && [ ! -e \"$wt\" ]; then git -C \"$root\" worktree move \"$aside\" \"$wt\" >&2 || { echo 'MU_RM stuck'; exit 0; }; fi; echo \"MU_RM $*\"; exit 0; }`,\n `git -C \"$root\" worktree move \"$wt\" \"$aside\" >&2 || { echo 'MU_RM failed'; exit 0; }`,\n ...quiescenceLines(probe, opts.force === true),\n `[ \"$(git -C \"$aside\" rev-parse --verify HEAD)\" = \"$want\" ] || fail moved`,\n `st=$(git -C \"$aside\" status --porcelain) || fail failed`,\n `[ -z \"$st\" ] || fail dirty`,\n ...(branch === undefined\n ? []\n : [\n `br=${shellQuote(`refs/heads/${branch}`)}`,\n // Create-only (old value \"\"): never moves an existing branch.\n `git -C \"$root\" update-ref \"$br\" \"$want\" \"\" 2>/dev/null || [ \"$(git -C \"$root\" rev-parse --verify -q \"$br\")\" = \"$want\" ] || fail branch-collision`,\n `[ \"$(git -C \"$root\" rev-parse --verify -q \"$br\")\" = \"$want\" ] || fail branch-failed`,\n ]),\n `git -C \"$root\" worktree remove \"$aside\" >&2 || fail failed`,\n `echo 'MU_RM removed'`,\n ].join(\"\\n\"),\n );\n const r = lastMatch(removed.out, REMOTE_RM_RE)?.[1];\n const force = ` close again, or if you know nothing uses it preview with --force: mu agent close ${name} -w ${ws}${opts.recoveryId === undefined ? \"\" : ` --recovery ${opts.recoveryId}`} --force`;\n if (r === \"removed\") {\n const warnings = removed.out\n .split(\"\\n\")\n .map((l) => /^MU_WARN (unproven|held (\\d+))$/.exec(l.trim()))\n .filter((m) => m !== null)\n .map((m) =>\n m[2] === undefined\n ? `host ${host} has neither /proc nor lsof to prove nothing is using ${path}; removed under --force`\n : `process ${m[2]} on ${host} was still inside ${path}; removed under --force`,\n );\n const said = warnings.length > 0 ? { warnings } : {};\n return branch === undefined\n ? { path, action: \"removed\", ...said }\n : { path, action: \"kept-branch\", branch, ...said };\n }\n if (r === \"gone\") return { path, action: \"gone\" };\n if (r === \"moved\")\n return refuse(\"moved\", `HEAD moved while closing (was ${short}); nothing was removed`);\n if (r === \"dirty\")\n return refuse(\"dirty\", `${path} changed while closing; nothing was removed`);\n if (r?.startsWith(\"held\")) {\n const pid = lastMatch(removed.out, REMOTE_RM_RE)?.[2];\n return refuse(\n \"held\",\n `${pid === undefined ? \"a process\" : `process ${pid}`} on ${host} is still inside ${path}; nothing was removed. Stop it and${force}`,\n );\n }\n if (r === \"unproven\") {\n return refuse(\n \"unreadable\",\n `host ${host} has neither /proc nor lsof to prove nothing is using ${path}; nothing was removed. Fix that and${force}`,\n );\n }\n if (r === \"stuck\") {\n return refuse(\n \"unreadable\",\n `could not move ${path} back from ${asidePath}; close again to resume`,\n );\n }\n if (r === \"branch-collision\") {\n return refuse(\n \"branch\",\n `branch ${branch} already exists at another commit; nothing was removed`,\n );\n }\n return refuse(\n r === \"branch-failed\" ? \"branch\" : \"unreadable\",\n `${r === \"branch-failed\" ? `could not make branch ${branch}` : \"git worktree remove failed\"}${removed.why === \"\" ? \"\" : `: ${removed.why}`}; nothing was removed`,\n );\n },\n opts.paneAlive === undefined ? {} : { paneAlive: opts.paneAlive },\n );\n}\n\n/**\n * The local mu variables a transport pane must not carry: a tmux pane inherits\n * the SERVER's env, which may be another agent's (its DB, sync dir, ctl socket,\n * identity). A template that runs `{cmd}` with the local env (a container exec,\n * `SendEnv MU_*`, a shim) would hand them to the remote pi.\n */\nexport const LOCAL_ONLY_ENV = [\n \"MU_DB_PATH\",\n \"MU_STATE_DIR\",\n \"MU_SYNC_DIR\",\n \"MU_CTL_SOCK\",\n \"MU_AGENT_NAME\",\n \"MU_WORKSTREAM\",\n \"MU_MANAGED_AGENT\",\n] as const;\n\n/**\n * The command the LOCAL pane runs: the profile's `shell` template filled with\n * the remote identity (never the local DB, state or sync dir), the user's\n * command and the two socket paths, as one `sh -c` word, run with the local-only mu variables unset.\n */\nexport function remoteShellCommand(\n profile: HostProfile,\n a: { workstream: string; name: string; command: string; localSock: string; cwd: string },\n): string {\n const remoteSock = remoteCtlSocketPath(a.workstream, a.name, process.getuid?.() ?? 0);\n const env = hostEnvWords({\n MU_MANAGED_AGENT: \"1\",\n MU_AGENT_NAME: a.name,\n MU_WORKSTREAM: a.workstream,\n MU_CTL_SOCK: remoteSock,\n MU_REMOTE: \"1\",\n });\n const filled = expandHostTemplate(profile.shell, {\n env,\n cmd: a.command,\n local_sock: a.localSock,\n remote_sock: remoteSock,\n cwd: a.cwd,\n });\n const unset = LOCAL_ONLY_ENV.map((k) => `-u ${k}`).join(\" \");\n return `exec env ${unset} /bin/sh -c ${shellQuote(filled)}`;\n}\n\n/**\n * The local pane's liveness probe for channel admission: unknown (a throw) keeps\n * the channel. A retained pane whose command ended (a gate's transport) is not\n * alive here: it holds no channel on the host, though its handle still exists.\n */\nexport async function localPaneAlive(paneId: string): Promise<boolean> {\n const mux = await activeMux();\n if (mux.paneResult === undefined) return mux.paneAlive(paneId);\n return (await mux.paneResult(paneId)).state === \"running\";\n}\n","// mu — remote recovery: what a deleted remote worker row said about its worktree.\n//\n// A remote agent's row is the only record of where its worktree lives (host,\n// path, base, last collected HEAD). The row dies when its pane is reaped,\n// its workstream is torn down, a peer's tombstone cascades it away, or\n// someone runs SQL. THE DATABASE writes the record: an AFTER DELETE trigger\n// on `agents` (and a BEFORE DELETE one on `workstreams` for the cascade),\n// defined in src/db-recovery.ts, so no deleter can forget and a rolled-back\n// delete rolls the record back too. This module is the reader.\n//\n// One row per ORIGINAL registry incarnation (`agent_id` = `agents.id`, never\n// reused): a name or workstream created again later is a different record,\n// and the exact aside path `closeRemoteWorktree` parks a tree at is derived\n// from that id, so it is stored, never recomputed from a new one. The table\n// has NO foreign key and no op: machine-local, never synced, rebuilt by\n// nothing (src/rebuild.ts reports it lost). Only FINALIZED rows (host, path\n// and base all recorded) are an owned worktree; anything else leaves nothing.\n//\n// Selection and the guards a close or collect passes before it touches the\n// tree live here too (src/agents/close-recovery.ts, src/remote-collect.ts use\n// them); nothing here runs a host command.\n\nimport type { Db } from \"./db.js\";\nimport { say } from \"./messages.js\";\n\n/** Why the row went away: `reap` (any plain delete), a `teardown`, or its workstream's deletion. */\nexport type RemoteRecoveryReason = \"reap\" | \"teardown\" | \"workstream-delete\";\n\nexport interface RemoteRecovery {\n /** The ORIGINAL registry incarnation (`agents.id`). */\n agentId: number;\n workstream: string;\n /** With `workstreamCreatedAt`: which generation of the name the agent lived in. */\n workstreamId: number;\n workstreamCreatedAt: string;\n name: string;\n paneId: string;\n host: string;\n /** The worktree path on the host. */\n cwd: string;\n base: string;\n collectedHead: string | null;\n /** The exact path a crashed close left (or would leave) the tree at. */\n aside: string;\n /** The profile's exec template when it existed, else null: identity, not authority. */\n hostExec: string | null;\n /** The worktree's repo on the host (agents.repo), null when the row had none. */\n hostRepo: string | null;\n reason: RemoteRecoveryReason;\n preservedAt: string;\n}\n\ninterface RawRow {\n agent_id: number;\n workstream: string;\n workstream_id: number;\n workstream_created_at: string;\n name: string;\n pane_id: string;\n host: string;\n cwd: string;\n base: string;\n collected_head: string | null;\n aside: string;\n host_exec: string | null;\n host_repo: string | null;\n reason: RemoteRecoveryReason;\n preserved_at: string;\n}\n\n// ─── Selection: which record a close or collect means ───────────────────────\n\n/** A recovery operation refused: nothing was changed on the host or in the record. Exit 4. */\nexport class RemoteRecoveryRefusedError extends Error {\n override readonly name = \"RemoteRecoveryRefusedError\";\n constructor(\n public readonly workstream: string,\n public readonly agentName: string,\n public readonly reason:\n | \"ambiguous\"\n | \"mismatch\"\n | \"gone\"\n | \"live-agent\"\n | \"resource-in-use\"\n | \"profile\"\n | \"changed\"\n | \"pin\",\n detail: string,\n /** The record ids the refusal is about (every candidate, or the one that moved). */\n public readonly candidates: readonly number[] = [],\n ) {\n super(say(\"remote.recovery_refused\", workstream, agentName, detail));\n }\n}\n\nconst rowToRecovery = (r: RawRow): RemoteRecovery => ({\n agentId: r.agent_id,\n workstream: r.workstream,\n workstreamId: r.workstream_id,\n workstreamCreatedAt: r.workstream_created_at,\n name: r.name,\n paneId: r.pane_id,\n host: r.host,\n cwd: r.cwd,\n base: r.base,\n collectedHead: r.collected_head,\n aside: r.aside,\n hostExec: r.host_exec,\n hostRepo: r.host_repo,\n reason: r.reason,\n preservedAt: r.preserved_at,\n});\n\n/** Every record, oldest incarnation first. */\nexport function listRemoteRecoveries(db: Db): RemoteRecovery[] {\n const rows = db.prepare(\"SELECT * FROM remote_recovery ORDER BY agent_id\").all() as RawRow[];\n return rows.map(rowToRecovery);\n}\n\n/** The record of ORIGINAL incarnation `agentId`, or undefined. */\nexport function getRemoteRecovery(db: Db, agentId: number): RemoteRecovery | undefined {\n const r = db.prepare(\"SELECT * FROM remote_recovery WHERE agent_id = ?\").get(agentId) as\n | RawRow\n | undefined;\n return r === undefined ? undefined : rowToRecovery(r);\n}\n\n/** Every record of workstream NAME `workstream` and agent `name`, oldest incarnation first. */\nexport function recoveriesFor(db: Db, workstream: string, name: string): RemoteRecovery[] {\n const rows = db\n .prepare(\"SELECT * FROM remote_recovery WHERE workstream = ? AND name = ? ORDER BY agent_id\")\n .all(workstream, name) as RawRow[];\n return rows.map(rowToRecovery);\n}\n\n/** The workstream names holding a record for agent `name` (the workstream may be gone). */\nexport function recoveryWorkstreams(db: Db, name: string): string[] {\n const rows = db\n .prepare(\"SELECT DISTINCT workstream FROM remote_recovery WHERE name = ? ORDER BY workstream\")\n .all(name) as { workstream: string }[];\n return rows.map((r) => r.workstream);\n}\n\n/**\n * The record `<workstream>/<name>` means. An explicit `recoveryId` must be a\n * record of that very name (`mismatch` otherwise) and is undefined once\n * removed: the caller decides (a retried close is a no-op; a collect refuses\n * with `recoveryGone`, never falling through to a live agent). Without it exactly ONE record\n * selects itself; several refuse (`ambiguous`) and list their ids, never the\n * newest one. Read only.\n */\nexport function selectRemoteRecovery(\n db: Db,\n workstream: string,\n name: string,\n recoveryId?: number,\n): RemoteRecovery | undefined {\n if (recoveryId !== undefined) {\n const rec = getRemoteRecovery(db, recoveryId);\n if (rec === undefined) return undefined;\n if (rec.workstream !== workstream || rec.name !== name) {\n throw new RemoteRecoveryRefusedError(\n workstream,\n name,\n \"mismatch\",\n `recovery ${recoveryId} belongs to ${rec.workstream}/${rec.name}`,\n [recoveryId],\n );\n }\n return rec;\n }\n const all = recoveriesFor(db, workstream, name);\n if (all.length <= 1) return all[0];\n const ids = all.map((r) => r.agentId);\n throw new RemoteRecoveryRefusedError(\n workstream,\n name,\n \"ambiguous\",\n `${all.length} removed agents of that name left a worktree (recoveries ${ids.join(\", \")}); pass --recovery <id>`,\n ids,\n );\n}\n\n/** An explicit `--recovery <id>` that is no longer there: refused, never read as \"no recovery asked\". */\nexport const recoveryGone = (\n workstream: string,\n name: string,\n recoveryId: number,\n): RemoteRecoveryRefusedError =>\n new RemoteRecoveryRefusedError(\n workstream,\n name,\n \"gone\",\n `recovery ${recoveryId} is gone (closed or never recorded); nothing was collected`,\n );\n\n// ─── Guards ─────────────────────────────────────────────────────────────────\n\n/** The profile at the time of use must be the one the record pinned. Missing provenance refuses. */\nexport function assertRecoveryProfile(\n rec: RemoteRecovery,\n profile: { exec: string } | undefined,\n): void {\n const refuse = (detail: string): never => {\n throw new RemoteRecoveryRefusedError(rec.workstream, rec.name, \"profile\", detail, [\n rec.agentId,\n ]);\n };\n if (profile === undefined) refuse(`host ${rec.host} has no profile now`);\n if (rec.hostExec === null) {\n refuse(\n `host ${rec.host} had no profile when the agent was removed: nothing proves the profile now named ${rec.host} reaches that worktree`,\n );\n }\n if (rec.hostRepo === null) refuse(`recovery ${rec.agentId} names no repo for its worktree`);\n if (profile?.exec !== rec.hostExec) {\n refuse(`host ${rec.host}'s profile changed since the agent was removed (exec differs)`);\n }\n}\n\n/**\n * Refuse unless nothing else claims what the record names: no current agent\n * of that name, no current agent on the same host and path, no NEWER record\n * of the same host and path (a name reused after its tree went away is\n * deterministically the same path: the newest record owns the tree, an older\n * one must not act on it), and the host's profile is the pinned one. Read only; run before any remote command and\n * again before the removal.\n */\nexport function assertRecoveryUsable(db: Db, rec: RemoteRecovery): void {\n const live = db\n .prepare(\n `SELECT ws.name AS workstream, a.name AS name FROM agents a JOIN workstreams ws ON ws.id = a.workstream_id\n WHERE (ws.name = ? AND a.name = ?) OR (a.host = ? AND a.cwd = ?)`,\n )\n .all(rec.workstream, rec.name, rec.host, rec.cwd) as { workstream: string; name: string }[];\n const same = live.find((a) => a.workstream === rec.workstream && a.name === rec.name);\n if (same !== undefined) {\n throw new RemoteRecoveryRefusedError(\n rec.workstream,\n rec.name,\n \"live-agent\",\n `a current agent holds the name; close it first, or recover after it is gone`,\n [rec.agentId],\n );\n }\n const other = live[0];\n if (other !== undefined) {\n throw new RemoteRecoveryRefusedError(\n rec.workstream,\n rec.name,\n \"resource-in-use\",\n `current agent ${other.workstream}/${other.name} uses ${rec.cwd} on ${rec.host}`,\n [rec.agentId],\n );\n }\n const newer = db\n .prepare(\n \"SELECT agent_id FROM remote_recovery WHERE host = ? AND cwd = ? AND agent_id > ? ORDER BY agent_id DESC LIMIT 1\",\n )\n .get(rec.host, rec.cwd, rec.agentId) as { agent_id: number } | undefined;\n if (newer !== undefined) {\n throw new RemoteRecoveryRefusedError(\n rec.workstream,\n rec.name,\n \"resource-in-use\",\n `newer recovery ${newer.agent_id} owns ${rec.cwd} on ${rec.host}; deal with it first`,\n [rec.agentId, newer.agent_id],\n );\n }\n assertRecoveryProfile(\n rec,\n db.prepare(\"SELECT exec FROM host_profiles WHERE name = ?\").get(rec.host) as\n | { exec: string }\n | undefined,\n );\n}\n\n/** Refuse (`changed`) unless the record is exactly `rec`: the CAS after every slow step. */\nexport function assertRecoveryUnchanged(db: Db, rec: RemoteRecovery): void {\n if (JSON.stringify(getRemoteRecovery(db, rec.agentId)) === JSON.stringify(rec)) return;\n throw new RemoteRecoveryRefusedError(\n rec.workstream,\n rec.name,\n \"changed\",\n `recovery ${rec.agentId} changed or went away while it was being used; preview it again`,\n [rec.agentId],\n );\n}\n\nconst SAME =\n \"agent_id = ? AND host = ? AND cwd = ? AND base = ? AND aside = ? AND collected_head IS ?\";\nconst sameArgs = (r: RemoteRecovery): (string | number | null)[] => [\n r.agentId,\n r.host,\n r.cwd,\n r.base,\n r.aside,\n r.collectedHead,\n];\n\n/** Delete exactly this record (compare-and-set on its identity and content). False when it is not there as read. */\nexport function deleteRemoteRecovery(db: Db, rec: RemoteRecovery): boolean {\n return (\n db.prepare(`DELETE FROM remote_recovery WHERE ${SAME}`).run(...sameArgs(rec)).changes === 1\n );\n}\n\n/** Record a collected HEAD on exactly this record (compare-and-set). False when it moved. */\nexport function setRecoveryCollectedHead(db: Db, rec: RemoteRecovery, head: string): boolean {\n return (\n db\n .prepare(`UPDATE remote_recovery SET collected_head = ? WHERE ${SAME}`)\n .run(head, ...sameArgs(rec)).changes === 1\n );\n}\n\n/** True when exactly this record is still there (the fence of a collect that wrote nothing). */\nexport function recoveryHolds(db: Db, rec: RemoteRecovery): boolean {\n return (\n db.prepare(`SELECT 1 FROM remote_recovery WHERE ${SAME}`).all(...sameArgs(rec)).length === 1\n );\n}\n\n/** Ids of the OTHER records of this name whose last collected commit is `commit` (a pin they rely on). */\nexport function pinnedByOthers(\n db: Db,\n rec: { workstream: string; name: string; agentId: number },\n commit: string,\n): number[] {\n const rows = db\n .prepare(\n \"SELECT agent_id FROM remote_recovery WHERE workstream = ? AND name = ? AND agent_id <> ? AND collected_head = ? ORDER BY agent_id\",\n )\n .all(rec.workstream, rec.name, rec.agentId, commit) as { agent_id: number }[];\n return rows.map((r) => r.agent_id);\n}\n","// mu — wait cursors: what a caller has already been handed.\n//\n// `wait_cursors` (machine-local) holds one row per (caller, typed ref):\n// the last CONSUMED token. A token is `{incarnation, runs}`, the two columns\n// the table has, and what it means depends on the ref kind:\n//\n// agent pi's process incarnation + the settled run count. A new\n// incarnation replaces the row; a stale one never suppresses\n// the run of a new process.\n// task `closed` + the id of the task's newest note. A re-close\n// writes a newer note, so a reopened-and-closed task is news.\n// delegate `delegate` + 1: a call reaches a terminal state once.\n//\n// A token is written only for an event the wait DELIVERED. Registering a\n// ref or starting a wait never writes one, and a sibling that a `first`\n// wait did not return stays unconsumed. Keys are typed, `<kind>:<ws>/<id>`:\n// workstream names hold no `/`, so no two refs collide.\n\nimport type { Db } from \"./db.js\";\n\nexport interface CursorToken {\n incarnation: string;\n runs: number;\n}\n\nexport type CursorKind = \"task\" | \"agent\" | \"delegate\";\n\nexport function cursorKey(kind: CursorKind, workstream: string, id: string): string {\n return `${kind}:${workstream}/${id}`;\n}\n\n/** The closed-task token: `noteId` is the task's newest note (0 for none). */\nexport const closedToken = (noteId: number): CursorToken => ({\n incarnation: \"closed\",\n runs: noteId,\n});\n\n/** The cursor key of an agent's DONE mark (src/wait-owed.ts): nothing is owed for the agent any more. */\nexport const doneKey = (workstream: string, name: string): string =>\n `done|${cursorKey(\"agent\", workstream, name)}`;\n\nexport const DELEGATE_TOKEN: CursorToken = { incarnation: \"delegate\", runs: 1 };\n\n/** The reserved caller of the stall-log marks: no caller is spelled like it (`<ws>/<agent>`, `pi:<s>`). */\nconst STALL_LOG_CALLER = \"mu:agent.stall\";\n\n/**\n * Log a task's stall once per owner identity: `emit` runs only when no wait, in any process, has\n * logged this task stalled on this (registry row, pi incarnation, run count) before. The mark is a\n * `stall-log|task:<ws>/<id>` row under a reserved caller (machine-local, like the `agent.stall` op\n * itself). One short immediate transaction: check, mark and emit together.\n */\nexport function logStallOnce(\n db: Db,\n task: { workstream: string; id: string },\n id: { agentId: number; incarnation: string; runs: number },\n emit: () => void,\n): void {\n const key = `stall-log|${cursorKey(\"task\", task.workstream, task.id)}`;\n const token = { incarnation: `${id.agentId}|${id.incarnation}`, runs: id.runs };\n db.transaction(() => {\n const row = db\n .prepare(\"SELECT incarnation, runs FROM wait_cursors WHERE caller = ? AND ref = ?\")\n .get(STALL_LOG_CALLER, key) as CursorToken | undefined;\n if (isConsumed(row, token)) return;\n recordCursors(db, STALL_LOG_CALLER, [{ key, token }]);\n emit();\n }).immediate();\n}\n\n/** Has this caller already consumed `token`'s event (or a later one)? */\nexport function isConsumed(cursor: CursorToken | undefined, token: CursorToken): boolean {\n return (\n cursor !== undefined && cursor.incarnation === token.incarnation && cursor.runs >= token.runs\n );\n}\n\n/** Every consumed token of `caller`, by key. Rows with no token are skipped. */\nexport function readCursors(db: Db, caller: string): Map<string, CursorToken> {\n const rows = db\n .prepare(\n \"SELECT ref, incarnation, runs FROM wait_cursors WHERE caller = ? AND incarnation IS NOT NULL AND runs IS NOT NULL\",\n )\n .all(caller) as { ref: string; incarnation: string; runs: number }[];\n return new Map(rows.map((r) => [r.ref, { incarnation: r.incarnation, runs: r.runs }]));\n}\n\n/**\n * Record consumed tokens, monotonically: within one incarnation `runs`\n * never goes down, and a different incarnation replaces the row. One short\n * write transaction; callable inside a larger one.\n */\nexport function recordCursors(\n db: Db,\n caller: string,\n entries: readonly { key: string; token: CursorToken }[],\n): void {\n if (entries.length === 0) return;\n const upsert = db.prepare(\n `INSERT INTO wait_cursors (caller, ref, incarnation, runs) VALUES (?, ?, ?, ?)\n ON CONFLICT (caller, ref) DO UPDATE\n SET incarnation = excluded.incarnation, runs = excluded.runs\n WHERE wait_cursors.incarnation IS NOT excluded.incarnation\n OR wait_cursors.runs IS NULL OR wait_cursors.runs < excluded.runs`,\n );\n db.transaction(() => {\n for (const e of entries) upsert.run(caller, e.key, e.token.incarnation, e.token.runs);\n }).immediate();\n}\n","// Code-unit string order for sorting names and paths.\n//\n// mu used `localeCompare` for these; the first call initialises ICU\n// (~4.5 ms per process, on nearly every list verb) and the resulting order\n// depends on the locale. Ids and paths want a stable, locale-free order.\n\nexport function compareStrings(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n","// mu — wait registrations: what a caller still owes a wait.\n//\n// `wait_registrations` (machine-local, one row per caller) holds the typed\n// refs that a later `mu wait` must still answer: the tasks, agents and\n// delegate calls this caller started. Two jobs, both small:\n//\n// 1. Registration. `registerOwnedWait` merges real refs into the caller's\n// row (deduped, in one canonical order): each must name an entity that\n// exists when it is registered. Refs come from mu's own producers as\n// typed values, never from parsing a shell line.\n// 2. One active wait per caller. `beginWait` bumps the row's `generation`\n// and marks it `waiting`; `endWait` is a compare-and-set on that\n// generation, so an older wait that finishes late (or twice) cannot\n// overwrite a newer one. A wait that died leaves `waiting` behind:\n// the next `beginWait` simply supersedes it.\n//\n// What this module does NOT do: it never records consumed runs (that is\n// `wait_cursors`, written by the wait that delivers an event), so\n// registering or beginning a wait cannot lose an unreturned event. `endWait`\n// removes only the refs the wait actually DELIVERED; an undelivered sibling,\n// a timeout or an interrupt leaves every ref owed.\n//\n// Every write is one short synchronous BEGIN IMMEDIATE transaction. None\n// spans an await, so no write lock is held while a wait sleeps.\n\nimport { isValidAgentName } from \"./agents.js\";\nimport { compareStrings } from \"./compare.js\";\nimport type { Db } from \"./db.js\";\nimport { isValidTaskId } from \"./tasks/id.js\";\nimport { cursorKey, doneKey } from \"./wait-cursor.js\";\nimport { isValidWorkstreamName } from \"./workstream.js\";\n\nexport const WAIT_REF_KINDS = [\"task\", \"agent\", \"delegate\"] as const;\nexport type WaitRefKind = (typeof WAIT_REF_KINDS)[number];\n\n/** One owed ref: a task or agent of a workstream, or a delegate call id. */\nexport interface RegisteredRef {\n kind: WaitRefKind;\n workstream: string;\n id: string;\n}\n\n/**\n * The UNCONSUMED run baseline of an agent ref: what a producer (`send`,\n * `spawn`, `claim`) saw BEFORE its effect: the ctl run count, pi's process\n * incarnation and the registry id. A wait counts the agent's runs from here, so\n * a send that settles before any wait starts is still caught. Distinct from a\n * consumed cursor (`wait_cursors`), which says what a wait already delivered.\n */\nexport interface RefBaseline {\n afterRuns: number;\n /**\n * The LATEST fence armed for this process, when later than `afterRuns` (the earliest unconsumed\n * one): a send armed after the first still owes the run that follows it, so a wait that delivers\n * a run at or below `latest` leaves the ref owed (`endWait`).\n */\n latest?: number;\n incarnation?: string;\n agentId?: number;\n}\n\n/** A ref to register, with its baseline when it is an agent. */\nexport type RegisterRef = RegisteredRef & { baseline?: RefBaseline };\n\nexport const WAIT_REGISTRATION_STATES = [\"armed\", \"waiting\"] as const;\nexport type WaitRegistrationState = (typeof WAIT_REGISTRATION_STATES)[number];\n\nexport interface WaitRegistration {\n caller: string;\n /** Canonical order: kind, workstream, id. */\n refs: RegisteredRef[];\n state: WaitRegistrationState;\n /** Bumped by every `beginWait`; never decreases. */\n generation: number;\n /** Unconsumed baselines of agent refs, by `cursorKey(\"agent\", ws, name)`. */\n baselines: Record<string, RefBaseline>;\n updatedAt: string;\n}\n\n/** The most refs one caller may owe at once. */\nexport const WAIT_REGISTRATION_MAX_REFS = 256;\n\n/** A caller, ref or registration mu refuses or cannot read. */\nexport class WaitRegistrationError extends Error {\n override readonly name = \"WaitRegistrationError\";\n}\n\nconst CALLER_MAX = 200;\nconst ID_MAX = 512;\n\n/** Throws WaitRegistrationError unless `caller` is 1-200 printable characters. */\nexport function checkCaller(caller: string): void {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: control characters are the point\n if (caller.trim() === \"\" || caller.length > CALLER_MAX || /[\\u0000-\\u001f\\u007f]/.test(caller)) {\n throw new WaitRegistrationError(\n `wait registration: caller must be 1-${CALLER_MAX} printable characters`,\n );\n }\n}\n\nfunction checkRef(ref: RegisteredRef): void {\n const where = `${ref.kind}:${ref.workstream}/${ref.id}`;\n if (!(WAIT_REF_KINDS as readonly string[]).includes(ref.kind)) {\n throw new WaitRegistrationError(`wait registration: unknown ref kind in ${where}`);\n }\n if (typeof ref.workstream !== \"string\" || !isValidWorkstreamName(ref.workstream)) {\n throw new WaitRegistrationError(`wait registration: bad workstream in ${where}`);\n }\n const ok =\n typeof ref.id === \"string\" &&\n (ref.kind === \"task\"\n ? isValidTaskId(ref.id)\n : ref.kind === \"agent\"\n ? isValidAgentName(ref.id)\n : ref.id !== \"\" && ref.id.length <= ID_MAX); // a call id is whatever delegate_calls stores\n if (!ok) throw new WaitRegistrationError(`wait registration: bad ${ref.kind} id in ${where}`);\n}\n\nconst keyOf = (r: RegisteredRef): string => `${r.kind}\\n${r.workstream}\\n${r.id}`;\n\nfunction compareRefs(a: RegisteredRef, b: RegisteredRef): number {\n return (\n compareStrings(a.kind, b.kind) ||\n compareStrings(a.workstream, b.workstream) ||\n compareStrings(a.id, b.id)\n );\n}\n\n/**\n * Refuse the first ref (canonical order) whose entity does not exist now:\n * the workstream, the task or agent in it, or the delegate call exactly as\n * `delegate_calls.call_id` stores it (and its task in that workstream).\n * Called inside the registering transaction.\n */\nfunction checkRefsExist(db: Db, refs: readonly RegisteredRef[]): void {\n const hasWorkstream = db.prepare(\"SELECT 1 FROM workstreams WHERE name = ?\");\n const hasTask = db.prepare(\n \"SELECT 1 FROM tasks t JOIN workstreams w ON w.id = t.workstream_id WHERE w.name = ? AND t.local_id = ?\",\n );\n const hasAgent = db.prepare(\n \"SELECT 1 FROM agents a JOIN workstreams w ON w.id = a.workstream_id WHERE w.name = ? AND a.name = ?\",\n );\n const hasCall = db.prepare(\n \"SELECT 1 FROM delegate_calls d JOIN tasks t ON t.id = d.task_id JOIN workstreams w ON w.id = t.workstream_id WHERE w.name = ? AND d.call_id = ?\",\n );\n for (const ref of refs) {\n const where = `${ref.kind} ${ref.workstream}/${ref.id}`;\n if (hasWorkstream.get(ref.workstream) === undefined) {\n throw new WaitRegistrationError(\n `wait registration: no workstream ${ref.workstream} (for ${where}); nothing registered`,\n );\n }\n const stmt = ref.kind === \"task\" ? hasTask : ref.kind === \"agent\" ? hasAgent : hasCall;\n if (stmt.get(ref.workstream, ref.id) === undefined) {\n throw new WaitRegistrationError(`wait registration: no ${where}; nothing registered`);\n }\n }\n}\n\n/** Validate, dedupe and order `refs` (copies; the input is not touched). */\nfunction canonical(refs: readonly RegisteredRef[]): RegisteredRef[] {\n const seen = new Map<string, RegisteredRef>();\n for (const ref of refs) {\n checkRef(ref);\n seen.set(keyOf(ref), { kind: ref.kind, workstream: ref.workstream, id: ref.id });\n }\n return [...seen.values()].sort(compareRefs);\n}\n\ninterface Row {\n caller: string;\n refs_json: string;\n state: WaitRegistrationState;\n generation: number;\n updated_at: string;\n baselines_json: string;\n}\n\nfunction parseBaselines(json: string, refs: readonly RegisteredRef[]): Record<string, RefBaseline> {\n let raw: unknown;\n try {\n raw = JSON.parse(json);\n } catch {\n return {};\n }\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) return {};\n const live = new Set(refs.filter((r) => r.kind === \"agent\").map((r) => refKeyOf(r)));\n const out: Record<string, RefBaseline> = {};\n for (const [k, v] of Object.entries(raw as Record<string, unknown>)) {\n const b = v as Partial<RefBaseline> | null;\n if (!live.has(k) || b === null || typeof b !== \"object\") continue;\n if (typeof b.afterRuns !== \"number\" || !Number.isInteger(b.afterRuns) || b.afterRuns < 0)\n continue;\n out[k] = {\n afterRuns: b.afterRuns,\n ...(typeof b.latest === \"number\" && Number.isInteger(b.latest) && b.latest > b.afterRuns\n ? { latest: b.latest }\n : {}),\n ...(typeof b.incarnation === \"string\" ? { incarnation: b.incarnation } : {}),\n ...(typeof b.agentId === \"number\" ? { agentId: b.agentId } : {}),\n };\n }\n return out;\n}\n\nconst refKeyOf = (r: RegisteredRef): string => cursorKey(r.kind, r.workstream, r.id);\n\n/**\n * Merge a new baseline into an old one: of one incarnation the EARLIEST fence is kept (the first run\n * is still owed) beside the LATEST (`latest`); a new incarnation replaces. Returns `old` itself when\n * nothing changes.\n */\nfunction mergeBaseline(old: RefBaseline | undefined, add: RefBaseline): RefBaseline {\n if (old === undefined || old.incarnation !== add.incarnation || old.agentId !== add.agentId) {\n return add;\n }\n const oldLatest = old.latest ?? old.afterRuns;\n const hi = Math.max(oldLatest, add.latest ?? add.afterRuns);\n const lo = Math.min(old.afterRuns, add.afterRuns);\n if (lo === old.afterRuns && hi === oldLatest) return old;\n const { latest: _a, ...rest } = old.afterRuns <= add.afterRuns ? old : add;\n return { ...rest, afterRuns: lo, ...(hi > lo ? { latest: hi } : {}) };\n}\n\nfunction parse(row: Row): WaitRegistration {\n let raw: unknown;\n try {\n raw = JSON.parse(row.refs_json);\n } catch {\n throw new WaitRegistrationError(`wait registration for ${row.caller}: refs_json is not JSON`);\n }\n if (!Array.isArray(raw)) {\n throw new WaitRegistrationError(`wait registration for ${row.caller}: refs_json is not a list`);\n }\n const refs = canonical(raw as RegisteredRef[]);\n return {\n caller: row.caller,\n refs,\n state: row.state,\n generation: row.generation,\n baselines: parseBaselines(row.baselines_json, refs),\n updatedAt: row.updated_at,\n };\n}\n\nconst select = (db: Db, caller: string): Row | undefined =>\n db\n .prepare(\n \"SELECT caller, refs_json, state, generation, updated_at, baselines_json FROM wait_registrations WHERE caller = ?\",\n )\n .get(caller) as Row | undefined;\n\n/** The caller's registration, or undefined when it never registered anything. */\nexport function readWaitRegistration(db: Db, caller: string): WaitRegistration | undefined {\n const row = select(db, caller);\n return row === undefined ? undefined : parse(row);\n}\n\n/**\n * Add `refs` to what `caller` owes a wait. Merges with the refs already\n * owed (deduped, canonical order) and keeps `state` and `generation`, so\n * registering while a wait is in flight neither disturbs it nor is lost\n * when it ends. Every ref must exist now (checked in the same transaction\n * that writes); a ref whose entity is deleted LATER stays owed. Refuses the\n * whole call (nothing stored) on a bad caller, a bad or missing ref, an\n * empty list, or more than\n * WAIT_REGISTRATION_MAX_REFS refs owed in total.\n */\nexport function registerOwnedWait(\n db: Db,\n caller: string,\n refs: readonly RegisterRef[],\n): WaitRegistration {\n checkCaller(caller);\n if (refs.length === 0) throw new WaitRegistrationError(\"wait registration: no refs to register\");\n const add = canonical(refs);\n const incoming = new Map<string, RefBaseline>();\n for (const r of refs) {\n if (r.baseline === undefined) continue;\n if (r.kind !== \"agent\") {\n throw new WaitRegistrationError(\n `wait registration: only an agent ref has a run baseline (${r.kind}:${r.workstream}/${r.id})`,\n );\n }\n const b = r.baseline;\n if (!Number.isInteger(b.afterRuns) || b.afterRuns < 0) {\n throw new WaitRegistrationError(\n `wait registration: baseline afterRuns must be a non-negative integer (${r.workstream}/${r.id})`,\n );\n }\n const key = refKeyOf(r);\n incoming.set(key, mergeBaseline(incoming.get(key), b));\n }\n return db\n .transaction((): WaitRegistration => {\n checkRefsExist(db, add);\n const row = select(db, caller);\n const old = row === undefined ? undefined : parse(row);\n const have = old?.refs ?? [];\n const merged = canonical([...have, ...add]);\n if (merged.length > WAIT_REGISTRATION_MAX_REFS) {\n throw new WaitRegistrationError(\n `wait registration: at most ${WAIT_REGISTRATION_MAX_REFS} refs may be owed at once (${caller} would owe ${merged.length})`,\n );\n }\n // New work for an agent: whatever DONE mark it held no longer holds.\n const unmark = db.prepare(\"DELETE FROM wait_cursors WHERE caller = ? AND ref = ?\");\n for (const r of add) if (r.kind === \"agent\") unmark.run(caller, doneKey(r.workstream, r.id));\n const baselines: Record<string, RefBaseline> = { ...(old?.baselines ?? {}) };\n for (const [k, b] of incoming) baselines[k] = mergeBaseline(baselines[k], b);\n const now = new Date().toISOString();\n const baselinesJson = JSON.stringify(baselines);\n if (row === undefined) {\n db.prepare(\n \"INSERT INTO wait_registrations (caller, refs_json, state, generation, updated_at, baselines_json) VALUES (?, ?, 'armed', 0, ?, ?)\",\n ).run(caller, JSON.stringify(merged), now, baselinesJson);\n } else if (merged.length !== have.length || baselinesJson !== row.baselines_json) {\n db.prepare(\n \"UPDATE wait_registrations SET refs_json = ?, baselines_json = ?, updated_at = ? WHERE caller = ?\",\n ).run(JSON.stringify(merged), baselinesJson, now, caller);\n }\n const after = select(db, caller);\n if (after === undefined) throw new WaitRegistrationError(\"wait registration vanished\");\n return parse(after);\n })\n .immediate();\n}\n\n/**\n * Store `baseline` as the unconsumed fence of an owed agent ref that has none\n * (a ref registered with no producer baseline: the first wait probed the run\n * count and counts from it), or whose stored fence belongs to another process\n * or registry row. A no-op when the ref is not owed or the fence is usable. Touches neither `state` nor `generation`, so it never disturbs a\n * wait in flight.\n */\nexport function fenceAgentRef(\n db: Db,\n caller: string,\n ref: RegisteredRef,\n baseline: RefBaseline,\n): void {\n db.transaction(() => {\n const row = select(db, caller);\n if (row === undefined) return;\n const reg = parse(row);\n const key = refKeyOf(ref);\n if (!reg.refs.some((r) => refKeyOf(r) === key)) return;\n // The same fence (or an earlier one of the same process) stays; a baseline of\n // another process or registry row, which no wait could use, is replaced.\n // (A probed fence is no send: it never raises `latest`.)\n const old = reg.baselines[key];\n const sameProcess =\n old !== undefined &&\n old.incarnation === baseline.incarnation &&\n old.agentId === baseline.agentId;\n const merged = sameProcess ? old : baseline;\n if (merged === old) return;\n db.prepare(\"UPDATE wait_registrations SET baselines_json = ? WHERE caller = ?\").run(\n JSON.stringify({ ...reg.baselines, [key]: merged }),\n caller,\n );\n }).immediate();\n}\n\n/** Every caller whose registration holds `ref`. */\nexport function callersOwing(db: Db, ref: RegisteredRef): string[] {\n const rows = db.prepare(\"SELECT caller FROM wait_registrations\").all() as { caller: string }[];\n return rows\n .filter(({ caller }) => {\n const row = select(db, caller);\n return row !== undefined && parse(row).refs.some((r) => keyOf(r) === keyOf(ref));\n })\n .map((r) => r.caller);\n}\n\n/**\n * Remove `refs` from `caller`'s registration, each agent ref's fence and DONE mark with it. For refs\n * the engine found DONE (src/wait-owed.ts), never for a delivered event (that is `endWait`). Touches\n * neither `state` nor `generation`, so it never disturbs a wait in flight. A no-op for a ref that is\n * not registered.\n */\nexport function dropOwnedRefs(db: Db, caller: string, refs: readonly RegisteredRef[]): void {\n const gone = new Set(refs.map(keyOf));\n db.transaction(() => {\n const row = select(db, caller);\n if (row === undefined) return;\n const reg = parse(row);\n const left = reg.refs.filter((r) => !gone.has(keyOf(r)));\n if (left.length === reg.refs.length) return;\n const kept = Object.fromEntries(\n Object.entries(reg.baselines).filter(([k]) => left.some((r) => refKeyOf(r) === k)),\n );\n db.prepare(\n \"UPDATE wait_registrations SET refs_json = ?, baselines_json = ?, updated_at = ? WHERE caller = ?\",\n ).run(JSON.stringify(left), JSON.stringify(kept), new Date().toISOString(), caller);\n const clear = db.prepare(\"DELETE FROM wait_cursors WHERE caller = ? AND ref = ?\");\n for (const r of refs) if (r.kind === \"agent\") clear.run(caller, doneKey(r.workstream, r.id));\n }).immediate();\n}\n\n/**\n * Start a wait for `caller`: bump the generation, mark the row `waiting`,\n * return the generation and the refs owed now. undefined (and nothing\n * written) when the caller owes nothing. An earlier wait still marked\n * `waiting` is superseded: its `endWait` will no longer match.\n */\nexport function beginWait(\n db: Db,\n caller: string,\n):\n | { generation: number; refs: RegisteredRef[]; baselines: Record<string, RefBaseline> }\n | undefined {\n return db\n .transaction(() => {\n const row = select(db, caller);\n if (row === undefined) return undefined;\n const reg = parse(row);\n if (reg.refs.length === 0) return undefined;\n const generation = reg.generation + 1;\n db.prepare(\n \"UPDATE wait_registrations SET state = 'waiting', generation = ?, updated_at = ? WHERE caller = ?\",\n ).run(generation, new Date().toISOString(), caller);\n return { generation, refs: reg.refs, baselines: reg.baselines };\n })\n .immediate();\n}\n\n/** The run an agent ref was delivered at, when it was a settled run (`endWait`). */\nexport interface DeliveredRun {\n runs?: number;\n incarnation?: string;\n}\n\n/**\n * Finish the wait that `beginWait` numbered `generation`: drop the\n * `delivered` refs from what is owed and re-arm the row. A compare-and-set:\n * `applied: false` (and nothing written) when the row is gone, a newer wait\n * started, or this generation already ended. Refs registered since\n * `beginWait`, and refs not delivered, stay owed. The row is kept even when\n * nothing is left, so generations never restart.\n */\nexport function endWait(\n db: Db,\n caller: string,\n generation: number,\n delivered: readonly (RegisteredRef & DeliveredRun)[],\n): { applied: boolean } {\n return db\n .transaction((): { applied: boolean } => {\n const row = select(db, caller);\n if (row === undefined || row.generation !== generation || row.state !== \"waiting\") {\n return { applied: false };\n }\n const reg = parse(row);\n const gone = new Set(canonical(delivered).map(keyOf));\n // A send armed after the delivered run (producer fence >= the run) still owes the run that\n // follows it: the ref stays, counted from the run just delivered.\n const baselines = { ...reg.baselines };\n for (const d of delivered) {\n const key = refKeyOf(d);\n const b = baselines[key];\n if (d.runs === undefined || b === undefined || b.latest === undefined) continue;\n if (\n b.incarnation !== undefined &&\n d.incarnation !== undefined &&\n b.incarnation !== d.incarnation\n )\n continue;\n if (b.latest < d.runs) continue;\n gone.delete(keyOf(d));\n const { latest, ...rest } = b;\n const afterRuns = Math.max(d.runs, b.afterRuns);\n baselines[key] = { ...rest, afterRuns, ...(latest > afterRuns ? { latest } : {}) };\n }\n const left = reg.refs.filter((r) => !gone.has(keyOf(r)));\n const kept = Object.fromEntries(\n Object.entries(baselines).filter(([k]) => left.some((r) => refKeyOf(r) === k)),\n );\n db.prepare(\n \"UPDATE wait_registrations SET refs_json = ?, baselines_json = ?, state = 'armed', updated_at = ? WHERE caller = ?\",\n ).run(JSON.stringify(left), JSON.stringify(kept), new Date().toISOString(), caller);\n return { applied: true };\n })\n .immediate();\n}\n","// mu — when an owned agent ref is still OWED a wait, and when it is DONE.\n//\n// One rule, kept here. An agent ref a caller registered is owed only while the agent owns open work\n// (a task that is not CLOSED) or a run it was sent is unsettled. When every task it owned is CLOSED\n// (or released) and its last run settled, the ref is DONE: a later `agent close`, or a pane that goes\n// away, is NOT a `dead` event. `dead` is for a pane lost while work or a run is still owed.\n//\n// A row that is gone cannot say what it owned, so DONE is recorded while the agent can still be\n// read: `agentOwed` over a reading, kept as a mark (`setAgentDone`: a cursor under\n// `done|agent:<ws>/<name>`, machine-local) by every wait tick, and by `agent close` of an agent\n// holding no unfinished task (closing on purpose is the end of its work). The engine\n// (src/wait.ts `ownedRefs`) drops a registered agent ref whose row is gone and which carries a mark:\n// no event, no dead. Arming new work for the agent (`registerOwnedWait`) and a tick that finds it\n// owed again clear the mark.\n\nimport { expectsCtl } from \"./agents/transport.js\";\nimport { ctlProbe } from \"./ctl/client.js\";\nimport { ctlSocketPath } from \"./ctl/path.js\";\nimport type { Db } from \"./db.js\";\nimport { doneKey, readCursors } from \"./wait-cursor.js\";\nimport { callersOwing, type RefBaseline } from \"./wait-registration.js\";\nimport type { AgentReading } from \"./wait-types.js\";\n\n/** How many tasks registry row `agentRowId` owns that are not CLOSED, and how many are. */\nexport function workOf(db: Db, agentRowId: number): { open: number; closed: number } {\n const row = db\n .prepare(\n `SELECT COALESCE(SUM(status != 'CLOSED'), 0) AS open, COALESCE(SUM(status = 'CLOSED'), 0) AS closed\n FROM tasks WHERE owner_id = ?`,\n )\n .get(agentRowId) as { open: number; closed: number };\n return row;\n}\n\n/**\n * What a reading says about an agent ref: `owed` (busy, a dialog, a queued message or an open task),\n * `done` (idle, nothing queued, no open task, and its work ran: the run a producer fenced settled, or\n * with no usable fence the agent was seen busy or owns a CLOSED task) or `unsure` (no fact: an\n * unreadable agent, or idle before any run is known to have happened). Only `done` marks, so an agent\n * lost unread, or lost before it ran, still reads dead. A fence of another pi process, or one the\n * engine probed itself (`probedFence`: no producer sent a run), does not apply.\n */\nexport function agentOwed(\n db: Db,\n agentRowId: number,\n reading: Pick<AgentReading, \"status\" | \"pending\" | \"blocked\" | \"runs\" | \"incarnation\">,\n fence: RefBaseline | undefined,\n probedFence: boolean,\n wasBusy: boolean,\n): \"owed\" | \"done\" | \"unsure\" {\n if (reading.status === null || reading.status === \"unknown\") return \"unsure\";\n if (reading.status !== \"needs_input\") return \"owed\";\n if (reading.pending === true || reading.blocked !== undefined) return \"owed\";\n const work = workOf(db, agentRowId);\n if (work.open > 0) return \"owed\";\n if (\n fence !== undefined &&\n !probedFence &&\n (fence.incarnation === undefined ||\n reading.incarnation === undefined ||\n fence.incarnation === reading.incarnation)\n ) {\n return reading.runs !== undefined && reading.runs > fence.afterRuns ? \"done\" : \"unsure\";\n }\n return wasBusy || work.closed > 0 ? \"done\" : \"unsure\";\n}\n\n/** Does `caller` hold a DONE mark for this agent? */\nexport function hasDoneMark(\n db: Db,\n caller: string,\n ref: { workstream: string; id: string },\n): boolean {\n return readCursors(db, caller).has(doneKey(ref.workstream, ref.id));\n}\n\n/** Set or clear the DONE mark of an agent for `callers` (default: whoever's registration holds its ref). */\nexport function setAgentDone(\n db: Db,\n workstream: string,\n name: string,\n done: boolean,\n callers: readonly string[] = callersOwing(db, { kind: \"agent\", workstream, id: name }),\n): void {\n const key = doneKey(workstream, name);\n for (const caller of callers) {\n if (hasDoneMark(db, caller, { workstream, id: name }) === done) continue;\n if (done) {\n db.prepare(\n \"INSERT OR IGNORE INTO wait_cursors (caller, ref, incarnation, runs) VALUES (?, ?, 'done', 1)\",\n ).run(caller, key);\n } else db.prepare(\"DELETE FROM wait_cursors WHERE caller = ? AND ref = ?\").run(caller, key);\n }\n}\n\n/**\n * Is a run in flight in this pi (busy, a queued message, a dialog)? Asked before `agent close` kills\n * the pane. A pi that cannot be asked, or an agent with no control socket, has none we can see: what\n * it owes is what its tasks say (`workOf`).\n */\nexport async function runInFlight(agent: {\n name: string;\n workstreamName: string;\n cli: string;\n}): Promise<boolean> {\n const sock = ctlSocketPath(agent.workstreamName, agent.name);\n if (!expectsCtl(agent, sock)) return false;\n const probe = await ctlProbe(sock, 1000, { hello: false });\n if (probe.kind !== \"ok\") return false;\n const { state, pending, blocked } = probe.status;\n return state === \"busy\" || pending === true || blocked !== undefined;\n}\n","// mu — `agent close` of a remote worktree whose agent row is gone (v_remote_recovery_close).\n//\n// The reaper, a teardown or a workstream deletion removed the row but kept\n// what it said about the worktree (`remote_recovery`, src/remote-recovery.ts).\n// This closes THAT: no agent comes back, no pane is opened or killed, no task\n// is touched. It reuses `closeRemoteWorktree` whole (quiescence, the common\n// git dir check, clean + known-HEAD or create-only keep-branch, no --force,\n// dirty refuses under every flag) with the ORIGINAL incarnation, so the aside\n// it resumes from is the one the first, crashed attempt parked the tree at.\n//\n// The record is checked again after every slow step (compare-and-set on all\n// of it, plus the live registry and the profile): before the removal, and at\n// the final delete, which removes only this record and only when the tree is\n// removed, kept on a branch or gone. Every refusal and error keeps it.\n// Runs under the agent lock `closeAgent` took.\n\nimport type { Db } from \"../db.js\";\nimport { emitEvent } from \"../logs.js\";\nimport { asideOf, closeRemoteWorktree, localPaneAlive } from \"../remote-agent.js\";\nimport {\n assertRecoveryProfile,\n assertRecoveryUnchanged,\n assertRecoveryUsable,\n deleteRemoteRecovery,\n type RemoteRecovery,\n RemoteRecoveryRefusedError,\n} from \"../remote-recovery.js\";\nimport type { CloseAgentResult, ClosePreview } from \"./close.js\";\n\n/** Why a close of `rec` would refuse right now, from the registry and the profile alone (no host command); null when it would go on. */\nexport function recoveryRefusal(db: Db, rec: RemoteRecovery): string | null {\n try {\n assertRecoveryUsable(db, rec);\n return null;\n } catch (err) {\n if (err instanceof RemoteRecoveryRefusedError) return err.message;\n throw err;\n }\n}\n\n/** The preview fields of a recovery: read only. */\nexport function recoveryPreview(\n db: Db,\n rec: RemoteRecovery,\n): Pick<ClosePreview, \"remote\" | \"recovery\"> {\n return {\n remote: { host: rec.host, path: rec.cwd, base: rec.base, collectedHead: rec.collectedHead },\n recovery: {\n id: rec.agentId,\n aside: rec.aside,\n reason: rec.reason,\n preservedAt: rec.preservedAt,\n refusal: recoveryRefusal(db, rec),\n },\n };\n}\n\n/** Apply a close to the selected record. The caller holds the agent lock and has passed the revision fence. */\nexport async function closeRecovery(\n db: Db,\n rec: RemoteRecovery,\n opts: { keepBranch: boolean; force?: boolean },\n): Promise<CloseAgentResult> {\n if (rec.aside !== asideOf(rec.cwd, rec.agentId)) {\n throw new RemoteRecoveryRefusedError(\n rec.workstream,\n rec.name,\n \"changed\",\n `recovery ${rec.agentId} names an aside that is not its own (${rec.aside}); refusing to guess`,\n [rec.agentId],\n );\n }\n assertRecoveryUsable(db, rec);\n const worktree = await closeRemoteWorktree(\n db,\n {\n name: rec.name,\n workstreamName: rec.workstream,\n host: rec.host,\n cwd: rec.cwd,\n base: rec.base,\n collectedHead: rec.collectedHead,\n repo: rec.hostRepo,\n // The ORIGINAL registry incarnation: the aside path derives from it.\n incarnation: rec.agentId,\n },\n {\n keepBranch: opts.keepBranch,\n force: opts.force === true,\n paneAlive: localPaneAlive,\n recoveryId: rec.agentId,\n checkProfile: (profile) => assertRecoveryProfile(rec, profile),\n beforeRemove: () => {\n assertRecoveryUnchanged(db, rec);\n assertRecoveryUsable(db, rec);\n },\n },\n );\n // The tree is removed, kept on a branch or gone; only now does the record go,\n // and only this one, as read.\n const deleted = deleteRemoteRecovery(db, rec);\n if (!deleted) assertRecoveryUnchanged(db, rec);\n const bits = [`recovery ${rec.agentId}`, `worktree ${worktree.action}`];\n if (worktree.branch !== undefined) bits.push(`as ${worktree.branch}`);\n emitEvent(db, rec.workstream, \"agent.close\", `agent close ${rec.name} (${bits.join(\", \")})`);\n return {\n killedPane: false,\n deletedRow: false,\n worktree,\n recovery: { id: rec.agentId, deleted },\n };\n}\n","// mu — remote command gates: `spawn --host` of a NON-pi command.\n//\n// A gate is a foreground remote command (`npm test`) in a pane. Its numeric\n// exit is the authoritative result `mu wait` returns, without pi or murmur.\n//\n// Two statuses exist and only one is the answer. The LOCAL pane runs the\n// profile's `shell` template (ssh, a container exec, a fake), whose own exit\n// may swallow or replace the remote command's. So the remote wrapper writes a\n// completion record keyed by the spawn-unique token (`agents.gate_token`):\n// `MU_GATE <token> <rc>`, atomically, on the host. The record is read with the\n// profile's `exec` template only AFTER the mux proves the transport pane\n// exited (`paneResult`), and that proof frees the pane's channel first, so at\n// --max-sessions 1 the read admits like any other exec. Absent, malformed or\n// foreign records, a signal or a lost transport are never success.\n//\n// Reading is idempotent (it never removes the record); `agent close` removes\n// only its own token's file.\n\nimport { randomUUID } from \"node:crypto\";\nimport type { AgentRow } from \"../agents.js\";\nimport type { Db } from \"../db.js\";\nimport { runHostTemplate } from \"../hosts.js\";\nimport { activeMux } from \"../mux.js\";\nimport { localPaneAlive } from \"../remote-agent.js\";\nimport { shellQuote } from \"../shell-quote.js\";\n\n/** What a gate's wait sees. `unknown` is retried (the result could not be read yet); `dead` is final. */\nexport type GateReading =\n | { kind: \"running\" }\n | { kind: \"exited\"; code: number }\n | { kind: \"dead\"; reason: string }\n | { kind: \"unknown\"; reason: string };\n\n/** A fresh token: the gate's marker on its row and the key of its remote record. */\nexport const newGateToken = (): string => randomUUID();\n\nconst TOKEN_RE = /^[0-9a-f-]{36}$/;\nconst DIR = `\"$HOME\"/.local/state/mu-next/remote-gates`;\n\nconst sh = (body: string): string => `sh -c ${shellQuote(body)}`;\n\nfunction assertToken(token: string): void {\n if (!TOKEN_RE.test(token)) throw new Error(`gate token ${JSON.stringify(token)} is not a uuid`);\n}\n\n/**\n * The command the template's `{cmd}` carries for a gate: runs `command` under\n * `sh -c` and records its numeric status for `token`. A host that cannot take\n * the record refuses to run the command (exit 126), so no gate runs unrecorded.\n */\nexport function gateWrapper(command: string, token: string): string {\n assertToken(token);\n return sh(\n [\n `d=${DIR}`,\n `mkdir -p \"$d\" || exit 126`,\n `rm -f \"$d/${token}\" \"$d/${token}.tmp\"`,\n `sh -c ${shellQuote(command)}`,\n `rc=$?`,\n `printf 'MU_GATE ${token} %s\\\\n' \"$rc\" > \"$d/${token}.tmp\" && mv \"$d/${token}.tmp\" \"$d/${token}\"`,\n `exit \"$rc\"`,\n ].join(\"\\n\"),\n );\n}\n\n/** The exec command that prints the token's record, behind a tag proving the script ran. */\nconst readCommand = (token: string): string =>\n sh([`f=${DIR}/${token}`, `echo MU_GATE_READ`, `[ ! -f \"$f\" ] || cat \"$f\"`].join(\"\\n\"));\n\n/** The exec command that removes the token's own files. */\nconst cleanCommand = (token: string): string =>\n sh([`d=${DIR}`, `rm -f \"$d/${token}\" \"$d/${token}.tmp\"`].join(\"\\n\"));\n\ntype Parsed = { kind: \"code\"; code: number } | { kind: \"dead\"; reason: string };\n\n/** The record in a read's stdout: exactly `MU_GATE <token> <digits>`, the gate's own token. */\nfunction parseRecord(stdout: string, token: string): Parsed {\n const lines = stdout.split(\"\\n\").map((l) => l.trim());\n const tag = lines.lastIndexOf(\"MU_GATE_READ\");\n const rest = (tag === -1 ? [] : lines.slice(tag + 1)).filter((l) => l !== \"\");\n if (rest.length === 0) return { kind: \"dead\", reason: \"no completion record on the host\" };\n const m = /^MU_GATE ([0-9a-f-]+) (\\d{1,3})$/.exec(rest[0] ?? \"\");\n if (rest.length !== 1 || m === null) {\n return { kind: \"dead\", reason: \"the completion record is malformed\" };\n }\n if (m[1] !== token) return { kind: \"dead\", reason: \"the completion record is another gate's\" };\n const code = Number(m[2]);\n if (code > 255) return { kind: \"dead\", reason: \"the completion record is malformed\" };\n return { kind: \"code\", code };\n}\n\n/** The row `agent` names right now: same registry id, pane and token, else it was replaced. */\nfunction sameRow(db: Db, agent: AgentRow): boolean {\n const row = db\n .prepare(\n `SELECT a.id, a.pane_id, a.gate_token FROM agents a JOIN workstreams w ON w.id = a.workstream_id\n WHERE w.name = ? AND a.name = ?`,\n )\n .get(agent.workstreamName, agent.name) as\n | { id: number; pane_id: string; gate_token: string | null }\n | undefined;\n return (\n row !== undefined &&\n row.id === agent.incarnation &&\n row.pane_id === agent.paneId &&\n row.gate_token === agent.gateToken\n );\n}\n\nconst unknown = (reason: string): GateReading => ({ kind: \"unknown\", reason });\n\n/**\n * Read one gate: running, exited with the remote command's numeric status,\n * dead (final failure: no usable record, or the pane is gone) or unknown\n * (retry: the mux or the host could not answer). A proven exit frees the pane's\n * channel through the result read's own admission (see `localPaneAlive`); an\n * unknown probe frees nothing.\n */\nexport async function readGate(db: Db, agent: AgentRow): Promise<GateReading> {\n const token = agent.gateToken;\n const host = agent.host;\n if (token === null || host === null) return unknown(\"not a remote command gate\");\n let pane: Awaited<ReturnType<NonNullable<Awaited<ReturnType<typeof activeMux>>[\"paneResult\"]>>>;\n try {\n const mux = await activeMux();\n if (mux.paneResult === undefined) return unknown(\"the multiplexer cannot report a pane's exit\");\n pane = await mux.paneResult(agent.paneId);\n } catch (e) {\n return unknown(`mux: ${e instanceof Error ? e.message : String(e)}`);\n }\n if (pane.state === \"running\") return { kind: \"running\" };\n if (pane.state === \"absent\") return { kind: \"dead\", reason: \"pane gone\" };\n // The transport exited: `localPaneAlive` reads it as dead, so the exec reclaims its channel.\n if (!sameRow(db, agent)) return { kind: \"dead\", reason: \"the agent was replaced\" };\n let run: Awaited<ReturnType<typeof runHostTemplate>>;\n try {\n run = await runHostTemplate(\n db,\n host,\n \"exec\",\n `gate:${agent.workstreamName}/${agent.name}`,\n { cmd: readCommand(token), cwd: \".\" },\n { paneAlive: localPaneAlive },\n );\n } catch (e) {\n return unknown(`result read: ${e instanceof Error ? e.message : String(e)}`);\n }\n if (!sameRow(db, agent)) return { kind: \"dead\", reason: \"the agent was replaced\" };\n if (run.exitCode !== 0) {\n return unknown(\n run.exitCode === null ? \"result read timed out\" : `result read failed (exit ${run.exitCode})`,\n );\n }\n if (!run.stdout.split(\"\\n\").some((l) => l.trim() === \"MU_GATE_READ\")) {\n return unknown(\"the host's answer carried no result tag\");\n }\n const rec = parseRecord(run.stdout, token);\n return rec.kind === \"code\" ? { kind: \"exited\", code: rec.code } : rec;\n}\n\n/**\n * Remove the gate's own remote record (its token's files only: a replacement\n * has another token). Best effort, one exec under its own channel; the caller\n * has already proven the pane dead and freed its channel.\n */\nexport async function cleanGateResult(db: Db, agent: AgentRow): Promise<boolean> {\n const token = agent.gateToken;\n const host = agent.host;\n if (token === null || host === null) return false;\n try {\n const r = await runHostTemplate(\n db,\n host,\n \"exec\",\n `gate-clean:${agent.workstreamName}/${agent.name}`,\n { cmd: cleanCommand(token), cwd: \".\" },\n { paneAlive: localPaneAlive },\n );\n return r.exitCode === 0;\n } catch {\n return false;\n }\n}\n","// The agent lock: one cross-process lock per (workstream, agent name), held\n// by every step that destroys or re-stages that name's disk state: `agent\n// close` (the whole sequence: kill, worktree release, row delete) and a\n// `--worktree` spawn's staging and rollback (reclaim, create, register,\n// remove). Row writes by anything else (reconcile, teardown, plain spawn)\n// do not take it; they carry their own compare-and-swap on the row's\n// identity (`deleteAgent`'s `expected`).\n//\n// FAIL CLOSED. Unlike the spawn lock (which only narrows a race and runs\n// unlocked when it cannot lock), a destructive agent step never runs\n// unlocked: no lock dir, or a live holder past the deadline, throws\n// `AgentLockBusyError` and nothing is done. STRICT ownership: the lock is\n// stolen only from a holder whose process is gone (a close can spend a\n// long time in git cleanup, well past the spawn lock's stale budget), and\n// a holder never removes a lock someone else took. See src/file-lock.ts.\n//\n// The lock lives beside the DB it protects (`<db dir>/locks/`), so two\n// databases never contend and a test DB in a temp dir locks in that dir.\n\nimport { createHash } from \"node:crypto\";\nimport { dirname, join } from \"node:path\";\nimport type { Db } from \"../db.js\";\nimport { locksDir, withFileLock } from \"../file-lock.js\";\nimport { AgentLockBusyError } from \"./errors.js\";\n\n/** Lock directory for an agent name. Workstream and agent names share the\n * charset `[a-z0-9_-]`, so `.` keeps `a-b`+`c` apart from `a`+`b-c`. */\nexport function agentLockPath(db: Db, workstream: string, name: string): string {\n const base = db.memory || db.name === \"\" ? locksDir() : join(dirname(db.name), \"locks\");\n return join(base, `agent-${workstream}.${name}.lock`);\n}\n\n/** Run `fn` holding the agent's lock; throws `AgentLockBusyError` instead\n * of running when it cannot be taken. */\nexport async function withAgentLock<T>(\n db: Db,\n workstream: string,\n name: string,\n fn: () => Promise<T>,\n opts?: { acquireTimeoutMs?: number },\n): Promise<T> {\n return withFileLock(agentLockPath(db, workstream, name), `${workstream}/${name}`, fn, {\n strict: true,\n ...(opts?.acquireTimeoutMs !== undefined ? { acquireTimeoutMs: opts.acquireTimeoutMs } : {}),\n timeoutEnvVar: \"MU_AGENT_LOCK_TIMEOUT_MS\",\n onUnavailable: () => {\n throw new AgentLockBusyError(name, workstream);\n },\n });\n}\n\n/**\n * The spawn-attempt lock: one cross-process lock per (task, attempt key),\n * held for a whole `agent spawn --task` attempt (reservation to outcome), so\n * two callers of the same attempt never both spawn or send. Strict like the\n * agent lock (fails closed, stolen only from a dead holder), and unlike the\n * advisory spawn lock, which runs unlocked when it cannot lock. A long DB\n * transaction is not the mechanism: the attempt spans panes and sockets.\n */\nexport function spawnAttemptLockPath(db: Db, taskId: number, attemptKey: string): string {\n const base = db.memory || db.name === \"\" ? locksDir() : join(dirname(db.name), \"locks\");\n const key = createHash(\"sha256\").update(attemptKey).digest(\"hex\").slice(0, 16);\n return join(base, `attempt-${taskId}.${key}.lock`);\n}\n\nexport async function withSpawnAttemptLock<T>(\n db: Db,\n taskId: number,\n attemptKey: string,\n fn: () => Promise<T>,\n onBusy: () => never,\n): Promise<T> {\n return withFileLock(\n spawnAttemptLockPath(db, taskId, attemptKey),\n `task ${taskId}/${attemptKey}`,\n fn,\n {\n strict: true,\n timeoutEnvVar: \"MU_AGENT_LOCK_TIMEOUT_MS\",\n onUnavailable: onBusy,\n },\n );\n}\n","// mu — generic cross-process advisory lock, via atomic `fs.mkdir`.\n//\n// Extracted from src/agents/spawn-lock.ts, which had exactly this logic\n// keyed to a tmux session name. Segments need the same primitive keyed to\n// a sync directory, and two copies of a lock implementation is how they\n// drift — so the mechanism lives here once and both callers name their own\n// resource. spawn-lock.ts keeps its session-specific wrapper and its\n// tests; only the body moved.\n//\n// Why a lockfile at all: every `mu` invocation is a separate short-lived\n// process, so there is no in-process mutex to lean on. `fs.mkdir` is\n// atomic and fails EEXIST when the directory exists — the classic\n// primitive, no dependency (honours the ROADMAP anti-feature pledge).\n//\n// BEST-EFFORT BY DEFAULT. A lock that cannot be taken (a read-only state\n// dir, or still contended at the deadline) falls through to running the\n// body UNLOCKED rather than failing the command. That suits the spawn\n// lock, which only narrows a race. A caller whose body must never run\n// unlocked passes `onUnavailable`, which runs INSTEAD of the body: the\n// segment flush does, because an unlocked append can interleave partial\n// lines or race another flush's self-repair truncate.\n//\n// STRICT MODE (`strict: true`, the agent lock) is a different protocol, and\n// fails closed on every error:\n// - PUBLISH. The lock dir is built complete (meta.json inside) under a\n// private name and `rename`d onto the lock path: it appears whole or\n// not at all, so no lock without an owner record exists, and a failed\n// metadata write is a failed acquire (`onUnavailable`), never a body\n// run without a lock.\n// - STALE RECLAIM. An aged lock is reclaimed only when its holder's pid\n// is gone and its record is readable. Reclaiming takes an O_EXCL claim\n// file (`<lock>.reclaim`), re-probes the SAME holder under the claim,\n// and only then removes the dir: two removers cannot both proceed, and\n// none can remove a newer holder that took the path after its probe.\n// An unreadable, missing or foreign record is never reclaimed. A claim left by a\n// crashed remover blocks (fails closed) until it is removed by hand.\n// - RELEASE is by token: a holder removes the lock only if it is still its.\n\nimport { randomBytes } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { defaultStateDir } from \"./db.js\";\n\n/** Sub-directory of the state dir holding lock directories. */\nexport function locksDir(): string {\n return join(defaultStateDir(), \"locks\");\n}\n\n/** Default: max time to wait to acquire before giving up. */\nconst DEFAULT_ACQUIRE_TIMEOUT_MS = 15_000;\n/** A held lock older than this is presumed abandoned (crashed process). */\nconst DEFAULT_STALE_LOCK_MS = 30_000;\n/** Poll interval while spinning. */\nconst RETRY_INTERVAL_MS = 25;\n\nexport interface FileLockOptions<T = unknown> {\n acquireTimeoutMs?: number;\n staleLockMs?: number;\n /** Env var consulted for the acquire timeout, if any. */\n timeoutEnvVar?: string;\n /** Run instead of `fn` when the lock cannot be taken (contended past\n * the deadline, or the lock dir cannot be created). Absent, `fn` runs\n * unlocked. */\n onUnavailable?: () => T;\n /** Strict ownership (see the header): an aged lock is reclaimed only\n * when the process that took it is gone (pid probe on this host), never\n * because it is old, and only under an exclusive claim. A holder doing\n * slow work (git cleanup, a pane kill) keeps its lock for as long as it\n * lives. Anything unreadable or failing is unavailable. Pair it with\n * `onUnavailable` to fail closed. */\n strict?: boolean;\n}\n\nconst sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));\n\nfunction resolveTimeout(opts?: FileLockOptions<unknown>): number {\n const envVar = opts?.timeoutEnvVar;\n if (envVar !== undefined) {\n const raw = process.env[envVar];\n if (raw !== undefined && raw !== \"\") {\n const n = Number.parseInt(raw, 10);\n if (Number.isFinite(n) && n >= 0) return n;\n }\n }\n return opts?.acquireTimeoutMs ?? DEFAULT_ACQUIRE_TIMEOUT_MS;\n}\n\n/** True unless `pid` is certainly gone (ESRCH). EPERM means it exists. */\nfunction pidMayBeAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code !== \"ESRCH\";\n }\n}\n\n/** Best-effort staleness probe (legacy mode): old enough. A vanished lock\n * returns false so the caller simply retries the mkdir. */\nasync function isStale(path: string, staleMs: number): Promise<boolean> {\n try {\n const s = await stat(path);\n return Date.now() - s.mtimeMs > staleMs;\n } catch {\n return false;\n }\n}\n\n/** Strict probe: the token of a lock that is old AND whose holder is\n * certainly gone; undefined for anything else, unreadable included. */\nasync function staleHolder(path: string, staleMs: number): Promise<string | undefined> {\n try {\n const s = await stat(path);\n if (Date.now() - s.mtimeMs <= staleMs) return undefined;\n } catch {\n return undefined;\n }\n const meta = await readFileLockMeta(path);\n if (meta === null || typeof meta.pid !== \"number\" || typeof meta.token !== \"string\") {\n return undefined;\n }\n return pidMayBeAlive(meta.pid) ? undefined : meta.token;\n}\n\n/** Remove a stale strict lock, exclusively. True when it is gone and the\n * caller should retry the acquire; false when it is not stale, someone\n * else is reclaiming, or anything failed. */\nasync function reclaimStale(lockPath: string, staleMs: number): Promise<boolean> {\n const seen = await staleHolder(lockPath, staleMs);\n if (seen === undefined) return false;\n const claim = `${lockPath}.reclaim`;\n try {\n await writeFile(claim, String(process.pid), { flag: \"wx\" });\n } catch {\n return false;\n }\n try {\n // Under the claim no other remover runs, and a stale lock is not\n // taken (the path is occupied): the holder seen above is still the\n // one there, or the lock is already gone. Anything else is left alone.\n if ((await staleHolder(lockPath, staleMs)) !== seen) return false;\n await rm(lockPath, { recursive: true });\n return true;\n } catch {\n return false;\n } finally {\n await rm(claim, { force: true }).catch(() => {});\n }\n}\n\n/** Strict acquire: the token when taken, undefined when unavailable. */\nasync function acquireStrict(\n lockPath: string,\n label: string,\n staleMs: number,\n deadline: number,\n): Promise<string | undefined> {\n const token = randomBytes(8).toString(\"hex\");\n const tmp = `${lockPath}.acq-${token}`;\n try {\n await mkdir(tmp);\n await writeFile(\n join(tmp, \"meta.json\"),\n JSON.stringify({ pid: process.pid, label, acquiredAt: new Date().toISOString(), token }),\n );\n for (;;) {\n try {\n await rename(tmp, lockPath); // whole or not at all; fails while held\n return token;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\" && code !== \"ENOTEMPTY\") return undefined;\n }\n if (await reclaimStale(lockPath, staleMs)) continue;\n if (Date.now() >= deadline) return undefined;\n await sleep(RETRY_INTERVAL_MS);\n }\n } catch {\n return undefined;\n } finally {\n await rm(tmp, { recursive: true, force: true }).catch(() => {});\n }\n}\n\n/**\n * Run `fn` while holding the lock directory at `lockPath`.\n *\n * Releases in a `finally`, so a throwing `fn` never leaks the lock.\n * Records pid + acquisition time in `meta.json` for stale-lock\n * diagnostics.\n */\nexport async function withFileLock<T>(\n lockPath: string,\n label: string,\n fn: () => Promise<T>,\n opts?: FileLockOptions<T>,\n): Promise<T> {\n const staleMs = opts?.staleLockMs ?? DEFAULT_STALE_LOCK_MS;\n const deadline = Date.now() + resolveTimeout(opts);\n const onUnavailable = opts?.onUnavailable;\n const unlocked = async (): Promise<T> =>\n onUnavailable === undefined ? await fn() : onUnavailable();\n let held = false;\n\n try {\n await mkdir(dirname(lockPath), { recursive: true });\n } catch {\n // Cannot even create the locks dir: run unlocked rather than refuse.\n return await unlocked();\n }\n\n if (opts?.strict === true) {\n const token = await acquireStrict(lockPath, label, staleMs, deadline);\n if (token === undefined) return await unlocked();\n try {\n return await fn();\n } finally {\n // Only a lock that is still ours: never a newer holder's.\n if ((await readFileLockMeta(lockPath))?.token === token) {\n await rm(lockPath, { recursive: true, force: true }).catch(() => {});\n }\n }\n }\n\n while (!held) {\n try {\n await mkdir(lockPath); // atomic; EEXIST if already held\n held = true;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") return await unlocked();\n if (await isStale(lockPath, staleMs)) {\n await rm(lockPath, { recursive: true, force: true }).catch(() => {});\n continue;\n }\n if (Date.now() >= deadline) return await unlocked();\n await sleep(RETRY_INTERVAL_MS);\n }\n }\n\n // Our token: release removes the lock only if it is still ours. A lock\n // stolen from us (aged out, legacy mode) now belongs to its new holder.\n const token = randomBytes(8).toString(\"hex\");\n const wrote = await writeFile(\n join(lockPath, \"meta.json\"),\n JSON.stringify({ pid: process.pid, label, acquiredAt: new Date().toISOString(), token }),\n ).then(\n () => true,\n () => false,\n );\n\n try {\n return await fn();\n } finally {\n // Wrote no record: nothing to compare, remove as before. Wrote one and\n // it is gone or another's: the lock was stolen, and is not ours to remove.\n if (!wrote || (await readFileLockMeta(lockPath))?.token === token) {\n await rm(lockPath, { recursive: true, force: true }).catch(() => {});\n }\n }\n}\n\n/** Read a held lock's metadata, or null. Exposed for tests. */\nexport async function readFileLockMeta(\n lockPath: string,\n): Promise<{ pid: number; label: string; acquiredAt: string; token?: string } | null> {\n try {\n const raw = await readFile(join(lockPath, \"meta.json\"), \"utf8\");\n return JSON.parse(raw) as { pid: number; label: string; acquiredAt: string; token?: string };\n } catch {\n return null;\n }\n}\n","// mu — `agent close`: preview and apply, fenced on the agent's identity.\n//\n// Close is destructive and slow (a pane kill, git cleanup of the worktree,\n// the row delete), and every `await` in it is a window in which the agent\n// can be replaced under the same name. Three guards, in order:\n//\n// 1. PREVIEW. `previewClose` writes nothing and prints the blast radius\n// plus `agentRevision` (src/revision.ts). `closeAgent` with\n// `ifRevision` recomputes it under the agent lock and refuses, before\n// anything is killed, when it moved (`RevisionMismatchError`, exit 4).\n// 2. LOCK. The whole sequence holds the agent lock, fail-closed and\n// strict (src/agents/lock.ts); a `--worktree` spawn's staging and\n// rollback take the same one, so none of them re-stages the disk\n// state this close is removing.\n// 3. IDENTITY. The row is captured with its incarnation. After the\n// kill and the liveness probe it is read again: a different\n// incarnation or pane means the name was replaced, and the close stops\n// (`AgentReplacedError`) before touching the worktree. The final delete\n// and the socket unlink compare the incarnation too (`deleteAgent`'s\n// `expected`): a replacement's row, socket and tasks are never removed.\n//\n// Without `ifRevision` the SDK closes at once (internal callers, tests);\n// guards 2 and 3 still apply. The CLI previews unless `--if` is given.\n\nimport { type AgentRow, deleteAgent, getAgentForCleanup, isPendingPaneId } from \"../agents.js\";\nimport type { Db } from \"../db.js\";\nimport { releaseHostChannelsForAgent } from \"../hosts.js\";\nimport { emitEvent } from \"../logs.js\";\nimport { activeMux } from \"../mux.js\";\nimport { closeRemoteWorktree, localPaneAlive } from \"../remote-agent.js\";\nimport { selectRemoteRecovery } from \"../remote-recovery.js\";\nimport { agentRevision, assertRevision } from \"../revision.js\";\nimport { runInFlight, setAgentDone, workOf } from \"../wait-owed.js\";\nimport {\n assertReleasable,\n getWorktreeAt,\n getWorktreeFor,\n type ReleasedWorktree,\n releaseWorktree,\n type WorktreeState,\n worktreeState,\n} from \"../worktree.js\";\nimport { closeRecovery, recoveryPreview } from \"./close-recovery.js\";\nimport { AgentPaneStillAliveError, AgentReplacedError } from \"./errors.js\";\nimport { cleanGateResult } from \"./gate.js\";\nimport { withAgentLock } from \"./lock.js\";\n\nexport interface CloseAgentOptions {\n /**\n * Throw the agent's worktree away even when it has uncommitted work.\n * Lossy; never makes a branch. Without it a dirty worktree refuses\n * (WorktreeDirtyError) before anything is killed.\n */\n discard?: boolean;\n /**\n * A remote worktree whose HEAD was never collected: keep it as the remote\n * branch `mu/<ws>/<agent>-<sha12>` and remove the worktree. Never overrides\n * uncommitted work, and `discard` does not stand in for it. A local\n * worktree always keeps its branch; the flag is ignored there.\n */\n keepBranch?: boolean;\n /**\n * The `revision` of `previewClose`. Checked under the agent lock before\n * anything is killed (`RevisionMismatchError`, exit 4, nothing done). An\n * agent that no longer exists is a no-op whatever the value: nothing is\n * left to destroy. Absent: close without a preview.\n */\n ifRevision?: number;\n /**\n * Close the remote worktree a REMOVED agent left (`remote_recovery`, the\n * original registry incarnation it names), not a live agent. Required when\n * several records share the name; without it exactly one selects itself.\n * Refuses while an agent holds the name or the path.\n */\n recoveryId?: number;\n /**\n * Close past a refusal the caller owns: the pane's liveness could not be\n * checked (the probe failed, or no multiplexer answers), a process has a\n * file in the worktree open for writing, or no scan could prove none has\n * (no /proc, no lsof). Never overrides a pane that answers alive, nor\n * uncommitted work. Without it these refuse (`AgentPaneStillAliveError`\n * state `unknown`, `WorktreeHeldError`) with everything kept.\n */\n force?: boolean;\n}\n\nexport interface CloseAgentResult {\n killedPane: boolean;\n deletedRow: boolean;\n /** What the close rule did to the agent's worktree (a remote one included); null when it had none. */\n worktree: ReleasedWorktree | null;\n /** Set when a remote recovery record was closed: its id and whether the record was removed. */\n recovery?: { id: number; deleted: boolean };\n}\n\n/** What `agent close` would do, read only. */\nexport interface ClosePreview {\n agentName: string;\n workstream: string;\n /** `agent`: a registry row; `orphan-worktree`: only a registered worktree\n * is left (a failed spawn or an earlier close); `recovery`: the agent row\n * is gone but `remote_recovery` kept its remote worktree; `none`: nothing. */\n kind: \"agent\" | \"orphan-worktree\" | \"recovery\" | \"none\";\n /** `agentRevision`: the value for `--if`. 0 when `kind` is `none`. */\n revision: number;\n /** The registry incarnation (`AgentRow.incarnation`); null without a row. */\n incarnation: number | null;\n paneId: string | null;\n /** Tasks the row owns, any workstream. IN_PROGRESS ones go back to OPEN. */\n ownedTasks: { ref: string; status: string; reverts: boolean }[];\n /** The worktree the close rule would handle; null when none is registered. */\n worktree: { path: string; state: WorktreeState } | null;\n /**\n * The remote worktree of a `--host --worktree` agent that the close removes\n * under the remote rule (`closeRemoteWorktree`), read from the row alone:\n * a preview runs no remote command (at `--max-sessions 1` the live pane\n * holds the only channel). Null for a local or `--cwd`-only agent.\n */\n remote: { host: string; path: string; base: string; collectedHead: string | null } | null;\n /**\n * The selected recovery record (`kind` `recovery`), under its own id: the\n * ORIGINAL registry incarnation, never `incarnation`. `refusal` is why an\n * apply would refuse right now (a current agent, a changed profile), null\n * when it would go on. Null otherwise.\n */\n recovery: {\n id: number;\n aside: string;\n reason: string;\n preservedAt: string;\n refusal: string | null;\n } | null;\n /** True when the close would refuse for uncommitted work (no `discard`). */\n refusesDirty: boolean;\n discard: boolean;\n keepBranch: boolean;\n}\n\nfunction remoteOf(agent: AgentRow | undefined): ClosePreview[\"remote\"] {\n if (agent?.host == null || agent.cwd === null || agent.base === null) return null;\n return {\n host: agent.host,\n path: agent.cwd,\n base: agent.base,\n collectedHead: agent.collectedHead,\n };\n}\n\nfunction ownedTasksOf(db: Db, agent: AgentRow): ClosePreview[\"ownedTasks\"] {\n const rows = db\n .prepare(\n `SELECT w.name || '/' || t.local_id AS ref, t.status AS status\n FROM tasks t JOIN workstreams w ON w.id = t.workstream_id\n WHERE t.owner_id = ? ORDER BY w.name, t.local_id`,\n )\n .all(agent.incarnation) as { ref: string; status: string }[];\n return rows.map((r) => ({ ...r, reverts: r.status === \"IN_PROGRESS\" }));\n}\n\n/** The worktree row the close would handle: the one the agent's `cwd` names,\n * else (an orphan) the newest registered for the name. */\nfunction worktreeOf(db: Db, workstream: string, name: string, agent?: AgentRow) {\n if (agent === undefined) return getWorktreeFor(db, workstream, name);\n // A remote agent's cwd is a path on its host: the local registry knows nothing\n // of it (its remote worktree is closed by `closeRemoteWorktree`).\n if (agent.host !== null) return undefined;\n return agent.cwd === null ? undefined : getWorktreeAt(db, agent.cwd);\n}\n\n/** Preview a close: nothing is written, nothing is killed. The one read an\n * apply is derived from, for orphans and torn-down workstreams too.\n *\n * Identity and revision come from ONE read transaction, taken after the\n * slow worktree check: the agent row, its worktree row, the owned tasks\n * and the revision are all of the same snapshot, also against another\n * process's writes. The check awaits git, so\n * the name may be replaced meanwhile; the snapshot taken before it is then\n * stale and the read is retried, and a name that will not hold still is\n * refused (`AgentReplacedError`) rather than described half and half. */\nexport async function previewClose(\n db: Db,\n name: string,\n opts: { workstream: string; discard?: boolean; keepBranch?: boolean; recoveryId?: number },\n): Promise<ClosePreview> {\n const discard = opts.discard === true;\n for (let attempt = 0; attempt < 3; attempt++) {\n const agent = getAgentForCleanup(db, name, opts.workstream);\n const row = worktreeOf(db, opts.workstream, name, agent);\n const state = row === undefined ? undefined : await worktreeState(row.path, row.base, row.root);\n // No await from here to the return, and ONE read transaction: under WAL\n // its first read pins a snapshot, so another mu process committing a\n // replacement cannot land between the identity and the revision.\n const preview = db.transaction((): ClosePreview | undefined => {\n const now = getAgentForCleanup(db, name, opts.workstream);\n const nowRow = worktreeOf(db, opts.workstream, name, now);\n // The git check above is of the pre-await row: stale when it moved.\n if (\n now?.incarnation !== agent?.incarnation ||\n now?.paneId !== agent?.paneId ||\n nowRow?.path !== row?.path\n ) {\n return undefined;\n }\n // A removed agent's remote worktree: asked for by id, or the one left\n // when nothing else is. Several records refuse (ambiguous) here.\n const rec =\n opts.recoveryId !== undefined || (now === undefined && nowRow === undefined)\n ? selectRemoteRecovery(db, opts.workstream, name, opts.recoveryId)\n : undefined;\n // A named record that is gone is \"nothing\", never the live agent.\n if (rec === undefined && opts.recoveryId !== undefined) {\n return {\n agentName: name,\n workstream: opts.workstream,\n kind: \"none\",\n revision: 0,\n incarnation: null,\n paneId: null,\n ownedTasks: [],\n worktree: null,\n remote: null,\n recovery: null,\n refusesDirty: false,\n discard,\n keepBranch: opts.keepBranch === true,\n };\n }\n if (rec !== undefined) {\n return {\n agentName: name,\n workstream: opts.workstream,\n kind: \"recovery\",\n revision: agentRevision(db, opts.workstream, name, opts.recoveryId),\n incarnation: null,\n paneId: null,\n ownedTasks: [],\n worktree: null,\n ...recoveryPreview(db, rec),\n refusesDirty: false,\n discard,\n keepBranch: opts.keepBranch === true,\n };\n }\n return {\n agentName: name,\n workstream: opts.workstream,\n kind: now ? \"agent\" : nowRow ? \"orphan-worktree\" : \"none\",\n revision: opts.recoveryId === undefined ? agentRevision(db, opts.workstream, name) : 0,\n incarnation: now?.incarnation ?? null,\n paneId: now?.paneId ?? null,\n ownedTasks: now ? ownedTasksOf(db, now) : [],\n worktree: nowRow && state ? { path: nowRow.path, state } : null,\n remote: remoteOf(now),\n recovery: null,\n refusesDirty: state === \"dirty\" && !discard,\n discard,\n keepBranch: opts.keepBranch === true,\n };\n })();\n if (preview !== undefined) return preview;\n }\n throw new AgentReplacedError(name, opts.workstream);\n}\n\n/**\n * Close an agent: kill its pane, apply the worktree close rule, remove its\n * DB row. Idempotent: an unknown agent is a no-op, a gone pane is fine.\n *\n * The worktree rule (src/worktree.ts `releaseWorktree`): dirty refuses\n * unless `discard`; clean and merged is removed; clean with unmerged\n * commits keeps a branch `mu/<ws>/<agent>-<sha12>` and is removed. The\n * refusal happens BEFORE the pane is killed. With no agent row but a\n * registered worktree (an earlier close or rollback left it) the same rule\n * runs on the leftover, so `agent close <name>` is the one way out.\n *\n * Fenced: see the header. Throws `AgentLockBusyError` (nothing done),\n * `RevisionMismatchError` (nothing done), `AgentReplacedError` (the\n * replacement is untouched).\n */\nexport async function closeAgent(\n db: Db,\n name: string,\n opts: CloseAgentOptions & { workstream: string },\n): Promise<CloseAgentResult> {\n return withAgentLock(db, opts.workstream, name, () => closeLocked(db, name, opts));\n}\n\nasync function closeLocked(\n db: Db,\n name: string,\n opts: CloseAgentOptions & { workstream: string },\n): Promise<CloseAgentResult> {\n const discard = opts.discard === true;\n const previewCommand = `mu agent close ${name} -w ${opts.workstream}`;\n const fence = (): void => {\n assertRevision(opts.ifRevision, agentRevision(db, opts.workstream, name, opts.recoveryId), {\n subject: `agent ${name}`,\n previewCommand,\n });\n };\n const agent = getAgentForCleanup(db, name, opts.workstream);\n const orphan = agent ? undefined : getWorktreeFor(db, opts.workstream, name);\n // A removed agent's remote worktree (`remote_recovery`): by id, or the one\n // left when there is no row and no local orphan. A gone record is a no-op.\n if (opts.recoveryId !== undefined || (agent === undefined && orphan === undefined)) {\n const rec = selectRemoteRecovery(db, opts.workstream, name, opts.recoveryId);\n if (rec === undefined) return { killedPane: false, deletedRow: false, worktree: null };\n fence();\n return closeRecovery(db, rec, {\n keepBranch: opts.keepBranch === true,\n force: opts.force === true,\n });\n }\n if (!agent) {\n if (orphan === undefined) return { killedPane: false, deletedRow: false, worktree: null };\n fence();\n const worktree = await releaseWorktree(db, orphan, { discard, force: opts.force === true });\n emitEvent(db, opts.workstream, \"agent.close\", closeLine(name, undefined, worktree));\n return { killedPane: false, deletedRow: false, worktree };\n }\n const row = worktreeOf(db, opts.workstream, name, agent);\n if (row !== undefined) await assertReleasable(row, { discard });\n const mux = await activeMux().catch(() => undefined);\n // Before the kill (the pane then answers nothing): is its run still going?\n const running = await runInFlight(agent);\n // The awaits above are where a replacement lands. Nothing below may act\n // on a name that is not the incarnation this close captured.\n const replaced = (): boolean => {\n const now = getAgentForCleanup(db, name, opts.workstream);\n return now !== undefined && !sameIncarnation(now, agent);\n };\n // Right before the kill, with nothing awaited in between: the git check\n // above is slow, and the identity (and the preview) must still hold when\n // the pane dies. The kill names the pane of the incarnation checked here.\n if (replaced()) throw new AgentReplacedError(name, opts.workstream);\n fence();\n // (The mux is resolved first, so nothing is awaited between the checks\n // and the kill.) A row that vanished (pruned as a ghost) has no pane left\n // to name: nothing to kill.\n if (getAgentForCleanup(db, name, opts.workstream) !== undefined) {\n await mux?.killPane(agent.paneId).catch(() => {\n /* idempotent — pane may already be gone, or the mux with it */\n });\n }\n // The row rule: never delete (nor release a claim, a worktree or a host\n // channel for) a row whose recorded pane may be alive. A pane that survives\n // the kill (moved, or the kill failed) keeps its row; so does one nobody\n // could ask (the probe failed, or no multiplexer answers), in every\n // workstream, unless `force` says it is gone. A pending placeholder never\n // had a pane. Past this check the pane is gone (proven, or forced).\n let alive: boolean | \"unknown\" = false;\n let why: string | undefined;\n if (!isPendingPaneId(agent.paneId)) {\n if (mux === undefined) {\n alive = \"unknown\";\n why = \"no multiplexer answers\";\n } else {\n try {\n alive = await mux.paneAlive(agent.paneId);\n } catch (err) {\n alive = \"unknown\";\n why = err instanceof Error ? err.message.split(\"\\n\")[0] : String(err);\n }\n }\n }\n if (alive === true || (alive === \"unknown\" && opts.force !== true)) {\n throw new AgentPaneStillAliveError(name, agent.workstreamName, agent.paneId, alive, why);\n }\n if (replaced()) throw new AgentReplacedError(name, opts.workstream);\n // Re-checks the state: a write after the pre-check still refuses, with\n // the agent row kept so the close can be retried. A remote worktree is\n // judged only now, after the kill: the pane held the host's channel (at cap\n // 1 the only one). Its pane is dead, so admission reclaims that channel.\n let worktree: ReleasedWorktree | null = null;\n // Set once closeRemoteWorktree is about to run: it returns only when the tree\n // is removed, kept on a branch or gone (anything else throws, row kept), so\n // the row's deletion needs no recovery record.\n let remoteHandled = false;\n if (row !== undefined)\n worktree = await releaseWorktree(db, row, { discard, force: opts.force === true });\n else if (remoteOf(agent) !== null) {\n remoteHandled = true;\n // The pane is gone (checked above): free its channel by id + pane.\n releaseHostChannelsForAgent(db, agent.incarnation, agent.paneId);\n worktree = await closeRemoteWorktree(db, agent, {\n keepBranch: opts.keepBranch === true,\n force: opts.force === true,\n paneAlive: localPaneAlive,\n beforeRemove: () => {\n if (replaced()) throw new AgentReplacedError(name, opts.workstream);\n },\n });\n if (replaced()) throw new AgentReplacedError(name, opts.workstream);\n }\n // A remote command gate: its pane is dead (probed above), so free its channel by id + pane and\n // remove ITS result record (its own token's files; a replacement has another token). Best effort:\n // a host that cannot answer leaves one stray file, never a blocked close.\n if (agent.gateToken !== null && agent.host !== null) {\n releaseHostChannelsForAgent(db, agent.incarnation, agent.paneId);\n await cleanGateResult(db, agent);\n if (replaced()) throw new AgentReplacedError(name, opts.workstream);\n }\n const openAtClose = workOf(db, agent.incarnation).open;\n const deletedRow = deleteAgent(\n db,\n name,\n agent.workstreamName,\n { incarnation: agent.incarnation, paneId: agent.paneId },\n { preserve: !remoteHandled },\n );\n if (!deletedRow && replaced()) throw new AgentReplacedError(name, opts.workstream);\n // A deliberate close of a worker with no open task and no run in flight is the end of its work,\n // not a death: the wait engine drops its ref (src/wait-owed.ts). A busy one is still news.\n if (deletedRow && !running && openAtClose === 0)\n setAgentDone(db, agent.workstreamName, name, true);\n // Machine-local table (`agents`): no trigger, so this emit is the\n // only record.\n emitEvent(db, agent.workstreamName, \"agent.close\", closeLine(name, agent.paneId, worktree));\n return { killedPane: true, deletedRow, worktree };\n}\n\nfunction sameIncarnation(a: AgentRow, b: AgentRow): boolean {\n return a.incarnation === b.incarnation && a.paneId === b.paneId;\n}\n\nfunction closeLine(name: string, paneId: string | undefined, wt: ReleasedWorktree | null): string {\n const bits = [paneId === undefined ? undefined : `pane=${paneId}`];\n if (wt !== null) {\n bits.push(`worktree ${wt.action}${wt.branch === undefined ? \"\" : ` as ${wt.branch}`}`);\n }\n const detail = bits.filter((b) => b !== undefined).join(\", \");\n return `agent close ${name}${detail === \"\" ? \"\" : ` (${detail})`}`;\n}\n","// mu — delegate outcome: what one finished `mu agent wait` means for a\n// delegate (a scratch agent started for one task).\n//\n// The classification lives here, not in the pi extension, so the\n// `mu_delegate` tool has no logic the CLI lacks (VISION § 1, The CLI\n// is the product, rule 2): `mu agent wait --json` reports it per\n// agent as `outcome`, and the extension only formats it.\n\nimport type { WaitSnapshot } from \"../wait.js\";\n\n/**\n * - `done`: the run settled with a final assistant text (`lastText`).\n * - `empty`: the run settled without one (or the agent has no\n * control socket to supply it); read the pane instead.\n * - `error`: the run stopped on an API error after pi's own retries\n * (`lastError`); the agent is alive and idle.\n * - `died`: the pane or its control socket went away mid-wait.\n * - `timeout`: still working when the wait gave up; the pane is untouched.\n * - `blocked`: not finished; pi is waiting on an extension dialog\n * (`blocked` holds its kind and title). The pane is untouched and needs\n * a human (or an attach) to answer it.\n * - `pending`: not finished, and the wait ended for another reason\n * (`--any` fired on a sibling).\n */\nexport type DelegateOutcome =\n | \"done\"\n | \"empty\"\n | \"error\"\n | \"died\"\n | \"blocked\"\n | \"timeout\"\n | \"pending\";\n\nexport function delegateOutcome(\n agent: Pick<WaitSnapshot, \"fired\" | \"dead\" | \"lastText\" | \"lastError\" | \"blocked\">,\n timedOut: boolean,\n): DelegateOutcome {\n if (agent.dead) return \"died\";\n if (agent.blocked !== undefined) return \"blocked\";\n if (agent.fired) {\n if (agent.lastError !== undefined) return \"error\";\n return agent.lastText ? \"done\" : \"empty\";\n }\n return timedOut ? \"timeout\" : \"pending\";\n}\n","// mu — AgentObservation: the one typed result of reading or watching an agent.\n//\n// Before this, the facts about an agent's run were split across three\n// shapes: `StateReading` (state, runs, pending; no text), the ctl `wait`\n// reply that `mu agent wait` consumed inline (text, error, session file; no\n// settled run count, incarnation or truncation flag), and\n// the snapshot `mu agent wait` read (neither). A caller that\n// needs to act on a settled run (apply its CLOSE block exactly once) needs\n// all of it at once: the registry id, the ctl incarnation, the SETTLED run\n// count, whether it settled, and the text with its truncation flag.\n//\n// This module is a seam, not an engine. It owns no polling and no loop:\n// `observeAgentStates` is one `readAgentStates` pass, and `watchAgentRun` is\n// the probe + ctl `wait` + drop fallback that `cmdAgentWait` carried inline,\n// moved here and returning observations. waitForEvents stays the only loop.\n//\n// Identity: `agentId` is the registry row id (a number, never reused);\n// `incarnation` is pi's own string (`--inc`). They are different things\n// and never substitute for one another.\n\nimport { dirname } from \"node:path\";\nimport type { RuntimeState, StateReading, StateSource } from \"../agent-state.js\";\nimport { agentKey, blockedReason, ctlRuntimeState, readAgentStates } from \"../agent-state.js\";\nimport type { AgentRow } from \"../agents.js\";\nimport type { SettledCloseInput } from \"../close-block.js\";\nimport { ctlProbe, ctlRequest } from \"../ctl/client.js\";\nimport { type CtlBlocked, INCARNATION_MISMATCH } from \"../ctl/protocol.js\";\nimport type { Db } from \"../db.js\";\nimport { AgentRestartedError } from \"./errors.js\";\nimport { type GateReading, readGate } from \"./gate.js\";\nimport { expectsCtl } from \"./transport.js\";\n\n/** Who an observation is about. */\nexport type ObservedAgent = Pick<\n AgentRow,\n \"name\" | \"workstreamName\" | \"paneId\" | \"cli\" | \"incarnation\" | \"gateToken\"\n>;\n\nexport interface AgentObservation {\n workstream: string;\n name: string;\n /** The registry row id (`AgentRow.incarnation`): a number, not pi's string. */\n agentId: number;\n paneId: string;\n /** Runtime state; null = the pane is gone (dead). */\n status: RuntimeState | null;\n /** Where the reading came from. */\n source: StateSource;\n /** When the state began (ms epoch), when the source says. */\n since: number | null;\n /** Why the state is unknown or blocked, when the source said. */\n reason?: string;\n /** How the control socket answered; absent for a non-pi agent. */\n ctl?: Exclude<StateReading[\"ctl\"], undefined>;\n /** A remote command gate that ended: the command's own numeric exit status (`status` is then null). */\n exit?: number;\n /** pi's process incarnation (ctl only; absent from older extensions). */\n incarnation?: string;\n /** pi's settled-run count: of the SETTLED run when `settled`, else the current count. */\n runs?: number;\n /** ctl only: pi holds queued messages. */\n pending?: boolean;\n /** True only for a ctl `wait` reply that ended `settled`: the run is over and its facts below are its own. */\n settled: boolean;\n /** The extension dialog pi is waiting on (status needs_permission). */\n blocked?: CtlBlocked;\n /** The settled run's final assistant text (tail-capped by the extension). */\n lastText?: string;\n /** True when `lastText` lost its head to the cap: a CLOSE block in it cannot be trusted. */\n lastTextTruncated?: boolean;\n /** The error that ended the settled run. */\n lastError?: string;\n /** The pi session file holding the run's full transcript. */\n sessionFile?: string;\n}\n\n/** A status read as an observation. `reading` undefined = the reader had no row. */\nexport function observationFromReading(\n agent: ObservedAgent,\n reading: StateReading | undefined,\n): AgentObservation {\n return {\n workstream: agent.workstreamName,\n name: agent.name,\n agentId: agent.incarnation,\n paneId: agent.paneId,\n status: reading?.alive === false ? null : (reading?.state ?? \"unknown\"),\n source: reading?.source ?? \"none\",\n since: reading?.since ?? null,\n ...(reading?.reason !== undefined ? { reason: reading.reason } : {}),\n ...(reading?.ctl !== undefined ? { ctl: reading.ctl } : {}),\n ...(reading?.incarnation !== undefined ? { incarnation: reading.incarnation } : {}),\n ...(reading?.runs !== undefined ? { runs: reading.runs } : {}),\n ...(reading?.pending !== undefined ? { pending: reading.pending } : {}),\n ...(reading?.blocked !== undefined ? { blocked: reading.blocked } : {}),\n settled: false,\n };\n}\n\n/** A remote command gate's reading as an observation: running reads busy, an ended one carries its numeric exit. */\nexport function observationFromGate(agent: ObservedAgent, gate: GateReading): AgentObservation {\n const base = {\n workstream: agent.workstreamName,\n name: agent.name,\n agentId: agent.incarnation,\n paneId: agent.paneId,\n source: \"none\" as const,\n since: null,\n settled: false,\n };\n switch (gate.kind) {\n case \"running\":\n return { ...base, status: \"busy\" };\n case \"exited\":\n return { ...base, status: null, exit: gate.code };\n case \"dead\":\n return { ...base, status: null, reason: gate.reason };\n case \"unknown\":\n return { ...base, status: \"unknown\", reason: gate.reason };\n }\n}\n\n/** One `readAgentStates` pass over `agents`, keyed `<workstream>/<name>`; a gate is read from its pane and result record instead. */\nexport async function observeAgentStates(\n db: Db,\n agents: readonly AgentRow[],\n): Promise<Map<string, AgentObservation>> {\n const gates = agents.filter((a) => a.gateToken !== null);\n const rest = agents.filter((a) => a.gateToken === null);\n const readings = await readAgentStates(rest, { stateDir: dirname(db.name) });\n const out = new Map<string, AgentObservation>(\n rest.map((a) => [agentKey(a), observationFromReading(a, readings.get(agentKey(a)))]),\n );\n const read = await Promise.all(gates.map((g) => readGate(db, g)));\n gates.forEach((g, i) => {\n const r = read[i];\n if (r !== undefined) out.set(agentKey(g), observationFromGate(g, r));\n });\n return out;\n}\n\n/** The facts of an observation that decide a settled close. */\nexport type SettleFacts = Pick<\n AgentObservation,\n | \"workstream\"\n | \"name\"\n | \"agentId\"\n | \"status\"\n | \"settled\"\n | \"incarnation\"\n | \"runs\"\n | \"lastText\"\n | \"lastTextTruncated\"\n | \"lastError\"\n>;\n\n/**\n * `applySettledClose`'s input for an observation, or undefined when it is\n * not one: it must be a ctl-settled run (`settled`), alive, with pi's\n * incarnation and the settled run count. Idle, blocked, unknown and\n * older-extension replies never qualify: a settle is never inferred.\n */\nexport function settledCloseInput(obs: SettleFacts): SettledCloseInput | undefined {\n if (!obs.settled || obs.status === null) return undefined;\n if (obs.incarnation === undefined || obs.runs === undefined) return undefined;\n return {\n workstream: obs.workstream,\n agent: obs.name,\n agentId: obs.agentId,\n incarnation: obs.incarnation,\n runs: obs.runs,\n lastText: obs.lastText ?? \"\",\n ...(obs.lastTextTruncated !== undefined ? { lastTextTruncated: obs.lastTextTruncated } : {}),\n settled: true,\n ...(obs.lastError !== undefined ? { lastError: obs.lastError } : {}),\n };\n}\n\nexport interface ObservedWatch {\n /** The agent's state when the watch started. */\n initial: AgentObservation;\n /** The run count the watch waits past (ctl `afterRuns`). */\n afterRuns: number;\n /** Resolves when the run ends. A REJECTION (AgentRestartedError) is fatal:\n * the incarnation the run belonged to is gone. */\n settled: Promise<AgentObservation>;\n}\n\n/**\n * Watch a pi agent's current or next run end over its control socket: one\n * ctl `wait` that the extension answers on `agent_settled`. `afterRuns`\n * (else a status read taken BEFORE the wait: a followUp queued while busy\n * runs in the same pi run) is the baseline; `inc` pins the pi process.\n *\n * undefined when the agent has no control socket or it does not answer\n * (the caller polls it instead). `signal` aborts the wait (`settled` then\n * resolves unknown, never dead and never settled).\n */\nexport async function watchAgentRun(\n agent: ObservedAgent,\n sock: string,\n signal: AbortSignal,\n opts: { afterRuns?: number; inc?: string },\n): Promise<ObservedWatch | undefined> {\n if (!expectsCtl(agent, sock)) return undefined;\n const base = {\n workstream: agent.workstreamName,\n name: agent.name,\n agentId: agent.incarnation,\n paneId: agent.paneId,\n };\n // With --after-runs the run past the baseline is the pending work: read\n // as busy until the wait settles; no status probe needed.\n let initial: AgentObservation = {\n ...base,\n status: \"busy\",\n source: \"ctl\",\n since: null,\n settled: false,\n };\n let afterRuns = opts.afterRuns;\n if (afterRuns === undefined) {\n const probe = await ctlProbe(sock);\n if (probe.kind !== \"ok\") return undefined;\n afterRuns = probe.status.runs;\n const { blocked } = probe.status;\n initial = {\n ...base,\n status: ctlRuntimeState(probe.status.state, blocked),\n source: \"ctl\",\n since: blocked?.since ?? probe.status.since,\n runs: probe.status.runs,\n pending: probe.status.pending,\n ...(probe.incarnation !== undefined ? { incarnation: probe.incarnation } : {}),\n ...(blocked !== undefined ? { blocked, reason: blockedReason(blocked) } : {}),\n settled: false,\n };\n }\n // returnOnBlocked: a dialog opening mid-run ends the wait instead of\n // holding it to --timeout. Older extensions ignore it.\n const req = {\n op: \"wait\",\n afterRuns,\n returnOnBlocked: true,\n ...(opts.inc !== undefined ? { incarnation: opts.inc } : {}),\n } as const;\n const restarted = (actual?: string): AgentRestartedError =>\n new AgentRestartedError(agent.name, agent.workstreamName, opts.inc ?? \"\", actual);\n const lost = (status: null | \"unknown\", reason?: string): AgentObservation => ({\n ...base,\n status,\n source: \"ctl\",\n since: null,\n ...(reason !== undefined ? { reason } : {}),\n settled: false,\n });\n const settled = ctlRequest(sock, req, { signal }).then(\n (reply): AgentObservation => {\n // A refused incarnation is fatal, never \"unknown\": the run is gone.\n if (!reply.ok && reply.error === INCARNATION_MISMATCH) throw restarted(reply.incarnation);\n if (!reply.ok) return lost(\"unknown\", reply.error);\n const facts = {\n ...base,\n source: \"ctl\" as const,\n since: reply.since ?? null,\n ...(reply.incarnation !== undefined ? { incarnation: reply.incarnation } : {}),\n ...(reply.runs !== undefined ? { runs: reply.runs } : {}),\n ...(reply.pending !== undefined ? { pending: reply.pending } : {}),\n };\n if (reply.ended === \"blocked\" && reply.blocked !== undefined) {\n return {\n ...facts,\n status: \"needs_permission\",\n blocked: reply.blocked,\n reason: blockedReason(reply.blocked),\n settled: false,\n };\n }\n if (reply.state === undefined) return lost(\"unknown\", \"ctl wait: no state\");\n return {\n ...facts,\n status: ctlRuntimeState(reply.state),\n // Only a reply that says it ended `settled` is a settled run; an\n // older extension's reply still fires the wait but never closes a task.\n settled: reply.ended === \"settled\",\n ...(reply.lastText !== undefined ? { lastText: reply.lastText } : {}),\n ...(reply.lastTextTruncated !== undefined\n ? { lastTextTruncated: reply.lastTextTruncated }\n : {}),\n ...(reply.lastError !== undefined ? { lastError: reply.lastError } : {}),\n ...(reply.sessionFile !== undefined ? { sessionFile: reply.sessionFile } : {}),\n };\n },\n // The connection dropped. A socket that still answers (pi's /new\n // restarts the session) hands back to polling; one that does not means\n // the pi that served it is gone. With `inc` an answering process must\n // also BE that incarnation: another one means the agent restarted and\n // the run is gone (fatal, never polled).\n async (): Promise<AgentObservation> => {\n if (signal.aborted) return lost(\"unknown\");\n const again = await ctlProbe(sock);\n if (\n opts.inc !== undefined &&\n again.kind === \"ok\" &&\n again.incarnation !== undefined &&\n again.incarnation !== opts.inc\n ) {\n throw restarted(again.incarnation);\n }\n return again.kind === \"ok\" ? lost(\"unknown\", \"ctl wait interrupted\") : lost(null);\n },\n );\n return { initial, afterRuns, settled };\n}\n","// mu — delegate calls as durable tasks (docs/VOCABULARY.md § delegate call).\n//\n// A `mu_delegate` call is a `kind=delegate` task with its brief, plus one\n// machine-local `delegate_calls` row keyed by a session-qualified `call_id`\n// (the caller's own id: `pi:<session>:<n>`). The task is the durable, waitable\n// face of the call (state, report, close); the row holds what is not\n// portable: the caller, the spawn request, the record target, the lifecycle.\n//\n// Writers (the only ones; the extension and the CLI both call these):\n// registerDelegateCall task + brief + row in ONE transaction; idempotent\n// per call_id; a changed request under it is refused.\n// markDelegate admission CAS: queued -> starting -> running, or\n// queued/starting -> refused, or refused -> queued |\n// starting (a reissue: same call, same task, by the\n// live runtime that will run or queue it).\n// `recording`/`done`/... are finishDelegate's.\n// finishDelegate THE recorder. `recording` is committed first, then\n// ONE op group writes the verdict note on the judged\n// task, the delegate's report and its close. If the\n// record fails the call is `failed`, never `done`,\n// and the answer is kept as the report. A duplicate\n// callback changes nothing.\n//\n// Readers: listDelegates, getDelegateCall, verdictTally. The tally attributes\n// ONE result per call_id (its own parsed `verdict`) to the qualified judged\n// task; it never scans label-matched notes (they carry no call id).\n\nimport { createHash } from \"node:crypto\";\nimport { dirname, join } from \"node:path\";\nimport type { Db, DELEGATE_CALL_STATES } from \"./db.js\";\nimport { parseVerdict, recordNote, type VerdictLabel } from \"./delegate-verdict.js\";\nimport { say } from \"./messages.js\";\nimport { withOpContext } from \"./op-context.js\";\nimport { addNote, addTask } from \"./tasks/edit.js\";\nimport { TaskNotFoundError } from \"./tasks/errors.js\";\nimport { closeTask, setTaskStatus } from \"./tasks/lifecycle.js\";\nimport { getTask } from \"./tasks/queries.js\";\n\n/**\n * Where a pane delegate's pi session lives, beside the DB at `dbPath`: one\n * directory per call task, so `mu delegates prune` removes exactly the pruned\n * calls' sessions. Out of pi's per-cwd folder, so the caller's `/resume` list\n * holds only its own sessions.\n */\nexport function delegateSessionDir(dbPath: string, workstream: string, task: string): string {\n return join(dirname(dbPath), \"delegate-sessions\", workstream, task);\n}\n\n/** A mux-free call's directory (receipt, log, pi session), beside the DB at `dbPath`. */\nexport function delegateProcessDir(dbPath: string, callId: string): string {\n return join(\n dirname(dbPath),\n \"delegate-process\",\n createHash(\"sha256\").update(callId).digest(\"hex\").slice(0, 16),\n );\n}\n\nexport { parseVerdict, type VerdictLabel } from \"./delegate-verdict.js\";\n\nexport type DelegateState = (typeof DELEGATE_CALL_STATES)[number];\nexport const TERMINAL_DELEGATE_STATES: readonly DelegateState[] = [\"done\", \"failed\", \"cancelled\"];\nconst TERMINAL = TERMINAL_DELEGATE_STATES;\nconst isTerminal = (s: DelegateState): boolean => TERMINAL.includes(s);\n\n/** What a call needs to start again from nothing: the prompt and the spawn options. */\nexport interface DelegateRequest {\n /** The whole prompt sent to the delegate (standing brief and task); also the task's brief note. */\n text: string;\n label?: string;\n cli?: string;\n model?: string;\n cwd?: string;\n workspace?: boolean;\n timeoutS?: number;\n keep?: boolean;\n}\n\nexport interface RecordRef {\n workstream: string;\n task: string;\n}\n\nexport interface DelegateRow {\n callId: string;\n /** The delegate task's local id, in `workstream`. */\n task: string;\n workstream: string;\n caller: string;\n state: DelegateState;\n wave: string | null;\n record: (RecordRef & { label: string | null }) | null;\n request: DelegateRequest;\n /** The agent that ran it, once running. */\n agent: string | null;\n /** The parsed verdict label of a done answer; null otherwise. */\n verdict: VerdictLabel | null;\n error: string | null;\n updatedAt: string;\n}\n\nexport class DelegateCallConflictError extends Error {\n override readonly name = \"DelegateCallConflictError\";\n constructor(\n public readonly callId: string,\n public readonly field: string,\n ) {\n super(say(\"delegate.conflict\", callId, field));\n }\n}\n\nexport class DelegateStateError extends Error {\n override readonly name = \"DelegateStateError\";\n constructor(\n public readonly callId: string,\n public readonly from: DelegateState,\n public readonly to: string,\n ) {\n super(say(\"delegate.state\", callId, from, to));\n }\n}\n\nexport class DelegateNotFoundError extends Error {\n override readonly name = \"DelegateNotFoundError\";\n constructor(public readonly callId: string) {\n super(say(\"delegate.not_found\", callId));\n }\n}\n\ninterface RawCall {\n task_id: number;\n caller: string;\n call_id: string;\n state: DelegateState;\n record_workstream: string | null;\n record_task: string | null;\n record_label: string | null;\n error: string | null;\n updated_at: string;\n request: string | null;\n verdict: string | null;\n agent: string | null;\n local_id: string;\n workstream: string;\n wave: string | null;\n}\n\nconst SELECT_CALL = `SELECT d.*, t.local_id AS local_id, w.name AS workstream, t.wave AS wave\n FROM delegate_calls d\n JOIN tasks t ON t.id = d.task_id\n JOIN workstreams w ON w.id = t.workstream_id`;\n\nfunction rowOf(r: RawCall): DelegateRow {\n let request: DelegateRequest = { text: \"\" };\n try {\n if (r.request) request = JSON.parse(r.request) as DelegateRequest;\n } catch {\n // an unreadable request is an empty one; the brief note still has the text\n }\n return {\n callId: r.call_id,\n task: r.local_id,\n workstream: r.workstream,\n caller: r.caller,\n state: r.state,\n wave: r.wave,\n record:\n r.record_workstream !== null && r.record_task !== null\n ? { workstream: r.record_workstream, task: r.record_task, label: r.record_label }\n : null,\n request,\n agent: r.agent,\n verdict: (r.verdict as VerdictLabel | null) ?? null,\n error: r.error,\n updatedAt: r.updated_at,\n };\n}\n\nexport function getDelegateCall(db: Db, callId: string): DelegateRow | undefined {\n const r = db.prepare(`${SELECT_CALL} WHERE d.call_id = ?`).get(callId) as RawCall | undefined;\n return r ? rowOf(r) : undefined;\n}\n\nfunction mustGet(db: Db, callId: string): DelegateRow {\n const row = getDelegateCall(db, callId);\n if (!row) throw new DelegateNotFoundError(callId);\n return row;\n}\n\n/** Calls of `caller` (all callers when undefined), optionally in one workstream and wave, oldest first. */\nexport function listDelegates(\n db: Db,\n caller?: string,\n workstream?: string,\n opts: {\n wave?: string;\n states?: readonly DelegateState[];\n /** Only calls whose task has one of these statuses. */\n taskStatuses?: readonly string[];\n /** Only calls updated after this ISO time. */\n updatedAfter?: string;\n } = {},\n): DelegateRow[] {\n const where: string[] = [];\n const args: string[] = [];\n if (caller !== undefined) {\n where.push(\"d.caller = ?\");\n args.push(caller);\n }\n if (workstream !== undefined) {\n where.push(\"w.name = ?\");\n args.push(workstream);\n }\n if (opts.wave !== undefined) {\n where.push(\"t.wave = ?\");\n args.push(opts.wave);\n }\n if (opts.states !== undefined) {\n where.push(`d.state IN (${opts.states.map(() => \"?\").join(\",\")})`);\n args.push(...opts.states);\n }\n if (opts.taskStatuses !== undefined) {\n where.push(`t.status IN (${opts.taskStatuses.map(() => \"?\").join(\",\")})`);\n args.push(...opts.taskStatuses);\n }\n if (opts.updatedAfter !== undefined) {\n where.push(\"d.updated_at > ?\");\n args.push(opts.updatedAfter);\n }\n const sql = `${SELECT_CALL}${where.length ? ` WHERE ${where.join(\" AND \")}` : \"\"} ORDER BY d.task_id`;\n return (db.prepare(sql).all(...args) as RawCall[]).map(rowOf);\n}\n\n/** Calls of any of `callers` (the union, each call once, oldest first), optionally in one workstream and wave. `[]` is no calls. */\nexport function listDelegatesOf(\n db: Db,\n callers: readonly string[],\n workstream?: string,\n opts: { wave?: string } = {},\n): DelegateRow[] {\n const set = [...new Set(callers)];\n if (set.length === 0) return [];\n const where = [`d.caller IN (${set.map(() => \"?\").join(\",\")})`];\n const args: string[] = [...set];\n if (workstream !== undefined) {\n where.push(\"w.name = ?\");\n args.push(workstream);\n }\n if (opts.wave !== undefined) {\n where.push(\"t.wave = ?\");\n args.push(opts.wave);\n }\n const sql = `${SELECT_CALL} WHERE ${where.join(\" AND \")} ORDER BY d.task_id`;\n return (db.prepare(sql).all(...args) as RawCall[]).map(rowOf);\n}\n\n/** JSON with sorted keys and no undefined, so two spellings of one request compare equal. */\nfunction canonical(v: unknown): string {\n if (Array.isArray(v)) return `[${v.map(canonical).join(\",\")}]`;\n if (typeof v === \"object\" && v !== null) {\n const o = v as Record<string, unknown>;\n return `{${Object.keys(o)\n .filter((k) => o[k] !== undefined)\n .sort()\n .map((k) => `${JSON.stringify(k)}:${canonical(o[k])}`)\n .join(\",\")}}`;\n }\n return JSON.stringify(v);\n}\n\n/** `delegate_<label>_<8 hex of the call id>`: stable per call, unique per id. */\nfunction taskIdFor(callId: string, label: string | undefined): string {\n const stem = (label ?? \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 20)\n .replace(/-+$/, \"\");\n const h = createHash(\"sha256\").update(callId).digest(\"hex\").slice(0, 8);\n return `delegate_${stem ? `${stem}_` : \"\"}${h}`;\n}\n\nconst now = (): string => new Date().toISOString();\n\nexport interface RegisterDelegateOptions {\n callId: string;\n caller: string;\n /** Where the task (and the delegate agent) lives. The extension's default is `scratch`. */\n workstream: string;\n request: DelegateRequest;\n wave?: string;\n /** The task the answer's verdict is written onto; must exist. */\n record?: RecordRef;\n /** Admission: `starting` (a slot is free), `queued` (waits for one), `refused` (past the queue). */\n state?: \"queued\" | \"starting\" | \"refused\";\n}\n\n/**\n * Create the call: a `kind=delegate` task, its brief note and the call row,\n * in ONE transaction. A queued or refused task is parked (outside\n * `next`/`ready`); a starting one is todo. The same call id with the same\n * request returns the existing call; a different one throws\n * {@link DelegateCallConflictError} and writes nothing.\n */\nexport function registerDelegateCall(\n db: Db,\n opts: RegisterDelegateOptions,\n): { call: DelegateRow; created: boolean } {\n const state = opts.state ?? \"queued\";\n return withOpContext(db, { intent: \"delegate.register\", actor: opts.caller, group: \"new\" }, () =>\n db\n .transaction(() => {\n const existing = getDelegateCall(db, opts.callId);\n if (existing) {\n const same = (field: string, a: unknown, b: unknown) => {\n if (canonical(a) !== canonical(b))\n throw new DelegateCallConflictError(opts.callId, field);\n };\n same(\"caller\", existing.caller, opts.caller);\n same(\"workstream\", existing.workstream, opts.workstream);\n same(\"wave\", existing.wave, opts.wave ?? null);\n same(\n \"record target\",\n existing.record\n ? { workstream: existing.record.workstream, task: existing.record.task }\n : null,\n opts.record ?? null,\n );\n same(\"request\", existing.request, opts.request);\n return { call: existing, created: false };\n }\n if (opts.record && !getTask(db, opts.record.task, opts.record.workstream))\n throw new TaskNotFoundError(opts.record.task, opts.record.workstream);\n const local = taskIdFor(opts.callId, opts.request.label);\n const headline = (opts.request.label ?? opts.request.text).replace(/\\s+/g, \" \").trim();\n addTask(db, {\n localId: local,\n workstream: opts.workstream,\n title: `delegate: ${headline.slice(0, 60)}`,\n kind: \"delegate\",\n ...(opts.wave !== undefined ? { wave: opts.wave } : {}),\n });\n addNote(db, local, opts.request.text, {\n workstream: opts.workstream,\n kind: \"brief\",\n author: opts.caller,\n group: \"inherit\",\n });\n if (state !== \"starting\")\n setTaskStatus(db, local, \"OPEN\", { workstream: opts.workstream, substate: \"parked\" });\n const taskId = (\n db\n .prepare(\n \"SELECT t.id AS id FROM tasks t JOIN workstreams w ON w.id = t.workstream_id WHERE w.name = ? AND t.local_id = ?\",\n )\n .get(opts.workstream, local) as { id: number }\n ).id;\n db.prepare(\n `INSERT INTO delegate_calls\n (task_id, caller, call_id, state, record_workstream, record_task, record_label, updated_at, request)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n taskId,\n opts.caller,\n opts.callId,\n state,\n opts.record?.workstream ?? null,\n opts.record?.task ?? null,\n opts.request.label ?? null,\n now(),\n canonical(opts.request),\n );\n return { call: mustGet(db, opts.callId), created: true };\n })\n .immediate(),\n );\n}\n\n/** The admission moves `markDelegate` allows. */\nconst MOVES: Readonly<Record<string, readonly DelegateState[]>> = {\n queued: [\"refused\"],\n starting: [\"queued\", \"refused\"],\n running: [\"starting\"],\n refused: [\"queued\", \"starting\"],\n};\n\n/**\n * One admission step, as a compare-and-set on the current state: two runtimes\n * cannot both start a call. `starting` unparks the task; `refused` parks it.\n * `queued` from `refused` is the reissue: nothing drains a durable queued row\n * but the runtime that holds it, so only that runtime may make one.\n * `done`, `failed`, `cancelled` and `recording` belong to {@link finishDelegate}.\n */\nexport function markDelegate(\n db: Db,\n callId: string,\n to: \"queued\" | \"starting\" | \"running\" | \"refused\",\n extra: { agent?: string; error?: string } = {},\n): DelegateRow {\n const row = mustGet(db, callId);\n const from = MOVES[to] ?? [];\n if (!from.includes(row.state)) throw new DelegateStateError(callId, row.state, to);\n return withOpContext(db, { intent: `delegate.${to}`, actor: row.caller, group: \"new\" }, () =>\n db\n .transaction(() => {\n const r = db\n .prepare(\n `UPDATE delegate_calls\n SET state = ?, updated_at = ?, agent = COALESCE(?, agent),\n error = CASE WHEN ? = 'refused' THEN COALESCE(?, error) ELSE NULL END\n WHERE call_id = ? AND state = ?`,\n )\n .run(to, now(), extra.agent ?? null, to, extra.error ?? null, callId, row.state);\n if (r.changes !== 1) throw new DelegateStateError(callId, mustGet(db, callId).state, to);\n if (to === \"starting\")\n setTaskStatus(db, row.task, \"OPEN\", { workstream: row.workstream, substate: \"todo\" });\n if (to === \"refused\")\n setTaskStatus(db, row.task, \"OPEN\", { workstream: row.workstream, substate: \"parked\" });\n return mustGet(db, callId);\n })\n .immediate(),\n );\n}\n\nexport interface FinishDelegateOptions {\n /** `done`, or why there is no answer: `timeout`, `died`, `error`, `empty`, `blocked`, `cancelled`, ... */\n outcome: string;\n /** The answer (done) or what is known of the run (the partial text, a pane tail). */\n text?: string;\n elapsedMs?: number;\n /** Who writes: the delegate's name, or the caller for a cancel. */\n author: string;\n /** False: leave the judged task alone (a spawn that never ran has no verdict to give). */\n record?: boolean;\n}\n\nexport interface FinishDelegateResult {\n /** False for a duplicate callback: nothing was written. */\n changed: boolean;\n state: DelegateState;\n task: string;\n record: RecordRef | null;\n /** Whether the verdict note landed on the judged task. */\n recorded: boolean;\n verdict: VerdictLabel | null;\n error?: string;\n}\n\n/** Who wrote the CLOSE note of a task that is already CLOSED; null when it is open or closed bare. */\nfunction closedBy(db: Db, task: string, workstream: string): string | null {\n const row = db\n .prepare(\n `SELECT n.author AS author FROM task_notes n\n JOIN tasks t ON t.id = n.task_id JOIN workstreams w ON w.id = t.workstream_id\n WHERE w.name = ? AND t.local_id = ? AND t.status = 'CLOSED' AND n.kind = 'close'\n ORDER BY n.id DESC LIMIT 1`,\n )\n .get(workstream, task) as { author: string | null } | undefined;\n return row?.author ?? null;\n}\n\nfunction finishText(outcome: string, text: string | undefined): string {\n if (outcome === \"done\") return text ?? \"\";\n return `no answer (${outcome})${text?.trim() ? `\\n\\n${text.trimEnd()}` : \"\"}`;\n}\n\n/**\n * The recorder. 1) `recording` is committed. 2) ONE op group: the verdict note\n * on the judged task (when there is a record target), then the delegate's\n * report and close, then the final state. A throw in 2 rolls the group back;\n * the call then becomes `failed` with the answer kept as its report: it is\n * never `done` without its verdict landed. A call already terminal is a no-op,\n * so a duplicate callback writes one verdict, one report and one close.\n */\nexport function finishDelegate(\n db: Db,\n callId: string,\n opts: FinishDelegateOptions,\n): FinishDelegateResult {\n const before = mustGet(db, callId);\n const unchanged = (row: DelegateRow): FinishDelegateResult => ({\n changed: false,\n state: row.state,\n task: row.task,\n record: row.record ? { workstream: row.record.workstream, task: row.record.task } : null,\n recorded: false,\n verdict: row.verdict,\n });\n if (isTerminal(before.state)) return unchanged(before);\n db.prepare(\n \"UPDATE delegate_calls SET state = 'recording', updated_at = ? WHERE call_id = ? AND state NOT IN ('done','failed','cancelled')\",\n ).run(now(), callId);\n\n const outcome = opts.outcome === \"done\" && !opts.text?.trim() ? \"empty\" : opts.outcome;\n const answered = outcome === \"done\";\n const cancelled = outcome === \"cancelled\";\n const label = before.record?.label ?? before.request.label ?? opts.author;\n const verdict = answered ? (parseVerdict(opts.text ?? \"\") ?? null) : null;\n const record = before.record\n ? { workstream: before.record.workstream, task: before.record.task }\n : null;\n const report = finishText(outcome, opts.text);\n\n const wantRecord = opts.record !== false;\n const write = (recordIt: boolean, error?: string): FinishDelegateResult =>\n withOpContext(db, { intent: \"delegate.finish\", actor: opts.author, group: \"new\" }, () =>\n db\n .transaction((): FinishDelegateResult => {\n const cur = mustGet(db, callId);\n if (isTerminal(cur.state)) return unchanged(cur);\n if (recordIt && record)\n addNote(\n db,\n record.task,\n recordNote(label, opts.author, outcome, opts.text, opts.elapsedMs ?? 0),\n {\n workstream: record.workstream,\n kind: \"verdict\",\n author: opts.author,\n group: \"inherit\",\n },\n );\n const ok = answered && error === undefined;\n const state: DelegateState = ok ? \"done\" : cancelled ? \"cancelled\" : \"failed\";\n // The delegate closed its own task first (a pane's close nudge, its own\n // habit): closeTask's no-op retry would drop the report. Keep it as a\n // report note; the close below then re-applies the outcome (a delegate's wontfix\n // becomes done, with a close note) and is not handed the report. A task someone\n // else closed (the orchestrator, a user) gets no note. The delegate is told\n // from them by the author of the close note: the call row's `agent`.\n const selfClosed =\n cur.agent !== null && closedBy(db, cur.task, cur.workstream) === cur.agent;\n if (selfClosed)\n addNote(db, cur.task, report, {\n workstream: cur.workstream,\n kind: \"report\",\n author: opts.author,\n group: \"inherit\",\n });\n closeTask(db, cur.task, {\n workstream: cur.workstream,\n author: opts.author,\n group: \"inherit\",\n ...(selfClosed ? {} : { report }),\n as: ok ? \"done\" : cancelled ? \"wontfix\" : \"rejected\",\n ...(ok\n ? { evidence: `answered ${verdict ?? \"with no VERDICT line\"} (call ${callId})` }\n : { why: error ?? `${outcome}: no answer (call ${callId})` }),\n });\n db.prepare(\n \"UPDATE delegate_calls SET state = ?, verdict = ?, error = ?, updated_at = ? WHERE call_id = ?\",\n ).run(state, ok ? verdict : null, error ?? null, now(), callId);\n return {\n changed: true,\n state,\n task: cur.task,\n record,\n recorded: recordIt && record !== null,\n verdict: ok ? verdict : null,\n ...(error !== undefined ? { error } : {}),\n };\n })\n .immediate(),\n );\n\n try {\n return write(wantRecord);\n } catch (e) {\n // The record (or the close) failed and the group rolled back: keep the\n // answer as the delegate's report and say why. Never `done`.\n const msg = e instanceof Error ? e.message : String(e);\n return write(\n false,\n `record ${record ? `${record.workstream}/${record.task} ` : \"\"}failed: ${msg}`,\n );\n }\n}\n\n/** The tally of one wave: see {@link verdictTally}. */\nexport interface VerdictTally {\n findings: {\n id: string;\n confirmed: number;\n refuted: number;\n unverified: number;\n pending: number;\n }[];\n queued: number;\n running: number;\n /** Call ids refused past the cap, still to reissue. */\n refused: string[];\n}\n\n/**\n * One wave's results, grouped by the judged task (`<workstream>/<task>`, or the\n * delegate's own task for a call with no record target). One result per call:\n * a done answer counts its parsed label (none: UNVERIFIED); failed and\n * cancelled calls are UNVERIFIED; queued, starting, running, recording and\n * refused are pending. Reads only the call rows, never notes. `callers`\n * restricts the wave to those callers' calls (a SET: managed ws/name and\n * pi:session; `[]` is no calls): two callers may use the same wave name in one\n * workstream. `undefined` reads every caller (a human's view).\n */\nexport function verdictTally(\n db: Db,\n /** The delegates' workstream; undefined = the wave in every workstream. */\n workstream: string | undefined,\n wave: string,\n /** Only these callers' calls (`mu state` never mixes in another session's identically named wave); `[]` is none. */\n callers?: readonly string[],\n): VerdictTally {\n return tallyCalls(\n callers === undefined\n ? listDelegates(db, undefined, workstream, { wave })\n : listDelegatesOf(db, callers, workstream, { wave }),\n );\n}\n\n/** The tally of exactly these calls (a wave a caller already narrowed). */\nexport function tallyCalls(calls: readonly DelegateRow[]): VerdictTally {\n const out: VerdictTally = { findings: [], queued: 0, running: 0, refused: [] };\n const byId = new Map<string, VerdictTally[\"findings\"][number]>();\n for (const c of calls) {\n const id = c.record ? `${c.record.workstream}/${c.record.task}` : `${c.workstream}/${c.task}`;\n let f = byId.get(id);\n if (!f) {\n f = { id, confirmed: 0, refuted: 0, unverified: 0, pending: 0 };\n byId.set(id, f);\n out.findings.push(f);\n }\n switch (c.state) {\n case \"done\":\n if (c.verdict === \"CONFIRMED\") f.confirmed++;\n else if (c.verdict === \"REFUTED\") f.refuted++;\n else f.unverified++;\n break;\n case \"failed\":\n case \"cancelled\":\n f.unverified++;\n break;\n case \"refused\":\n f.pending++;\n out.refused.push(c.callId);\n break;\n case \"queued\":\n f.pending++;\n out.queued++;\n break;\n default:\n f.pending++;\n out.running++;\n }\n }\n return out;\n}\n","// mu — a delegate's answer as a verdict: the pure half of src/delegates.ts.\n//\n// Dependency-free on purpose: the pi extension (extension/delegate.ts) bundles\n// standalone and must not pull in the DB, yet it words the same note.\n\n/** The verdict labels a check may answer. Anything else is UNVERIFIED. */\nexport const VERDICT_LABELS = [\"CONFIRMED\", \"REFUTED\", \"UNVERIFIED\"] as const;\nexport type VerdictLabel = (typeof VERDICT_LABELS)[number];\n\n/** `42s`, `3m 05s`, `1h 02m`. */\nexport function formatElapsed(ms: number): string {\n const t = Math.max(0, Math.round(ms / 1000));\n if (t < 60) return `${t}s`;\n const m = Math.floor(t / 60);\n if (m < 60) return `${m}m ${String(t % 60).padStart(2, \"0\")}s`;\n return `${Math.floor(m / 60)}h ${String(m % 60).padStart(2, \"0\")}m`;\n}\n\n/** A `VERDICT:` line: at the start of the line, behind at most ONE role word\n * (`REFUTER: VERDICT: …`, which is how checks write it by hand). Nothing else\n * may precede it, so a verdict quoted mid-line in the evidence is not one. */\nconst VERDICT_LINE = /^(?:\\w+: )?VERDICT:/;\nconst LABEL_RE = new RegExp(`\\\\b(${VERDICT_LABELS.join(\"|\")})\\\\b`);\n\n/** The index of the FIRST verdict line of `lines`, or -1. Later `VERDICT:`\n * lines are evidence text, not a second verdict. */\nfunction firstVerdictLine(lines: readonly string[]): number {\n return lines.findIndex((l) => VERDICT_LINE.test(l));\n}\n\n/** `line` as a verdict line: null when it is not one, else its label (the first\n * known label after the colon; undefined when it names none). */\nexport function verdictLineLabel(line: string): VerdictLabel | undefined | null {\n if (!VERDICT_LINE.test(line)) return null;\n const after = line.slice(line.indexOf(\"VERDICT:\") + \"VERDICT:\".length);\n return LABEL_RE.exec(after)?.[1] as VerdictLabel | undefined;\n}\n\n/** The label on the first `VERDICT:` line (the first known label after the\n * colon), or undefined when there is no verdict line or no known label. */\nexport function parseVerdict(answer: string): VerdictLabel | undefined {\n const lines = answer.trimEnd().split(\"\\n\");\n const at = firstVerdictLine(lines);\n if (at < 0) return undefined;\n return verdictLineLabel(lines[at] ?? \"\") ?? undefined;\n}\n\n/**\n * The note a delegate's answer leaves on the task it judged. A done answer\n * keeps everything from its first verdict line on, so a multi-line EVIDENCE\n * body (and any `VERDICT:` text quoted in it) survives whole (else the whole answer, marked NO VERDICT LINE); any\n * other outcome records the gap. Never cut: the note is the evidence.\n */\nexport function recordNote(\n label: string,\n name: string,\n outcome: string | undefined,\n lastText: string | undefined,\n elapsedMs: number,\n): string {\n if (outcome !== \"done\" || !lastText?.trim())\n return `REFUTER ${label}: no verdict (${outcome === \"done\" ? \"empty\" : (outcome ?? \"no result\")})`;\n const lines = lastText.trimEnd().split(\"\\n\");\n const at = firstVerdictLine(lines);\n const body = at >= 0 ? lines.slice(at).join(\"\\n\") : `NO VERDICT LINE: ${lastText.trimEnd()}`;\n return `REFUTER ${label} (${name}, ${formatElapsed(elapsedMs)}):\\n${body}`;\n}\n","// mu — spawn receipts: the journal of one task-bound spawn attempt.\n//\n// One row per (task, attempt key) in the machine-local `spawn_receipts`\n// table. The orchestration (task-spawn.ts) writes it BEFORE each external\n// effect, so a process that dies anywhere leaves a row whose state says how\n// far it got, and a replay reads it back instead of acting again.\n//\n// The row names the registry incarnation it created (`agent_id` =\n// `agents.id`, plus `pane_id`) with NO foreign key: it must outlive the\n// agent. A replay compares both against the agent now holding the name; a\n// deleted or replaced one is \"stale\", never silently swapped for the\n// replacement. `incarnation` is pi's own string (the `--inc` of `agent\n// wait`), a different thing, and is only known once a reply carried it.\n//\n// States, in order: reserved (nothing happened) < pane (agent row + pane\n// exist) < claimed (the task is owned by agent_id) < sending (the prompt MAY\n// have been written: never resend) < sent | unknown. failed means definitely\n// unsent and rolled back. Pure SQL: no mux, no ctl.\n\nimport { createHash } from \"node:crypto\";\nimport type { Db, SpawnReceiptState } from \"../db.js\";\n\nexport interface SpawnReceipt {\n taskId: number;\n /** `manual:<key>`: the namespace of a manual spawn (the executor's attempts are `task_auto.last_spawn`). */\n attemptKey: string;\n name: string;\n workstream: string;\n /** Hash of the request (name, --next-free, text): a replay with another one conflicts. */\n requestSha: string;\n /** The id the send carries on the control socket (`mu agent check`). Never resent. */\n msgId: string;\n agentId: number | null;\n paneId: string | null;\n /** How the prompt went: `ctl` (a receipt id was carried) or `mux` (no receipt). */\n transport: \"ctl\" | \"mux\" | null;\n /** pi's incarnation, once a reply (or a receipt check) named it. */\n incarnation: string | null;\n runs: number | null;\n state: SpawnReceiptState;\n detail: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface RawReceipt {\n task_id: number;\n attempt_key: string;\n name: string;\n workstream: string;\n request_sha: string;\n msg_id: string;\n agent_id: number | null;\n pane_id: string | null;\n transport: \"ctl\" | \"mux\" | null;\n incarnation: string | null;\n runs: number | null;\n state: SpawnReceiptState;\n detail: string | null;\n created_at: string;\n updated_at: string;\n}\n\nconst fromRaw = (r: RawReceipt): SpawnReceipt => ({\n taskId: r.task_id,\n attemptKey: r.attempt_key,\n name: r.name,\n workstream: r.workstream,\n requestSha: r.request_sha,\n msgId: r.msg_id,\n agentId: r.agent_id,\n paneId: r.pane_id,\n transport: r.transport,\n incarnation: r.incarnation,\n runs: r.runs,\n state: r.state,\n detail: r.detail,\n createdAt: r.created_at,\n updatedAt: r.updated_at,\n});\n\n/** The request's identity: same name, same --next-free, same text, same host, same remote --root. */\nexport function requestSha(req: {\n name: string;\n nextFree: boolean;\n text: string;\n host?: string | undefined;\n root?: string | undefined;\n}): string {\n // A local request hashes exactly as before these fields existed (saved receipts stay valid).\n const parts: unknown[] = [req.name, req.nextFree, req.text];\n if (req.host !== undefined) parts.push(req.host);\n if (req.host !== undefined && req.root !== undefined) parts.push({ root: req.root });\n return createHash(\"sha256\").update(JSON.stringify(parts)).digest(\"hex\");\n}\n\nexport function getReceipt(db: Db, taskId: number, attemptKey: string): SpawnReceipt | undefined {\n const row = db\n .prepare(\"SELECT * FROM spawn_receipts WHERE task_id = ? AND attempt_key = ?\")\n .get(taskId, attemptKey) as RawReceipt | undefined;\n return row ? fromRaw(row) : undefined;\n}\n\n/** Write the reservation. Throws on a duplicate key (the caller holds the attempt lock and checked). */\nexport function reserveReceipt(\n db: Db,\n r: Pick<SpawnReceipt, \"taskId\" | \"attemptKey\" | \"name\" | \"workstream\" | \"requestSha\" | \"msgId\">,\n): SpawnReceipt {\n const now = new Date().toISOString();\n db.prepare(\n `INSERT INTO spawn_receipts\n (task_id, attempt_key, name, workstream, request_sha, msg_id, state, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, 'reserved', ?, ?)`,\n ).run(r.taskId, r.attemptKey, r.name, r.workstream, r.requestSha, r.msgId, now, now);\n const row = getReceipt(db, r.taskId, r.attemptKey);\n if (row === undefined) throw new Error(\"spawn receipt vanished after reservation\");\n return row;\n}\n\n/** What `updateReceipt` may change. */\nexport type ReceiptPatch = Partial<\n Pick<\n SpawnReceipt,\n | \"name\"\n | \"agentId\"\n | \"paneId\"\n | \"transport\"\n | \"incarnation\"\n | \"runs\"\n | \"state\"\n | \"detail\"\n | \"msgId\"\n | \"requestSha\"\n >\n>;\n\nconst COLUMN: Record<keyof ReceiptPatch, string> = {\n name: \"name\",\n agentId: \"agent_id\",\n paneId: \"pane_id\",\n transport: \"transport\",\n incarnation: \"incarnation\",\n runs: \"runs\",\n state: \"state\",\n detail: \"detail\",\n msgId: \"msg_id\",\n requestSha: \"request_sha\",\n};\n\n/** Patch a receipt (only the keys present). */\nexport function updateReceipt(\n db: Db,\n taskId: number,\n attemptKey: string,\n patch: ReceiptPatch,\n): SpawnReceipt {\n const keys = (Object.keys(patch) as (keyof ReceiptPatch)[]).filter((k) => patch[k] !== undefined);\n const sets = [...keys.map((k) => `${COLUMN[k]} = ?`), \"updated_at = ?\"];\n db.prepare(\n `UPDATE spawn_receipts SET ${sets.join(\", \")} WHERE task_id = ? AND attempt_key = ?`,\n ).run(\n ...keys.map((k) => patch[k] as string | number | null),\n new Date().toISOString(),\n taskId,\n attemptKey,\n );\n const row = getReceipt(db, taskId, attemptKey);\n if (row === undefined) throw new Error(\"spawn receipt vanished\");\n return row;\n}\n\n/**\n * Reuse a FAILED attempt: nothing was sent, so the same key may run again,\n * with a fresh msgId and the new request. Clears the old identity.\n */\nexport function resetReceipt(\n db: Db,\n taskId: number,\n attemptKey: string,\n next: Pick<SpawnReceipt, \"name\" | \"requestSha\" | \"msgId\">,\n): SpawnReceipt {\n db.prepare(\n `UPDATE spawn_receipts\n SET name = ?, request_sha = ?, msg_id = ?, agent_id = NULL, pane_id = NULL,\n transport = NULL, incarnation = NULL, runs = NULL, state = 'reserved', detail = NULL, updated_at = ?\n WHERE task_id = ? AND attempt_key = ?`,\n ).run(next.name, next.requestSha, next.msgId, new Date().toISOString(), taskId, attemptKey);\n const row = getReceipt(db, taskId, attemptKey);\n if (row === undefined) throw new Error(\"spawn receipt vanished\");\n return row;\n}\n","// mu — `agent spawn --task`: the task-bound spawn, claim and first prompt as\n// ONE journaled attempt (docs/VOCABULARY.md § spawn receipt).\n//\n// Order of effects, each journaled in `spawn_receipts` BEFORE it happens:\n// reserve (msgId minted, nothing else) -> spawn the pane (the registry id +\n// pane are journaled inside the spawn lock) -> claim the task for THAT id\n// -> `sending` -> write the prompt with the reserved msgId -> sent -> brief.\n//\n// Failure policy. Everything up to a send that provably never reached pi\n// (ctl missing, refused, outdated, busy, a claim that lost its task, a pane\n// dead with no write evidence) is UNSENT: the claim is released and the spawn\n// rolled back, each only while it is still this attempt's own (identity\n// bound; spawn.ts's guards are reused unchanged). From the moment the prompt\n// may have been written, anything else is UNKNOWN: pane and claim are KEPT\n// (deleteAgent would reopen the task for another dispatch), the receipt says\n// `unknown`, and a replay asks the extension ONCE (`status {msgId}`) but\n// never resends: an extension keeps only its last 64 ids, so \"not found\" is\n// still UNKNOWN, not unsent.\n//\n// Replay (same task + attempt key). The saved registry id + pane are compared\n// with the agent now holding the name; a deleted or replaced one is reported\n// `stale`, never swapped for the replacement. The attempt lock is strict\n// (fails closed); the advisory spawn lock stays inside spawnAgent.\n\nimport { type AgentRow, getAgentForCleanup } from \"../agents.js\";\nimport { newMsgId } from \"../ctl/client.js\";\nimport type { Db } from \"../db.js\";\nimport { delegateSessionDir } from \"../delegates.js\";\nimport { claimTask, releaseTask, resolveActorIdentity } from \"../tasks/claim.js\";\nimport { addNote } from \"../tasks/edit.js\";\nimport { TaskAlreadyOwnedError, TaskNotFoundError } from \"../tasks/errors.js\";\nimport { getTask, selectTaskNotes, taskIdFor } from \"../tasks.js\";\nimport { getWorktreeAt } from \"../worktree.js\";\nimport {\n AgentBusyError,\n AgentCtlUnreachableError,\n AgentEmptySendError,\n AgentExistsError,\n AgentExtensionOutdatedError,\n AgentFreshNeedsCtlError,\n AgentPaneDeadError,\n AgentReplacedError,\n AgentSendRefusedError,\n AgentSendUnsupportedError,\n AgentSlashCommandUnsupportedError,\n SpawnAttemptBusyError,\n SpawnAttemptFailedError,\n SpawnReceiptConflictError,\n SpawnTaskStateError,\n SpawnTrustDialogError,\n} from \"./errors.js\";\nimport { withSpawnAttemptLock } from \"./lock.js\";\nimport {\n getReceipt,\n requestSha,\n reserveReceipt,\n resetReceipt,\n type SpawnReceipt,\n updateReceipt,\n} from \"./receipts.js\";\nimport {\n rollbackSpawn,\n type SpawnAgentOptions,\n type SpawnedAgent,\n type StagedWorktree,\n spawnAgent,\n} from \"./spawn.js\";\nimport {\n agentCtlSocket,\n checkMessage,\n expectsCtl,\n isSlashCommand,\n parseSessionCommand,\n recordSend,\n type SendResult,\n sendViaTransport,\n} from \"./transport.js\";\n\nexport interface TaskSpawnRequest {\n /** The spawn itself (name, workstream, cli, worktree, ...). `onIdentity` is this module's. */\n spawn: Omit<SpawnAgentOptions, \"onIdentity\">;\n /** The task's local id, in `spawn.workstream`. */\n task: string;\n /** The attempt's name. Default: the task id. Stored as `manual:<key>`. */\n attempt?: string;\n /** The first prompt; also the task's pinned brief once it is delivered. */\n text: string;\n}\n\nexport interface TaskSpawnOutcome {\n /** `sent`: delivered (now or by an earlier run). `unknown`: it may have landed; never resent. */\n state: \"sent\" | \"unknown\";\n /** True when a saved receipt answered and nothing new was spawned or sent. */\n replay: boolean;\n receipt: SpawnReceipt;\n /** The live agent of THIS attempt; absent when its identity is stale. */\n agent?: SpawnedAgent | AgentRow;\n /** The saved identity no longer holds: the agent was `deleted`, or the name now belongs to another `replaced` it. */\n stale?: \"deleted\" | \"replaced\";\n /** The send's own result; only on the run that sent. */\n send?: SendResult;\n /** On `unknown`: why (the error, or the replay probe's verdict). */\n reason?: string;\n /** A replay's one receipt probe, when it made one. */\n checked?: \"accepted\" | \"not-accepted\" | \"unreachable\";\n /** Whether the brief note was written, found, or could not be (reconciled on replay). */\n brief: \"recorded\" | \"kept\" | \"pending\";\n}\n\nconst manualKey = (req: TaskSpawnRequest): string => `manual:${req.attempt ?? req.task}`;\n\n/**\n * The executor's `auto:<n>` namespace (src/auto-attempt.ts reserves it and\n * charges the run). Guarded replay: the receipt must already be reserved, a\n * failed (or stale-identity) attempt is NEVER reset or reused (it throws\n * `SpawnAttemptFailedError`; the next attempt is a new key and a new charge),\n * and `guard` is asked before the pane exists (`spawn`) and again inside the\n * transaction just before the prompt is written (`send`): a throw there is an\n * unsent failure, rolled back like any other.\n */\nexport interface AutoAttemptRequest extends Omit<TaskSpawnRequest, \"attempt\"> {\n /** `auto:<n>`. */\n key: string;\n guard: (phase: \"spawn\" | \"send\") => void;\n /**\n * The attempt is an IN-PLACE retry of a live worker: an unsent failure marks\n * the receipt failed and nothing else. The worker, its claim and its worktree\n * are never released, killed or rolled back.\n */\n keepAgent?: boolean;\n}\n\n/** Errors raised BEFORE any byte of the prompt could have been written. */\nexport function definitelyUnsent(err: unknown): boolean {\n return (\n err instanceof AgentCtlUnreachableError ||\n err instanceof AgentExtensionOutdatedError ||\n err instanceof AgentEmptySendError ||\n err instanceof AgentFreshNeedsCtlError ||\n err instanceof AgentSendUnsupportedError ||\n err instanceof AgentSlashCommandUnsupportedError ||\n err instanceof AgentBusyError ||\n err instanceof AgentSendRefusedError ||\n // Another pi owns the socket now: refused before (or at) the dispatch.\n err instanceof AgentReplacedError ||\n // A pane that died WITH write evidence (a msgId) may have taken the prompt first.\n (err instanceof AgentPaneDeadError && err.msgId === undefined)\n );\n}\n\n/** INSERT `text` as the task's `brief` note unless it already has one. */\nexport async function pinBrief(\n db: Db,\n task: string,\n workstream: string,\n text: string,\n): Promise<\"recorded\" | \"kept\"> {\n // Resolve the author first: no await may sit between the check and the INSERT.\n const author = await resolveActorIdentity();\n // One IMMEDIATE transaction takes the write lock before the check, so two\n // concurrent callers (in-process or separate CLIs) cannot both see \"no brief\".\n const recorded = db\n .transaction((): boolean => {\n if (selectTaskNotes(db, task, { workstream }).notes.some((n) => n.kind === \"brief\")) {\n return false;\n }\n addNote(db, task, text, { workstream, kind: \"brief\", author });\n return true;\n })\n .immediate();\n return recorded ? \"recorded\" : \"kept\";\n}\n\n/** Best-effort brief pin: a delivered prompt is never reported as failed over its note. */\nasync function tryPinBrief(\n db: Db,\n req: TaskSpawnRequest,\n): Promise<\"recorded\" | \"kept\" | \"pending\"> {\n try {\n return await pinBrief(db, req.task, req.spawn.workstream, req.text);\n } catch {\n return \"pending\";\n }\n}\n\n/** The worktree this attempt's agent runs in, as rollbackSpawn needs it (registry row at its cwd). */\nfunction stagedOf(db: Db, row: AgentRow): StagedWorktree | undefined {\n // A remote worktree has no local registry row: the agent row carries host, path, base and repo.\n if (row.host !== null) {\n if (row.cwd === null || row.base === null || row.repo === null) return undefined;\n return {\n path: row.cwd,\n base: row.base,\n root: row.repo,\n createdAt: row.createdAt,\n incarnation: row.incarnation,\n host: row.host,\n };\n }\n const wt = row.cwd === null ? undefined : getWorktreeAt(db, row.cwd);\n if (wt === undefined || wt.agent !== row.name) return undefined;\n return {\n path: wt.path,\n base: wt.base,\n root: wt.root,\n createdAt: wt.createdAt,\n incarnation: row.incarnation,\n };\n}\n\n/** The agent now holding the saved name, when it IS the saved incarnation. */\nexport function savedIdentity(\n db: Db,\n rec: SpawnReceipt,\n): { agent?: AgentRow; stale?: \"deleted\" | \"replaced\" } {\n const cur = getAgentForCleanup(db, rec.name, rec.workstream);\n if (cur === undefined) return { stale: \"deleted\" };\n if (rec.agentId !== null && cur.incarnation === rec.agentId && cur.paneId === rec.paneId) {\n return { agent: cur };\n }\n return { stale: \"replaced\" };\n}\n\n/**\n * Run (or replay) one task-bound spawn attempt. Throws before any effect for\n * a bad request (unknown task, owned task, slash text, busy or conflicting\n * attempt) and, after an UNSENT failure, the original error once its own\n * resources are cleaned up. A delivered or unknown outcome is returned.\n */\nexport async function spawnForTask(db: Db, req: TaskSpawnRequest): Promise<TaskSpawnOutcome> {\n const ws = req.spawn.workstream;\n const taskId = taskIdFor(db, req.task, ws);\n if (taskId === null) throw new TaskNotFoundError(req.task, ws);\n // The text is a prompt, never a pi session command (those carry no receipt).\n if (req.text === \"\") throw new AgentEmptySendError(req.spawn.name, ws);\n if (parseSessionCommand(req.text) !== undefined || isSlashCommand(req.text)) {\n throw new AgentSlashCommandUnsupportedError(req.spawn.name, ws, req.text, []);\n }\n const key = manualKey(req);\n return withSpawnAttemptLock(\n db,\n taskId,\n key,\n () => run(db, req, taskId, key, undefined),\n () => {\n throw new SpawnAttemptBusyError(req.task, key);\n },\n );\n}\n\n/** Run or resume one reserved executor attempt (see {@link AutoAttemptRequest}). */\nexport async function spawnAutoAttempt(db: Db, req: AutoAttemptRequest): Promise<TaskSpawnOutcome> {\n const ws = req.spawn.workstream;\n const taskId = taskIdFor(db, req.task, ws);\n if (taskId === null) throw new TaskNotFoundError(req.task, ws);\n if (req.text === \"\") throw new AgentEmptySendError(req.spawn.name, ws);\n if (parseSessionCommand(req.text) !== undefined || isSlashCommand(req.text)) {\n throw new AgentSlashCommandUnsupportedError(req.spawn.name, ws, req.text, []);\n }\n return withSpawnAttemptLock(\n db,\n taskId,\n req.key,\n () => run(db, req, taskId, req.key, req.guard, req.keepAgent === true),\n () => {\n throw new SpawnAttemptBusyError(req.task, req.key);\n },\n );\n}\n\nasync function run(\n db: Db,\n req: TaskSpawnRequest,\n taskId: number,\n key: string,\n guard: AutoAttemptRequest[\"guard\"] | undefined,\n keep = false,\n): Promise<TaskSpawnOutcome> {\n const ws = req.spawn.workstream;\n const sha = requestSha({\n name: req.spawn.name,\n nextFree: req.spawn.nextFree === true,\n text: req.text,\n host: req.spawn.host,\n root: req.spawn.root,\n });\n const saved = getReceipt(db, taskId, key);\n const auto = guard !== undefined;\n const failedAttempt = (why: string): never => {\n throw new SpawnAttemptFailedError(req.task, key, why);\n };\n if (saved === undefined) {\n if (auto) return failedAttempt(\"it was never reserved\");\n return fresh(db, req, taskId, key, sha);\n }\n if (saved.state === \"failed\") {\n // Nothing was sent: a manual key may run again, with this request. An\n // executor attempt never does: its run was charged, the next one is new.\n if (auto) return failedAttempt(saved.detail ?? \"it failed before anything was sent\");\n return fresh(db, req, taskId, key, sha, true);\n }\n if (saved.requestSha !== sha) throw new SpawnReceiptConflictError(req.task, key, saved.name);\n const id = savedIdentity(db, saved);\n\n if (saved.state === \"sent\") {\n const brief = await tryPinBrief(db, req);\n return {\n state: \"sent\",\n replay: true,\n receipt: saved,\n ...(id.agent !== undefined ? { agent: id.agent } : {}),\n ...(id.stale !== undefined ? { stale: id.stale } : {}),\n brief,\n };\n }\n\n if (saved.state === \"sending\" || saved.state === \"unknown\") return reconcile(db, req, saved, id);\n\n if (saved.state === \"reserved\" && auto) {\n // Nothing happened yet (the executor spawns `nextFree`, so a taken name is skipped).\n return drive(db, req, taskId, key, saved, undefined, guard, keep);\n }\n if (saved.state === \"reserved\") {\n // No identity journaled: a name that exists now is not provably ours.\n if (req.spawn.nextFree !== true && getAgentForCleanup(db, saved.name, ws) !== undefined) {\n throw new AgentExistsError(saved.name);\n }\n updateReceipt(db, taskId, key, { state: \"failed\", detail: \"reservation never reached a pane\" });\n return fresh(db, req, taskId, key, sha, true);\n }\n\n // pane | claimed: resume at the next step on the saved identity, or start over.\n if (id.agent === undefined) {\n const why = `saved agent ${saved.agentId ?? \"?\"} is ${id.stale ?? \"gone\"}; nothing was sent`;\n updateReceipt(db, taskId, key, { state: \"failed\", detail: why });\n if (auto) return failedAttempt(why);\n return fresh(db, req, taskId, key, sha, true);\n }\n return drive(db, req, taskId, key, saved, id.agent, guard, keep);\n}\n\n/** Reserve, then spawn and drive a brand new attempt (or a reset failed one). */\nasync function fresh(\n db: Db,\n req: TaskSpawnRequest,\n taskId: number,\n key: string,\n sha: string,\n reuse = false,\n): Promise<TaskSpawnOutcome> {\n const ws = req.spawn.workstream;\n // Cheap refusals before any effect: someone else already owns the task.\n const task = getTask(db, req.task, ws);\n if (task === undefined) throw new TaskNotFoundError(req.task, ws);\n if (task.ownerId !== null) {\n throw new TaskAlreadyOwnedError(req.task, task.ownerName ?? \"<unknown>\");\n }\n if (task.status === \"CLOSED\") throw new SpawnTaskStateError(req.task, \"is closed\");\n const base = { name: req.spawn.name, requestSha: sha, msgId: newMsgId() };\n const rec = reuse\n ? resetReceipt(db, taskId, key, base)\n : reserveReceipt(db, { taskId, attemptKey: key, workstream: ws, ...base });\n return drive(db, req, taskId, key, rec, undefined, undefined);\n}\n\n/** A delegate task's pi spawn keeps its session in {@link delegateSessionDir}. */\nfunction delegateSession(\n db: Db,\n task: string,\n ws: string,\n): Pick<SpawnAgentOptions, \"piSessionDir\"> {\n if (getTask(db, task, ws)?.kind !== \"delegate\") return {};\n return { piSessionDir: delegateSessionDir(db.name, ws, task) };\n}\n\n/**\n * Spawn (when `agent` is absent), claim (when not yet), send, journal. The\n * rollback try covers everything up to the moment the prompt may be written.\n */\nasync function drive(\n db: Db,\n req: TaskSpawnRequest,\n taskId: number,\n key: string,\n start: SpawnReceipt,\n resumed: AgentRow | undefined,\n guard: AutoAttemptRequest[\"guard\"] | undefined,\n keep = false,\n): Promise<TaskSpawnOutcome> {\n const ws = req.spawn.workstream;\n // Before any effect: a refusal leaves the reservation as it is (resumable).\n if (resumed === undefined) guard?.(\"spawn\");\n let rec = start;\n let agent: SpawnedAgent | AgentRow | undefined = resumed;\n let claimed = rec.state === \"claimed\";\n let staged: StagedWorktree | undefined =\n resumed !== undefined && req.spawn.worktree === true ? stagedOf(db, resumed) : undefined;\n let sending = false;\n // spawnAgent rolls its own pane, row and worktree back when it throws.\n let spawnThrew = false;\n\n const unsent = async (err: unknown): Promise<never> => {\n // `keep`: a live worker's in-place retry. Its claim and pane are the worker's, not this attempt's.\n if (agent !== undefined && !spawnThrew && !keep) {\n const owned = agent.incarnation;\n // Only while the task is still owned by THIS incarnation (and not\n // closed): a claim committed before a crash is undone too, a task\n // someone else holds now is not touched.\n try {\n releaseTask(db, req.task, { workstream: ws, expectedOwnerId: owned });\n } catch {\n // best-effort: a held task is left for `mu task release`\n }\n try {\n await rollbackSpawn(db, agent.name, agent.paneId, staged, owned, ws);\n } catch {\n // best-effort, as in spawnAgent's own rollback\n }\n }\n try {\n updateReceipt(db, taskId, key, {\n state: \"failed\",\n detail: err instanceof Error ? err.message : String(err),\n });\n } catch {\n // the original error matters more\n }\n throw err;\n };\n\n let row: AgentRow;\n try {\n if (agent === undefined) {\n spawnThrew = true;\n const spawned = await spawnAgent(db, {\n ...req.spawn,\n ...delegateSession(db, req.task, ws),\n onIdentity: (r) => {\n rec = updateReceipt(db, taskId, key, {\n state: \"pane\",\n name: r.name,\n agentId: r.incarnation,\n paneId: r.paneId,\n });\n if (req.spawn.worktree === true) staged = stagedOf(db, r);\n agent = r;\n },\n });\n agent = spawned;\n spawnThrew = false;\n // The pi this spawn's handshake saw: every send below is bound to it.\n if (spawned.ctlIncarnation !== undefined) {\n rec = updateReceipt(db, taskId, key, { incarnation: spawned.ctlIncarnation });\n }\n // The pane is up but cannot take (or confirm) a prompt: nothing was sent.\n if (spawned.ctl === \"missing\" || spawned.ctl === \"refused\") {\n throw new AgentCtlUnreachableError(\n spawned.name,\n ws,\n spawned.ctlSocket,\n spawned.ctl,\n spawned.host,\n );\n }\n if (spawned.trustDialog === true) throw new SpawnTrustDialogError(spawned.name);\n }\n const target = agent;\n if (!claimed) {\n await claimTask(db, req.task, {\n workstream: ws,\n agentName: target.name,\n expectedAgentId: target.incarnation,\n });\n claimed = true;\n rec = updateReceipt(db, taskId, key, { state: \"claimed\" });\n }\n // One immediate transaction right before the write (no await inside):\n // the delivery targets the SAVED registry id + pane, never whatever holds\n // the name now, and only while the claim is still this agent's and the\n // task still open (a resume from 'claimed' trusts no earlier view).\n // 'sending' is journaled BEFORE the write: from here a crash means \"may have landed\".\n req.spawn.signal?.throwIfAborted(); // the last point an abort still rolls back\n const checked = db\n .transaction((): { row: AgentRow; rec: SpawnReceipt } => {\n const now = getAgentForCleanup(db, target.name, ws);\n if (\n now === undefined ||\n now.incarnation !== target.incarnation ||\n now.paneId !== target.paneId\n ) {\n throw new AgentReplacedError(target.name, ws, \"sent to\");\n }\n guard?.(\"send\");\n const t = getTask(db, req.task, ws);\n if (t === undefined) throw new TaskNotFoundError(req.task, ws);\n if (t.status === \"CLOSED\") throw new SpawnTaskStateError(req.task, \"was closed\");\n if (t.ownerId !== now.incarnation) {\n if (t.ownerId !== null) {\n throw new TaskAlreadyOwnedError(req.task, t.ownerName ?? \"<unknown>\");\n }\n throw new SpawnTaskStateError(req.task, `is no longer claimed by ${now.name}`);\n }\n const journaled = updateReceipt(db, taskId, key, {\n state: \"sending\",\n transport: expectsCtl(now, agentCtlSocket(db, now)) ? \"ctl\" : \"mux\",\n });\n return { row: now, rec: journaled };\n })\n .immediate();\n row = checked.row;\n rec = checked.rec;\n sending = true;\n } catch (err) {\n return unsent(err);\n }\n\n // ── the write ──\n let undelivered: string | undefined;\n let sent: SendResult;\n try {\n sent = await sendViaTransport(row, req.text, {\n socket: agentCtlSocket(db, row),\n msgId: rec.msgId,\n ...(rec.incarnation !== null ? { expectIncarnation: rec.incarnation } : {}),\n onUndelivered: (w) => {\n undelivered = w.message;\n },\n });\n } catch (err) {\n if (sending && definitelyUnsent(err)) return unsent(err);\n const reason = err instanceof Error ? err.message : String(err);\n const inc = (err as { incarnation?: unknown }).incarnation;\n // Keep the pane, the claim and the receipt: the prompt may be running.\n const unknownRec = updateReceipt(db, taskId, key, {\n state: \"unknown\",\n detail: reason,\n ...(typeof inc === \"string\" ? { incarnation: inc } : {}),\n });\n return {\n state: \"unknown\",\n replay: false,\n receipt: unknownRec,\n agent: agent,\n reason,\n brief: \"pending\",\n };\n }\n if (undelivered !== undefined) {\n // A paste that looked calm but never registered: not provably sent.\n const unknownRec = updateReceipt(db, taskId, key, { state: \"unknown\", detail: undelivered });\n return {\n state: \"unknown\",\n replay: false,\n receipt: unknownRec,\n agent,\n reason: undelivered,\n brief: \"pending\",\n };\n }\n\n // ── delivered: nothing below may fail the attempt ──\n try {\n rec = updateReceipt(db, taskId, key, {\n state: \"sent\",\n detail: null,\n ...(sent.incarnation !== undefined ? { incarnation: sent.incarnation } : {}),\n ...(sent.runs !== undefined ? { runs: sent.runs } : {}),\n });\n } catch {\n // stays 'sending': a replay asks the extension and records it\n }\n try {\n recordSend(\n db,\n row,\n \"plain\",\n Buffer.byteLength(req.text),\n { transport: sent.transport, state: sent.state, since: sent.since },\n await resolveActorIdentity(),\n );\n } catch {\n // the audit line is best-effort once delivered\n }\n const brief = await tryPinBrief(db, req);\n return { state: \"sent\", replay: false, receipt: rec, agent: agent ?? row, send: sent, brief };\n}\n\n/** A `sending`/`unknown` receipt: ask the extension ONCE about the saved msgId; never resend. */\nasync function reconcile(\n db: Db,\n req: TaskSpawnRequest,\n saved: SpawnReceipt,\n id: { agent?: AgentRow; stale?: \"deleted\" | \"replaced\" },\n): Promise<TaskSpawnOutcome> {\n const stay = (reason: string, checked?: TaskSpawnOutcome[\"checked\"]): TaskSpawnOutcome => {\n const rec =\n saved.state === \"unknown\"\n ? saved\n : updateReceipt(db, saved.taskId, saved.attemptKey, { state: \"unknown\", detail: reason });\n return {\n state: \"unknown\",\n replay: true,\n receipt: rec,\n ...(id.agent !== undefined ? { agent: id.agent } : {}),\n ...(id.stale !== undefined ? { stale: id.stale } : {}),\n reason,\n ...(checked !== undefined ? { checked } : {}),\n brief: \"pending\",\n };\n };\n if (id.agent === undefined) return stay(`the sending agent is ${id.stale ?? \"gone\"}`);\n if (saved.transport !== \"ctl\") return stay(\"the send went through the pane: no receipt to ask\");\n const check = await checkMessage(agentCtlSocket(db, id.agent), saved.msgId);\n if (check.state !== \"accepted\") {\n return stay(\n check.state === \"unreachable\"\n ? check.reason\n : \"the extension does not remember the id (it keeps the last 64): still unknown, never unsent\",\n check.state,\n );\n }\n const rec = updateReceipt(db, saved.taskId, saved.attemptKey, {\n state: \"sent\",\n ...(check.incarnation !== undefined ? { incarnation: check.incarnation } : {}),\n ...(check.runs !== undefined ? { runs: check.runs } : {}),\n });\n const brief = await tryPinBrief(db, req);\n return { state: \"sent\", replay: true, receipt: rec, agent: id.agent, checked: \"accepted\", brief };\n}\n","// Cross-process advisory lock for the tmux-topology critical section of\n// a spawn.\n//\n// Why this exists: every `mu` invocation is a separate short-lived\n// process, so there is no in-process mutex to lean on. When an operator\n// (or the model) fires several spawns in parallel —\n//\n// for n in 1 2 3; do mu agent spawn scout-$n -w scratch & done; wait\n//\n// — each process runs the check-then-act inside `mux.spawnAgent`:\n// \"does mu-scratch exist?\" → all see \"no\" → all call\n// `tmux new-session -d -s mu-scratch`. Exactly one wins; the losers get\n// \"duplicate session\", throw, and `rollbackSpawn` removes their agent\n// row. Net effect: agents silently dropped (and sometimes duplicated as\n// windows race).\n//\n// The fix is a filesystem advisory lock keyed on the tmux SESSION name\n// (the shared resource — two spawns into different sessions never\n// contend). It wraps ONLY the fast topology + DB-insert section, NOT the\n// slow liveness/readiness wait, so genuine parallelism (the whole point\n// of `&`) is preserved: process A creates the session and inserts its\n// row, releases, then waits for liveness while process B is already\n// creating its own window.\n//\n// Mechanism: `fs.mkdir` is atomic and fails with EEXIST if the directory\n// exists — the classic lockfile primitive, no extra dependency (honors\n// the ROADMAP anti-feature pledge). A `meta.json` inside records pid +\n// acquisition time for stale-lock diagnostics and breaking.\n\nimport { join } from \"node:path\";\nimport { type FileLockOptions, locksDir, withFileLock } from \"../file-lock.js\";\n\n/** Lock directory path for a given tmux session name. The session name\n * is already validated ([a-z0-9_-] plus the `mu-` prefix), so it is a\n * safe path segment. Exported for tests that need to read the lock's\n * metadata directly via readFileLockMeta. */\nexport function lockPathForSession(session: string): string {\n return join(locksDir(), `spawn-${session}.lock`);\n}\n\n/** Max time to wait to acquire the lock before giving up (ms). A spawn's\n * critical section is sub-second; this is generous headroom for a deep\n * parallel fan-out queued behind one slow tmux server. */\nconst DEFAULT_ACQUIRE_TIMEOUT_MS = 15_000;\n\n/** A held lock older than this is presumed abandoned (a crashed `mu`\n * process that never released) and force-broken. Must comfortably\n * exceed the critical section's real duration. */\nconst STALE_LOCK_MS = 30_000;\n\nexport interface SpawnLockOptions {\n acquireTimeoutMs?: number;\n staleLockMs?: number;\n}\n\n/**\n * Run `fn` while holding the per-session spawn lock.\n *\n * The mechanism (atomic mkdir, stale-lock breaking, release-in-finally,\n * proceed-unlocked-on-non-contention) lives in src/file-lock.ts so\n * segments can reuse it without a second copy. This wrapper owns the\n * session-keyed path and the spawn-specific timeouts.\n */\nexport async function withSpawnLock<T>(\n session: string,\n fn: () => Promise<T>,\n opts?: SpawnLockOptions,\n): Promise<T> {\n const lockOpts: FileLockOptions<T> = {\n acquireTimeoutMs: opts?.acquireTimeoutMs ?? DEFAULT_ACQUIRE_TIMEOUT_MS,\n staleLockMs: opts?.staleLockMs ?? STALE_LOCK_MS,\n timeoutEnvVar: \"MU_SPAWN_LOCK_TIMEOUT_MS\",\n };\n return withFileLock(lockPathForSession(session), session, fn, lockOpts);\n}\n","// mu — dead `--worktree` stagings. A spawn killed past the reach of its own\n// rollback (SIGKILL, a crash) between staging and its pane leaves the\n// placeholder row (pane `%pending-<name>`) and a fresh, possibly half-made\n// worktree that no pane ever ran in. `mu doctor` lists them; the next spawn\n// in the workstream removes them (`reclaimDeadStagings`).\n\nimport { type AgentRow, deleteAgent, getAgent, isPendingPaneId, listAgents } from \"../agents.js\";\nimport type { Db } from \"../db.js\";\nimport { discardWorktree } from \"../vcs/git.js\";\nimport { getWorktreeAt, reclaimWorktreePath } from \"../worktree.js\";\nimport { withAgentLock } from \"./lock.js\";\n\n/** A live spawn patches its placeholder within the spawn lock's 15 s acquire\n * plus pane creation (staging itself holds the agent lock, checked too). */\nconst STAGING_DEAD_MS = 60_000;\n\n/** Local placeholder rows older than the staging window, counted from the\n * later of the row and its worktree's registration (a slow create is live). */\nexport function deadStagings(db: Db, workstream?: string, now = Date.now()): AgentRow[] {\n return listAgents(db, workstream === undefined ? {} : { workstream }).filter((a) => {\n if (!isPendingPaneId(a.paneId) || a.host !== null) return false;\n const made = a.cwd === null ? undefined : getWorktreeAt(db, a.cwd)?.createdAt;\n return now - Math.max(Date.parse(a.updatedAt), made ? Date.parse(made) : 0) > STAGING_DEAD_MS;\n });\n}\n\n/**\n * Remove `workstream`'s dead stagings: under the agent lock (a busy lock means\n * a live holder: skipped), only the same placeholder, and its worktree only\n * when it is mu's own unused one. An unregistered dir there is the staging's\n * half-made `git worktree add` (the path was empty or reclaimed before it ran);\n * a registered one goes through `reclaimWorktreePath`, which refuses work.\n * Best-effort per row; returns the names reclaimed.\n */\nexport async function reclaimDeadStagings(db: Db, workstream: string): Promise<string[]> {\n const done: string[] = [];\n for (const a of deadStagings(db, workstream)) {\n try {\n await withAgentLock(\n db,\n workstream,\n a.name,\n async () => {\n const cur = getAgent(db, a.name, workstream);\n if (cur?.incarnation !== a.incarnation || cur.paneId !== a.paneId) return;\n if (cur.cwd !== null) {\n if (getWorktreeAt(db, cur.cwd) === undefined) await discardWorktree(undefined, cur.cwd);\n else await reclaimWorktreePath(db, { agent: a.name, workstream, path: cur.cwd });\n }\n if (deleteAgent(db, a.name, workstream, { incarnation: a.incarnation }))\n done.push(a.name);\n },\n { acquireTimeoutMs: 0 },\n );\n } catch {\n // busy or refused: left in place, and listed by `mu doctor`\n }\n }\n return done;\n}\n","// mu — agent error classes.\n//\n// Every agent verb that can fail in a typed way has its own error class\n// here. The CLI's classifyError() (src/cli/handle.ts) maps them to exit\n// codes:\n// usage → 2 (AgentAbortNeedsCtlError, AgentFreshNeedsCtlError,\n// AgentSlashCommandUnsupportedError)\n// not found → 3 (AgentNotFoundError)\n// conflict → 4 (AgentExistsError, AgentNameExhaustedError,\n// AgentNotInWorkstreamError,\n// AgentSendUnsupportedError,\n// AgentExtensionOutdatedError, AgentBusyError)\n// timeout → 5 (AgentAbortTimeoutError: abort/interrupt only; a wait\n// that hits its cap is exit 0 with timedOut, not an error)\n// failure → 1 (AgentSpawnCliNotFoundError, AgentDiedOnSpawnError,\n// AgentSpawnStartupError, AgentCtlUnreachableError)\n//\n// AgentDiedOnSpawnError + AgentSpawnStartupError reach into spawn.ts for\n// defaultSpawnLivenessMs — a single, narrow cross-cluster import that\n// documents itself in the error message (\"agent died within Nms of\n// spawn\" / \"agent reported a startup error within Nms of spawn\") —\n// and AgentSpawnStartupError for isExecFailureLine, to pick hints that\n// fit the matched line.\n//\n// AgentSpawnCliNotFoundError is the pre-flight cousin of the two\n// post-spawn-detect errors above: thrown BEFORE the worktree is created when\n// the resolved `--cli` command's first token doesn't exist on PATH.\n// Distinct from AgentSpawnStartupError so the operator can tell\n// 'I never had a working CLI' from 'CLI started but parked at an error'.\n\nimport { say } from \"../messages.js\";\nimport { defaultSpawnLivenessMs } from \"./spawn.js\";\n\n/**\n * Pre-flight failure: the command mu would have spawned in the new\n * pane doesn't resolve to a binary on PATH (and isn't an absolute /\n * relative path that exists + is executable). Thrown by `spawnAgent`\n * BEFORE the worktree is created so a typo in `--cli` never leaves\n * an orphan worktree behind.\n *\n * Live\n * dogfood report: `mu agent spawn worker-1 --cli pi-meta` on a host\n * where the `pi-meta` binary wasn't on PATH printed `Spawned worker-1\n * (pi-meta)` and the pane immediately died with `command not found`;\n * the existing 1.5s liveness check sometimes missed it (the shell\n * stays alive after the failed exec). Pre-flighting the PATH lookup\n * surfaces the typo before any side effects (worktree, pane, DB row).\n *\n * Distinct from `AgentSpawnStartupError` (pane alive but parked at an\n * error prompt) and `AgentDiedOnSpawnError` (pane vanished within the\n * liveness window). All three carry different remediation hints, so\n * they're separate types.\n */\nexport class AgentSpawnCliNotFoundError extends Error {\n override readonly name = \"AgentSpawnCliNotFoundError\";\n constructor(\n public readonly cli: string,\n /** First whitespace-separated token of the resolved command — the\n * thing actually missing on PATH. Surfaced verbatim in the\n * message so the operator sees what mu searched for (which may\n * differ from `cli` when `$MU_<UPPER_CLI>_COMMAND` rewrites it). */\n public readonly binary: string,\n /** Name of the env var that mu consulted before falling back to\n * the bare `cli` value (e.g. `MU_PI_META_COMMAND`). Always set\n * to the conventional name so the message can name it. */\n public readonly envVarChecked: string,\n ) {\n super(say(\"agent.cli_not_found\", cli, binary, envVarChecked));\n }\n}\n\nexport class AgentExistsError extends Error {\n override readonly name = \"AgentExistsError\";\n constructor(public readonly agentName: string) {\n // v5: agent names are UNIQUE per (workstream, name) — the same\n // name can legitimately exist in two different workstreams. The\n // pre-v5 message claimed global uniqueness, which (a) lied about\n // the schema and (b) misled operators into closing the existing\n // agent when the actual fix is `-w <other-ws>`.\n super(say(\"agent.exists\", agentName));\n }\n}\n\n/** `spawn --next-free` found no free valid name near the asked one. */\nexport class AgentNameExhaustedError extends Error {\n override readonly name = \"AgentNameExhaustedError\";\n constructor(\n public readonly agentName: string,\n reason: string,\n ) {\n super(say(\"agent.name_exhausted\", agentName, reason));\n }\n}\n\nexport class AgentNotFoundError extends Error {\n override readonly name = \"AgentNotFoundError\";\n constructor(\n public readonly agentName: string,\n /** Optional workstream context. When set, the message is enriched\n * with `(in workstream <ws>)` so the verb that hit the miss\n * (e.g. `mu agent close <agent> -w <ws>`) doesn't leave the\n * operator guessing which scope was searched. Optional so existing\n * call sites that only know the agent name keep their original\n * one-line message. */\n public readonly workstream?: string,\n ) {\n super(say(\"agent.not_found\", agentName, workstream));\n }\n}\n\n/**\n * Thrown when an entity-targeted verb is invoked with `-w/--workstream\n * <name>` but the named agent lives in a different workstream.\n * Mirrors `TaskNotInWorkstreamError`. Maps to exit code 4 (conflict /\n * wrong scope). Distinguishes \"the user typo'd the workstream\" from\n * \"the agent doesn't exist anywhere\" (which surfaces as\n * `AgentNotFoundError`).\n */\nexport class AgentNotInWorkstreamError extends Error {\n override readonly name = \"AgentNotInWorkstreamError\";\n constructor(\n public readonly agentName: string,\n public readonly expectedWorkstream: string,\n public readonly actualWorkstream: string,\n ) {\n super(say(\"agent.not_in_workstream\", agentName, expectedWorkstream, actualWorkstream));\n }\n}\n\n/**\n * Thrown when an agent's pane is created and titled successfully but the\n * spawned process exits within the liveness window (default 1500ms;\n * configurable via `MU_SPAWN_LIVENESS_MS`). The most common cause is the\n * underlying CLI failing fast: a wrapper CLI blocking on a single-instance\n * lock, `claude` rejecting an invalid API key, etc. The agent's last\n * scrollback (when capturable) is attached to help diagnose.\n */\nexport class AgentDiedOnSpawnError extends Error {\n override readonly name = \"AgentDiedOnSpawnError\";\n /** The pane's transport reaches another machine (a host profile, or a hand-written ssh hop): remote causes, not wrapper locks. */\n readonly remote: boolean;\n /** The host profile the pane ran, when it was a `--host` spawn. */\n readonly host: string | undefined;\n constructor(\n public readonly agentName: string,\n public readonly paneId: string,\n public readonly scrollback: string | undefined,\n /** The command the pane ran; an `ssh ...` command gets remote hints. */\n public readonly command?: string,\n /** When it died; default `within <MU_SPAWN_LIVENESS_MS>ms of spawn`. */\n when = `within ${defaultSpawnLivenessMs()}ms of spawn`,\n host?: string,\n ) {\n const tail = scrollback?.trim();\n const detail = tail ? say(\"agent.scrollback\", tail) : \"\";\n const remote = host !== undefined || /^\\s*ssh\\s/.test(command ?? \"\");\n const cause = remote ? say(\"agent.died_cause_remote\", host) : say(\"agent.died_cause_local\");\n super(say(\"agent.died_on_spawn\", agentName, when, paneId, cause, detail));\n this.remote = remote;\n this.host = host;\n }\n}\n\n/**\n * Thrown when an agent's pane is alive AND staying alive after the\n * liveness window, but its first burst of output matches a known\n * provider-startup-failure pattern (missing API key, auth rejected, …).\n * Source: feedback ws task `agent_spawn_model_auth_failure_counts_as_live`.\n * Live dogfood report: `pi-meta --no-solo --model sonnet:high` printed\n * `Error: No API key found for amazon-bedrock` and parked at a prompt.\n * The pane stayed alive (1.5s liveness check passed) but the worker\n * could never do work — the orchestrator only discovered this when\n * `mu task wait` stalled minutes later.\n *\n * Distinct from `AgentDiedOnSpawnError`:\n * - `AgentDiedOnSpawnError` → pane vanished within the liveness window\n * (CLI exited fast).\n * - `AgentSpawnStartupError` → pane alive, but the captured scrollback\n * tail contains a curated provider-auth-failure pattern.\n * The two carry different remediation hints (CLI override vs. fix the\n * env var), so they're separate types instead of one with a flag.\n *\n * The pattern list is curated and short to keep false-positive risk low\n * — the scan only looks at the last ~30 lines of the 50-line capture\n * taken right after the liveness sleep, so matches naturally come from\n * the CLI's first ~1.5s of output (not arbitrary later prompts the\n * agent might type into).\n */\nexport class AgentSpawnStartupError extends Error {\n override readonly name = \"AgentSpawnStartupError\";\n constructor(\n public readonly agentName: string,\n public readonly paneId: string,\n /** The single scrollback line that matched a known startup-error\n * pattern. Surfaced verbatim in the message so the operator sees\n * what mu saw. */\n public readonly matchedLine: string,\n /** Full captured scrollback (tail-trimmed already by\n * awaitSpawnLiveness). Attached to the message for context. */\n public readonly scrollback: string,\n /** When it was seen; default `within <MU_SPAWN_LIVENESS_MS>ms of spawn`. */\n when = `within ${defaultSpawnLivenessMs()}ms of spawn`,\n ) {\n super(\n say(\n \"agent.startup_error\",\n agentName,\n when,\n paneId,\n matchedLine.trim(),\n say(\"agent.scrollback\", scrollback.trim()),\n ),\n );\n }\n}\n\n/**\n * The agent's pane and pi are up, but nothing answers on its control\n * socket (`MU_CTL_SOCK`): the mu pi extension is not loaded, or, for a\n * remote agent, the ssh command lacks the `-L` forward. Spawn does not\n * throw it — the agent is usable by hand — but prints it as a warning;\n * verbs that need the socket throw it.\n */\nexport class AgentCtlUnreachableError extends Error {\n override readonly name = \"AgentCtlUnreachableError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n public readonly socket: string,\n public readonly kind: \"missing\" | \"refused\",\n /** The host profile the agent runs on, when remote: its forward is the usual cause. */\n public readonly host?: string | null,\n ) {\n super(say(\"agent.ctl_unreachable\", agentName, kind, socket));\n }\n}\n\n/**\n * A side-effecting ctl request (send, fresh, interrupt, command) was\n * written to a live agent's socket, then no reply arrived (timeout or\n * close). pi may have queued the prompt, so a blind resend can duplicate it.\n */\nexport class AgentSendIndeterminateError extends Error {\n override readonly name = \"AgentSendIndeterminateError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n public readonly op: string,\n public readonly reason: string,\n /** The receipt id the send carried: `mu agent check <agent> <msgId>` asks whether it landed. */\n public readonly msgId?: string,\n /** The pi process the send was written to (hello's), when the extension reports one. */\n public readonly incarnation?: string,\n /** The registry row the send went to (`AgentRow.incarnation`): its receipt check is offered only while that row stands. */\n public readonly agentId?: number,\n ) {\n super(say(\"agent.send_indeterminate\", agentName, op, reason, msgId));\n }\n}\n\n/**\n * `mu agent wait --inc <i>` found another pi process behind the socket:\n * the agent restarted, and the run the caller waits on died with the old\n * process. Waiting more cannot recover it.\n */\nexport class AgentRestartedError extends Error {\n override readonly name = \"AgentRestartedError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n public readonly expected: string,\n public readonly actual?: string,\n ) {\n super(say(\"agent.restarted\", agentName, expected, actual));\n }\n}\n\n/**\n * `agent close` killed the pane and it is STILL alive (moved out from under\n * the kill, or the mux refused), or its liveness could not be checked (the\n * probe failed, or no multiplexer answers: `unknown`, with `reason`). The\n * row, its claims and its worktree stay: nothing is freed while the pane may\n * run. Exit 4; the message names the retry (`--force` for `unknown` only).\n */\nexport class AgentPaneStillAliveError extends Error {\n override readonly name = \"AgentPaneStillAliveError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n public readonly paneId: string,\n public readonly state: true | \"unknown\",\n public readonly reason?: string,\n ) {\n super(say(\"agent.pane_still_alive\", agentName, workstream, paneId, state, reason));\n }\n}\n\n/**\n * The name now belongs to another incarnation (a respawn, or the same pane\n * id reused) than the one this step meant, so nothing more was done to it.\n * `agent close`: whatever it already did to the ORIGINAL (a pane kill)\n * stands. `agent spawn --send` / `--task`: the prompt was NOT written. In\n * both the replacement's row, socket, worktree and tasks are untouched.\n * Exit 4.\n */\nexport class AgentReplacedError extends Error {\n override readonly name = \"AgentReplacedError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n during: \"closed\" | \"sent to\" | \"collected\" = \"closed\",\n ) {\n super(say(\"agent.replaced\", agentName, workstream, during));\n this.during = during;\n }\n readonly during: \"closed\" | \"sent to\" | \"collected\";\n}\n\n/**\n * Another mu process holds this agent's lock (a close, or a `--worktree`\n * spawn staging the name) and did not release it in time. Nothing was\n * done: a destructive agent step never runs unlocked. Exit 4.\n */\nexport class AgentLockBusyError extends Error {\n override readonly name = \"AgentLockBusyError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n ) {\n super(say(\"agent.lock_busy\", agentName, workstream));\n }\n}\n\n/**\n * A ctl verb (send, abort, ...) found the agent's control socket silent\n * AND its pane gone: the process exited (or the pane was closed behind\n * mu's back), so there is nothing to link or forward. Raised\n * instead of AgentCtlUnreachableError, which is for a live pane.\n */\nexport class AgentPaneDeadError extends Error {\n override readonly name = \"AgentPaneDeadError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n public readonly paneId: string,\n /** Set when a send/fresh WAS written before the pane died: it may have landed. */\n public readonly msgId?: string,\n ) {\n super(say(\"agent.pane_dead\", agentName, paneId, msgId));\n }\n}\n\n/**\n * `mu agent abort` on an agent that does not run pi: there is no control\n * socket to carry the abort, and mu does not silently signal the pane.\n */\nexport class AgentAbortNeedsCtlError extends Error {\n override readonly name = \"AgentAbortNeedsCtlError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n public readonly cli: string,\n ) {\n super(say(\"agent.abort_needs_ctl\", agentName, cli));\n }\n}\n\n/** The abort was delivered but pi did not settle within the timeout. */\nexport class AgentAbortTimeoutError extends Error {\n override readonly name = \"AgentAbortTimeoutError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n public readonly timeoutMs: number,\n ) {\n super(say(\"agent.abort_timeout\", agentName, timeoutMs));\n }\n}\n\n/**\n * `mu agent send --fresh` on an agent without a control socket (non-pi\n * CLI): there is no one-operation new session.\n */\nexport class AgentFreshNeedsCtlError extends Error {\n override readonly name = \"AgentFreshNeedsCtlError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n public readonly cli: string,\n ) {\n super(say(\"agent.fresh_needs_ctl\", agentName, cli));\n }\n}\n\n/**\n * The agent's pi serves the control socket with an extension it loaded\n * before mu learned `op` (e.g. `fresh`): running pi processes keep the\n * extension code they started with. pi's `/reload` re-imports the\n * extension through the pi package and keeps the socket; a\n * respawn always works. An extension that serves op `command` takes\n * `/reload` over ctl; an older one cannot be reloaded by mu: respawn it.\n */\nexport class AgentExtensionOutdatedError extends Error {\n override readonly name = \"AgentExtensionOutdatedError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n /** The op it answered \"unknown op\" to, or the feature (msgId, incarnation) its hello lacks. */\n public readonly op: string,\n public readonly extVersion?: string,\n /** Ops the extension serves (from its \"unknown op\" reply or hello); absent from old extensions. */\n public readonly ops?: readonly string[],\n /** The recovery inputs only the caller can compute (the mux and the agent row). */\n public readonly recovery: {\n /** A shell line that types /reload into the pane through the mux (herdr). */\n muxReload?: string;\n /** The agent's original spawn command, rebuilt from its row. */\n respawn?: string;\n /** `op` is a feature of the hello reply, not an op. */\n feature?: boolean;\n } = {},\n ) {\n super(\n say(\n \"agent.extension_outdated\",\n agentName,\n extVersion ?? \"version unknown\",\n recovery.feature === true,\n op,\n ),\n );\n }\n}\n\n/**\n * `send --fresh` or a session command (`/new`, `/reload`, `/compact`)\n * refused: pi is mid-turn, and running it would abandon the turn.\n */\nexport class AgentBusyError extends Error {\n override readonly name = \"AgentBusyError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n /** The session command refused, e.g. \"/new\". Absent: `--fresh`. */\n public readonly command?: string,\n ) {\n super(say(\"agent.busy\", agentName, command ?? \"--fresh\"));\n }\n}\n\n/**\n * A slash command other than `/new`, `/reload`, `/compact` sent to a pi\n * agent. The control socket cannot run it (pi.sendUserMessage would\n * hand it to the model as text), and mu has no paste into a pi pane:\n * the operator types it in the pane.\n */\nexport class AgentSlashCommandUnsupportedError extends Error {\n override readonly name = \"AgentSlashCommandUnsupportedError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n public readonly text: string,\n public readonly supported: readonly string[],\n ) {\n super(say(\"agent.slash_unsupported\", agentName, supported, text));\n }\n}\n\n/**\n * An empty message sent to a pi agent over the control socket.\n * pi.sendUserMessage(\"\") is meaningless; a bare Enter is a pane\n * keystroke, which mu does not send.\n */\nexport class AgentEmptySendError extends Error {\n override readonly name = \"AgentEmptySendError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n ) {\n super(say(\"agent.empty_send\", agentName));\n }\n}\n\n/**\n * `mu agent send` to a non-pi agent on a backend with no `sendToPane`\n * (tmux): its bracketed paste cannot be confirmed, so mu refuses. Maps to\n * exit code 4 (conflict).\n */\nexport class AgentSendUnsupportedError extends Error {\n override readonly name = \"AgentSendUnsupportedError\";\n constructor(\n public readonly agentName: string,\n public readonly workstream: string,\n public readonly cli: string,\n ) {\n super(say(\"agent.send_unsupported\", agentName, cli));\n }\n}\n\n/**\n * A pi extension answered a send/fresh with `ok: false`: it read the request\n * and took nothing. (Unlike a silent socket, an explicit refusal proves the\n * prompt was not accepted.)\n */\nexport class AgentSendRefusedError extends Error {\n override readonly name = \"AgentSendRefusedError\";\n constructor(public readonly reason: string) {\n super(say(\"agent.send_refused\", reason));\n }\n}\n\n/**\n * `agent spawn --task`: another mu process is running this same attempt\n * (task + attempt key). Nothing was done; retry once it finishes and the\n * replay returns its outcome. Exit 4.\n */\nexport class SpawnAttemptBusyError extends Error {\n override readonly name = \"SpawnAttemptBusyError\";\n constructor(\n public readonly task: string,\n public readonly attemptKey: string,\n ) {\n super(say(\"agent.attempt_busy\", task, attemptKey));\n }\n}\n\n/**\n * `mu next`: an executor attempt (`auto:<n>`) cannot be run or resumed: it\n * failed before anything was sent (its run stays charged), was never\n * reserved, or its saved identity is gone. It is never reset; the next\n * attempt is a new key and a new charge. Exit 4.\n */\nexport class SpawnAttemptFailedError extends Error {\n override readonly name = \"SpawnAttemptFailedError\";\n constructor(\n public readonly task: string,\n public readonly attemptKey: string,\n reason: string,\n ) {\n super(say(\"agent.attempt_failed\", task, attemptKey, reason));\n }\n}\n\n/**\n * `mu next`: permission, readiness or the revision changed between the\n * reservation and an effect (revoked `mu task auto`, another host\n * designated, the task claimed or closed). Nothing was spawned or sent past\n * this point; a reservation made earlier stays resumable. Exit 4.\n */\nexport class SpawnAttemptGuardError extends Error {\n override readonly name = \"SpawnAttemptGuardError\";\n constructor(\n public readonly task: string,\n public readonly attemptKey: string,\n reason: string,\n ) {\n super(say(\"agent.attempt_stopped\", task, attemptKey, reason));\n }\n}\n\n/**\n * `agent spawn --task`: the task is not claimable by this attempt any more\n * (closed, or owned by someone else since the claim). Nothing was sent; the\n * attempt's own pane is rolled back. Exit 4.\n */\nexport class SpawnTaskStateError extends Error {\n override readonly name = \"SpawnTaskStateError\";\n constructor(\n public readonly task: string,\n reason: string,\n ) {\n super(say(\"agent.task_state\", task, reason));\n }\n}\n\n/**\n * `agent spawn --task` replayed an attempt key with a different request\n * (name, text or --next-free): a second prompt must be a new attempt. Exit 4.\n */\nexport class SpawnReceiptConflictError extends Error {\n override readonly name = \"SpawnReceiptConflictError\";\n constructor(\n public readonly task: string,\n public readonly attemptKey: string,\n public readonly savedName: string,\n ) {\n super(say(\"agent.receipt_conflict\", task, attemptKey, savedName));\n }\n}\n\n/**\n * `agent spawn --task`: the agent came up but cannot take the prompt (Claude\n * is parked at its folder-trust dialog). Nothing was sent; the spawn was\n * rolled back. Exit 1.\n */\nexport class SpawnTrustDialogError extends Error {\n override readonly name = \"SpawnTrustDialogError\";\n constructor(public readonly agentName: string) {\n super(say(\"agent.trust_dialog\", agentName));\n }\n}\n"],"mappings":"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","names":["capture","pad","SEP","text","options","stylize","builder","colors","style","sequencer","map","Table","firstLine","execFile","existsSync","mkdirSync","rmSync","statSync","basename","dirname","resolve","promisify","dirname","existsSync","homedir","join","dirname","resolve","createHash","dirname","join","randomUUID","randomUUID","capture","join","createHash","dirname","randomUUID","machineId","now","randomUUID","process","resolve","picocolors","Table","resolve","sleep","PANE_ID_RE","isValidPaneId","assertValidPaneId","realExecutor","currentExecutor","ensureSession","killSession","listPanes","killPane","paneAlive","currentSessionName","spawnAgent","args","appendEnvFlags","sleep","capture","attachCommands","healthCheck","dirname","sleep","join","homedir","existsSync","now","randomUUID","dirname","stat","now","paneAlive","randomUUID","profile","run","dirname","randomUUID","randomUUID","now","createHash","createHash","live","rowFromDb","now","rowFromDb","canonical","now","live","readdirSync","dirname","join","crc32","live","execFile","existsSync","readFileSync","join","promisify","execFile","existsSync","mkdirSync","rmSync","dirname","resolve","execFile","worktreePath","resolve","mkdirSync","dirname","rmSync","existsSync","join","existsSync","exec","promisify","execFile","readFileSync","pid","command","crc32","sameRow","join","dirname","readdirSync","now","now","row","track","now","firstLine","run","r","m","live","live","now","randomUUID","randomUUID","unknown","run","createHash","dirname","join","dirname","join","join","sleep","dirname","token","join","dirname","createHash","now","worktree","dirname","dirname","createHash","dirname","join","VERDICT_LINE","join","dirname","createHash","canonical","taskIdFor","createHash","fromRaw","now","reconcile","spawnAgent","now","rec","now","rowFromDb","rows","dirname","live","join","join","DEFAULT_ACQUIRE_TIMEOUT_MS","now","envVarNameForCli","promisify","execFile","shellQuote","existsSync","basename","existsSync","spawnAgent","envVarNameForCli","resolve","dirname","mkdirSync","statSync","rmSync","paneGone","say","sleep"]}
|