@idea1/cli 1.7.7 → 1.8.1

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 (195) hide show
  1. package/README.md +126 -60
  2. package/dist/cli/named-lists.d.ts.map +1 -1
  3. package/dist/cli/named-lists.js +5 -0
  4. package/dist/cli/named-lists.js.map +1 -1
  5. package/dist/commands/approve-pr.d.ts.map +1 -1
  6. package/dist/commands/approve-pr.js +94 -8
  7. package/dist/commands/approve-pr.js.map +1 -1
  8. package/dist/commands/attach-project-item.d.ts.map +1 -1
  9. package/dist/commands/attach-project-item.js +28 -41
  10. package/dist/commands/attach-project-item.js.map +1 -1
  11. package/dist/commands/close-worktree.d.ts.map +1 -1
  12. package/dist/commands/close-worktree.js +50 -84
  13. package/dist/commands/close-worktree.js.map +1 -1
  14. package/dist/commands/create-worktree.d.ts.map +1 -1
  15. package/dist/commands/create-worktree.js +1 -4
  16. package/dist/commands/create-worktree.js.map +1 -1
  17. package/dist/commands/get-project-item-url.d.ts.map +1 -1
  18. package/dist/commands/get-project-item-url.js +3 -1
  19. package/dist/commands/get-project-item-url.js.map +1 -1
  20. package/dist/commands/help.js +13 -13
  21. package/dist/commands/help.js.map +1 -1
  22. package/dist/commands/index.d.ts +1 -2
  23. package/dist/commands/index.d.ts.map +1 -1
  24. package/dist/commands/index.js +1 -3
  25. package/dist/commands/index.js.map +1 -1
  26. package/dist/commands/join-project-item.d.ts.map +1 -1
  27. package/dist/commands/join-project-item.js +18 -60
  28. package/dist/commands/join-project-item.js.map +1 -1
  29. package/dist/commands/next-workflow-step.d.ts.map +1 -1
  30. package/dist/commands/next-workflow-step.js +16 -22
  31. package/dist/commands/next-workflow-step.js.map +1 -1
  32. package/dist/commands/push.d.ts.map +1 -1
  33. package/dist/commands/push.js +4 -3
  34. package/dist/commands/push.js.map +1 -1
  35. package/dist/commands/ready-for-approval.d.ts.map +1 -1
  36. package/dist/commands/ready-for-approval.js +94 -8
  37. package/dist/commands/ready-for-approval.js.map +1 -1
  38. package/dist/commands/release.d.ts.map +1 -1
  39. package/dist/commands/release.js +4 -15
  40. package/dist/commands/release.js.map +1 -1
  41. package/dist/commands/start-agent-implementation.d.ts.map +1 -1
  42. package/dist/commands/start-agent-implementation.js +10 -13
  43. package/dist/commands/start-agent-implementation.js.map +1 -1
  44. package/dist/commands/start-dev-implementation.d.ts.map +1 -1
  45. package/dist/commands/start-dev-implementation.js +7 -8
  46. package/dist/commands/start-dev-implementation.js.map +1 -1
  47. package/dist/commands/start.d.ts.map +1 -1
  48. package/dist/commands/start.js +21 -15
  49. package/dist/commands/start.js.map +1 -1
  50. package/dist/commands/update-branch.d.ts.map +1 -1
  51. package/dist/commands/update-branch.js +28 -75
  52. package/dist/commands/update-branch.js.map +1 -1
  53. package/dist/interactive.d.ts.map +1 -1
  54. package/dist/interactive.js +47 -34
  55. package/dist/interactive.js.map +1 -1
  56. package/dist/lib/claude-options.d.ts +11 -10
  57. package/dist/lib/claude-options.d.ts.map +1 -1
  58. package/dist/lib/claude-options.js +38 -39
  59. package/dist/lib/claude-options.js.map +1 -1
  60. package/dist/lib/settings.d.ts +23 -27
  61. package/dist/lib/settings.d.ts.map +1 -1
  62. package/dist/lib/settings.js +35 -50
  63. package/dist/lib/settings.js.map +1 -1
  64. package/dist/prompts/platform-prompts.d.ts +30 -0
  65. package/dist/prompts/platform-prompts.d.ts.map +1 -0
  66. package/dist/prompts/platform-prompts.js +38 -0
  67. package/dist/prompts/platform-prompts.js.map +1 -0
  68. package/dist/prompts/project-item-prompts.d.ts +44 -0
  69. package/dist/prompts/project-item-prompts.d.ts.map +1 -0
  70. package/dist/prompts/project-item-prompts.js +41 -0
  71. package/dist/prompts/project-item-prompts.js.map +1 -0
  72. package/dist/services/claude.d.ts +27 -33
  73. package/dist/services/claude.d.ts.map +1 -1
  74. package/dist/services/claude.js +40 -140
  75. package/dist/services/claude.js.map +1 -1
  76. package/dist/services/git.d.ts +24 -121
  77. package/dist/services/git.d.ts.map +1 -1
  78. package/dist/services/git.js +73 -470
  79. package/dist/services/git.js.map +1 -1
  80. package/dist/services/github.d.ts +20 -4
  81. package/dist/services/github.d.ts.map +1 -1
  82. package/dist/services/github.js +77 -6
  83. package/dist/services/github.js.map +1 -1
  84. package/dist/services/platform.d.ts +75 -0
  85. package/dist/services/platform.d.ts.map +1 -0
  86. package/dist/services/platform.js +237 -0
  87. package/dist/services/platform.js.map +1 -0
  88. package/dist/services/setup.d.ts +1 -1
  89. package/dist/services/setup.js +1 -1
  90. package/dist/services/template-renderer.d.ts +10 -0
  91. package/dist/services/template-renderer.d.ts.map +1 -0
  92. package/dist/services/template-renderer.js +20 -0
  93. package/dist/services/template-renderer.js.map +1 -0
  94. package/dist/services/worktree.d.ts +17 -16
  95. package/dist/services/worktree.d.ts.map +1 -1
  96. package/dist/services/worktree.js +41 -65
  97. package/dist/services/worktree.js.map +1 -1
  98. package/dist/types/index.d.ts +14 -58
  99. package/dist/types/index.d.ts.map +1 -1
  100. package/dist/version.d.ts +1 -1
  101. package/dist/version.js +1 -1
  102. package/dist/workflow/data/project-item.d.ts +21 -0
  103. package/dist/workflow/data/project-item.d.ts.map +1 -0
  104. package/dist/workflow/data/project-item.js +2 -0
  105. package/dist/workflow/data/project-item.js.map +1 -0
  106. package/dist/workflow/data/workflow-context.d.ts +46 -0
  107. package/dist/workflow/data/workflow-context.d.ts.map +1 -0
  108. package/dist/workflow/data/workflow-context.js +14 -0
  109. package/dist/workflow/data/workflow-context.js.map +1 -0
  110. package/dist/{lib → workflow/data}/workflow-states.d.ts +1 -1
  111. package/dist/workflow/data/workflow-states.d.ts.map +1 -0
  112. package/dist/{lib → workflow/data}/workflow-states.generated.d.ts +1 -1
  113. package/dist/workflow/data/workflow-states.generated.d.ts.map +1 -0
  114. package/dist/{lib → workflow/data}/workflow-states.generated.js +1 -1
  115. package/dist/workflow/data/workflow-states.generated.js.map +1 -0
  116. package/dist/{lib → workflow/data}/workflow-states.js +1 -1
  117. package/dist/workflow/data/workflow-states.js.map +1 -0
  118. package/dist/workflow/engine/approval-flow.d.ts +53 -0
  119. package/dist/workflow/engine/approval-flow.d.ts.map +1 -0
  120. package/dist/workflow/engine/approval-flow.js +111 -0
  121. package/dist/workflow/engine/approval-flow.js.map +1 -0
  122. package/dist/{services → workflow/engine}/branch-setup.d.ts +2 -1
  123. package/dist/workflow/engine/branch-setup.d.ts.map +1 -0
  124. package/dist/{services → workflow/engine}/branch-setup.js +6 -5
  125. package/dist/workflow/engine/branch-setup.js.map +1 -0
  126. package/dist/workflow/engine/handlers/agent-implementation.d.ts +10 -0
  127. package/dist/workflow/engine/handlers/agent-implementation.d.ts.map +1 -0
  128. package/dist/workflow/engine/handlers/agent-implementation.js +42 -0
  129. package/dist/workflow/engine/handlers/agent-implementation.js.map +1 -0
  130. package/dist/{services/workflow-handlers → workflow/engine/handlers}/approve-pr.d.ts +7 -4
  131. package/dist/workflow/engine/handlers/approve-pr.d.ts.map +1 -0
  132. package/dist/workflow/engine/handlers/approve-pr.js +63 -0
  133. package/dist/workflow/engine/handlers/approve-pr.js.map +1 -0
  134. package/dist/{services/workflow-handlers → workflow/engine/handlers}/dev-implementation.d.ts +3 -2
  135. package/dist/workflow/engine/handlers/dev-implementation.d.ts.map +1 -0
  136. package/dist/workflow/engine/handlers/dev-implementation.js +36 -0
  137. package/dist/workflow/engine/handlers/dev-implementation.js.map +1 -0
  138. package/dist/workflow/engine/handlers/index.d.ts +21 -0
  139. package/dist/workflow/engine/handlers/index.d.ts.map +1 -0
  140. package/dist/{services/workflow-handlers → workflow/engine/handlers}/index.js +10 -6
  141. package/dist/workflow/engine/handlers/index.js.map +1 -0
  142. package/dist/workflow/engine/handlers/ready-for-approval.d.ts +11 -0
  143. package/dist/workflow/engine/handlers/ready-for-approval.d.ts.map +1 -0
  144. package/dist/workflow/engine/handlers/ready-for-approval.js +56 -0
  145. package/dist/workflow/engine/handlers/ready-for-approval.js.map +1 -0
  146. package/dist/{services → workflow/engine}/release-flow.d.ts +19 -10
  147. package/dist/workflow/engine/release-flow.d.ts.map +1 -0
  148. package/dist/{services → workflow/engine}/release-flow.js +33 -16
  149. package/dist/workflow/engine/release-flow.js.map +1 -0
  150. package/dist/workflow/engine/workflow-engine.d.ts +162 -0
  151. package/dist/workflow/engine/workflow-engine.d.ts.map +1 -0
  152. package/dist/workflow/engine/workflow-engine.js +405 -0
  153. package/dist/workflow/engine/workflow-engine.js.map +1 -0
  154. package/package.json +2 -1
  155. package/dist/commands/integrate.d.ts +0 -13
  156. package/dist/commands/integrate.d.ts.map +0 -1
  157. package/dist/commands/integrate.js +0 -128
  158. package/dist/commands/integrate.js.map +0 -1
  159. package/dist/lib/workflow-states.d.ts.map +0 -1
  160. package/dist/lib/workflow-states.generated.d.ts.map +0 -1
  161. package/dist/lib/workflow-states.generated.js.map +0 -1
  162. package/dist/lib/workflow-states.js.map +0 -1
  163. package/dist/services/branch-setup.d.ts.map +0 -1
  164. package/dist/services/branch-setup.js.map +0 -1
  165. package/dist/services/context.d.ts +0 -26
  166. package/dist/services/context.d.ts.map +0 -1
  167. package/dist/services/context.js +0 -304
  168. package/dist/services/context.js.map +0 -1
  169. package/dist/services/release-flow.d.ts.map +0 -1
  170. package/dist/services/release-flow.js.map +0 -1
  171. package/dist/services/workflow-engine.d.ts +0 -67
  172. package/dist/services/workflow-engine.d.ts.map +0 -1
  173. package/dist/services/workflow-engine.js +0 -371
  174. package/dist/services/workflow-engine.js.map +0 -1
  175. package/dist/services/workflow-handlers/agent-implementation.d.ts +0 -9
  176. package/dist/services/workflow-handlers/agent-implementation.d.ts.map +0 -1
  177. package/dist/services/workflow-handlers/agent-implementation.js +0 -38
  178. package/dist/services/workflow-handlers/agent-implementation.js.map +0 -1
  179. package/dist/services/workflow-handlers/approve-pr.d.ts.map +0 -1
  180. package/dist/services/workflow-handlers/approve-pr.js +0 -122
  181. package/dist/services/workflow-handlers/approve-pr.js.map +0 -1
  182. package/dist/services/workflow-handlers/dev-implementation.d.ts.map +0 -1
  183. package/dist/services/workflow-handlers/dev-implementation.js +0 -34
  184. package/dist/services/workflow-handlers/dev-implementation.js.map +0 -1
  185. package/dist/services/workflow-handlers/index.d.ts +0 -18
  186. package/dist/services/workflow-handlers/index.d.ts.map +0 -1
  187. package/dist/services/workflow-handlers/index.js.map +0 -1
  188. package/dist/services/workflow-handlers/ready-for-approval.d.ts +0 -10
  189. package/dist/services/workflow-handlers/ready-for-approval.d.ts.map +0 -1
  190. package/dist/services/workflow-handlers/ready-for-approval.js +0 -59
  191. package/dist/services/workflow-handlers/ready-for-approval.js.map +0 -1
  192. package/dist/services/workflow.d.ts +0 -14
  193. package/dist/services/workflow.d.ts.map +0 -1
  194. package/dist/services/workflow.js +0 -37
  195. package/dist/services/workflow.js.map +0 -1
