duaer-spec 0.5.1 → 0.6.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.
- package/.cursor/rules/agents-workflow.mdc +31 -26
- package/.cursor/rules/duaer-spec.mdc +10 -2
- package/.duaer/handoff.json +9 -0
- package/ADOPT.md +44 -16
- package/AGENTS.md +80 -49
- package/CHANGELOG.md +27 -17
- package/README.md +24 -1
- package/bin/duaer.mjs +97 -9
- package/docs/agent/README.md +1 -0
- package/docs/agent/branching-and-release.md +207 -0
- package/docs/agent/change-checklist.md +15 -10
- package/docs/agent/e2e-test-plan.md +8 -0
- package/docs/agent/workflow.md +25 -20
- package/docs/baseline.md +17 -5
- package/package.json +2 -2
|
@@ -1,52 +1,57 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: duaer-spec agent ops (
|
|
2
|
+
description: duaer-spec agent ops (develop+main, feat/fix, .worktree, push opt-in)
|
|
3
3
|
alwaysApply: true
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Agent development workflow
|
|
7
7
|
|
|
8
|
-
Part of **duaer-spec**. Authoritative over Duaer when they conflict.
|
|
9
|
-
repository integrates on `main`. Adopting projects may document another
|
|
10
|
-
integration branch in their baseline.
|
|
8
|
+
Part of **duaer-spec**. Authoritative over Duaer when they conflict.
|
|
11
9
|
|
|
12
|
-
##
|
|
10
|
+
## Required branches
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
| Branch | Role |
|
|
13
|
+
|---|---|
|
|
14
|
+
| `main` | Production / online |
|
|
15
|
+
| `develop` | Day-to-day integration |
|
|
16
|
+
| `feat/<name>` | Feature → merge to `develop` |
|
|
17
|
+
| `fix/<name>` | Bugfix → `develop` (hotfix: from `main` → `main` then `develop`) |
|
|
18
|
+
|
|
19
|
+
Detail: `docs/agent/branching-and-release.md`.
|
|
16
20
|
|
|
17
21
|
## Isolated development (mandatory worktree)
|
|
18
22
|
|
|
19
23
|
Before editing files for a new request:
|
|
20
24
|
|
|
21
|
-
1. Update local
|
|
22
|
-
2. Create
|
|
23
|
-
3. Create
|
|
25
|
+
1. Update local **`develop`** (hotfix: **`main`**)
|
|
26
|
+
2. Create `feat/<name>` or `fix/<name>`
|
|
27
|
+
3. Create worktree at **`.worktree/<request-id>`** (required)
|
|
24
28
|
4. Develop only inside that worktree
|
|
25
|
-
5. Never develop
|
|
26
|
-
6. Never reuse
|
|
27
|
-
7. Never commit `.worktree/`
|
|
29
|
+
5. Never develop on `main` / `develop` or in the primary checkout
|
|
30
|
+
6. Never reuse another agent's branch/worktree
|
|
31
|
+
7. Never commit `.worktree/`
|
|
28
32
|
|
|
29
33
|
```bash
|
|
30
34
|
mkdir -p .worktree
|
|
31
|
-
git worktree add .worktree/<request-id> -b
|
|
35
|
+
git worktree add .worktree/<request-id> -b feat/<name> develop
|
|
32
36
|
cd .worktree/<request-id>
|
|
33
37
|
```
|
|
38
|
+
|
|
34
39
|
## Immutable habits
|
|
35
40
|
|
|
36
|
-
- Spec-sync
|
|
41
|
+
- Spec-sync for behavior changes; ADR when architecture/security/contracts change
|
|
37
42
|
- One logical change per commit; leave the worktree clean
|
|
38
|
-
- User/protocol-visible changes update
|
|
39
|
-
- Merge
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
If the user links an issue for this repo: verify the claim first; do not implement until it exists. Comment in the issue's language; close when conclusive. An issue link does not authorize push.
|
|
43
|
+
- User/protocol-visible changes update E2E scenario docs
|
|
44
|
+
- Merge into **`develop`** when done (hotfix: **`main`**, then back-merge **`develop`**)
|
|
45
|
+
- **Handoff (mandatory):** stop worktree-bound processes → remove `.worktree/<id>` →
|
|
46
|
+
restart from primary checkout on `develop` (`duaer handoff [--run]`, `.duaer/handoff.json`)
|
|
47
|
+
- Push only when the user explicitly asks
|
|
48
|
+
- Promote **`develop` → `main`** only when the user asks to go online
|
|
46
49
|
|
|
47
|
-
## GitHub PR intake
|
|
50
|
+
## GitHub issue / PR intake
|
|
48
51
|
|
|
49
|
-
|
|
52
|
+
Issue: verify before work; comment in issue language; close when conclusive.
|
|
53
|
+
PR: judge principle; merge sound PRs; no silent reimplementation.
|
|
54
|
+
Neither authorizes push by itself.
|
|
50
55
|
|
|
51
56
|
## Commits
|
|
52
57
|
|
|
@@ -54,4 +59,4 @@ If the user links a PR: judge the principle first. If sound, merge that PR (pres
|
|
|
54
59
|
type(scope): description
|
|
55
60
|
```
|
|
56
61
|
|
|
57
|
-
Types: `feat fix docs test chore refactor perf build ci` — English, imperative
|
|
62
|
+
Types: `feat fix docs test chore refactor perf build ci` — English, imperative.
|
|
@@ -16,14 +16,22 @@ If this conflicts with root `AGENTS.md` (worktrees, commits, Issue/PR),
|
|
|
16
16
|
|
|
17
17
|
For new behavior, fixes, refactors that change product behavior, or architecture:
|
|
18
18
|
|
|
19
|
-
0. **Isolate first (mandatory):** update
|
|
20
|
-
|
|
19
|
+
0. **Isolate first (mandatory):** update **`develop`** (hotfix: **`main`**),
|
|
20
|
+
create `feat|fix/<name>`, add worktree at `.worktree/<request-id>`,
|
|
21
21
|
work only there. Never skip the worktree. Never commit `.worktree/`.
|
|
22
|
+
Never develop on `main` or `develop`.
|
|
22
23
|
1. **Silently follow** the procedure in `.cursor/skills/duaer-do/SKILL.md`
|
|
23
24
|
(assign Brief → light tasks → implement → converge → handoff line).
|
|
24
25
|
2. Do **not** wait for `/duaer-do` or any other skill invocation.
|
|
25
26
|
3. Do **not** say “please run `/duaer-specify`” — you do it.
|
|
26
27
|
4. Do **not** dump a methodology tutorial unless they ask how Duaer works.
|
|
28
|
+
5. Merge to **`develop`** when done (hotfix: **`main`**, then back-merge
|
|
29
|
+
**`develop`**). Promote to **`main`** only if the user asks to go online.
|
|
30
|
+
6. **Handoff (mandatory):** stop processes bound to `.worktree/<id>/`, remove
|
|
31
|
+
the worktree, then restart services from the primary checkout on `develop`
|
|
32
|
+
using `.duaer/handoff.json` / `duaer handoff [--run]`. Never leave the user
|
|
33
|
+
on a dead worktree server.
|
|
34
|
+
See `docs/agent/branching-and-release.md`.
|
|
27
35
|
|
|
28
36
|
## Handoff
|
|
29
37
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"onWorktreeRemove": {
|
|
4
|
+
"stop": "Stop any process whose working directory is under the request worktree (dev servers, file watchers, local APIs).",
|
|
5
|
+
"restartFromPrimary": true,
|
|
6
|
+
"commands": []
|
|
7
|
+
},
|
|
8
|
+
"notes": "After merging into develop (or hotfix main), stop worktree-bound processes, remove .worktree/<id>, then restart from the primary checkout. Add commands such as \"npm run dev\" when this project needs a local service after handoff. Empty commands = stop only; agent still reports handoff."
|
|
9
|
+
}
|
package/ADOPT.md
CHANGED
|
@@ -7,36 +7,64 @@ Brief → work → accept **without** the human operating slash commands or CLI.
|
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
9
|
npx duaer-spec init --here
|
|
10
|
-
# pin: npx github:fujiezee/duaer-spec@v0.
|
|
10
|
+
# pin: npx github:fujiezee/duaer-spec@v0.6.1 duaer init --here
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
npx duaer-spec init --here --method
|
|
15
|
-
npx duaer-spec init --here --ops
|
|
15
|
+
npx duaer-spec init --here --ops
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Ensure the repo has **`main`** and **`develop`**. See
|
|
19
|
+
[`docs/agent/branching-and-release.md`](docs/agent/branching-and-release.md).
|
|
20
|
+
|
|
21
|
+
After that: talk to the agent in plain language.
|
|
22
|
+
|
|
23
|
+
## Updating an existing install
|
|
24
|
+
|
|
25
|
+
Already ran `duaer init` before? Refresh managed files:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx duaer-spec@latest init --here --force
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Then:
|
|
32
|
+
|
|
33
|
+
1. **Review the git diff** — keep your project-specific edits to
|
|
34
|
+
`.duaer/memory/constitution.md`, `project-context.md`, `docs/baseline.md`,
|
|
35
|
+
and especially **`.duaer/handoff.json` `commands`** (your restart scripts).
|
|
36
|
+
2. Restore any local overrides you still need.
|
|
37
|
+
3. Confirm `.gitignore` still contains `.worktree/`.
|
|
38
|
+
4. No need to re-learn slash commands — talk to the agent as before.
|
|
39
|
+
|
|
40
|
+
Pin a version if you prefer:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx duaer-spec@0.6.1 init --here --force
|
|
44
|
+
# or
|
|
45
|
+
npx github:fujiezee/duaer-spec@v0.6.1 duaer init --here --force
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Adopters are **not** auto-updated; re-run init when you want a newer revision.
|
|
19
49
|
|
|
20
50
|
## What gets installed
|
|
21
51
|
|
|
22
|
-
- Always-on
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
- Agent ops (`AGENTS.md`) when using `--all` / `--ops`
|
|
52
|
+
- Always-on autonomous job loop
|
|
53
|
+
- `.duaer/handoff.json` — restart services on **develop** after worktree remove
|
|
54
|
+
- Agent ops: `AGENTS.md`, branching/release docs, mandatory `.worktree/`
|
|
26
55
|
|
|
27
|
-
##
|
|
56
|
+
## Branch model (mandatory)
|
|
28
57
|
|
|
29
|
-
|
|
|
58
|
+
| Branch | Role |
|
|
30
59
|
|---|---|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
| `
|
|
60
|
+
| `main` | Production / online |
|
|
61
|
+
| `develop` | Day-to-day integration |
|
|
62
|
+
| `feat/<name>` | Features → `develop` |
|
|
63
|
+
| `fix/<name>` | Fixes → `develop` (hotfix via `main`) |
|
|
64
|
+
|
|
65
|
+
After merge: **`duaer handoff [--run]`** (stop worktree services → restart on develop).
|
|
34
66
|
|
|
35
67
|
## Precedence
|
|
36
68
|
|
|
37
69
|
1. `AGENTS.md` — how employees operate
|
|
38
70
|
2. `DUADER.md` / `.duaer/` — how jobs are briefed
|
|
39
|
-
|
|
40
|
-
## Updates
|
|
41
|
-
|
|
42
|
-
`duaer init --force` (review the diff) or pin a tag.
|
package/AGENTS.md
CHANGED
|
@@ -35,7 +35,8 @@ until the reported problem has been independently verified.
|
|
|
35
35
|
close the issue when the conclusion is clear. If verification is
|
|
36
36
|
inconclusive, comment with what was tried and leave the issue open.
|
|
37
37
|
4. If the problem **does** exist: follow the isolated development workflow,
|
|
38
|
-
implement the smallest coherent fix, merge into local `
|
|
38
|
+
implement the smallest coherent fix, merge into local `develop` (or
|
|
39
|
+
hotfix into `main` then back-merge `develop`), then comment
|
|
39
40
|
on the issue and close it.
|
|
40
41
|
5. Write the issue comment in the issue's language (the language of the
|
|
41
42
|
original title and body). Repository docs, code, and commits stay English
|
|
@@ -103,6 +104,23 @@ copy limited to the information and actions users need to complete the task:
|
|
|
103
104
|
* Put rationale and implementation detail in documentation or code comments,
|
|
104
105
|
not in the page UI, unless the user explicitly requests explanatory content.
|
|
105
106
|
|
|
107
|
+
## Mandatory branch model
|
|
108
|
+
|
|
109
|
+
Repositories that adopt this agent-ops contract **must** use:
|
|
110
|
+
|
|
111
|
+
| Branch | Role |
|
|
112
|
+
|---|---|
|
|
113
|
+
| **`main`** | Production / officially online |
|
|
114
|
+
| **`develop`** | Day-to-day integration and debugging |
|
|
115
|
+
| **`feat/<name>`** | Feature work (from `develop` → merge to `develop`) |
|
|
116
|
+
| **`fix/<name>`** | Bug fixes (from `develop` → `develop`; hotfixes from `main` → `main` then back to `develop`) |
|
|
117
|
+
|
|
118
|
+
Do **not** develop on `main` or `develop`. Full flows (including go-live by
|
|
119
|
+
issue type): [branching-and-release](docs/agent/branching-and-release.md).
|
|
120
|
+
|
|
121
|
+
**duaer-spec itself** uses this model: integrate on **`develop`**, promote to
|
|
122
|
+
**`main`** only when shipping.
|
|
123
|
+
|
|
106
124
|
## Mandatory Isolated Development
|
|
107
125
|
|
|
108
126
|
Every request must use its own dedicated branch and worktree.
|
|
@@ -113,8 +131,9 @@ Landing-blocker commits, if needed, go on top of the author's branch.
|
|
|
113
131
|
|
|
114
132
|
Before modifying any file, the agent must:
|
|
115
133
|
|
|
116
|
-
1. Update the primary checkout's local
|
|
117
|
-
|
|
134
|
+
1. Update the primary checkout's local **`develop`** (or **`main`** for a
|
|
135
|
+
production hotfix)
|
|
136
|
+
2. Create a unique branch from that base (`feat/…` or `fix/…`)
|
|
118
137
|
3. Create a dedicated worktree **under the project** at `.worktree/<request-id>`
|
|
119
138
|
4. Enter that worktree
|
|
120
139
|
5. Only then begin development
|
|
@@ -122,13 +141,13 @@ Before modifying any file, the agent must:
|
|
|
122
141
|
Worktrees live in **`.worktree/`** at the repository root. That directory is
|
|
123
142
|
**mandatory**, not optional, and **must never be committed** (see `.gitignore`).
|
|
124
143
|
|
|
125
|
-
Example:
|
|
144
|
+
Example (normal feature):
|
|
126
145
|
|
|
127
146
|
```bash
|
|
128
|
-
git switch
|
|
147
|
+
git switch develop
|
|
129
148
|
git pull --ff-only
|
|
130
149
|
mkdir -p .worktree
|
|
131
|
-
git worktree add .worktree/<request-id> -b
|
|
150
|
+
git worktree add .worktree/<request-id> -b feat/<request-id> develop
|
|
132
151
|
cd .worktree/<request-id>
|
|
133
152
|
```
|
|
134
153
|
|
|
@@ -136,26 +155,21 @@ Branch and worktree names must be unique and clearly associated with the request
|
|
|
136
155
|
Do **not** place request worktrees outside the repo (for example `../worktrees/`)
|
|
137
156
|
unless the project baseline explicitly overrides this and still keeps them
|
|
138
157
|
untracked.
|
|
139
|
-
|
|
140
|
-
**This repository's default integration branch is `main`.** Adopting projects
|
|
141
|
-
may substitute another long-lived branch (for example `develop`); document that
|
|
142
|
-
override in the project baseline. Do not inherit git policy from `examples/`.
|
|
143
|
-
|
|
144
158
|
## Multi-Agent Isolation
|
|
145
159
|
|
|
146
160
|
* Each agent must use its own branch and worktree
|
|
147
161
|
* Never develop directly in the primary checkout
|
|
148
|
-
* Never develop directly on `main`
|
|
162
|
+
* Never develop directly on `main` or `develop`
|
|
149
163
|
* Never reuse another agent's branch or worktree
|
|
150
164
|
* Never modify files inside another request's worktree
|
|
151
165
|
* Never switch another agent's branch
|
|
152
166
|
* Never delete another agent's branch or worktree
|
|
153
167
|
* Never include unrelated changes from another request
|
|
154
|
-
* Do not commit local environment files, caches, databases, or
|
|
168
|
+
* Do not commit local environment files, caches, databases, secrets, or `.worktree/`
|
|
155
169
|
|
|
156
|
-
The primary checkout is reserved for synchronizing and merging
|
|
157
|
-
|
|
158
|
-
tracked files or interfere with another worktree.
|
|
170
|
+
The primary checkout is reserved for synchronizing and merging **`develop`**
|
|
171
|
+
(and **`main`** on promote / hotfix). Shared toolchains and caches may be
|
|
172
|
+
reused when that cannot modify tracked files or interfere with another worktree.
|
|
159
173
|
|
|
160
174
|
## Immutable Rules
|
|
161
175
|
|
|
@@ -186,25 +200,33 @@ explicitly requested by the user, **except** for forked third-party pull
|
|
|
186
200
|
request heads when the project requires local suites before merge. Record the
|
|
187
201
|
result in the pull request comment.
|
|
188
202
|
|
|
189
|
-
### 4. Merge Back into Local `main`
|
|
203
|
+
### 4. Merge Back into Local `develop` (or hotfix `main`)
|
|
190
204
|
|
|
191
|
-
After development:
|
|
205
|
+
After normal development:
|
|
192
206
|
|
|
193
207
|
1. Complete targeted validation
|
|
194
208
|
2. Review the complete diff
|
|
195
209
|
3. Commit all logical changes
|
|
196
|
-
4. Update the request branch with the latest local
|
|
210
|
+
4. Update the request branch with the latest local **`develop`**
|
|
197
211
|
5. Resolve conflicts inside the request worktree
|
|
198
212
|
6. Return to the primary checkout
|
|
199
|
-
7. Merge the request branch into local
|
|
213
|
+
7. Merge the request branch into local **`develop`**
|
|
200
214
|
8. Verify the expected commits are present
|
|
201
|
-
9.
|
|
202
|
-
|
|
203
|
-
|
|
215
|
+
9. Stop any server/process started from the request worktree; if the user still
|
|
216
|
+
needs a local service, start it from the primary checkout on **`develop`**
|
|
217
|
+
10. Remove the request worktree
|
|
218
|
+
11. Delete the merged request branch
|
|
219
|
+
12. Push only when the user explicitly requested remote publishing for the
|
|
204
220
|
current request
|
|
221
|
+
13. Promote **`develop` → `main`** only when the user explicitly asks to ship /
|
|
222
|
+
go online (see [branching-and-release](docs/agent/branching-and-release.md))
|
|
223
|
+
|
|
224
|
+
**Production hotfix:** base and merge into **`main`**, then merge the fix into
|
|
225
|
+
**`develop`** so integration does not regress. Then clean up the worktree.
|
|
205
226
|
|
|
206
|
-
If another agent has updated `
|
|
207
|
-
(`git fetch` then `git rebase
|
|
227
|
+
If another agent has updated `develop`, refresh the request branch before
|
|
228
|
+
merging (`git fetch` then `git rebase develop`, or merge if project policy
|
|
229
|
+
requires it).
|
|
208
230
|
|
|
209
231
|
Do not overwrite, reset, or discard changes already merged by another agent.
|
|
210
232
|
|
|
@@ -214,26 +236,30 @@ explicitly requests that exact operation.
|
|
|
214
236
|
|
|
215
237
|
### 5. Clean Up the Request Worktree
|
|
216
238
|
|
|
217
|
-
Once the request branch is merged into local
|
|
218
|
-
delete the merged branch. Never leave a merged
|
|
239
|
+
Once the request branch is merged into local **`develop`** (or **`main`** for a
|
|
240
|
+
hotfix), remove its worktree and delete the merged branch. Never leave a merged
|
|
241
|
+
worktree on disk.
|
|
219
242
|
|
|
220
243
|
```bash
|
|
221
244
|
git worktree remove .worktree/<request-id>
|
|
222
|
-
git branch -d
|
|
245
|
+
git branch -d feat|fix/<request-id>
|
|
223
246
|
git worktree prune
|
|
224
247
|
```
|
|
225
248
|
|
|
226
|
-
* Remove only after verifying merge commits are present
|
|
249
|
+
* Remove only after verifying merge commits are present on the target long-lived branch
|
|
227
250
|
* The worktree must be clean first
|
|
228
251
|
* Use `git branch -d` (not `-D`)
|
|
229
252
|
* Delete only your own worktree and branch
|
|
230
253
|
* Never commit `.worktree/` (ignored)
|
|
254
|
+
* Stop worktree-bound services before remove; then restart from the primary
|
|
255
|
+
checkout on **`develop`** via `.duaer/handoff.json` / `duaer handoff [--run]`
|
|
256
|
+
(mandatory handoff — see [branching-and-release](docs/agent/branching-and-release.md))
|
|
231
257
|
|
|
232
258
|
## Development Workflow
|
|
233
259
|
|
|
234
|
-
1. Update local
|
|
235
|
-
2. Create a unique
|
|
236
|
-
3. Create and enter
|
|
260
|
+
1. Update local **`develop`** (or **`main`** for hotfix)
|
|
261
|
+
2. Create a unique `feat/` or `fix/` branch
|
|
262
|
+
3. Create and enter `.worktree/<request-id>`
|
|
237
263
|
4. Read the baseline and relevant specs (and Duaer memory when present)
|
|
238
264
|
5. Identify affected specs, ADRs, E2E scenarios, and validation
|
|
239
265
|
6. Implement the smallest coherent change
|
|
@@ -241,16 +267,19 @@ git worktree prune
|
|
|
241
267
|
8. Run targeted, risk-based checks
|
|
242
268
|
9. Review the complete diff
|
|
243
269
|
10. Commit each logical change
|
|
244
|
-
11. Refresh
|
|
245
|
-
12. Merge into local
|
|
246
|
-
13.
|
|
247
|
-
|
|
270
|
+
11. Refresh against latest **`develop`** (or **`main`** for hotfix)
|
|
271
|
+
12. Merge into local **`develop`** (hotfix: **`main`**, then back-merge to **`develop`**)
|
|
272
|
+
13. Stop worktree services; remove worktree; delete short branch; **handoff**
|
|
273
|
+
restart on `develop` (`duaer handoff [--run]` / `.duaer/handoff.json`)
|
|
274
|
+
14. Push only when explicitly requested
|
|
275
|
+
15. Promote **`develop` → `main`** only when the user explicitly asks to go online
|
|
248
276
|
|
|
249
|
-
Development must not begin before steps 1–3 are complete.
|
|
277
|
+
Development must not begin before isolation steps 1–3 are complete.
|
|
250
278
|
|
|
251
|
-
For feature work that uses Duaer,
|
|
252
|
-
|
|
253
|
-
|
|
279
|
+
For feature work that uses Duaer, the agent runs the job loop autonomously
|
|
280
|
+
(Brief → work → accept). Agent ops in this file still govern isolation, commits,
|
|
281
|
+
and merge. Branch/release detail:
|
|
282
|
+
[branching-and-release](docs/agent/branching-and-release.md).
|
|
254
283
|
|
|
255
284
|
## Commit Format
|
|
256
285
|
|
|
@@ -266,20 +295,20 @@ Allowed types: `feat fix docs test chore refactor perf build ci`
|
|
|
266
295
|
|
|
267
296
|
## Completion Checklist
|
|
268
297
|
|
|
269
|
-
* [ ] Local
|
|
270
|
-
* [ ] A unique
|
|
271
|
-
* [ ] A dedicated worktree was created
|
|
298
|
+
* [ ] Local **`develop`** was updated before development (or **`main`** for hotfix)
|
|
299
|
+
* [ ] A unique `feat/` or `fix/` branch was created
|
|
300
|
+
* [ ] A dedicated worktree was created under `.worktree/`
|
|
272
301
|
* [ ] All development occurred inside that worktree
|
|
273
302
|
* [ ] No other agent's branch or worktree was modified
|
|
274
303
|
* [ ] Relevant specs and E2E scenarios were updated
|
|
275
304
|
* [ ] Targeted validation passed or was documented as unnecessary
|
|
276
|
-
* [ ] No secrets, local data, or unrelated changes are included
|
|
305
|
+
* [ ] No secrets, local data, `.worktree/`, or unrelated changes are included
|
|
277
306
|
* [ ] All logical changes were committed
|
|
278
|
-
* [ ] The branch was refreshed against the latest local
|
|
279
|
-
* [ ] Changes were merged into local
|
|
280
|
-
* [ ]
|
|
281
|
-
* [ ] The merged request branch was deleted
|
|
307
|
+
* [ ] The branch was refreshed against the latest local **`develop`** (or hotfix base)
|
|
308
|
+
* [ ] Changes were merged into local **`develop`** (hotfix: **`main`** + back-merge **`develop`**)
|
|
309
|
+
* [ ] Worktree-bound services stopped; worktree removed; short branch deleted
|
|
282
310
|
* [ ] Remote publishing was skipped unless explicitly requested
|
|
311
|
+
* [ ] Promotion **`develop` → `main`** only if the user asked to go online
|
|
283
312
|
* [ ] If pushed, the remote, branch, commit set, and Git identity were verified
|
|
284
313
|
* [ ] If a GitHub issue was linked: verified before work; commented in its
|
|
285
314
|
language; closed when conclusive
|
|
@@ -295,7 +324,9 @@ Report:
|
|
|
295
324
|
* Documentation updated
|
|
296
325
|
* Validation performed or skipped
|
|
297
326
|
* Commit hashes and messages
|
|
298
|
-
* Merge result
|
|
327
|
+
* Merge target (`develop` / `main`) and result
|
|
299
328
|
* Worktree and branch cleanup result
|
|
329
|
+
* Service handoff (stopped in worktree / restarted on develop) if applicable
|
|
300
330
|
* Push target and result, or confirmation that nothing was pushed
|
|
331
|
+
* Whether `main` was promoted (or N/A)
|
|
301
332
|
* Linked GitHub issue / PR outcomes (or N/A)
|
package/CHANGELOG.md
CHANGED
|
@@ -1,36 +1,46 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 0.6.1 — 2026-09-15
|
|
4
4
|
|
|
5
|
-
###
|
|
5
|
+
### Worktree → develop service handoff
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
- `duaer
|
|
11
|
-
-
|
|
7
|
+
- Mandatory handoff after merge: stop worktree-bound processes, remove
|
|
8
|
+
`.worktree/<id>`, restart from primary checkout on `develop`
|
|
9
|
+
- `.duaer/handoff.json` configures restart commands (e.g. `npm run dev`)
|
|
10
|
+
- CLI: `duaer handoff` / `duaer handoff --run`
|
|
11
|
+
- Docs: update path for existing installs (`init --force` + review diff)
|
|
12
12
|
|
|
13
|
-
## 0.
|
|
13
|
+
## 0.6.0 — 2026-09-15
|
|
14
14
|
|
|
15
|
-
###
|
|
15
|
+
### Mandatory branch model + release flows
|
|
16
16
|
|
|
17
|
-
-
|
|
18
|
-
-
|
|
17
|
+
- Required: `main` / `develop` / `feat/*` / `fix/*`
|
|
18
|
+
- [`docs/agent/branching-and-release.md`](docs/agent/branching-and-release.md)
|
|
19
19
|
|
|
20
|
-
## 0.
|
|
20
|
+
## 0.5.1 — 2026-09-15
|
|
21
|
+
|
|
22
|
+
- Mandatory `.worktree/` (gitignored)
|
|
23
|
+
|
|
24
|
+
## 0.5.0 — 2026-09-15
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
- Autonomous digital employee (ask, don’t operate phases)
|
|
27
|
+
|
|
28
|
+
## 0.4.0 — 2026-09-15
|
|
29
|
+
|
|
30
|
+
- Everyday `/duaer-do` path (later agent-internal)
|
|
31
|
+
|
|
32
|
+
## 0.3.0 — 2026-09-15
|
|
23
33
|
|
|
24
|
-
-
|
|
34
|
+
- Job handoff policy
|
|
25
35
|
|
|
26
36
|
## 0.2.0 — 2026-09-15
|
|
27
37
|
|
|
28
|
-
- `delivery.json`
|
|
38
|
+
- `delivery.json`
|
|
29
39
|
|
|
30
40
|
## 0.1.1 — 2026-09-15
|
|
31
41
|
|
|
32
|
-
- Digital-employee
|
|
42
|
+
- Digital-employee positioning
|
|
33
43
|
|
|
34
44
|
## 0.1.0 — 2026-09-15
|
|
35
45
|
|
|
36
|
-
- First public
|
|
46
|
+
- First public release
|
package/README.md
CHANGED
|
@@ -26,10 +26,33 @@ required.
|
|
|
26
26
|
Step skills and CLI checks exist for agents and power users — not as the
|
|
27
27
|
everyday human UI.
|
|
28
28
|
|
|
29
|
+
## Branches (mandatory)
|
|
30
|
+
|
|
31
|
+
| Branch | Role |
|
|
32
|
+
|---|---|
|
|
33
|
+
| `main` | Production / online |
|
|
34
|
+
| `develop` | Day-to-day integration |
|
|
35
|
+
| `feat/<name>` | Features → `develop` |
|
|
36
|
+
| `fix/<name>` | Fixes → `develop` (hotfix via `main`) |
|
|
37
|
+
|
|
38
|
+
Go-live and flows by issue type:
|
|
39
|
+
[`docs/agent/branching-and-release.md`](docs/agent/branching-and-release.md).
|
|
40
|
+
|
|
41
|
+
**After merge:** `duaer handoff [--run]` restarts local services on `develop`
|
|
42
|
+
(configure commands in `.duaer/handoff.json`).
|
|
43
|
+
|
|
44
|
+
## Updating
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx duaer-spec@latest init --here --force # review diff; keep handoff commands
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Details: [`ADOPT.md`](ADOPT.md)#updating-an-existing-install
|
|
51
|
+
|
|
29
52
|
## Optional
|
|
30
53
|
|
|
31
54
|
```bash
|
|
32
|
-
npx duaer-spec@0.
|
|
55
|
+
npx duaer-spec@0.6.1 init --here --method
|
|
33
56
|
```
|
|
34
57
|
|
|
35
58
|
Details: [`ADOPT.md`](ADOPT.md) · Method: [`DUADER.md`](DUADER.md) · Ops: [`AGENTS.md`](AGENTS.md)
|
package/bin/duaer.mjs
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
statSync,
|
|
16
16
|
writeFileSync,
|
|
17
17
|
} from 'node:fs'
|
|
18
|
+
import { spawn } from 'node:child_process'
|
|
18
19
|
import { dirname, join, resolve } from 'node:path'
|
|
19
20
|
import { fileURLToPath } from 'node:url'
|
|
20
21
|
|
|
@@ -26,19 +27,25 @@ const POLICY_MODES = new Set(['off', 'coach', 'strict'])
|
|
|
26
27
|
|
|
27
28
|
const USAGE = `duaer — digital-employee delivery (duaer-spec ${PKG.version})
|
|
28
29
|
|
|
29
|
-
Human (once):
|
|
30
|
-
duaer init [--here]
|
|
30
|
+
Human (once / update):
|
|
31
|
+
duaer init [--here] [--force] Install or refresh into a project
|
|
31
32
|
|
|
32
|
-
After install: talk to the agent in plain language.
|
|
33
|
+
After install: talk to the agent in plain language.
|
|
33
34
|
|
|
34
|
-
Agent / optional
|
|
35
|
+
Agent / optional:
|
|
36
|
+
duaer handoff [dir] [--run] After merge: print/restart services on develop
|
|
35
37
|
duaer status [dir]
|
|
36
38
|
duaer check | policy | version
|
|
37
39
|
|
|
38
|
-
Init: --all (default) | --method | --ops | --force | --branch <n> | --here
|
|
40
|
+
Init: --all (default) | --method | --ops | --force | --branch <n> (default: develop) | --here
|
|
41
|
+
|
|
42
|
+
Update existing install:
|
|
43
|
+
npx duaer-spec@latest init --here --force
|
|
44
|
+
# then review git diff; keep project-specific constitution / baseline / handoff commands
|
|
39
45
|
|
|
40
46
|
Example:
|
|
41
47
|
npx duaer-spec init --here
|
|
48
|
+
duaer handoff --run
|
|
42
49
|
`
|
|
43
50
|
|
|
44
51
|
function parseArgs(argv) {
|
|
@@ -48,13 +55,14 @@ function parseArgs(argv) {
|
|
|
48
55
|
dir: '.',
|
|
49
56
|
mode: 'all',
|
|
50
57
|
force: false,
|
|
51
|
-
branch: '
|
|
58
|
+
branch: 'develop',
|
|
52
59
|
workplace: false,
|
|
53
60
|
delivery: false,
|
|
54
61
|
job: false,
|
|
55
62
|
allJobs: false,
|
|
56
63
|
strict: false,
|
|
57
64
|
policyMode: null,
|
|
65
|
+
run: false,
|
|
58
66
|
}
|
|
59
67
|
const rest = args.slice(1)
|
|
60
68
|
for (let i = 0; i < rest.length; i++) {
|
|
@@ -69,6 +77,7 @@ function parseArgs(argv) {
|
|
|
69
77
|
else if (a === '--job') out.job = true
|
|
70
78
|
else if (a === '--all-jobs') out.allJobs = true
|
|
71
79
|
else if (a === '--strict' || a === '--gate') out.strict = true
|
|
80
|
+
else if (a === '--run') out.run = true
|
|
72
81
|
else if (a === '--branch') {
|
|
73
82
|
out.branch = rest[++i]
|
|
74
83
|
if (!out.branch) throw new Error('--branch requires a value')
|
|
@@ -170,11 +179,37 @@ function writeDefaultPolicy(target, { force }) {
|
|
|
170
179
|
console.log(' .duaer/delivery-policy.json (mode=coach)')
|
|
171
180
|
}
|
|
172
181
|
|
|
182
|
+
function defaultHandoff() {
|
|
183
|
+
return {
|
|
184
|
+
schemaVersion: 1,
|
|
185
|
+
onWorktreeRemove: {
|
|
186
|
+
stop:
|
|
187
|
+
'Stop any process whose working directory is under the request worktree (dev servers, file watchers, local APIs).',
|
|
188
|
+
restartFromPrimary: true,
|
|
189
|
+
commands: [],
|
|
190
|
+
},
|
|
191
|
+
notes:
|
|
192
|
+
'After merging into develop, stop worktree processes, remove .worktree/<id>, then restart from the primary checkout. Add commands such as "npm run dev" when needed.',
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function writeDefaultHandoff(target, { force }) {
|
|
197
|
+
const path = join(target, '.duaer', 'handoff.json')
|
|
198
|
+
if (existsSync(path) && !force) {
|
|
199
|
+
console.log(`skip (exists): ${path}`)
|
|
200
|
+
return
|
|
201
|
+
}
|
|
202
|
+
ensureDir(dirname(path))
|
|
203
|
+
writeFileSync(path, JSON.stringify(defaultHandoff(), null, 2) + '\n')
|
|
204
|
+
console.log(' .duaer/handoff.json')
|
|
205
|
+
}
|
|
206
|
+
|
|
173
207
|
function installMethod(target, opts) {
|
|
174
208
|
console.log('Installing Duaer method…')
|
|
175
209
|
copyPath(join(PKG_ROOT, '.duaer'), join(target, '.duaer'), opts)
|
|
176
210
|
console.log(' .duaer/')
|
|
177
211
|
writeDefaultPolicy(target, opts)
|
|
212
|
+
writeDefaultHandoff(target, opts)
|
|
178
213
|
|
|
179
214
|
ensureDir(join(target, '.cursor', 'skills'))
|
|
180
215
|
const skillsRoot = join(PKG_ROOT, '.cursor', 'skills')
|
|
@@ -227,7 +262,13 @@ function installOps(target, opts) {
|
|
|
227
262
|
console.log(' .cursor/rules/agents-workflow.mdc, ai-ui-copy.mdc')
|
|
228
263
|
|
|
229
264
|
ensureDir(join(target, 'docs', 'agent'))
|
|
230
|
-
for (const name of [
|
|
265
|
+
for (const name of [
|
|
266
|
+
'workflow.md',
|
|
267
|
+
'change-checklist.md',
|
|
268
|
+
'e2e-test-plan.md',
|
|
269
|
+
'branching-and-release.md',
|
|
270
|
+
'README.md',
|
|
271
|
+
]) {
|
|
231
272
|
copyPath(
|
|
232
273
|
join(PKG_ROOT, 'docs', 'agent', name),
|
|
233
274
|
join(target, 'docs', 'agent', name),
|
|
@@ -298,9 +339,10 @@ function cmdInit(opts) {
|
|
|
298
339
|
Hired.
|
|
299
340
|
|
|
300
341
|
You: describe work in Cursor (plain language).
|
|
301
|
-
Agent: runs Brief → work → accept
|
|
342
|
+
Agent: runs Brief → work → accept; uses develop + .worktree/; after merge runs handoff.
|
|
302
343
|
|
|
303
|
-
|
|
344
|
+
Update later: npx duaer-spec@latest init --here --force (review the diff)
|
|
345
|
+
Handoff: duaer handoff [--run] # restart services on develop after worktree remove
|
|
304
346
|
`)
|
|
305
347
|
}
|
|
306
348
|
|
|
@@ -590,6 +632,49 @@ Not a git merge lock.
|
|
|
590
632
|
`)
|
|
591
633
|
}
|
|
592
634
|
|
|
635
|
+
function cmdHandoff(opts) {
|
|
636
|
+
const target = resolve(opts.dir)
|
|
637
|
+
const cfg = readJson(join(target, '.duaer', 'handoff.json'), defaultHandoff())
|
|
638
|
+
const block = cfg.onWorktreeRemove || {}
|
|
639
|
+
const commands = Array.isArray(block.commands) ? block.commands.filter(Boolean) : []
|
|
640
|
+
|
|
641
|
+
console.log(`Handoff @ ${target}`)
|
|
642
|
+
console.log('(worktree → merged develop / hotfix main)\n')
|
|
643
|
+
console.log('1. Confirm request branch is merged into develop (hotfix: main + back-merge develop)')
|
|
644
|
+
console.log(`2. Stop: ${block.stop || defaultHandoff().onWorktreeRemove.stop}`)
|
|
645
|
+
console.log('3. git worktree remove .worktree/<id> && git branch -d feat|fix/<name>')
|
|
646
|
+
console.log('4. Restart from primary checkout on the merged branch:\n')
|
|
647
|
+
|
|
648
|
+
if (!commands.length) {
|
|
649
|
+
console.log(' (no commands in .duaer/handoff.json)')
|
|
650
|
+
console.log(' Add e.g. "npm run dev" under onWorktreeRemove.commands')
|
|
651
|
+
console.log(' If you started a server in the worktree, re-run that same command here.')
|
|
652
|
+
} else {
|
|
653
|
+
for (const c of commands) console.log(` $ ${c}`)
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
if (opts.run) {
|
|
657
|
+
if (!commands.length) {
|
|
658
|
+
console.log('\n--run: nothing to start (commands empty).')
|
|
659
|
+
return
|
|
660
|
+
}
|
|
661
|
+
console.log('')
|
|
662
|
+
for (const c of commands) {
|
|
663
|
+
const child = spawn(c, {
|
|
664
|
+
shell: true,
|
|
665
|
+
cwd: target,
|
|
666
|
+
detached: true,
|
|
667
|
+
stdio: 'ignore',
|
|
668
|
+
})
|
|
669
|
+
child.unref()
|
|
670
|
+
console.log(`started (detached) pid=${child.pid}: ${c}`)
|
|
671
|
+
}
|
|
672
|
+
console.log('\nServices should now be bound to the primary checkout, not .worktree/.')
|
|
673
|
+
} else if (commands.length) {
|
|
674
|
+
console.log('\nTip: duaer handoff --run # start the commands above in the background')
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
593
678
|
function main() {
|
|
594
679
|
let opts
|
|
595
680
|
try {
|
|
@@ -608,6 +693,9 @@ function main() {
|
|
|
608
693
|
case 'check':
|
|
609
694
|
cmdCheck(opts)
|
|
610
695
|
break
|
|
696
|
+
case 'handoff':
|
|
697
|
+
cmdHandoff(opts)
|
|
698
|
+
break
|
|
611
699
|
case 'job':
|
|
612
700
|
case 'status':
|
|
613
701
|
cmdJob(opts)
|
package/docs/agent/README.md
CHANGED
|
@@ -6,6 +6,7 @@ Wins over Duaer and `examples/` when they conflict.
|
|
|
6
6
|
| Doc | Description |
|
|
7
7
|
|---|---|
|
|
8
8
|
| [workflow.md](workflow.md) | Rules R1–R6, development loop, spec guidance |
|
|
9
|
+
| [branching-and-release.md](branching-and-release.md) | **Required** `main`/`develop`/`feat`/`fix` + go-live by issue type |
|
|
9
10
|
| [change-checklist.md](change-checklist.md) | Finish checklist |
|
|
10
11
|
| [e2e-test-plan.md](e2e-test-plan.md) | E2E scenario catalog template |
|
|
11
12
|
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Branching and release flows
|
|
2
|
+
|
|
3
|
+
> Part of **duaer-spec** agent ops. Precedence: [`AGENTS.md`](../../AGENTS.md) ·
|
|
4
|
+
> [workflow](workflow.md).
|
|
5
|
+
> Language: English for branch names and docs.
|
|
6
|
+
|
|
7
|
+
This is **mandatory** for repositories that adopt duaer-spec agent ops.
|
|
8
|
+
Yes: every such repo **must** have a production main branch, a development
|
|
9
|
+
integration branch, feature branches, and bugfix branches.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. Required branch model
|
|
14
|
+
|
|
15
|
+
| Branch | Role | Who merges here |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| **`main`** | Production / officially online | Only **promotion / release** (or emergency hotfix) |
|
|
18
|
+
| **`develop`** | Day-to-day integration and debugging | Finished `feat/*` and normal `fix/*` |
|
|
19
|
+
| **`feat/<name>`** | One feature / one request | → `develop` when ready to integrate |
|
|
20
|
+
| **`fix/<name>`** | One bugfix / one request | → `develop` (normal); or → `main` then `develop` (hotfix) |
|
|
21
|
+
|
|
22
|
+
### Rules
|
|
23
|
+
|
|
24
|
+
1. **Do not develop on `main` or `develop`.** Those are long-lived only.
|
|
25
|
+
2. **Every request** uses a short-lived `feat/` or `fix/` branch **and** a
|
|
26
|
+
mandatory worktree at `.worktree/<request-id>` (never commit `.worktree/`).
|
|
27
|
+
3. **Default base for new work:** updated local **`develop`**.
|
|
28
|
+
4. **Going online** means promoting `develop` → `main` (or a release PR into
|
|
29
|
+
`main`) when the user **explicitly** asks to ship / go online.
|
|
30
|
+
5. **Push** is always opt-in; never infer push from “merge” or “done”.
|
|
31
|
+
|
|
32
|
+
### Naming
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
feat/<short-description> # new capability / improvement
|
|
36
|
+
fix/<short-description> # defect
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Optional types when the project already uses them: `docs/`, `chore/`, `refactor/`,
|
|
40
|
+
`test/`, `ci/` — still branch from `develop`, merge back to `develop` first.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 2. Day-to-day development (feature or normal bug)
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
update develop
|
|
48
|
+
→ git worktree add .worktree/<id> -b feat|fix/<name> develop
|
|
49
|
+
→ work only in that worktree (Duaer job loop as needed)
|
|
50
|
+
→ merge into local develop
|
|
51
|
+
→ handoff (mandatory):
|
|
52
|
+
stop processes bound to the worktree
|
|
53
|
+
remove .worktree/<id>; delete feat|fix/<name>
|
|
54
|
+
restart services from the primary checkout on develop
|
|
55
|
+
(see .duaer/handoff.json / `duaer handoff [--run]`)
|
|
56
|
+
→ push develop only if the user asked
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Example:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
git switch develop
|
|
63
|
+
git pull --ff-only
|
|
64
|
+
mkdir -p .worktree
|
|
65
|
+
git worktree add .worktree/feat-login -b feat/login develop
|
|
66
|
+
cd .worktree/feat-login
|
|
67
|
+
# ... implement, commit ...
|
|
68
|
+
cd ../.. # primary checkout
|
|
69
|
+
git switch develop
|
|
70
|
+
git merge feat/login
|
|
71
|
+
|
|
72
|
+
# Handoff — do not skip
|
|
73
|
+
# 1) stop anything started under .worktree/feat-login
|
|
74
|
+
git worktree remove .worktree/feat-login
|
|
75
|
+
git branch -d feat/login
|
|
76
|
+
# 2) restart on develop (primary checkout)
|
|
77
|
+
duaer handoff --run
|
|
78
|
+
# or: npm run dev # if listed in .duaer/handoff.json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Worktree → develop service handoff (mandatory)
|
|
82
|
+
|
|
83
|
+
Deleting a worktree **removes that directory**. Any server started there will
|
|
84
|
+
break. Agents **must**:
|
|
85
|
+
|
|
86
|
+
1. Merge the request branch into **`develop`** (hotfix: **`main`**, then
|
|
87
|
+
back-merge **`develop`**)
|
|
88
|
+
2. **Stop** processes whose cwd is under `.worktree/<id>/`
|
|
89
|
+
3. `git worktree remove .worktree/<id>` and delete the short branch
|
|
90
|
+
4. **Restart** from the **primary checkout** on the merged long-lived branch:
|
|
91
|
+
- Read `.duaer/handoff.json` → `onWorktreeRemove.commands`
|
|
92
|
+
- Run `duaer handoff` (prints the plan) or `duaer handoff --run` (starts
|
|
93
|
+
configured commands in the background from the project root)
|
|
94
|
+
- If `commands` is empty but the agent started a server in the worktree,
|
|
95
|
+
restart the **same** command from the primary checkout on `develop`
|
|
96
|
+
- Tell the user the new service is on the merged branch, not the old worktree
|
|
97
|
+
|
|
98
|
+
Configure per project by editing `.duaer/handoff.json`, for example:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"schemaVersion": 1,
|
|
103
|
+
"onWorktreeRemove": {
|
|
104
|
+
"restartFromPrimary": true,
|
|
105
|
+
"commands": ["npm run dev"]
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 3. Go-live / online (promote to production)
|
|
113
|
+
|
|
114
|
+
Use when the user explicitly asks to **ship**, **go online**, **release**, or
|
|
115
|
+
**promote to production**.
|
|
116
|
+
|
|
117
|
+
```text
|
|
118
|
+
develop is green / accepted for release
|
|
119
|
+
→ update local main and develop
|
|
120
|
+
→ merge develop → main (or open/merge release PR main ← develop)
|
|
121
|
+
→ tag / release notes if the project uses them
|
|
122
|
+
→ push main (and tags) only if the user asked to publish
|
|
123
|
+
→ deploy per project runbook (out of scope for duaer-spec itself)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Never merge a random `feat/*` straight into `main` for a normal feature.
|
|
127
|
+
Features land on **`develop` first**, then ride a promotion to **`main`**.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 4. Flows by problem type
|
|
132
|
+
|
|
133
|
+
### A. New feature / improvement
|
|
134
|
+
|
|
135
|
+
| Step | Action |
|
|
136
|
+
|---|---|
|
|
137
|
+
| Branch | `feat/<name>` from **`develop`** |
|
|
138
|
+
| Worktree | `.worktree/<id>` (required) |
|
|
139
|
+
| Integrate | Merge → **`develop`** |
|
|
140
|
+
| Online | Later promotion **`develop` → `main`** when user asks to ship |
|
|
141
|
+
|
|
142
|
+
### B. Normal bug (not blocking production)
|
|
143
|
+
|
|
144
|
+
| Step | Action |
|
|
145
|
+
|---|---|
|
|
146
|
+
| Branch | `fix/<name>` from **`develop`** |
|
|
147
|
+
| Worktree | `.worktree/<id>` |
|
|
148
|
+
| Integrate | Merge → **`develop`** |
|
|
149
|
+
| Online | Same as features: ship when promoting `develop` → `main` |
|
|
150
|
+
|
|
151
|
+
### C. Production hotfix (must go live immediately)
|
|
152
|
+
|
|
153
|
+
| Step | Action |
|
|
154
|
+
|---|---|
|
|
155
|
+
| Branch | `fix/<name>` from **`main`** |
|
|
156
|
+
| Worktree | `.worktree/<id>` |
|
|
157
|
+
| Online | Merge → **`main`** first (after validation) |
|
|
158
|
+
| Backport | Merge the same fix into **`develop`** (or merge `main` into `develop`) so develop does not regress |
|
|
159
|
+
| Cleanup | Remove worktree; delete `fix/<name>` |
|
|
160
|
+
| Push | Only if the user asked to publish |
|
|
161
|
+
|
|
162
|
+
### D. Docs / chore / CI-only
|
|
163
|
+
|
|
164
|
+
Same as **A**: from `develop`, merge to `develop`. Promote with the next
|
|
165
|
+
`develop` → `main` ship unless the user asks for an urgent docs-only release.
|
|
166
|
+
|
|
167
|
+
### E. Linked GitHub issue
|
|
168
|
+
|
|
169
|
+
Still: verify the claim (R5), then use **A/B/C** by issue type. Closing the
|
|
170
|
+
issue does not mean push or promote to `main`.
|
|
171
|
+
|
|
172
|
+
### F. Linked GitHub PR
|
|
173
|
+
|
|
174
|
+
Judge principle (R6). Merge that PR into the correct target (`develop` for
|
|
175
|
+
normal work, `main` only if it is already a production/hotfix PR). Completeness
|
|
176
|
+
follow-up stays on `develop` unless it is a landing blocker.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 5. What agents must not do
|
|
181
|
+
|
|
182
|
+
- Develop or commit directly on `main` or `develop`
|
|
183
|
+
- Skip `.worktree/` isolation
|
|
184
|
+
- Merge feature work only to `main` and leave `develop` behind
|
|
185
|
+
- Push, tag, or deploy without an explicit user ask for that action
|
|
186
|
+
- Leave a merged worktree on disk
|
|
187
|
+
- Assume a server started inside a worktree still runs after `worktree remove`
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 6. Primary checkout role
|
|
192
|
+
|
|
193
|
+
The primary clone is for:
|
|
194
|
+
|
|
195
|
+
- updating and merging **`develop`** (and **`main`** on promote/hotfix)
|
|
196
|
+
- creating/removing `.worktree/<id>` entries
|
|
197
|
+
|
|
198
|
+
All implementation edits happen inside the request worktree.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Related
|
|
203
|
+
|
|
204
|
+
- [workflow.md](workflow.md) — R4 and development loop
|
|
205
|
+
- [change-checklist.md](change-checklist.md) — finish checklist
|
|
206
|
+
- [baseline.md](../baseline.md) — frozen: `develop` + `main`
|
|
207
|
+
- [ADOPT.md](../../ADOPT.md) — install into another repo
|
|
@@ -43,11 +43,12 @@ See [R6](workflow.md#r6--merge-a-linked-pull-request-whose-principle-is-sound-th
|
|
|
43
43
|
## 1. Request Start
|
|
44
44
|
|
|
45
45
|
- [ ] Existing uncommitted work is identified and preserved.
|
|
46
|
-
- [ ] `origin/
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
- [ ] `origin/develop` fetched; local `develop` fast-forwarded when clean
|
|
47
|
+
(hotfix: `main`).
|
|
48
|
+
- [ ] Dedicated `feat/` or `fix/` branch and worktree under
|
|
49
|
+
**`.worktree/<request-id>`** (mandatory; never commit `.worktree/`).
|
|
49
50
|
- [ ] Shared toolchains/caches reused where safe; mutable state stays local.
|
|
50
|
-
- [ ] Current branch is not `main` before implementation begins.
|
|
51
|
+
- [ ] Current branch is not `main` or `develop` before implementation begins.
|
|
51
52
|
|
|
52
53
|
---
|
|
53
54
|
|
|
@@ -95,10 +96,13 @@ See [spec update guidance](workflow.md#3-spec-update-guidance).
|
|
|
95
96
|
## 6. Merge / PR
|
|
96
97
|
|
|
97
98
|
- [ ] Active job handoff considered by the **agent** (do not require the human to run CLI for routine work).
|
|
98
|
-
- [ ] Branch refreshed against latest `main
|
|
99
|
-
- [ ] Merged into local `
|
|
99
|
+
- [ ] Branch refreshed against latest `develop` (hotfix: `main`).
|
|
100
|
+
- [ ] Merged into local `develop` (hotfix: `main`, then back-merge `develop`).
|
|
101
|
+
- [ ] Worktree services stopped; worktree removed; short branch deleted;
|
|
102
|
+
**handoff** restart on `develop` (`duaer handoff` / `.duaer/handoff.json`).
|
|
100
103
|
- [ ] Only this request's logical changes included.
|
|
101
104
|
- [ ] Push performed only if the user explicitly asked for this request.
|
|
105
|
+
- [ ] `develop` → `main` promotion only if the user asked to go online.
|
|
102
106
|
|
|
103
107
|
---
|
|
104
108
|
|
|
@@ -117,15 +121,16 @@ See [spec update guidance](workflow.md#3-spec-update-guidance).
|
|
|
117
121
|
|
|
118
122
|
| # | Gate | Source |
|
|
119
123
|
|---|---|---|
|
|
120
|
-
| 1 | Branch + worktree from up-to-date `main` | [R4](workflow.md#r4--request-branch--worktree--merge-gate) |
|
|
124
|
+
| 1 | Branch + `.worktree/` from up-to-date `develop` (hotfix: `main`) | [R4](workflow.md#r4--request-branch--worktree--merge-gate) · [branching](branching-and-release.md) |
|
|
121
125
|
| 2 | Change implements the planned work | [Development loop](workflow.md#2-development-loop) |
|
|
122
126
|
| 3 | Impacted specs updated | [R1](workflow.md#r1--spec-first--spec-sync) |
|
|
123
127
|
| 4 | E2E docs updated or confirmed unnecessary | [R3](workflow.md#r3--e2e-coverage-doc) |
|
|
124
128
|
| 5 | Targeted validation done or waived with reason | Development loop |
|
|
125
|
-
| 5a | Active job handoff
|
|
129
|
+
| 5a | Active job handoff by the agent (coach/strict) | Delivery OS — not a git lock |
|
|
126
130
|
| 6 | Conventional commits | [R2](workflow.md#r2--commit-per-change) |
|
|
127
|
-
| 7 | No secrets
|
|
128
|
-
| 8 | Merged
|
|
131
|
+
| 7 | No secrets, local data, or `.worktree/` | [§4](workflow.md#4-what-never-to-commit) |
|
|
132
|
+
| 8 | Merged to `develop` (hotfix: `main` + back-merge); worktree cleaned | [R4](workflow.md#r4--request-branch--worktree--merge-gate) |
|
|
133
|
+
| 8a | `develop` → `main` only if user asked to go online | [branching-and-release](branching-and-release.md) |
|
|
129
134
|
| 9 | Linked issue: verified, commented, closed when conclusive | [R5](workflow.md#r5--verify-linked-github-issues-before-work-then-reply-and-close) |
|
|
130
135
|
| 10 | Linked PR: principle reviewed; merged when sound; follow-up after | [R6](workflow.md#r6--merge-a-linked-pull-request-whose-principle-is-sound-then-follow-up) |
|
|
131
136
|
|
|
@@ -31,6 +31,10 @@ the table for their app.
|
|
|
31
31
|
| E2E-004 | Default `coach`: unfinished job — agent must not claim done | manual |
|
|
32
32
|
| E2E-005 | Converge stamps `accepted`; agent reports ready for review | manual |
|
|
33
33
|
| E2E-006 | `duaer-do` skill describes agent-triggered loop | manual |
|
|
34
|
+
| E2E-007 | Request worktrees use `.worktree/<id>`; `.worktree/` gitignored | manual |
|
|
35
|
+
| E2E-008 | Docs require main+develop+feat+fix and typed go-live flows | manual |
|
|
36
|
+
| E2E-009 | After merge, handoff restarts services on develop (`duaer handoff`) | manual |
|
|
37
|
+
| E2E-010 | ADOPT documents `init --force` update path for existing installs | manual |
|
|
34
38
|
|
|
35
39
|
## Traceability
|
|
36
40
|
|
|
@@ -42,3 +46,7 @@ the table for their app.
|
|
|
42
46
|
| E2E-004 | policy coach | Handoff etiquette |
|
|
43
47
|
| E2E-005 | `delivery.json` | Accept stamp |
|
|
44
48
|
| E2E-006 | `duaer-do` | Internal playbook |
|
|
49
|
+
| E2E-007 | `.worktree/` + `.gitignore` | Mandatory isolation |
|
|
50
|
+
| E2E-008 | `branching-and-release.md` | Branch + release matrix |
|
|
51
|
+
| E2E-009 | `.duaer/handoff.json` / `duaer handoff` | Service handoff |
|
|
52
|
+
| E2E-010 | `ADOPT.md` Updating | Existing installs |
|
package/docs/agent/workflow.md
CHANGED
|
@@ -41,27 +41,29 @@ handling. They cannot be relaxed without explicit human override.
|
|
|
41
41
|
|
|
42
42
|
### R4 — Request branch + worktree + merge gate
|
|
43
43
|
|
|
44
|
-
> **Every new request starts from `main` in a dedicated
|
|
45
|
-
>
|
|
44
|
+
> **Every new request starts from `develop` (hotfix: `main`) in a dedicated
|
|
45
|
+
> `.worktree/<id>` on a `feat/*` or `fix/*` branch, and finishes after merge
|
|
46
|
+
> into that long-lived target. Going online is a separate `develop` → `main`
|
|
47
|
+
> promotion when the user asks to ship.**
|
|
46
48
|
|
|
47
49
|
- Before editing: preserve existing uncommitted work; fetch and fast-forward
|
|
48
|
-
local
|
|
49
|
-
at **`.worktree/<request-id
|
|
50
|
+
local **`develop`** when clean (hotfix: **`main`**); create a new request
|
|
51
|
+
branch and worktree at **`.worktree/<request-id>`**. Worktrees are
|
|
50
52
|
**mandatory**. Never stash or overwrite another agent's work merely to start.
|
|
51
|
-
- Name branches
|
|
52
|
-
- Do not implement in the primary checkout or
|
|
53
|
+
- Name branches `feat/<short-description>` or `fix/<short-description>`.
|
|
54
|
+
- Do not implement in the primary checkout or on `main` / `develop`.
|
|
53
55
|
- Keep `.worktree/` gitignored — never commit request worktrees.
|
|
54
|
-
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
-
|
|
59
|
-
request.
|
|
56
|
+
- After validation: merge into local **`develop`** (hotfix: **`main`**, then
|
|
57
|
+
back-merge **`develop`**), stop worktree-bound services, remove the worktree,
|
|
58
|
+
delete the short branch.
|
|
59
|
+
- Push only when the user explicitly requests remote publishing.
|
|
60
|
+
- Promote **`develop` → `main`** only when the user explicitly asks to go online.
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
under `examples/` do not change this repo's default.
|
|
62
|
+
Full matrix by issue type:
|
|
63
|
+
[branching-and-release](branching-and-release.md).
|
|
64
64
|
|
|
65
|
+
**duaer-spec itself** requires `main` + `develop` + `feat/*` + `fix/*`.
|
|
66
|
+
Example overlays under `examples/` do not change this.
|
|
65
67
|
### R5 — Verify linked GitHub issues before work, then reply and close
|
|
66
68
|
|
|
67
69
|
> **A linked GitHub issue is not a task until the reported problem is shown to
|
|
@@ -84,16 +86,18 @@ unrelated pushes.
|
|
|
84
86
|
## 2. Development Loop
|
|
85
87
|
|
|
86
88
|
1. **Intake** — If an issue or PR is linked, complete R5 / R6 first.
|
|
87
|
-
2. **Isolate** — Update `main
|
|
89
|
+
2. **Isolate** — Update `develop` (hotfix: `main`), create `feat|fix` + `.worktree/` (R4).
|
|
88
90
|
3. **Orient** — Read baseline, relevant specs, and Duaer memory when present.
|
|
89
|
-
4. **Specify (when using Duaer)** —
|
|
91
|
+
4. **Specify (when using Duaer)** — Agent runs Brief → work → accept autonomously.
|
|
90
92
|
5. **Implement** — Smallest coherent change; update specs alongside (R1).
|
|
91
93
|
6. **Verify** — Targeted checks; E2E runs only if the user asks (except fork
|
|
92
94
|
landing rules in `AGENTS.md`).
|
|
93
95
|
7. **Commit** — One logical change per commit (R2).
|
|
94
|
-
8. **Merge & clean** —
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
8. **Merge & clean** — Merge to `develop` (hotfix: `main` + back-merge), stop
|
|
97
|
+
worktree services, remove worktree (R4).
|
|
98
|
+
9. **Go online** — Only if asked: promote `develop` → `main`
|
|
99
|
+
([branching-and-release](branching-and-release.md)).
|
|
100
|
+
10. **Report** — Use the Final Report section in `AGENTS.md`.
|
|
97
101
|
---
|
|
98
102
|
|
|
99
103
|
## 3. Spec Update Guidance
|
|
@@ -114,6 +118,7 @@ when changing duaer-spec's own agent-ops contract.
|
|
|
114
118
|
|
|
115
119
|
- Secrets, tokens, credentials, private keys
|
|
116
120
|
- Local databases, caches, build artifacts, `node_modules/`
|
|
121
|
+
- `.worktree/` (mandatory request worktrees)
|
|
117
122
|
- Machine-specific paths or environment files with secrets
|
|
118
123
|
- Unrelated changes from another request or agent
|
|
119
124
|
|
package/docs/baseline.md
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
# Baseline (project-specific)
|
|
2
2
|
|
|
3
3
|
Frozen decisions for the adopting project: language, stack, architecture
|
|
4
|
-
boundaries, and
|
|
4
|
+
boundaries, and branch model.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
no application runtime.
|
|
6
|
+
## Branch model (mandatory)
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
| Branch | Role |
|
|
9
|
+
|---|---|
|
|
10
|
+
| `main` | Production / officially online |
|
|
11
|
+
| `develop` | Day-to-day integration |
|
|
12
|
+
| `feat/<name>` | Features |
|
|
13
|
+
| `fix/<name>` | Bug fixes |
|
|
14
|
+
|
|
15
|
+
See [branching-and-release](agent/branching-and-release.md).
|
|
16
|
+
|
|
17
|
+
**duaer-spec itself:** English docs and commits; integrate on **`develop`**;
|
|
18
|
+
promote to **`main`** when shipping; no application runtime.
|
|
19
|
+
|
|
20
|
+
When you copy agent ops into another repository, keep this branch model unless
|
|
21
|
+
the project explicitly documents a justified exception in an ADR (not
|
|
22
|
+
recommended).
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "duaer-spec",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Digital employees
|
|
3
|
+
"version": "0.6.1",
|
|
4
|
+
"description": "Digital employees: autonomous delivery; main/develop/feat/fix; worktree handoff",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"duaer": "bin/duaer.mjs",
|