duaer-spec 0.13.0 → 0.15.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/.duaer/active-job.json +4 -3
- package/.duaer/memory/testing.md +22 -8
- package/.duaer/specs/033-agent-detect/delivery.json +13 -0
- package/.duaer/specs/033-agent-detect/spec.md +24 -0
- package/.duaer/specs/033-agent-detect/tasks.md +4 -0
- package/.duaer/specs/034-stale-worktree/delivery.json +15 -0
- package/.duaer/specs/034-stale-worktree/spec.md +20 -0
- package/.duaer/specs/034-stale-worktree/tasks.md +5 -0
- package/.duaer/specs/035-revise-card-below/delivery.json +10 -0
- package/.duaer/specs/035-revise-card-below/spec.md +19 -0
- package/.duaer/specs/035-revise-card-below/tasks.md +7 -0
- package/.duaer/specs/036-progress-cta/delivery.json +10 -0
- package/.duaer/specs/036-progress-cta/spec.md +18 -0
- package/.duaer/specs/036-progress-cta/tasks.md +5 -0
- package/.duaer/specs/037-live-i18n/delivery.json +38 -0
- package/.duaer/specs/037-live-i18n/spec.md +43 -0
- package/.duaer/specs/037-live-i18n/tasks.md +13 -0
- package/.duaer/specs/038-revise-enqueue-style/delivery.json +18 -0
- package/.duaer/specs/038-revise-enqueue-style/spec.md +60 -0
- package/.duaer/specs/038-revise-enqueue-style/tasks.md +7 -0
- package/.duaer/specs/039-desk-scroll-sync/delivery.json +18 -0
- package/.duaer/specs/039-desk-scroll-sync/spec.md +65 -0
- package/.duaer/specs/039-desk-scroll-sync/tasks.md +6 -0
- package/.duaer/specs/040-terminal-queue-wait/active-job.json +12 -0
- package/.duaer/specs/040-terminal-queue-wait/delivery.json +26 -0
- package/.duaer/specs/040-terminal-queue-wait/spec.md +85 -0
- package/.duaer/specs/040-terminal-queue-wait/tasks.md +6 -0
- package/.duaer/specs/041-desk-wide-queue/delivery.json +18 -0
- package/.duaer/specs/041-desk-wide-queue/spec.md +74 -0
- package/.duaer/specs/041-desk-wide-queue/tasks.md +6 -0
- package/.duaer/specs/042-progress-style/delivery.json +17 -0
- package/.duaer/specs/042-progress-style/spec.md +48 -0
- package/.duaer/specs/042-progress-style/tasks.md +6 -0
- package/.duaer/specs/043-live-history/active-job.json +12 -0
- package/.duaer/specs/043-live-history/delivery.json +21 -0
- package/.duaer/specs/043-live-history/spec.md +41 -0
- package/.duaer/specs/043-live-history/tasks.md +7 -0
- package/.duaer/specs/044-desk-layout/delivery.json +18 -0
- package/.duaer/specs/044-desk-layout/spec.md +60 -0
- package/.duaer/specs/044-desk-layout/tasks.md +7 -0
- package/.duaer/specs/045-revise-hang/delivery.json +40 -0
- package/.duaer/specs/045-revise-hang/spec.md +50 -0
- package/.duaer/specs/045-revise-hang/tasks.md +10 -0
- package/.duaer/specs/046-revise-stuck/delivery.json +9 -0
- package/.duaer/specs/046-revise-stuck/spec.md +59 -0
- package/.duaer/specs/046-revise-stuck/tasks.md +9 -0
- package/.duaer/specs/047-revise-preempt-kill/active-job.json +6 -0
- package/.duaer/specs/047-revise-preempt-kill/delivery.json +13 -0
- package/.duaer/specs/047-revise-preempt-kill/spec.md +53 -0
- package/.duaer/specs/047-revise-preempt-kill/tasks.md +6 -0
- package/.duaer/specs/048-progress-below/active-job.json +6 -0
- package/.duaer/specs/048-progress-below/delivery.json +8 -0
- package/.duaer/specs/048-progress-below/spec.md +44 -0
- package/.duaer/specs/048-progress-below/tasks.md +8 -0
- package/.duaer/specs/049-progress-column/active-job.json +6 -0
- package/.duaer/specs/049-progress-column/delivery.json +8 -0
- package/.duaer/specs/049-progress-column/spec.md +50 -0
- package/.duaer/specs/049-progress-column/tasks.md +7 -0
- package/.duaer/specs/050-validate-before-confirm/delivery.json +8 -0
- package/.duaer/specs/050-validate-before-confirm/spec.md +64 -0
- package/.duaer/specs/050-validate-before-confirm/tasks.md +16 -0
- package/.duaer/specs/051-confirm-wide-structured/delivery.json +8 -0
- package/.duaer/specs/051-confirm-wide-structured/spec.md +49 -0
- package/.duaer/specs/051-confirm-wide-structured/tasks.md +11 -0
- package/.duaer/specs/052-desk-fullscreen/delivery.json +8 -0
- package/.duaer/specs/052-desk-fullscreen/spec.md +37 -0
- package/.duaer/specs/052-desk-fullscreen/tasks.md +9 -0
- package/.duaer/specs/053-release-014/delivery.json +8 -0
- package/.duaer/specs/053-release-014/spec.md +36 -0
- package/.duaer/specs/053-release-014/tasks.md +9 -0
- package/.duaer/specs/054-live-l3-smoke/delivery.json +9 -0
- package/.duaer/specs/054-live-l3-smoke/spec.md +41 -0
- package/.duaer/specs/054-live-l3-smoke/tasks.md +10 -0
- package/.duaer/specs/055-release-015/delivery.json +8 -0
- package/.duaer/specs/055-release-015/spec.md +16 -0
- package/.duaer/specs/055-release-015/tasks.md +4 -0
- package/CHANGELOG.md +43 -1
- package/README.md +12 -4
- package/README.zh-CN.md +9 -4
- package/bin/duaer-live.mjs +1166 -130
- package/docs/agent/e2e-test-plan.md +30 -0
- package/package.json +4 -2
- package/web/live-dev/app.js +1350 -306
- package/web/live-dev/i18n.js +545 -0
- package/web/live-dev/index.html +199 -133
- package/web/live-dev/styles.css +541 -103
package/.duaer/active-job.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"branch": "
|
|
4
|
-
"
|
|
2
|
+
"featureDir": ".duaer/specs/055-release-015",
|
|
3
|
+
"branch": "feat/release-015",
|
|
4
|
+
"worktree": ".worktree/feat-release-015",
|
|
5
|
+
"status": "active"
|
|
5
6
|
}
|
package/.duaer/memory/testing.md
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
# Testing expectations (project contract)
|
|
2
2
|
|
|
3
3
|
Agents **must** read this file before marking work verified or accepting a job.
|
|
4
|
-
|
|
5
|
-
level model and risk rules unless an ADR
|
|
4
|
+
This file is the **duaer-spec** repo contract. Adopters replace command examples
|
|
5
|
+
with their product scripts; keep the level model and risk rules unless an ADR
|
|
6
|
+
documents a change.
|
|
6
7
|
|
|
7
8
|
## Levels
|
|
8
9
|
|
|
9
|
-
| Level | What | Typical commands (
|
|
10
|
+
| Level | What | Typical commands (this repo) | Default owner |
|
|
10
11
|
|---|---|---|---|
|
|
11
|
-
| **L0** | Lint / typecheck / static | `
|
|
12
|
-
| **L1** | Unit tests for changed modules | `npm test`
|
|
12
|
+
| **L0** | Lint / typecheck / static | `node --check bin/duaer-live.mjs` `node --check web/live-dev/app.js` | After every implementation pass |
|
|
13
|
+
| **L1** | Unit tests for changed modules | `npm test` when unit files exist under `test/` | Default for code changes |
|
|
13
14
|
| **L2** | Integration / product acceptance at changed boundaries | project acceptance or integration suite | When boundaries or core paths change |
|
|
14
|
-
| **L3** | Automated E2E /
|
|
15
|
+
| **L3** | Automated E2E / protocol smoke for user-visible paths | **`npm run test:live`** (live desk shell + `/api/validate` gate; mock LLM, no paid API) | When live desk UI / protocol UX changes |
|
|
15
16
|
| **L4** | Manual account / device path when automation cannot cover auth or real data | documented steps in the Brief | When UI/auth and no automated substitute |
|
|
16
17
|
|
|
17
18
|
IDE Browser / MCP exploration is **optional discovery**. It does **not** replace
|
|
18
|
-
L3
|
|
19
|
+
L3 when `npm run test:live` covers the touched path.
|
|
19
20
|
|
|
20
21
|
## Risk table (what to run)
|
|
21
22
|
|
|
@@ -24,12 +25,25 @@ L3 automation when the project has an E2E suite.
|
|
|
24
25
|
| Docs / comments only | None (note in Brief) |
|
|
25
26
|
| Internal code, same behavior | L0 + L1 for affected packages |
|
|
26
27
|
| API / data / core path | L0 + L1 + L2 (or documented equivalent) |
|
|
27
|
-
| User-visible or protocol-visible UI/UX | L0 +
|
|
28
|
+
| User-visible or protocol-visible UI/UX (live desk) | L0 + **`npm run test:live` (L3)** + update E2E catalog |
|
|
28
29
|
| Auth / payments / irreversible ops | Above + L4 if L3 cannot cover |
|
|
29
30
|
|
|
30
31
|
Prefer **targeted subsets** over full monorepo suites. Do not skip a required
|
|
31
32
|
level without an explicit waiver in the feature docs (`tasks.md` or Spec).
|
|
32
33
|
|
|
34
|
+
## Live desk L3 (`npm run test:live`)
|
|
35
|
+
|
|
36
|
+
Covers without a paid LLM:
|
|
37
|
+
|
|
38
|
+
1. Desk shell HTML/CSS/JS markers (three columns, structured confirm fields,
|
|
39
|
+
`validationAllowsSend`)
|
|
40
|
+
2. Local validate failures (empty / too-short card)
|
|
41
|
+
3. `/api/validate` pass and `/api/validate/fix` via an in-process mock
|
|
42
|
+
OpenAI-compatible server
|
|
43
|
+
|
|
44
|
+
Does **not** cover: real model quality, Terminal CLI launch, or full revise
|
|
45
|
+
dispatch. Those stay manual E2E catalog rows or future suites.
|
|
46
|
+
|
|
33
47
|
## Opt-in (still need an explicit ask or Spec note)
|
|
34
48
|
|
|
35
49
|
Mark these in the project table when they are expensive:
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-16T04:15:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["docs", "L0", "L3-catalog"],
|
|
6
|
+
"commands": [
|
|
7
|
+
"node --check bin/duaer-live.mjs",
|
|
8
|
+
"PATH=/usr/bin:/bin node -e detectAgents smoke"
|
|
9
|
+
],
|
|
10
|
+
"result": "pass",
|
|
11
|
+
"e2e": ["E2E-034"]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Feature Specification: Detect CLI agents under launchd PATH
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `fix/agent-detect`
|
|
4
|
+
|
|
5
|
+
**Created**: 2026-09-16
|
|
6
|
+
|
|
7
|
+
**Status**: Active
|
|
8
|
+
|
|
9
|
+
## Goal
|
|
10
|
+
|
|
11
|
+
Live desk must detect installed Cursor Agent / Claude Code even when started
|
|
12
|
+
via LaunchAgent (minimal PATH).
|
|
13
|
+
|
|
14
|
+
## Problem
|
|
15
|
+
|
|
16
|
+
LaunchAgent PATH is `/usr/bin:/bin:/usr/sbin:/sbin`, so `which agent|claude`
|
|
17
|
+
fails even though `~/.local/bin` and `/usr/local/bin` have the CLIs.
|
|
18
|
+
|
|
19
|
+
## Acceptance
|
|
20
|
+
|
|
21
|
+
1. `ensureCliSearchPath` prepends `~/.local/bin`, `/usr/local/bin`, `/opt/homebrew/bin`
|
|
22
|
+
2. `whichCmd` falls back to those dirs if `which` misses
|
|
23
|
+
3. `/api/agents` reports installed agents when binaries exist there
|
|
24
|
+
4. LaunchAgent plist PATH updated (local handoff) after merge
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-16T04:28:30.000Z",
|
|
4
|
+
"summary": "Live desk recovers Brief/status from product primary after worktree handoff cleanup; revise recreates worktree instead of failing.",
|
|
5
|
+
"verification": {
|
|
6
|
+
"levels": ["docs", "L0", "L1-smoke", "L3-catalog"],
|
|
7
|
+
"commands": [
|
|
8
|
+
"/usr/local/bin/node --check bin/duaer-live.mjs",
|
|
9
|
+
"curl -s 'http://127.0.0.1:8792/api/status?jobId=024-job-3l9xtu'"
|
|
10
|
+
],
|
|
11
|
+
"result": "pass",
|
|
12
|
+
"e2e": ["E2E-035"],
|
|
13
|
+
"notes": "Smoke: status=accepted, delivery.status=accepted, canRevise=true, handoffCleaned=true, worktreeExists=false, featureDir=/Users/morgan/autotest/.duaer/specs/034-job-3l9xtu, resolvedFrom=primary. LaunchAgent 8787 reloaded after merge."
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Feature Specification: Survive worktree handoff cleanup
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `fix/stale-worktree`
|
|
4
|
+
|
|
5
|
+
**Created**: 2026-09-16
|
|
6
|
+
|
|
7
|
+
**Status**: Active
|
|
8
|
+
|
|
9
|
+
## Goal
|
|
10
|
+
|
|
11
|
+
After the digital employee merges and removes the request worktree, the live
|
|
12
|
+
desk must still show accepted status / preview from the product repo, and
|
|
13
|
+
revise must recreate a worktree instead of erroring「worktree 已不存在」.
|
|
14
|
+
|
|
15
|
+
## Acceptance
|
|
16
|
+
|
|
17
|
+
1. Status resolves Brief/delivery from `repoPath` + `specDir` when worktree gone
|
|
18
|
+
2. Preview/artifacts serve from primary checkout when needed
|
|
19
|
+
3. Revise recreates `.worktree/feat-*-rN` from develop and copies Brief
|
|
20
|
+
4. canRevise true when primary Brief exists
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Feature Specification: Revise card below confirm card
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `fix/revise-card-below`
|
|
4
|
+
|
|
5
|
+
**Created**: 2026-09-16
|
|
6
|
+
|
|
7
|
+
**Status**: Active
|
|
8
|
+
|
|
9
|
+
## Goal
|
|
10
|
+
|
|
11
|
+
Keep the top confirm card unchanged. Put the revise card in the bottom panel
|
|
12
|
+
so users can read it under the dialogue flow without the top card becoming 改进卡.
|
|
13
|
+
|
|
14
|
+
## Acceptance
|
|
15
|
+
|
|
16
|
+
1. Confirm card title/labels/styles never switch to revise chrome
|
|
17
|
+
2. Revise fields render in `#revisePanel` below preview
|
|
18
|
+
3. Chat applyCard updates bottom revise fields in revise mode
|
|
19
|
+
4. After revise lock, top still shows original requirements
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Tasks
|
|
2
|
+
|
|
3
|
+
- [x] T001 Keep top confirm card original; never switch to revise chrome
|
|
4
|
+
- [x] T002 Render revise fields in `#revisePanel` below preview
|
|
5
|
+
- [x] T003 Chat applyCard updates bottom revise fields in revise mode
|
|
6
|
+
- [x] T004 After revise lock, top still shows original requirements
|
|
7
|
+
- [x] T005 Docs E2E-036 + verify (`node --check`) + accept + merge + reload live
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Feature Specification: Hide product/revise CTAs until accepted
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `fix/progress-cta`
|
|
4
|
+
|
|
5
|
+
**Created**: 2026-09-16
|
|
6
|
+
|
|
7
|
+
**Status**: Active
|
|
8
|
+
|
|
9
|
+
## Goal
|
|
10
|
+
|
|
11
|
+
While progress shows in-progress (e.g. `0/3 · 进行中`), do not show 查看成品
|
|
12
|
+
or 再改一版 / 改进卡. Those appear only after delivery accepted.
|
|
13
|
+
|
|
14
|
+
## Acceptance
|
|
15
|
+
|
|
16
|
+
1. Status `dispatched` with open delivery → preview null, canRevise false
|
|
17
|
+
2. Status accepted → preview + revise CTA available
|
|
18
|
+
3. During revising round → preview may stay; revise panel as needed
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"status": "accepted",
|
|
4
|
+
"feature": "037-live-i18n",
|
|
5
|
+
"acceptedAt": "2026-09-16T04:52:00.000Z",
|
|
6
|
+
"summary": "Live desk zh-CN/en i18n with language switcher, catalogs, DOM data-i18n, and dynamic sync.",
|
|
7
|
+
"verification": {
|
|
8
|
+
"commands": [
|
|
9
|
+
{
|
|
10
|
+
"command": "node --check web/live-dev/i18n.js",
|
|
11
|
+
"result": "pass — exit 0 (SYNTAX_OK) 2026-09-16"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"command": "node --check web/live-dev/app.js",
|
|
15
|
+
"result": "pass — exit 0 (SYNTAX_OK) 2026-09-16"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"command": "key parity: every t() key in app.js vs zhCN + en in i18n.js",
|
|
19
|
+
"result": "pass — no missing keys"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"command": "grep user-visible Chinese in app.js",
|
|
23
|
+
"result": "pass — only intentional LLM kickoff string + comments"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"command": "curl -sS -o /dev/null -w '%{http_code}' http://localhost:8787/",
|
|
27
|
+
"result": "pass — HTTP 200 (pre-merge; LaunchAgent still on primary develop)"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"command": "curl -sS -o /dev/null -w '%{http_code}' http://localhost:8787/i18n.js",
|
|
31
|
+
"result": "expected 404 pre-merge — i18n.js not on develop until merge + kickstart"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"e2e": ["E2E-038"],
|
|
35
|
+
"notes": "T007 smoke: language switch + localStorage persistence covered by code path (initI18n/detectLocale/setLocale + #langSelect). Post-merge handoff: launchctl kickstart live8787 then re-curl /i18n.js."
|
|
36
|
+
},
|
|
37
|
+
"tasksCompleted": ["T001", "T002", "T003", "T004", "T005", "T006", "T007", "T008"]
|
|
38
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Feature Specification: Live desk i18n (zh-CN + en)
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `feat/live-i18n`
|
|
4
|
+
|
|
5
|
+
**Created**: 2026-09-16
|
|
6
|
+
|
|
7
|
+
**Status**: Active
|
|
8
|
+
|
|
9
|
+
## Goal
|
|
10
|
+
|
|
11
|
+
Live desk UI supports multiple languages. Initial locales: **zh-CN** (default)
|
|
12
|
+
and **en**, with a visible language switcher. Preference persists.
|
|
13
|
+
|
|
14
|
+
## In scope
|
|
15
|
+
|
|
16
|
+
- Message catalogs for static + dynamic live UI copy
|
|
17
|
+
- Header language switch (zh-CN / en)
|
|
18
|
+
- Persist locale (`localStorage` key `duaer.live.locale`)
|
|
19
|
+
- Browser language hint on first visit (zh* → zh-CN, else en)
|
|
20
|
+
- Confirm card / revise card / dispatch / preview / revise CTAs translated
|
|
21
|
+
- Do not change confirm-card layout; i18n only for strings
|
|
22
|
+
|
|
23
|
+
## Out of scope
|
|
24
|
+
|
|
25
|
+
- Translating agent Terminal prompts (may stay bilingual later)
|
|
26
|
+
- Full localization of every server console log line
|
|
27
|
+
- Translating LLM system prompts used by `/api/chat`
|
|
28
|
+
|
|
29
|
+
## Acceptance
|
|
30
|
+
|
|
31
|
+
1. Switching to English updates visible desk copy (static `data-i18n` + dynamic
|
|
32
|
+
JS strings) without a layout break
|
|
33
|
+
2. Reload keeps the chosen locale via `localStorage` (`duaer.live.locale`)
|
|
34
|
+
3. zh-CN remains default when no preference and browser language is Chinese
|
|
35
|
+
4. Language switcher (`#langSelect`) is visible in the header
|
|
36
|
+
5. E2E catalog note (E2E-038)
|
|
37
|
+
|
|
38
|
+
## Notes
|
|
39
|
+
|
|
40
|
+
- Catalogs live in `web/live-dev/i18n.js`; `app.js` imports `t` / `setLocale` /
|
|
41
|
+
`onLocaleChange`
|
|
42
|
+
- Static files under `web/live-dev/` are served as-is by `bin/duaer-live.mjs`
|
|
43
|
+
(no whitelist); `i18n.js` needs no server change
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Tasks: Live desk i18n
|
|
2
|
+
|
|
3
|
+
- [x] T001 Add `web/live-dev/i18n.js` with zh-CN + en catalogs, `t`, `setLocale`,
|
|
4
|
+
`applyDomI18n`, `initI18n`, `onLocaleChange`, `getLocale`
|
|
5
|
+
- [x] T002 Mark static copy in `index.html` with `data-i18n` / placeholders;
|
|
6
|
+
add `#langSelect` + `.lang-switch` styles
|
|
7
|
+
- [x] T003 Expand catalogs for every user-visible string set from `app.js`
|
|
8
|
+
- [x] T004 Wire `app.js`: import i18n, replace hardcoded UI strings with `t()`,
|
|
9
|
+
sync dynamic chrome on `onLocaleChange`, bind `#langSelect`
|
|
10
|
+
- [x] T005 Confirm `duaer-live` static serve covers `i18n.js` (directory serve)
|
|
11
|
+
- [x] T006 Spec acceptance + E2E-038 note
|
|
12
|
+
- [x] T007 Smoke-test: open live desk, switch zh-CN ↔ en, reload persists
|
|
13
|
+
- [x] T008 Stamp `delivery.json` accepted (parent verify / merge)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"status": "accepted",
|
|
4
|
+
"feature": "038-revise-enqueue-style",
|
|
5
|
+
"acceptedAt": "2026-09-16T05:22:00.000Z",
|
|
6
|
+
"summary": "Honest revise Terminal enqueue after accepted delivery (fresh session, no false PID reuse) and dark revise card matching panel plate/shadow.",
|
|
7
|
+
"verification": {
|
|
8
|
+
"commands": [
|
|
9
|
+
{
|
|
10
|
+
"command": "node --check bin/duaer-live.mjs",
|
|
11
|
+
"result": "pass — exit 0 (SYNTAX_OK) 2026-09-16"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"e2e": ["E2E-039"],
|
|
15
|
+
"notes": "T004: syntax check on duaer-live.mjs; runner heartbeat + isTerminalRunnerHealthy reviewed; revise after accepted uses continueSession=false with Terminal queue; revise-panel CSS uses var(--plate)/var(--shadow) like .panel. Post-merge handoff: launchctl kickstart com.duaer.live8787."
|
|
16
|
+
},
|
|
17
|
+
"tasksCompleted": ["T001", "T002", "T003", "T004"]
|
|
18
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Feature Specification: Fix revise enqueue + dark revise card
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `fix/revise-enqueue-style`
|
|
4
|
+
|
|
5
|
+
**Created**: 2026-09-16
|
|
6
|
+
|
|
7
|
+
**Status**: Active
|
|
8
|
+
|
|
9
|
+
## Goal
|
|
10
|
+
|
|
11
|
+
Make revise enqueue truthful: when the UI reports「已送入原 Terminal」, an agent
|
|
12
|
+
must actually start. Reuse the same Terminal window and queue when healthy; do
|
|
13
|
+
not treat a dead or stale runner as live (false PID reuse). Avoid `--continue`
|
|
14
|
+
against an ended session. Prefer a fresh agent prompt (no `--continue`) after
|
|
15
|
+
accepted delivery while still enqueueing through the Terminal queue. Restyle
|
|
16
|
+
the revise card to the desk dark plate/panel look (not translucent white).
|
|
17
|
+
|
|
18
|
+
## Problem
|
|
19
|
+
|
|
20
|
+
1. UI can show「已送入原 Terminal」while no agent runs
|
|
21
|
+
2. False PID reuse / stale runner makes enqueue look successful
|
|
22
|
+
3. `--continue` after an ended session fails to launch work
|
|
23
|
+
4. Revise card chrome is translucent white and clashes with dark plate/panel desk
|
|
24
|
+
|
|
25
|
+
## In scope
|
|
26
|
+
|
|
27
|
+
- Runner liveness: heartbeat (or equivalent) so dead PIDs are not treated as
|
|
28
|
+
active Terminal targets
|
|
29
|
+
- Enqueue must actually trigger the agent in the intended Terminal when the
|
|
30
|
+
runner is alive; same window OK
|
|
31
|
+
- After accepted delivery, prefer new agent prompt without `--continue`, still
|
|
32
|
+
via Terminal queue
|
|
33
|
+
- Do not use `--continue` when the prior session has ended
|
|
34
|
+
- Restyle revise card to dark plate/panel desk style
|
|
35
|
+
|
|
36
|
+
## Out of scope
|
|
37
|
+
|
|
38
|
+
- Changing first-dispatch / non-revise launch flows except as needed for shared
|
|
39
|
+
runner health
|
|
40
|
+
- Redesigning left-chat revise dialogue copy beyond what enqueue honesty needs
|
|
41
|
+
- Remote push / promote to `main`
|
|
42
|
+
|
|
43
|
+
## Acceptance
|
|
44
|
+
|
|
45
|
+
1. When UI shows「已送入原 Terminal」after revise confirm, an agent process
|
|
46
|
+
actually starts (or clearly fails with honest UI — no false success)
|
|
47
|
+
2. A dead/stale runner PID is not reused as a live Terminal target; heartbeat
|
|
48
|
+
(or equivalent) detects liveness before enqueue success
|
|
49
|
+
3. Same Terminal window may be reused when the runner is alive; enqueue must
|
|
50
|
+
still trigger the agent
|
|
51
|
+
4. After accepted delivery, revise relaunch prefers a new agent prompt without
|
|
52
|
+
`--continue`, while still using the Terminal queue
|
|
53
|
+
5. `--continue` is not used against an ended session as the sole launch path
|
|
54
|
+
6. Revise card matches dark plate/panel desk styling (no translucent white card)
|
|
55
|
+
7. E2E catalog note (E2E-039)
|
|
56
|
+
|
|
57
|
+
## Assumptions
|
|
58
|
+
|
|
59
|
+
- Terminal queue / desk runner already exists; this job hardens liveness and
|
|
60
|
+
post-accept launch policy, then restyles the revise card
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Tasks
|
|
2
|
+
|
|
3
|
+
- [x] T001 Harden revise enqueue: runner heartbeat/liveness, no false PID reuse,
|
|
4
|
+
no `--continue` after accepted delivery; still use Terminal queue
|
|
5
|
+
- [x] T002 Restyle revise card to dark plate/panel desk (not translucent white)
|
|
6
|
+
- [x] T003 Spec-sync / E2E-039 for honest enqueue + card style
|
|
7
|
+
- [x] T004 Risk-based verify, accept delivery, merge to develop, handoff
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"status": "accepted",
|
|
4
|
+
"feature": "039-desk-scroll-sync",
|
|
5
|
+
"acceptedAt": "2026-09-16T05:30:00.000Z",
|
|
6
|
+
"summary": "Viewport-bound desk columns with independent scrolls; right panel auto-focuses active stage in sync with left chat.",
|
|
7
|
+
"verification": {
|
|
8
|
+
"commands": [
|
|
9
|
+
{
|
|
10
|
+
"command": "node --check web/live-dev/app.js",
|
|
11
|
+
"result": "ok (exit 0)"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"e2e": ["E2E-040"],
|
|
15
|
+
"notes": "CSS (styles.css) not node-checkable. Layout height 100dvh-minus-header; both columns overflow independently. JS: focusRightPanel on bubbles, revise, dispatch, progress, preview."
|
|
16
|
+
},
|
|
17
|
+
"tasksCompleted": ["T001", "T002", "T003", "T004"]
|
|
18
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Feature Specification: Live desk left↔right scroll sync
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `feat/desk-scroll-sync`
|
|
4
|
+
|
|
5
|
+
**Created**: 2026-09-16
|
|
6
|
+
|
|
7
|
+
**Status**: Active
|
|
8
|
+
|
|
9
|
+
## Goal
|
|
10
|
+
|
|
11
|
+
On the live desk, the right column grows long across the job lifecycle
|
|
12
|
+
(confirm → dispatch → progress → preview → revise) while the left chat stays
|
|
13
|
+
anchored at the top. Keep left↔right focus in sync so the content the user
|
|
14
|
+
needs on the right scrolls into view when chat activity or mode changes
|
|
15
|
+
advance the active stage.
|
|
16
|
+
|
|
17
|
+
## Problem
|
|
18
|
+
|
|
19
|
+
1. Right-column content stacks tall; the active section (confirm / progress /
|
|
20
|
+
preview / revise) can sit below the viewport while the user is still
|
|
21
|
+
talking on the left
|
|
22
|
+
2. Left chat stays at the top by design; without coordinated scroll, users
|
|
23
|
+
miss the stage that chat just unlocked or updated
|
|
24
|
+
3. Manual scrolling the whole page (or losing independent panel scroll) breaks
|
|
25
|
+
the two-column desk model
|
|
26
|
+
|
|
27
|
+
## In scope
|
|
28
|
+
|
|
29
|
+
- Independent vertical scroll on the right panel (not whole-page scroll as the
|
|
30
|
+
primary mechanism)
|
|
31
|
+
- Auto-scroll the right panel so the **active section** enters view when chat
|
|
32
|
+
activity or mode/stage changes make that section the focus:
|
|
33
|
+
confirm, progress, preview, or revise
|
|
34
|
+
- Optionally scroll the left chat log to the bottom when new bubbles arrive
|
|
35
|
+
(keep composer / chat chrome usable)
|
|
36
|
+
- Preserve existing confirm-card field layout and copy — no redesign of
|
|
37
|
+
confirm fields
|
|
38
|
+
|
|
39
|
+
## Out of scope
|
|
40
|
+
|
|
41
|
+
- Redesigning confirm-card fields, labels, or structure
|
|
42
|
+
- Redesigning progress / preview / revise card chrome beyond scroll/focus
|
|
43
|
+
- Changing dispatch, agent launch, or revise enqueue semantics
|
|
44
|
+
- Remote push / promote to `main`
|
|
45
|
+
|
|
46
|
+
## Acceptance
|
|
47
|
+
|
|
48
|
+
1. Right panel scrolls independently; tall stage stacks do not force the left
|
|
49
|
+
chat off-screen as the only way to see later stages
|
|
50
|
+
2. When the active stage becomes confirm, progress, preview, or revise (via
|
|
51
|
+
chat activity or mode change), that section scrolls into view in the right
|
|
52
|
+
panel without requiring the user to hunt for it
|
|
53
|
+
3. Left chat remains usable at the top of the desk layout; optional auto-scroll
|
|
54
|
+
of the left log to the latest bubble on new messages does not break typing
|
|
55
|
+
4. Confirm-card fields are unchanged (same fields / structure; scroll-only UX)
|
|
56
|
+
5. E2E catalog note for this behavior (E2E-040)
|
|
57
|
+
|
|
58
|
+
## Assumptions
|
|
59
|
+
|
|
60
|
+
- Preferred approach: independent right-panel overflow + `scrollIntoView` (or
|
|
61
|
+
equivalent) on the active section; left log bottom-scroll on new bubbles is
|
|
62
|
+
optional polish if not already reliable
|
|
63
|
+
- Existing partial `scrollIntoView` for revise confirm may be extended, not
|
|
64
|
+
replaced wholesale
|
|
65
|
+
- Implementation deferred; this Brief + tasks only for now
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"feature": "040-terminal-queue-wait",
|
|
4
|
+
"featureDirectory": ".duaer/specs/040-terminal-queue-wait",
|
|
5
|
+
"specDir": ".duaer/specs/040-terminal-queue-wait",
|
|
6
|
+
"branch": "feat/terminal-queue-wait",
|
|
7
|
+
"worktree": ".worktree/feat-terminal-queue-wait",
|
|
8
|
+
"startedAt": "2026-09-16T05:40:00.000Z",
|
|
9
|
+
"updatedAt": "2026-09-16T05:46:00.000Z",
|
|
10
|
+
"source": "duaer-do",
|
|
11
|
+
"status": "accepted"
|
|
12
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"status": "accepted",
|
|
4
|
+
"feature": "040-terminal-queue-wait",
|
|
5
|
+
"acceptedAt": "2026-09-16T05:46:00.000Z",
|
|
6
|
+
"summary": "Honest Terminal queue wait while runner is busy: busy=running.cmd → queued/busy flags; UI i18n; E2E-041; never interrupt.",
|
|
7
|
+
"verification": {
|
|
8
|
+
"commands": [
|
|
9
|
+
{
|
|
10
|
+
"command": "node --check bin/duaer-live.mjs",
|
|
11
|
+
"result": "ok (exit 0)"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"command": "node --check web/live-dev/app.js",
|
|
15
|
+
"result": "ok (exit 0)"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"command": "node --check web/live-dev/i18n.js",
|
|
19
|
+
"result": "ok (exit 0)"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"e2e": ["E2E-041"],
|
|
23
|
+
"notes": "T004: ESM syntax checks pass. Busy runner detected via running.cmd; API returns queued/busy without interrupt. Post-merge handoff: launchctl kickstart com.duaer.live8787."
|
|
24
|
+
},
|
|
25
|
+
"tasksCompleted": ["T001", "T002", "T003", "T004"]
|
|
26
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Feature Specification: Terminal busy-queue honesty
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `feat/terminal-queue-wait`
|
|
4
|
+
|
|
5
|
+
**Created**: 2026-09-16
|
|
6
|
+
|
|
7
|
+
**Status**: Active
|
|
8
|
+
|
|
9
|
+
## Goal
|
|
10
|
+
|
|
11
|
+
When the user revises or re-dispatches while the Terminal runner is already
|
|
12
|
+
busy (`running.cmd` present and healthy), **wait for the current task to
|
|
13
|
+
finish** — do not interrupt it. Still enqueue via `pending.cmd`. Return
|
|
14
|
+
honest API flags (`queued` / `busy` / `reused` or equivalent) so the UI does
|
|
15
|
+
**not** claim the agent has already started. Show clear zh-CN / en copy that
|
|
16
|
+
the work is queued and will run after the current task ends.
|
|
17
|
+
|
|
18
|
+
## Problem
|
|
19
|
+
|
|
20
|
+
1. Busy-runner enqueue can look like an immediate start (e.g.「已送入原
|
|
21
|
+
Terminal」/「数字员工已启动」) even though the new prompt only sits in
|
|
22
|
+
`pending.cmd` until `running.cmd` finishes
|
|
23
|
+
2. API reuse success (`reused: true` / `mode: "terminal-reuse"`) does not
|
|
24
|
+
distinguish idle reuse from busy queue-wait
|
|
25
|
+
3. Users may think the revise already interrupted or replaced the in-flight
|
|
26
|
+
task
|
|
27
|
+
|
|
28
|
+
## User decision (frozen)
|
|
29
|
+
|
|
30
|
+
- **Wait** for the current Terminal task to finish; **do not** interrupt
|
|
31
|
+
- Keep writing `pending.cmd` (queue)
|
|
32
|
+
- Make enqueue honesty explicit in API **and** UI
|
|
33
|
+
|
|
34
|
+
## In scope
|
|
35
|
+
|
|
36
|
+
- Detect busy runner: `running.cmd` present **and** runner healthy
|
|
37
|
+
(heartbeat / PID liveness as already used for reuse)
|
|
38
|
+
- On revise / re-dispatch into that runner: write `pending.cmd`; do not kill
|
|
39
|
+
or replace `running.cmd`
|
|
40
|
+
- API response must expose queue honesty, e.g.:
|
|
41
|
+
- `queued: true`
|
|
42
|
+
- `busy: true`
|
|
43
|
+
- `reused: true` (same Terminal / runner)
|
|
44
|
+
- (or equivalent fields the UI can rely on without implying “started now”)
|
|
45
|
+
- Live desk UI: when those flags indicate busy-queue, do **not** use “agent
|
|
46
|
+
already started” / immediate-reuse success copy
|
|
47
|
+
- i18n zh-CN / en message along the lines of:
|
|
48
|
+
- zh-CN:「已排入原 Terminal,当前任务结束后自动跑」
|
|
49
|
+
- en: equivalent (“Queued in the existing Terminal; runs after the current
|
|
50
|
+
task finishes”)
|
|
51
|
+
- Preserve post-accept revise policy from prior jobs: **no false `--continue`**
|
|
52
|
+
after accepted delivery; this job is about **busy-queue honesty**, not
|
|
53
|
+
reopening the continue-session debate
|
|
54
|
+
- E2E catalog note **E2E-041**
|
|
55
|
+
|
|
56
|
+
## Out of scope
|
|
57
|
+
|
|
58
|
+
- Interrupting, preempting, or cancelling the in-flight `running.cmd` task
|
|
59
|
+
- Changing first-dispatch / cold-open Terminal flows except shared response
|
|
60
|
+
fields needed for honesty
|
|
61
|
+
- Redesigning revise card chrome (038) or desk scroll (039)
|
|
62
|
+
- Remote push / promote to `main`
|
|
63
|
+
|
|
64
|
+
## Acceptance
|
|
65
|
+
|
|
66
|
+
1. When runner is healthy and `running.cmd` is present, revise / re-dispatch
|
|
67
|
+
writes `pending.cmd` and does **not** interrupt the current task
|
|
68
|
+
2. API returns honesty flags such that `queued` + `busy` (and `reused` when
|
|
69
|
+
same Terminal) are true in that case — UI can tell “queued, waiting” from
|
|
70
|
+
“started now”
|
|
71
|
+
3. UI does **not** claim the agent already started solely because reuse
|
|
72
|
+
succeeded; shows the queued/wait message (zh-CN + en)
|
|
73
|
+
4. Idle healthy runner reuse (no busy `running.cmd`) remains truthful; still
|
|
74
|
+
may reuse the same Terminal without the busy-wait message
|
|
75
|
+
5. After accepted delivery, revise still avoids false `--continue` (unchanged
|
|
76
|
+
policy; not regressed by this job)
|
|
77
|
+
6. E2E-041 documents busy-queue wait + honest UI/API
|
|
78
|
+
|
|
79
|
+
## Assumptions
|
|
80
|
+
|
|
81
|
+
- Runner already serializes: finish current → pick next `pending.cmd`; this
|
|
82
|
+
job makes that behavior **visible and honest**, not a new interrupt model
|
|
83
|
+
- Shared launch path in `bin/duaer-live.mjs` + `web/live-dev` i18n/UI are the
|
|
84
|
+
primary touch points
|
|
85
|
+
- Implementation deferred; Brief + tasks only for now
|