package/README.md CHANGED
@@ -15,7 +15,7 @@ npm install -g @idea1/cli
15
15
  Run commands directly from the command line:
16
16
 
17
17
  ```bash
18
- # Put a project item under workflow management (branch + metadata, no code changes)
18
+ # Put a project item under workflow management (branch recorded on idea1.ai, no code changes)
19
19
  idea1 start --url https://app.idea1.ai/project/items/590
20
20
 
21
21
  # Advance the item to its next workflow state (runs that state's automation)
@@ -29,8 +29,10 @@ idea1 start-dev-implementation # or: idea1 dev
29
29
  idea1 ready-for-approval # or: idea1 rfa
30
30
  idea1 approve-pr # or: idea1 approve
31
31
 
32
- # Carry an integration branch into working/release (opens the PR, assigns its approver; the assignee merges it)
33
- idea1 integrate # or: idea1 int
32
+ # The same two commands on a branch with no project item, e.g. an integration branch:
33
+ # open its PR into working/release and name the approver, then (as the approver) merge it
34
+ idea1 ready-for-approval --assignee octocat
35
+ idea1 approve-pr --branch working/integration/<name>-main
34
36
 
35
37
  # Release the release branch to production (opens the release PR into main, assigned to you, and merges it once the checks pass)
36
38
  idea1 release # or: idea1 r
@@ -58,20 +60,22 @@ The state names and their order are defined once, in `shared-config/workflow-sta
58
60
 
