duaer-spec 0.24.0 → 0.25.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/.claude/rules/agents-workflow.md +2 -0
- package/.cursor/rules/agents-workflow.mdc +2 -0
- package/.cursor/rules/fde-8787-only.mdc +31 -0
- package/.duaer/active-job.json +3 -2
- package/.duaer/handoff.json +2 -2
- package/.duaer/memory/testing.md +17 -0
- package/.duaer/memory/verify.json +4 -0
- package/.duaer/specs/216-release-024/delivery.json +10 -0
- package/.duaer/specs/216-release-024/tasks.md +3 -3
- package/.duaer/specs/217-regression-employee-docs/delivery.json +10 -0
- package/.duaer/specs/217-regression-employee-docs/spec.md +12 -0
- package/.duaer/specs/217-regression-employee-docs/tasks.md +5 -0
- package/.duaer/specs/218-release-0241/delivery.json +10 -0
- package/.duaer/specs/218-release-0241/spec.md +16 -0
- package/.duaer/specs/218-release-0241/tasks.md +4 -0
- package/.duaer/specs/219-verify-gate/delivery.json +10 -0
- package/.duaer/specs/219-verify-gate/spec.md +26 -0
- package/.duaer/specs/219-verify-gate/tasks.md +5 -0
- package/.duaer/specs/220-project-activate-click/delivery.json +10 -0
- package/.duaer/specs/220-project-activate-click/spec.md +15 -0
- package/.duaer/specs/220-project-activate-click/tasks.md +4 -0
- package/.duaer/specs/221-wave-exit-preempt/delivery.json +14 -0
- package/.duaer/specs/221-wave-exit-preempt/spec.md +25 -0
- package/.duaer/specs/221-wave-exit-preempt/tasks.md +5 -0
- package/.duaer/specs/222-wave-exit-cat/delivery.json +10 -0
- package/.duaer/specs/222-wave-exit-cat/spec.md +14 -0
- package/.duaer/specs/222-wave-exit-cat/tasks.md +4 -0
- package/.duaer/specs/223-dispatch-center/delivery.json +10 -0
- package/.duaer/specs/223-dispatch-center/spec.md +16 -0
- package/.duaer/specs/223-dispatch-center/tasks.md +6 -0
- package/.duaer/specs/224-dispatch-center-page/delivery.json +10 -0
- package/.duaer/specs/224-dispatch-center-page/spec.md +15 -0
- package/.duaer/specs/224-dispatch-center-page/tasks.md +6 -0
- package/.duaer/specs/225-wave-retry/delivery.json +10 -0
- package/.duaer/specs/225-wave-retry/spec.md +15 -0
- package/.duaer/specs/225-wave-retry/tasks.md +5 -0
- package/.duaer/specs/226-progress-pollute/delivery.json +10 -0
- package/.duaer/specs/226-progress-pollute/spec.md +15 -0
- package/.duaer/specs/226-progress-pollute/tasks.md +5 -0
- package/.duaer/specs/227-desk-sqlite/delivery.json +14 -0
- package/.duaer/specs/227-desk-sqlite/spec.md +17 -0
- package/.duaer/specs/227-desk-sqlite/tasks.md +6 -0
- package/.duaer/specs/228-desk-sqlite-all/delivery.json +14 -0
- package/.duaer/specs/228-desk-sqlite-all/spec.md +30 -0
- package/.duaer/specs/228-desk-sqlite-all/tasks.md +6 -0
- package/.duaer/specs/229-task-decompose-graph/delivery.json +14 -0
- package/.duaer/specs/229-task-decompose-graph/spec.md +14 -0
- package/.duaer/specs/229-task-decompose-graph/tasks.md +6 -0
- package/.duaer/specs/230-graph-confirm-busy/delivery.json +15 -0
- package/.duaer/specs/230-graph-confirm-busy/spec.md +13 -0
- package/.duaer/specs/230-graph-confirm-busy/tasks.md +4 -0
- package/.duaer/specs/231-graph-edge-spacing/delivery.json +16 -0
- package/.duaer/specs/231-graph-edge-spacing/spec.md +12 -0
- package/.duaer/specs/231-graph-edge-spacing/tasks.md +6 -0
- package/.duaer/specs/232-fde-8787-only/delivery.json +15 -0
- package/.duaer/specs/232-fde-8787-only/spec.md +13 -0
- package/.duaer/specs/232-fde-8787-only/tasks.md +5 -0
- package/.duaer/specs/233-dispatch-graph-present/delivery.json +15 -0
- package/.duaer/specs/233-dispatch-graph-present/spec.md +13 -0
- package/.duaer/specs/233-dispatch-graph-present/tasks.md +5 -0
- package/.duaer/specs/234-dispatch-no-zoom/delivery.json +15 -0
- package/.duaer/specs/234-dispatch-no-zoom/spec.md +14 -0
- package/.duaer/specs/234-dispatch-no-zoom/tasks.md +5 -0
- package/.duaer/specs/235-dispatch-node-status/delivery.json +15 -0
- package/.duaer/specs/235-dispatch-node-status/spec.md +13 -0
- package/.duaer/specs/235-dispatch-node-status/tasks.md +5 -0
- package/.duaer/specs/236-open-external-8787/delivery.json +15 -0
- package/.duaer/specs/236-open-external-8787/spec.md +16 -0
- package/.duaer/specs/236-open-external-8787/tasks.md +5 -0
- package/.duaer/specs/237-graph-repo-evidence/delivery.json +15 -0
- package/.duaer/specs/237-graph-repo-evidence/spec.md +14 -0
- package/.duaer/specs/237-graph-repo-evidence/tasks.md +5 -0
- package/.duaer/specs/238-dispatch-stage/delivery.json +15 -0
- package/.duaer/specs/238-dispatch-stage/spec.md +14 -0
- package/.duaer/specs/238-dispatch-stage/tasks.md +5 -0
- package/.duaer/specs/239-bug-dispatch/delivery.json +13 -0
- package/.duaer/specs/239-bug-dispatch/spec.md +42 -0
- package/.duaer/specs/239-bug-dispatch/tasks.md +9 -0
- package/.duaer/specs/239-node-zoom/delivery.json +15 -0
- package/.duaer/specs/239-node-zoom/spec.md +12 -0
- package/.duaer/specs/239-node-zoom/tasks.md +4 -0
- package/.duaer/specs/240-dispatch-nav/delivery.json +15 -0
- package/.duaer/specs/240-dispatch-nav/spec.md +13 -0
- package/.duaer/specs/240-dispatch-nav/tasks.md +5 -0
- package/.duaer/specs/241-graph-wrap/delivery.json +15 -0
- package/.duaer/specs/241-graph-wrap/spec.md +15 -0
- package/.duaer/specs/241-graph-wrap/tasks.md +5 -0
- package/.duaer/specs/242-project-btn/delivery.json +14 -0
- package/.duaer/specs/242-project-btn/spec.md +13 -0
- package/.duaer/specs/242-project-btn/tasks.md +4 -0
- package/.duaer/specs/243-bug-kind-toggle/delivery.json +9 -0
- package/.duaer/specs/243-bug-kind-toggle/spec.md +12 -0
- package/.duaer/specs/243-bug-kind-toggle/tasks.md +6 -0
- package/.duaer/specs/243-graph-result-bar/delivery.json +11 -0
- package/.duaer/specs/243-graph-result-bar/spec.md +25 -0
- package/.duaer/specs/243-graph-result-bar/tasks.md +5 -0
- package/.duaer/specs/244-bug-btn-bottom/delivery.json +9 -0
- package/.duaer/specs/244-bug-btn-bottom/spec.md +12 -0
- package/.duaer/specs/244-bug-btn-bottom/tasks.md +5 -0
- package/.duaer/specs/245-preview-opaque/delivery.json +9 -0
- package/.duaer/specs/245-preview-opaque/spec.md +11 -0
- package/.duaer/specs/245-preview-opaque/tasks.md +4 -0
- package/.duaer/specs/246-bug-chat-autofill/delivery.json +14 -0
- package/.duaer/specs/246-bug-chat-autofill/spec.md +32 -0
- package/.duaer/specs/246-bug-chat-autofill/tasks.md +8 -0
- package/.duaer/specs/247-timeline-quicknav/delivery.json +13 -0
- package/.duaer/specs/247-timeline-quicknav/spec.md +23 -0
- package/.duaer/specs/247-timeline-quicknav/tasks.md +7 -0
- package/.duaer/specs/248-quicknav-visible/delivery.json +9 -0
- package/.duaer/specs/248-quicknav-visible/spec.md +17 -0
- package/.duaer/specs/248-quicknav-visible/tasks.md +4 -0
- package/.duaer/specs/249-result-cta-after-deploy/delivery.json +9 -0
- package/.duaer/specs/249-result-cta-after-deploy/spec.md +21 -0
- package/.duaer/specs/249-result-cta-after-deploy/tasks.md +4 -0
- package/.duaer/specs/250-release-025/spec.md +13 -0
- package/.duaer/specs/250-release-025/tasks.md +5 -0
- package/AGENTS.md +3 -0
- package/CHANGELOG.md +162 -0
- package/README.md +27 -3
- package/README.zh-CN.md +20 -3
- package/bin/duaer-live.mjs +684 -227
- package/bin/duaer.mjs +18 -9
- package/bin/live-archify.mjs +66 -0
- package/bin/live-bug-context.mjs +184 -0
- package/bin/live-deliverables.mjs +54 -36
- package/bin/live-desk-db.mjs +575 -0
- package/bin/live-modules.mjs +96 -0
- package/bin/live-orchestrate.mjs +69 -0
- package/bin/live-project-chat-key.mjs +13 -0
- package/bin/live-project-chat.mjs +68 -18
- package/bin/live-project-timeline.mjs +121 -0
- package/bin/live-verify-gate.mjs +378 -0
- package/bin/live-worktree-name.mjs +27 -11
- package/docs/agent/e2e-test-plan.md +64 -4
- package/docs/agent/live-desk.md +84 -23
- package/package.json +2 -2
- package/web/live-dev/app.js +904 -113
- package/web/live-dev/architecture-ir.mjs +15 -0
- package/web/live-dev/architecture-mount.mjs +103 -6
- package/web/live-dev/dispatch-center.html +102 -0
- package/web/live-dev/dispatch-center.js +351 -0
- package/web/live-dev/employee-catalog.mjs +1 -1
- package/web/live-dev/i18n-de.js +49 -5
- package/web/live-dev/i18n-es.js +48 -4
- package/web/live-dev/i18n-fr.js +49 -5
- package/web/live-dev/i18n-ja.js +49 -5
- package/web/live-dev/i18n-ko.js +48 -4
- package/web/live-dev/i18n-pt-BR.js +48 -4
- package/web/live-dev/i18n-ru.js +49 -5
- package/web/live-dev/i18n-vi.js +49 -5
- package/web/live-dev/i18n-zh-TW.js +48 -4
- package/web/live-dev/i18n.js +100 -8
- package/web/live-dev/index.html +107 -35
- package/web/live-dev/styles.css +308 -11
- package/web/live-dev/task-graph.mjs +318 -21
|
@@ -45,6 +45,8 @@ cd .worktree/feat-login
|
|
|
45
45
|
- Merge into **`develop`** when done (hotfix: **`main`**, then back-merge **`develop`**)
|
|
46
46
|
- **Handoff (mandatory):** stop worktree-bound processes → remove `.worktree/<id>` →
|
|
47
47
|
restart from primary checkout on `develop` (`duaer handoff [--run]`, `.duaer/handoff.json`)
|
|
48
|
+
- **FDE desk:** only `http://127.0.0.1:8787` (`com.duaer.live8787`). Never start
|
|
49
|
+
`duaer-live` on another port; do not open Cursor Browser just to check the desk
|
|
48
50
|
- Push only when the user explicitly asks (a deploy/hosting ask authorizes
|
|
49
51
|
the `gh` + push needed for that publish — see `docs/agent/deploy-github.md`)
|
|
50
52
|
- Promote **`develop` → `main`** only when the user asks to go online
|
|
@@ -48,6 +48,8 @@ cd .worktree/feat-login
|
|
|
48
48
|
- Merge into **`develop`** when done (hotfix: **`main`**, then back-merge **`develop`**)
|
|
49
49
|
- **Handoff (mandatory):** stop worktree-bound processes → remove `.worktree/<id>` →
|
|
50
50
|
restart from primary checkout on `develop` (`duaer handoff [--run]`, `.duaer/handoff.json`)
|
|
51
|
+
- **FDE desk:** only `http://127.0.0.1:8787` (`com.duaer.live8787`). Never start
|
|
52
|
+
`duaer-live` on another port; do not open Cursor Browser just to check the desk
|
|
51
53
|
- Push only when the user explicitly asks (a deploy/hosting ask authorizes
|
|
52
54
|
the `gh` + push needed for that publish — see `docs/agent/deploy-github.md`)
|
|
53
55
|
- Promote **`develop` → `main`** only when the user asks to go online
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: FDE live desk is only http://127.0.0.1:8787 — never alternate ports
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# FDE desk port (8787 only)
|
|
7
|
+
|
|
8
|
+
The Duaer-spec FDE desk has **one** URL:
|
|
9
|
+
|
|
10
|
+
`http://127.0.0.1:8787`
|
|
11
|
+
|
|
12
|
+
Managed by LaunchAgent `com.duaer.live8787`.
|
|
13
|
+
|
|
14
|
+
## Do
|
|
15
|
+
|
|
16
|
+
- Check / restart with `launchctl kickstart -k "gui/$(id -u)/com.duaer.live8787"`
|
|
17
|
+
- Verify with `curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8787/`
|
|
18
|
+
- After merge handoff, restart that LaunchAgent only (see `.duaer/handoff.json`)
|
|
19
|
+
- Open architecture / 派工图 via desk `POST /api/open-external` (OS browser on :8787)
|
|
20
|
+
|
|
21
|
+
## Do not
|
|
22
|
+
|
|
23
|
+
- Start `node bin/duaer-live.mjs` on any port other than **8787**
|
|
24
|
+
- Start a second desk when 8787 is already listening
|
|
25
|
+
- Use Cursor Browser / Simple Browser / browser MCP to open the desk or
|
|
26
|
+
architecture present pages — Cursor proxies those as random high ports
|
|
27
|
+
(`:62489`, `:64074`, …). That is **not** a second FDE server.
|
|
28
|
+
- Treat product preview ports (3000, 8081, …) as the FDE desk
|
|
29
|
+
|
|
30
|
+
Interactive `duaer live` may still open the OS browser once; LaunchAgent sets
|
|
31
|
+
`DUAER_LIVE_NO_BROWSER=1` so kickstart does not spam tabs.
|
package/.duaer/active-job.json
CHANGED
package/.duaer/handoff.json
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
"stop": "Stop any process whose working directory is under the request worktree (dev servers, file watchers, local APIs). Also stop the FDE desk if it was started from a worktree copy of duaer-live.",
|
|
5
5
|
"restartFromPrimary": true,
|
|
6
6
|
"commands": [
|
|
7
|
-
"launchctl kickstart -k \"gui/$(id -u)/com.duaer.live8787\" 2>/dev/null || (lsof -t -iTCP:8787 -sTCP:LISTEN | xargs kill 2>/dev/null; sleep 1; node bin/duaer-live.mjs --port 8787)"
|
|
7
|
+
"launchctl kickstart -k \"gui/$(id -u)/com.duaer.live8787\" 2>/dev/null || (lsof -t -iTCP:8787 -sTCP:LISTEN | xargs kill 2>/dev/null; sleep 1; DUAER_LIVE_NO_BROWSER=1 node bin/duaer-live.mjs --port 8787)"
|
|
8
8
|
]
|
|
9
9
|
},
|
|
10
|
-
"notes": "
|
|
10
|
+
"notes": "FDE desk is ONLY http://127.0.0.1:8787 (com.duaer.live8787). Never start duaer-live on another port. LaunchAgent sets DUAER_LIVE_NO_BROWSER=1 so kickstart does not open new browser tabs. After merge: remove worktree, then kickstart so routes load from primary checkout on develop."
|
|
11
11
|
}
|
package/.duaer/memory/testing.md
CHANGED
|
@@ -92,6 +92,23 @@ local **`develop`**:
|
|
|
92
92
|
A waiver must state: which level, why it cannot run now, and the follow-up.
|
|
93
93
|
“Too slow” alone is not enough if a subset command exists.
|
|
94
94
|
|
|
95
|
+
## Machine accept gate (live desk)
|
|
96
|
+
|
|
97
|
+
Product repos that ship through Duaer-spec FDE keep a short contract at
|
|
98
|
+
`.duaer/memory/verify.json`:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{ "commands": ["npm test"], "timeoutSec": 600 }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
When tasks are complete, or an employee writes `delivery.json` `accepted`, the
|
|
105
|
+
desk runs those commands in the worktree. A non-zero exit, or a missing /
|
|
106
|
+
invalid file, sets status back to `open` and stores the command, exit code, and
|
|
107
|
+
output tail on `delivery.verification`. Docs-only work with no commands uses
|
|
108
|
+
`{ "waiver": "docs-only" }`. The first command list is frozen for that dispatch
|
|
109
|
+
so a later waiver cannot replace it. `npx duaer-spec update` does not overwrite
|
|
110
|
+
an existing `verify.json`.
|
|
111
|
+
|
|
95
112
|
## Adopter profiles
|
|
96
113
|
|
|
97
114
|
Thick product examples (e.g. `examples/dianwu-flow/testing.md`) may add L5+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-19T14:05:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1"],
|
|
6
|
+
"commands": ["npm test (177 pass)", "gh release v0.24.0", "npm view duaer-spec version → 0.24.0"],
|
|
7
|
+
"result": "pass"
|
|
8
|
+
},
|
|
9
|
+
"summary": "Released 0.24.0 (deploy employee + common locales) to GitHub and npm."
|
|
10
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Tasks
|
|
2
2
|
|
|
3
|
-
- [
|
|
4
|
-
- [
|
|
5
|
-
- [
|
|
3
|
+
- [x] T001 Bump to 0.24.0 and move CHANGELOG
|
|
4
|
+
- [x] T002 Promote main; push; tag; gh release; npm
|
|
5
|
+
- [x] T003 Stamp accepted
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-19T14:10:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1"],
|
|
6
|
+
"commands": ["node import locale files", "npm test subset live-i18n-common"],
|
|
7
|
+
"result": "pass"
|
|
8
|
+
},
|
|
9
|
+
"summary": "Documented Functional regression employee in READMEs and desk drawer copy."
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Spec: Document Functional regression employee
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Explain the **Functional regression** digital employee in READMEs and desk
|
|
6
|
+
drawer copy so operators know what it verifies and what it must not change.
|
|
7
|
+
|
|
8
|
+
## Acceptance
|
|
9
|
+
|
|
10
|
+
- [ ] README.zh-CN / README.md have a three-role section with clear 功能回归 duties
|
|
11
|
+
- [ ] `employee.lead` / `employee.regression.cap` describe regression in zh/en/ja and other locales
|
|
12
|
+
- [ ] live-desk.md mentions regression boundaries
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-19T14:12:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1"],
|
|
6
|
+
"commands": ["npm test (177 pass)", "gh release v0.24.1", "npm view duaer-spec version → 0.24.1"],
|
|
7
|
+
"result": "pass"
|
|
8
|
+
},
|
|
9
|
+
"summary": "Released 0.24.1 (Functional regression employee docs) to GitHub and npm."
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# 218 — Release 0.24.1
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Ship 0.24.1: Functional regression digital employee docs (README + drawer).
|
|
6
|
+
|
|
7
|
+
## Scope
|
|
8
|
+
|
|
9
|
+
Bump version, CHANGELOG, promote develop → main, push, GitHub Release
|
|
10
|
+
`v0.24.1`, trigger npm Trusted Publishing.
|
|
11
|
+
|
|
12
|
+
## Acceptance
|
|
13
|
+
|
|
14
|
+
1. `package.json` is `0.24.1`; CHANGELOG has `0.24.1` (Unreleased cleared).
|
|
15
|
+
2. Tag `v0.24.1` on main; GitHub Release published.
|
|
16
|
+
3. npm shows `duaer-spec@0.24.1`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-19T23:10:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1", "L3"],
|
|
6
|
+
"commands": ["node --check bin/duaer-live.mjs", "npm test (185 pass)"],
|
|
7
|
+
"result": "pass"
|
|
8
|
+
},
|
|
9
|
+
"summary": "Desk runs verify.json before a delivery stamp can stick. Failed or missing contracts reopen accepted."
|
|
10
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# 219 — Machine verify gate
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
The live desk, not the digital employee, decides whether `delivery.json` may stay `accepted`.
|
|
6
|
+
|
|
7
|
+
## In scope
|
|
8
|
+
|
|
9
|
+
- Read the product worktree `.duaer/memory/verify.json`.
|
|
10
|
+
- When every task is checked, or the employee writes `accepted`, run `commands` in the worktree.
|
|
11
|
+
- Non-zero exit: set status back to `open`, store command / exit / tail on `delivery.verification`, enqueue the log on the regression lane (last lane when N≥2). Do not nudge “stamp accept”.
|
|
12
|
+
- Exit 0: allow `accepted` and keep the same evidence.
|
|
13
|
+
- Missing or invalid contract: do not accept. Status tells the operator the contract is missing or unreadable.
|
|
14
|
+
- `{ "waiver": "docs-only" }` with no commands passes without a shell. If a command list was already seen, later edits cannot replace it with a waiver.
|
|
15
|
+
- `init` / `update` must not overwrite an existing product `verify.json`.
|
|
16
|
+
|
|
17
|
+
## Out of scope
|
|
18
|
+
|
|
19
|
+
- Screen recordings, a second judge model, a new employee role, post-deploy browser checks.
|
|
20
|
+
- Parsing commands out of `testing.md` prose.
|
|
21
|
+
|
|
22
|
+
## Acceptance
|
|
23
|
+
|
|
24
|
+
1. A failing command cannot leave the job or deliverables page in the accepted state.
|
|
25
|
+
2. A passing command records the command and exit code on `delivery.json`.
|
|
26
|
+
3. The all-tasks-done “stamp accept” nudge is gone.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-20T01:20:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1", "L3"],
|
|
6
|
+
"commands": ["npm test (185 pass)"],
|
|
7
|
+
"result": "pass"
|
|
8
|
+
},
|
|
9
|
+
"summary": "Project activate click shows drawer errors and the drawer scrolls."
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 220 — Project activate click shows feedback
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Clicking「选为当前项目」always shows a result in the open project drawer.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
Validation only posted a chat bubble behind the drawer, so a missing name or description looked like a dead click. The drawer also clips overflow, so the button can sit below the fold.
|
|
10
|
+
|
|
11
|
+
## Acceptance
|
|
12
|
+
|
|
13
|
+
1. Missing path, name, or description shows the message in the drawer (`#historyErr`), not only in chat.
|
|
14
|
+
2. While activate is in flight, the button is disabled.
|
|
15
|
+
3. The project drawer scrolls so the button stays reachable.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-20T01:25:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1", "L3"],
|
|
6
|
+
"commands": [
|
|
7
|
+
"node --check bin/duaer-live.mjs",
|
|
8
|
+
"node --check bin/live-orchestrate.mjs",
|
|
9
|
+
"npm test (188 pass)"
|
|
10
|
+
],
|
|
11
|
+
"result": "pass"
|
|
12
|
+
},
|
|
13
|
+
"summary": "A finished wave that still holds the Terminal is preempted once the next job is queued."
|
|
14
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# 221 — Preempt a finished wave so the next job starts
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
After a wave's tasks are checked, the next queued `--continue` starts even if the CLI did not exit.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
The employee prints「本波完成,退出等编排器」and stays in the session. The desk already enqueued the next wave, then refuses to release that fingerprint again. The runner cannot dequeue until the leftover process dies, so the job looks stuck after the first wave.
|
|
10
|
+
|
|
11
|
+
## In scope
|
|
12
|
+
|
|
13
|
+
- On status poll, if `running.cmd`'s wave ids are all `[x]` and `queueDepth > 0`, preempt that session.
|
|
14
|
+
- Do not preempt a session whose own wave is still open.
|
|
15
|
+
|
|
16
|
+
## Out of scope
|
|
17
|
+
|
|
18
|
+
- Changing task assignment, verify.json, or the personal-intro product job.
|
|
19
|
+
- Killing the Terminal runner itself.
|
|
20
|
+
|
|
21
|
+
## Acceptance
|
|
22
|
+
|
|
23
|
+
1. A busy lane whose running script wave is fully checked, with a queued job, is preempted.
|
|
24
|
+
2. A busy lane whose running script wave is still open is not preempted, even if an earlier wave is done and the queue is non-empty.
|
|
25
|
+
3. The decision is covered by unit tests; live-desk docs and the E2E catalog record the behavior.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-20T01:32:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1", "L3"],
|
|
6
|
+
"commands": ["node --check bin/live-orchestrate.mjs", "npm test (188 pass)"],
|
|
7
|
+
"result": "pass"
|
|
8
|
+
},
|
|
9
|
+
"summary": "A queued continue preempts a leftover CLI even when running.cmd only cats the prompt file."
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# 222 — Preempt when the Terminal script does not name its wave
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
A queued continue starts even when `running.cmd` only `cat`s the prompt file.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
The first preempt only fired when `running.cmd` contained `- T00N:` lines. Live jobs store the wave in a prompt file that the next enqueue overwrites, so the desk saw no wave ids and left the leftover CLI in place.
|
|
10
|
+
|
|
11
|
+
## Acceptance
|
|
12
|
+
|
|
13
|
+
1. Busy lane, `queueDepth > 0`, and no wave ids in the running script → preempt.
|
|
14
|
+
2. Busy lane whose named wave is still open → do not preempt.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-20T01:45:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1", "L3"],
|
|
6
|
+
"commands": ["node --check web/live-dev/app.js", "npm test (188 pass)"],
|
|
7
|
+
"result": "pass"
|
|
8
|
+
},
|
|
9
|
+
"summary": "Dispatch center lists projects in a 100px rail and shows the selected project's dispatch graph."
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# 223 — Dispatch center
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Open a project's dispatch graph from a top control, not from hidden hint text.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
The line「与系统架构图同一排版…点击图可新页面全屏查看」is not visible on the desk. The graph needs a button and a place that stays on screen.
|
|
10
|
+
|
|
11
|
+
## Acceptance
|
|
12
|
+
|
|
13
|
+
1. The top bar has「调度中心」. Opening it hides the three-column desk and shows a two-pane view.
|
|
14
|
+
2. The left pane is 100px wide and lists current projects. Selecting one shows that project's dispatch graph on the right.
|
|
15
|
+
3. The dispatch card no longer shows that hint. A「查看派工图」button opens the center on the current project.
|
|
16
|
+
4. A project with no confirmed tasks shows a short empty line, not the graph.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Tasks
|
|
2
|
+
|
|
3
|
+
- [x] Top Dispatch center opens a two-pane view
|
|
4
|
+
- [x] Left rail is 100px and lists projects; the right pane shows that project's dispatch graph
|
|
5
|
+
- [x] Dispatch card hint is a button that opens the center on the current project
|
|
6
|
+
- [x] Empty projects show a short empty line
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-20T02:05:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1", "L3"],
|
|
6
|
+
"commands": ["node --check web/live-dev/app.js", "node --check web/live-dev/dispatch-center.js", "npm test (188 pass)"],
|
|
7
|
+
"result": "pass"
|
|
8
|
+
},
|
|
9
|
+
"summary": "Dispatch center is a separate page with a 100px project rail and the selected project's graph."
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 224 — Dispatch center is its own page
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Dispatch center opens a separate page, not a panel over the desk.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
The first version hid the three-column desk in place. It needs its own page.
|
|
10
|
+
|
|
11
|
+
## Acceptance
|
|
12
|
+
|
|
13
|
+
1. The top Dispatch center button and the dispatch-card button each open `/dispatch-center.html` in a new page.
|
|
14
|
+
2. That page has a title, a 100px project rail, and the selected project's dispatch graph.
|
|
15
|
+
3. The desk itself no longer hides behind an in-page overlay.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-20T02:20:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1", "L3"],
|
|
6
|
+
"commands": ["node --check bin/duaer-live.mjs", "npm test (190 pass)"],
|
|
7
|
+
"result": "pass"
|
|
8
|
+
},
|
|
9
|
+
"summary": "An unchecked released wave is enqueued again when the Terminal lane is idle."
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 225 — Requeue a lost wave
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
If a released wave is still unchecked and the Terminal lane is idle, enqueue it again.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
T007 was marked released, then the runner died and the queue emptied. The desk refused to release that fingerprint again, so the job looked in progress with nothing queued.
|
|
10
|
+
|
|
11
|
+
## Acceptance
|
|
12
|
+
|
|
13
|
+
1. An unchecked task-wave fingerprint is dropped when the lane is not busy and the queue is empty.
|
|
14
|
+
2. A checked wave, and a non-task fingerprint, stay released.
|
|
15
|
+
3. The drop happens before the next wave release, with a cooldown so a just-enqueued job is not duplicated.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-20T02:35:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1", "L3"],
|
|
6
|
+
"commands": ["node --check web/live-dev/app.js", "npm test (190 pass)"],
|
|
7
|
+
"result": "pass"
|
|
8
|
+
},
|
|
9
|
+
"summary": "Status poll ignores stale job responses so a new project does not keep the previous 派工进度."
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 226 — Status poll must not paint another project's progress
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Switching or creating a project must not keep showing the previous project's 派工进度.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
`clearDeskWorkspace` clears the timeline, but an in-flight `/api/status` from the old `jobId` can finish afterward and call `renderProgress`, so the new desk looks polluted until refresh.
|
|
10
|
+
|
|
11
|
+
## Acceptance
|
|
12
|
+
|
|
13
|
+
1. After a status poll returns, if `state.jobId` is no longer the job that was requested, do not apply progress, preview, or accepted chat bubbles.
|
|
14
|
+
2. Creating or switching to an empty project still clears the progress column; a stale poll cannot refill it.
|
|
15
|
+
3. Covered by a source marker test; E2E catalog updated.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-20T02:30:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1"],
|
|
6
|
+
"commands": [
|
|
7
|
+
"node --check bin/live-desk-db.mjs",
|
|
8
|
+
"node --test test/live-desk-db.test.mjs test/live-project-chat.test.mjs (14 pass)",
|
|
9
|
+
"npm test (195 pass)"
|
|
10
|
+
],
|
|
11
|
+
"result": "pass"
|
|
12
|
+
},
|
|
13
|
+
"summary": "Project desk sessions use ~/.duaer/live/desk.sqlite with automatic legacy JSON import and versioned schema migrations on open."
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# 227 — Desk project sessions in SQLite
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Store FDE project desk sessions in SQLite under `~/.duaer/live/desk.sqlite`, with automatic import of legacy JSON and a versioned schema for upgrades.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
Whole-file JSON rewrites for every persist are slow. Users who already have `project-chats/*.json` must keep their data when they install or upgrade duaer-spec.
|
|
10
|
+
|
|
11
|
+
## Acceptance
|
|
12
|
+
|
|
13
|
+
1. `readProjectChat` / `writeProjectChat` use SQLite; public API paths stay the same.
|
|
14
|
+
2. On first open of a live root, existing `project-chats/*.json` sessions are imported; re-open does not duplicate.
|
|
15
|
+
3. The database stores `schema_version`; opening a newer duaer-spec runs migrations in order.
|
|
16
|
+
4. `engines.node` requires a Node that ships `node:sqlite`.
|
|
17
|
+
5. Unit tests cover round-trip, JSON import, and schema version.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-20T02:50:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1"],
|
|
6
|
+
"commands": [
|
|
7
|
+
"node --check bin/live-desk-db.mjs bin/duaer-live.mjs",
|
|
8
|
+
"node --test test/live-desk-db.test.mjs (7 pass)",
|
|
9
|
+
"npm test (197 pass)"
|
|
10
|
+
],
|
|
11
|
+
"result": "pass"
|
|
12
|
+
},
|
|
13
|
+
"summary": "Config, repos, and live jobs join project sessions in desk.sqlite with legacy import; live root remains per-machine and never packaged."
|
|
14
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# 228 — Desk durable state fully in SQLite
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Keep all durable FDE live data in `~/.duaer/live/desk.sqlite` (config, repos, jobs, sessions). Architecture HTML stays a regenerable disk cache. Per-machine `~/.duaer/live` is never packaged or published with duaer-spec.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
Sessions alone left config / repos / jobs on JSON and directories. Operators expect one database; install/upgrade must import legacy files automatically. Local desk data must not ship to other users.
|
|
10
|
+
|
|
11
|
+
## In scope
|
|
12
|
+
|
|
13
|
+
1. Schema migration v2: `desk_kv` (config, repos) + `jobs` (id + files map).
|
|
14
|
+
2. On open: import legacy `config.json`, `repos.json`, and `jobs/*/…` when missing from the DB; do not delete legacy files.
|
|
15
|
+
3. Runtime read/write for config, repos, and live jobs use SQLite as source of truth; job directories are materialized so existing Brief paths keep working.
|
|
16
|
+
4. Docs/ADR/CHANGELOG/E2E note; unit tests for import + round-trip.
|
|
17
|
+
|
|
18
|
+
## Out of scope
|
|
19
|
+
|
|
20
|
+
- Publishing or bundling any user's `~/.duaer/live`
|
|
21
|
+
- Moving `architecture/` HTML into SQLite (regenerable cache)
|
|
22
|
+
- Moving product-repo worktree Briefs (those stay in the product repo)
|
|
23
|
+
|
|
24
|
+
## Acceptance
|
|
25
|
+
|
|
26
|
+
1. Config and repos load/save via SQLite; legacy files import once.
|
|
27
|
+
2. Live jobs import and round-trip (job.json / spec.md / tasks.md and other text files under the job dir).
|
|
28
|
+
3. Opening a newer desk runs migration to `DESK_SCHEMA_VERSION` ≥ 2.
|
|
29
|
+
4. Docs state that live data is local-only and never part of the npm package.
|
|
30
|
+
5. Targeted unit tests pass; `npm test` passes.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Tasks
|
|
2
|
+
|
|
3
|
+
- [x] Schema v2: desk_kv + jobs + legacy import for config/repos/jobs
|
|
4
|
+
- [x] Route config/repos/jobs IO through SQLite (materialize job dirs)
|
|
5
|
+
- [x] Update ADR 002, live-desk docs, CHANGELOG, E2E-172/173
|
|
6
|
+
- [x] Unit tests + npm test; stamp delivery accepted
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "accepted",
|
|
3
|
+
"acceptedAt": "2026-09-20T03:20:00.000Z",
|
|
4
|
+
"verification": {
|
|
5
|
+
"levels": ["L0", "L1", "L3"],
|
|
6
|
+
"commands": [
|
|
7
|
+
"node --check web/live-dev/app.js web/live-dev/task-graph.mjs",
|
|
8
|
+
"npm test (200 pass)",
|
|
9
|
+
"npm run test:live (1 pass)"
|
|
10
|
+
],
|
|
11
|
+
"result": "pass"
|
|
12
|
+
},
|
|
13
|
+
"summary": "After architecture confirm, decompose atomic tasks with parallel marks, recommend 1–4 workers, and generate the dispatch graph only after count confirm (revise same gate)."
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# 229 — Task decompose → recommend workers → dispatch graph
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
After architecture confirm (and on revise re-confirm), decompose atomic tasks with parallel marks, recommend 1–4 digital employees, and generate the dispatch graph only after the operator confirms the count.
|
|
6
|
+
|
|
7
|
+
## Acceptance
|
|
8
|
+
|
|
9
|
+
1. Dispatch panel appears only after architecture is confirmed.
|
|
10
|
+
2. Atomic task list is visible above Digital employees; parallelizable tasks are marked.
|
|
11
|
+
3. System recommends worker count (1–4) from parallel width; user can change it.
|
|
12
|
+
4. Confirm count generates the dispatch graph; graph is gated until then.
|
|
13
|
+
5. Revise path uses the same gate after architecture re-confirm.
|
|
14
|
+
6. Docs/E2E/i18n/tests updated; risk verification passes.
|