its-magic 0.1.2-48 → 0.1.2-55

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/README.md CHANGED
@@ -2,38 +2,78 @@
2
2
 
3
3
  [GitHub Repository](https://github.com/fl0wm0ti0n/its-magic)
4
4
 
5
- Happy coding! Build something awesome.
6
-
7
- Drop-in template repo that implements a structured its-magic workflow in Cursor:
8
- intake -> discovery -> architecture -> sprint plan -> execute -> QA -> release,
9
- with pause/resume, decision gates, and persistent artifacts.
5
+ You bring the idea; its-magic is your structured **AI dev team** in Cursor — PO, Tech
6
+ Lead, Dev, QA, Release, and Curator — that turns ideas into shipped software through
7
+ explicit phases and handoff artifacts.
8
+
9
+ State lives in repo files (`docs/product`, `handoffs`, `sprints`, `decisions`) not
10
+ chat-only memory. Run `/intake` with your idea, then follow intake → discovery →
11
+ architecture → sprint plan → execute → QA → release; pause/resume and decision gates
12
+ keep you in control when you want to steer. Implementers: see `docs/developer/README.md`
13
+ for the DEV shard.
14
+
15
+ When you want hands-off delivery, enable **`AUTO_FLOW_MODE=full_autonomy`**
16
+ (default-off), run **`/auto` once in Cursor**, and let the native in-chat auto-chain
17
+ drain your backlog — self-verify UAT, bounded block retry, and advance to the next OPEN
18
+ story or bug without re-invoking each phase manually. The outer driver is **optional**
19
+ (**fallback** for headless/CI or when native chain is unavailable). Guided and
20
+ decision-gated modes remain the default.
10
21
 
11
22
  ## Features (what its-magic can do)
12
23
 
13
- - Structured phase workflow with explicit artifacts.
14
- - Artifact-first memory (state in files, not chat only).
15
- - Decision gate + escalation (`decisions/DEC-xxxx.md`).
16
- - Pause/resume with checkpoints (`handoffs/resume_brief.md`).
17
- - Automated execute/QA loop with safety caps (optional).
18
- - 3-layer quality chain: AI loop local validate-and-push → CI auto-fix.
19
- - User-visible metadata guard for operator-facing scripts/CLI (`US-0071` / `DEC-0053`):
20
- `python scripts/check-user-visible-metadata.py` (see `docs/engineering/runbook.md`).
21
- - CI/CD templates driven by `docs/engineering/runbook.md`.
22
- - Team-friendly local overrides (`scratchpad.local.md`).
23
- - Optional remote/docker execution and autonomous installs.
24
- - Built-in benchmarks (live, prompted, headless).
25
- - Multiplatform distribution (npm, Chocolatey, Homebrew).
24
+ ### Autonomous AI workflow
25
+
26
+ - Run `/intake` through `/release` with explicit phase handoffs and fresh subagent contexts.
27
+ - Use `/pause` and `/resume` with checkpoints when you want to steer; escalate blocking
28
+ choices to `decisions/DEC-xxxx.md`.
29
+ - Enable **`AUTO_FLOW_MODE=full_autonomy`** (default-off), run **`/auto` once in Cursor**,
30
+ and drain backlog in-chat; outer driver is **optional** / **fallback** for headless/CI.
31
+ - Team mode routes work across PO, Tech Lead, Dev, QA, Release, and Curator roles.
32
+ - Backlog and bug drain advance OPEN items without re-invoking each phase manually.
33
+ - See the catalog in **Commands and workflow** for phase commands and orchestration details.
34
+
35
+ ### Quality & verification gates
36
+
37
+ - 3-layer quality chain: AI execute/QA loop → local `validate-and-push` → CI auto-fix.
38
+ - Phase gates include `/plan-verify`, `/qa`, `/verify-work`, and `/uat` with fail-closed stops.
39
+ - `/acceptance` blocks README ↔ backlog drift; user-visible metadata guard on operator scripts.
40
+ - Browser UAT probes with structured fallback when live browser checks are unavailable.
41
+ - Release gates enforce coverage, parity, and evidence before publish.
42
+ - See the catalog in **Features** (`/acceptance`) and **Commands and workflow** for gate commands.
43
+
44
+ ### Distribution & install
45
+
46
+ - Global install via npm, npx, Chocolatey, or Homebrew; apply to any repo with
47
+ `its-magic --target`.
48
+ - Modes: `missing` (safe merge), `overwrite` (+ `--backup`), `upgrade` (framework only),
49
+ and `--clean-repo`.
50
+ - Lifecycle QA matrix validates fresh install, upgrade, backup, and clean-repo paths.
51
+ - Multi-target release publish with confirmation gates for npm/choco/brew.
52
+ - See the **Feature coverage catalog** below for distribution-tagged items.
53
+
54
+ ### Operator control & ergonomics
55
+
56
+ - Scratchpad flags and `scratchpad.local.md` tune behavior without rewriting framework files.
57
+ - Guided intake packs structure your first `/intake` conversation.
58
+ - Caveman voice mode and optional input compression for terse operator UX.
59
+ - `TOKEN_PROFILE` cost profiles slim context packs without changing workflow semantics.
60
+ - Voice input shortcuts and permissions/runtime connectivity for remote execution.
61
+ - See the catalog in **Other useful capabilities** for scratchpad and governance flags.
26
62
 
27
63
  <!-- readme-feature-coverage-catalog -->
28
64
 
29
65
  ### Feature coverage catalog (US-0091)
30
66
 
67
+ - `/acceptance` — README ↔ backlog/acceptance feature coverage backfill + blocking drift gate (`US-0091`).
68
+ - `README.md` — Visionary intro + tiered feature hierarchy (autonomous AI dev team positioning, root/template parity) (`US-0094`).
69
+ - `/auto` — Native in-chat auto-chain + full-autonomy mode (`US-0095`, `US-0092`).
31
70
  - `/bin` — POSIX npm installer + Linux remote test targets (WSL / SSH / Docker) (`US-0084`).
32
71
  - `/choco` — Configurable Multi-Target Release Publish with Confirmation Gate (`US-0054`).
33
72
  - `/devops` — First-Class Bug Issue Workflow (Open/Closed) (`US-0079`).
34
73
  - `/engineering` — Agent-Driven Codebase Map Bootstrap (`US-0082`).
35
74
  - `/engineering` — Remote Runtime Connectivity Contract for QA/Release/Publish (`US-0064`).
36
75
  - `/install` — Template/install payload omits intake gate scripts (`BUG-0001`).
76
+ - `/installed` — its-magic ships its OWN packaging CI into generated repos, breaking CI in every created project (`BUG-0009`).
37
77
  - `/intake` — Optional Caveman-style input compression (safe file scope) (`US-0090`).
38
78
  - `/lint` — CI/CD Workflows (`US-0007`).
39
79
  - `/or` — Cursor Caveman mode (scratchpad-configurable terse responses) (`US-0089`).
@@ -1140,6 +1180,7 @@ workflow stops and points you to `scripts/validate-and-push` for local fixing.
1140
1180
  - `/acceptance` — Mandatory Intake Question Packs for First and Small Intakes (`US-0068`).
1141
1181
  - `/ask` — /ask Command: Context-Aware Questions Without Workflow (`US-0020`).
1142
1182
  - `/ask` — Context Compaction and Tiered Token-Cost Optimization Mode (`US-0053`).
1183
+ - `/auto` — Architecture triad archiver ignores `## US-xxxx` headings, blocking `/auto` with `STATE_ARCHIVE_BOUNDARY_AMBIGUOUS` (`BUG-0010`).
1143
1184
  - `/auto` — Configurable Auto Phase Selection Policy (`US-0070`).
1144
1185
  - `/auto` — Continuous `/auto` Backlog-Drain Mode with Fine-Tune Switches (`US-0044`).
1145
1186
  - `/auto` — Fresh Subagent Context Per Phase and /auto Orchestration (`US-0023`).
@@ -1184,6 +1225,7 @@ workflow stops and points you to `scripts/validate-and-push` for local fixing.
1184
1225
  - `/repetitive` — Delegable Intake Clarification Without Hard Blocks (`US-0083`).
1185
1226
  - `/research` — Knowledge Curation & Early Research (`US-0029`).
1186
1227
  - `/risk` — Intelligent Intake Decomposition and Risk-Aware PO Questioning (`US-0051`).
1228
+ - `/scratchpad` — Caveman mode missing voice compression rules (US-0089 incomplete delivery) (`BUG-0011`).
1187
1229
  - `/scratchpad` — Executable Scratchpad-Driven Sync and Auto-Push Wiring (`US-0076`).
1188
1230
  - `/scratchpad` — Scratchpad Delivery Simplification (Example-Only Install Policy) (`US-0073`).
1189
1231
  - `/scratchpad` — Upgrade Scratchpad Example–First Refresh (Fix Example Drift vs Materialized Baseline) (`US-0075`).
@@ -1191,6 +1233,7 @@ workflow stops and points you to `scripts/validate-and-push` for local fixing.
1191
1233
  - `/sprint-plan` — Explicit `/sprint-plan --bulk` Mode (`US-0046`).
1192
1234
  - `/sprint-plan` — Sprint Sizing Rules and Configurable Sprint Planning (`US-0022`).
1193
1235
  - `/story` — Optional Feature User Guide Generation (`US-0032`).
1236
+ - `/uat` — Cursor browser-integrated UAT self-test (browser_smoke + automatable manual UI) (`US-0093`).
1194
1237
  - `/uat` — UAT Artifact Lifecycle and Ownership (`US-0027`).
1195
1238
  - `SKILL` scratchpad flag — Skill and Templates (`US-0004`).
1196
1239
  - `US-0001` scratchpad flag — Core Workflow Commands (`US-0001`).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "its-magic",
3
- "version": "0.1.2-48",
3
+ "version": "0.1.2-55",
4
4
  "description": "its-magic - AI dev team workflow for Cursor.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -7,6 +7,8 @@ Scoped modes (DEC-0073 §10 / US-0090):
7
7
  --scope=readme-feature-coverage DEC-0074 README feature-coverage pair table.
8
8
  --scope=downstream-ci-guard DEC-0075 downstream CI guard script pair table.
9
9
  --scope=us-0092 DEC-0078 full-autonomy outer driver + probe surfaces.
10
+ --scope=us-0093 DEC-0079 browser UAT probe surfaces.
11
+ --scope=us-0095 DEC-0080 native in-chat auto-chain surfaces.
10
12
  --scope=all union of all tables.
11
13
  """
12
14
 
@@ -78,6 +80,40 @@ US0092_PAIRS: tuple[tuple[str, str], ...] = (
78
80
  ("docs/engineering/runbook.md", "template/docs/engineering/runbook.md"),
79
81
  )
80
82
 
83
+ US0093_PAIRS: tuple[tuple[str, str], ...] = (
84
+ ("scripts/uat_probe_lib.py", "template/scripts/uat_probe_lib.py"),
85
+ (".cursor/commands/verify-work.md", "template/.cursor/commands/verify-work.md"),
86
+ (".cursor/commands/qa.md", "template/.cursor/commands/qa.md"),
87
+ (".cursor/commands/execute.md", "template/.cursor/commands/execute.md"),
88
+ (
89
+ ".cursor/scratchpad.local.example.md",
90
+ "template/.cursor/scratchpad.local.example.md",
91
+ ),
92
+ ("docs/engineering/runbook.md", "template/docs/engineering/runbook.md"),
93
+ (
94
+ "docs/engineering/auto-orchestration-reference.md",
95
+ "template/docs/engineering/auto-orchestration-reference.md",
96
+ ),
97
+ (
98
+ "docs/engineering/context/installer-owned-paths.manifest",
99
+ "template/docs/engineering/context/installer-owned-paths.manifest",
100
+ ),
101
+ )
102
+
103
+ US0095_PAIRS: tuple[tuple[str, str], ...] = (
104
+ (".cursor/commands/auto.md", "template/.cursor/commands/auto.md"),
105
+ (
106
+ "docs/engineering/auto-orchestration-reference.md",
107
+ "template/docs/engineering/auto-orchestration-reference.md",
108
+ ),
109
+ ("docs/engineering/runbook.md", "template/docs/engineering/runbook.md"),
110
+ ("README.md", "template/README.md"),
111
+ (
112
+ "scripts/check_intake_template_parity.py",
113
+ "template/scripts/check_intake_template_parity.py",
114
+ ),
115
+ )
116
+
81
117
  DOWNSTREAM_CI_GUARD_PAIRS: tuple[tuple[str, str], ...] = (
82
118
  (
83
119
  "scripts/check_downstream_ci_guard.py",
@@ -95,12 +131,16 @@ SCOPES: dict[str, tuple[tuple[str, str], ...]] = {
95
131
  "readme-feature-coverage": README_FEATURE_COVERAGE_PAIRS,
96
132
  "downstream-ci-guard": DOWNSTREAM_CI_GUARD_PAIRS,
97
133
  "us-0092": US0092_PAIRS,
134
+ "us-0093": US0093_PAIRS,
135
+ "us-0095": US0095_PAIRS,
98
136
  "all": (
99
137
  INTAKE_TEMPLATE_PAIRS
100
138
  + CAVEMAN_COMPRESS_PAIRS
101
139
  + README_FEATURE_COVERAGE_PAIRS
102
140
  + DOWNSTREAM_CI_GUARD_PAIRS
103
141
  + US0092_PAIRS
142
+ + US0093_PAIRS
143
+ + US0095_PAIRS
104
144
  ),
105
145
  }
106
146
 
@@ -71,19 +71,95 @@ Operators must follow the runbook recipe
71
71
  `stop_reason` vocabulary: `completed`, `decision_gate`, `missing_input`,
72
72
  `pause_request`, `loop_max`, `error`, `blocked`.
73
73
 
74
+ ## Native in-chat auto-chain (US-0095 / DEC-0080)
75
+
76
+ When **`AUTO_FLOW_MODE=full_autonomy`** runs in **Cursor IDE**, the orchestrator
77
+ **self-chains in-chat** across intersected lifecycle phases and backlog-drain
78
+ segment boundaries via a **foreground sequential** Task/subagent loop in the
79
+ **same /auto orchestrator session** — without mandatory outer driver or manual
80
+ re-invocation between segments.
81
+
82
+ ### Activation gate
83
+
84
+ | # | Condition |
85
+ |---|-----------|
86
+ | 1 | Merged scratchpad **`AUTO_FLOW_MODE=full_autonomy`** (exact literal) |
87
+ | 2 | Invocation context = **Cursor IDE** (default Agent panel `/auto` without `--invoke-cmd`) |
88
+ | 3 | Task tool available for foreground subagent spawn |
89
+
90
+ Set **`native_chain_active=true`** in `state.md` phase boundary when all hold.
91
+
92
+ ### Continuation loop (reference Step 5 — IDE primary)
93
+
94
+ 1. Resolve next `phase_id` from intersected schedule or drain-advance target.
95
+ 2. **US-0069** preflight (role matrix + capability gate).
96
+ 3. **Spawn fresh subagent** (Task tool, foreground — blocks until done).
97
+ 4. Verify isolation evidence + **DEC-0038** strict-proof tuple in `state.md`.
98
+ 5. Increment **`outer_cycle_index`**; check **`AUTO_LOOP_MAX_CYCLES`**.
99
+ 6. Branch stop matrix → continue spawn, drain-advance, block-retry, or hard stop.
100
+
101
+ **Loop invariants** (spawn-only — **BUG-0006** unchanged):
102
+
103
+ 1. Orchestrator **must not** stop after one phase or one story segment solely due to Cursor turn boundaries when continuation is schedulable.
104
+ 2. Each phase completes only via **fresh subagent spawn** + artifacts — orchestrator **must not** execute phase-role work in-band (**`AUTO_ORCHESTRATOR_PHASE_EXECUTION`** forbidden).
105
+ 3. **`stop_reason=completed (segment exhausted)`** is **invalid** when next phase, drain target, or relaxable retry is schedulable.
106
+
107
+ Preflight/post checks per **US-0069** / **DEC-0051** at every boundary.
108
+
109
+ ### Fail-closed: `NATIVE_CHAIN_UNAVAILABLE`
110
+
111
+ Emit when Task tool denied, spawn depth limit hit, or IDE context cannot schedule foreground subagent. Hard stop for native path. Optional fallback hint only: `python scripts/auto_outer_driver.py --repo .` (**optional** / **fallback** for headless/CI). **Non-suppressible** under **`AUTO_QUIET=1`**.
112
+
113
+ ### IDE drain-advance-without-pause
114
+
115
+ Deterministic **7-step** algorithm when **`full_autonomy`** + drain policy active (**`AUTO_BACKLOG_DRAIN=1`** or bug-queue per **US-0087** mutex).
116
+
117
+ **Trigger** (all required): `stop_phase=refresh-context`; `stop_reason=completed`; drain enabled; budget remaining.
118
+
119
+ | Step | Action |
120
+ |------|--------|
121
+ | **1** | **READ** latest phase-boundary block in `docs/engineering/state.md` |
122
+ | **2** | **ASSERT** **DEC-0069** pairing — completed phase refreshed **`resume_brief`** + **`state.md`**; stale → **`RESUME_BRIEF_STALE`** (fail-closed, no advance) |
123
+ | **3** | **SELECT** next work item (story or bug per drain mutex) |
124
+ | **4** | **RELOAD** scratchpad; **MATERIALIZE** `resolved_phase_plan` (**US-0070**) |
125
+ | **5** | **PREPEND** `handoffs/resume_brief.md` with segment pointers |
126
+ | **6** | **APPEND** `state.md` materialization breadcrumb for new segment |
127
+ | **7** | **IMMEDIATELY** spawn first phase subagent — **without operator re-`/auto`**, **no** mandatory outer-driver instruction |
128
+
129
+ **DEC-0069 pairing mandate**: every phase boundary and drain advance **must** refresh **`resume_brief`** + **`state.md`** before scheduling in-chat continuation. Stale brief → **`RESUME_BRIEF_STALE`** fail-closed (no advance).
130
+
131
+ ### Native-chain stop matrix (US-0095)
132
+
133
+ Native chain **does not weaken** **DEC-0078** hard gates. Hard stops (no relaxation): **`decision_gate`**, isolation/strict-proof violations, security deny, **`BACKLOG_MAX_STORIES_REACHED`**, **`AUTO_LOOP_MAX_CYCLES`**, unrecoverable **`error`**, **`pause_request`**. Relaxable transient stops per **DEC-0078** when configured.
134
+
135
+ ### `AUTO_QUIET` under native chain (US-0095)
136
+
137
+ | Event | `AUTO_QUIET=0` | `AUTO_QUIET=1` |
138
+ |-------|----------------|----------------|
139
+ | Routine phase PASS | May notify | **Suppress** |
140
+ | In-chat phase continuation | Compact breadcrumb OK | **Suppress** |
141
+ | Drain advance | Segment notify OK | **Suppress** routine prose; **no** outer-driver wait |
142
+ | Gates, caps, errors, **`NATIVE_CHAIN_UNAVAILABLE`** | **Always** | **Always** |
143
+
144
+ **Forbidden** in IDE-primary `full_autonomy` prose: mandatory `run the outer driver`; `re-run /auto` between drain segments; `segment exhausted` as terminal when continuation pending; unqualified `python scripts/auto_outer_driver.py`.
145
+
146
+ Full detail: **`docs/engineering/auto-orchestration-reference.md`**.
147
+
74
148
  ## Full-autonomy mode + outer driver (US-0092 / DEC-0078)
75
149
 
76
- **`AUTO_FLOW_MODE=full_autonomy`** (exact literal, default-off) enables the shipped
77
- stdlib outer driver **`scripts/auto_outer_driver.py`**. The driver **loops hook
78
- invocations** spawn-only preserved (**BUG-0006**); it never performs phase-role work.
150
+ **`AUTO_FLOW_MODE=full_autonomy`** (exact literal, default-off) enables hands-off
151
+ orchestration. **IDE primary path** (US-0095): run **`/auto` once in Cursor**
152
+ native in-chat auto-chain above. **Optional fallback**: stdlib outer driver
153
+ **`scripts/auto_outer_driver.py`** for headless/CI or when **`NATIVE_CHAIN_UNAVAILABLE`**.
79
154
 
80
- Operator recipe: set scratchpad keys run
155
+ The driver **loops hook invocations** spawn-only preserved (**BUG-0006**); it
156
+ never performs phase-role work. Headless/CI recipe: set scratchpad keys → run
81
157
  `python scripts/auto_outer_driver.py --repo .` once → interpret exit table in
82
- **`docs/engineering/runbook.md`** § **Full-autonomy outer driver (US-0092)**.
158
+ **`docs/engineering/runbook.md`** § **Full-autonomy outer driver (US-0092)** (**fallback**).
83
159
 
84
160
  **Drain-advance-without-pause**: with **`full_autonomy`** + **`AUTO_BACKLOG_DRAIN=1`**
85
161
  (or bug-queue policy), segment completion schedules the next OPEN story/bug
86
- **immediately** without operator re-`/auto`; **`resume_brief`** +
162
+ **immediately** **without operator re-`/auto`**; **`resume_brief`** +
87
163
  **`state.md`** refresh per **DEC-0069** at every boundary.
88
164
 
89
165
  ### Full-autonomy stop matrix (US-0092)
@@ -48,6 +48,32 @@ as stale isolation evidence).
48
48
 
49
49
  Release gate semantics (US-0039): mandatory gates (check-in test, QA, UAT) and no-bypass/override contract are enforced at `/release`; see `.cursor/commands/release.md` and `.cursor/commands/qa.md`.
50
50
 
51
+ ### Browser UAT self-test (US-0093)
52
+
53
+ When **`UAT_BROWSER_PROBE_MODE=cursor`** (default) and acceptance steps classify as **`browser_smoke`**
54
+ (or automatable **`manual_operator`** re-routed per **DEC-0079** §4), execute the **Cursor browser MCP**
55
+ sequence during `/execute` when web UI verification applies (**BUG-0006**: **`scripts/uat_probe_lib.py`**
56
+ never invokes MCP — subagent only):
57
+
58
+ 1. **Resolve target URL** — `docs/engineering/runtime-connectivity.md` first `http(s)://`; else
59
+ `package.json` dev/start + **`DEV_SERVER_PORT`** scratchpad override.
60
+ 2. **`browser_navigate`** — load URL; respect enterprise origin allowlist.
61
+ 3. **Step plan** — map automatable verbs to **`browser_click`** / **`browser_type`** / **`browser_scroll`**;
62
+ **never** fill password/credential fields; **never** read **`.env`** paths.
63
+ 4. **`browser_screenshot`** — write to **`sprints/Sxxxx/evidence/browser/<probe_id>-<seq>.png`** (max **5**).
64
+ 5. **Console + network evidence** — counts + summary path refs only (no inline secrets).
65
+ 6. **Verdict** — set **`passed`**, **`reason_code`**, **`browser_evidence_refs`** on the matching
66
+ **`probe_results[]`** row in **`uat.json`**. **`passed=true`** in **`cursor`** mode requires
67
+ non-empty **`navigation_url`** + at least one screenshot or console/network summary path — else
68
+ downgrade to **`UAT_BROWSER_PROBE_FAILED`**.
69
+ 7. **Fallback trigger** — MCP unavailable → record **`UAT_BROWSER_UNAVAILABLE`**; when
70
+ **`UAT_BROWSER_FALLBACK_CHAIN=1`**, stdlib HTTP/Playwright fallback runs via **`uat_probe_lib.py`**.
71
+ Both fail → **`UAT_BROWSER_PROBE_FAILED`** (no silent PASS).
72
+
73
+ Optional validation: **`python scripts/uat_probe_lib.py --merge-result <fragment.json>`** —
74
+ evidence-required-on-PASS in **`cursor`** mode. No auto-read **`.env`**, no credential auto-fill,
75
+ no intake evidence mutation.
76
+
51
77
  ## Intake evidence tooling reference (US-0078 / DEC-0060)
52
78
 
53
79
  Stories that harden intake persistence ship **`scripts/intake_evidence_lib.py`**,
@@ -77,6 +103,29 @@ parity for listed paths: **`python scripts/check_token_cost_parity.py --repo .`*
77
103
  - `/execute` must not start/continue implementation solely based on
78
104
  non-canonical status evidence.
79
105
 
106
+ ## Browser UAT self-test (US-0093)
107
+
108
+ When acceptance steps classify as **`browser_smoke`** (or automatable **`manual_operator`**
109
+ reclassified per **DEC-0079** §4) and **`UAT_BROWSER_PROBE_MODE=cursor`**, execute the **Cursor
110
+ browser MCP** sequence during execute-phase verification — **lib never calls MCP directly**
111
+ (**BUG-0006**):
112
+
113
+ 1. **Resolve target URL** — `docs/engineering/runtime-connectivity.md` first `http(s)://`; else
114
+ dev-server port from `package.json` + scratchpad **`DEV_SERVER_PORT`**.
115
+ 2. **`browser_navigate`** — respect origin allowlist.
116
+ 3. **Step plan** — **`browser_click`** / **`browser_type`** / **`browser_scroll`** when
117
+ automatable; **never** fill password/credential fields or read **`.env`**.
118
+ 4. **`browser_screenshot`** → **`sprints/Sxxxx/evidence/browser/<probe_id>-<seq>.png`** (max **5**).
119
+ 5. Console + network summary path refs only (no inline secrets).
120
+ 6. Write **`browser_evidence_refs`** to **`uat.json`** `probe_results[]`; mirror
121
+ **Runtime browser evidence** in **`qa-findings.md`**.
122
+ 7. MCP unavailable → **`UAT_BROWSER_UNAVAILABLE`** + stdlib fallback when
123
+ **`UAT_BROWSER_FALLBACK_CHAIN=1`**; validate with
124
+ **`python scripts/uat_probe_lib.py --merge-result <fragment.json>`**.
125
+
126
+ Reason codes: **`UAT_BROWSER_UNAVAILABLE`**, **`UAT_BROWSER_PROBE_FAILED`**,
127
+ **`UAT_BROWSER_PROBE_TIMEOUT`**. **No silent PASS** without agent evidence in **`cursor`** mode.
128
+
80
129
  ## Steps
81
130
  1. Implement one task at a time.
82
131
  2. Update summary and engineering state.
@@ -56,6 +56,35 @@ acceptance steps, execute probes where stack profile resolves, record evidence i
56
56
  Fail closed with **`UAT_PROBE_UNRESOLVED`** (not PASS) when no probe maps.
57
57
  Forbidden: auto-read **`.env`**, mutate intake evidence — **`UAT_PROBE_FORBIDDEN`**.
58
58
 
59
+ Reason codes extend with **`UAT_BROWSER_UNAVAILABLE`**, **`UAT_BROWSER_PROBE_FAILED`**,
60
+ **`UAT_BROWSER_PROBE_TIMEOUT`** (**US-0093** / **DEC-0079**).
61
+
62
+ ### Browser UAT self-test (US-0093)
63
+
64
+ When **`UAT_BROWSER_PROBE_MODE=cursor`** (default) and step classifies as **`browser_smoke`**
65
+ (or automatable **`manual_operator`** reclassified per **DEC-0079** §4), execute the **Cursor
66
+ browser MCP** sequence — **lib never calls MCP directly** (**BUG-0006**):
67
+
68
+ 1. **Resolve target URL** — `docs/engineering/runtime-connectivity.md` first `http(s)://`; else
69
+ dev-server port from `package.json` + scratchpad **`DEV_SERVER_PORT`**.
70
+ 2. **`browser_navigate`** — load health/app URL; respect enterprise origin allowlist.
71
+ 3. **Step plan** — map acceptance verbs to **`browser_click`** / **`browser_type`** /
72
+ **`browser_scroll`** when automatable; **never** fill password/credential fields or read **`.env`**.
73
+ 4. **`browser_screenshot`** — write to **`sprints/Sxxxx/evidence/browser/<probe_id>-<seq>.png`**
74
+ (max **5** per probe).
75
+ 5. **Console + network evidence** — counts + summary path refs only (no inline secrets).
76
+ 6. **Verdict** — set **`passed`**, **`reason_code`**, **`browser_evidence_refs`** in
77
+ **`uat.json`** `probe_results[]`; **`passed=true`** in **`cursor`** mode **requires** non-empty
78
+ **`navigation_url`** + at least one screenshot or console/network summary path — else
79
+ **`UAT_BROWSER_PROBE_FAILED`**. Mirror under **`qa-findings.md`** **Runtime browser evidence**.
80
+ 7. **Fallback** — MCP unavailable → record **`UAT_BROWSER_UNAVAILABLE`**, run stdlib fallback when
81
+ **`UAT_BROWSER_FALLBACK_CHAIN=1`**; validate via
82
+ **`python scripts/uat_probe_lib.py --merge-result <fragment.json>`**.
83
+
84
+ **No silent PASS** — stdlib alone does **not** PASS **`browser_smoke`** in **`cursor`** mode
85
+ without agent **`browser_evidence_refs`**. Security: no auto-read **`.env`**, no credential
86
+ auto-fill, no intake evidence mutation — **`UAT_PROBE_FORBIDDEN`** unchanged.
87
+
59
88
  ## Steps
60
89
  0. If `SECURITY_REVIEW=1`, verify `docs/engineering/security-review.md` exists
61
90
  and has no unresolved `critical` findings before proceeding. If unresolved
@@ -103,12 +103,39 @@ Record evidence in **`sprints/Sxxxx/uat.json`** `probe_results[]` and
103
103
  **No silent PASS** — unresolvable steps must record fail-closed reason codes:
104
104
 
105
105
  `UAT_PROBE_UNRESOLVED`, `UAT_STACK_PROFILE_UNKNOWN`, `UAT_PROBE_TIMEOUT`,
106
- `UAT_PROBE_FAILED`, `UAT_PROBE_FORBIDDEN`, `UAT_PROBE_PASS`.
106
+ `UAT_PROBE_FAILED`, `UAT_PROBE_FORBIDDEN`, `UAT_PROBE_PASS`,
107
+ `UAT_BROWSER_UNAVAILABLE`, `UAT_BROWSER_PROBE_FAILED`, `UAT_BROWSER_PROBE_TIMEOUT`.
107
108
 
108
109
  Probe catalog: **`build`**, **`test`**, **`api_health`**, **`process_health`**,
109
110
  **`browser_smoke`**, **`cli_smoke`**, **`manual_operator`**. CLI:
110
111
  `python scripts/uat_probe_lib.py --repo . --step "<acceptance step>" --report`.
111
112
 
113
+ ### Browser UAT self-test (US-0093)
114
+
115
+ When **`UAT_BROWSER_PROBE_MODE=cursor`** (default) and step classifies as **`browser_smoke`**
116
+ (or automatable **`manual_operator`** reclassified per **DEC-0079** §4), execute the **Cursor
117
+ browser MCP** sequence — **lib never calls MCP directly** (**BUG-0006**):
118
+
119
+ 1. **Resolve target URL** — `docs/engineering/runtime-connectivity.md` first `http(s)://`; else
120
+ dev-server port from `package.json` + scratchpad **`DEV_SERVER_PORT`**.
121
+ 2. **`browser_navigate`** — load health/app URL; respect enterprise origin allowlist.
122
+ 3. **Step plan** — map acceptance verbs to **`browser_click`** / **`browser_type`** /
123
+ **`browser_scroll`** when automatable; **never** fill password/credential fields or read **`.env`**.
124
+ 4. **`browser_screenshot`** — write to **`sprints/Sxxxx/evidence/browser/<probe_id>-<seq>.png`**
125
+ (max **5** per probe).
126
+ 5. **Console + network evidence** — counts + summary path refs only (no inline secrets).
127
+ 6. **Verdict** — set **`passed`**, **`reason_code`**, **`browser_evidence_refs`** in
128
+ **`uat.json`** `probe_results[]`; **`passed=true`** in **`cursor`** mode **requires** non-empty
129
+ **`navigation_url`** + at least one screenshot or console/network summary path — else
130
+ **`UAT_BROWSER_PROBE_FAILED`**. Mirror under **`qa-findings.md`** **Runtime browser evidence**.
131
+ 7. **Fallback** — MCP unavailable → record **`UAT_BROWSER_UNAVAILABLE`**, run stdlib fallback when
132
+ **`UAT_BROWSER_FALLBACK_CHAIN=1`**; validate via
133
+ **`python scripts/uat_probe_lib.py --merge-result <fragment.json>`**.
134
+
135
+ **No silent PASS** — stdlib alone does **not** PASS **`browser_smoke`** in **`cursor`** mode
136
+ without agent **`browser_evidence_refs`**. Security: no auto-read **`.env`**, no credential
137
+ auto-fill, no intake evidence mutation — **`UAT_PROBE_FORBIDDEN`** unchanged.
138
+
112
139
  ## Steps
113
140
  1. Convert acceptance criteria into testable UAT steps. Derive steps directly from the story's acceptance criteria in `docs/product/acceptance.md`. Each AC should map to at least one UAT step. Run **`scripts/uat_probe_lib.py`** for each step where automation applies; record `probe_results[]` in **`uat.json`**.
114
141
  2. Populate UAT artifacts: write derived steps into `uat.json` (with description and result per step, accurate pass/fail counts) and `uat.md` (step list with results, summary section). Ensure UAT artifacts are in **populated** state per DEC-0009 — not placeholder.
@@ -238,6 +238,27 @@ DOC_DETAIL_LEVEL=balanced
238
238
  # - README_FEATURE_COVERAGE_ENFORCE: 0|1 (default 0 until backfill + --report green)
239
239
  README_FEATURE_COVERAGE_ENFORCE=1
240
240
 
241
+ #
242
+ # ## Browser UAT self-test (US-0093 / DEC-0079)
243
+ # Two-tier browser probe: stdlib lib classifies + agent owns Cursor browser MCP (BUG-0006).
244
+ # - UAT_BROWSER_PROBE_MODE: cursor|http_fallback|playwright_fallback (default cursor)
245
+ # - cursor: agent executes MCP sequence; lib emits plan + UAT_PROBE_UNRESOLVED until evidence
246
+ # - http_fallback: stdlib HTTP GET (CI recipe — set this in CI)
247
+ # - playwright_fallback: subprocess Playwright primary; HTTP fallback when missing
248
+ # - UAT_BROWSER_FALLBACK_CHAIN: 0|1 (default 1; enable HTTP → Playwright after MCP unavailable)
249
+ # - UAT_PROCESS_HEALTH_POLL_SECONDS: positive int (default 60; process_health readiness cap)
250
+ # - UAT_PROCESS_HEALTH_POLL_INTERVAL_SECONDS: positive int (default 2; poll interval)
251
+ # - DEV_SERVER_PORT: int (optional; URL/port inference override)
252
+ # - DEV_SERVER_COMMAND: shell command (optional; process_health startup override)
253
+ # Interaction: orthogonal to PERMISSION_MODE and Cursor browser approval modes (manual / allow-list /
254
+ # auto-run per vendor docs). Health URLs from docs/engineering/runtime-connectivity.md first.
255
+ UAT_BROWSER_PROBE_MODE=cursor
256
+ UAT_BROWSER_FALLBACK_CHAIN=1
257
+ UAT_PROCESS_HEALTH_POLL_SECONDS=60
258
+ UAT_PROCESS_HEALTH_POLL_INTERVAL_SECONDS=2
259
+ DEV_SERVER_PORT=
260
+ DEV_SERVER_COMMAND=
261
+
241
262
  #
242
263
  # ## Caveman mode (US-0089)
243
264
  # Response-side voice toggle. Default off. Composition is orthogonal to
@@ -247,10 +268,18 @@ README_FEATURE_COVERAGE_ENFORCE=1
247
268
  # - CAVEMAN_MODE: 0|1 (default 0; absence = 0)
248
269
  # - CAVEMAN_LEVEL: lite|full|ultra (empty; with MODE=1 empty -> treat as full;
249
270
  # unknown value -> CAVEMAN_LEVEL_UNKNOWN and fall back to pre-US-0089 voice)
250
- # - CAVEMAN_COMPRESS_INPUT: 0|1 -- reserved for US-0090; inert in US-0089;
251
- # no behavior until compression story ships
252
- # - CAVEMAN_FILE_SCOPE: string -- reserved for US-0090; inert in US-0089;
253
- # no behavior until compression story ships
271
+ #
272
+ # ## Caveman input compression (US-0090 / DEC-0073)
273
+ # Input-side prose minification via scripts/caveman_compress_input.py. Default off.
274
+ # Orthogonal to CAVEMAN_MODE (reply voice) and TOKEN_PROFILE (context breadth).
275
+ # - CAVEMAN_COMPRESS_INPUT: 0|1 (default 0) -- activation gate; must be 1 for --write
276
+ # - CAVEMAN_FILE_SCOPE: string (empty default) -- allow-list of files eligible for compression:
277
+ # * empty: no files in scope (fail-closed on --write with CAVEMAN_COMPRESS_SCOPE_EMPTY)
278
+ # * named profile: e.g. docs-prose-only (user-guides, runbook, state-archive, handoffs/archive)
279
+ # * raw globs: e.g. docs/user-guides/**/*.md,handoffs/archive/*.md (forward slashes only)
280
+ # * hybrid: profile:docs-prose-only;globs:handoffs/archive/*.md
281
+ # Mutation requires COMPRESS_INPUT=1 + non-empty scope + CLI --write; use --dry-run first.
282
+ # Originals land in docs/.caveman-originals/<path>; deny-list always wins over allow.
254
283
  CAVEMAN_MODE=0
255
284
  CAVEMAN_LEVEL=
256
285
  CAVEMAN_COMPRESS_INPUT=0
@@ -240,3 +240,23 @@ USER_GUIDE_MODE=0
240
240
  DOC_AUDIENCE_PROFILE=both
241
241
  DOC_DETAIL_LEVEL=balanced
242
242
 
243
+ #
244
+ # ## Browser UAT self-test (US-0093 / DEC-0079)
245
+ # Two-tier browser probe: stdlib lib classifies + agent owns Cursor browser MCP (BUG-0006).
246
+ # - UAT_BROWSER_PROBE_MODE: cursor|http_fallback|playwright_fallback (default cursor)
247
+ # - cursor: agent executes MCP sequence; lib emits plan + UAT_PROBE_UNRESOLVED until evidence
248
+ # - http_fallback: stdlib HTTP GET (CI recipe — set this in CI)
249
+ # - playwright_fallback: subprocess Playwright primary; HTTP fallback when missing
250
+ # - UAT_BROWSER_FALLBACK_CHAIN: 0|1 (default 1; enable HTTP → Playwright after MCP unavailable)
251
+ # - UAT_PROCESS_HEALTH_POLL_SECONDS: positive int (default 60; process_health readiness cap)
252
+ # - UAT_PROCESS_HEALTH_POLL_INTERVAL_SECONDS: positive int (default 2; poll interval)
253
+ # - DEV_SERVER_PORT: int (optional; URL/port inference override)
254
+ # - DEV_SERVER_COMMAND: shell command (optional; process_health startup override)
255
+ # Interaction: orthogonal to PERMISSION_MODE and Cursor browser approval modes (manual / allow-list /
256
+ # auto-run per vendor docs). Health URLs from docs/engineering/runtime-connectivity.md first.
257
+ UAT_BROWSER_PROBE_MODE=cursor
258
+ UAT_BROWSER_FALLBACK_CHAIN=1
259
+ UAT_PROCESS_HEALTH_POLL_SECONDS=60
260
+ UAT_PROCESS_HEALTH_POLL_INTERVAL_SECONDS=2
261
+ DEV_SERVER_PORT=
262
+ DEV_SERVER_COMMAND=