59
61
  ### How the workflow engine works
60
62
 
61
- An item **under workflow management** has exactly one branch on origin that carries `.idea1/<branch>.json` with the item's URL and current `workflowState`. That committed file is the durable, shared record: the idea1.ai web client writes the same file when a state is advanced from the browser, and every CLI command first syncs the branch's state from origin (adopting the metadata into local git config and fast-forwarding a local checkout when it is behind) — so the CLI and the web client never disagree.
63
+ An item **under workflow management** has a *workflow context* on idea1.ai: its workflow status together with the one branch on origin that carries its work — the repository and branch name, the PR target (base) branch, the dev workflow type and any stack or integration branch. An item with no context is outside workflow management and has no status. The CLI reads and records the context through the platform's MCP tools (`get_workflow_context_for_branch`, `get_workflow_context_for_item`, `upsert_workflow_context`) and records state changes with `set_item_workflow_status`; the web client works on the same context, so the two always agree, and any clone resolves a branch to its item from the platform. Locally, each clone remembers the item URL a branch was last resolved to in its git config, so ordinary branches are recognized as unmanaged instantly.
62
64
 
63
- A transition is "enter state X". Entering a state runs that state's automation (a *handler*), then records the new state in the branch metadata, in local git config and on the idea1.ai item. Most states have no automation; the implementation states do:
65
+ The branch itself carries the work. A branch's PR is therefore gated on a CI/CD run of exactly what merges, and `approve-pr` merges that run's head. When a branch is deleted on GitHub the context keeps its name and records whether the work merged; a context whose branch is gone without merging gets a new branch the next time the item enters a pre-merge state, while merged work stays merged. Branches put under workflow before the platform kept contexts carry a legacy `.idea1/<branch>.json` file, which the CLI removes from the branch before the approval gate.
66
+
67
+ A transition is "enter state X". Entering a state runs that state's automation (a *handler*), then records the new state on the item's context. An item outside workflow management is put under it by the transition itself - the branch is created on origin and the context recorded before any automation runs - so entering the first state is what starts an item. Handlers are idempotent, so a transition replayed after the item was moved back does not repeat work that is already done. Most states have no automation; the implementation states do:
64
68
 
65
69
  | Entering | Automation |
66
70
  |----------|-----------|
67
71
  | Build Spec in Progress … Ready for Agent Implementation | none — status only |
68
72
  | **Agent Implementation** | ensures the branch is checked out locally (worktree or main repo), then **launches Claude** to implement the item. This is the only transition that starts code-writing automation |
69
73
  | **Dev Implementation** | commits and pushes the agent's work, creates the PR, removes the worktree if `removeWorktreeAtState` says so |
70
- | **Needs Approval for Release** | requires the PR, sets its assignee (required — the approver of record) and any requested reviewers, removes the worktree if configured |
71
- | **Approved and Merged** | verifies you are the assignee, removes the metadata file, waits for the CI/CD suite, merges the PR — the merge is the approval — then deletes the branch and worktree |
74
+ | **Needs Approval for Release** | requires the PR, sets its assignee (required — the approver of record) and any requested reviewers, removes a legacy workflow context file if the branch still carries one (its final commit), and removes the worktree if configured. From here on the branch stays as it is |
75
+ | **Approved and Merged** | verifies you are the assignee, waits for the CI/CD suite, merges the PR as it stands — the merge is the approval — then deletes the branch and worktree |
72
76
  | Released | none — normally set by GitHub automation when the work merges to `main` |
73
77
 
74
- `start` begins state management, `next` advances one state, and `start-agent-implementation` jumps to Agent Implementation — all three reduce to the same engine, so branches and items always end up consistent with the state they are in.
78
+ `start` begins state management, `next` advances one state, and `start-agent-implementation` jumps to Agent Implementation — all three reduce to the same engine, so branches and items always end up consistent with the state they are in. The engine and its layers are described in `src/workflow/README.md`.
75
79
 
76
80
  ### Who approves what
77
81
 
@@ -79,7 +83,7 @@ A change reaches production through two merges, and **each merge is its approval
79
83
 
80
84
  **Into `working/release`** — the PR's **assignee** (required) is its approver. They review the code and approve it by running `idea1 approve-pr`, which waits for the full CI/CD suite and then **merges** the PR. That is not the GitHub "Approve" button, which only leaves a review behind and merges nothing. A red or unfinished suite stops the merge, and there is no override at this stage. `approve-pr` checks that the person merging is the assignee; anyone else has to confirm explicitly, and the evidence report lists that merge as an exception. Requested reviewers are optional and record nothing. GitHub records the approval as `merged_by`, with its timestamp and merge commit.
81
85
 
82
- **Integration branches into `working/release`** — work items for an integration PR into `working/integration/<name>-main` and are approved there exactly as above. The integration branch itself enters `working/release` through `idea1 integrate`: it opens the PR with the approval chain of the work items it carries and assigns its approver; the assignee merges it (`idea1 integrate --pr-mode merge`) once the suite passes — the same sequence as a release, including the recorded admin override.
86
+ **Any other branch into `working/release`** — a branch with no project item takes the same gate. `idea1 ready-for-approval` opens its PR (with the approval chain of what the branch carries as the body) and names its assignee; `idea1 approve-pr` merges it once the suite passes, with the same no-override rule, and then deletes the branch. Only the idea1.ai status writes are absent. Integration branches work this way: work items PR into `working/integration/<name>-main` and are approved there exactly as above, then the integration branch itself is carried into `working/release` with these two commands — its PR body lists every work-item PR and who approved it, and `approve-pr` refuses while any PR still targets the integration branch.
83
87
 
84
88
  **Into `main`** — `idea1 release` opens the release PR **assigned to whoever ran it**: the releaser is the approver, and their merge is the recorded approval. No review is required — every change in the release was already approved above, and the release PR body lists each contained PR with who approved it. What this stage gates is the build: the required CI/CD checks must pass first. In the default `create` mode the releaser merges the PR in GitHub once the checks are green; in `merge` mode the CLI waits for every check with `gh` and merges here. An emergency admin override past a red check needs an explicit confirmation and a stated reason, and is recorded as a comment on the PR before the merge.
85
89
 
