viepilot 1.14.0 → 2.1.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/README.md +3 -3
  3. package/bin/viepilot.cjs +7 -5
  4. package/bin/vp-tools.cjs +193 -0
  5. package/dev-install.sh +34 -13
  6. package/docs/user/features/hooks.md +93 -0
  7. package/lib/adapters/claude-code.cjs +42 -0
  8. package/lib/adapters/cursor.cjs +31 -0
  9. package/lib/adapters/index.cjs +26 -0
  10. package/lib/hooks/brainstorm-staleness.cjs +231 -0
  11. package/lib/viepilot-config.cjs +103 -0
  12. package/lib/viepilot-install.cjs +128 -153
  13. package/package.json +1 -1
  14. package/skills/vp-audit/SKILL.md +21 -21
  15. package/skills/vp-auto/SKILL.md +21 -7
  16. package/skills/vp-brainstorm/SKILL.md +42 -36
  17. package/skills/vp-crystallize/SKILL.md +22 -16
  18. package/skills/vp-debug/SKILL.md +2 -2
  19. package/skills/vp-docs/SKILL.md +7 -7
  20. package/skills/vp-evolve/SKILL.md +25 -12
  21. package/skills/vp-info/SKILL.md +23 -23
  22. package/skills/vp-pause/SKILL.md +5 -5
  23. package/skills/vp-request/SKILL.md +12 -12
  24. package/skills/vp-resume/SKILL.md +4 -4
  25. package/skills/vp-rollback/SKILL.md +3 -3
  26. package/skills/vp-status/SKILL.md +4 -4
  27. package/skills/vp-task/SKILL.md +2 -2
  28. package/skills/vp-ui-components/SKILL.md +12 -12
  29. package/skills/vp-update/SKILL.md +17 -17
  30. package/templates/architect/apis.html +11 -10
  31. package/templates/architect/architect-actions.js +217 -0
  32. package/templates/architect/architecture.html +8 -7
  33. package/templates/architect/data-flow.html +5 -4
  34. package/templates/architect/decisions.html +4 -3
  35. package/templates/architect/deployment.html +10 -9
  36. package/templates/architect/erd.html +7 -6
  37. package/templates/architect/feature-map.html +5 -4
  38. package/templates/architect/sequence-diagram.html +6 -5
  39. package/templates/architect/style.css +146 -0
  40. package/templates/architect/tech-notes.html +3 -2
  41. package/templates/architect/tech-stack.html +8 -7
  42. package/templates/architect/user-use-cases.html +8 -7
  43. package/templates/project/AI-GUIDE.md +49 -49
  44. package/workflows/audit.md +3 -3
  45. package/workflows/autonomous.md +38 -5
  46. package/workflows/brainstorm.md +398 -222
  47. package/workflows/crystallize.md +46 -33
  48. package/workflows/debug.md +9 -9
  49. package/workflows/documentation.md +5 -5
  50. package/workflows/evolve.md +44 -12
  51. package/workflows/pause-work.md +2 -2
  52. package/workflows/request.md +8 -8
  53. package/workflows/resume-work.md +1 -1
  54. package/workflows/rollback.md +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: vp-resume
3
- description: "Resume work từ previous session với full context restoration"
3
+ description: "Resume work from previous session with full context restoration"
4
4
  version: 0.1.1
5
5
  ---
6
6
 
@@ -10,7 +10,7 @@ version: 0.1.1
10
10
  - Treat all user text after the skill mention as `{{VP_ARGS}}`
11
11
 
12
12
  ## B. User Prompting
13
- Prompt user conversationally với options.
13
+ Prompt user conversationally with options.
14
14
 
15
15
  ## C. Tool Usage
16
16
  Use Cursor tools: `Shell`, `ReadFile`, `Glob`, `rg`, `ApplyPatch`, `WebSearch`, `WebFetch`, `Subagent`
@@ -25,12 +25,12 @@ Use Cursor tools: `Shell`, `ReadFile`, `Glob`, `rg`, `ApplyPatch`, `WebSearch`,
25
25
  <implementation_routing_guard>
26
26
  ## Implementation routing guard (ENH-021)
27
27
 
28
- - **Khôi phục context** — không implement shipping mặc định; tiếp tục **`/vp-auto`** khi task plan. Xem `workflows/request.md`.
28
+ - **Restore context** — does not implement default shipping; continue with **`/vp-auto`** when a task plan exists. See `workflows/request.md`.
29
29
  </implementation_routing_guard>
