viepilot 2.45.6 → 2.47.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/CHANGELOG.md CHANGED
@@ -7,6 +7,67 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.47.0] - 2026-05-06
11
+
12
+ ### Added
13
+ - **ENH-081** Brownfield Scan Trace Log — `BROWNFIELD-TRACE.md` real-time trace artifact
14
+ (`workflows/crystallize.md`). Before any signal category scanning begins, crystallize now
15
+ writes `.viepilot/BROWNFIELD-TRACE.md` to disk with all 13 categories pre-populated as
16
+ `planned`. Full feature set:
17
+ - **Trace initialization + resume detection**: on session start, checks for existing trace;
18
+ if `Status: scan_complete` → AUQ offers skip re-scan or re-scan from scratch; if trace is
19
+ mid-scan (interrupted) → AUQ offers resume from the last completed signal category
20
+ - **Per-Category Update Protocol (ENH-081)**: on category start → row moves to `scanning`;
21
+ on completion → row moves to `done`/`assumed`/`skipped` with file count, signals found,
22
+ start time, and duration; `## Files Read Log` appended with `[x]` (read) / `[ ]` (not found)
23
+ per file probed
24
+ - **Coverage gate (ENH-081)**: before presenting Scan Report, counts remaining `planned` rows;
25
+ non-blocking warning if any categories were not executed; sets `Status: scan_complete` in
26
+ trace header after gate passes
27
+ - **Gap Filling Log (ENH-081)**: each user response during Step 0-B-ii gap-filling is
28
+ immediately appended to `## Gap Filling Log` — no batching
29
+ - **Step Completion tracking**: `## Step Completion` rows updated after Step 0-C (Brainstorm
30
+ Stub) and Step 0-D (UI Workspace, 3 cases: done / skipped / N/A)
31
+
32
+ ## [2.46.1] - 2026-05-06
33
+
34
+ ### Fixed
35
+ - **ENH-080** Upgrade re-scan (ENH-067 Step 0-B) now detects Signal Category 13 gap for
36
+ projects crystallized before v2.46.0:
37
+ - Delta computation table extended with `v2.46.0` row: detection field `ui_signals_imported`
38
+ absent from HANDOFF.json; trigger re-check prevents false-positive for backend-only projects
39
+ (no CSS, no Tailwind, no UI component files)
40
+ - Step 0-D now persists `ui_signals_imported: true/false` + `ui_signals_imported_at`/
41
+ `ui_signals_skipped_at` to `HANDOFF.json` after workspace generation or skip — marks gap
42
+ as "evaluated"; prevents re-asking on every crystallize run; `--upgrade` forces re-evaluation
43
+ - Patch mode handler added: re-runs Signal Cat 13 (Sub-scans A/B/C) + Step 0-D when UI gap
44
+ detected; AUQ gate preserved; no brainstorm supplement check (reads codebase directly)
45
+
46
+ ## [2.46.0] - 2026-04-27
47
+
48
+ ### Added
49
+ - **ENH-079** Signal Category 13 — UI/Design System Signals in brownfield scanner
50
+ (`workflows/crystallize.md`). When an existing project has a real UI layer, the
51
+ brownfield scan now reverse-engineers it into a complete `.viepilot/ui-direction/`
52
+ workspace automatically:
53
+ - Sub-scan A: CSS custom properties (`--color-*`, `--font-*`, `--spacing-*`, `--radius-*`),
54
+ Tailwind config (`theme.extend.colors`, `fontFamily`, `spacing`, `borderRadius`),
55
+ SCSS variables, design token JSON files → Design.MD v1 `design.md`
56
+ - Sub-scan B: Page/route inventory for 8 framework types (Next.js App Router, Next.js Pages
57
+ Router, React Router, Vue Router, Angular, Nuxt 3, SvelteKit, plain HTML) →
58
+ `index.html` hub + `pages/{slug}.html` stubs per discovered route
59
+ - Sub-scan C: Component inventory via file glob + UI library detection from `package.json`
60
+ (shadcn/ui, Material UI, Chakra UI, Ant Design, Headless UI, Bootstrap, Radix) →
61
+ `notes.md ## components_inventory`
62
+ - AUQ gate: "Generate ui-direction workspace?" before reverse-engineering (skippable)
63
+ - Scan Report `ui_signals` field: `triggered`, `workspace_generated`, `ui_tokens`,
64
+ `ui_pages`, `ui_components`
65
+ - `notes.md` front matter: `reverse_engineered: true` flag — distinguishes auto-generated
66
+ sessions from manually crafted brainstorm sessions
67
+ - `workflows/brainstorm.md` Step 3C: imports Signal 13 data when brownfield stub contains
68
+ `ui_signals`; handles 3 cases (workspace generated / data present / not triggered);
69
+ offers on-demand workspace generation via AUQ
70
+
10
71
  ## [2.45.6] - 2026-04-27