@@ -87,7 +91,7 @@ This is the change-management control DataFabrIQ is audited on; see `infrastruct
87
91
 
88
92
  ### start
89
93
 
90
- Put a project item under workflow management. An item that has never been started enters **Build Spec in Progress**; an item that already has a state keeps it. The branch is created on origin from the base branch with the metadata file as its first commit — nothing is checked out, no code is written and Claude is not launched. Idempotent: running it again for a managed item just reports the branch and state.
94
+ Put a project item under workflow management. An item yet to be started enters **Build Spec in Progress**; an item that already has a state keeps it. The branch is created on origin at the base branch's tip and recorded in the item's workflow context on idea1.ai; the working tree and the code stay as they are, and Claude stays closed. Idempotent: running it again for a managed item just reports the branch and state.
91
95
 
92
96
  ```bash
93
97
  idea1 start --url <url> [options]
@@ -96,8 +100,9 @@ idea1 s --url <url>
96
100
  ```
97
101
 
98
102
  **Options:**
99
- - `-u, --url <url>` - The Idea1.ai project item URL. Leave blank to create a new item (you'll be prompted for a `--title`).
103
+ - `-u, --url <url>` - The Idea1.ai project item URL. Leave blank to create a new item (you'll be prompted for a `--title` and a `--project`).
100
104
  - `-t, --title <title>` - Title for the new project item (only when no URL is given).
105
+ - `-P, --project <name>` - The Project to create the new item in, chosen from the team's live Projects (only when no URL is given; always asked, never defaulted).
101
106
  - `-p, --source-path <path>` - Path to source directory.
102
107
  - `-n, --branch-name <name>` - Branch name (auto-generated from the item description if not provided).
103
108
  - `-b, --base-branch <branch>` - Base branch / PR target (default: `working/release`).
@@ -107,7 +112,7 @@ idea1 s --url <url>
107
112
 
108
113
  Advance a project item to its next workflow state and run that state's automation. On the item's branch no arguments are needed; from anywhere else pass the item URL — the CLI finds the branch on origin (moving into its local checkout when one exists) or, for an item without a branch yet, reads the current state from idea1.ai and creates the branch first.
109
114
 
110
- With `--to <state>` the item advances through every state up to that one in a single run — the same as running `next` once per state, with each state's automation in order. The CLI only moves forward; an item already at or past the requested state is reported as an error.
115
+ With `--to <state>` the item advances through every state up to that one in a single run — the same as running `next` once per state: each state's automation runs and the state is recorded on idea1.ai before the next state is entered. A run that stops part way leaves the item at the last state it entered, and running it again continues from there. The CLI only moves forward; an item already at or past the requested state is left as it is.
111
116
 
112
117
  ```bash
113
118
  idea1 next # on the item's branch
@@ -123,16 +128,16 @@ idea1 n
123
128
  - Any option of the state being entered (for example `--model`/`--effort` for Agent Implementation, `--assignee`/`--reviewers` for Needs Approval for Release). Options that were not supplied are prompted for when that state is reached.
124
129
 
125
130
  **What it does:**
126
- 1. Syncs the branch's workflow state from origin (picking up changes made in the web client).
127
- 2. Puts the item under workflow management if it is not yet (a never-started item enters Build Spec in Progress, which is the whole step).
128
- 3. Runs the automation of every state entered, records the new state on the branch, in git config and on idea1.ai.
131
+ 1. Reads the item's workflow context from idea1.ai (picking up changes made in the web client) and fast-forwards the local checkout to origin when it is behind.
132
+ 2. Puts the item under workflow management when it is outside it yet (an item yet to be started enters Build Spec in Progress, which is the whole step).
133
+ 3. Runs the automation of every state entered and records the new state on idea1.ai.
129
134
  4. Reports "Workflow is complete" at `Released`.
130
135
 
131
136
  The automation is idempotent, so re-running a transition after the item was moved back in the web client does not repeat work that is already done: an existing PR is reused, an already-merged PR is left alone and the item simply moves on.
132
137
 
133
138
  ### start-agent-implementation
134
139
 
135
- Start implementing a project item: put it under workflow management if needed, move it to **Agent Implementation** (through any intermediate states, which have no automation), set up the working environment and launch Claude Code with the implementation prompt (or a prompt you supply — see `--entry-point-prompt`). This is the command behind "Send for Implementation" in the web client; `start-project-item` remains an alias so existing team command templates keep working.
140
+ Start implementing a project item: put it under workflow management if needed, move it to **Agent Implementation** (through any intermediate states, which have no automation), set up the working environment and launch Claude Code with the implementation prompt — the repository's `prompts.agentImplementation` setting (see [Prompts](#prompts)), the built-in default, or a prompt you supply with `--entry-point-prompt`. This is the command behind "Send for Implementation" in the web client; `start-project-item` remains an alias so existing team command templates keep working.
136
141
 
