@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 +7 -0
- package/app/feature.test.ts +2 -0
- package/app/feature.ts +5 -0
- package/package.json +1 -1
- package/prompts/feature.md +39 -9
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
|
|
package/app/feature.test.ts
CHANGED
|
@@ -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.
|
|
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",
|
package/prompts/feature.md
CHANGED
|
@@ -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
|
-
|
|
27
|
-
|
|
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.
|
|
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
|
-
|
|
51
|
-
|
|
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
|
-
|
|
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
|