11
72
 
12
73
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viepilot",
3
- "version": "2.45.6",
3
+ "version": "2.47.0",
4
4
  "description": "**Autonomous Vibe Coding Framework / Bộ khung phát triển tự động có kiểm soát**",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -334,6 +334,70 @@ Store the pending gap list. Re-surface the same AUQ at `/save` before writing th
334
334
  Proceed normally. Do **not** set `upgrade_supplement_version` — gap will re-surface on next open.
335
335
  </step>
336
336
 
337
+ <step name="brownfield_ui_signal_import">
338
+ ### Step 3C: Brownfield UI Signal Import (ENH-079)
339
+
340
+ **Trigger:** When the loaded session is a brownfield import stub (contains `session-brownfield-import.md` or `IS_BROWNFIELD=true`) AND the session's embedded Scan Report contains a `ui_signals` field.
341
+
342
+ **Check:** Read session file for `ui_signals` YAML block under `## Scan Report`.
343
+
344
+ ---
345
+
346
+ **Case 1 — workspace already generated** (`ui_signals.workspace_generated: true`):
347
+
348
+ Display notice (no AUQ required):
349
+ ```
350
+ UI workspace already generated at .viepilot/ui-direction/{session-id}/
351
+ Open index.html to review {ui_pages.count} pages and {ui_components.total} components.
352
+ ```
353
+ Continue brainstorm normally. Do not re-generate workspace.
354
+
355
+ ---
356
+
357
+ **Case 2 — Signal 13 data present, workspace NOT yet generated** (`ui_signals.triggered: true`, `workspace_generated: false` or absent):
358
+
359
+ Import into session notes.md:
360
+ - `ui_pages.routes[]` → populate `## pages_inventory` section
361
+ - `ui_components` data → populate `## components_inventory` section
362
+ - `ui_tokens` summary → populate `## design_tokens` section
363
+ - Set notes.md front matter: `reverse_engineered: true`
364
+
365
+ Display import summary:
366
+ ```
367
+ Imported Signal 13 data: {ui_pages.count} pages, {ui_components.total} components,
368
+ {ui_tokens.detected} tokens detected ({ui_tokens.assumed} assumed).
369
+ ```
370
+
371
+ **Claude Code (terminal) — REQUIRED:** Offer workspace generation via AUQ:
372
+ - question: "Signal 13 data imported. Generate full ui-direction workspace now?"
373
+ - header: "UI Workspace"
374
+ - options:
375
+ a. "Yes — generate workspace (Recommended)" → run workspace generation (Step 0-D logic from crystallize.md)
376
+ b. "Continue brainstorm first" → proceed; workspace generation remains available
377
+
378
+ **Text fallback:**
379
+ ```
380
+ Signal 13 data imported.
381
+ 1. Generate ui-direction workspace now (Recommended)
382
+ 2. Continue brainstorm first
383
+ ```
384
+
385
+ ---
386
+
387
+ **Case 3 — `ui_signals` not present** (Signal 13 not triggered for this project):
388
+
389
+ Skip this step entirely. Proceed to Step 4 normally.
390
+
391
+ ---
392
+
393
+ **Reverse-engineered workspace handling:**
394
+
395
+ When `notes.md` front matter contains `reverse_engineered: true`:
396
+ - Display "(Reverse-engineered)" badge in session header instead of standard brainstorm banner
397
+ - Skip "missing brainstorm" warnings in vp-audit and vp-crystallize
398
+ - Do not treat session as an incomplete brainstorm — it is a valid documentation artifact
399
+ </step>
400
+
337
401
  <step name="brainstorm_mode">
338
402
  ## 4. Brainstorm Mode
339
403
 
