duaer-spec 0.6.0 → 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 +2 -1
- package/.cursor/rules/duaer-spec.mdc +4 -0
- package/.duaer/handoff.json +9 -0
- package/ADOPT.md +35 -14
- package/AGENTS.md +5 -2
- package/CHANGELOG.md +18 -19
- package/README.md +12 -1
- package/bin/duaer.mjs +88 -6
- package/docs/agent/branching-and-release.md +39 -8
- package/docs/agent/change-checklist.md +2 -1
- package/docs/agent/e2e-test-plan.md +4 -0
- package/package.json +2 -2
|
@@ -42,7 +42,8 @@ cd .worktree/<request-id>
|
|
|
42
42
|
- One logical change per commit; leave the worktree clean
|
|
43
43
|
- User/protocol-visible changes update E2E scenario docs
|
|
44
44
|
- Merge into **`develop`** when done (hotfix: **`main`**, then back-merge **`develop`**)
|
|
45
|
-
-
|
|
45
|
+
- **Handoff (mandatory):** stop worktree-bound processes → remove `.worktree/<id>` →
|
|
46
|
+
restart from primary checkout on `develop` (`duaer handoff [--run]`, `.duaer/handoff.json`)
|
|
46
47
|
- Push only when the user explicitly asks
|
|
47
48
|
- Promote **`develop` → `main`** only when the user asks to go online
|
|
48
49
|
|
|
@@ -27,6 +27,10 @@ For new behavior, fixes, refactors that change product behavior, or architecture
|
|
|
27
27
|
4. Do **not** dump a methodology tutorial unless they ask how Duaer works.
|
|
28
28
|
5. Merge to **`develop`** when done (hotfix: **`main`**, then back-merge
|
|
29
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.
|
|
30
34
|
See `docs/agent/branching-and-release.md`.
|
|
31
35
|
|
|
32
36
|
## Handoff
|
|
@@ -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,26 +7,51 @@ 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.6.
|
|
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
|
-
Ensure the repo has **`main`** and **`develop`**.
|
|
19
|
-
`feat/*` / `fix/*` for work. See
|
|
18
|
+
Ensure the repo has **`main`** and **`develop`**. See
|
|
20
19
|
[`docs/agent/branching-and-release.md`](docs/agent/branching-and-release.md).
|
|
21
20
|
|
|
22
|
-
After that: talk to the agent in plain language.
|
|
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.
|
|
23
49
|
|
|
24
50
|
## What gets installed
|
|
25
51
|
|
|
26
|
-
- Always-on
|
|
27
|
-
-
|
|
52
|
+
- Always-on autonomous job loop
|
|
53
|
+
- `.duaer/handoff.json` — restart services on **develop** after worktree remove
|
|
28
54
|
- Agent ops: `AGENTS.md`, branching/release docs, mandatory `.worktree/`
|
|
29
|
-
- Optional step skills for large jobs (agent-only)
|
|
30
55
|
|
|
31
56
|
## Branch model (mandatory)
|
|
32
57
|
|
|
@@ -35,15 +60,11 @@ After that: talk to the agent in plain language. Do not teach them `/duaer-*`.
|
|
|
35
60
|
| `main` | Production / online |
|
|
36
61
|
| `develop` | Day-to-day integration |
|
|
37
62
|
| `feat/<name>` | Features → `develop` |
|
|
38
|
-
| `fix/<name>` | Fixes → `develop` (hotfix via `main`
|
|
63
|
+
| `fix/<name>` | Fixes → `develop` (hotfix via `main`) |
|
|
39
64
|
|
|
40
|
-
|
|
65
|
+
After merge: **`duaer handoff [--run]`** (stop worktree services → restart on develop).
|
|
41
66
|
|
|
42
67
|
## Precedence
|
|
43
68
|
|
|
44
69
|
1. `AGENTS.md` — how employees operate
|
|
45
70
|
2. `DUADER.md` / `.duaer/` — how jobs are briefed
|
|
46
|
-
|
|
47
|
-
## Updates
|
|
48
|
-
|
|
49
|
-
`duaer init --force` (review the diff) or pin a tag.
|
package/AGENTS.md
CHANGED
|
@@ -251,7 +251,9 @@ git worktree prune
|
|
|
251
251
|
* Use `git branch -d` (not `-D`)
|
|
252
252
|
* Delete only your own worktree and branch
|
|
253
253
|
* Never commit `.worktree/` (ignored)
|
|
254
|
-
* Stop worktree-bound services before remove; restart from primary
|
|
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))
|
|
255
257
|
|
|
256
258
|
## Development Workflow
|
|
257
259
|
|
|
@@ -267,7 +269,8 @@ git worktree prune
|
|
|
267
269
|
10. Commit each logical change
|
|
268
270
|
11. Refresh against latest **`develop`** (or **`main`** for hotfix)
|
|
269
271
|
12. Merge into local **`develop`** (hotfix: **`main`**, then back-merge to **`develop`**)
|
|
270
|
-
13. Stop worktree services; remove worktree; delete short branch
|
|
272
|
+
13. Stop worktree services; remove worktree; delete short branch; **handoff**
|
|
273
|
+
restart on `develop` (`duaer handoff [--run]` / `.duaer/handoff.json`)
|
|
271
274
|
14. Push only when explicitly requested
|
|
272
275
|
15. Promote **`develop` → `main`** only when the user explicitly asks to go online
|
|
273
276
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,42 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.1 — 2026-09-15
|
|
4
|
+
|
|
5
|
+
### Worktree → develop service handoff
|
|
6
|
+
|
|
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
|
+
|
|
3
13
|
## 0.6.0 — 2026-09-15
|
|
4
14
|
|
|
5
15
|
### Mandatory branch model + release flows
|
|
6
16
|
|
|
7
|
-
- Required
|
|
8
|
-
|
|
9
|
-
- New doc: [`docs/agent/branching-and-release.md`](docs/agent/branching-and-release.md)
|
|
10
|
-
— day-to-day, go-live, feature / bug / hotfix / issue / PR flows
|
|
11
|
-
- Agent ops merge target is **`develop`**; promote to **`main`** only when
|
|
12
|
-
shipping; hotfixes from `main` then back-merge `develop`
|
|
13
|
-
- Worktree cleanup includes stopping services and restarting on `develop` if needed
|
|
14
|
-
- `duaer init` default `--branch` is `develop`
|
|
17
|
+
- Required: `main` / `develop` / `feat/*` / `fix/*`
|
|
18
|
+
- [`docs/agent/branching-and-release.md`](docs/agent/branching-and-release.md)
|
|
15
19
|
|
|
16
20
|
## 0.5.1 — 2026-09-15
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- Request worktrees **must** live under **`.worktree/<request-id>`**
|
|
21
|
-
- `.worktree/` is gitignored; `duaer init` ensures the ignore rule
|
|
22
|
+
- Mandatory `.worktree/` (gitignored)
|
|
22
23
|
|
|
23
24
|
## 0.5.0 — 2026-09-15
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- Humans ask; agents run Brief → work → accept without slash-command ops
|
|
26
|
+
- Autonomous digital employee (ask, don’t operate phases)
|
|
28
27
|
|
|
29
28
|
## 0.4.0 — 2026-09-15
|
|
30
29
|
|
|
31
|
-
- `/duaer-do`
|
|
30
|
+
- Everyday `/duaer-do` path (later agent-internal)
|
|
32
31
|
|
|
33
32
|
## 0.3.0 — 2026-09-15
|
|
34
33
|
|
|
35
|
-
- Job handoff policy
|
|
34
|
+
- Job handoff policy
|
|
36
35
|
|
|
37
36
|
## 0.2.0 — 2026-09-15
|
|
38
37
|
|
|
39
|
-
- `delivery.json`
|
|
38
|
+
- `delivery.json`
|
|
40
39
|
|
|
41
40
|
## 0.1.1 — 2026-09-15
|
|
42
41
|
|
|
@@ -44,4 +43,4 @@
|
|
|
44
43
|
|
|
45
44
|
## 0.1.0 — 2026-09-15
|
|
46
45
|
|
|
47
|
-
- First public
|
|
46
|
+
- First public release
|
package/README.md
CHANGED
|
@@ -38,10 +38,21 @@ everyday human UI.
|
|
|
38
38
|
Go-live and flows by issue type:
|
|
39
39
|
[`docs/agent/branching-and-release.md`](docs/agent/branching-and-release.md).
|
|
40
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
|
+
|
|
41
52
|
## Optional
|
|
42
53
|
|
|
43
54
|
```bash
|
|
44
|
-
npx duaer-spec@0.6.
|
|
55
|
+
npx duaer-spec@0.6.1 init --here --method
|
|
45
56
|
```
|
|
46
57
|
|
|
47
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
40
|
Init: --all (default) | --method | --ops | --force | --branch <n> (default: develop) | --here
|
|
39
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
|
|
45
|
+
|
|
40
46
|
Example:
|
|
41
47
|
npx duaer-spec init --here
|
|
48
|
+
duaer handoff --run
|
|
42
49
|
`
|
|
43
50
|
|
|
44
51
|
function parseArgs(argv) {
|
|
@@ -55,6 +62,7 @@ function parseArgs(argv) {
|
|
|
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')
|
|
@@ -304,9 +339,10 @@ function cmdInit(opts) {
|
|
|
304
339
|
Hired.
|
|
305
340
|
|
|
306
341
|
You: describe work in Cursor (plain language).
|
|
307
|
-
Agent: runs Brief → work → accept
|
|
342
|
+
Agent: runs Brief → work → accept; uses develop + .worktree/; after merge runs handoff.
|
|
308
343
|
|
|
309
|
-
|
|
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
|
|
310
346
|
`)
|
|
311
347
|
}
|
|
312
348
|
|
|
@@ -596,6 +632,49 @@ Not a git merge lock.
|
|
|
596
632
|
`)
|
|
597
633
|
}
|
|
598
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
|
+
|
|
599
678
|
function main() {
|
|
600
679
|
let opts
|
|
601
680
|
try {
|
|
@@ -614,6 +693,9 @@ function main() {
|
|
|
614
693
|
case 'check':
|
|
615
694
|
cmdCheck(opts)
|
|
616
695
|
break
|
|
696
|
+
case 'handoff':
|
|
697
|
+
cmdHandoff(opts)
|
|
698
|
+
break
|
|
617
699
|
case 'job':
|
|
618
700
|
case 'status':
|
|
619
701
|
cmdJob(opts)
|
|
@@ -48,9 +48,11 @@ update develop
|
|
|
48
48
|
→ git worktree add .worktree/<id> -b feat|fix/<name> develop
|
|
49
49
|
→ work only in that worktree (Duaer job loop as needed)
|
|
50
50
|
→ merge into local develop
|
|
51
|
-
→
|
|
52
|
-
|
|
53
|
-
|
|
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]`)
|
|
54
56
|
→ push develop only if the user asked
|
|
55
57
|
```
|
|
56
58
|
|
|
@@ -66,15 +68,44 @@ cd .worktree/feat-login
|
|
|
66
68
|
cd ../.. # primary checkout
|
|
67
69
|
git switch develop
|
|
68
70
|
git merge feat/login
|
|
69
|
-
|
|
71
|
+
|
|
72
|
+
# Handoff — do not skip
|
|
73
|
+
# 1) stop anything started under .worktree/feat-login
|
|
70
74
|
git worktree remove .worktree/feat-login
|
|
71
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
|
|
72
79
|
```
|
|
73
80
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
+
```
|
|
78
109
|
|
|
79
110
|
---
|
|
80
111
|
|
|
@@ -98,7 +98,8 @@ See [spec update guidance](workflow.md#3-spec-update-guidance).
|
|
|
98
98
|
- [ ] Active job handoff considered by the **agent** (do not require the human to run CLI for routine work).
|
|
99
99
|
- [ ] Branch refreshed against latest `develop` (hotfix: `main`).
|
|
100
100
|
- [ ] Merged into local `develop` (hotfix: `main`, then back-merge `develop`).
|
|
101
|
-
- [ ] Worktree services stopped; worktree removed; short branch deleted
|
|
101
|
+
- [ ] Worktree services stopped; worktree removed; short branch deleted;
|
|
102
|
+
**handoff** restart on `develop` (`duaer handoff` / `.duaer/handoff.json`).
|
|
102
103
|
- [ ] Only this request's logical changes included.
|
|
103
104
|
- [ ] Push performed only if the user explicitly asked for this request.
|
|
104
105
|
- [ ] `develop` → `main` promotion only if the user asked to go online.
|
|
@@ -33,6 +33,8 @@ the table for their app.
|
|
|
33
33
|
| E2E-006 | `duaer-do` skill describes agent-triggered loop | manual |
|
|
34
34
|
| E2E-007 | Request worktrees use `.worktree/<id>`; `.worktree/` gitignored | manual |
|
|
35
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 |
|
|
36
38
|
|
|
37
39
|
## Traceability
|
|
38
40
|
|
|
@@ -46,3 +48,5 @@ the table for their app.
|
|
|
46
48
|
| E2E-006 | `duaer-do` | Internal playbook |
|
|
47
49
|
| E2E-007 | `.worktree/` + `.gitignore` | Mandatory isolation |
|
|
48
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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "duaer-spec",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"description": "Digital employees: autonomous
|
|
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",
|