30
30
 
31
31
 
32
32
  <objective>
33
- Restore complete project context resume work seamlessly.
33
+ Restore complete project context and resume work seamlessly.
34
34
 
35
35
  **Reads:**
36
36
  - `.viepilot/HANDOFF.json`
@@ -25,14 +25,14 @@ Use Cursor tools: `Shell`, `ReadFile`, `Glob`, `rg`, `ApplyPatch`, `WebSearch`,
25
25
  <implementation_routing_guard>
26
26
  ## Implementation routing guard (ENH-021)
27
27
 
28
- - **Checkpoint / revert** — không thay **`/vp-auto`** cho work mới; sau rollback dùng **`/vp-evolve`** / **`/vp-auto`** theo quy trình. Xem `workflows/request.md`.
28
+ - **Checkpoint / revert** — does not replace **`/vp-auto`** for new work; after rollback use **`/vp-evolve`** / **`/vp-auto`** per workflow. See `workflows/request.md`.
29
29
  </implementation_routing_guard>
30
30
 
31
31
 
32
32
  <objective>
33
- Rollback đến bất kỳ checkpoint nào một cách an toàn, với backup state preservation.
33
+ Rollback to any checkpoint safely, with backup and state preservation.
34
34
 
35
- **Checkpoints:** Git tags với prefix `vp-`
35
+ **Checkpoints:** Git tags with prefix `vp-`
36
36
  - `vp-p{N}-t{M}` - Start of task M in phase N
37
37
  - `vp-p{N}-t{M}-done` - Task M complete
38
38
  - `vp-p{N}-complete` - Phase N complete
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: vp-status
3
- description: "Hiển thị progress dashboard actionable insights"
3
+ description: "Display progress dashboard and actionable insights"
4
4
  version: 0.1.1
5
5
  ---
6
6
 
@@ -22,12 +22,12 @@ Use Cursor tools: `Shell`, `ReadFile`, `Glob`, `rg`, `ApplyPatch`, `WebSearch`,
22
22
  <implementation_routing_guard>
23
23
  ## Implementation routing guard (ENH-021)
24
24
 
25
- - **Read-only / dashboard** — không implement shipping; **`/vp-evolve`** → **`/vp-auto`**. Xem `workflows/request.md`.
25
+ - **Read-only / dashboard** — does not implement shipping; **`/vp-evolve`** → **`/vp-auto`**. See `workflows/request.md`.
26
26
  </implementation_routing_guard>
27
27
 
28
28
 
29
29
  <objective>
30
- Hiển thị visual progress dashboard với actionable insights.
30
+ Display a visual progress dashboard with actionable insights.
31
31
 
32
32
  **Reads:**
33
33
  - `.viepilot/TRACKER.md`
@@ -35,7 +35,7 @@ Hiển thị visual progress dashboard với actionable insights.
35
35
  - `.viepilot/phases/*/PHASE-STATE.md`
36
36
  - `CHANGELOG.md`
37
37
 
38
- **Output:** Dashboard display với next action suggestions.
38
+ **Output:** Dashboard display with next action suggestions.
39
39
  </objective>
40
40
 
41
41
  <process>
@@ -22,12 +22,12 @@ Use Cursor tools: `Shell`, `ReadFile`, `Glob`, `rg`, `ApplyPatch`, `WebSearch`,
22
22
  <implementation_routing_guard>
23
23
  ## Implementation routing guard (ENH-021)
24
24
 
25
- - Skill này **chỉ** quản **state/tag/task** trong `.viepilot/` — **không** thay **`/vp-auto`** để implement shipping code. Implement: **`/vp-auto`** hoặc user **explicit** override. Chuỗi plan: **`/vp-evolve`** trước. Xem `workflows/request.md`.
25
+ - This skill **only** manages **state/tag/task** in `.viepilot/` — does **not** replace **`/vp-auto`** for implementing shipping code. To implement: use **`/vp-auto`** or user **explicit** override. Plan chain: **`/vp-evolve`** first. See `workflows/request.md`.
26
26
  </implementation_routing_guard>
27
27
 
28
28
 
29
29
  <objective>
30
- Manual control over tasks khi cần fine-grained management.
30
+ Manual control over tasks when fine-grained management is needed.
31
31
 
32
32
  **Commands:**