@@ -54,10 +54,15 @@ If `~/.viepilot/config.json` is absent, use defaults (en/en) — do not fail.
54
54
  | v2.32.0 | `## Admin & Governance` in PROJECT-CONTEXT.md | section absent AND `admin_imported` not in HANDOFF.json |
55
55
  | v2.33.0 | `## Content Management` in PROJECT-CONTEXT.md | section absent AND `content_imported` not in HANDOFF.json |
56
56
  | v2.34.0 | `## User Data Management` in PROJECT-CONTEXT.md | section absent AND `user_data_imported` not in HANDOFF.json |
57
+ | v2.46.0 | UI/Design scan not run (Signal Cat 13) | `ui_signals_imported` absent from HANDOFF.json AND any UI trigger condition met: `.css`/`.scss` files > 5 OR `tailwind.config.js`/`tailwind.config.ts` exists OR component files (`.jsx/.tsx/.vue/.svelte`) > 10 |
57
58
 
58
59
  Cross-check: confirm section is actually absent from current `PROJECT-CONTEXT.md` before listing
59
60
  as a gap — avoids false positives for projects that have the content already.
60
61
 
62
+ UI trigger re-check note: backend-only projects (no CSS, no Tailwind, no UI components) must
63
+ NOT see "UI scan gap" — the trigger condition re-check prevents false-positive upgrade noise
64
+ for CLI tools, data pipelines, and other non-UI projects.
65
+
61
66
  ### Upgrade menu
62
67
 
63
68
  **Claude Code (terminal) — REQUIRED:**
@@ -89,6 +94,10 @@ For each missing section, run only the corresponding Step 1D export item:
89
94
  - `## Admin & Governance` → Step 1D item 7 (ENH-063)
90
95
  - `## Content Management` → Step 1D item 8 (ENH-065)
91
96
  - `## User Data Management` → Step 1D item 9 (ENH-066)
97
+ - UI/Design scan (v2.46.0, ENH-079) → Re-run Signal Category 13 (Sub-scans A/B/C) then
98
+ proceed through Step 0-D (AUQ gate + workspace generation). AUQ gate is preserved — user
99
+ can still choose to skip. No brainstorm supplement check required (reads codebase directly).
100
+ After gate: writes `ui_signals_imported` to HANDOFF.json per Task 121.2 spec.
92
101
 
93
102
  For each item:
