@nanobpm/nano-workforce 0.61.1 → 0.62.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [0.62.0](https://github.com/nanobpm/nano-workforce/compare/v0.61.1...v0.62.0) (2026-08-13)
2
+
3
+
4
+ ### Features
5
+
6
+ * **feature-prompt:** claim the issue with a comment before starting work ([#207](https://github.com/nanobpm/nano-workforce/issues/207)) ([b1b23c9](https://github.com/nanobpm/nano-workforce/commit/b1b23c9928704616aa2173cfa056668a11d32e1c))
7
+
1
8
  ## [0.61.1](https://github.com/nanobpm/nano-workforce/compare/v0.61.0...v0.61.1) (2026-08-13)
2
9
 
3
10
 
@@ -104,6 +104,8 @@ test("startFeature: seeds the single task slice + base-branch brief onto the ins
104
104
  assertEquals(v.task.prompt.includes("owner/repo#42"), true);
105
105
  assertEquals(v.converge, true);
106
106
  assertEquals(v.autoMerge, false);
107
+ // A single-issue run owns its issue, so the agent is told it may claim it (epic slices never set this).
108
+ assertEquals(v.claimIssue, true);
107
109
  assertEquals(v.baseBranch, "epic/x");
108
110
  // The brief is the authoritative base-branch override the agent gets via appendPrompt.
109
111
  assertEquals(v.baseBranchBrief.includes("epic/x"), true);
package/app/feature.ts CHANGED
@@ -202,6 +202,11 @@ export async function startFeature(
202
202
  // merge-loop. `converge=false` ⇒ merge is moot.
203
203
  converge,
204
204
  autoMerge,
205
+ // A single-issue feature run OWNS its issue (the whole issue is the slice), so the agent may
206
+ // claim it with a "starting work" comment on a first run (prompts/feature.md). Epic slices
207
+ // (plan-fanout) deliberately DO NOT set this — their `issue` is the shared parent epic, which
208
+ // must never be claimed per-slice.
209
+ claimIssue: true,
205
210
  // Seed the agent-result variables so the escalation loop + record worker can reference them
206
211
  // before the first `senior:feature` job completes (the harness merges the real values in).
207
212
  answer: null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanobpm/nano-workforce",
3
- "version": "0.61.1",
3
+ "version": "0.62.0",
4
4
  "description": "Nano Workforce — an Agent Graph Orchestration application for Agentic SDLC: durable BPMN processes that coordinate a graph of AI agents across the software delivery lifecycle.",
5
5
  "type": "module",
6
6
  "main": "main.ts",
@@ -22,16 +22,44 @@ You have `gh` / git authenticated for the target repository.
22
22
 
23
23
  Always use the branch **`feat/<task.id>`**. Because a resumed run gets a fresh
24
24
  process with no memory of your last run, the branch name MUST be derivable from
25
- `task.id` alone. On start, check whether it already exists on the remote
26
- (`git ls-remote --heads origin feat/<task.id>` or
27
- `gh pr list --head feat/<task.id> --state all`):
25
+ `task.id` alone. On start, check whether it already exists on the remote with
26
+ `git ls-remote --heads origin feat/<task.id>` — a non-empty result means the
27
+ branch exists. Use this ref check as the authoritative first-run/resume signal:
28
+ a remote branch can exist without any PR, so `gh pr list --head feat/<task.id> --state all`
29
+ is reliable only as a *supplementary* PR lookup once `git ls-remote` has
30
+ established the branch exists, never as the existence check itself:
28
31
 
29
32
  - **It does not exist** → this is a first run. Branch off the base branch (see
30
33
  the note below — usually the repository default branch, but an epic may pin an
31
- integration branch in your appended task context).
34
+ integration branch in your appended task context). **Claim the issue now** — see
35
+ below.
32
36
  - **It exists** → this is a **resume**. `git fetch` and check it out, read its diff
33
37
  and any open (draft) PR, and **continue from there** — do not restart from
34
- scratch. Fold in `variables.answer` as the guidance you were waiting on.
38
+ scratch. Fold in `variables.answer` as the guidance you were waiting on. Do
39
+ **not** re-claim — you already announced this run on your first pass.
40
+
41
+ ## Claim your issue on a first run (only when `variables.claimIssue` is true)
42
+
43
+ So humans and other agents can see the work has been picked up, announce yourself
44
+ on the issue **before implementing** — but ONLY on a first run (your
45
+ `feat/<task.id>` branch did not yet exist, per the check above) AND only when
46
+ **`variables.claimIssue` is true**:
47
+
48
+ ```sh
49
+ gh issue comment <variables.issue> --body-file - <<'BODY'
50
+ 🤖 Starting work on this issue — branch `feat/<task.id>`.
51
+ BODY
52
+ ```
53
+
54
+ - `variables.claimIssue` is set **only for single-issue feature runs**, where
55
+ `variables.issue` IS the issue you implement and close, so claiming it is
56
+ correct. **Epic slices leave it unset** — their `variables.issue` is the shared
57
+ *parent epic*, which must never be claimed per-slice; when `claimIssue` is not
58
+ true, **skip this step entirely**.
59
+ - The branch-existence check above is what makes this idempotent: a resumed run
60
+ (branch already exists) never re-claims, so the issue gets exactly one claim.
61
+ - It is a courtesy claim, **not a gate** — if the comment fails (e.g. a transient
62
+ `gh` error), carry on and implement anyway.
35
63
 
36
64
  ## Your base branch (default branch, unless the epic pins one)
37
65
 
@@ -44,14 +72,16 @@ against the wrong base will not be merged into the epic.
44
72
 
45
73
  ## What to do
46
74
 
47
- 1. Clone / check out your base branch (first run the default branch, or the
75
+ 1. Claim your issue if `variables.claimIssue` is true and this is a first run (see
76
+ above).
77
+ 2. Clone / check out your base branch (first run — the default branch, or the
48
78
  pinned epic branch if your context names one) or your existing
49
79
  `feat/<task.id>` branch (resume — see above).
50
- 2. Implement `task.prompt`. Keep the change scoped to this slice only.
51
- 3. Commit (sign off — this repo family enforces DCO: `git commit -s`), push the
80
+ 3. Implement `task.prompt`. Keep the change scoped to this slice only.
81
+ 4. Commit (sign off — this repo family enforces DCO: `git commit -s`), push the
52
82
  branch, and open a pull request with `gh pr create` describing the slice and
53
83
  linking the parent issue (`Depends-on:`/`Closes` as appropriate).
54
- 4. Clean up any scratch clone/worktree you created outside the commit.
84
+ 5. Clean up any scratch clone/worktree you created outside the commit.
55
85
 
56
86
  > **Do not request the Copilot review yourself.** When you open a *ready* PR the
57
87
  > app enrolls it into the review-convergence loop and requests the initial