33
33
  - `list` - List tasks in current phase
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: vp-ui-components
3
- description: "Quản workflow sưu tầm tái sử dụng UI components"
3
+ description: "Manage workflow for collecting and reusing UI components"
4
4
  version: 0.1.1
5
5
  ---
6
6
 
@@ -10,7 +10,7 @@ version: 0.1.1
10
10
  - Treat all user text after the skill mention as `{{VP_ARGS}}`
11
11
 
12
12
  ## B. User Prompting
13
- Prompt user conversationally với numbered list options.
13
+ Prompt user conversationally with numbered list options.
14
14
 
15
15
  ## C. Tool Usage
16
16
  Use Cursor tools: `Shell`, `ReadFile`, `Glob`, `rg`, `ApplyPatch`, `WebSearch`, `WebFetch`, `Subagent`
@@ -25,23 +25,23 @@ Use Cursor tools: `Shell`, `ReadFile`, `Glob`, `rg`, `ApplyPatch`, `WebSearch`,
25
25
  <implementation_routing_guard>
26
26
  ## Implementation routing guard (ENH-021)
27
27
 
28
- - **Curation** `ui-components/` + metadata — không implement toàn bộ feature app / framework shipping mặc định; thay đổi lớn **`/vp-evolve`** → **`/vp-auto`**. Xem `workflows/request.md`.
28
+ - **Curation** `ui-components/` + metadata — does not implement full app feature / default framework shipping; large changes go through **`/vp-evolve`** → **`/vp-auto`**. See `workflows/request.md`.
29
29
  </implementation_routing_guard>
30
30
 
31
31
 
32
32
  <objective>
33
- Thu thập, phân loại, lưu trữ UI components để tái sử dụng:
33
+ Collect, classify, and store UI components for reuse:
34
34
  - Global library: `~/.viepilot/ui-components/`
35
35
  - Project library: `.viepilot/ui-components/`
36
36
 
37
- Nguồn thể đến từ prompt/link/snippet (đặc biệt 21st.dev), sau đó chuẩn hóa thành artifacts metadata.
37
+ Sources can come from prompt/link/snippet (especially 21st.dev), then normalized into artifacts with metadata.
38
38
 
39
39
  **Creates/Updates:**
40
40
  - `~/.viepilot/ui-components/{category}/{component-id}/...`
41
41
  - `.viepilot/ui-components/{category}/{component-id}/...`
42
- - `INDEX.md` cho global + local store
42
+ - `INDEX.md` for global + local store
43
43
 
44
- **After:** Component thể dùng lại cho `/vp-brainstorm --ui` `/vp-crystallize`.
44
+ **After:** Component is reusable for `/vp-brainstorm --ui` and `/vp-crystallize`.
45
45
  </objective>
46
46
 
47
47
  <execution_context>
@@ -50,11 +50,11 @@ Nguồn có thể đến từ prompt/link/snippet (đặc biệt 21st.dev), sau
50
50
 
51
51
  <context>
52
52
  Optional flags:
53
- - `--add` : Add/capture component mới
54
- - `--list` : Liệt component theo category
55
- - `--sync` : Đồng bộ global ↔ local index
56
- - `--from-21st` : Ưu tiên flow ingest từ 21st.dev references
57
- - `--approve` : Mark component status thành approved
53
+ - `--add` : Add/capture new component
54
+ - `--list` : List components by category
55
+ - `--sync` : Sync global ↔ local index
56
+ - `--from-21st` : Prioritize ingest flow from 21st.dev references
57
+ - `--approve` : Mark component status as approved
58
58
  </context>
59
59
 
60
60
  <process>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: vp-update
3
- description: "Nâng cấp package viepilot qua npm (dry-run, --yes, --global) qua vp-tools"
3
+ description: "Upgrade viepilot package via npm (dry-run, --yes, --global) via vp-tools"
4
4
  version: 0.1.1
5
5
  ---
6
6
 
@@ -22,18 +22,18 @@ Use Cursor tools: `Shell`, `ReadFile`, `Glob`, `rg`, `ApplyPatch`, `WebSearch`,
22
22
  <implementation_routing_guard>
23
23
  ## Implementation routing guard (ENH-021)
24
24
 