137
142
  ```bash
138
143
  idea1 start-agent-implementation --url <url> [options]
@@ -147,8 +152,8 @@ idea1 implement --url <url> --entry-point-prompt "Read the spec in docs/spec.md
147
152
  - `-m, --model <model>` - Claude model for the implementation session (default: `opus`). Valid values: `fable`, `opus`, `sonnet`, `haiku`
148
153
  - `-e, --effort <level>` - Claude effort level (default: `high`). Valid values: `low`, `medium`, `high`, `xhigh`, `max`
149
154
  - `-im, --claude-entry-point <mode>` - How Claude is invoked once the environment is ready (default: `launch`). Valid values: `launch` (start a new Claude session), `inline` (output a structured prompt for an already-running Claude session), `none` (do not invoke Claude)
150
- - `-udp, --use-default-prompt <yes|no>` - Whether to launch Claude with the default implementation prompt (default: `yes`). Answering `no` asks for the prompt to use instead.
151
- - `-epp, --entry-point-prompt <prompt>` - The prompt to launch Claude with, replacing the default implementation prompt. Supplying it skips the "Use default prompt?" question.
155
+ - `-udp, --use-default-prompt <yes|no>` - Whether to launch Claude with the repository's implementation prompt, or the built-in one when the repository sets none (default: `yes`). Answering `no` asks for the prompt to use instead.
156
+ - `-epp, --entry-point-prompt <prompt>` - The prompt to launch Claude with, replacing the implementation prompt. Supplying it skips the "Use default prompt?" question. It is a Handlebars template like the repository's prompt, so it can use the same [variables](#prompts).
152
157
 
153
158
  An item already in Agent Implementation is not transitioned again: the working environment is set up (or reused) and Claude is launched.
154
159
 
@@ -178,12 +183,11 @@ idea1 j --branch-name <branch>
178
183
  - `--pull-request-url <url>` - A GitHub PR URL; its head branch is joined.
179
184
  - `-p, --source-path <path>` - Path to source directory.
180
185
  - `-iso, --isolation <mode>` - Where to work on the branch (default: `worktree`). See [Isolation mode](#isolation-mode).
181
- - `-pm, --permission-mode <mode>`, `-m, --model <model>`, `-e, --effort <level>` - Claude session settings recorded for the environment (defaults: `plan`, `opus`, `high`).
182
186
 
183
187
  **What it does:**
184
- 1. Resolves the branch from the URL (or the URL from the branch) using the committed branch metadata.
188
+ 1. Resolves the branch from the URL (or the URL from the branch) through the item's workflow context on idea1.ai.
185
189
  2. Reuses the checkout that already holds the branch, or sets one up — a git worktree, or the branch checked out in the main repository (creating a local tracking branch if it only exists on origin).
186
- 3. Syncs the workflow state from the metadata committed on origin into local git config, defaulting a legacy branch with no recorded state to `Agent Implementation`, and pushes any recovered metadata back to origin.
190
+ 3. Reports the item the branch implements and its state. A branch outside workflow management is joined as plain git work; `attach-project-item` puts it under workflow.
187
191
  4. Runs any setup hooks defined in `.idea1/settings.json` (newly created worktrees only).
188
192
 
189
193
  If a project item URL is supplied but no branch exists for it yet, `join-project-item` puts the item under workflow management first (as `start` does) and then sets up the environment.
@@ -206,14 +210,14 @@ idea1 a --url <url>
206
210
  - `-w, --workflow-type <type>` - Development workflow type: `independent` or `integration`. You also choose any stack branch and (for integration) the integration branch.
207
211
 
208
212
  **What it does:**
209
- 1. Verifies the current branch is not already attached to a project item (errors if it is — use `join-project-item` to resume instead).
210
- 2. Creates the project item if no URL was supplied, and reads its current workflow state from idea1.ai.
211
- 3. Records the per-branch metadata (project item URL, base branch, workflow state, dev workflow type, stack/integration branch) in git config and the committed `.idea1/<branch>.json` file, and pushes the branch.
212
- 4. Records the branch on the idea1.ai item. If the item is already at `Dev Implementation` or later, makes sure a PR into the base branch exists.
213
+ 1. Verifies the current branch is free to implement the item (a branch that already implements one is resumed with `join-project-item`).
214
+ 2. Creates the project item if no URL was supplied.
215
+ 3. Records the branch in the item's workflow context on idea1.ai (base branch, dev workflow type, stack/integration branch) in a single call, which puts an item outside workflow management under it at `Build Spec in Progress` and leaves an item that already has a state at that state. The branch is pushed to origin beforehand and stays as it is.
216
+ 4. If the item is already at `Dev Implementation` or later, makes sure a PR into the base branch exists.
213
217
 
214
218
  ### start-dev-implementation
215
219
 
216
- Enter **Dev Implementation** from Agent Implementation — the same step `next` takes from that state.
220
+ Advance the item to **Dev Implementation** — the same as `next --to "Dev Implementation"`. From Agent Implementation that is one step; from an earlier state every state in between is entered first, each with its own automation. An item already at or past Dev Implementation is left as it is.
217
221
 
218
222
  ```bash
219
223
  idea1 start-dev-implementation [options]
@@ -224,68 +228,68 @@ idea1 dev [options]
224
228
  - `-p, --source-path <path>` - Path to worktree directory
225
229
 
226
230
  **What it does:**
227
- 1. Validates the current state is "Agent Implementation" (after syncing from origin)
231
+ 1. Enters every state before Dev Implementation the item has yet to reach (after syncing from origin)
228
232
  2. Commits and pushes all changes in the branch
229
233
  3. Creates a PR of the branch into its base branch
230
- 4. Records "Dev Implementation" in the branch metadata, git config and on Idea1.ai
234
+ 4. Records "Dev Implementation" on Idea1.ai
231
235
  5. If in a worktree and `removeWorktreeAtState` is `Dev Implementation`, removes the worktree. The main repo stays on its current branch; use `join-project-item` to work on the item in the main repo or a new worktree.
232
236
 
233
237
  ### ready-for-approval
234
238
 
235
- Enter **Needs Approval for Release** from Dev Implementation — the same step `next` takes from that state. Its job is to name the **assignee**, who will approve the change by merging it.
239
+ On a project item's branch, advance the item to **Needs Approval for Release** — the same as `next --to "Needs Approval for Release"`: from an earlier state, every state in between is entered first, each with its own automation (PR creation on the way into Dev Implementation, for one), and an item already at or past it is left as it is. On any other branch (an integration branch, a branch with no project item), open the branch's PR into the base branch when it has none. Either way its job is to name the **assignee**, who will approve the change by merging it.
236
240
 
237
241
  ```bash
238
242
  idea1 ready-for-approval [options]
239
243
  idea1 rfa --assignee octocat
244
+ idea1 rfa --assignee octocat # on working/integration/<name>-main: opens the PR into working/release
245
+ idea1 rfa --assignee octocat -b working/release # a branch with no project item, naming the PR target
240
246
  ```
241
247
 
242
248
  **Options:**
