duaer-spec 0.8.0 → 0.9.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/ADOPT.md +9 -1
- package/AGENTS.md +4 -2
- package/CHANGELOG.md +12 -0
- package/CLAUDE.md +7 -1
- package/DUADER.md +7 -3
- package/GEMINI.md +9 -0
- package/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/bin/duaer.mjs +148 -1
- package/docs/agent/e2e-test-plan.md +2 -0
- package/package.json +11 -3
package/ADOPT.md
CHANGED
|
@@ -32,7 +32,9 @@ npx duaer-spec init --here --ops
|
|
|
32
32
|
npx duaer-spec update --method # rare; usually omit
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
Works with **Cursor**, **Claude Code**,
|
|
35
|
+
Works with **Cursor**, **Claude Code**, **Codex**, **GitHub Copilot**,
|
|
36
|
+
**Windsurf / Devin**, **Cline**, **Continue**, **Gemini CLI**, and **Aider**
|
|
37
|
+
(adapters installed by default).
|
|
36
38
|
|
|
37
39
|
## What you get
|
|
38
40
|
|
|
@@ -40,6 +42,12 @@ Works with **Cursor**, **Claude Code**, and **Codex** (all hosts installed by de
|
|
|
40
42
|
- Cursor: `.cursor/rules` + `.cursor/skills`
|
|
41
43
|
- Claude Code: `CLAUDE.md` + `.claude/rules` + `.claude/skills`
|
|
42
44
|
- Codex: `AGENTS.md` + `.agents/skills`
|
|
45
|
+
- Copilot: `.github/copilot-instructions.md`
|
|
46
|
+
- Windsurf / Devin: `.windsurf/rules`, `.devin/rules`
|
|
47
|
+
- Cline: `.clinerules/`
|
|
48
|
+
- Continue: `.continue/rules/`
|
|
49
|
+
- Gemini CLI: `GEMINI.md`
|
|
50
|
+
- Aider: `.aider.conf.yml` → reads `AGENTS.md`
|
|
43
51
|
- `.duaer/handoff.json` + `duaer handoff` after worktree remove
|
|
44
52
|
- Agent ops: `main` / `develop` / `feat` / `fix` + `.worktree/`
|
|
45
53
|
|
package/AGENTS.md
CHANGED
|
@@ -27,10 +27,12 @@ flags.
|
|
|
27
27
|
|
|
28
28
|
1. Isolate: `feat|fix/<name>` + `.worktree/feat-<name>/` (or `fix-…`); never
|
|
29
29
|
reuse the Brief folder name as the worktree id.
|
|
30
|
-
2. Follow the `duaer-do` skill under the host skill root:
|
|
31
|
-
- Codex: `.agents/skills/duaer-do/SKILL.md`
|
|
30
|
+
2. Follow the `duaer-do` skill under the host skill root (when the host has skills):
|
|
31
|
+
- Codex / shared: `.agents/skills/duaer-do/SKILL.md`
|
|
32
32
|
- Cursor: `.cursor/skills/duaer-do/SKILL.md`
|
|
33
33
|
- Claude Code: `.claude/skills/duaer-do/SKILL.md`
|
|
34
|
+
- Copilot / Windsurf / Cline / Continue / Gemini / Aider: follow this section
|
|
35
|
+
and the host adapter files installed by `duaer init`
|
|
34
36
|
3. Briefs live in `.duaer/specs/<nnn-slug>/`. Method notes: [`DUADER.md`](DUADER.md).
|
|
35
37
|
4. One handoff line; never claim done unless `delivery.json` is `accepted`.
|
|
36
38
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.0 — 2026-09-15
|
|
4
|
+
|
|
5
|
+
### More common agent hosts
|
|
6
|
+
|
|
7
|
+
- GitHub Copilot: `.github/copilot-instructions.md`
|
|
8
|
+
- Windsurf + Devin: `.windsurf/rules/`, `.devin/rules/`
|
|
9
|
+
- Cline: `.clinerules/`
|
|
10
|
+
- Continue: `.continue/rules/`
|
|
11
|
+
- Gemini CLI: `GEMINI.md`
|
|
12
|
+
- Aider: `.aider.conf.yml` (reads `AGENTS.md`)
|
|
13
|
+
- Cursor / Claude Code / Codex unchanged
|
|
14
|
+
|
|
3
15
|
## 0.8.0 — 2026-09-15
|
|
4
16
|
|
|
5
17
|
### Codex host
|
package/CLAUDE.md
CHANGED
|
@@ -13,11 +13,17 @@ This repository uses **duaer-spec**: coding agents are digital employees.
|
|
|
13
13
|
|
|
14
14
|
## Layout
|
|
15
15
|
|
|
16
|
-
| Host | Always-on | Skills |
|
|
16
|
+
| Host | Always-on | Skills / notes |
|
|
17
17
|
|---|---|---|
|
|
18
18
|
| Cursor | `.cursor/rules/` | `.cursor/skills/` |
|
|
19
19
|
| Claude Code | `CLAUDE.md` + `.claude/rules/` | `.claude/skills/` |
|
|
20
20
|
| Codex | `AGENTS.md` | `.agents/skills/` |
|
|
21
|
+
| Copilot | `.github/copilot-instructions.md` | also reads `AGENTS.md` |
|
|
22
|
+
| Windsurf / Devin | `.windsurf/rules/`, `.devin/rules/` | — |
|
|
23
|
+
| Cline | `.clinerules/` | — |
|
|
24
|
+
| Continue | `.continue/rules/` | — |
|
|
25
|
+
| Gemini CLI | `GEMINI.md` | — |
|
|
26
|
+
| Aider | `.aider.conf.yml` | reads `AGENTS.md` |
|
|
21
27
|
|
|
22
28
|
Installed by `npx duaer-spec init --here` / `update`.
|
|
23
29
|
|
package/DUADER.md
CHANGED
|
@@ -38,9 +38,13 @@ Humans need not configure it for everyday use.
|
|
|
38
38
|
.duaer/active-job.json
|
|
39
39
|
.duaer/specs/<nnn-slug>/ # Brief (≠ worktree folder name)
|
|
40
40
|
spec.md | tasks.md | delivery.json
|
|
41
|
-
.cursor/rules|skills/ # Cursor
|
|
42
|
-
.claude/rules|skills/ + CLAUDE.md # Claude Code
|
|
43
|
-
.agents/skills/ + AGENTS.md # Codex
|
|
41
|
+
.cursor/rules|skills/ # Cursor
|
|
42
|
+
.claude/rules|skills/ + CLAUDE.md # Claude Code
|
|
43
|
+
.agents/skills/ + AGENTS.md # Codex (+ shared skills)
|
|
44
|
+
.github/copilot-instructions.md # Copilot
|
|
45
|
+
.windsurf/rules/ + .devin/rules/ # Windsurf / Devin
|
|
46
|
+
.clinerules/ + .continue/rules/ # Cline / Continue
|
|
47
|
+
GEMINI.md + .aider.conf.yml # Gemini / Aider
|
|
44
48
|
```
|
|
45
49
|
|
|
46
50
|
Worktree and Brief are different layers. Prefer
|
package/GEMINI.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# GEMINI.md — duaer-spec
|
|
2
|
+
|
|
3
|
+
This project uses **duaer-spec**: coding agents are digital employees.
|
|
4
|
+
|
|
5
|
+
**Precedence:** `AGENTS.md` (ops) wins over `DUADER.md` / `.duaer/` (method).
|
|
6
|
+
|
|
7
|
+
- Follow `AGENTS.md` § Autonomous job loop
|
|
8
|
+
- Job skill (when available): `.agents/skills/duaer-do/SKILL.md`
|
|
9
|
+
- Branches / worktrees: `docs/agent/branching-and-release.md`
|
package/README.md
CHANGED
|
@@ -19,9 +19,9 @@ npx duaer-spec init --here
|
|
|
19
19
|
npx duaer-spec update
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
Then use **Cursor**, **Claude Code**, or **
|
|
22
|
+
Then use **Cursor**, **Claude Code**, **Codex**, **Copilot**, **Windsurf**, **Cline**, **Continue**, **Gemini**, or **Aider** — describe what you want.
|
|
23
23
|
|
|
24
|
-
Install writes
|
|
24
|
+
Install writes host adapters for each (see [`ADOPT.md`](ADOPT.md)).
|
|
25
25
|
|
|
26
26
|
中文说明:[`README.zh-CN.md`](README.zh-CN.md)
|
|
27
27
|
|
package/README.zh-CN.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
**Duaer** 把 AI 编程助手变成**数字员工**:你用自然语言提需求,它自己跑 Spec → 实现 → 验收;只有交接干净才算完成。
|
|
4
4
|
|
|
5
|
-
你**不用**操作流程。装一次之后,在 **Cursor
|
|
5
|
+
你**不用**操作流程。装一次之后,在 **Cursor** / **Claude Code** / **Codex** / **Copilot** / **Windsurf** / **Cline** / **Continue** / **Gemini** / **Aider** 里说话即可。
|
|
6
6
|
|
|
7
|
-
`init` / `update`
|
|
7
|
+
`init` / `update` 会写入各宿主适配文件(详见 [`ADOPT.md`](ADOPT.md))。
|
|
8
8
|
|
|
9
9
|
## 安装
|
|
10
10
|
|
package/bin/duaer.mjs
CHANGED
|
@@ -284,6 +284,144 @@ function installCodexMethod(target, opts) {
|
|
|
284
284
|
)
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
+
function stripRuleComment(md) {
|
|
288
|
+
return md.replace(/^<!--[\s\S]*?-->\s*/, '').trim()
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function withYamlFrontmatter(body, lines) {
|
|
292
|
+
return `---\n${lines.join('\n')}\n---\n\n${stripRuleComment(body)}\n`
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function loadPackagedRule(name) {
|
|
296
|
+
const claudePath = join(PKG_ROOT, '.claude', 'rules', name)
|
|
297
|
+
if (existsSync(claudePath)) return readFileSync(claudePath, 'utf8')
|
|
298
|
+
const mdc = name.replace(/\.md$/, '.mdc')
|
|
299
|
+
return cursorRuleToClaude(readFileSync(join(PKG_ROOT, '.cursor', 'rules', mdc), 'utf8'), '.claude')
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function genericHostRuleBody(name) {
|
|
303
|
+
let body = loadPackagedRule(name)
|
|
304
|
+
body = body.replaceAll(
|
|
305
|
+
'.claude/skills/duaer-do/SKILL.md',
|
|
306
|
+
'AGENTS.md § Autonomous job loop (and `.agents/skills/duaer-do/SKILL.md` when present)',
|
|
307
|
+
)
|
|
308
|
+
body = body.replaceAll('.claude/skills/', '.agents/skills/')
|
|
309
|
+
return body
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function defaultGeminiMd() {
|
|
313
|
+
return `# GEMINI.md — duaer-spec
|
|
314
|
+
|
|
315
|
+
This project uses **duaer-spec**: coding agents are digital employees.
|
|
316
|
+
|
|
317
|
+
**Precedence:** \`AGENTS.md\` (ops) wins over \`DUADER.md\` / \`.duaer/\` (method).
|
|
318
|
+
|
|
319
|
+
- Follow \`AGENTS.md\` § Autonomous job loop
|
|
320
|
+
- Job skill (when available): \`.agents/skills/duaer-do/SKILL.md\`
|
|
321
|
+
- Branches / worktrees: \`docs/agent/branching-and-release.md\`
|
|
322
|
+
`
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function defaultCopilotInstructions() {
|
|
326
|
+
return `# GitHub Copilot — duaer-spec
|
|
327
|
+
|
|
328
|
+
Treat agents as **digital employees**. Humans state intent; you run Brief → work → accept.
|
|
329
|
+
|
|
330
|
+
**Precedence:** \`AGENTS.md\` > \`DUADER.md\` / \`.duaer/\`
|
|
331
|
+
|
|
332
|
+
1. Isolate on \`feat|fix/<name>\` under \`.worktree/feat-<name>/\` (never name the worktree after \`.duaer/specs/<nnn-slug>/\`).
|
|
333
|
+
2. Follow \`AGENTS.md\` § Autonomous job loop (skill: \`.agents/skills/duaer-do/SKILL.md\` when present).
|
|
334
|
+
3. Do not ask the human to operate slash commands or phase names.
|
|
335
|
+
4. One handoff line; never claim done unless \`delivery.json\` is \`accepted\`.
|
|
336
|
+
|
|
337
|
+
See also: \`DUADER.md\`, \`docs/agent/branching-and-release.md\`.
|
|
338
|
+
`
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function defaultAiderConf() {
|
|
342
|
+
return `# duaer-spec — point Aider at the shared agent contract
|
|
343
|
+
read: [AGENTS.md, DUADER.md]
|
|
344
|
+
`
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function installRuleSet(target, relDir, names, frontmatterLines, opts, label) {
|
|
348
|
+
const dir = join(target, ...relDir.split('/'))
|
|
349
|
+
ensureDir(dir)
|
|
350
|
+
for (const name of names) {
|
|
351
|
+
const dest = join(dir, name)
|
|
352
|
+
if (existsSync(dest) && !opts.force) {
|
|
353
|
+
console.log(`skip (exists): ${dest} (use --force to overwrite)`)
|
|
354
|
+
continue
|
|
355
|
+
}
|
|
356
|
+
const body = genericHostRuleBody(name)
|
|
357
|
+
const content = frontmatterLines?.length
|
|
358
|
+
? withYamlFrontmatter(body, frontmatterLines)
|
|
359
|
+
: `${stripRuleComment(body)}\n`
|
|
360
|
+
ensureDir(dirname(dest))
|
|
361
|
+
writeFileSync(dest, content, 'utf8')
|
|
362
|
+
}
|
|
363
|
+
console.log(` ${label}`)
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function installExtraHosts(target, opts) {
|
|
367
|
+
console.log('Installing common host adapters…')
|
|
368
|
+
|
|
369
|
+
// GitHub Copilot
|
|
370
|
+
ensureDir(join(target, '.github'))
|
|
371
|
+
writeIfNeeded(
|
|
372
|
+
join(target, '.github', 'copilot-instructions.md'),
|
|
373
|
+
defaultCopilotInstructions(),
|
|
374
|
+
opts,
|
|
375
|
+
)
|
|
376
|
+
console.log(' .github/copilot-instructions.md')
|
|
377
|
+
|
|
378
|
+
// Gemini CLI
|
|
379
|
+
const geminiSrc = join(PKG_ROOT, 'GEMINI.md')
|
|
380
|
+
if (existsSync(geminiSrc)) {
|
|
381
|
+
copyPath(geminiSrc, join(target, 'GEMINI.md'), opts)
|
|
382
|
+
} else {
|
|
383
|
+
writeIfNeeded(join(target, 'GEMINI.md'), defaultGeminiMd(), opts)
|
|
384
|
+
}
|
|
385
|
+
console.log(' GEMINI.md')
|
|
386
|
+
|
|
387
|
+
// Aider
|
|
388
|
+
writeIfNeeded(join(target, '.aider.conf.yml'), defaultAiderConf(), opts)
|
|
389
|
+
console.log(' .aider.conf.yml')
|
|
390
|
+
|
|
391
|
+
const ruleNames = ['duaer-spec.md', 'agents-workflow.md', 'ai-ui-copy.md']
|
|
392
|
+
|
|
393
|
+
// Windsurf (Cascade) + Devin Desktop
|
|
394
|
+
installRuleSet(
|
|
395
|
+
target,
|
|
396
|
+
'.windsurf/rules',
|
|
397
|
+
ruleNames,
|
|
398
|
+
['trigger: always_on'],
|
|
399
|
+
opts,
|
|
400
|
+
'.windsurf/rules/*',
|
|
401
|
+
)
|
|
402
|
+
installRuleSet(
|
|
403
|
+
target,
|
|
404
|
+
'.devin/rules',
|
|
405
|
+
ruleNames,
|
|
406
|
+
['trigger: always_on'],
|
|
407
|
+
opts,
|
|
408
|
+
'.devin/rules/*',
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
// Cline
|
|
412
|
+
installRuleSet(target, '.clinerules', ruleNames, null, opts, '.clinerules/*')
|
|
413
|
+
|
|
414
|
+
// Continue.dev
|
|
415
|
+
installRuleSet(
|
|
416
|
+
target,
|
|
417
|
+
'.continue/rules',
|
|
418
|
+
ruleNames,
|
|
419
|
+
['alwaysApply: true'],
|
|
420
|
+
opts,
|
|
421
|
+
'.continue/rules/*',
|
|
422
|
+
)
|
|
423
|
+
}
|
|
424
|
+
|
|
287
425
|
function cursorRuleToClaude(mdc, skillHost) {
|
|
288
426
|
let body = mdc.replace(/^---\n[\s\S]*?\n---\n+/, (fm) => {
|
|
289
427
|
const desc = (fm.match(/^description:\s*(.+)$/m) || [])[1]
|
|
@@ -421,6 +559,9 @@ function cmdInit(opts) {
|
|
|
421
559
|
if (opts.mode === 'all' || opts.mode === 'ops') {
|
|
422
560
|
installOps(target, opts)
|
|
423
561
|
}
|
|
562
|
+
if (opts.mode === 'all' || opts.mode === 'method' || opts.mode === 'ops') {
|
|
563
|
+
installExtraHosts(target, opts)
|
|
564
|
+
}
|
|
424
565
|
if (opts.mode === 'all' || opts.mode === 'method') {
|
|
425
566
|
writeInitMarker(target, opts)
|
|
426
567
|
}
|
|
@@ -428,7 +569,7 @@ function cmdInit(opts) {
|
|
|
428
569
|
console.log(`
|
|
429
570
|
Hired.
|
|
430
571
|
|
|
431
|
-
Talk to the agent in plain language (Cursor, Claude
|
|
572
|
+
Talk to the agent in plain language (Cursor, Claude, Codex, Copilot, and more).
|
|
432
573
|
Later update: npx duaer-spec update
|
|
433
574
|
`)
|
|
434
575
|
}
|
|
@@ -568,6 +709,12 @@ function checkWorkplace(target) {
|
|
|
568
709
|
['.claude/skills/duaer-do/SKILL.md', 'method'],
|
|
569
710
|
['.agents/skills/duaer-do/SKILL.md', 'method'],
|
|
570
711
|
['CLAUDE.md', 'method'],
|
|
712
|
+
['GEMINI.md', 'method'],
|
|
713
|
+
['.github/copilot-instructions.md', 'method'],
|
|
714
|
+
['.windsurf/rules/duaer-spec.md', 'method'],
|
|
715
|
+
['.clinerules/duaer-spec.md', 'method'],
|
|
716
|
+
['.continue/rules/duaer-spec.md', 'method'],
|
|
717
|
+
['.aider.conf.yml', 'method'],
|
|
571
718
|
['AGENTS.md', 'ops'],
|
|
572
719
|
['.cursor/rules/agents-workflow.mdc', 'ops'],
|
|
573
720
|
['.claude/rules/agents-workflow.md', 'ops'],
|
|
@@ -40,6 +40,7 @@ the table for their app.
|
|
|
40
40
|
| E2E-013 | Worktree id ≠ Brief `<nnn-slug>`; path is `.worktree/feat-…/.duaer/specs/…` | manual |
|
|
41
41
|
| E2E-014 | Init installs Cursor + Claude hosts (`CLAUDE.md`, `.claude/skills`) | manual |
|
|
42
42
|
| E2E-015 | Init installs Codex skills under `.agents/skills/` | manual |
|
|
43
|
+
| E2E-016 | Init installs Copilot/Windsurf/Cline/Continue/Gemini/Aider adapters | manual |
|
|
43
44
|
|
|
44
45
|
## Traceability
|
|
45
46
|
|
|
@@ -60,3 +61,4 @@ the table for their app.
|
|
|
60
61
|
| E2E-013 | AGENTS / branching naming | Avoid double `<nnn-slug>` |
|
|
61
62
|
| E2E-014 | Claude + Cursor install | Dual host |
|
|
62
63
|
| E2E-015 | Codex `.agents/skills` | Triple host |
|
|
64
|
+
| E2E-016 | Extra host adapters | Copilot+Windsurf+Cline+… |
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "duaer-spec",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Digital employees for Cursor, Claude
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Digital employees for Cursor, Claude, Codex, Copilot, Windsurf, Cline, Continue, Gemini, Aider",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"duaer": "bin/duaer.mjs",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
".claude",
|
|
15
15
|
"AGENTS.md",
|
|
16
16
|
"CLAUDE.md",
|
|
17
|
+
"GEMINI.md",
|
|
17
18
|
"DUADER.md",
|
|
18
19
|
"ADOPT.md",
|
|
19
20
|
"CHANGELOG.md",
|
|
@@ -49,7 +50,14 @@
|
|
|
49
50
|
"claude",
|
|
50
51
|
"claude-code",
|
|
51
52
|
"codex",
|
|
52
|
-
"openai-codex"
|
|
53
|
+
"openai-codex",
|
|
54
|
+
"copilot",
|
|
55
|
+
"windsurf",
|
|
56
|
+
"cline",
|
|
57
|
+
"continue",
|
|
58
|
+
"gemini",
|
|
59
|
+
"aider",
|
|
60
|
+
"devin"
|
|
53
61
|
],
|
|
54
62
|
"license": "MIT",
|
|
55
63
|
"scripts": {
|