25
- - **Nâng cấp ViePilot package** (npm) — không implement feature product trong repo đang làm việc mặc định; feature code qua **`/vp-auto`**. Xem `workflows/request.md`.
25
+ - **Upgrade ViePilot package** (npm) — does not implement product features in the working repo by default; feature code goes through **`/vp-auto`**. See `workflows/request.md`.
26
26
  </implementation_routing_guard>
27
27
 
28
28
 
29
29
  <objective>
30
- Chạy **`vp-tools update`** để lên kế hoạch và (khi được xác nhận) thực thi `npm` nâng cấp `viepilot`.
30
+ Run **`vp-tools update`** to plan and (when confirmed) execute the `npm` upgrade of `viepilot`.
31
31
 
32
- **Ràng buộc an toàn:**
33
- - **Non-interactive** (CI, agent không TTY): bắt buộc **`--dry-run`** hoặc **`--yes`**; nếu không sẽ exit lỗi.
34
- - Luôn ưu tiên **`--dry-run`** trước khi apply, trừ khi user đã yêu cầu apply.
32
+ **Safety constraints:**
33
+ - **Non-interactive** (CI, agent without TTY): **`--dry-run`** or **`--yes`** is required; otherwise exits with an error.
34
+ - Always prefer **`--dry-run`** before applying, unless the user has explicitly requested to apply.
35
35
 
36
- **Phân biệt target:** trong repo **không phải** ViePilot nhưng `node_modules/viepilot`, lệnh thể cập nhật **local dependency**. Muốn chỉ nâng **global**, thêm **`--global`**.
36
+ **Target distinction:** in a repo that is **not** ViePilot but has `node_modules/viepilot`, the command may update the **local dependency**. To upgrade only the **global** install, add **`--global`**.
37
37
  </objective>
38
38
 
39
39
  <execution_context>