243
249
  - `-a, --assignee <username>` - **Required.** Who approves the PR by merging it (prompted from the repository's assignable users when omitted)
244
250
  - `-r, --reviewers <user1,user2>` - Who to request a review from (multi-select when omitted). Optional, and separate from approval — the assignee is the approver
251
+ - `-b, --base-branch <branch>` - Branches with no project item only: the branch the PR targets (default: the open PR's base, else `baseBranch`, then `working/release`)
252
+ - `--title <title>` - Branches with no project item only: PR title when the PR has to be created (default: `Integration <name> <YYYY-MM-DD>` for an integration branch, else the branch name; prompted when omitted)
245
253
 
246
- **What it does:**
247
- 1. Validates the current state is "Dev Implementation" (after syncing from origin)
254
+ **What it does on a project item's branch:**
255
+ 1. Enters every state before Needs Approval for Release the item has yet to reach (after syncing from origin)
248
256
  2. Ensures no uncommitted or unpushed changes in the local checkout
249
257
  3. Requires the PR to exist, then sets the assignee (the transition refuses to proceed without one) and requests any reviewers
250
- 4. Records "Needs Approval for Release" in the branch metadata, git config and on Idea1.ai
251
- 5. If in a worktree and `removeWorktreeAtState` is `Needs Approval for Release` (the default) or earlier, removes the worktree
258
+ 4. Legacy branches only: removes the `.idea1/<branch>.json` workflow context file the branch still carries and pushes — the branch's final commit, so the CI/CD suite runs once more on exactly what will merge and the target branch receives the work alone
259
+ 5. Records "Needs Approval for Release" on Idea1.ai. From here on the branch stays as it is
260
+ 6. If in a worktree and `removeWorktreeAtState` is `Needs Approval for Release` (the default) or earlier, removes the worktree
261
+
262
+ **What it does on a branch with no project item:**
263
+ 1. Requires you to be on the branch with nothing uncommitted, unpushed or behind origin; refuses on the base branch itself and refuses a PR straight into `main` (that is `idea1 release`)
264
+ 2. Reuses the branch's open PR (and its base) when one exists; otherwise creates the PR into the base branch with the approval chain of what the branch carries as its body — every PR merged into the branch with its author and approver, and commits pushed straight to the branch listed as the change under review (they are not an exception: this PR is their stage-1 approval)
265
+ 3. Sets the assignee and requests any reviewers
266
+ 4. Records no workflow status — there is no project item
252
267
 
253
268
  ### approve-pr
254
269
 
255
- Enter **Approved and Merged** from Needs Approval for Release — the same step `next` takes from that state. Run by the PR's **assignee**: it waits for the CI/CD suite and merges the PR, and that merge is the approval of record.
270
+ On a project item's branch, advance the item to **Approved and Merged** — the same as `next --to "Approved and Merged"`: from an earlier state, every state in between is entered first, each with its own automation, and an item already at or past it is left as it is. On any other branch, merge the branch's PR. Run by the PR's **assignee**: it waits for the CI/CD suite and merges the PR, and that merge is the approval of record. There is no admin override at this stage for any branch.
256
271
 
257
272
  ```bash
258
273
  idea1 approve-pr
259
274
  idea1 approve
275
+ idea1 approve-pr --branch working/integration/<name>-main # from anywhere: the branch need not be checked out
260
276
  ```
261
277
 
262
- **What it does:**
263
- 1. Validates the current state is "Needs Approval for Release" (after syncing from origin)
278
+ **Options:**
279
+ - `-b, --branch <branch>` - Branch whose PR to approve (default: the current branch). A project item's branch is approved through the workflow; any other branch through its PR alone
280
+
281
+ **What it does on a project item's branch:**
282
+ 1. Enters every state before Approved and Merged the item has yet to reach (after syncing from origin)
264
283
  2. Verifies the approver: refuses when the PR has no assignee, and when you are not the assignee warns that the merge record will name you instead and requires an explicit confirmation (the evidence report lists such a merge as an exception)
265
- 3. Removes the branch's `.idea1/<branch>.json` so it does not leak into the target branch, waits for the required CI/CD checks on the PR (that push re-runs the suite), then merges the PR. A red or unfinished suite stops the merge — there is no admin override at this stage
266
- 4. Records "Approved and Merged" in git config and on Idea1.ai
284
+ 3. Waits for the required CI/CD checks on the PR — the checks of the branch's tip on origin, which the PR must have picked up first — then merges the PR. A red or unfinished suite stops the merge — there is no admin override at this stage. The branch is merged as it stands. A legacy branch that still carries its workflow context file has the file removed and pushed instead, and the approval is left for a second run once the re-run suite passes
285
+ 4. Records "Approved and Merged" on Idea1.ai
267
286
  5. Switches to the base branch and deletes the feature branch. If still running inside a worktree, removes the worktree instead of switching branches — this always happens, since the base branch can't be checked out in place there
268
287
 
269
- ### integrate
270
-
271
- Carry an integration branch (`working/integration/<name>-main`) into the release branch. This is stage 1 for integration work: the work items were each approved on their own PR into the integration branch; `integrate` opens the integration branch's PR into `working/release`, assigns its approver, and — run by that assignee — merges it once the required CI/CD checks pass. It is not part of the project-item state machine.
272
-
273
- ```bash
274
- idea1 integrate --assignee octocat # on the integration branch: open the PR and assign its approver
275
- idea1 integrate --pr-mode merge # run by the assignee: wait for the checks, then merge
276
- idea1 int
277
- ```
278
-
279
- **Options:**
280
- - `-b, --branch <branch>` - Integration branch to integrate (default: the current branch when it is one, otherwise a pick from the integration branches on origin)
281
- - `-t, --target <branch>` - Branch to integrate into (default: `baseBranch`, then `working/release`)
282
- - `-a, --assignee <username>` - Who approves the integration by merging its PR (prompted when the PR is created and none is given)
283
- - `-pr, --pr-mode <mode>` - `create` (default) opens the PR in the browser to merge there once the checks pass; `merge` waits for every check with `gh` and merges here
284
- - `--title <title>` - PR title (default: `Integration <name> <YYYY-MM-DD>`)
285
-
286
- **What it does:**
287
- 1. Reuses the open PR from the integration branch into the target if one exists; otherwise requires you to be on the integration branch with nothing uncommitted, unpushed or behind origin, and creates the PR assigned to the approver, with the approval chain of the work-item PRs it carries as its body
288
- 2. In `merge` mode, checks that you are the assignee (anyone else must confirm explicitly), waits for the required CI/CD checks and merges. Checks that fail, never start or never finish stop the merge; the admin override takes an explicit confirmation and a required reason, and the exception is recorded as a comment on the PR before anything is merged
288
+ **What it does on a branch with no project item:**
289
+ 1. Finds the branch's PR (run `ready-for-approval` first if there is none) and takes the target branch from it
290
+ 2. Refuses while any open PR still targets the branch — merging would retire the branch and orphan them
291
+ 3. Verifies the approver exactly as above, waits for the required CI/CD checks and merges. A red or unfinished suite stops the merge — no override
292
+ 4. Deletes the branch on origin and locally (removing its worktree, or switching to the base branch first when it is checked out in the main repo). Records no workflow status
289
293
 
290
294
  ### release
291
295
 
@@ -333,6 +337,9 @@ Create `.idea1/settings.json` in your repository root to configure repo-specific
333
337
  "hooks": {
334
338
  "setup-worktree": "dev/workflow/setup-worktree.sh"
335
339
  },
340
+ "prompts": {
341
+ "agentImplementation": "Implement {{projectItemUrl}} on {{branchName}}."
342
+ },
336
343
  "defaults": {
337
344
  "branchPrefix": "working/agent",
338
345
  "baseBranch": "working/release",
@@ -344,6 +351,9 @@ Create `.idea1/settings.json` in your repository root to configure repo-specific
344
351
  **Hooks:**
345
352
  - `setup-worktree` - Script to run after creating a new worktree (e.g., install dependencies)
346
353
 
354
+ **Prompts:**
355
+ - `agentImplementation` - The prompt an Agent Implementation session starts with. See [Prompts](#prompts).
356
+
347
357
  **Defaults:**
348
358
  - `branchPrefix` - Prefix for new branches (default: `working/agent`)
349
359
  - `baseBranch` - Default base branch for branching (default: `working/release`)
@@ -355,8 +365,8 @@ Create `.idea1/settings.json` in your repository root to configure repo-specific
355
365
  `.idea1/settings.local.json` is an optional, git-ignored file with the same shape as
356
366
  `settings.json`. Anything it defines overrides the committed settings for that clone
357
367
  only, which keeps developer-specific preferences out of the shared configuration.
358
- `hooks` and `defaults` are merged section by section, so overriding one value leaves
359
- the rest of the committed settings in place.
368
+ `hooks`, `prompts` and `defaults` are merged section by section, so overriding one value
369
+ leaves the rest of the committed settings in place.
360
370
 
361
371
  ```json
362
372
  {
@@ -366,6 +376,56 @@ the rest of the committed settings in place.
366
376
  }
367
377
  ```
368
378
 
379
+ ### Prompts
380
+
381
+ Every prompt the CLI gives Claude is a [Handlebars](https://handlebarsjs.com/) template
382
+ rendered against a data model, so a repository can replace a prompt with its own template
383
+ using the full Handlebars syntax (`{{#if}}`, `{{#each}}`, `{{else}}`, ...).
384
+
385
+ `prompts.agentImplementation` is the prompt an Agent Implementation session starts with
386
+ (`start-agent-implementation`, or `next` entering Agent Implementation). It is either the
387
+ template itself or the file that holds it, relative to the repository root:
388
+
389
+ ```json
390
+ {
391
+ "prompts": {
392
+ "agentImplementation": "/df-implement-project-item {{projectItemUrl}}"
393
+ }
394
+ }
395
+ ```
396
+
397
+ ```json
398
+ {
399
+ "prompts": {
400
+ "agentImplementation": { "templateFile": ".idea1/prompts/agent-implementation.md" }
401
+ }
402
+ }
403
+ ```
404
+
405
+ Without the setting, the built-in prompt asks Claude to implement the item from its Idea1
406
+ context. `--entry-point-prompt` replaces both for one session and is rendered the same way.
407
+ The settings are read from the main repository, so an override in its
408
+ `settings.local.json` applies in worktrees too.
409
+
410
+ The template renders against the item and its branch:
411
+
412
+ | Variable | Value |
413
+ |----------|-------|
414
+ | `projectItemUrl` | The project item's URL |
415
+ | `workflowStatus` | The item's workflow state (`Agent Implementation`) |
416
+ | `repositoryFullName` | The repository, as `owner/name` |
417
+ | `branchName` | The item's branch |
418
+ | `baseBranch` | The branch the item's PR targets (the integration branch for integration work) |
419
+ | `devWorkflowType` | `independent` or `integration` |
420
+ | `stackBranch` | The branch this one is stacked on, or null |
421
+ | `integrationBranch` | The integration branch, or null for independent work |
422
+ | `pullRequestUrl` | The item's PR, or empty when there is none yet |
423
+ | `workingPath` | The directory the branch is checked out in |
424
+
425
+ Rendering is strict: a template that outputs a variable not in this list fails with an error
426
+ rather than rendering it empty. Test a null variable with `{{#if}}` before outputting it, e.g.
427
+ `{{#if stackBranch}}Stacked on {{stackBranch}}.{{/if}}`.
428
+
369
429
  ### Worktree Removal
370
430
 
371
431
  When work happens in a git worktree, `removeWorktreeAtState` decides which workflow
@@ -395,6 +455,12 @@ Settings include:
395
455
  Branch names are not user settings: they belong to the repository and are read from
396
456
  its `.idea1/settings.json`.
397
457
 
458
+ ## How the CLI uses Claude
459
+
460
+ Every use of Claude Code goes through `src/services/claude.ts`, the only module that spawns `claude`. It always passes `--model` and `--effort`: a caller that states neither gets the documented defaults (`opus`, `high` — the same defaults the implementation session offers), so a run never inherits whatever was last picked in an interactive session.
461
+
462
+ Access to the Idea1 cloud platform — reading a project item's summary (by item or by the branch it implements), recording the item's workflow context, setting its workflow status, creating items, listing Projects, generating a branch name — goes through `src/services/platform.ts`. Its prompts are Handlebars templates in `src/prompts/`, rendered by `src/services/template-renderer.ts` like every other prompt. Today it drives the Idea1 MCP tools through Claude on `sonnet` at `medium` effort (these are simple tool calls, not implementation sessions); that transport is the module's implementation detail and may become direct calls to the platform API. The implementation session launched on entering Agent Implementation is the one place the model and effort are the user's choice (`--model`, `--effort`).
463
+
398
464
  ## Requirements
399
465
 
400
466
  - Node.js 20+
@@ -1 +1 @@
1
- {"version":3,"file":"named-lists.d.ts","sourceRoot":"","sources":["../../src/cli/named-lists.ts"],"names":[],"mappings":"AAqBA;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAYrG"}
1
+ {"version":3,"file":"named-lists.d.ts","sourceRoot":"","sources":["../../src/cli/named-lists.ts"],"names":[],"mappings":"AA0BA;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAYrG"}
@@ -1,4 +1,5 @@
1
1
  import * as github from '../services/github.js';
2
+ import * as platform from '../services/platform.js';
2
3
  /**
3
4
  * Registry of named choice lists. Options reference these by name via
4
5
  * CommandOption.choices, letting multiple options share the same
@@ -8,6 +9,10 @@ const registry = {
8
9
  'github-members': async () => {
9
10
  const logins = await github.listAssignableUsers();
10
11
  return logins.map(login => ({ label: login, value: login }));
12
+ },
13
+ 'idea1-projects': async () => {
14
+ const projects = await platform.listProjects();
15
+ return projects.map(name => ({ label: name, value: name }));
11
16
  }
12
17
  };
13
18
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"named-lists.js","sourceRoot":"","sources":["../../src/cli/named-lists.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAC;AAShD;;;;GAIG;AACH,MAAM,QAAQ,GAAmC;IAC/C,gBAAgB,EAAE,KAAK,IAAI,EAAE;QAC3B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAClD,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY;IACjD,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,GAAG,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,QAAQ,EAAE,CAAC;IACjC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,uBAAuB,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"named-lists.js","sourceRoot":"","sources":["../../src/cli/named-lists.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAC;AAChD,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AASpD;;;;GAIG;AACH,MAAM,QAAQ,GAAmC;IAC/C,gBAAgB,EAAE,KAAK,IAAI,EAAE;QAC3B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAClD,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,gBAAgB,EAAE,KAAK,IAAI,EAAE;QAC3B,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,CAAC;QAC/C,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,CAAC;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY;IACjD,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,GAAG,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,QAAQ,EAAE,CAAC;IACjC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,uBAAuB,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"approve-pr.d.ts","sourceRoot":"","sources":["../../src/commands/approve-pr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAKjD,eAAO,MAAM,gBAAgB,EAAE,OAW9B,CAAC"}
1
+ {"version":3,"file":"approve-pr.d.ts","sourceRoot":"","sources":["../../src/commands/approve-pr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAuFjD,eAAO,MAAM,gBAAgB,EAAE,OAuC9B,CAAC"}
@@ -1,15 +1,101 @@
1
- import { WorkflowStates } from '../lib/workflow-states.js';
2
- import { advanceTo, requireCurrentState, resolveContext } from '../services/workflow-engine.js';
3
- import { approvePrHandler } from '../services/workflow-handlers/approve-pr.js';
1
+ import { logger } from '../lib/logger.js';
2
+ import { readBranchSettings } from '../lib/settings.js';
3
+ import * as git from '../services/git.js';
4
+ import * as github from '../services/github.js';
5
+ import * as worktree from '../services/worktree.js';
6
+ import { WorkflowStates } from '../workflow/data/workflow-states.js';
7
+ import { cleanUpMergedBranch, mergeAsApprover } from '../workflow/engine/approval-flow.js';
8
+ import { confirmApproverIdentity } from '../workflow/engine/release-flow.js';
9
+ import { advanceAsNeededTo, getProjectItemSummaryForBranch, resolveTransition, resolveTransitionIfManaged } from '../workflow/engine/workflow-engine.js';
10
+ import { deferredHandlerOptions } from '../workflow/engine/handlers/index.js';
11
+ /**
12
+ * Stage 1 approval for a branch with no project item: the assignee merges the branch's PR once
13
+ * the required checks pass (no override), then the branch is cleaned up. No workflow status is
14
+ * recorded. The branch need not be checked out - the assignee can approve from anywhere.
15
+ */
16
+ async function approvePrOnBranchWithNoItem(branchName) {
17
+ await github.ensureGitHubCli();
18
+ // Captured before anything moves: cleanup may switch branches or remove a worktree.
19
+ const workingPath = await git.getCheckoutPathForBranch(branchName);
20
+ const isCurrentBranch = (await git.getCurrentBranch()) === branchName;
21
+ const prInfo = await github.getPrInfo(branchName);
22
+ if (!prInfo) {
23
+ throw new Error('No PR found for this branch. Run idea1 ready-for-approval first to open it and name its approver.');
24
+ }
25
+ logger.info(`PR #${prInfo.number} found`);
26
+ const state = prInfo.state.toUpperCase();
27
+ if (state === 'CLOSED') {
28
+ throw new Error(`PR #${prInfo.number} is closed without being merged; there is nothing to approve.`);
29
+ }
30
+ const baseBranch = prInfo.baseRefName ?? await worktree.resolveBaseBranch();
31
+ const releaseTargetBranch = (await readBranchSettings(await git.getRepoRoot())).releaseTargetBranch;
32
+ if (baseBranch === releaseTargetBranch) {
33
+ throw new Error(`PR #${prInfo.number} targets ${releaseTargetBranch}: that is a release, not a change to approve. ` +
34
+ 'Use idea1 release for it (change-management-policy.md clause 2).');
35
+ }
36
+ logger.header(`Approve: ${branchName} -> ${baseBranch}`);
37
+ logger.info('This branch has no project item, so no workflow status is recorded.');
38
+ logger.newline();
39
+ if (state === 'MERGED') {
40
+ logger.dim(`PR #${prInfo.number} is already merged; cleaning up the branch.`);
41
+ }
42
+ else {
43
+ if (isCurrentBranch) {
44
+ await git.ensureBranchUpToDate();
45
+ }
46
+ // Merging retires the branch, which would orphan any PR still targeting it.
47
+ const openPrsInto = await github.listOpenPrsInto(branchName);
48
+ if (openPrsInto.length > 0) {
49
+ const list = openPrsInto.map(pr => ` #${pr.number} ${pr.headRefName} ${pr.title}`).join('\n');
50
+ throw new Error(`${openPrsInto.length} open PR(s) still target ${branchName}; approve or close them before approving this branch:\n${list}`);
51
+ }
52
+ await confirmApproverIdentity(branchName);
53
+ await mergeAsApprover({ branchName, baseBranch, prNumber: prInfo.number });
54
+ }
55
+ await cleanUpMergedBranch({ branchName, baseBranch, workingPath });
56
+ logger.newline();
57
+ logger.success(`PR merged into ${baseBranch} - the merge is the recorded approval`);
58
+ }
59
+ /**
60
+ * The transition for a named branch when it is a project item's branch, else null.
61
+ */
62
+ async function resolveTransitionForNamedBranch(branchName, resolved) {
63
+ const projectItemUrl = (await getProjectItemSummaryForBranch(branchName))?.url ?? null;
64
+ return projectItemUrl ? resolveTransition({ projectItemUrl, options: resolved }) : null;
65
+ }
4
66
  export const approvePrCommand = {
5
67
  name: 'approve-pr',
6
68
  aliases: ['approve'],
7
- description: 'Approve the PR by merging it (the assignee runs this), completing the workflow',
8
- options: approvePrHandler.options,
69
+ description: 'Approve the PR by merging it (the assignee runs this) - on a project item\'s branch (advancing the item through every state before it) or any other branch',
70
+ options: [
71
+ {
72
+ longName: 'branch',
73
+ shortName: 'b',
74
+ description: 'Branch whose PR to approve (default: the current branch)',
75
+ defaultValue: '',
76
+ promptWhenDefaultExists: false
77
+ },
78
+ // On a project item's branch the item may be further back; the states it passes through on the
79
+ // way (the assignee of Needs Approval for Release, for one) ask for their own options.
80
+ ...deferredHandlerOptions([])
81
+ ],
9
82
  async execute(resolved) {
10
- const context = await resolveContext({ options: resolved });
11
- requireCurrentState(context, WorkflowStates.NeedsApprovalForRelease, 'approve-pr');
12
- await advanceTo(context, WorkflowStates.ApprovedAndMerged);
83
+ const requestedBranch = resolved['branch'] || null;
84
+ // A named branch the platform records as an item's is approved through
85
+ // the workflow engine, from wherever the command is run. With no branch named, the current
86
+ // branch is the target, managed or not.
87
+ const transition = requestedBranch
88
+ ? await resolveTransitionForNamedBranch(requestedBranch, resolved)
89
+ : await resolveTransitionIfManaged({ options: resolved });
90
+ if (transition) {
91
+ await advanceAsNeededTo(transition, WorkflowStates.ApprovedAndMerged);
92
+ return;
93
+ }
94
+ const branchName = requestedBranch ?? await git.getCurrentBranch();
95
+ if (branchName === 'HEAD') {
96
+ throw new Error('You are not on a branch (detached HEAD). Check out the branch to approve, or pass --branch <name>.');
97
+ }
98
+ await approvePrOnBranchWithNoItem(branchName);
13
99
  }
14
100
  };
15
101
  //# sourceMappingURL=approve-pr.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"approve-pr.js","sourceRoot":"","sources":["../../src/commands/approve-pr.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChG,OAAO,EAAE,gBAAgB,EAAE,MAAM,6CAA6C,CAAC;AAE/E,MAAM,CAAC,MAAM,gBAAgB,GAAY;IACvC,IAAI,EAAE,YAAY;IAClB,OAAO,EAAE,CAAC,SAAS,CAAC;IACpB,WAAW,EAAE,gFAAgF;IAC7F,OAAO,EAAE,gBAAgB,CAAC,OAAO;IAEjC,KAAK,CAAC,OAAO,CAAC,QAAgC;QAC5C,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5D,mBAAmB,CAAC,OAAO,EAAE,cAAc,CAAC,uBAAuB,EAAE,YAAY,CAAC,CAAC;QACnF,MAAM,SAAS,CAAC,OAAO,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAC7D,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"approve-pr.js","sourceRoot":"","sources":["../../src/commands/approve-pr.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"attach-project-item.d.ts","sourceRoot":"","sources":["../../src/commands/attach-project-item.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AASjD,eAAO,MAAM,wBAAwB,EAAE,OAwFtC,CAAC"}
1
+ {"version":3,"file":"attach-project-item.d.ts","sourceRoot":"","sources":["../../src/commands/attach-project-item.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AASjD,eAAO,MAAM,wBAAwB,EAAE,OA2FtC,CAAC"}