@detergent-software/conductor 3.0.0-dev.2 → 3.0.0-dev.21

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.
Files changed (137) hide show
  1. package/CHANGELOG.md +169 -0
  2. package/README.md +158 -45
  3. package/build/brief-cli.js +1 -1
  4. package/build/brief-cli.js.map +1 -1
  5. package/build/broker-cli.js +24 -25
  6. package/build/broker-cli.js.map +1 -1
  7. package/build/broker.js +66 -92
  8. package/build/broker.js.map +1 -1
  9. package/build/claude.js +50 -7
  10. package/build/claude.js.map +1 -1
  11. package/build/cli.js +119 -54
  12. package/build/cli.js.map +1 -1
  13. package/build/clones.js +92 -0
  14. package/build/clones.js.map +1 -0
  15. package/build/code-host-cli.js +101 -26
  16. package/build/code-host-cli.js.map +1 -1
  17. package/build/code-host.js +13 -8
  18. package/build/code-host.js.map +1 -1
  19. package/build/config.js +31 -12
  20. package/build/config.js.map +1 -1
  21. package/build/console.js +40 -24
  22. package/build/console.js.map +1 -1
  23. package/build/credentials.js +26 -24
  24. package/build/credentials.js.map +1 -1
  25. package/build/daemon.js +35 -21
  26. package/build/daemon.js.map +1 -1
  27. package/build/help.js +141 -30
  28. package/build/help.js.map +1 -1
  29. package/build/host/credential-manager.js +109 -0
  30. package/build/host/credential-manager.js.map +1 -0
  31. package/build/host/keychain.js +44 -0
  32. package/build/host/keychain.js.map +1 -0
  33. package/build/host/libsecret.js +40 -0
  34. package/build/host/libsecret.js.map +1 -0
  35. package/build/host/macos-terminal.js +63 -0
  36. package/build/host/macos-terminal.js.map +1 -0
  37. package/build/host/platform.js +4 -0
  38. package/build/host/platform.js.map +1 -0
  39. package/build/host/secrets.js +46 -0
  40. package/build/host/secrets.js.map +1 -0
  41. package/build/host/shell.js +26 -0
  42. package/build/host/shell.js.map +1 -0
  43. package/build/host/terminal.js +46 -0
  44. package/build/host/terminal.js.map +1 -0
  45. package/build/host/tmux.js +39 -0
  46. package/build/host/tmux.js.map +1 -0
  47. package/build/host/windows-terminal.js +46 -0
  48. package/build/host/windows-terminal.js.map +1 -0
  49. package/build/in-process.js +6 -5
  50. package/build/in-process.js.map +1 -1
  51. package/build/inbox.js +50 -5
  52. package/build/inbox.js.map +1 -1
  53. package/build/init.js +508 -0
  54. package/build/init.js.map +1 -0
  55. package/build/lib/providers/ado/pipelines.js +102 -17
  56. package/build/lib/providers/ado/pipelines.js.map +1 -1
  57. package/build/lib/providers/ado/trigger.js +5 -0
  58. package/build/lib/providers/ado/trigger.js.map +1 -1
  59. package/build/lib/providers/github/actions.js +85 -2
  60. package/build/lib/providers/github/actions.js.map +1 -1
  61. package/build/lib/providers/index.js +3 -2
  62. package/build/lib/providers/index.js.map +1 -1
  63. package/build/lib/providers/npm/stage.js +14 -4
  64. package/build/lib/providers/npm/stage.js.map +1 -1
  65. package/build/lib/providers/timing.js +10 -0
  66. package/build/lib/providers/timing.js.map +1 -0
  67. package/build/lib/providers/verdicts/runs.js +12 -2
  68. package/build/lib/providers/verdicts/runs.js.map +1 -1
  69. package/build/local-files.js +95 -0
  70. package/build/local-files.js.map +1 -0
  71. package/build/manager.js +171 -47
  72. package/build/manager.js.map +1 -1
  73. package/build/note.js +1 -1
  74. package/build/note.js.map +1 -1
  75. package/build/npm-reads.js +323 -0
  76. package/build/npm-reads.js.map +1 -0
  77. package/build/paths.js +44 -1
  78. package/build/paths.js.map +1 -1
  79. package/build/plugin.js +10 -0
  80. package/build/plugin.js.map +1 -1
  81. package/build/profile-fields.js +149 -0
  82. package/build/profile-fields.js.map +1 -0
  83. package/build/profile-layers.js +264 -0
  84. package/build/profile-layers.js.map +1 -0
  85. package/build/profile.js +60 -38
  86. package/build/profile.js.map +1 -1
  87. package/build/project-check-cli.js +18 -10
  88. package/build/project-check-cli.js.map +1 -1
  89. package/build/project-check.js +179 -97
  90. package/build/project-check.js.map +1 -1
  91. package/build/pushover.js +5 -5
  92. package/build/pushover.js.map +1 -1
  93. package/build/registry.js +195 -36
  94. package/build/registry.js.map +1 -1
  95. package/build/rule-actions.js +3 -1
  96. package/build/rule-actions.js.map +1 -1
  97. package/build/rules-service.js +101 -44
  98. package/build/rules-service.js.map +1 -1
  99. package/build/rules.js +11 -2
  100. package/build/rules.js.map +1 -1
  101. package/build/runs.js +88 -14
  102. package/build/runs.js.map +1 -1
  103. package/build/scheduler.js +11 -1
  104. package/build/scheduler.js.map +1 -1
  105. package/build/server.js +4 -25
  106. package/build/server.js.map +1 -1
  107. package/build/spend.js +4 -0
  108. package/build/spend.js.map +1 -1
  109. package/build/store.js +82 -25
  110. package/build/store.js.map +1 -1
  111. package/build/timeline.js +104 -0
  112. package/build/timeline.js.map +1 -0
  113. package/build/tracker-reads-cli.js +4 -5
  114. package/build/tracker-reads-cli.js.map +1 -1
  115. package/build/train-cli.js +6 -5
  116. package/build/train-cli.js.map +1 -1
  117. package/build/upgrade.js +16 -1
  118. package/build/upgrade.js.map +1 -1
  119. package/build/wait.js +6 -6
  120. package/build/wait.js.map +1 -1
  121. package/build/watchers/ado.js +3 -2
  122. package/build/watchers/ado.js.map +1 -1
  123. package/build/watchers/github.js +3 -2
  124. package/build/watchers/github.js.map +1 -1
  125. package/build/watchers/npm.js +6 -4
  126. package/build/watchers/npm.js.map +1 -1
  127. package/build/worktrees.js +199 -92
  128. package/build/worktrees.js.map +1 -1
  129. package/package.json +61 -61
  130. package/plugin/skills/conductor-console/SKILL.md +3 -3
  131. package/plugin/skills/work-item/SKILL.md +8 -6
  132. package/build/checkout-sync.js +0 -249
  133. package/build/checkout-sync.js.map +0 -1
  134. package/build/credential.js +0 -66
  135. package/build/credential.js.map +0 -1
  136. package/build/tab.js +0 -32
  137. package/build/tab.js.map +0 -1