@@ -42,31 +42,31 @@ Chạy **`vp-tools update`** để lên kế hoạch và (khi được xác nh
42
42
 
43
43
  <process>
44
44
 
45
- ### Step 1: Dry run (mặc định khi tự động)
45
+ ### Step 1: Dry run (default when automated)
46
46
  ```bash
47
47
  vp-tools update --dry-run
48
48
  ```
49
- Đọc output: planned npm command, phiên bản hiện tại vs latest, cảnh báo ambiguous/global.
49
+ Read output: planned npm command, current version vs latest, ambiguous/global warnings.
50
50
 
51
- ### Step 2: Apply (sau khi user đồng ý hoặc đã yêu cầu rõ)
51
+ ### Step 2: Apply (after user confirms or explicitly requests it)
52
52
  ```bash
53
53
  vp-tools update --yes
54
54
  ```
55
- Hoặc ép global:
55
+ Or force global:
56
56
  ```bash
57
57
  vp-tools update --global --dry-run
58
58
  vp-tools update --global --yes
59
59
  ```
60
60
 
61
61
  ### Step 3: Interactive
62
- Nếu terminal tương tác **không** `--yes`, CLI thể hỏi xác nhận trước khi chạy npm.
62
+ If the terminal is interactive and **no** `--yes` flag is present, the CLI may prompt for confirmation before running npm.
63
63
 
64
- ### Step 4: Rollback gợi ý
65
- Output dry-run/update thường gợi ý `npm install -g viepilot@<previous>` — giữ phiên bản từ `vp-tools info` nếu cần hoàn tác.
64
+ ### Step 4: Suggested rollback
65
+ Dry-run/update output typically suggests `npm install -g viepilot@<previous>` — keep the previous version from `vp-tools info` in case a rollback is needed.
66
66
  </process>
67
67
 
68
68
  <success_criteria>
69
- - [ ] Không chạy apply trong non-interactive thiếu `--yes`
70
- - [ ] Nêu target (local vs global) khi user đang project lạ
71
- - [ ] Ghi nhận khi đã `already up to date` (no-op thành công)
69
+ - [ ] Do not run apply in non-interactive mode without `--yes`
70
+ - [ ] Clearly state target (local vs global) when user is in an external project
71
+ - [ ] Acknowledge when `already up to date` (successful no-op)
72
72
  </success_criteria>
@@ -6,7 +6,7 @@
6
6
  <title>APIs — {project}</title>
7
7
  <link rel="stylesheet" href="style.css" />
8
8
  </head>
9
- <body>
9
+ <body data-arch-slug="apis">
10
10
  <nav class="nav-sidebar">
11
11
  <div class="logo">
12
12
  <span>ViePilot Architect Mode</span>
@@ -52,7 +52,7 @@
52
52
  </tr>
53
53
  </thead>
54
54
  <tbody>
55
- <tr>
55
+ <tr data-arch-id="A1">
56
56
  <td><span class="badge method-get">GET</span></td>
57
57
  <td>/api/resource</td>
58
58
  <td>Yes</td>
@@ -61,7 +61,7 @@
61
61
  <td>200, 401, 500</td>
62
62
  <td>{Notes}</td>
63
63
  </tr>
64
- <tr>
64
+ <tr data-arch-id="A2">
65
65
  <td><span class="badge method-post">POST</span></td>
66
66
  <td>/api/resource</td>
67
67
  <td>Yes</td>
@@ -70,7 +70,7 @@
70
70
  <td>201, 400, 401</td>
71
71
  <td>{Notes}</td>
72
72
  </tr>
73
- <tr>
73
+ <tr data-arch-id="A3">
74
74
  <td><span class="badge method-put">PUT</span></td>
75
75
  <td>/api/resource/:id</td>
76
76
  <td>Yes</td>
@@ -79,7 +79,7 @@
79
79
  <td>200, 400, 404</td>
80
80
  <td>{Notes}</td>
81
81
  </tr>
82
- <tr>
82
+ <tr data-arch-id="A4">
83
83
  <td><span class="badge method-delete">DELETE</span></td>
84
84
  <td>/api/resource/:id</td>
85
85
  <td>Yes</td>
@@ -88,7 +88,7 @@
88
88
  <td>200, 404</td>
89
89
  <td>{Notes}</td>
90
90
  </tr>
91
- <tr>
91
+ <tr data-arch-id="A5">
92
92
  <td><span class="badge method-patch">PATCH</span></td>
93
93
  <td>/api/resource/:id</td>
94
94
  <td>Yes</td>
@@ -113,7 +113,7 @@
113
113
  </tr>
114
114
  </thead>
115
115
  <tbody>
116
- <tr>
116
+ <tr data-arch-id="A6">
117
117
  <td>API Style</td>
118
118
  <td>
119
119
  <span class="badge method-get">REST</span>
@@ -124,19 +124,19 @@
124
124
  <td>{Rationale}</td>
125
125
  <td>{Notes}</td>
126
126
  </tr>
127
- <tr>
127
+ <tr data-arch-id="A7">
128
128
  <td>Authentication</td>
129
129
  <td>{JWT / Session / OAuth2 / API Key}</td>
130
130
  <td>{Rationale}</td>
131
131
  <td>{Notes}</td>
132
132
  </tr>
133
- <tr>
133
+ <tr data-arch-id="A8">
134
134
  <td>Versioning</td>
135
135
  <td>{URL path / Header / None}</td>
136
136
  <td>{Rationale}</td>
137
137
  <td>{Notes}</td>
138
138
  </tr>
139
- <tr>
139
+ <tr data-arch-id="A9">
140
140
  <td>Rate limiting</td>
141
141
  <td>{Strategy}</td>
142
142
  <td>{Rationale}</td>
@@ -154,5 +154,6 @@
154
154
  document.getElementById('theme-toggle').textContent = isLight ? '🌙 Dark' : '☀️ Light';
155
155
  }
156
156
  </script>
157
+ <script src="architect-actions.js"></script>
157
158
  </body>
158
159
  </html>