94
103
  1. Check if architect `notes.md` has the corresponding YAML section (`## admin`, `## content`,
@@ -269,7 +278,92 @@ When brownfield was triggered automatically (not via `--brownfield`), present th
269
278
  > - "Cancel" / "3" → exit without changes
270
279
 
271
280
  **When brownfield mode is active:**
272
- 1. Run the full 12-category codebase scanner (Signal Categories 1–12 below).
281
+
282
+ ### Brownfield Scan Trace — Initialization (ENH-081)
283
+
284
+ **Before running any signal category**, initialize the scan trace:
285
+
286
+ 1. Check if `.viepilot/BROWNFIELD-TRACE.md` exists.
287
+
288
+ 2. **If exists AND `Status: scan_complete`** — prior scan completed. Offer resume via AUQ:
289
+ ```
290
+ question: "Prior scan found (completed {date}). Re-scan or resume from gap-filling?"
291
+ header: "Brownfield Trace"
292
+ options:
293
+ a. "Resume — skip re-scan, go to gap-filling (Recommended)"
294
+ b. "Re-scan from scratch — overwrite trace"
295
+ ```
296
+ - On "Resume": skip to Interactive Gap-Filling (Step 0-B-ii), using data from prior trace.
297
+ - On "Re-scan": delete trace, continue to step 4 below.
298
+
299
+ 3. **If exists AND `Status: scanning`** — prior scan was interrupted. Read which category row
300
+ last shows `scanning` → identify interrupted category N. Offer via AUQ:
301
+ ```
302
+ question: "Prior scan interrupted at Signal Cat {N} — {Category Name}. How to proceed?"
303
+ header: "Interrupted Scan"
304
+ options:
305
+ a. "Resume from Signal Cat {N} (Recommended)"
306
+ b. "Re-scan from scratch"
307
+ ```
308
+ - On "Resume from Cat N": skip completed categories (1 through N-1), restart from Cat N.
309
+ - On "Re-scan": overwrite trace, continue to step 4 below.
310
+
311
+ 4. **If not exists (or user chose "Re-scan"):** create `.viepilot/BROWNFIELD-TRACE.md`:
312
+
313
+ ```markdown
314
+ # Brownfield Scan Trace
315
+
316
+ <!-- Generated by vp-crystallize --brownfield v{crystallize_version} -->
317
+
318
+ ## Session Info
319
+ - **Started**: {ISO-8601 timestamp}
320
+ - **Project**: {project_name or "unknown (pre-scan)"}
321
+ - **crystallize_version**: {semver}
322
+ - **Status**: scanning
323
+
324
+ ## Signal Coverage
325
+
326
+ | # | Category | Status | Files Checked | Signals Found | Started | Duration |
327
+ |---|----------|--------|---------------|---------------|---------|----------|
328
+ | 1 | Build Manifest & Package Identity | planned | — | — | — | — |
329
+ | 2 | Framework & Library Detection | planned | — | — | — | — |
330
+ | 3 | Architecture Layer Inference | planned | — | — | — | — |
331
+ | 4 | Database Schema Signals | planned | — | — | — | — |
332
+ | 5 | API Contract Files | planned | — | — | — | — |
333
+ | 6 | Infrastructure & Deployment Config | planned | — | — | — | — |
334
+ | 7 | Environment & Configuration Shape | planned | — | — | — | — |
335
+ | 8 | Test Coverage Signals | planned | — | — | — | — |
336
+ | 9 | Code Quality & Tooling | planned | — | — | — | — |
337
+ | 10 | Documentation Files | planned | — | — | — | — |
338
+ | 11 | Git History & Version Signals | planned | — | — | — | — |
339
+ | 12 | File Extension Language Survey | planned | — | — | — | — |
340
+ | 13 | UI/Design System Signals | planned | — | — | — | — |
341
+
342
+ ## Files Read Log
343
+
344
+ (Populated during scanning — one subsection per signal category)
345
+
346
+ ## Gap Filling Log
347
+
348
+ | Field | Status | Source | Value |
349
+ |-------|--------|--------|-------|
350
+
351
+ (Populated during interactive gap-filling — Step 0-B-ii)
352
+
353
+ ## Step Completion
354
+
355
+ | Step | Status | Completed At | Notes |
356
+ |------|--------|-------------|-------|
357
+ | 0-B Scanner | in_progress | {timestamp} | — |
358
+ | 0-C Brainstorm Stub | pending | — | — |
359
+ | 0-D UI Workspace | pending | — | N/A if not triggered |
360
+ ```
361
+
362
+ **Write this file to disk immediately** — before any signal category scanning begins.
363
+
364
+ ---
365
+
366
+ 1. Run the full 13-category codebase scanner (Signal Categories 1–13 below).
273
367
  2. Produce a structured **Scan Report** (see schema at end of this step).
274
368
  3. Classify every field as DETECTED / ASSUMED / MISSING per Gap Detection Rules.
275
369
  4. Present Scan Report summary to user; interactively fill every MISSING MUST-DETECT field.
@@ -676,6 +770,179 @@ Rule: `secondary_languages[]` = languages with ≥5 files that are not `primary_
676
770
 
677
771
  ---
678
772
 
773
+ ### Signal Category 13 — UI/Design System Signals
774
+
775
+ **Trigger condition (ANY of):**
776
+ - `.css` or `.scss` files > 5 in the project
777
+ - `tailwind.config.js` or `tailwind.config.ts` exists
778
+ - Component files (`.jsx`, `.tsx`, `.vue`, `.svelte`) > 10
779
+ - Route config files detected (see Sub-scan B sources below)
780
+
781
+ **Runs after:** Signal Category 12.
782
+ **Output stored in:** `ui_signals` Scan Report field.
783
+
784
+ ---
785
+
786
+ #### Sub-scan A — Design Token Extraction
787
+
788
+ **Sources (priority order):**
789
+
790
+ 1. `tailwind.config.js` / `tailwind.config.ts`
791
+ - Extract: `theme.extend.colors`, `theme.colors`, `theme.fontFamily`, `theme.spacing`, `theme.borderRadius`
792
+
793
+ 2. CSS custom properties in `*.css` / `globals.css` / `variables.css` / `_variables.scss`
794
+ - `--color-*`, `--primary-*`, `--bg-*`, `--text-*` → TOKEN_MAP.colors
795
+ - `--font-*`, `--text-size-*` → TOKEN_MAP.typography
796
+ - `--spacing-*`, `--gap-*`, `--padding-*` → TOKEN_MAP.spacing
797
+ - `--radius-*`, `--rounded-*` → TOKEN_MAP.rounded
798
+
799
+ 3. SCSS variables: `$color-primary`, `$font-size-base`, `$spacing-unit`, etc.
800
+
801
+ 4. Design token JSON files: `tokens.json`, `design-tokens.json`, `theme.json`
802
+
803
+ **Output:** Populate TOKEN_MAP for workspace generation step.
804
+ - ASSUMED prefix for any token not found in any source.
805
+ - Track `source_files[]` — list of all files scanned.
806
+
807
+ **Scan Report field:** `ui_tokens: { detected: N, assumed: M, source_files: [] }`
808
+
809
+ ---
810
+
811
+ #### Sub-scan B — Page/Route Inventory
812
+
813
+ | Framework | Detection method | Route extraction |
814
+ |-----------|-----------------|-----------------|
815
+ | Next.js 13+ App Router | `app/` directory with `page.tsx` or `page.jsx` | Directory structure → route paths |
816
+ | Next.js Pages Router | `pages/` directory (exclude `api/` and `_` prefixes) | Directory structure → route paths |
817
+ | React Router | `src/routes/*.{jsx,tsx}`, `src/App.{jsx,tsx}` | Parse `<Route path="...">` attrs |
818
+ | Vue Router | `src/router/index.{js,ts}` | Parse `routes: [{ path, component }]` |
819
+ | Angular | `src/app/app-routing.module.ts` | Parse `Routes` array |
820
+ | Nuxt 3 | `pages/` directory | Directory structure → route paths |
821
+ | Plain HTML | `*.html` at root, `src/`, `public/` | File names → page names |
822
+ | SvelteKit | `src/routes/+page.svelte` | Directory structure |
823
+
824
+ **Scan Report field:** `ui_pages: { count: N, routes: [], framework: string }`
825
+
826
+ Framework values: `"next-app"` | `"next-pages"` | `"react-router"` | `"vue-router"` | `"angular"` | `"nuxt3"` | `"sveltekit"` | `"html"` | `"unknown"`
827
+
828
+ ---
829
+
830
+ #### Sub-scan C — Component Inventory
831
+
832
+ **Sources:**
833
+
834
+ 1. Component file globs:
835
+ - `src/components/**/*.{jsx,tsx,vue,svelte}`
836
+ - `components/**/*.{jsx,tsx,vue}`
837
+ - `app/components/**/*`
838
+
839
+ 2. UI library detection from `package.json` dependencies:
840
+ - `@mui/material` → Material UI
841
+ - `@chakra-ui/react` → Chakra UI
842
+ - `@shadcn/ui` or `components/ui/` directory → shadcn/ui
843
+ - `antd` → Ant Design
844
+ - `@headlessui/react` → Headless UI
845
+ - `react-bootstrap` → Bootstrap
846
+ - `@radix-ui/*` → Radix primitives
847
+
848
+ 3. Common component pattern detection (by filename):
849
+ - Button, Modal, Dialog, Card, Form, Input, Select, Table, Navbar, Sidebar, Footer, Header
850
+
851
+ **Scan Report field:**
852
+ ```yaml
853
+ ui_components:
854
+ total: N
855
+ ui_library: string # "shadcn/ui" | "Material UI" | "Chakra UI" | "Ant Design" | "Headless UI" | "Bootstrap" | "Radix" | "none"
856
+ categories:
857
+ layout: N
858
+ forms: N
859
+ navigation: N
860
+ data-display: N
861
+ feedback: N
862
+ ```
863
+
864
+ ---
865
+
866
+ ### Brownfield Scan Trace — Per-Category Update Protocol (ENH-081)
867
+
868
+ For each signal category (1–13), apply this update protocol to `BROWNFIELD-TRACE.md`:
869
+
870
+ #### On category start
871
+
872
+ Update the category's row in `## Signal Coverage`:
873
+ - Status: `scanning`
874
+ - Started: current ISO timestamp (time portion only: `HH:MM:SS`)
875
+
876
+ #### On category complete
877
+
878
+ Update the category's row:
879
+ - **Status**: one of:
880
+ - `done` — evidence found, DETECTED tier (high confidence)
881
+ - `assumed` — evidence found, ASSUMED tier (low confidence / indirect signal)
882
+ - `skipped` — no relevant files found; category not applicable to this project
883
+ - **Files Checked**: integer count of files actually read
884
+ - **Signals Found**: comma-separated key results (e.g. `react, next.js`), or `none`
885
+ - **Duration**: elapsed seconds since category started (e.g. `3s`)
886
+
887
+ Append a new subsection to `## Files Read Log`:
888
+
889
+ ```markdown
890
+ ### Signal {N} — {Category Name}
891
+
892
+ - [x] {relative/path/to/file} → {signal or "none found"}
893
+ - [x] {another/file.json} → {result summary}
894
+ - [ ] {expected/missing.yaml} → not present
895
+ ```
896
+
897
+ Legend:
898
+ - `[x]` = file was read (exists on disk and was examined)
899
+ - `[ ]` = file was expected per workflow probe list but not found on disk
900
+
901
+ **Skipped category** (no files probed): append instead:
902
+ ```markdown
903
+ ### Signal {N} — {Category Name}
904
+
905
+ (No files probed — category not applicable to this project)
906
+ ```
907
+
908
+ #### Status transitions
909
+
910
+ Flow: `planned → scanning → done` (full evidence) | `scanning → assumed` (low confidence) | `scanning → skipped` (no files)
911
+
912
+ ```
913
+ planned → scanning (category starts)
914
+ scanning → done (evidence found — DETECTED)
915
+ scanning → assumed (evidence found — ASSUMED, low confidence)
916
+ scanning → skipped (no matching files found)
917
+ ```
918
+
919
+ #### Example — Signal Category 5 (API Contract Files)
920
+
921
+ Row after completion:
922
+ ```
923
+ | 5 | API Contract Files | done | 3 | openapi.yaml, swagger.json (REST) | 14:23:05 | 2s |
924
+ ```
925
+
926
+ Files Read Log append:
927
+ ```markdown
928
+ ### Signal 5 — API Contract Files
929
+
930
+ - [x] openapi.yaml → REST (OpenAPI 3.0)
931
+ - [x] swagger.json → REST (Swagger 2.0)
932
+ - [ ] graphql/schema.graphql → not present
933
+ - [x] src/routes/index.ts → REST route patterns detected
934
+ ```
935
+
936
+ #### Signal Category 13 special format
937
+
938
+ Signal Category 13 (UI/Design) Signals Found field format:
939
+ ```
940
+ tailwind ({N} colors), {M} routes ({framework}), {K} components ({ui_library})
941
+ ```
942
+ Example: `tailwind (12 colors), 8 routes (next-app), 24 components (shadcn/ui)`
943
+
944
+ ---
945
+
679
946
  ### Scan Report Schema (finalized)
680
947
 
681
948
  After running all 12 signal categories, produce this structured Scan Report:
@@ -741,6 +1008,26 @@ top_contributors: []
741
1008
  docs_extracted: [] # { file, summary, key_facts[] }
742
1009
  language_distribution: {} # { ts: 142, java: 38, ... }
743
1010
  open_questions: [] # root-level open questions (includes rollup from modules)
1011
+ ui_signals: # present only when Signal Category 13 triggered
1012
+ triggered: bool
1013
+ workspace_generated: bool # true after workspace generation step completes
1014
+ ui_tokens:
1015
+ detected: N # tokens extracted from sources
1016
+ assumed: M # tokens filled with ASSUMED values
1017
+ source_files: [] # files scanned (tailwind.config.js, globals.css, etc.)
1018
+ ui_pages:
1019
+ count: N
1020
+ routes: [] # [ { path, name, source_file } ]
1021
+ framework: string # "next-app" | "next-pages" | "react-router" | "vue-router" | "angular" | "nuxt3" | "sveltekit" | "html" | "unknown"
1022
+ ui_components:
1023
+ total: N
1024
+ ui_library: string # "shadcn/ui" | "Material UI" | "Chakra UI" | "Ant Design" | "Headless UI" | "Bootstrap" | "Radix" | "none"
1025
+ categories:
1026
+ layout: N
1027
+ forms: N
1028
+ navigation: N
1029
+ data-display: N
1030
+ feedback: N
744
1031
  ```
745
1032
 
746
1033
  ---
@@ -829,6 +1116,19 @@ Root gap tier: MISSING (worst across modules)
829
1116
 
830
1117
  After scanner completes:
831
1118
 
1119
+ **Coverage gate (ENH-081):** Before presenting the Scan Report, verify the trace:
1120
+
1121
+ 1. Read `## Signal Coverage` table from `.viepilot/BROWNFIELD-TRACE.md`.
1122
+ 2. Count rows still showing `planned` (never executed).
1123
+ 3. If any `planned` rows found: display warning (non-blocking):
1124
+ ```
1125
+ ⚠️ Coverage incomplete — {N} signal categories not executed:
1126
+ - Signal Cat {N}: {Category Name}
1127
+ Proceeding with partial Scan Report. Uncovered gap fields will be MISSING.
1128
+ ```
1129
+ 4. Update trace `## Session Info` → `Status: scan_complete`.
1130
+ 5. Update `## Step Completion` row "0-B Scanner" → `done` + current timestamp.
1131
+
832
1132
  1. Display Scan Report summary table to user (field | value | status).
833
1133
  2. **Per-module MISSING fields** — for each module with `gap_tier: MISSING`, pause and ask per field:
834
1134
  ```
@@ -843,6 +1143,14 @@ After scanner completes:
843
1143
  5. Capture all user responses; update Scan Report fields accordingly.
844
1144
  6. All remaining unresolved items → `open_questions[]` (roll up per-module `open_questions[]` into root).
845
1145
 
1146
+ **Gap Filling Log (ENH-081):** For each field where the user provides or confirms a value, append a row to `## Gap Filling Log` in `.viepilot/BROWNFIELD-TRACE.md`. Write after each user response — do not batch:
1147
+
1148
+ | Field | Status | Source | Value |
1149
+ |-------|--------|--------|-------|
1150
+ | {field_name} | MISSING → user-filled | user input | {value} |
1151
+ | {field_name} | ASSUMED → accepted | user accept | {assumed_value} |
1152
+ | {field_name} | DETECTED → user-confirmed | user confirm | {value} |
1153
+
846
1154
  ---
847
1155
 
848
1156
  ### Brownfield Brainstorm Stub Generation (Step 0-C)
@@ -869,6 +1177,120 @@ After gap-filling is complete, write:
869
1177
 
870
1178
  **Purpose:** This stub allows `vp-audit` and other ViePilot tools to not error on missing brainstorm session files. The presence of `session-brownfield-import.md` is treated as a valid brownfield import.
871
1179
 
1180
+ **Trace update (ENH-081):** Update `.viepilot/BROWNFIELD-TRACE.md` `## Step Completion` row
1181
+ "0-C Brainstorm Stub" → `done` + current timestamp + `stub: docs/brainstorm/session-brownfield-import.md`.
1182
+
1183
+ ---
1184
+
1185
+ ### UI Workspace Generation Gate (Step 0-D)
1186
+
1187
+ **Condition:** Run only when `ui_signals.triggered: true` in the Scan Report.
1188
+
1189
+ #### AUQ Gate — Brownfield UI Reverse-Engineering
1190
+
1191
+ **Claude Code (terminal) — REQUIRED:** Call AskUserQuestion:
1192
+ - question: "UI signals detected — generate ui-direction workspace from existing code?"
1193
+ - header: "Brownfield UI Reverse-Engineering"
1194
+ - options:
1195
+ a. "Yes — generate now (Recommended)" → proceed to workspace generation below
1196
+ b. "Skip — I will create ui-direction manually" → set `ui_signals.workspace_generated: false`; add note to `open_questions[]`; write to `.viepilot/HANDOFF.json`: `{ "ui_signals_imported": false, "ui_signals_skipped_at": "{ISO-8601 timestamp}" }` (merge — do not overwrite unrelated fields); continue
1197
+
1198
+ **Text fallback (non-terminal adapters):**
1199
+ ```
1200
+ UI signals detected. Options:
1201
+ 1. Yes — generate ui-direction workspace now (Recommended)
1202
+ 2. Skip — create ui-direction manually later
1203
+ ```
1204
+
1205
+ #### Workspace Generation
1206
+
1207
+ When user selects "Yes — generate now":
1208
+
1209
+ Generate session ID: `brownfield-{YYYY-MM-DD}` (or reuse existing if re-running).
1210
+
1211
+ Create artifacts under `.viepilot/ui-direction/{session-id}/`:
1212
+
1213
+ **`design.md`** (Design.MD v1 format):
1214
+ - Populate colors, typography, spacing, rounded from TOKEN_MAP (Sub-scan A)
1215
+ - Prefix ASSUMED for any token not extracted from source
1216
+ - Add `## Source` section listing all scanned files and extraction method
1217
+
1218
+ **`notes.md`**:
1219
+ ```markdown
1220
+ ---
1221
+ reverse_engineered: true
1222
+ source_project: {project_name}
1223
+ scan_date: {ISO date}
1224
+ signal_category: 13
1225
+ ---
1226
+
1227
+ ## pages_inventory
1228
+
1229
+ | Route | Page Name | Source File | Status |
1230
+ |-------|-----------|-------------|--------|
1231
+ {one row per route from ui_pages.routes[]}
1232
+
1233
+ ## components_inventory
1234
+
1235
+ | Component | Type | File | UI Library |
1236
+ |-----------|------|------|------------|
1237
+ {one row per component from ui_components scan}
1238
+
1239
+ ## design_tokens
1240
+
1241
+ - Detected: {ui_tokens.detected} tokens
1242
+ - Assumed: {ui_tokens.assumed} tokens
1243
+ - Sources: {ui_tokens.source_files[]}
1244
+ ```
1245
+
1246
+ **`index.html`** hub page:
1247
+ - Header: project name + UI library badge (if `ui_library != "none"`)
1248
+ - Table of contents: one link per page stub
1249
+ - Each entry: route path + source file reference
1250
+
1251
+ **`pages/{slug}.html`** stubs — one per discovered route:
1252
+ - Page title (from route name) + route path
1253
+ - "Reverse-engineered from: {source file}"
1254
+ - Component list (if detectable via import analysis)
1255
+ - Placeholder section for handover notes
1256
+
1257
+ **Generated artifact tree:**
1258
+ ```
1259
+ .viepilot/ui-direction/
1260
+ brownfield-{YYYY-MM-DD}/
1261
+ design.md ← design tokens (Design.MD v1)
1262
+ notes.md ← pages_inventory + components_inventory + design_tokens
1263
+ index.html ← hub page with all discovered pages linked
1264
+ pages/
1265
+ {slug}.html ← one per discovered route/page
1266
+ ```
1267
+
1268
+ After generation: set `ui_signals.workspace_generated: true` in Scan Report.
1269
+
1270
+ Also write to `.viepilot/HANDOFF.json` (merge — do not overwrite unrelated fields):
1271
+ ```json
1272
+ {
1273
+ "ui_signals_imported": true,
1274
+ "ui_signals_imported_at": "{ISO-8601 timestamp}",
1275
+ "ui_signals_version": "2.46.0"
1276
+ }
1277
+ ```
1278
+ This flag is used by Step 0-B upgrade re-scan (ENH-080) to detect whether Signal Cat 13 has
1279
+ been run for this project. A future `--upgrade` re-run can force re-evaluation by re-running
1280
+ Signal Cat 13 even when `ui_signals_imported: true` is present.
1281
+
1282
+ **Reverse-engineered workspace notice:** The workspace is a documentation approximation
1283
+ from static code analysis — not a pixel-perfect rendering. `pages/*.html` stubs describe
1284
+ what exists based on file structure and imports. The `reverse_engineered: true` flag allows
1285
+ downstream tools (`vp-audit`, `vp-crystallize`) to adjust expectations (e.g., skip
1286
+ "missing brainstorm" warnings).
1287
+
1288
+ **Trace update (ENH-081):** Update `.viepilot/BROWNFIELD-TRACE.md` `## Step Completion` row
1289
+ "0-D UI Workspace":
1290
+ - If workspace generated: `done` + timestamp + `workspace: .viepilot/ui-direction/{session-id}/`
1291
+ - If user skipped AUQ: `skipped` + timestamp + `reason: user skipped`
1292
+ - If Signal Category 13 did not trigger: `N/A` (update row to `N/A` + timestamp)
1293
+
872
1294
  ---
873
1295
 
874
1296
  ### Safety Rules