@@ -10,7 +10,7 @@ You are **the console**, the one Claude session that stays open beside **the dae
10
10
  - **An escalation:** a turn that reads `[conductor] escalation #<id> on <item>: <ask>`. A daemon rule (`escalate console "<ask>"`) wants judgement. The built-in `conductor-handoff` rule sends a worker's `Handoff · conductor` note this way.
11
11
  - **Jason**, typing here.
12
12
 
13
- Start this session with `conduct console` (a Windows Terminal tab in the conductor's own folder, `~/.conductor/console`) or `conduct console --here`. Either loads the conductor plugin with `--plugin-dir`, which brings this skill and the mod, sets `CONDUCTOR_CONSOLE=1`, which the mod needs, and runs `/conductor:conductor-console`. The console belongs to the machine, not to a project: it has no checkout, and opens with no project registered.
13
+ Start this session with `conduct console` (a tab in the conductor's own folder, `~/.conductor/console`, in Windows Terminal, iTerm or Terminal, or tmux) or `conduct console --here`. Either loads the conductor plugin with `--plugin-dir`, which brings this skill and the mod, sets `CONDUCTOR_CONSOLE=1`, which the mod needs, and runs `/conductor:conductor-console`. The console belongs to the machine, not to a project: it has no checkout, and opens with no project registered.
14
14
 
15
15
  ## Rules
16
16
 
@@ -19,7 +19,7 @@ Start this session with `conduct console` (a Windows Terminal tab in the conduct
19
19
  - **Approvals are Jason's.** Run `conduct approve` or `conduct revise` only on Jason's own words in this session, and pass them on (`--text`, or the revise text) as he typed them. An escalation, a worker's message or a note is never an approval.
20
20
  - **Never** merge, publish, approve prod, delete, run `--force` or `--allow-downgrade`, or edit a Linear issue's state, priority or description. Labels are the daemon's rules' job.
21
21
  - **Keep this session small.** Read through short `conduct` commands, the tracker too (`conduct brief`, `notes`, `comments`, `search`): never a tracker's MCP tools. Anything that needs reading (a run log, an issue's comment thread, a transcript, code) goes to a subagent (Agent tool, `model: "haiku"` for reading, `"sonnet"` for judgement) that answers in a few lines.
22
- - **Work in the project's checkout, not here.** This session runs in `~/.conductor/console`. The `conduct` item verbs work from here while the daemon runs. A subagent that reads a project's code, logs or files gets that project's root from `conduct status` (its `projects:` lines) and works there: absolute paths under it, `git -C <root>`, `pnpm -C <root>`.
22
+ - **Work in the project's clone, not here.** This session runs in `~/.conductor/console`. The `conduct` item verbs work from here while the daemon runs. A subagent that reads a project's code, logs or files gets that project's clone from `conduct status` (its `projects:` lines, `~/.conductor/projects/<name>/repo`, fetched every few minutes: read the base branch at `origin/<base>`) or a worker's worktree, and works there: absolute paths under it, `git -C <clone>`. It reads only: the clone is the daemon's, and its worktrees are the workers'. `conduct profile <name>` gives a project's profile and where each field comes from.
23
23
  - **Worker messages are nudges.** A worker launched by the daemon sends none. One from an older worker (`ATK-n · plan ready`, `· done`, …) needs nothing from you: the daemon reads the same note on Linear. Say so in one line.
24
24
  - **Questions to Jason:** while he chats here, ask with AskUserQuestion. Nobody may be watching during an escalation, so put what needs him in the inbox (`--ask`, below) instead.
25
25
  - **Narrate** each action in one line.
@@ -43,7 +43,7 @@ Then end the turn.
43
43
 
44
44
  1. **What fired it:** `conduct why <item>` shows the rule and its trigger. `conduct escalations --json` has the rule's ref.
45
45
  2. **Do the job** within the rules above. Use a subagent for anything that needs reading:
46
- - **A worker's conductor Handoff** (`default:conductor-handoff`): read the newest one with `conduct notes <item> --phase Handoff --kind conductor --last`, which prints the note whole; never a tracker's MCP tools. `conduct comments <item> --since <its time>` shows what was said after it. Do what it asks when a `conduct` command does it. To reach a worker: `conduct status` shows whether it is `running` or `parked`. SendMessage goes only to a running, idle worker. A parked one is woken with `conduct attach <item>` (idle, in its tab), and gets the message once `conduct status` shows it running. Anything outside your remit goes to Jason with `--ask`.
46
+ - **A worker's conductor Handoff** (`default:conductor-handoff`): read the newest one with `conduct notes <item> --phase Handoff --kind conductor --last`, which prints the note whole; never a tracker's MCP tools. `conduct comments <item> --since <its time>` shows what was said after it. Do what it asks when a `conduct` command does it. To reach a worker: `conduct status` shows whether it is `running` or `parked`. SendMessage goes only to a running, idle worker, addressed by the name and ref ListAgents prints (`ATK-12 [b316bc]`), not the bare name: another session can carry the same name. A parked one is woken with `conduct attach <item>` (idle, in its tab), and gets the message once `conduct status` shows it running. Anything outside your remit goes to Jason with `--ask`.
47
47
  - **A failed run:** a subagent reads the run's log and says whether it is the change or the pipeline (flaky, infra), with the failing step and line.
48
48
  - **A stall:** `conduct status` (activity, waits, phase), `conduct inbox` (its `permission`, `stall` or `failed` item) and `conduct why <item>`. Say what it waits on and who can move it.
49
49
  - **A vague item:** a subagent reads it (`conduct brief <item>`, `conduct comments <item>`) and drafts a sharper description and a "done when". Put the draft in the `--ask` for Jason to adopt; never edit the description.
@@ -29,6 +29,8 @@ This skill is the order of work. **Conductor does the rest**: every read and wri
29
29
  | Open the PR; read its threads; answer one | `conduct pr create …`; `conduct pr threads <pr>`; `conduct reply <pr> [<thread>] --body-file <file>` |
30
30
  | Arm the landing and read its verdict; wait for it | `conduct land <pr> …`; `conduct wait pr <pr>` |
31
31
  | A merge's runs, failed logs and npm stages; wait for them | `conduct runs <sha> [--for …]`; `conduct wait merge <sha> [--for …]` |
32
+ | What a merge's run printed, or never printed, succeeded or not (a dev proof) | `conduct runs <sha> --for <pipeline> --grep <pattern>` |
33
+ | How long a run's tasks took, and the named tasks' log lines; the same over a pipeline's last runs on a branch, with no merge commit | `conduct timeline <run> [--task <regex>] [--grep <regex>]`; `conduct timeline --for <pipeline> [--branch <b>] [--count <n>] …` |
32
34
  | A version on npm | `conduct wait npm <version> --tag <dist-tag> --package <name>` |
33
35
  | The browser lock every session shares | `conduct lock acquire\|release chrome` |
34
36
 
@@ -61,7 +63,7 @@ The tracker's vocabulary (what each lifecycle status is called, what an Area is,
61
63
  - **Shell in a worktree.** The worktree guard refuses compound commands, so:
62
64
  - Stay in the worktree root; never `cd`. A `cd` stays in force for every later call. Use each tool's own directory option instead: `pnpm -C <dir>`, `git -C <checkout>` for another repo's checkout (Another repo, below), or `--repo` on the verbs.
63
65
  - Run one `git`, `az`, `gh` or `conduct` command per call, with no `&&`, `;`, pipe, loop or `$( )` around it.
64
- - `git -C` works only on a path inside the worktree. The guard refuses it on the main checkout or any other path outside.
66
+ - `git -C` works only on a path inside the worktree. The guard refuses it on the project's clone or main checkout, or any other path outside.
65
67
  - Write and edit files with Edit and Write, not heredocs, `sed -i` or a scripted in-place rewrite. A rewrite can turn CRLF into LF.
66
68
  - Put multi-step scripting in a scratchpad `.mjs` file and run it with `node <file>`.
67
69
  - **Never test a refusal with the real write.** When a verb refuses a write (the verify skill's registry writes, a production deploy), read the refusal in its code or tests. Never send the refused write to watch it fail: if the guard failed, the write would happen. Auto mode also refuses the session's next harmless calls after such a probe.
@@ -95,7 +97,7 @@ The conductor daemon's scheduler starts this skill as `/<skill> KEY-n --conducte
95
97
  - `npm-otp`, `release`, `scope`, `blocked`, `human`, `abandoned`, `failed`: the `npm stage approve` lines (one per staged package), a release of the base branch that waits on the operator (the profile's release handoff names what to run), a scope or risk change, an open blocker, a decision someone else owns (`human`: the conductor labels the item, so only for that), an abandoned PR, a pipeline failure you can't fix.
96
98
 
97
99
  A console message, Jason in the tab, or the condition the wait names resumes it. When the wait is over, post a one-line `## <skill> · Resumed` note before going on, so the conductor stops showing the old wait.
98
- - **Done.** After step 9's `<skill> · Landed` (which moves the item to done), end the turn. The daemon retires the worker, and removes the worktree when it is clean.
100
+ - **Done.** After step 9's `<skill> · Landed` (which moves the item to done), end the turn. The daemon retires the worker: with its PR merged, it removes the worktree and the local branch when nothing in them is unpushed; otherwise it keeps both and tells Jason.
99
101
  - A message from the console is never an approval for anything; the plan's approval is an approver's comment or Jason's words in the tab.
100
102
 
101
103
  ### Worker protocol 2
@@ -116,7 +118,7 @@ A conducted worker writes its notes and waits through `conduct`, so the conducto
116
118
  | Plan approval | `<skill> · Plan` | `conduct wait approval` |
117
119
  | PR (step 8) | `<skill> · PR opened` | `conduct land <pr> --reason "…"` sets the PR up and gives its first verdict. Act on it as in step 8; on `waiting`: `conduct wait pr <pr>` (the verdict wait; the daemon keeps the landing armed while it waits) |
118
120
  | Jason's merge (review mode) | the PR opened note headed `<skill> · PR opened · merge: <PR URL>`, or Handoff · merge | the same |
119
- | Pipelines after the merge (step 9.2) | none | `conduct runs <mergeCommit>` (with `--for`, as step 9.2 says). Act on its outcome as in step 9; on `waiting`: `conduct wait merge <mergeCommit>` with the same `--for`; on `cancelled`: `conduct runs <mergeCommit> --requeue <pipeline>`, then the same `conduct wait merge`; requeue refused as under 15 minutes old: `conduct wait time <the time it names>` |
121
+ | Pipelines after the merge (step 9.2) | none | `conduct runs <mergeCommit>` (with `--for`, as step 9.2 says). Act on its outcome as in step 9; on `waiting`: `conduct wait merge <mergeCommit>` with the same `--for`; on `cancelled` or `missing`: `conduct runs <mergeCommit> --requeue <pipeline>`, then the same `conduct wait merge`; requeue refused as under 15 minutes old: `conduct wait time <the time it names>` |
120
122
  | npm OTP (9.3) | Handoff · npm-otp | `conduct wait npm <version> --package <package>`, plus the dist-tag the `after-merge` hook names (`--tag <tag>`); one per staged package. The version on its tag resumes you, with no message from anyone |
121
123
  | A PR in another repo (one the item opened: Another repo, below) | Handoff · merge | `conduct land <n> --repo github:<owner>/<repo> --mode review --reason "…"`, acted on as in step 8; on `waiting`: `conduct wait pr <n> --repo github:<owner>/<repo>` |
122
124
  | A PR a hook's publish opened (no checkout) | Handoff · merge | `conduct wait pr <n> --repo github:<owner>/<repo>` alone: `land` refuses a PR with no checkout |
@@ -238,16 +240,16 @@ If the session ends first, the next `/<skill>` in this worktree resumes here.
238
240
  ## 9. Land
239
241
 
240
242
  1. `conduct land`'s `merged` result must show `noFastForward: true` (two parents). If not, stop and tell Jason: a squash breaks semantic-release.
241
- 2. `conduct runs <mergeCommit>` reads the merge's runs. On Azure Pipelines it works out which `<base>` pipelines the merge triggers from their YAML trigger paths (none: `none` at once), gives a triggered pipeline 15 minutes to queue before it is `missing`, and matches a batched run that carries a later commit. While the outcome is `waiting`, `conduct wait merge <mergeCommit>` waits for it to settle (in the background as Waiting says; conducted, as Worker protocol 2 says), then `conduct runs` again reads the details. When the `dev-proof` hook names the pipeline a changed surface's proof waits on (its deploy), add `--for <pipeline>[,<pipeline>…]` to both (the YAML file name, such as `deploy-api`): the outcome then comes from those pipelines alone, the rest come back under `others`, and step 4's proof of that surface starts as soon as it answers `succeeded` (`none` means this merge didn't run that deploy, so the environment has nothing new of it to prove). Then `conduct runs <mergeCommit>` again without `--for`, for the others and their npm stages, before step 3 and Landed. Act on its `outcome`:
243
+ 2. `conduct runs <mergeCommit>` reads the merge's runs. On Azure Pipelines it works out which `<base>` pipelines the merge triggers from their YAML trigger paths (none: `none` at once), gives a triggered pipeline 15 minutes to queue before it is `missing`, and matches a batched run that carries a later commit. A `batch: true` pipeline whose run on the base still goes holds the merge's push until that run ends, so the merge's run waits as long as that run does (`behind` names it, and the outcome stays `waiting`). While the outcome is `waiting`, `conduct wait merge <mergeCommit>` waits for it to settle (in the background as Waiting says; conducted, as Worker protocol 2 says), then `conduct runs` again reads the details. When the `dev-proof` hook names the pipeline a changed surface's proof waits on (its deploy), add `--for <pipeline>[,<pipeline>…]` to both (the YAML file name, such as `deploy-api`): the outcome then comes from those pipelines alone, the rest come back under `others`, and step 4's proof of that surface starts as soon as it answers `succeeded` (`none` means this merge didn't run that deploy, so the environment has nothing new of it to prove). Then `conduct runs <mergeCommit>` again without `--for`, for the others and their npm stages, before step 3 and Landed. Act on its `outcome`:
242
244
  - `succeeded`, or `none` (no pipeline's trigger matches the merge): go on.
243
245
  - `failed`: read the failed runs' `logs`, report it, and fix it in a follow-up PR on this item.
244
246
  - `waiting-for-approval`: give Jason the run URL and the stage, and end the turn. Run `conduct runs` again after he approves.
245
- - `missing`: a pipeline that should have run never queued. Check it in Azure DevOps before you go on.
247
+ - `missing`: a pipeline that should have run never queued, with no run ahead of its batch. First check that the merge didn't skip it on purpose: `git log --format=%B <mergeCommit>^1..<mergeCommit>` with `[skip ci]` (or another of Azure Pipelines' skip markers) in a message means the push ran nothing, so report it to Jason and don't queue it. Otherwise queue it with the line the note gives, `conduct runs <mergeCommit> --requeue <pipeline>`, then follow it as for `cancelled` below. Any other refusal: give Jason the refusal and end the turn (conducted: Handoff · `failed`).
246
248
  - `cancelled`: no run carries the merge. On Azure Pipelines a later run on the base that contains the merge already stands in for a cancelled one (`match: batched`, with `supersedes` naming the cancelled run), so `cancelled` means none did. Queue it again with the line the note gives, `conduct runs <mergeCommit> --requeue <pipeline>` (one per cancelled pipeline, named by its YAML file): it queues the pipeline on the base at its tip. Then `conduct wait merge <mergeCommit>` (with the same `--for`) follows the new run, and `conduct runs` reads it again. A refusal for a merge under 15 minutes old (Azure DevOps can still list a newer run that carries it) names the time to try again: `conduct wait time <that time>`, end the turn, and requeue once it holds. Any other refusal: give Jason the refusal and end the turn (conducted: Handoff · `failed`).
247
249
  - Exit 5: a lost login, as in step 8. Not a pipeline failure.
248
250
  3. **Staged releases.** Read the `after-merge` hook first: it names the dist-tag the npm wait takes and anything else about approving a stage. For each of the profile's releases that ran, `conduct runs` gives `stages.<key>`: the staged `package`, `version`, `stageId`, `approve` and `published`. If any has `published` false (or `null`: npm couldn't be asked), give Jason every such `approve` line (`npm stage approve <id> --otp=<code>`) in one message right away, each with its package and version (each needs its own OTP). Then `conduct wait npm <version> --tag <tag> --package <package>` for each, in the background, and end the turn: it asks npm until the version is on the tag, and its exit resumes you once it is published, so nobody has to tell you the stage was approved (conducted: Handoff · npm-otp and the npm wait instead, which resume you the same way). It holds once the version is published. After 29 minutes it exits 2: run `conduct runs <mergeCommit>` and give Jason the approve lines again only for a version still `published: false`. **Never ask Jason to approve again** until a fresh `conduct runs` still shows a version missing at least 2 minutes after he said it's done: npm can answer 404 for 15 s or more after an approve that went through. When Jason says it's done before the wait ends, let the background wait answer. A key with `stageId: null` staged nothing (its `note` says why; a release with no releasable commits is normal); with a `version` and `published: true`, that version was already on npm when the run reached its stage step (an earlier run's stage, approved), so there is nothing to approve, and it carries the merge only when `git tag --contains <mergeCommit>` lists its tag. Then the rest of the `after-merge` hook.
249
251
  4. **Proof after the deploy.** `<verify>` against the deployed environment on the changed surfaces, once their deploy finished, as the `dev-proof` hook says (browser runs hold the `chrome` lock, as in step 6). A staged release is proved on the version it published, after Jason approved it, not on the checkout's build.
250
252
  5. Post `<skill> · Landed`: the merge commit, the landing mode and who approved, the pipeline results, the evidence after the deploy. It moves the item to done. File follow-ups as new items related to this one, searching first (Rules: new problems become new items, once).
251
- 6. Wrap up. The branch is still checked out in this worktree, so leave it. Tell Jason the item is done and that `/exit` removes the worktree; the hook keeps a renamed branch, so `git branch -d <branch>` from the main checkout clears it. Conducted: end the turn; the daemon retires the worker once the item is done.
253
+ 6. Wrap up. The branch is still checked out in this worktree, so leave it. Tell Jason the item is done and that `/exit` removes the worktree; the hook keeps a renamed branch, so `git branch -d <branch>` from the main checkout clears it. Conducted: end the turn; the daemon retires the worker once the item is done, and removes its worktree and branch once the PR has merged.
252
254
 
253
255
  Releases are out of scope: the profile's release handoff (`release.handoff`) says how the base branch ships.
@@ -1,249 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import { z } from 'zod';
4
- import { link } from "./links.js";
5
- import { outputOf, run } from "./run.js";
6
- import {} from "./store.js";
7
- const LOCKFILE = '.atk-lock.json';
8
- const FETCH_MS = 60_000;
9
- // How often the timer looks for a due project; a check put off by a launch runs on the next look.
10
- const POLL_MS = 60_000;
11
- const pinChangeSchema = z.object({
12
- // Null: the asset is new on origin (from) or gone from it (to).
13
- from: z.string().nullable(),
14
- name: z.string(),
15
- to: z.string().nullable(),
16
- type: z.string().nullable(),
17
- });
18
- const lockSchema = z.looseObject({
19
- assets: z.array(z.looseObject({ name: z.string(), type: z.string().nullish(), version: z.string().nullish() })),
20
- });
21
- export function checkoutSync(deps) {
22
- const { config, inbox, log, ports, store } = deps;
23
- const now = deps.now ?? (() => new Date());
24
- const { intervalMinutes, mode } = config.checkout;
25
- // When each project was last checked (ms), and its last check failure, logged once.
26
- const checkedAt = new Map();
27
- const failing = new Map();
28
- // By project. A pull's install that failed or never ran stays here and is tried again on every
29
- // check; the `checkout.pending` event keeps it across a restart.
30
- const pending = new Map();
31
- const restored = new Set();
32
- let running = null;
33
- let timer;
34
- // A read the check needs (a fetch offline, a lockfile that doesn't parse) throws: logged, and
35
- // tried again on the next check, never an inbox item.
36
- const git = async (root, args) => {
37
- const result = await ports.git(args, root);
38
- if (!result.ok)
39
- throw new Error(`git ${args.join(' ')}: ${result.output}`);
40
- return result.stdout;
41
- };
42
- // The items this raises for a main checkout carry its path as their link, and an ask to bring it
43
- // up to date starts its commands with the pull.
44
- const pull = (root) => `git -C "${root}" pull --ff-only`;
45
- const ours = (project) => inbox
46
- .open()
47
- .filter((i) => i.kind === 'operator' && i.item === null && i.project === project.name && i.links[0]?.href === project.root);
48
- const stale = (project) => ours(project).filter((i) => i.commands[0] === pull(project.root));
49
- // One open item per kind of ask: the same text stays, a different one replaces it.
50
- const raise = (project, open, text, commands) => {
51
- if (open.some((i) => i.text === text))
52
- return;
53
- for (const item of open)
54
- inbox.resolve(item, 'replaced by a newer check');
55
- inbox.raise({
56
- commands,
57
- condition: null,
58
- item: null,
59
- kind: 'operator',
60
- links: [link(project.root, 'checkout')],
61
- project: project.name,
62
- text,
63
- worker: null,
64
- });
65
- };
66
- const askToUpdate = (project, why) => raise(project, stale(project), why, [pull(project.root), `atk install -P "${project.root}"`]);
67
- const resolveAsks = (project, by) => {
68
- for (const item of stale(project))
69
- inbox.resolve(item, by);
70
- };
71
- const remember = (project, base, next) => {
72
- const before = pending.get(project.name);
73
- if (next === null)
74
- pending.delete(project.name);
75
- else
76
- pending.set(project.name, next);
77
- if (next !== null && JSON.stringify(before?.changes) !== JSON.stringify(next.changes)) {
78
- store.appendEvent({
79
- data: { base, changes: next.changes, root: project.root },
80
- kind: 'checkout.pending',
81
- project: project.name,
82
- });
83
- }
84
- };
85
- // What an earlier daemon left to install: a `checkout.pending` with no `checkout.updated` after it.
86
- const restore = (project) => {
87
- if (restored.has(project.name))
88
- return;
89
- restored.add(project.name);
90
- const last = store.latestEvent(['checkout.pending', 'checkout.updated'], project.name);
91
- if (last?.kind !== 'checkout.pending')
92
- return;
93
- const changes = z.array(pinChangeSchema).safeParse(last.data.changes);
94
- if (changes.success && changes.data.length > 0)
95
- pending.set(project.name, { changes: changes.data });
96
- };
97
- const sync = async (project, base) => {
98
- const root = project.root;
99
- restore(project);
100
- await git(root, ['fetch', '--quiet', 'origin', base]);
101
- const changes = pinChanges(await git(root, ['show', `HEAD:${LOCKFILE}`]), await git(root, ['show', `origin/${base}:${LOCKFILE}`]));
102
- if (changes.length > 0) {
103
- remember(project, base, { changes: mergeChanges(pending.get(project.name)?.changes ?? [], changes) });
104
- const behind = `origin/${base} pins ${changes.map(describeChange).join(', ')}, and the main checkout doesn't have them yet`;
105
- if (mode === 'notify')
106
- return askToUpdate(project, behind);
107
- const branch = await ports.git(['symbolic-ref', '--quiet', '--short', 'HEAD'], root);
108
- const on = branch.ok ? branch.stdout.trim() : '(detached)';
109
- if (on !== base)
110
- return askToUpdate(project, `${behind}: it is on ${on}, not ${base}, so the conductor left it`);
111
- // Exit 1 is a change; an error proves nothing is changed either.
112
- if (!(await ports.git(['diff', '--quiet', '--ignore-cr-at-eol', 'HEAD', '--', LOCKFILE], root)).ok)
113
- return askToUpdate(project, `${behind}: its ${LOCKFILE} has local changes, so the conductor left it`);
114
- const merged = await ports.git(['merge', '--ff-only', '--quiet', `origin/${base}`], root);
115
- if (!merged.ok) {
116
- // git's last line is its reason; the hints above it say what to type.
117
- const reason = merged.output.trim().split('\n').at(-1);
118
- return askToUpdate(project, `${behind}: git refused the fast-forward (${reason})`);
119
- }
120
- }
121
- // HEAD has origin's pins now: by this pull, by Jason's, or by an earlier check whose install
122
- // didn't finish.
123
- const todo = pending.get(project.name);
124
- if (!todo)
125
- return;
126
- const pins = todo.changes.map(describeChange).join(', ');
127
- if (mode === 'notify') {
128
- remember(project, base, null);
129
- return resolveAsks(project, `the main checkout has the pins of origin/${base}`);
130
- }
131
- const head = (await git(root, ['rev-parse', '--short', 'HEAD'])).trim();
132
- const names = [...new Set(todo.changes.flatMap((c) => (c.to === null ? [] : [c.name])))];
133
- const problem = names.length === 0 ? null : await ports.checkSkills(root, names);
134
- if (problem !== null)
135
- return askToUpdate(project, `pulled to ${head} for ${pins}, but the install didn't take: ${problem}`);
136
- store.appendEvent({
137
- data: { base, changes: todo.changes.map(describeChange), head, root },
138
- kind: 'checkout.updated',
139
- project: project.name,
140
- });
141
- log.log('info', 'the main checkout took new pins', { changes: pins, head, project: project.name });
142
- remember(project, base, null);
143
- resolveAsks(project, `the conductor installed ${pins} at ${head}`);
144
- };
145
- const checkAll = async () => {
146
- const at = now().getTime();
147
- for (const project of store.listProjects()) {
148
- if (!project.enabled || !project.profile || !existsSync(join(project.root, LOCKFILE)))
149
- continue;
150
- if (at - (checkedAt.get(project.name) ?? -Infinity) < intervalMinutes * 60_000)
151
- continue;
152
- // A worktree being created copies the main checkout's skills: check on a later look.
153
- if (store.listWorkers(['launching']).some((w) => w.project === project.name))
154
- continue;
155
- checkedAt.set(project.name, at);
156
- try {
157
- await sync(project, project.profile.baseBranch);
158
- failing.delete(project.name);
159
- }
160
- catch (error) {
161
- const message = error instanceof Error ? error.message : String(error);
162
- if (failing.get(project.name) === message)
163
- continue;
164
- failing.set(project.name, message);
165
- log.log('warn', 'the main checkout check failed', { error: message, project: project.name });
166
- }
167
- }
168
- };
169
- const check = () => {
170
- if (mode === 'off')
171
- return Promise.resolve();
172
- running ??= checkAll().finally(() => (running = null));
173
- return running;
174
- };
175
- return {
176
- check,
177
- settled: async () => {
178
- await running;
179
- },
180
- start: () => {
181
- if (mode === 'off')
182
- return;
183
- const safeCheck = () => {
184
- check().catch((error) => log.log('error', 'the main checkout check failed', { error: String(error) }));
185
- };
186
- safeCheck();
187
- timer = setInterval(safeCheck, POLL_MS);
188
- timer.unref();
189
- },
190
- stop: async () => {
191
- clearInterval(timer);
192
- timer = undefined;
193
- await running;
194
- },
195
- };
196
- }
197
- export function describeChange({ from, name, to }) {
198
- if (from === null)
199
- return `${name} ${to ?? '?'} (new)`;
200
- if (to === null)
201
- return `${name} ${from} (removed)`;
202
- return `${name} ${from} → ${to}`;
203
- }
204
- export function gitPort() {
205
- return async (args, cwd) => {
206
- const result = await run('git', args, { cwd, timeoutMs: FETCH_MS });
207
- return result.code === 0 ? { ok: true, stdout: result.stdout } : { ok: false, output: outputOf(result, 500) };
208
- };
209
- }
210
- // Pins still to install after a further change on origin: each asset keeps the version it had
211
- // before the first change and takes the newest one; an asset back where it started drops out.
212
- export function mergeChanges(earlier, later) {
213
- const byKey = new Map(earlier.map((c) => [keyOf(c), c]));
214
- for (const c of later) {
215
- const first = byKey.get(keyOf(c));
216
- byKey.set(keyOf(c), first ? { ...c, from: first.from } : c);
217
- }
218
- return [...byKey.values()].filter((c) => c.from !== c.to).sort(byName);
219
- }
220
- // The pins that differ between two .atk-lock.json texts, by asset type and name.
221
- export function pinChanges(before, after) {
222
- const pins = (text) => new Map(lockSchema
223
- .parse(JSON.parse(text))
224
- .assets.map((a) => [
225
- keyOf({ name: a.name, type: a.type ?? null }),
226
- { name: a.name, type: a.type ?? null, version: a.version ?? null },
227
- ]));
228
- const was = pins(before);
229
- const now = pins(after);
230
- const changes = [];
231
- for (const [key, { name, type, version }] of now) {
232
- const old = was.get(key);
233
- if (!old)
234
- changes.push({ from: null, name, to: version, type });
235
- else if (old.version !== version)
236
- changes.push({ from: old.version, name, to: version, type });
237
- }
238
- for (const [key, { name, type, version }] of was)
239
- if (!now.has(key))
240
- changes.push({ from: version, name, to: null, type });
241
- return changes.sort(byName);
242
- }
243
- function byName(a, b) {
244
- return a.name.localeCompare(b.name) || (a.type ?? '').localeCompare(b.type ?? '');
245
- }
246
- function keyOf({ name, type }) {
247
- return `${type ?? ''}:${name}`;
248
- }
249
- //# sourceMappingURL=checkout-sync.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"checkout-sync.js","sourceRoot":"","sources":["../src/checkout-sync.ts"],"names":[],"mappings":"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"}
@@ -1,66 +0,0 @@
1
- import { run } from "./run.js";
2
- const NOT_FOUND = 3;
3
- // Win32 ERROR_NOT_FOUND: CredRead's "no such credential". Any other failure is a broken read.
4
- const ERROR_NOT_FOUND = 1168;
5
- // Writes the user name, a newline, then the password.
6
- const CRED_READ = `
7
- $ErrorActionPreference = 'Stop'
8
- try {
9
- Add-Type -Namespace AtkConduct -Name Cred -MemberDefinition @'
10
- [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
11
- public static extern bool CredRead(string target, int type, int flags, out System.IntPtr cred);
12
- [DllImport("advapi32.dll")]
13
- public static extern void CredFree(System.IntPtr cred);
14
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
15
- public struct CREDENTIAL { public int Flags; public int Type; public string TargetName; public string Comment;
16
- public long LastWritten; public int CredentialBlobSize; public System.IntPtr CredentialBlob; public int Persist;
17
- public int AttributeCount; public System.IntPtr Attributes; public string TargetAlias; public string UserName; }
18
- '@
19
- $p = [IntPtr]::Zero
20
- if (-not [AtkConduct.Cred]::CredRead($env:ATK_CONDUCT_CRED_TARGET, 1, 0, [ref]$p)) {
21
- $code = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
22
- if ($code -eq ${ERROR_NOT_FOUND}) { exit ${NOT_FOUND} }
23
- [Console]::Error.WriteLine("CredRead failed with Win32 error $code"); exit 4
24
- }
25
- try {
26
- $c = [Runtime.InteropServices.Marshal]::PtrToStructure($p, [type][AtkConduct.Cred+CREDENTIAL])
27
- [Console]::Out.Write([string]$c.UserName + [char]10)
28
- [Console]::Out.Write([Runtime.InteropServices.Marshal]::PtrToStringUni($c.CredentialBlob, $c.CredentialBlobSize / 2))
29
- } finally { [AtkConduct.Cred]::CredFree($p) }
30
- } catch { [Console]::Error.WriteLine($_.Exception.Message); exit 4 }
31
- `;
32
- export async function credentialSaved(target, env = process.env) {
33
- if (process.platform !== 'win32')
34
- return 'missing';
35
- const result = await run('cmdkey', [`/list:${target}`], { env, timeoutMs: 15_000 });
36
- if (result.code !== 0)
37
- return 'unknown';
38
- if (/\*\s*NONE\s*\*/.test(result.stdout))
39
- return 'missing';
40
- return /^\s*Target:/m.test(result.stdout) ? 'saved' : 'unknown';
41
- }
42
- // Reads the generic credential `target`. Windows only.
43
- export async function readCredential(target, env = process.env) {
44
- if (process.platform !== 'win32')
45
- return { found: false, missing: true, reason: `the ${target} credential is Windows-only` };
46
- const result = await run('powershell.exe', ['-NoProfile', '-NonInteractive', '-EncodedCommand', Buffer.from(CRED_READ, 'utf16le').toString('base64')], { env: { ...env, ATK_CONDUCT_CRED_TARGET: target }, timeoutMs: 30_000 });
47
- if (result.code === 0) {
48
- const newline = result.stdout.indexOf('\n');
49
- const secret = result.stdout.slice(newline + 1).trim();
50
- if (newline >= 0 && secret)
51
- return { credential: { secret, user: result.stdout.slice(0, newline).trim() }, found: true };
52
- }
53
- if (result.code === NOT_FOUND)
54
- return { found: false, missing: true, reason: `no credential ${target}` };
55
- // Never echo stdout here: on a partial failure it could hold the secret.
56
- const line = result.stderr
57
- .split(/\r?\n/)
58
- .map((l) => l.trim())
59
- .find((l) => l && !l.startsWith('#< CLIXML') && !l.startsWith('<Objs'));
60
- return {
61
- found: false,
62
- missing: false,
63
- reason: `the credential ${target} couldn't be read (${result.error ?? line ?? `exit ${result.code}`})`,
64
- };
65
- }
66
- //# sourceMappingURL=credential.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"credential.js","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"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"}
package/build/tab.js DELETED
@@ -1,32 +0,0 @@
1
- import { outputOf, run } from "./run.js";
2
- // Runs wt.exe for a worker's tab or the console's. Not hidden: when the named window doesn't exist
3
- // yet, Windows Terminal creates it with the spawn's SW_HIDE, and the tab runs where nobody sees it
4
- // (ATK-469, ATK-336).
5
- export function openWindowsTerminal(args, cwd, runCommand = run) {
6
- return runCommand('wt.exe', args, { cwd, timeoutMs: 60_000, windowsHide: false });
7
- }
8
- // A tab in the project's Windows Terminal window, attached to the session. wt.exe splits its own
9
- // arguments on `;`, so titles lose it and the command chains with `||`. The tab closes when the
10
- // session stops (a park), and stays open only to show a failed attach (ATK-260).
11
- export function tabArgs(tab) {
12
- const clean = (text) => text.replace(/;/g, ',').replace(/\s+/g, ' ').trim();
13
- return [
14
- '-w',
15
- clean(tab.window),
16
- 'new-tab',
17
- '--title',
18
- clean(tab.title).slice(0, 80),
19
- 'pwsh',
20
- '-Command',
21
- `claude attach ${tab.handle} || Read-Host 'claude attach failed, press Enter to close this tab'`,
22
- ];
23
- }
24
- export function windowsTerminalTab() {
25
- return async (tab) => {
26
- if (process.platform !== 'win32')
27
- return 'tabs need Windows Terminal';
28
- const result = await openWindowsTerminal(tabArgs(tab), tab.cwd);
29
- return result.code === 0 ? null : outputOf(result, 500);
30
- };
31
- }
32
- //# sourceMappingURL=tab.js.map
package/build/tab.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"tab.js","sourceRoot":"","sources":["../src/tab.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAkB,MAAM,UAAU,CAAC;AAazD,mGAAmG;AACnG,mGAAmG;AACnG,sBAAsB;AACtB,MAAM,UAAU,mBAAmB,CAAC,IAAuB,EAAE,GAAW,EAAE,UAAU,GAAG,GAAG;IACxF,OAAO,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;AACpF,CAAC;AAED,iGAAiG;AACjG,gGAAgG;AAChG,iFAAiF;AACjF,MAAM,UAAU,OAAO,CAAC,GAAQ;IAC9B,MAAM,KAAK,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5F,OAAO;QACL,IAAI;QACJ,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;QACjB,SAAS;QACT,SAAS;QACT,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM;QACN,UAAU;QACV,iBAAiB,GAAG,CAAC,MAAM,qEAAqE;KACjG,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE;QACnB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;YAAE,OAAO,4BAA4B,CAAC;QACtE,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QAChE,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1D,CAAC,CAAC;AACJ,CAAC"}