@@ -0,0 +1,217 @@
1
+ /**
2
+ * ViePilot Architect Item Actions (ENH-033)
3
+ *
4
+ * Injects per-item Approve / Edit prompt-copy buttons into every element
5
+ * marked with [data-arch-id] in the Architect HTML workspace.
6
+ *
7
+ * ISOLATION RULE: Each action is scoped exclusively to the identified item
8
+ * on the identified page. Approving one item does NOT imply approval of any
9
+ * related item on any other page. Cross-page updates require separate prompts.
10
+ *
11
+ * Prompt formats:
12
+ * APPROVE: [ARCH:{slug}:{id}] APPROVE — "{title}" on {slug} page. No changes needed.
13
+ * EDIT: [ARCH:{slug}:{id}] EDIT — "{title}" on {slug} page. Current: "{excerpt}". What should I change?
14
+ */
15
+
16
+ (function () {
17
+ 'use strict';
18
+
19
+ // ── Prompt templates ──────────────────────────────────────────────────────
20
+
21
+ function approvePrompt(slug, id, title) {
22
+ return '[ARCH:' + slug + ':' + id + '] APPROVE — "' + title + '" on ' + slug + ' page. No changes needed.';
23
+ }
24
+
25
+ function editPrompt(slug, id, title, excerpt) {
26
+ var body = excerpt ? ' Current: "' + excerpt + '".' : '';
27
+ return '[ARCH:' + slug + ':' + id + '] EDIT — "' + title + '" on ' + slug + ' page.' + body + ' What should I change?';
28
+ }
29
+
30
+ // ── Clipboard helper ─────────────────────────────────────────────────────
31
+
32
+ function copyText(text, btn) {
33
+ var original = btn.textContent;
34
+ function onDone() {
35
+ btn.textContent = 'Copied!';
36
+ btn.classList.add('copied');
37
+ setTimeout(function () {
38
+ btn.textContent = original;
39
+ btn.classList.remove('copied');
40
+ }, 1500);
41
+ }
42
+ if (navigator.clipboard && navigator.clipboard.writeText) {
43
+ navigator.clipboard.writeText(text).then(onDone).catch(function () {
44
+ legacyCopy(text);
45
+ onDone();
46
+ });
47
+ } else {
48
+ legacyCopy(text);
49
+ onDone();
50
+ }
51
+ }
52
+
53
+ function legacyCopy(text) {
54
+ var ta = document.createElement('textarea');
55
+ ta.value = text;
56
+ ta.style.cssText = 'position:fixed;top:0;left:0;opacity:0;pointer-events:none;';
57
+ document.body.appendChild(ta);
58
+ ta.focus();
59
+ ta.select();
60
+ try { document.execCommand('copy'); } catch (e) { /* silent */ }
61
+ document.body.removeChild(ta);
62
+ }
63
+
64
+ // ── Text extraction ───────────────────────────────────────────────────────
65
+
66
+ function getTitle(el) {
67
+ if (el.dataset.archTitle) return el.dataset.archTitle.trim().slice(0, 80);
68
+ // Table row: first <td>
69
+ if (el.tagName === 'TR') {
70
+ var td = el.querySelector('td');
71
+ if (td) return td.textContent.trim().slice(0, 80);
72
+ }
73
+ // Card/div: heading
74
+ var h = el.querySelector('h2,h3,h4,h5');
75
+ if (h) return h.textContent.trim().slice(0, 80);
76
+ return el.textContent.trim().slice(0, 80);
77
+ }
78
+
79
+ function getExcerpt(el) {
80
+ if (el.dataset.archExcerpt) return el.dataset.archExcerpt.trim().slice(0, 100);
81
+ // Table row: second <td>
82
+ if (el.tagName === 'TR') {
83
+ var tds = el.querySelectorAll('td');
84
+ if (tds.length >= 2) return tds[1].textContent.trim().slice(0, 100);
85
+ }
86
+ // Card/div: first <p>
87
+ var p = el.querySelector('p');
88
+ if (p) return p.textContent.trim().slice(0, 100);
89
+ return '';
90
+ }
91
+
92
+ // ── Build actions DOM ─────────────────────────────────────────────────────
93
+
94
+ function makeActionsEl(slug, id, title, excerpt) {
95
+ var wrap = document.createElement('div');
96
+ wrap.className = 'arch-item-actions';
97
+
98
+ var badge = document.createElement('span');
99
+ badge.className = 'arch-id-badge';
100
+ badge.textContent = id;
101
+ badge.title = 'Item ID: [ARCH:' + slug + ':' + id + ']';
102
+
103
+ var btnApprove = document.createElement('button');
104
+ btnApprove.className = 'arch-btn arch-btn-approve';
105
+ btnApprove.textContent = '✅ Approve';
106
+ btnApprove.title = 'Copy APPROVE prompt — scoped to this item only';
107
+ btnApprove.type = 'button';
108
+ btnApprove.addEventListener('click', function (e) {
109
+ e.stopPropagation();
110
+ copyText(approvePrompt(slug, id, title), btnApprove);
111
+ });
112
+
113
+ var btnEdit = document.createElement('button');
114
+ btnEdit.className = 'arch-btn arch-btn-edit';
115
+ btnEdit.textContent = '✏️ Edit';
116
+ btnEdit.title = 'Copy EDIT prompt — scoped to this item only';
117
+ btnEdit.type = 'button';
118
+ btnEdit.addEventListener('click', function (e) {
119
+ e.stopPropagation();
120
+ copyText(editPrompt(slug, id, title, excerpt), btnEdit);
121
+ });
122
+
123
+ wrap.appendChild(badge);
124
+ wrap.appendChild(btnApprove);
125
+ wrap.appendChild(btnEdit);
126
+ return wrap;
127
+ }
128
+
129
+ // ── Inject into page ──────────────────────────────────────────────────────
130
+
131
+ function inject() {
132
+ var slug = (document.body.dataset.archSlug || 'unknown').trim();
133
+ var items = document.querySelectorAll('[data-arch-id]');
134
+
135
+ items.forEach(function (el) {
136
+ var id = el.dataset.archId;
137
+ if (!id) return;
138
+ var title = getTitle(el);
139
+ var excerpt = getExcerpt(el);
140
+ var actionsEl = makeActionsEl(slug, id, title, excerpt);
141
+
142
+ if (el.tagName === 'TR') {
143
+ // Ensure thead gets an empty actions header column (once per table)
144
+ var table = el.closest('table');
145
+ if (table) {
146
+ var theadRow = table.querySelector('thead tr');
147
+ if (theadRow && !theadRow.querySelector('.arch-actions-th')) {
148
+ var th = document.createElement('th');
149
+ th.className = 'arch-actions-th';
150
+ theadRow.appendChild(th);
151
+ }
152
+ }
153
+ var td = document.createElement('td');
154
+ td.className = 'arch-actions-cell';
155
+ td.appendChild(actionsEl);
156
+ el.appendChild(td);
157
+ } else {
158
+ // Card / div: insert after first child (heading area)
159
+ var first = el.firstElementChild;
160
+ if (first && first.nextSibling) {
161
+ el.insertBefore(actionsEl, first.nextSibling);
162
+ } else if (first) {
163
+ el.appendChild(actionsEl);
164
+ } else {
165
+ el.prepend(actionsEl);
166
+ }
167
+ }
168
+ });
169
+ }
170
+
171
+ // ── Stale / gap badge injection (ENH-034) ────────────────────────────────
172
+ // Items with data-arch-stale="true" get an amber "⚠ gap" badge.
173
+ // Stale means: brainstorm detected a gap here; HTML not yet synced.
174
+
175
+ function injectStaleBadges() {
176
+ document.querySelectorAll('[data-arch-stale="true"]').forEach(function (el) {
177
+ var reason = el.getAttribute('data-arch-stale-note') || 'gap detected in brainstorm';
178
+ var badge = document.createElement('span');
179
+ badge.className = 'arch-gap-badge';
180
+ badge.textContent = '⚠ gap';
181
+ badge.title = reason;
182
+
183
+ if (el.tagName === 'TR') {
184
+ var firstTd = el.querySelector('td');
185
+ if (firstTd && !firstTd.querySelector('.arch-gap-badge')) {
186
+ firstTd.appendChild(badge);
187
+ }
188
+ } else {
189
+ var h = el.querySelector('h2,h3,h4');
190
+ if (h && !h.querySelector('.arch-gap-badge')) {
191
+ h.appendChild(badge);
192
+ }
193
+ }
194
+ });
195
+ }
196
+
197
+ function markStale(id, reason) {
198
+ var el = document.querySelector('[data-arch-id="' + id + '"]');
199
+ if (!el) return;
200
+ el.setAttribute('data-arch-stale', 'true');
201
+ if (reason) el.setAttribute('data-arch-stale-note', reason);
202
+ injectStaleBadges();
203
+ }
204
+
205
+ // Expose for browser console use during architect review sessions
206
+ window.vpMarkStale = markStale;
207
+
208
+ if (document.readyState === 'loading') {
209
+ document.addEventListener('DOMContentLoaded', function () {
210
+ inject();
211
+ injectStaleBadges();
212
+ });
213
+ } else {
214
+ inject();
215
+ injectStaleBadges();
216
+ }
217
+ })();
@@ -6,7 +6,7 @@
6
6
  <title>Architecture — {project}</title>
7
7
  <link rel="stylesheet" href="style.css" />
8
8
  </head>
9
- <body>
9
+ <body data-arch-slug="architecture">
10
10
  <nav class="nav-sidebar">
11
11
  <div class="logo">
12
12
  <span>ViePilot Architect Mode</span>
@@ -37,7 +37,7 @@
37
37
  <button id="theme-toggle" onclick="toggleTheme()">☀️ Light</button>
38
38
  </div>
39
39
 
40
- <div class="card">
40
+ <div class="card" data-arch-id="ARCH-DIAG1" data-arch-title="C4 Context Diagram">
41
41
  <h2>C4 Context Diagram</h2>
42
42
  <div class="mermaid-wrap">
43
43
  <div class="mermaid">
@@ -55,7 +55,7 @@ C4Context
55
55
  </div>
56
56
  </div>
57
57
 
58
- <div class="card">
58
+ <div class="card" data-arch-id="ARCH-DIAG2" data-arch-title="System Diagram">
59
59
  <h2>System Diagram</h2>
60
60
  <div class="mermaid-wrap">
61
61
  <div class="mermaid">
@@ -89,13 +89,13 @@ graph TD
89
89
  </tr>
90
90
  </thead>
91
91
  <tbody>
92
- <tr>
92
+ <tr data-arch-id="C1">
93
93
  <td>{Component 1}</td>
94
94
  <td>{Responsibility}</td>
95
95
  <td>{Technology}</td>
96
96
  <td>{Notes}</td>
97
97
  </tr>
98
- <tr>
98
+ <tr data-arch-id="C2">
99
99
  <td>{Component 2}</td>
100
100
  <td>{Responsibility}</td>
101
101
  <td>{Technology}</td>
@@ -124,7 +124,7 @@ graph TD
124
124
  </tr>
125
125
  </thead>
126
126
  <tbody>
127
- <tr>
127
+ <tr data-arch-id="C3">
128
128
  <td>{External System 1}</td>
129
129
  <td>{SaaS / Internal / 3rd party}</td>
130
130
  <td>{What it does}</td>
@@ -132,7 +132,7 @@ graph TD
132
132
  <td>{Team / Vendor}</td>
133
133
  <td>{Notes}</td>
134
134
  </tr>
135
- <tr>
135
+ <tr data-arch-id="C4">
136
136
  <td>{External System 2}</td>
137
137
  <td>{SaaS / Internal / 3rd party}</td>
138
138
  <td>{What it does}</td>
@@ -155,5 +155,6 @@ graph TD
155
155
  mermaid.initialize({ startOnLoad: false, theme: isLight ? 'default' : 'dark' });
156
156
  }
157
157
  </script>
158
+ <script src="architect-actions.js"></script>
158
159
  </body>
159
160
  </html>
@@ -6,7 +6,7 @@
6
6
  <title>Data Flow — {project}</title>
7
7
  <link rel="stylesheet" href="style.css" />
8
8
  </head>
9
- <body>
9
+ <body data-arch-slug="data-flow">
10
10
  <nav class="nav-sidebar">
11
11
  <div class="logo">
12
12
  <span>ViePilot Architect Mode</span>
@@ -37,7 +37,7 @@
37
37
  <button id="theme-toggle" onclick="toggleTheme()">☀️ Light</button>
38
38
  </div>
39
39
 
40
- <div class="card">
40
+ <div class="card" data-arch-id="DF-DIAG1" data-arch-title="Primary Request Flow">
41
41
  <h2>Primary Request Flow</h2>
42
42
  <div class="mermaid-wrap">
43
43
  <div class="mermaid">
@@ -58,7 +58,7 @@ sequenceDiagram
58
58
  </div>
59
59
  </div>
60
60
 
61
- <div class="card">
61
+ <div class="card" data-arch-id="DF-DIAG2" data-arch-title="Event Flow (Async)">
62
62
  <h2>Event Flow (Async)</h2>
63
63
  <div class="mermaid-wrap">
64
64
  <div class="mermaid">
@@ -83,7 +83,7 @@ flowchart LR
83
83
  </tr>
84
84
  </thead>
85
85
  <tbody>
86
- <tr>
86
+ <tr data-arch-id="DF1">
87
87
  <td>{Flow name}</td>
88
88
  <td>{Trigger}</td>
89
89
  <td>{Steps}</td>
@@ -104,5 +104,6 @@ flowchart LR
104
104
  mermaid.initialize({ startOnLoad: false, theme: isLight ? 'default' : 'dark' });
105
105
  }
106
106
  </script>
107
+ <script src="architect-actions.js"></script>
107
108
  </body>
108
109
  </html>