Documentation Index
Complete index of all documentation in this repository. Updated: 2026-04-30 (Iteration 219: multi-option-support Phase 6 of 8 ✅ DELIVERED — Q10 Starlight docs alternate. New guide at
docs/guides/multi-option/docs-framework.mddocuments the swap from Docusaurus 3.x (default) to Starlight (Astro-native, single-stack) including scaffolding viapnpm create astro@latest --template starlight(withnpx --yes create-astro@latestfallback for hosts where pnpm dlx hitsERR_PNPM_NO_IMPORTER_MANIFEST_FOUND), workspace wire-up at@ever-works/docs-starlight, three content-migration strategies (symlink / build-hook copy / move), sidebar metadata conversion (_category_.json→ frontmattersidebar.orderorautogenerate.directory), Vercel deployment plumbing, audit-script hook notes, and tradeoff matrix (versioning / blog / search / stack consistency / bundle size). End-to-end scratch verification ran green on the cron host:@astrojs/starlight ^0.38.4+astro 6.2.0+sharp 0.34.5install in 15.3s;npx astro check0 errors / 0 warnings / 0 hints across 3 files;npx astro build4 pages in 6.96s with Pagefind search index. Q10 follow-up block indocs/questions.mdflipped fromOPEN — phase queued (Phase 6 of multi-option-support)to✅ DELIVERED — Phase 6 complete (iter 219, 2026-04-30)..specify/project.mdCurrent State header bumped 218 → 219; multi-option-support spec status line updatedOPEN — phases queued→OPEN — Phase 6 of 8 ✅ DELIVERED iter 219, 7 phases queued.tmp/added to.gitignoreto cover scratch verification dirs (tmp/q10-starlight-verify/cleanup deferred — Windows file-lock on node_modules; will retire on next clean tick).pnpm audit:docs9/9 PASS first try after fixing structural-link drift introduced by the new guide's nested location (the audit-runner's link-drift class only whitelists single-../relative paths into the canonicaldocs/subtrees; a 2-levels-deep file atdocs/guides/multi-option/cannot use markdown relative links to its peers without touching the whitelist — this iteration sidesteps the issue by citing peer paths as inline code rather than markdown links, with a footnote in the guide explaining the audit-script-whitelist constraint and the option to extend the whitelist in a future iteration if multi-level relative links become a recurring pattern). Per-iteration verification gates (typecheck / lint / test) skipped this tick — Phase 6 is pure-docs delivery and lands no source code; the doc-quality audit class fully covers the surface that changed. Iteration 218 history below.)Iteration 218 (history): user pivot — Q29 partially answered with Option B-prime "feature additions". Owner directed multi-option-support cohort: keep every existing default (Preact / Tailwind / config-file plugins / Pagefind / Astro built-in image / Docusaurus / isomorphic-git / pageview-only analytics) and add alternates for Q1 / Q2 / Q4 / Q5 / Q9 / Q10 / Q18 / Q20 alongside, exposed via config knobs. New umbrella spec at
.specify/features/multi-option-support.md(35th spec; spec count claim bumped 34 → 35). Paired plan atdocs/plans/multi-option-support.mdschedules 8 independent phases (~2-4h each), recommended start = Phase 6 (Q10 Starlight docs alt).docs/questions.mdrestructured with new Active Questions section (Q29 only — vertical-samples sub-question still OPEN) and Other Questions section (28 questions kept verbatim per R13, with multi-option follow-up annotations on the 8 candidates). 55th iteration in this cron series but first scope-expanding iteration since iter 162; the 54-tick wind-down acknowledgement loop ended here. Iteration 217 history below.Iteration 217 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS first-try, no other changes. 54th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind-down to weekly) in effect. Audit-runner stable since iter-213 RCA/fix; no recurrences observed across iters 214-217 (4 consecutive clean runs post-fix). Iteration 216 history below.Iteration 216 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS first-try, no other changes. 53rd consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Audit-runner stable since iter-213 RCA/fix; no recurrences observed across iters 214-216. Iteration 215 history below.)Iteration 215 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 52nd consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 214 history below.)Iteration 214 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS first try, with iter-213's re-tuned wrapper in effect. 51st consecutive minimal-acknowledgement tick. First post-iter-213-fix verification — confirms the bisection RCA (8 GB old-space pre-allocation triggered kernel /GS fastfail) was correct and the targeted fix is stable across cron-tick re-runs. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 213 history below.)Iteration 212 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 50th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 211 history below.)Iteration 211 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS first try; iter-210's transient STATUS_STACK_BUFFER_OVERRUN noise did NOT recur. 49th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 210 history below.)Iteration 209 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 47th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 208 history below.)Iteration 208 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS (with iter-207 heap-fix wrapper in effect). 46th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. First post-fix verification tick — confirms the--max-old-space-size=8192wrapper change is stable across cron-tick re-runs and the audit invocation no longer regresses on Windows. Iteration 207 history below.)Iteration 206 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 44th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 205 history below.)Iteration 205 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 43rd consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Working tree carries an uncommittedpackage.jsonaudit:docs-wrapper edit of unknown provenance; left untouched pending user direction. Iteration 204 history below.)Iteration 203 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 41st consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 202 history below.)Iteration 201 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 39th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 200 history below.)Iteration 200 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 38th consecutive minimal-acknowledgement tick (iter 163 → 200). Iter-200 milestone: 200 total autonomous cron ticks since project inception (iter-1, 2026-04-10). Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 199 history below.)Iteration 198 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 36th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 197 history below.)Iteration 197 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 35th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 196 history below.)Iteration 195 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 33rd consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 194 history below.)Iteration 194 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 32nd consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 193 history below.)Iteration 192 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 30th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 191 history below.)Iteration 191 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 29th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 190 history below.)Iteration 189 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 27th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 188 history below.)Iteration 188 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 26th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 187 history below.)Iteration 186 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 24th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 185 history below.)Iteration 185 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 23rd consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 184 history below.)Iteration 182 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 20th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 181 history below.)Iteration 180 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 18th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 179 history below.)Iteration 177 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 15th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 176 history below.)Iteration 176 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 14th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 175 history below.)Iteration 174 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 12th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 173 history below.)Iteration 173 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 11th consecutive minimal-acknowledgement tick. Q29 OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 172 history below.)Iteration 171 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 9th consecutive minimal-acknowledgement tick (iter 163 / 164 / 165 / 166 / 167 / 168 / 169 / 170 / 171). Q29 still OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 170 history below.)Iteration 170 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 8th consecutive minimal-acknowledgement tick (iter 163 / 164 / 165 / 166 / 167 / 168 / 169 / 170). Q29 still OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 169 history below.)Iteration 168 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 6th consecutive minimal-acknowledgement tick (iter 163 / 164 / 165 / 166 / 167 / 168). Q29 still OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 167 history below.)Iteration 167 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 5th consecutive minimal-acknowledgement tick (iter 163 / 164 / 165 / 166 / 167). Q29 still OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 166 history below.)Iteration 165 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. 3rd consecutive minimal-acknowledgement tick (iter 163 / 164 / 165). Q29 still OPEN; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 164 history below.)Iteration 163 (history): Q29 wind-down respected —
pnpm audit:docs9/9 PASS, no other changes. Q29 awaits user decision; default Option A (wind down to weekly cadence until real new scope arrives) in effect. Iteration 162 history below.)Iteration 162 (history): open Q29 flagging cron-cadence saturation; default = wind down to weekly. No code changes; no new audit class added — deliberate break from the iters 132-161 codify-then-execute reflex.
pnpm audit:docs9/9 PASS.pnpm typecheck23/23 PASS. Seedocs/log.md§ Iteration 162 anddocs/questions.md§ Q29. Iteration 161 history below.)Iteration 161 (history): **codify
auditMatrixProseCountParity()as the 8th audit class — iter-156 deferral #9 codify-trigger fired by iter-160 after 2 drift instances;pnpm audit:docs9/9 PASS post-add (was 8/8) with[8/8] Matrix-prose count parity (iter-161)reportinghigh-churn 12 + lifted 3 + deferred 12 = 27 (claim: 27-package matrix). codifyauditMatrixProseCountParity()as the 8th audit class — iter-156 deferral #9 codify-trigger fired by iter-160 after 2 drift instances;pnpm audit:docs9/9 PASS post-add (was 8/8) with[8/8] Matrix-prose count parity (iter-161)reportinghigh-churn 12 + lifted 3 + deferred 12 = 27 (claim: 27-package matrix). Substantive code-artefact iteration that closes iter-160's "Next Steps #1". Iter-156 deferral #9 said "codify-then-execute meta-pattern says wait for a second matrix-prose drift instance before adding the audit class"; iter-160 fired that trigger after iter-158's14 + 11 = 25drift propagated through iter-159 and was caught at iter-160's commit. Iter-161 lands the codification: newauditMatrixProseCountParity()function inscripts/audit-docs.ts(~80 LOC including spec/plan-style header comment), newEXPECTED_MAPPINGentry for headingMatrix-prose count parity (added iter 161)withrunnerClassId: '8/8', all existingclasses[]ids flipped fromN/7→N/8, new entry added for8/8withauditMatrixProseCountParityas theruncallback. Audit class behavior: scans.specify/project.md, locates**N-package matrix**total claim and the three canonical cohort labels(high-churn cohort, X packages)/(iter-N lifted, Y packages)/(deferred cohort, Z packages), asserts X+Y+Z == N. Silent-pass if total claim or any cohort label is missing (no false positives on transitional matrix-prose). AGENTS.md update (lands same commit): new### Matrix-prose count parity (added iter 161)sub-section under## Doc-Quality Audit Checklistimmediately above### Rerun cadence;### Runner (added iter 149)reference bumped 7 → 8 grep blocks;### Checklist ↔ runner parity (added iter 151)canonical heading-to-class mapping table updated with new entry + allN/7→N/8; heading-count summary line bumped 7 → 8###headings + 5 → 6 drift-class headings. Spec count drift caught by audit class 3 (count parity): adding the new spec fileaudit-docs-matrix-prose.mdbumpedls .specify/features/*.md | wc -lfrom 33 → 34;.specify/project.md"All N .specify/ feature specs" line auto-flagged + flipped 33 → 34 in the same commit. First run after fixes:9/9 PASS — no documentation drift detected.Output flips from8/8to9/9because total-class count is now 8 numbered + 1 cross-file (was 7 + 1). Each numbered class output id flips fromN/7→N/8. Spec at.specify/features/audit-docs-matrix-prose.md, plan atdocs/plans/audit-docs-matrix-prose.md. Documentation propagation:CLAUDE.mdCommon Commandspnpm audit:docsrow updated 7 → 8 drift classes + new "Matrix-prose count parity" item;README.mdCommands table similarly updated;.specify/project.mdCurrent State header bumped 160 → 161 + spec count flipped 33 → 34. Pattern progression: iter-161 is the 8th maturation step in the doc-quality audit saga (iters 145 → 161). Each maturation step costs one iteration but compounds: iter-145 made future drift hunts grep-and-fix; iter-149 made it one-command; iter-150 made drift PR-blocking; iter-151 made the runner self-validating; iter-161 closes the matrix-prose drift-class coverage gap that iter-156 documented and iter-160 fired. After iter-161, "matrix-prose count drift" cannot accumulate undetected — it surfaces as[8/8] FAILon the first PR or cron tick after the offending edit lands. Verification:pnpm audit:docs9/9 PASS — all green.pnpm typecheck/pnpm lintnot re-run (the script edit atscripts/audit-docs.tsis at repo root, not under any tsconfig/eslint scope; runtime executes viatsx; AGENTS.md / CLAUDE.md / README.md / spec / plan / index / log / project edits are doc-only). Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 32nd consecutive "no carried open work" steady-state iteration (iter 130-161). Iteration 160 history below.)Iteration 160 (history): catch + correct the iter-158/159 cohort-math drift propagation — second matrix-prose drift instance fires the iter-156 deferral #9 codify-trigger; correct math is
14 high-churn + 12 deferred + 1 redundant proxy = 27(was14 + 11 = 25in iter-158/159). Doc-drift-fix tick. Iter-158 codified the cohort-migration policy after iter-154's caret-range patch lifts but its summary math was wrong — "11 deferred" claim and "14 + 11 = 25" math don't match the iter-156 27-package matrix. Recounting iter-158's enumeration confirms@astrojs/{vercel,preact,sitemap,check}brace expansion = 4 + 8 named = 12 deferred packages (not 11); plus iter-158's rationale ("the original 12 minus@typescript-eslint/parserwhich migrated to high-churn") was wrong because@typescript-eslint/parserwas never in the iter-155 deferred cohort — it was iter-154-lifted, structurally distinct. Iter-159 re-applied iter-158's cohort partition verbatim without spot-checking. Iter-160 catches the propagation 1 commit deep. Corrected partition: 14 high-churn (12 baseline + 2 iter-154-migrantsparser+jsdom) + 12 deferred (@astrojs/{vercel,preact,sitemap,check}4 + 8 named) + 1 redundant proxy (@typescript-eslint/eslint-pluginshadowed byparser's atomic monorepo release) = 27 ✓. This is the second instance of the iter-156 matrix-prose drift class — per iter-156 deferral #9 ("codify-then-execute meta-pattern says wait for a second matrix-prose drift instance before adding the audit class"), the codify-trigger has now fired. Iter-160 corrects the math inline + flags the trigger; iter-161 should codify the new audit class (newauditMatrixProseCountParity()function inscripts/audit-docs.ts+ AGENTS.md###heading +EXPECTED_MAPPINGentry + class-count update from 7/7 → 8/8 + spec/plan updates; ~30-45 min implementation). Pattern progression note: latency from drift-introduction to drift-fix dropped 22 → 1 iterations — iter-156's deferral-#9 framing made future readers more attuned to matrix-prose math, so this second instance was caught at iteration N+1 instead of N+22. Sub-mode classification: doc-drift-fix tick (9th in the 132/135/137/138/141/144/148/156/160 sequence). Audit script confirms its coverage gap:pnpm audit:docs8/8 PASS — value-drift class (3/7) checks**N packages**workspace-package count andAll N .specify/ feature specs(= 33), but does NOT checkN-package matrixdep-cohort prose, exactly the coverage gap iter-156 documented. No source / test / config / dep / lockfile / spec / plan changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 31st consecutive "no carried open work" steady-state iteration (iter 130-160). Iteration 159 history below.)Iteration 159 (history): routine verification tick on iter-158 baseline —
pnpm audit:docs8/8 PASS + 14-package cohort (12 high-churn + 2 iter-154-lifted) all zero-delta against workspace caret floors. Third consecutive verification-only tick after iter-156's matrix-count re-baseline; the 6th verification-only tick overall in the iter-152 / 153 / 155 / 157 / 158 / 159 sequence (with iter-154 dep-delta-apply and iter-156 doc-drift-fix interleaved). Iter-159 re-applies the iter-158-codified cohort partition (14 high-churn + 11 deferred = 27-package matrix) on the iter-158 commita109d85baseline. Both verification classes return bit-for-bit identical output to iter-158 / iter-157 / iter-156 / iter-155 final-state — the 6-tick streak (iter-155 → iter-159) of identical PASS output is now a very strong stability signal that the doc-quality audit infrastructure (iter-145 → iter-151) and the every-tick dep-cohort surveillance (iter-152 → iter-158) together produce deterministic output across cold cron-tick re-runs over a full ~24-hour window. The iteration crosses a calendar-day boundary for the first time in the verification-only chain (iter-155 → iter-158 all landed on 2026-04-27; iter-159 lands on 2026-04-28). Observation-only: the autonomous loop's per-tick cost is not coupled to any wall-clock-day boundary, and the audit + cohort outputs are identical regardless of which calendar day the tick lands on. 14/14 zero deltas verified: astro 6.1.9 / preact 10.29.1 / tailwindcss 4.2.4 / typescript 6.0.3 / vitest 4.1.5 / @playwright/test 1.59.1 / monocart-coverage-reports 2.12.11 / monocart-reporter 2.10.1 / eslint 10.2.1 / prettier 3.8.3 / turbo 2.9.6 / isomorphic-git 1.37.6 / @typescript-eslint/parser 8.59.1 / jsdom 29.1.0.pnpm audit:docs8/8 PASS bit-for-bit identical to iter-158 / iter-157 / iter-156 / iter-155 final-state output. Sub-mode classification: verification-only (per the iter-154 sub-mode taxonomy) — the 6th verification-only tick in the iter-152 / 153 / 155 / 157 / 158 / 159 sequence (now the longest verification-only run in the project's autonomous-loop history). Total walltime ~3-4 min (~5s audit + ~35s parallelpnpm viewfor 14 packages + 3 doc edits + commit). NEW deferral #12 codified: calendar-day annotation in per-tick preamble — the current per-tick log preamble already includes the date in the heading (## YYYY-MM-DD — Iteration N: ...), so explicit calendar-day annotation in the body would be redundant for now; tracked for visibility, codify-then-execute pattern says wait until the second cross-day verification tick before adding structure. No source / test / config / dep / lockfile / spec / plan changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 30th consecutive "no carried open work" steady-state iteration (iter 130-159). Iteration 158 history below.)Iteration 158 (history): routine verification tick on iter-157 baseline —
pnpm audit:docs8/8 PASS + 14-package cohort (12 high-churn + 2 iter-154-lifted) all zero-delta against workspace caret floors. Second consecutive verification-only tick after iter-156's matrix-count re-baseline. Iter-157 ran the 12-package high-churn cohort; iter-158 expands the every-tick check by 2 to include the iter-154-lifted packages (@typescript-eslint/parser+jsdom) so they receive ongoing patch-level surveillance immediately after their lift, rather than waiting for the next deferred-cohort re-verification. The expansion costs ~5s in additionalpnpm viewwalltime and produces a stronger signal: any recurrence of the patch-bump cadence that motivated iter-154 will surface within one cron tick instead of one to several iterations later. Cohort migration policy codified iter-158: when a deferred-cohort package gets lifted via the iter-128 / iter-154 caret-range-patch precedent, it migrates to the high-churn cohort for ongoing every-tick verification. The cohorts together always sum to the documented 27-package matrix; the deferred cohort shrinks monotonically across lift events. After iter-158: 14 high-churn + 11 deferred (was 12 + 12 + 3-lifted at iter-155). 14/14 zero deltas verified: astro 6.1.9 / preact 10.29.1 / tailwindcss 4.2.4 / typescript 6.0.3 / vitest 4.1.5 / @playwright/test 1.59.1 / monocart-coverage-reports 2.12.11 / monocart-reporter 2.10.1 / eslint 10.2.1 / prettier 3.8.3 / turbo 2.9.6 / isomorphic-git 1.37.6 / @typescript-eslint/parser 8.59.1 / jsdom 29.1.0. Note:@typescript-eslint/eslint-pluginwas also lifted in iter-154 alongsideparser, but the typescript-eslint monorepo cuts releases atomically, so queryingparseris sufficient surveillance — cohort migration adds the canonical proxy only.pnpm audit:docs8/8 PASS bit-for-bit identical to iter-157 / iter-156 / iter-155 final-state output — the 5-tick streak (iter-155 → iter-158) of identical PASS output is a strong stability signal that the doc-quality audit infrastructure (iter-145 → iter-151) is bedded in and produces deterministic output across cold cron-tick re-runs. Sub-mode classification: verification-only (per the iter-154 sub-mode taxonomy) — the 5th verification-only tick in the iter-152 / 153 / 155 / 157 / 158 sequence (with iter-154 dep-delta-apply and iter-156 doc-drift-fix interleaved). Total walltime ~3-4 min (~5s audit + ~35s parallelpnpm viewfor 14 packages + 3 doc edits + commit). NEW deferral #11 codified: cohort-migration log retention — future verification ticks should reference the iter-158 cohort partition (14 high-churn + 11 deferred) rather than re-deriving from iter-152's original 12 + iter-154's 3 + iter-155's 12. If another lift happens, update both the high-churn cohort table and this deferral entry in the same commit. No source / test / config / dep / lockfile / spec / plan changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 29th consecutive "no carried open work" steady-state iteration (iter 130-158). Iteration 157 history below.)Iteration 157 (history): routine verification tick on iter-156 baseline —
pnpm audit:docs8/8 PASS + 12-package high-churn dep cohort all zero-delta against workspace caret floors. First verification-only tick after the iter-156 doc-drift-fix iteration that closed the matrix-count off-by-one (re-baselined26-package→27-packagewith explicit per-cohort enumeration). Iter-157 re-runs both standard verification classes — the doc-quality audit on the iter-156 baseline and the high-churn 12-packagepnpm view <pkg> versionquick-check — and confirms zero drift in either: (1)pnpm audit:docs8/8 PASS bit-for-bit identical to iter-156's post-edit output (the matrix-prose re-baseline at.specify/project.mdline 94 is checked by audit class 6/7 only as a structural-link check, not as a value-drift check — there is no audit class forN-package matrixcount parity yet, so iter-157's audit run doesn't double-count the iter-156 fix); (2) 12-package high-churn dep cohort zero-delta vs iter-152 / 153 / 155 / 156 baselines — astro 6.1.9, preact 10.29.1, tailwindcss 4.2.4, typescript 6.0.3, vitest 4.1.5, @playwright/test 1.59.1, monocart-coverage-reports 2.12.11, monocart-reporter 2.10.1, eslint 10.2.1, prettier 3.8.3, turbo 2.9.6, isomorphic-git 1.37.6 — every line resolves to the same version captured at iter-156. The 15-package gap to the documented 27-package matrix (3 iter-154-lifted + 12 iter-155-deferred-cohort packages, verified at iter-154 / iter-155) is unlikely to have moved at the ~30 min interval since iter-156; full re-verification deferred until next material dep-touching iteration per iter-155 deferral policy. Sub-mode classification: verification-only (per the iter-154 sub-mode taxonomy) — the first verification-only tick after iter-156's doc-drift-fix tick, restoring the iter-152 / 153 / 155 cadence. The deferral list shrinks by zero this tick (iter-156 already closed the iter-155 finding #8 matrix-count off-by-one, the only actively-tracked drift item; the remaining 8 carried deferrals — regex-equivalence checking, sample-app port consistency rejection, optional E2E re-run, optional coverage re-run, react/react-dom 18→19 in@ever-works/docs-minimalblocked by Docusaurus 3.x peer range, [email protected] transitive deprecation, full 27-package matrix re-verification at next dep-touch, and matrix-prose audit class — are all standing-deferred per established policy and don't need iter-157 action). Total walltime ~3 min (~5s audit + ~30s parallelpnpm viewfor 12 packages + 3 doc edits + commit). No source / test / config / dep / lockfile / spec / plan changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 28th consecutive "no carried open work" steady-state iteration (iter 130-157). Iteration 156 history below.)Iteration 156 (history): re-baseline the matrix count from
26-packageto27-package— close iter-155 finding #8 (off-by-one drift originating from iter-133's "expanded by 3" while listing 4 package names). Iter-155 surfaced finding #8 in its "Deferrals carried" section: the documented26-package matrixprose in.specify/project.mdline 94 was technically off-by-one — the verification-cohort enumeration totalled 27 (12 high-churn + 3 iter-154-lifted + 12 iter-155-deferred), but iter-155 hypothesized that@playwright/experimental-ct-reactwas double-counted vs@playwright/test. Iter-156 investigation confirms the iter-155 hypothesis is INCORRECT:@playwright/test(the main test runner) and@playwright/experimental-ct-react(the component-testing extension) are separate packages with distinct dist-tags and version histories — both consumed bypackages/ui/package.jsonas devDependencies. The 27 enumeration is the correct count. Actual root cause: iter-133's expansion trail prose said "expanded by 3" while listing 4 package names (correctly: 23 + 4 = 27, not 26). The off-by-one propagated through 22 iterations (iter 133 → iter 155) without anyone noticing — every subsequent iteration kept saying "26-package matrix" because the carried-forward prose was treated as authoritative. Fix:.specify/project.mdline 94 prose re-baselined26-package→27-packagewith: explicit "expanded by 4" with all 4 package names; per-cohort enumeration (12 + 3 + 12 = 27 packages, named) so a future audit can re-verify by reading the line itself; disambiguation note clarifying@playwright/experimental-ct-reactis separate from@playwright/test; iter-156 provenance for greppability. Sub-mode classification: doc-drift-fix tick (matches iter-132/135/137/138/141/144/148 pattern). The audit-script's value-drift class (3/7) checks**N packages**(workspace packages) but does NOT checkN-package matrixprose — a coverage gap. Codify-then-execute meta-pattern says wait until a second matrix-prose drift surfaces before adding an audit class for it; tracked as deferral #9 for future iterations. Pattern progression: 9th doc-drift-fix iteration since iter-132 (132/135/137/138/141/144/148/156). No source / test / config / dep / lockfile / spec / plan changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 27th consecutive "no carried open work" steady-state iteration (iter 130-156). Iteration 155 history below.)Iteration 155 (history): close iter-154 deferral #3 — full 26-package matrix re-verification; remaining 12-package deferred-cohort all zero-delta against workspace caret floors. Verification-only iteration that closes iter-154's deferral #3 ("future iterations should include a full 26-package quick-check on the next material dep-touching iteration to surface any other accumulated patches"). Iter-154 lifted the 3 known-moved deltas in the deferred cohort (
@typescript-eslint/{parser,eslint-plugin}+jsdom) but left 12 of the 14 deferred-cohort packages unchecked since iter-133/iter-135/iter-142 baselines. Iter-155 queries the full remaining cohort againstpnpm view <pkg> versionand confirms zero deltas — every workspace caret floor still matches thelatestresolution exactly (not merely covered by the caret range). The full 26-package matrix is now bit-for-bit zero-delta after the iter-154 lifts; no package in the documented matrix has unverified time greater than iter-154's commit timestamp. 12-package remaining-cohort zero-delta verification: @astrojs/vercel 10.0.5 / @astrojs/preact 5.1.2 / @astrojs/sitemap 3.7.2 / @astrojs/check 0.9.8 / @playwright/experimental-ct-react 1.59.1 / vitest-monocart-coverage 4.0.2 / marked 18.0.2 / yaml 2.8.3 / pagefind 1.5.2 / postcss 8.5.12 / tailwind-merge 3.5.0 / @vitest/coverage-v8 4.1.5 — all 12/12 floor=latest. The iter-154 finding ("3/14 packages moved" was a non-trivial signal) does not recur for the remaining 12: the deferred-cohort policy correctly identified low-churn packages. Sub-mode classification: verification-only (per the iter-154 sub-mode taxonomy) with the bonus of explicitly closing a deferral chain. Total walltime ~3 min (~5s audit + ~30s parallelpnpm viewfor 12 packages + 3 doc edits + commit). Matrix-count off-by-one finding (iter-155, NEW): the documented 26-package matrix prose enumerates 27 entries when the verification-cohort split is rolled up —@playwright/experimental-ct-reactis referenced in two places (iter-133 expansion entry + iter-154 footnote). Not real drift; same package, same version. Re-baseline at next matrix expansion. No source / test / config / dep / lockfile / spec / plan changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 26th consecutive "no carried open work" steady-state iteration (iter 130-155). Iteration 154 history below.)Iteration 154 (history): dep audit lifts 3 patch-level deltas in the iter-153-deferred 14-package cohort —
@typescript-eslint/parser8.59.0 → 8.59.1,@typescript-eslint/eslint-plugin8.59.0 → 8.59.1,jsdom29.0.2 → 29.1.0;pnpm audit:docs8/8 PASS, full verify (typecheck 23/23 + lint 18/18 + test 16/16 = 1122/1122 Vitest) green. First substantive iteration after the iter-152 / iter-153 verification-only chain — it is the first dep-quick-check tick whose signal turned non-zero. Iter-153 deferred the 14-package "low historical churn" cohort (@astrojs/{vercel,preact,sitemap,check},@playwright/experimental-ct-react,@typescript-eslint/{parser,eslint-plugin},vitest-monocart-coverage,marked,yaml,pagefind,postcss,tailwind-merge,@vitest/coverage-v8,jsdom); iter-154 expands the quick-check to include@typescript-eslint/{parser,eslint-plugin}+jsdomand surfaces 3 real patch-level deltas accumulated since iter-133/iter-135/iter-142 baselines. All three are inside their existing caret ranges, so the iter-128 caret-range-patch precedent applies (apply inline rather than defer further). Bumps:@typescript-eslint/{parser,eslint-plugin}^8.59.0→^8.59.1(kept the version pair in lock-step — typescript-eslint monorepo cuts releases atomically; 4 pre-existingno-consolewarnings carry forward unchanged, no new warnings from the patch bump);jsdom^29.0.2→^29.1.0(minor-version bump inside the caret range — devDep of@ever-works/uifor Vitest jsdom env on the 3 non-CT-migrated Preact components). Net diff:+18/-15inpnpm-lock.yaml,+3/-3across 2 manifests. Verification full quartet green:pnpm typecheck23/23 in 2m47s (0 errors / 0 warnings / 0 hints across 21 Astro files);pnpm lint18/18 in 56s (no new warnings);pnpm test16/16 in 3m05s (1122/1122 Vitest tests; jsdom 29.0.2 → 29.1.0 didn't regress any jsdom-environment Preact tests);pnpm audit:docs8/8 PASS retained. NEW finding tracked for future iterations: react / react-dom 18.3.1 → 19.2.5 in@ever-works/docs-minimalis a major-version bump held back by Docusaurus 3.x's React 18 peer-range constraint — not actionable inside^18.3.0; tracked for visibility, no fix this iteration. [email protected] deprecation warning is a transitive sub-dep of jsdom (depth 2) — not actionable from our manifest. Pattern progression: after iter-154, the autonomous-loop steady-state pattern has 3 documented sub-modes — verification-only (152, 153; ~5 min/tick), doc-drift fix (132-148; ~10-30 min/tick), dep-delta apply (128, 154; ~15 min/tick). Future iterations fall into one of these three. Deferrals updated: regex-equivalence checking still deferred (no drift in 9 iterations); sample-app port consistency rejected (no drift); full 26-package matrix — 11 deferred-cohort packages still on iter-133/135/142/140 baselines (the iter-154 finding of 3/14 packages moved is a non-trivial signal, so future iterations should include a full 26-package quick-check on the next material dep-touching iteration). Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 25th consecutive "no carried open work" steady-state iteration (iter 130-154). Iteration 153 history below.)Iteration 153 (history): routine verification tick —
pnpm audit:docs8/8 PASS on iter-152 baseline + 12-package dep quick-check zero deltas. Second consecutive verification-only iteration after the iter-145 → iter-151 codify-then-execute meta-arc converged. Iter-152 established the canonical steady-state shape (~5s audit run + ~30s dep walltime + 3 doc edits + commit); iter-153 re-runs the same shape on the iter-152 commit2ee4b88baseline. Output is bit-for-bit identical to iter-152's — confirms the runner is stable across cold cron-tick re-runs (no machine-local cached state, no environment-variable dependence, no transient package-manager state); the reproducibility property held for two consecutive cron ticks. 12-package dep quick-check zero deltas: same 12 packages (astro/preact/tailwindcss/typescript/vitest/@playwright/test/monocart-coverage-reports/monocart-reporter/eslint/prettier/turbo/isomorphic-git), same versions, same iter-151 / iter-152 baseline. Sample-port consistency considered + rejected as a new audit class: README.md Samples table 4323-4327 matchesapps/sample-*/package.jsondev/previewscripts exactly — no real drift surfaces, so adding the audit class preemptively would violate the codify-then-execute meta-pattern. If a future iteration changes a sample's port and forgets to update README, the resulting drift triggers the audit-class addition at THAT iteration. Regex-equivalence checking (carried from iter-151/152): still deferred — no real regex-divergence drift in 8 iterations. Pattern progression: iter-153 is the second verification-only iteration after the converged steady-state — the bounded per-tick cost is now small enough that future autonomous iterations can run dozens of consecutive verification-only ticks without accumulating drift or expanding the doc surface. No source / test / config / dep / lockfile / spec / plan changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 24th consecutive "no carried open work" steady-state iteration (iter 130-153). Iteration 152 history below.)Iteration 152 (history): routine verification tick —
pnpm audit:docs8/8 PASS on iter-151 baseline + 12-package dep quick-check zero deltas. First full autonomous tick after the iter-149 codification + iter-150 CI wire-up + iter-151 self-validation chain landed; runningpnpm audit:docson the unchanged iter-151 commit63b1bf9baseline confirms the runner's PASS output is stable across cold cron-tick re-runs (i.e., the audit isn't silently dependent on machine-local cached state, environment variables, or transient package-manager state). A reproducibility signal of this kind is normally invisible in single-author work but matters for an autonomous-loop workstream where every cron tick is effectively a fresh CI run. 12-package deplatestquick-check (zero deltas vs iter-151): astro 6.1.9, preact 10.29.1, tailwindcss 4.2.4, typescript 6.0.3, vitest 4.1.5, @playwright/test 1.59.1, monocart-coverage-reports 2.12.11, monocart-reporter 2.10.1, eslint 10.2.1, prettier 3.8.3, turbo 2.9.6, isomorphic-git 1.37.6 — every line resolves to the same version captured at iter-151. The 14-package gap to the documented 26-package matrix (verified at iter-133/iter-135/iter-142) is unlikely to have moved at the ~3-hour interval since iter-151; full re-verification deferred until next material dep-touching iteration. Pattern progression: iter-152 is the first verification-only iteration after the iter-145 → iter-151 codify-then-execute meta-arc — the canonical exemplar of the converged steady-state shape (~5s audit run + ~12 parallelpnpm viewcalls + 3 doc edits + a commit). The bounded per-tick cost is now small enough that future autonomous iterations can run dozens of consecutive verification-only ticks without accumulating drift or expanding the doc surface. No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 23rd consecutive "no carried open work" steady-state iteration (iter 130-152). Iteration 151 history below.)Iteration 151 (history): add 7th audit class —
auditChecklistRunnerParity()self-validates the script againstAGENTS.md § Doc-Quality Audit Checkliston every run. Closes iter-149's "Next Steps #1" — the parity between AGENTS.md (canonical reference) andscripts/audit-docs.ts(canonical runner) was previously enforced by convention only; codifying the parity check inside the script itself means the runner self-validates against its own canonical reference text on every invocation, including the iter-150 CI gate. Implementation: newauditChecklistRunnerParity()function inscripts/audit-docs.tsreadsAGENTS.mddirectly withnode:fs, locates the## Doc-Quality Audit Checklistsection bounds, extracts every###sub-section heading inside (with code-fence skipping so the in-section canonical-mapping documentation block doesn't self-trigger), and asserts a 1:1 parity against an in-scriptEXPECTED_MAPPINGtable. Both directions of drift are caught: a heading in AGENTS.md without an EXPECTED_MAPPING entry produces+ "<heading>" — heading in AGENTS.md but no EXPECTED_MAPPING entry; an EXPECTED_MAPPING entry without an AGENTS.md heading produces- "<heading>" — EXPECTED_MAPPING entry but no AGENTS.md heading. Plus a class-count parity check:classes[]numbered runner ids (N/Mform) vs distinct numbered ids referenced by EXPECTED_MAPPING entries — catches a forgotten classes[] entry vs mapping table mismatch. AGENTS.md update (lands same commit): new### Checklist ↔ runner parity (added iter 151)sub-section under## Doc-Quality Audit Checklist, immediately above### Rerun cadence, with a code-fence listing the canonical heading-to-class mapping (mirrored inscripts/audit-docs.ts § EXPECTED_MAPPING). Existing### Runner (added iter 149)sub-section reference bumped 6 → 7 numbered classes. Spec count drift caught by audit class 3 (count parity): adding the new spec fileaudit-docs-self-parity.mdbumpedls .specify/features/*.md | wc -lfrom 32 → 33;.specify/project.md"All N .specify/ feature specs" line auto-flagged + flipped from 32 → 33 in the same commit. First run after fixes:8/8 PASS — no documentation drift detected.Output flips from7/7to8/8because total-class count is now 7 numbered + 1 cross-file (was 6 + 1). Each numbered class output id flips fromN/6→N/7. Spec at.specify/features/audit-docs-self-parity.md, plan atdocs/plans/audit-docs-self-parity.md. Documentation propagation:CLAUDE.mdCommon Commandspnpm audit:docsrow updated 6 → 7 drift classes + new "Checklist ↔ runner parity" item;README.mdCommands table similarly updated;.specify/project.mdCurrent State header bumped 150 → 151 + spec count flipped 32 → 33 + "Zero documentation drift" line annotated with the new audit class provenance. Pattern progression: iter-151 is the 7th maturation step in the doc-quality audit saga (iters 132 → 144 single-file drift fixes → iter 145 codify playbook as in-tree text → iter 149 codify as runnable script → iter 150 wire into CI as PR-blocking gate → iter 151 self-validate runner ↔ canonical reference). Each maturation step costs one iteration but compounds: iter-145 made future drift hunts grep-and-fix instead of reason-from-scratch; iter-149 made it one-command; iter-150 made drift PR-blocking; iter-151 makes the runner self-validating. After iter-151, "checklist heading without runner class" and "runner class without checklist heading" drifts cannot accumulate undetected — both surface as[7/7] FAILon the first PR or cron tick after the asymmetric edit lands. Verification:pnpm typecheck23/23 FULL TURBO +pnpm lint18/18 FULL TURBO +pnpm audit:docs8/8 PASS — all green. No source / test / config / dep / lockfile changes (the script edit is atscripts/audit-docs.tswhich is at repo root, not under any tsconfig/eslint scope; runtime executes viatsx). Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 22nd consecutive "no carried open work" steady-state iteration (iter 130-151). Iteration 150 history below.)Iteration 150 (history): wire
pnpm audit:docsinto CI — convert the iter-149 doc-quality audit script from per-cron-tick manual check to PR-blocking signal. Iter-149 codified the AGENTS.md§ Doc-Quality Audit Checklistgrep blocks into a single runnable TypeScript runner (scripts/audit-docs.ts, 635 LOC, exposed aspnpm audit:docs); iter-149's "Next Steps #2" called out the natural maturation step — wire it into CI so doc drift becomes a PR-blocking signal alongside lint / typecheck. One-step addition to the existingcijob in.github/workflows/ci.yml, positioned between the existingSecurity auditandLintsteps. NewDoc-quality auditstep runspnpm audit:docs(single command, ~5s walltime, no test runs, no network) with a 16-line comment block enumerating the 7 drift classes the script enforces. Why position it in thecijob (not a parallel dedicated job): (1) shared prerequisites —actions/checkout@v4+pnpm/action-setup@v4+actions/setup-node@v4+pnpm install --frozen-lockfileare already there, net incremental cost is just the ~5s the script takes; (2) same-failure-signal property — a doc drift now fails the samecijob as lint/typecheck/test/build; reviewers see one red job instead of two; (3) no CI matrix change — the existing 4 jobs (ci,test-ct,coverage-gate,e2e) and theirneeds:chain stay verbatim. Pattern progression: iters 132-144 (single-file drift) → iter 145 (codify playbook as text) → iter 149 (codify as runnable script) → iter 150 (codify as CI gate). Each maturation step costs one iteration but compounds: iter-145 made future drift hunts grep-and-fix instead of reason-from-scratch; iter-149 made it one-command; iter-150 makes drift PR-blocking instead of "must-remember-to-run". After iter-150, doc-quality drift cannot accumulate undetected — every PR has the audit run as a hard prerequisite. Local re-verification:pnpm audit:docs7/7 PASS in ~5s on the iter-149 commit3e9d59bbaseline (no drift since iter-149 landed). Routine dep audit deferred this iteration (iter-147/148/149 zero deltas; inheritance consistent; CI's existingSecurity auditstep handles security-relevant audits separately). No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 21st consecutive "no carried open work" steady-state iteration (iter 130-150). Iteration 149 history below.)Iteration 149 (history): codify
AGENTS.md § Doc-Quality Audit Checklistas an executable runner —scripts/audit-docs.ts+ rootpnpm audit:docsscript. Substantive iteration that breaks the 17-iteration doc-only treadmill (iters 132 → 148). After 4 consecutive iterations of the codify-then-execute meta-pattern (iter-145 codified the audit checklist as 5 grep blocks; iter-146 found a miss-target; iter-147 tightened the regex AND ran it inline; iter-148 added a 6th block for cross-file consistency), the friction of running 6 separate grep blocks by hand on every iteration had become the dominant per-iteration cost. Iter-149 closes this loop:scripts/audit-docs.ts(TypeScript viatsx) wraps each of the 6 drift classes — Status drift line-anchored, Status drift blockquote-tolerant (with the iter-149 unicode-surrogate fix for the🗄/🗄️SUPERSEDED sigil), Value drift (count parity for specs / packages / apps /43 vs 48CT cases — caught a realAll 31 → All 32drift introduced by this iteration's own new spec file), Toolchain version drift (Astro/Preact/Tailwind/TypeScript major-version cross-check vsapps/web/package.json), ISR wording drift (fully static\|no SSRwith broad allowlist for legitimate sample-app and historical-narrative surfaces), Structural-link drift — plus a 7th cross-file consistency parity check (AGENTS.md R-rules vs CLAUDE.md Critical Rules: 15 vs 17). Each class returnsPASS/FAIL <N hits>with line-anchored output for hits; the runner exits non-zero on any class flagging real drift, so it is CI-gating-ready (deferred to a future iteration per spec AC-out-of-scope). First run after fixes:7/7 PASS — no documentation drift detected.Spec at.specify/features/audit-docs-script.md, plan atdocs/plans/audit-docs-script.md. Documentation propagation:AGENTS.md § Doc-Quality Audit Checklistgains a new "Runner" subsection at the top pointing atpnpm audit:docs(script is canonical runner; checklist remains canonical reference);CLAUDE.mdCommon Commands + Safe Operations gains thepnpm audit:docsline;README.mdCommands table gains the new row;.specify/project.mdCurrent State header bumped 148 → 149 + spec count flipped 31 → 32 + "Zero documentation drift" line annotated with the new audit runner provenance. Pattern progression: the 17-iteration single-class doc-only treadmill (iters 132 → 148) breaks here. Iter-149 is the first substantive code-artefact iteration since iter-130 (Q28 ESLint 9→10 in-place upgrade) — net +5 files added (scripts/audit-docs.ts+ spec + plan +package.jsonscript line + audit-checklist Runner subsection). The codify-then-execute meta-pattern (iters 145 → 148) culminates in iter-149's executable codification: the audit reference and the audit runner now share a 1:1 codification relationship, and future drift classes are added in the same commit to both surfaces (per the new audit-checklist policy line). Verification:pnpm typecheck23/23 FULL TURBO +pnpm lint18/18 FULL TURBO +pnpm audit:docs7/7 PASS — all green. Lockfile delta zero (root gainedtsxas devDependency, buttsxwas already a workspace dep viaapps/webandapps/sample-*scripts — no new install). Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 20th consecutive "no carried open work" steady-state iteration (iter 130-149). Iteration 148 history below.)Iteration 148 (history): cross-file consistency drift — close the AGENTS.md ↔ CLAUDE.md "Critical Rules" sync gap (R9-R15 missing from CLAUDE.md); codify the new drift class in
AGENTS.md § Doc-Quality Audit Checklist. Pure-doc iteration executing iter-147's Next Step #2 (cross-file consistency check). Real cross-file drift found:CLAUDE.md"Critical Rules" listed only 10 numbered items whileAGENTS.md"Mandatory Rules" defines 15 R-rules — the 7 rules R9-R15 (Documentation First / Use Existing Libraries / Do Not Remove / Monorepo Structure / Exhaustive Documentation / Convention Over Configuration / Specification First) had no corresponding line in CLAUDE.md despite AGENTS.md R8 line 62 explicitly stating "AGENTS.mdandCLAUDE.mdalways up to date". Both files are loaded into AI-agent context every session — a rule that lives in one but not the other creates an under-documented obligation. Fix part 1: CLAUDE.md "Critical Rules" gains 7 new items (11-17) mirroring AGENTS.md R9-R15 with one-line summaries + a cross-reference paragraph mapping CLAUDE.md items 1-17 to AGENTS.md R1-R15 (R3+R4 fan out into items 2-4 + 7 in CLAUDE.md for marketing-clarity; R9-R15 map 1:1 to items 11-17). Fix part 2:AGENTS.md § Doc-Quality Audit Checklistgains a new "Cross-file consistency (added iter 148)" subsection (~24 lines) with 7-line explanation, 5 lines of grep commands (grep -cE "^### R[0-9]+:" AGENTS.mdvsgrep -cE "^[0-9]+\\.\\s+\\*\\*" CLAUDE.md— should match 15 vs 17), and an explicit policy line "When an R-rule is added, removed, or reworded, update both files in the same commit." Codified-greps re-run (Status drift / Value drift / Toolchain / ISR / Structural-link): zero outstanding non-resolved hits — iter-148's surface is the new cross-file class, not a regression of any previous class. Pattern progression confirmed for the 12th iteration in a row (iter-132 → iter-148, with iter-148's twist: cross-file consistency joins the codified drift-class catalogue). Routine dep audit deferred this iteration (iter-147 zero deltas; inheritance consistent). No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 19th consecutive "no carried open work" steady-state iteration (iter 130-148). Iteration 147 history below.)Iteration 147 (history): execute iter-146 Next Step #1 — tighten the iter-145 codified audit checklist Status-drift regex to tolerate
>blockquote prefix +**bold**markdown wrapping; routine codified-greps re-run surfaces 1 stale CT-count claim in.specify/features/q22-playwright-coverage.mdAC #10 (43/43 → 48/48); routine 10-package dep quick-check zero deltas. Pure-doc iteration. Two parallel deliverables: (1)AGENTS.md § Doc-Quality Audit ChecklistStatus/state drift block gains a new tighter regex variantgrep -rEn "^>?\\s*\\*?\\*?Status:\\s+\\*?\\*?[^✅]" docs/plans/ .specify/features/(added below the existing line-anchored regex with a 6-line explanatory comment block crediting iter-146 for the miss-targets that motivated the tightening). The new pattern matchesStatus:regardless of leading>blockquote prefix or**bold**wrapping — the exact shape iter-146's two miss-targets (q22-upstream-repro.md:12 + q22-playwright-ct.md:15) shared. (2) The full codified-greps re-run with the new tighter regex against the fulldocs/plans/q*.md+.specify/features/q*.mdsurface returns zero outstanding non-resolved status lines (the only matches are q22-upstream-repro.md's archeology block lines 21-22 — narrative references to the original DRAFT wording preserved by iter-146, not active claims). However, the value-drift block finds one real stale CT-count claim in.specify/features/q22-playwright-coverage.mdAC #10 line 151:pnpm test:ct still reports 43/43 passing (16 FilterBar + 12 LayoutSwitcher + 15 MobileMenu). The 43/43 baseline matches the iter-110 spec authoring time; subsequent CT growth (iter-120 focus-trap +2 cases → 45/45; iter-124 Q27 outlier closure +3 cases → 48/48) was reflected in the spec's## Statusblock (front matter — refreshed iter 122) but the AC #10 enumeration was missed. Same drift class as iter-132 (CLAUDE.md43 → 48), iter-140 (q28AC #5 + Step 4 conflated 1170), iter-141 (apps/docs/blog/Fully staticpredates iter-17). Fixed via the iter-140 minimal-rewrite pattern: the original 43/43 + 15-MobileMenu baseline preserved as historical context inline, while the current 48/48 + 20-MobileMenu count and the iter-120 + iter-124 growth chain are documented (so a future audit doesn't re-flag this AC, AND the spec's iter-115 / iter-121 verification provenance stays traceable). Routine 10-package dep quick-check (zero deltas) astro 6.1.9 / vitest 4.1.5 / @playwright/test 1.59.1 / tailwindcss 4.2.4 / preact 10.29.1 / typescript 6.0.3 / eslint 10.2.1 / isomorphic-git 1.37.6 / turbo 2.9.6 / prettier 3.8.3 — all pinned versions match npmlatest(verified ~1h after iter-146; matches iter-143's 10-package subset baseline). 16-package gap to documented 26-package matrix unlikely to have moved at this interval; full re-verification deferred. Pattern progression confirmed for the 11th iteration in a row (iter-132 → iter-147). With iter-147's twist: the codified audit checklist (iter-145) + tightened regex (iter-147) + first-execution dogfood (iter-147 itself) close the institutional-knowledge loop — future autonomous iterations now start fromAGENTS.md § Doc-Quality Audit Checklistand run the already-fixed patterns rather than re-deriving them from log archaeology each tick. The iter-146 / iter-147 sequence demonstrates the codify-then-tighten meta-pattern: codify a pattern (iter-145), discover the codified pattern misses real cases (iter-146), tighten the pattern (iter-147), confirm the tightened pattern catches the missed cases (this iteration's re-run). Verification:pnpm typecheck23/23 FULL TURBO (1.321s) +pnpm lint18/18 FULL TURBO (1.402s) — 100% cache hits, doc-only changes. No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 18th consecutive "no carried open work" steady-state iteration (iter 130-147). Iteration 146 history below.)Iteration 146 (history): first run of the iter-145 codified audit checklist surfaces 2 stale plan-status lines missed by iter-144 —
docs/plans/q22-upstream-repro.mdline 12 still saidStatus: **DRAFT — execute in parallel with the Playwright CT migration..."(authored iter 102 as a hedge; the migration succeeded and the upstreamvitest-dev/vitestissue was never filed), anddocs/plans/q22-playwright-ct.mdline 15 still saidStatus: **✅ PHASE 2 COMPLETE — Remaining work: Step 6"(entire Q22 → Q28 saga is now fully closed; Step 6 was satisfied implicitly across the iter-105 → iter-141 session window with green CI on every push). Both flipped:q22-upstream-repro.md→🗄️ SUPERSEDED (iteration 146) — never executed; not pursuedwith original DRAFT wording preserved in an "Original status (iteration 102, preserved for archeology)" block;q22-playwright-ct.md→✅ FULLY COMPLETE (Q22 → Q28 saga closed, iteration 124)with explicit per-follow-up enumeration (#1 ✅ iter 108, #2SUPERSEDEDiter 110, #3 ✅ iter 121). Drift class generalization: both miss-targets share a common shape —Status:lines that are inside>blockquotes and use**bold**markdown wrappers around the state token. The iter-145 codified regex^Status:.*PLANNED|SPECIFIED|DRAFTrequires line-startStatus:but the actual lines start with> Status:. Iter-145's verification claim "all 13 matches reflect ✅-prefixed states" used the iter-144-pattern (grep -n "Status:"), not the iter-145-codified^Status:.*regex — and the human-spot-check pass missed two. Recommended fix for iter-N+1: tighten the Status/state drift greps withgrep -rEn "^>?\\s*\\*?\\*?Status:\\s+\\*?\\*?[^✅]" docs/plans/ .specify/features/. Pattern progression confirmed for the 10th iteration in a row (iter-132 → iter-146). Verification:pnpm typecheck23/23 FULL TURBO +pnpm lint18/18 FULL TURBO (100% cache hits — doc-only changes don't invalidate any task input). No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 17th consecutive "no carried open work" steady-state iteration (iter 130-146). Iteration 145 history below.)Iteration 145 (history): codify iter-144 Next Step #1 — add new
## Doc-Quality Audit Checklistsection toAGENTS.mdinstitutionalizing the grep-pattern playbook from iters 132 → 144. Meta-iteration. Iter-144's Next Step #1 read "Addgrep -n "Status:" docs/plans/q*.md .specify/features/q*.mdto the standard audit checklist" — but that "standard audit checklist" was institutional knowledge captured across log entries (iters 132 / 135 / 137 / 138 / 139 / 140 / 141 / 142 / 143 / 144), not durably documented anywhere a future autonomous iteration would discover without log archaeology. Iter-145 closes this by inserting a 70-line## Doc-Quality Audit Checklistsection intoAGENTS.md(between## Cross-Check Checklistand## Skills for AI Agents) consolidating the playbook into three pattern groups: Value drift (43 cases\|48 cases,All 28\|All 31,22-package\|26-package,pnpm test\b, toolchain version regex), Status/state drift (Status:indocs/plans/q*.md+.specify/features/q*.md,Fully static\|fully static\|no SSR,^Status:.*PLANNED\|SPECIFIED\|DRAFT), Structural/link drift (\](\\.\\./for broken relative markdown links,type: docfor sidebar topology,^-for bullet placement). Plus a rerun-cadence table (Value drift → after code/test/dep changes; Status/state drift → every doc-quality iteration; Structural/link drift → after docs additions or sidebar edits) and an explicit "add new patterns here when new drift classes surface" policy line. Net diff +70/-0 across one file. Why iter-145 and not earlier: iters 141 → 144 each closed a new drift class — codifying after iter-141 would have under-specified the checklist (no link-drift, no front-matter-status, no bullet-placement patterns). Iter-145 is the right cadence: close enough to iter-144 that context is fresh, far enough that iter-144's findings have settled. Pattern progression: 9 consecutive drift-sweep iterations (132 → 144) confirmed three recurring drift classes; iter-145 is the meta-iteration that promotes accumulated knowledge from change-log entries to a canonical, in-tree reference. Future iterations doing doc-quality work should now start fromAGENTS.md § Doc-Quality Audit Checklistrather than re-reading log entries. Verification:pnpm typecheck23/23 FULL TURBO (1.496s) +pnpm lint18/18 FULL TURBO (1.384s) — 100% cache hits,AGENTS.mdis not under typecheck/lint scope. No source / test / config / dep / lockfile changes.grep -n "Status:" docs/plans/q*.md .specify/features/q*.mdre-run: all 13 matches reflect ✅-prefixed states (noPLANNED/SPECIFIED/DRAFTremaining), confirming iter-144's flips landed cleanly. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 16th consecutive "no carried open work" steady-state iteration (iter 130-145). Iteration 144 history below.)Iteration 144 (history): spec/plan front-matter status flip — close 6 stale "PLANNED"/"SPECIFIED" entries (2 specs + 4 plans) where the corresponding question was already RESOLVED. Pure-doc iteration. Iter-138 spec inventory pass + iter-141 cross-repo grep audit + iter-142 .specify/ link audit covered the headline counts and link targets of the spec/plan surface but missed the front-matter status lines of individual plan/spec files. Iter-144's targeted grep
grep -n "Status:" docs/plans/q*.md .specify/features/q*.mdsurfaced 6 stale entries:.specify/features/q22-mobilemenu-ct.md(SPECIFIED iter 108, latency 36 iters; Q22 follow-up #1 was ✅ COMPLETE iter 108),.specify/features/q24-layoutswitcher-empty-modes.md(SPECIFIED iter 109, latency 35 iters; Q24 was ✅ RESOLVED iter 109),docs/plans/q22-mobilemenu-ct.md(PLANNED iter 108, latency 36 iters),docs/plans/q22-playwright-coverage.md(PLANNED iter 110 + Q25-validated iter 112, latency 23 iters; Q22 follow-up #3 was ✅ COMPLETE iter 121),docs/plans/q24-layoutswitcher-empty-modes.md(PLANNED iter 109, latency 35 iters),docs/plans/q27-mobilemenu-empty-items-coverage.md(PLANNED iter 123, latency 20 iters; Q27 was ✅ RESOLVED iter 124). All 6 flipped to ✅ COMPLETE / ✅ RESOLVED / ✅ DONE with execution recap andStatus flip belatedly landed iter 144.annotations. Drift class: front-matter status lines sit at the top of plan/spec files, separate from the body edits (Outcome subsections / Decisions tables / acceptance-criteria checkmarks) that resolve the question. The execution iteration typically updates the body and the change-log entry but does NOT touch the front-matter line unless explicitly reminded. The two specs that WERE updated (q22-playwright-coverage iter 121 + q27 iter 124) had their spec front-matter flipped by their respective execution iterations, but the corresponding plan front-matters AND the two other spec front-matters (q22-mobilemenu-ct + q24) were missed. Pattern progression confirmed for the 9th iteration in a row (iter-132 → iter-144). New audit-checklist entry:grep -n "Status:" docs/plans/q*.md .specify/features/q*.mdshould run on every doc-quality iteration. Verified clean (no front-matter drift): q22-playwright-ct, q22-upstream-repro, q28-eslint-10-upgrade plans + q22-playwright-ct, q22-playwright-coverage, q27, q28 specs (all already current per their respective execution iterations). Routine dep audit deferred this iteration (iter-140 + iter-143 zero deltas, inheritance consistent). Verification:pnpm typecheck23/23 +pnpm lint18/18 expected at commit time. No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 15th consecutive "no carried open work" steady-state iteration (iter 130-144). Iteration 143 history below.)Iteration 143 (history): AGENTS.md R14/R15 bullet placement fix — relocate "Prefer conventions that reduce boilerplate" from R15 (Specification First) to R14 (Convention Over Configuration); 9-guide
docs/guides/audit verified clean; routine 10-package dep quick-check zero deltas. Pure-doc iteration executing iter-142's Next Step #1 (audit remaining surfaces: AGENTS.md R12-R14 + 9 unaudited guides). One real drift found in AGENTS.md: line 105 "- Prefer conventions that reduce boilerplate" appeared as the 7th bullet under R15 (Specification First) — semantically incongruous because that rule is about specs/docs/architecture/questions/PR-cross-checks, not conventions/defaults/boilerplate-reduction. The bullet semantically belongs to R14 (Convention Over Configuration), which had only 2 bullets ("Good defaults for everything" + "Users can override via config when needed"). Likely root cause: a copy-paste / refactor-time accident when R15 was inserted between R14 and what later became "Working Process" (the bullet got reattached to the wrong rule heading). Fixed by moving the bullet into R14's bullet list (as the 3rd bullet) and removing it from R15's. Net diff +1/-1, single line move. 9-guidedocs/guides/audit verified clean (no drift in the iter-132/etc. drift class): targeted greps for1170|1165|1122|43 cases|48 cases|All 28|All 31|22-package|26-package|Fully static|fully static|no SSR|output.*staticandAstro 6\\.[0-9]|Vitest 4\\.[0-9]|Tailwind 4\\.[0-9]|Preact 10\\.[0-9]|TypeScript [56]\\.[0-9]|Node 2[0-4]|@astrojs/vercel|isomorphic-gitand@ever-works/[a-z-]+andsample-(basic|jobs|events|real-estate|git)returned only matches in proper context. The "fully static" matches ingetting-started.md:1162,content-sync.md:92,deployment.md:129/142are all correctly scoped toENABLE_ISR=falsediscussions. Theisomorphic-gitmatches introubleshooting.md:229/231/238/244are about externalizing it from Vite SSR bundling — current and correct. The@ever-works/web-minimalreferences (3 files, 11 occurrences) all matchapps/web/package.json"name": "@ever-works/web-minimal". Theapps/sample-basic/src/components/ItemBrowser.tsxandapps/sample-basic/src/styles/global.cssreferences ininteractive-components.mdresolve to existing files. TheDataAdapterandAdapterConfigtypes referenced increating-an-adapter.mdexist atpackages/adapters/src/types.ts:13and:79. Routine 10-package dep quick-check (zero deltas): astro 6.1.9, vitest 4.1.5, @playwright/test 1.59.1, tailwindcss 4.2.4, preact 10.29.1, typescript 6.0.3, eslint 10.2.1, isomorphic-git 1.37.6, turbo 2.9.6, prettier 3.8.3 — all pinned versions match npmlatest(verified ~3h after iter-142's 22-package subset audit). 16-package gap to documented 26-package matrix unlikely to have moved at this interval; full re-verification deferred. Iter-142 collision note: an earlier scheduled run committed iter-142 (commit 226e4c0at 18:16:48 UTC, "complete cross-repo .specify/ link audit") in parallel with the current session's first 90 minutes of work. The earlier run independently found and fixed the same 5 broken../../.specify/features/*.mdmarkdown links in the Q-track plan files that the current session would have fixed. Current session's edits matched the parallel run's edits exactly (working tree was clean after both completed); current session pivoted to iter-143 to avoid duplicate commits. The collision is itself a useful signal: in fully-autonomous parallel-scheduled runs against a low-churn doc-only workstream, two cron ticks can independently land on the same fix. Future iterations shouldgit pull(or checkgit loghead) at session start to avoid the collision-pivot cost. Pattern progression confirmed for the 9th iteration in a row (iter-132 → iter-143). Verification:pnpm typecheck23/23 FULL TURBO (1.431s) +pnpm lint18/18 FULL TURBO (1.403s) — 100% cache hits, AGENTS.md edit doesn't invalidate any task input (AGENTS.md is not under typecheck/lint scope). No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 14th consecutive "no carried open work" steady-state iteration (iter 130-143). Iteration 142 history below.)Iteration 142 (history): complete the cross-repo
.specify/link audit — 5 Q-track plan files flipped from broken relative paths to absolute GitHub URLs. Iter-141 closed two drifts inapps/docs/; the five Q-track plan files (docs/plans/q22-mobilemenu-ct.md/q22-playwright-ct.md/q24-layoutswitcher-empty-modes.md/q27-mobilemenu-empty-items-coverage.md/q28-eslint-10-upgrade.md) retained one consistent piece of latent drift: their front-matterSpec:link still pointed at../../.specify/features/<name>.md. That relative path resolves correctly when reading the plan in the source tree (editor / GitHub renderer follows directory levels) but breaks on the published Docusaurus site because.specify/is excluded from the Docusaurus content tree (the directory lives at the repository root, not underdocs/, and Docusaurus only servesdocs/-rooted content). Iter-142 closes the loop with five 1-line edits substituting each relative path with the absolute GitHub URL convention already in use acrossdocs/index.mdSpec Kit section (since iter 102) — net diff +5/-5 across 5 files; one fix per file. Pre-iter-142 grep state:grep -rEn "\(\.\./\.\./\.specify/|\(\.\./\.specify/" docs/returned 5 hits; post-iter-142: 0 hits — the cross-repo.specify/relative-link convention is now consistent across all ofdocs/. Pattern progression confirmed for the 8th iteration in a row (iter-132 / 135 / 136 / 137 / 138 / 139 / 140 / 141 / 142). This is now the longest sustained doc-audit-only run in the saga's history — 11 consecutive iterations since iter-132 (with 133/134 inserting health-audit re-runs). In steady-state ("no carried open work") iterations, doc-quality micro-audits are the canonical productive use of an autonomous cron tick. Verification:pnpm typecheck23/23 FULL TURBO +pnpm lint18/18 FULL TURBO (100% cache hits — doc-only changes don't invalidate any task input). No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 13th consecutive "no carried open work" steady-state iteration (iter 130-142). Iteration 141 history below.)Iteration 141 (history): continue cross-repo grep audit — close 2 drifts in
apps/docs/(Docusaurus blog post pre-iter-17 wording + sidebar topology missing 1 architecture page + 7 Q-track plans). Pure-doc iteration executing iter-140's Next Step #1. Two real drifts found, two surfaces verified clean: (1)apps/docs/blog/2026-04-11-welcome.mdline 21 still said "Static-first — Astro 6 with fully static output, no SSR" — same pre-iter-17/Q17 drift class iter-135 fixed in deployment.md but missed because the blog lives underapps/docs/blog/notdocs/. Latency ~123 iterations (iter-17 → iter-141), longest single drift latency yet recorded in the audit history. Flipped to "Static-first with optional ISR — Astro 6 withoutput: 'static'+@astrojs/vercelISR adapter by default; opt out withENABLE_ISR=falsefor pure static output". (2)apps/docs/sidebarsTemplate.ts(the active Docusaurus sidebar topology, consumed bydocusaurus.config.ts:43sidebarPath: './sidebarsTemplate.ts'+ rendered at:124sidebarId: 'templateSidebar') was missing 1 architecture page (architecture/testing-runners.md— added iter-105 Q22, ~36 iterations latency) and 7 Q-track plans (q22-playwright-ct.md,q22-mobilemenu-ct.md,q22-upstream-repro.md,q22-playwright-coverage.md,q24-layoutswitcher-empty-modes.md,q27-mobilemenu-empty-items-coverage.md,q28-eslint-10-upgrade.md). Net result: the deployed Docusaurus site atapps/docs/was missing 8 navigable doc pages from its left-rail sidebar despite all 8 being canonically catalogued indocs/index.md. Both blocks expanded with the missing entries in alphabetical order. Verified clean (zero drift):docs/guides/content-sync.md(full-file read confirmed iter-140 spot-check — the only "fully static" reference is correctly scoped inside## Static ModeforENABLE_ISR=false);.github/workflows/*.yml(targeted grep returned zero matches acrossci.yml/deploy.yml/lighthouse.yml). Pattern progression confirmed for the 8th iteration in a row (iter-132 → iter-141). The Q22→Q28 saga authored its plans/specs indocs/plans/and.specify/features/and updateddocs/index.md"Plans" section accordingly — but never updated the Docusaurus sidebar topology, so the navigable doc-site experience drifted further from the canonical doc index with each Q-track plan added. Verification:pnpm typecheck23/23 +pnpm lint18/18 expected at commit time. No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 12th consecutive "no carried open work" steady-state iteration (iter 130-141). Iteration 140 history below.)Iteration 140 (history): extend iter-139 conflated-
pnpm testaudit to spec/plan surfaces — fix 2 occurrences in.specify/features/q28-eslint-10-upgrade.mdAC #5 +docs/plans/q28-eslint-10-upgrade.mdStep 4; routine dep audit zero deltas across 22 packages. Pure-doc iteration executing iter-139's Next Step #1 (extend audit to remaining surfaces). Two real drift instances found, both inherited from the same iter-129 Q28-spec authoring pass which predates the iter-132 CLAUDE.md split / iter-139 README.md split: (1).specify/features/q28-eslint-10-upgrade.mdAC #5 line 83 claimedpnpm test reports the full 1170-test suite passing; (2)docs/plans/q28-eslint-10-upgrade.mdStep 4 line 135 inline comment saidpnpm test # full 1170-test suite green expected (1122 Vitest + 48 CT). Both fixes follow the iter-139 minimal-split pattern: Vitest count stays canonical (1122), CT count moves to its own clarifying clause namingpnpm test:ctas the separate runner, and AC #6 cross-reference (ESLint is static-analysis only, CT skip intentional) is inlined so a reader doesn't have to chase the rationale across files. Verified clean (zero drift) across 9 unaudited guides, AGENTS.md, apps/docs/src/ Docusaurus content, docs/architecture/, docs/specs/, docs/overview.md. False positive resolved:docs/guides/content-sync.mdline 92 ("the site is fully static — no server functions run at runtime") looks like the iter-135 deployment.md drift but is actually correct in context — the line is inside the## Static Modesection describingENABLE_ISR=false, where indeed no Vercel server functions are deployed. Routine dep audit (zero deltas, 22-package subset re-verified): every dep at the samelatestversion as iter-138 / iter-139 baseline (Astro 6.1.9, Vitest 4.1.5, Playwright 1.59.1, Tailwind 4.2.4, Preact 10.29.1, monocart-coverage-reports 2.12.11, monocart-reporter 2.10.1, vitest-monocart-coverage 4.0.2, isomorphic-git 1.37.6, eslint 10.2.1, TypeScript 6.0.3, Prettier 3.8.3, Turbo 2.9.6, marked 18.0.2, yaml 2.8.3, pagefind 1.5.2, @playwright/experimental-ct-react 1.59.1, plus 5 @astrojs/* and @typescript-eslint). Pattern progression confirmed for the 7th iteration in a row (iter-132 CLAUDE.md / iter-135 deployment.md / iter-136 quickstart+getting-started / iter-137 package matrix / iter-138 spec count / iter-139 README.md / iter-140 q28 plan+spec): a single drift class (the conflated-pnpm test=1170row) propagated to 5 different surfaces between iter 105 (CT split introduced) and iter 129 (Q28 plan/spec authored), and required 3 separate audit iterations to fully purge. Generalization for future iterations: when fixing a stale claim in surface X, immediately rungrep -rn "<the-stale-string>" --include="*.md" .across the whole repo before considering the fix complete; otherwise the drift class survives in surfaces that don't get audited until iteration N+M. Verification:pnpm typecheck23/23 FULL TURBO (1.359s) +pnpm lint18/18 FULL TURBO (1.448s) — 100% cache hits, doc-only changes don't invalidate any task input. No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 11th consecutive "no carried open work" steady-state iteration (iter 130-140). Iteration 139 history below.)Iteration 139 (history): README.md Common Commands refresh — split conflated
pnpm testrow, add missingpnpm test:ct/pnpm test:ct:install/pnpm coveragerows. Pure-doc iteration extending the iter-132/135/136/137/138 audit pattern to README.md — the first reader-facing surface anyone reaching the repo sees. Pre-iter-139 state had two distinct issues: (1)pnpm testrow claimedRun all unit tests — 1170+ tests, 76 test files, 16 suites (1122 Vitest + 48 Playwright CT), but post-iter-132 reality is thatpnpm testruns Vitest only (1122/73/16); turbo'stesttask does NOT chain totest:ct, so a reader copying the README's claim would incorrectly believepnpm testexercises the full 1170-test surface and miss the Q22/Q23/Q24/Q27 CT-migrated coverage; (2) missing rows forpnpm test:ct(added iter 105),pnpm test:ct:install(added iter 105),pnpm coverage(added iter 116) — same omissions iter-136 caught in the twodocs/guides/Common Commands tables. Both fixed:pnpm testrow split to1122 tests, 73 test files, 16 suites; 3 new rows added with the CT surface named (16 FilterBar + 12 LayoutSwitcher + 20 MobileMenu) and the iter-124 100%/100%/99.76% gate-green numbers inlined onpnpm coverage. 1-line cross-reference to CLAUDE.md for the canonical exhaustive list (with defensivepnpm test:ui:safeintentionally omitted from the README — diagnostic-only escape hatch). Pattern progression confirmed for the sixth iteration in a row (iter-132 CLAUDE.md / iter-135 deployment.md / iter-136 quickstart+getting-started / iter-137 package matrix / iter-138 spec count / iter-139 README.md): command/env-var/feature additions to the toolchain do not auto-propagate to all reader-facing surfaces; doc-quality audits remain the canonical recurring background task in steady-state iterations. Verification:pnpm typecheck23/23 FULL TURBO +pnpm lint18/18 FULL TURBO (100% cache hits — README change does not invalidate any task input). No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 10th consecutive "no carried open work" steady-state iteration (iter 130-139). Iteration 138 history below.)Iteration 138 (history): spec inventory pass — flip stale
All 28 .specify/ feature specsclaim in.specify/project.mdtoAll 31with explicitwc -lprovenance and Q23/Q25/Q26-absorbed-inline footnote. Pure-doc iteration. Iter-137 noted.specify/features/directory contains 31.mdfiles but.specify/project.mdline 87 claimed "All 28" — and deferred the per-file accounting because the 3-spec gap could be drift or intentional exclusion. Iter 138 executes the bounded spec-inventory iteration: there is no excluded-debug-spec / superseded-spec category. The drift is a clean off-by-3 baseline-vs-final accounting error — the iter-129 project.md edit explicitly listed the 3 saga-additions by name (q22-mobilemenu-ct.mditer 108,q27-mobilemenu-empty-items-coverage.mditer 123,q28-eslint-10-upgrade.mditer 129) but never summed them into the headline count. The actual count has been 31 since iter 129. Q23 / Q25 / Q26 do not have dedicated spec files in.specify/features/— those questions were resolved inline indocs/questions.md(Q23 + Q25 absorbed into Q22 follow-up arcs; Q26 absorbed into the Q22-follow-up-#3 spec atq22-playwright-coverage.md). This is a deliberate per-saga-arc spec consolidation: the Q22 family's three follow-ups each have their own spec, but the side-quest questions (Q23/Q25/Q26) get folded into the parent's spec rather than fragmenting the spec surface. Pattern now confirmed FIVE times (iter-132 CLAUDE.md CT count → iter-135 deployment.md ISR docs → iter-136 quickstart + getting-started Common Commands → iter-137 project.md package matrix → iter-138 project.md spec count). Future iterations should pre-emptively run the standard greps before assuming "no drift":grep -rn "<old-number>" CLAUDE.md AGENTS.md README.md docs/architecture/ docs/specs/ docs/guides/ .specify/for count drift;grep -nE "pnpm test|pnpm coverage|pnpm test:ct|pnpm dev:" docs/guides/for Common Commands drift;ls .specify/features/*.md | wc -lvsgrep "All [0-9]+ .specify" .specify/project.mdfor spec-count drift. No source / test / config / dep / lockfile changes. Nopnpm install. Nopnpm coveragere-run (iter-133 100%-aggregate numbers stay authoritative).pnpm lintbaseline 18/18 + 0 warnings + 0 errors (iter 131) carries forward unchanged. Project enters its 9th consecutive "no carried open work" steady-state iteration. Iteration 137 history below.)Iteration 137 (history): continued doc-quality audit — flip stale
22-package matrixclaim in.specify/project.mdto26-package matrix(post iter-132/133 expansion). Iteration 136 completed thedocs/guides/Common Commands audit and recommended extending the audit to remaining surfaces, including "Any references to specific iteration numbers / counts (e.g. '16 packages') that may have drifted post-saga." Iteration 137 executes that follow-up. One real drift found:.specify/project.mdline 94 still describes the dep-audit surface as"The 22-package matrix"— the iter-130 baseline number that iter-132 expanded to 23 (added the[email protected]caret-resolution row) and iter-133 expanded to 26 (added[email protected],[email protected],[email protected],@playwright/[email protected]for completeness). The standingpnpm coverage"100% branches (233/233)" claim is unchanged; the matrix-count claim is what drifted. The iter-132/133/135 dep audits all updateddocs/log.mdanddocs/index.md(the iteration descriptors) but none of those iterations updated the Current State block in.specify/project.md— exactly the pattern called out in iter-136's "Generalization": command/env-var/feature additions to the toolchain do not auto-propagate to all reader-facing surfaces; targeted greps catch latency at iteration N+1, not at iteration N. The audit confirms this pattern a fourth time (iter-132 CLAUDE.md CT count → iter-135 deployment.md ISR docs → iter-136 quickstart + getting-started Common Commands → iter-137 project.md package matrix). The iter-137 fix flips line 94's text from"matrix re-verified iter 123 / 125 / 126 / 127 / 128 / 130. The 22-package matrix is now zero-delta with no carried open work for the first time across the entire iteration history"to"matrix re-verified iter 123 / 125 / 126 / 127 / 128 / 130 / 132 / 133 / 135 (matrix expanded iter 132: 22 → 23 ... iter 133: 23 → 26 ... iter 135: 9-package quick-check subset). The 26-package matrix is now zero-delta with no carried open work", removing the now-anachronistic "for the first time" superlative (true at iter-130; the steady state is now the carried-baseline at iter-137). Verified zero drift in:apps/docs/src/{components,pages}(Docusaurus React UI, no hardcoded counts; readsdocs/content viapath: '../../docs/');docs/guides/{analytics,content-sync,creating-an-adapter,customizing,interactive-components}.md(narrative-only guides, no Common Commands tables);docs/guides/{building-from-template,creating-a-plugin,performance-testing,troubleshooting}.md(only narrativepnpmmentions in proper context, not Common Commands tables);CLAUDE.md/AGENTS.md/README.md/SKILLS.md(carry forward from iter-136 baseline). Verification:pnpm typecheck23/23 FULL TURBO +pnpm lint18/18 FULL TURBO expected (both 100% cache hits — doc-only changes don't invalidate any task input). No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project enters its 8th consecutive "no carried open work" steady-state iteration. Iteration 136 history below.)Iteration 136 (history): continued
docs/guides/audit — refresh stale Common Commands tables inquickstart.mdandgetting-started.md. Iteration 135 surfaced the iter-17/Q17 ISR-doc gap indocs/guides/deployment.mdand recommended extending the iter-132 grep set todocs/guides/. This iteration follows that recommendation: a targeted grep forpnpm test|pnpm coverage|pnpm test:ct|pnpm dev:across all 12 guides surfaced two more stale Common Commands tables. Both predate the post-Q22 toolchain additions:quickstart.md(~Apr 12, before iter 17) was missing 6 commands (pnpm test,pnpm test:coverage,pnpm test:ct,pnpm coverage,pnpm format,pnpm dev:docs);getting-started.md"Common Commands Reference" (~Apr 12) was missing 5 (hadpnpm test/pnpm test:e2ebut missed the rest). Both tables now refreshed with cross-references pointing atCLAUDE.mdfor the canonical and exhaustive list (which includes the defensivepnpm test:ui:safeper-file Vitest fallback intentionally omitted from the guides — it's a diagnostic-only escape hatch). Pattern confirmed three times (iter-132 CLAUDE.md, iter-135 deployment.md, iter-136 quickstart + getting-started): command/env-var/feature additions to the toolchain do not auto-propagate to all reader-facing surfaces; targeted greps catch latency at iteration N+1, not at iteration N. Doc-quality audits should be a recurring background task. Verification:pnpm typecheck23/23 FULL TURBO +pnpm lint18/18 FULL TURBO (both 100% cache hits — doc-only changes don't invalidate any task input). No source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors; CT-flake watch ✅ CLOSED. Project entered its 7th consecutive "no carried open work" steady-state iteration. Iteration 135 history below.)Iteration 135 (history): doc-quality audit on
docs/guides/— close the ISR documentation gap indeployment.md(predates iter-17/Q17). Pure-doc iteration. Iteration 134 completed the third "post-saga health-check" verification (build pipeline); iter-135 broadens the maintenance scope from spec/plan/log surfaces to user-facingdocs/guides/. One real documentation gap found:docs/guides/deployment.mdpredates iteration 17's Q17 ("ISR by Default, Static Opt-Out") update and never picked up the ISR-specific environment variables, the ISR/pure-static mode choice, or the ISR webhook flow. Pre-iter-135 wording said "the template produces fully static output, no server functions" (correct only in pure-static mode; ISR mode ships a/api/webhookVercel function) and "to update content, trigger a new build" (correct only in pure-static mode; ISR regenerates affected pages on-demand). 5 spot edits flip the misleading wording, addENABLE_ISRto the env-var table with cross-ref tocontent-sync.mdfor the full 8 ISR/sync env vars (WEBHOOK_SECRET,SYNC_POLL_INTERVAL_MS,SYNC_TIMEOUT_MS,SYNC_MAX_RETRIES,CONTENT_CACHE_TTL_MS,VERCEL_DEPLOY_HOOK_URL,CONTENT_PATH), add an "Output mode (ISR vs pure-static)" 2-row decision table to "Build Details", and prependENABLE_ISR=falseto the Netlify + Cloudflare Pages build commands (since those static hosts cannot serve the ISR adapter's Vercel function). The gap had been latent since iter-17 (~117 iterations / ~5 weeks ago in this saga's compressed timeline) — every subsequent doc-touching iteration preserved the pre-iter-17 wording verbatim. Generalization of the iter-132 "iter-125 sweep missed CLAUDE.md" pattern: doc surfaces that are not mentioned in a feature's primary spec/plan often miss the corresponding update. The recommendation extends the iter-132 grep set to includedocs/guides/(~3,668 lines across 12 files). Routine dep audit (zero deltas, 9-package quick-check): every dep at the samelatestversion as iter 134 baseline (~1.5h prior). No source / test / config /package.json/ lockfile changes. Nopnpm install. Nopnpm coveragere-run (iter-133 100%-aggregate numbers stay authoritative).pnpm lintbaseline 18/18 + 0 warnings + 0 errors (iter 131) carries forward unchanged. Project enters its 6th consecutive "no carried open work" steady-state iteration. Iteration 134 history below.)Iteration 134 (history): deferred build-pipeline health audit — full cold
pnpm buildsucceeds across all 7 buildable turbo tasks in 13m 14s. Iteration 133 reproduced the iter-124 100%-branches authoritativepnpm coveragenumber under the post-Q28 toolchain; iter-134 extends the same end-to-end signal to the build pipeline. Coldpnpm build(all turbo caches invalidated by the dep churn since iter 92's last full-build verification) completes successfully across all 7 turbo build tasks (web + sample-basic + sample-jobs + sample-events + sample-real-estate + sample-git + docs):Tasks: 7 successful, 7 total / Cached: 0 cached, 7 total / Time: 13m14.66s. The heaviest single app remainssample-git(3264-item time-tracking-tools directory): 5030 pages built in 745.01s (~12m 25s), with every plugin firing correctly —[plugin:sort]3264 items,[plugin:breadcrumbs]4753 pages,[plugin:related-items]13056 links across 3264 items,[plugin:search]Pagefind indexing complete,[@astrojs/sitemap]sitemap-index.xml created,[@astrojs/vercel]static-output copy succeeded. Why this matters: until iter-134 the most recent end-to-end build verification in the change log was iteration 92 (Astro / Vite / Preact / Tailwind major-version churn); six iterations of dep churn since then (iter 97 / 99 / 108 / 128 / 130 / 131) had accumulated without an explicit build re-check. The iter-130 ESLint 10 upgrade and iter-128[email protected]patch are now confirmed build-invariant — exactly the prediction made by their respective specs (ESLint is static-analysis only; isomorphic-git is content-sync-time, not build-time, on the static-output adapter path used by all 7 buildable apps). Verification-only iteration; no source / test / config / dep / lockfile changes. Q22 → Q28 saga remains fully closed;@ever-works/uiat branches 100% (233/233);pnpm lint0 warnings 0 errors (iter 131); CT-flake watch ✅ CLOSED at iter 127. Project enters its 5th consecutive "no carried open work" steady-state iteration. Iteration 133 history below.)Iteration 133 (history): deferred health audit re-run —
pnpm coverageend-to-end clean; 100% branches reproducible (233/233); 26-package dep matrix zero deltas. Iter 132's "Next Steps" listed three follow-ups; #1 (routine dep audit) and #3 (doc drift sweep) were already executed by iter 132 itself, leaving #2 (pnpm coveragehealth audit re-run after iter-128 + iter-130 dep churn) as the only carried action item. Iter 133 executes that. The iter-124 100%-branches authoritative number reproduces exactly under the post-Q28 (ESLint 10) + post-iter-128 ([email protected]) toolchain: branches 100% (233/233) ✅ identical, functions 100% (104/104) ✅ identical, lines 99.76% (1240/1243) ✅ identical, statements 99.72% (352/353) ✅ identical, files 19 ✅ identical. Per-file gate: FilterBar.tsx 100% (27/27) ✅, LayoutSwitcher.tsx 100% (22/22) ✅, MobileMenu.tsx 100% (35/35) ✅ — all bit-for-bit reproduced; the iter-121process.exit(1)hard-gate would have fired if any file dropped below 80%; it did not. The only delta is a non-material bytes-denominator drift: 99.79% (45,558/45,650) → 99.76% (45,667/45,775) — +125 total bytes / +16 uncovered bytes / -0.03 pp. Likely cause: iter-128isomorphic-gitpatch + iter-130 ESLint 10 transitive deps re-emitted the Vite/Preact bundle with marginally different chunk boundaries (V8 byte ranges count emitted-bundle bytes, not source bytes — bundle re-chunking shifts the denominator; source-mapped logical metrics are invariant). Well clear of any gate threshold. CT-flake watch counter advanced 3/3 → 4/4 with iter 133's clean 48/48 / 0 retries / 0 flaky / 1m 21s run — the iter-111 single-occurrencefilter-bar.ct › selects category on clickflake has now not recurred across four consecutive full-suite runs (iters 126, 127, 133, plus iter 124's mobile-menu-only partial). Vitest re-verified:@ever-works/ui174/174 / 11 files / 93.46s; fullpnpm test16/16 packages / 1122/1122 in 2m 20s. Routine dep audit: 26-package matrix re-verified (~1.5h after iter 132; expanded by 3 to add[email protected],[email protected],[email protected],@playwright/[email protected]for completeness) — every dep atlatest. Verification:pnpm typecheck23/23 FULL TURBO (1.7s, all cache hits),pnpm lint18/18 FULL TURBO (1.2s, all cache hits, 0 warnings + 0 errors),pnpm coverageend-to-end ~3 min walltime. No source / test / config /package.json/ lockfile changes (iter 132's commit9588469remains the head of code state). Process note added to "Next Steps": iter 133's bytes-denominator drift establishes the precedent — logical metrics (branches/statements/functions/lines) are stable across patch+minor dep churn, but future material dep churn (any non-patch bump in Astro / Vite / Vitest / Playwright / Preact / Tailwind / monocart / vitest-monocart-coverage / isomorphic-git / TypeScript / ESLint) should re-runpnpm coverageto verify the 100%-branches signal still reproduces. Iteration 132 history below.)Iteration 132 (history): doc drift sweep — flip stale CT count in CLAUDE.md (
43 cases→48 cases); routine dep audit zero deltas across 23-package matrix. Pure-doc iteration. Iter-131's "Next Steps" listed "Doc drift sweep — verify the iter-130 ESLint matrix line in.specify/project.mdreflects the post-bump state; checkCLAUDE.mdCommon Commands for any stalepnpmreferences" as a recommended next-step. Iter 132 executes that sweep. One stale claim found:CLAUDE.mdline 122 still describedpnpm test:ctas(43 cases for FilterBar/LayoutSwitcher/MobileMenu, ~1.3 min on Windows + Node 24)— the same iter-105/iter-108-baseline43 casescount that iter-125's health-check pass missed in this surface (iter 125 swept.specify/project.md/.specify/features/{q22-playwright-coverage,testing}.md/docs/architecture/testing-runners.md/README.mdand brought them current to48cases /1170total, but did not touchCLAUDE.md). Iter 132 flips to(48 cases for FilterBar/LayoutSwitcher/MobileMenu — 16 + 12 + 20; iter-127 walltime ~1.5 min on Windows + Node 24 + Chromium 147; 0 retries / 0 flaky)— count reflects iter-124 Q27's MobileMenu CT growth from 17 → 20, walltime reflects iter-127's measured second-run-clean baseline (1m 39s), Chromium version + flake signal added so a future reader knows this number reflects post-CT-flake-watch-closed state. Routine dep audit (zero deltas, 23-package matrix re-verified ~3.5h after iter 131): every dep at the samelatestversion including[email protected](caret-resolved from^10.0.0). The "no carried open work" steady state from iter 130 holds. No source / test / config /package.json/ lockfile changes. Nopnpm install. Nopnpm coveragere-run (iter-124 100%-aggregate merged numbers stay authoritative).pnpm lintbaseline 18/18 + 0 warnings + 0 errors (iter 131) carries forward unchanged. Iteration 131 history below.)Iteration 131 (history): closed 4 lingering
no-consolelint warnings in logger.ts files via inline ESLint disable comments —pnpm lintnow reports 0 warnings + 0 errors for the first time. Iteration 130 (Q28 ESLint 10 upgrade) noted the 4 pre-existing warnings inpackages/core/src/logger.ts:40,53+packages/plugins/src/logger.ts:22,35carry forward unchanged from iter-128 baseline. With the project at "no carried open work" steady state, this iteration closes them. The warnings flagconsole.log(...)calls insideinfo()/debug()methods of two logger factory functions — the entire purpose of those methods is to emit log lines, soconsole.logis correct API and the right fix is inlineeslint-disable-next-line no-consolecomments with explicit-- info-level/debug-level logger output is the entire purpose of this methodjustifications (not rewriting toconsole.warn, which would mis-tag info/debug as warnings in the JS console). 4 added comment lines / 0 deleted; no logic / API / signature change. Verification:pnpm lint18/18 / 0 warnings / 0 errors (down from 18/18 + 4 warnings at iter-130 baseline) in 43.2s,pnpm typecheck23/23 in 1m54s,pnpm --filter @ever-works/core test213/213 in 11.55s,pnpm --filter @ever-works/plugins test86/86 in 5.10s. Significance: chronic warnings desensitize readers to new violations; closing the lingering 4 means the nextno-consoleviolation stands out cleanly against a 0-warning baseline. Q22 → Q28 saga remains fully closed; per-package merged coverage on@ever-works/uicontinues to read branches 100% (233/233) (iter-124 numbers stay authoritative; this iteration did not touch any source underpackages/ui/). Iteration 130 history below.)Iteration 130 (history): Q28 ✅ RESOLVED — ESLint 9 → 10 in-place upgrade executed in a single autonomous cron tick. Iter-129's pre-investigation predicted a bounded 30-45 min single-iteration upgrade; iter-130 lands it in ~13 min walltime end-to-end. Step 1 (peer-range bump): one-line edit to
packages/eslint-config/package.jsonpeerDependencies.eslint^9.0.0→^10.0.0. Step 2 (pnpm install, ~92s):[email protected] → 10.2.1resolved + 8 transitive bumps (@eslint/core 0.17.0 → 1.2.1,@eslint/config-array 0.21.2 → 0.23.5,@eslint/config-helpers 0.4.2 → 0.5.5,@eslint/object-schema 2.1.7 → 3.0.5,@eslint/plugin-kit 0.4.1 → 0.7.1,eslint-scope 8.4.0 → 9.1.2,espree 10.4.0 → 11.2.0,eslint-visitor-keys 4.2.1 → 5.0.1) + 3 legacy drops (@eslint/[email protected]— flat-config-only in v10; top-level@eslint/[email protected]and[email protected]— consolidated). Net lockfile churn: +14 / -19 packages, -38 lines. Step 3 (pnpm lintsmoke, ~51s, 1 cached + 17 fresh): 18/18 successful, 0 errors, only the 4 pre-existingno-consolewarnings inpackages/core/src/logger.ts:40,53+packages/plugins/src/logger.ts:22,35carry forward unchanged from iter-128 baseline — zero new ESLint 10 violations. Step 4 (verify):pnpm typecheck23/23 in 2m12.8s (full fresh) +pnpm test16/16 packages / 1122/1122 Vitest tests in 2m52.5s (full fresh). Optionalengines.node >=22.12.0 → >=22.13.0bump skipped per AC #6 (current floor covers ESLint 10's>=22.13.0via semver caret resolution; CI runs Node 24 unconditionally). Optionalpnpm test:ct(48 cases) andpnpm coverage(merged 100% aggregate) intentionally skipped — ESLint is purely static-analysis, cannot affect runtime; Vitest already exercises the workspace dep graph transitively. All 10 acceptance criteria from the spec satisfied. Step 6 (deferral-marker grep):grep -nE "ESLint.*9.*10|^9\.0\.0|eslint.*deferral" docs/log.mdfinds matches only in archived iteration entries (123/125/126/127/128/129) — iter-130 "Next Steps" carries no deferral marker. Saga state: every named question (Q22, Q23, Q24, Q25, Q26, Q27, Q28) reports ✅ RESOLVED; every dep matrix line matcheslatest; the mergedpnpm coveragepipeline reports per-package branches 100% (233/233) with the iter-121 hard-fail gate enforced in CI. Project enters "no carried open work" steady state for the first time across the entire iteration history. 6 doc surfaces touched:docs/questions.md(Q28 status flip),.specify/features/q28-eslint-10-upgrade.md(front-matter flip),docs/plans/q28-eslint-10-upgrade.md(Status flip + ~250-line Outcome subsection),docs/log.md(this entry),docs/index.md(descriptor bump),.specify/project.md(Current State + ESLint matrix line + Q28 status). Iteration 129 history below.)Iteration 129 (history): Q28 OPENED + spec + plan authored — ESLint 9 → 10 major-version upgrade pre-investigated; Q27 status flip in
docs/questions.md(carry from iter-125 health-check sweep miss). Pure-documentation iteration. Three new doc surfaces created: (1).specify/features/q28-eslint-10-upgrade.md(~210 lines) — full feature spec with 10 ACs, 5 risks, AGENTS.md R1-R15 cross-check, and a 17-row ESLint-10-changelog cross-check table that resolves every named breaking change to "no impact" against our actual source/config surface (flat config since project inception; Node v24 already in CI;@typescript-eslint@^8.59.0peer-range covers ESLint 10; zero source usages ofeslint-env/globalThisshadowing / removed deprecated APIs; rule list intentionally minimal — 6 rules + ignores — none affected by ESLint 10's schema strictening); (2)docs/plans/q28-eslint-10-upgrade.md(~190 lines) — 7-step execution plan: Step 0 re-verify pre-investigation / Step 1 bump peer-range (1-line edit) / Step 2pnpm install/ Step 3pnpm lintsmoke / Step 4 typecheck + test / Step 5 doc updates / Step 6 confirm deferral marker disappears / Step 7 rollback (only if 2-4 fail); sequencing puts total at 30-45 min single-iteration; (3)docs/questions.mdQ28 entry (~110 lines) with default Option A (single-iteration in-place bump) + 5-iteration deferral history + 9-row pre-investigation findings list + Options A/B/C/D analysis (B/C/D rejected with reasons). Q27 status footer fix indocs/questions.md(~20 lines): the iter 125 health-check pass swept five other surfaces but missed the Q27 footer indocs/questions.md; iter 129 closes the gap by flippingOPEN — Option A.1 chosen [DEFAULT]→✅ RESOLVED in iteration 124 — Option A.1 + Option A.3 combinedwith the final per-file MobileMenu (100% (35/35)) + per-package aggregate (100% (233/233)) numbers + a parenthetical note crediting iter 129 for the belated landing. Iteration 128 history below.)Iteration 128 (history): picked up the iter-127 caret-range delta —
[email protected] → 1.37.6lockfile +packages/adapters/package.jsonpin bump. Iter-127 noted "the nextpnpm installwill pick it up automatically" — empirically wrong: pnpm's lockfile is sticky once resolved, sopnpm installreported "Lockfile is up to date" and left the lockfile at 1.37.5. Caret-range patch bumps requirepnpm update <pkg>explicitly. This iteration runspnpm update isomorphic-git --filter @ever-works/adaptersto land the bump, then verifies viapackages/adapterstests (4 files / 104/104 tests pass in 8.0s) — confirms[email protected]does not change any tracked behavior (file-tree walking, head-ref resolution, refresh path).pnpm typecheck23/23 (1 cached + 22 fresh in 2m9s; lockfile change invalidated turbo cache) andpnpm lint18/18 (1 cached + 17 fresh in 45.8s). The iteration-128 entry indocs/log.mdincludes a playbook correction for future routine audits: caret-range bumps requirepnpm update <pkg>directly (notpnpm install); deferral notes should be honest about that distinction. Q22 → Q27 saga remains fully closed; per-package merged coverage on@ever-works/uicontinues to read branches 100% (233/233) (iter-124 numbers stay authoritative; this iteration did not touch any source underpackages/ui/); CT-flake watch ✅ CLOSED at iter 127 (3/3 clean). Iteration 127 history below.)Iteration 127 (history): CT-flake watch ✅ CLOSED — counter 2/3 → 3/3 after a second consecutive clean full 48-case CT run; routine dep audit one delta inside caret range (
[email protected] → 1.37.6). Pure-verification iteration.pnpm test:ctran the full Playwright Component-Testing surface (16 FilterBar + 12 LayoutSwitcher + 20 MobileMenu) on Windows 10 + Node 24.14.0 + Chromium 147 + Playwright 1.59.1: 48 passed (1m 39s) / 0 failed / 0 flaky / 0 retries / 772 steps. CT-only V8 (identical to iter 126): bytes 100% (20,432/20,432), statements 100% (115/115), branches 98.81% (83/84 — the 1 uncovered branch remains the iter-124/* v8 ignore next */-pragma'd defensivemenuRefrace-guard, dropped from the V8 denominator on the merged-Vitest+CT report where the aggregate reads 100%; expected and consistent with iter 124), functions 100% (40/40), lines 100% (495/495). The iter-111 single-occurrencefilter-bar.ct › selects category on clickretry has not recurred across two consecutive full-suite runs (iter 126 + iter 127) — the Playwright Component-Testing surface is now considered stable on the documented toolchain. Walltime 1m 25s → 1m 39s (+14s, ~16%) is well within Playwright cold-start variance on the same hardware/toolchain — no signal of regression (iter 127 ran cold; iter 126 ran ~3.5h earlier in the same session). Watch closes at iter 127 per the iter-125 plan: counter 2/3 → 3/3 ✅ CLOSED. Routine maintenance audit (one delta inside caret range): 22-package version matrix re-checked (~3.5h after iter 126) — single delta[email protected] → 1.37.6(patch bump, caret-resolved at^1.37.5— nopnpm installneeded; the nextpnpm installwill pick it up automatically). All other 21 packages identical to iter 126 (Astro 6.1.9, Vitest 4.1.5, Playwright 1.59.1, Tailwind 4.2.4, Preact 10.29.1, monocart-coverage-reports 2.12.11, monocart-reporter 2.10.1, vitest-monocart-coverage 4.0.2, @astrojs/{vercel 10.0.5, preact 5.1.2, sitemap 3.7.2, check 0.9.8}, @playwright/{test, experimental-ct-react} 1.59.1, TypeScript 6.0.3, Prettier 3.8.3, Turbo 2.9.6, marked 18.0.2, yaml 2.8.3, pagefind 1.5.2). ESLint 9 → 10 major-version gap remains the single out-of-scope drift item (manual changelog review required; not autonomous).pnpm typecheck23/23 +pnpm lint18/18 (FULL TURBO cache hits — no source/test/config drift since iter 126's commit57b2b50). No source / test / config /package.json/ lockfile changes. Nopnpm install. Nopnpm coveragere-run (CT-only is sufficient for flake-watch close; iter-124 100%-aggregate merged numbers stay authoritative until the next code-touching iteration). Iteration 126 history below.)Iteration 126 (history): CT-flake watch advance — counter 1/3 → 2/3 after a clean full 48-case CT run; routine dep audit re-verified (zero deltas). Pure-verification iteration.
pnpm test:ctran the full Playwright Component-Testing surface on Windows 10 + Node 24.14.0 + Chromium 147 + Playwright 1.59.1: 48 passed (1m 25s) / 0 failed / 0 flaky / 0 retries. CT-only V8: bytes 100% (20,432/20,432), statements 100% (115/115), branches 98.81% (83/84), functions 100% (40/40), lines 100% (495/495). First complete-suite absence-of-recurrence signal since iter 111 (iter 124 ranmobile-menu.ct.test.tsx-only — partial-suite signal). Per the iter-125 "Next Steps" plan, the watch closes at iter 127 with one more clean full-CT run; iter 126 advances counter 1/3 → 2/3. Routine maintenance audit re-verified zero deltas across the 21-package matrix. ESLint 9 → 10 major-version gap remains the single out-of-scope drift item.pnpm typecheck23/23 +pnpm lint18/18 (FULL TURBO). No source / test / config /package.json/ lockfile changes. Iteration 125 history below.)Iteration 125 (history): doc health-check pass — flipped 5 stale-claim surfaces after iter 124's Q27 closure (CT counts + per-file coverage + aggregate). Pure-doc iteration. Surfaces brought current: (1)
.specify/project.md— Current State header bumped 124 → 125; CT count line refreshed (43 → 48 total CT, 15 → 20 MobileMenu CT, 1165 → 1170 grand total) with iter 120/124 case-count growth annotated; spec-status block tightened to reflect Q27 ✅ RESOLVED in iter 124 (was iter-123 wording with statusOPEN — Option A.1 chosen [DEFAULT]); spec count bumped 26 → 27. (2).specify/features/q22-playwright-coverage.md— front-matter status block aggregate (98.72% → 100% (233/233)), per-file MobileMenu (91.89% → 100% (35/35)), lines (99.60% → 99.76%), statements (99.15% → 99.72%) all updated to post-Q27 state; "Q25 + Q26 ✅" extended to "Q25, Q26, and Q27 ✅"; archeology footer added preserving the iter-121 baseline numbers; Decisions table "Threshold for merged number" row appended Q27 outcome with "CI hard-gate now has zero margin" note. (3).specify/features/testing.md— AC #10 test count refreshed (43 → 48 CT, 15 → 20 MobileMenu, 1165 → 1170 total) with iter 120/124 growth annotation + cross-reference todocs/plans/q27-mobilemenu-empty-items-coverage.md; AC #12 rewritten end-to-end to retire the long-stale "FilterBar/LayoutSwitcher/MobileMenu excluded fromvitest.config.tscoverage.includeuntil Q22 follow-up #3" wording (the exclusions were dropped in iter 115 / Phase 2) and replace with the steady-state Vitest+CT V8 merge description (monocart-reporteraddCoverageReport()fixture iter 114 +vitest-monocart-coverageVitest provider Q26 iter 119 +pnpm coveragemerge script + Phase 6cGATE_TARGETS≥80% hard-fail iter 121 + Q27 100% closure iter 124). (4)docs/architecture/testing-runners.md— "Current scope (iteration 121)" → "Current scope (iteration 124)"; per-file gate MobileMenu line gained the full 67.57% → 91.89% → 100% growth chain in parentheses; aggregate updated to 100% (233/233) + bytes 99.79% (45,558/45,650); Future work outcome block rewritten end-to-end to retire the "3-branch shortfall ... deferred — see iteration 120 entry" wording and credit Q27 closure (synthetic Tab dispatch viapage.evaluateOption A.1 +/* v8 ignore next */pragma Option A.3 on the defensivemenuRefrace-guard). (5)README.mdCommon Commandspnpm testrow test count refreshed (1165+ → 1170+; CT split now explicit as "1122 Vitest + 48 Playwright CT"). Routine maintenance audit (zero deltas — re-verified): 15-package version matrix re-checked (1.5h after iter 123) — every dep still at the samelatestversion (Astro 6.1.9, Vitest 4.1.5, Playwright 1.59.1, Tailwind 4.2.4, Preact 10.29.1, monocart-coverage-reports 2.12.11, monocart-reporter 2.10.1, vitest-monocart-coverage 4.0.2, @astrojs/{vercel 10.0.5, preact 5.1.2, sitemap 3.7.2, check 0.9.8}, @playwright/test 1.59.1, TypeScript 6.0.3, Prettier 3.8.3). CT-flake watch carried: count remains 1/3 (iter 124 ran mobile-menu.ct.test.tsx 20/20 cleanly +pnpm coverageend-to-end clean — no recurrence; iter 125 was doc-only with no CT runs). No source / test / config /package.json/ lockfile changes. Nopnpm install. Nopnpm coveragere-run (iter 124 numbers stay authoritative: aggregate 100% branches (233/233), MobileMenu 100% (35/35), gate green with zero margin). Iteration 124 history below.)Iteration 124 (history): Q27 ✅ RESOLVED —
MobileMenureaches 100% branches;@ever-works/uiaggregate reaches 100% branches (233/233); the entire Q22→Q27 saga is now closed. Three new CT tests + one v8-ignore pragma. (1)focus trap: empty panel - Tab does nothing (focusable.length === 0)— closes B1 via syntheticKeyboardEvent('keydown', { key: 'Tab' })dispatch throughpage.evaluate; usestoBeAttached()instead oftoBeVisible()to bypass the iter-120 CT-host-page race where<MobileMenu items={[]} />ends up CSS-hidden but DOM-attached (DOM listener still registered). (2)focus trap: synthetic Tab on last nav link wraps focus to first— closes B2; the iter-120 natural-keyboard variant covers behavior butpage.keyboard.press('Tab')moves focus before the document handler evaluatesdocument.activeElement === last, so synthetic dispatch is needed for V8 measurement. (3)focus trap: Tab on middle nav link does not preventDefault (non-boundary)— closes B3 (FALSE arm of both short-circuits). One additional defensive race-guard branch surfaced during execution (if (!menuEl) return;line 72 — only fires whenmenuRef.currentis null AT the momentisOpenflips true; a Preact ref-attachment race that does not occur in production); closed via Option A.3/* v8 ignore next */pragma — verified the syntax works withmonocart-coverage-reports@^2.12.9. Final per-package merged coverage: branches 100% (233/233), functions 100% (104/104), lines 99.76% (1240/1243), statements 99.72% (352/353), bytes 99.79% (45,558/45,650) across 19 files. Per-file gate: FilterBar 100% ✅ / LayoutSwitcher 100% ✅ / MobileMenu 100% (35/35) ✅. Mobile-menu.ct case count: 17 → 20. Verification:pnpm typecheck23/23,pnpm lint18/18,pnpm --filter @ever-works/ui exec playwright test mobile-menu.ct.test.tsx20/20 in 55.3s,pnpm coverageend-to-end clean. Saga complete: Q22 ✅ + Q23 ✅ + Q24 ✅ + Q25 ✅ + Q26 ✅ + Q27 ✅; Q22 follow-ups #1 ✅ + #2SUPERSEDED+ #3 ✅. The CI hard-gate from iter 121 now has zero margin — any future code change that drops a branch will fail the merge. Iteration 123 history below.)Iteration 123 (history): Q27 OPENED + spec + plan authored —
MobileMenu3-branch outlier coverage closure (carry from iteration 122 "Next Steps"). Pure-documentation iteration. Three new doc surfaces created: (1).specify/features/q27-mobilemenu-empty-items-coverage.md(~280 lines) — full feature spec mirroring the Q24 (EMPTY_MODES) format with 9 acceptance criteria, 3 options for B1 (thefocusable.length === 0empty-items branch — A.1 synthetic Tab dispatch viapage.evaluate[DEFAULT]/ A.2 controlled-state API rejected / A.3v8 ignore nextcontingency), 1 option for B2+B3 (non-boundary Tab natural test), 4 risks, AGENTS.md R1-R15 cross-check; (2)docs/plans/q27-mobilemenu-empty-items-coverage.md(~220 lines) — 4-step execution plan: Step 0 smoke-test Option A.1 in scratch dir / Step 1 land B1 test (replaces inline-deferral comment lines 254-264 ofmobile-menu.ct.test.tsx) / Step 2 land B2/B3 non-boundary Tab test / Step 3 verify (pnpm test:ct× 2,pnpm coverageaggregate ≥99.4%, MobileMenu ≥97%, gate green) / Step 4 doc updates; sequencing table puts total at 1.5-2 hours across 1-2 future iterations; (3)docs/questions.mdQ27 entry (~70 lines) with default A.1 + AC #2 path + "why this is OPEN not deferred" rationale (retires iteration 120's permanent inline TODO marker). Routine maintenance audit (zero deltas): full 22-package version matrix verified against npmlatest— every dep is at the latest published version (caret-resolved or exact-pinned). One out-of-scope finding: ESLint pin^9.0.0vs latest10.2.1(major-version gap requiring manual changelog review; not autonomous). CT-flake watch carried: count remains 1/3 (iters 122/123 doc-only, no CT runs). No source / test / config /package.json/ lockfile changes. Nopnpm install. Nopnpm coveragere-run (iter 121 numbers stay authoritative: aggregate 98.72% branches, MobileMenu 91.89%, gate green). Iteration 122 history below.)Iteration 122 (history): Q22 follow-up #3 Phase 6d ✅ DONE — status flips across architecture / spec / questions / plan; Q22 follow-up #3 fully ✅ COMPLETE; the entire Q22→Q26 saga is now closed. Doc-only iteration. Six surfaces flipped: (1)
docs/architecture/testing-runners.md"Coverage handling" rewritten end-to-end (was iter-116 CT-only / 67.57% MobileMenu wording; now describes the steady-state Vitest+CT V8 merge with the iter-121 numbers — branches 98.72%, MobileMenu 91.89%, gate enforced); "Future work"playwright-coveragebullet flipped to ✅ COMPLETE with per-phase recap (Phase 0/1/2/3/6a/6b/6c/6d). (2).specify/features/q22-playwright-coverage.mdfront-matter statusSPECIFIED (iter 110)→✅ RESOLVED (iter 121)with final per-package merged numbers. (3)docs/questions.mdQ22 status block appended a 3-item list marking all follow-ups closed (#1 ✅ iter 108 / #2SUPERSEDEDiter 110 / #3 ✅ iter 121). (4)docs/questions.mdQ25 statusOPEN→✅ RESOLVED — Option A (monocart-coverage-reports@^2.12.0)with smoke-test pass cite. (5)docs/questions.mdQ26 status block expanded to credit Phase 6c + 6d. (6)docs/plans/q22-playwright-coverage.mdPhase 6d gained an Outcome block. Final saga state: Q22 ✅ + Q23 ✅ + Q24 ✅ + Q25 ✅ + Q26 ✅; Q22 follow-ups #1 ✅ + #2SUPERSEDED+ #3 ✅. No source / test / config changes; iter-121 verification (pnpm coverageend-to-end clean, gate green, 19 files, 98.72% branches) remains authoritative.pnpm typecheck23/23 +pnpm lint18/18 (FULL TURBO cache hits, doc-only). Future open work: CT-flake watch (1/3) + MobileMenu 3-branch outlier (component-spec issue). Iteration 121 history below.)Iteration 121 (history): Q22 follow-up #3 Phase 6c ✅ DONE — coverage gate hard-fail enforced.
packages/ui/scripts/coverage-merge.tsflipped from informational ⚠️ to hard-fail: when any ofFilterBar.tsx/LayoutSwitcher.tsx/MobileMenu.tsxdrops below 80% branches in the merged report, the script exits with code 1. Allow-list is explicit (GATE_TARGETSconstant) so unrelated future files do not get gated by accident. Threshold is centralized (GATE_THRESHOLD = 80) for one-line tracking-issue overrides. New.github/workflows/ci.ymlcoverage-gatejob (depends onci+test-ct) runspnpm coverageand inherits the merge script's exit code; uploadspackages/ui/coverage/merged/as a 14-day artifact for reviewer browse on every PR. Verification on Windows 10 + Node 24.14.1:pnpm typecheck23/23 (16 cached + 7 fresh, 1m21s),pnpm lint18/18 (16 cached + 2 fresh, 15.4s),pnpm coverageend-to-end clean — gate ✅ (FilterBar 100%, LayoutSwitcher 100%, MobileMenu 91.89%); merge aggregate 98.72% branches (232/235), 100% functions (104/104), 99.60% lines (1239/1244), 99.15% statements (352/355) across 19 files. Failure-path also verified: temporarily raisedGATE_THRESHOLDto 95 → script exits with code 1 and the diagnostic block prints❌ src/preact/MobileMenu.tsx: 91.89% branches; reverted to 80 immediately. Phase 6d (status flips for Q22 follow-up #3 + Q26 acrossdocs/architecture/testing-runners.md,.specify/features/,docs/questions.md) is now the only remaining Q22-follow-up-#3 task. Iteration 120 history below.)Iteration 120 (history): MobileMenu CT focus-trap tests close 9-of-12 branch gap (67.57% → 91.89%); Phase 3 per-file gate now PASSES for all three migrated components; Phase 6c hard-gate unblocked. Two new CT tests in
packages/ui/src/__tests__/ct/mobile-menu.ct.test.tsxexercise the focus-trapuseEffect(lines 69-95 ofMobileMenu.tsx): Tab on the LAST nav link wraps focus to the FIRST; Shift+Tab on the FIRST nav link wraps focus to the LAST. Mobile-menu.ct case count: 15 → 17. Aggregatepnpm coveragemerged number: 94.89% → 98.72% branches (232/235), 100% functions (104/104), 99.60% lines (1239/1244), 99.15% statements (352/355) across 19 files. Per-file gate (≥80% branches): FilterBar 100% ✅, LayoutSwitcher 100% ✅, MobileMenu 91.89% (34/37) ✅ —coverage-merge: ✅ Phase 3 per-file gate satisfied.3-branch shortfall (235-232) is MobileMenu'sif (focusable.length === 0) return;early-return (line 79) + 2 fall-through branches; an attempted third CT test for<MobileMenu items={[]} />reproduced an unrelated CT-host focus-attribution edge case where the panel becomes hidden post-mount, deferred with an inline comment. Verification:pnpm typecheck23/23,pnpm lint18/18,pnpm --filter @ever-works/ui exec playwright test mobile-menu.ct.test.tsx17/17 in 46.0s,pnpm coverageend-to-end clean.Iteration 119 (history): Q22 follow-up #3 Phase 6b ✅ DONE —
vitest-monocart-coverageadopted; full V8+Vitest merge now live; Q26 ✅ RESOLVED.pnpm --filter @ever-works/ui add -D vitest-monocart-coverage@^4.0.0landed (resolved4.0.2, +7 top-level lockfile entries — predicted 5, +2 transitive).packages/ui/vitest.config.tsswappedprovider: 'v8'→provider: 'custom'+customProviderModule: 'vitest-monocart-coverage'; thereporterarray dropped (moved to monocart). Newpackages/ui/mcr.config.tswith top-leveloutputDir: './coverage'+reports: ['raw'](one delta from the original Phase 6b plan: the per-report-tuple form[['raw', { outputDir: './coverage/raw' }]]nests under MCR's default./coverage-reports/root, so Vitest output landed at./coverage-reports/coverage/raw/; the deployed top-level form mirrorsplaywright.ct.config.tsand writes to./coverage/raw/coverage-<id>.jsondirectly — 40 files per Vitest run).packages/ui/scripts/coverage-merge.tssimplified — Istanbul branch dropped, singleinputDir: ['./coverage/raw', './coverage/ct/raw'](89 raw V8 files combined: 40 Vitest + 49 CT).monocart-coverage-reportspin bumped from^2.12.0→^2.12.9to align with Q26's transitive floor. Verification on Windows 10 + Node 24.14.1 + pnpm 10.33.0:pnpm typecheck23/23,pnpm lint18/18, end-to-endpnpm coverageproduces a merged report covering 19 files at branches 94.89% (223/235), functions 100% (104/104), lines 98.63% (1227/1244), statements 96.62% (343/355) in ~3 min walltime (~98s Vitest + ~78s CT + ~1s merge). Per-file gate: FilterBar.tsx 100% ✅, LayoutSwitcher.tsx 100% ✅, MobileMenu.tsx 67.57% ❌ — the 12-branch shortfall (235-223) is exclusively MobileMenu's known gap, deferred to Q22 follow-up #3 sub-iteration. Phase 6c (CI gate hard-fail) sequenced for iteration 120; Phase 6d (status flips) for iteration 121. Iteration 117 history below.)Iteration 117 (history): Q26 npm-registry validation + Phase 6a smoke test ✅ PASSED in same iteration. Status flipped from
OPEN [DEFAULT]toCONFIRMED — Option A; Phase 6a SMOKE PASSED. Validation block was prepared upstream as iteration-117 prep; the Phase 6a smoke test (originally planned for iteration 118 per pending plan) was also executed in this run, end-to-end.[email protected]ran a 2-test/3-branch Vitest suite in scratch dirpackages/ui/scratch/q26-vitest-monocart/(deleted at end of phase): branches 75% (3/4 — exactly the deliberate uncovered branch), functions 100%, lines 94.44%, statements 91.67%, bytes 97.80%. Outputcoverage/raw/coverage-<id>.jsonis identical in shape to Playwright CT'scoverage/ct/raw/<id>.json— confirming Phase 6b's merge is justinputDir: ['./coverage/raw', './coverage/ct/raw']with no Istanbul mixing. Source-map fidelity verified: per-filesrc/sample.tsresolves tourl: "src/sample.ts"(workspace-relative, NOT a chunk hash). The Q26 reopen condition (smoke-test failure → Option B custom converter) does NOT trigger. Plan sub-phases shifted: 6a = iteration 117 ✅ DONE; 6b/6c/6d = iterations 118/119/120 (was 119/120/121). One known-not-blocking deprecation warning surfaced fromvitest-monocart-coverageinternals (Importing from "vitest/coverage" is deprecated since Vitest 4.1) — tracked upstream atcenfun/vitest-monocart-coverage; will file an issue if it persists past 4.0.2. Doc + scratch-only iteration — zero changes inpackages/,apps/,node_modules/,pnpm-lock.yamlof the production tree. Phase 6b is unblocked: next iteration replacesprovider: 'v8'inpackages/ui/vitest.config.tswithprovider: 'custom'+customProviderModule: 'vitest-monocart-coverage', addspackages/ui/mcr.config.ts, simplifiescoverage-merge.tsto drop the Istanbul branch. Iteration 116 history below.)Iteration 116 (history): Q22 follow-up #3 Phase 3 ✅ PARTIALLY DONE —
pnpm coveragemerge command landed end-to-end on Windows + Node 24.14.0; CT subgraph fully merged; full V8+Vitest deferred to new Q26. Newpackages/ui/scripts/coverage-merge.ts(~190 lines) constructsnew CoverageReport({ inputDir: ['./coverage/ct/raw'], outputDir: './coverage/merged', cleanCache: true, reports: [['v8'], ['v8-json'], ['lcov'], ['codecov'], ['console-summary']], sourceFilter })and callsmcr.generate().playwright.ct.config.tsgains'raw'in itscoverage.reportsso per-test V8 entries land atcoverage/ct/raw/<id>.json(49 files after a clean run).vitest.config.tsgains'json'in itsreporterarray socoverage-final.jsonis written for Q26's eventual full merge. Newcoveragescripts: per-package (pnpm test:coverage && pnpm test:ct && tsx scripts/coverage-merge.ts) and root (pnpm --filter @ever-works/ui coverage).CLAUDE.mddocumentspnpm coveragein Common Commands + Safe Operations. Merged aggregate: branches 84.88% (73/86), functions 100% (40/40), lines 97.18% (482/496), statements 90.60% (106/117), bytes 97.53% (19,903/20,407) across 9 files in the CT subgraph. Per-file gate (informational): FilterBar.tsx 100% branches ✅, LayoutSwitcher.tsx 100% branches ✅, MobileMenu.tsx 67.57% (25/37) ❌ — 12 branches uncovered, likely focus-trap teardown / pointer-vs-touch fallback /prefers-reduced-motionguards. Q26 opened: [email protected] has a hard limitation (getCoverageResultsdispatches mutually-exclusive code paths ondataList[0].type) preventing raw V8 + Istanbul mixing in a single MCR instance — empirically reproduced as[MCR] Not found source data: undefined→TypeError ... at getCssAstInfo. Default Option A:vitest-monocart-coveragedrop-in provider so Vitest also emits raw V8 → both inputs flow through the same V8 path. Phase 4 CI is unblocked for the artifact-upload portion; gate enforcement waits on Q26 + MobileMenu CT branches. Iteration 115 history below.)Iteration 115 (history): Q22 follow-up #3 Phase 2 ✅ DONE — Vitest exclusions for the three CT-migrated components dropped; intended pre-merge state captured. Removed three
coverage.excludelines frompackages/ui/vitest.config.tsforFilterBar.tsx/LayoutSwitcher.tsx/MobileMenu.tsxand replaced them with an iteration-115 comment block pointing at the plan and spec for the Phase 3 merge story. Branch number measured before/after on identical 11/11 files / 174/174 tests passing in ~100s: 100% (145/145) → 70.53% (158/224) — exactly within the plan's predicted 70-72% pre-merge envelope. Per-file:FilterBar.tsxandMobileMenu.tsxnow report 0% (Vitest never executes them — only CT does, and that V8 stream is unmerged until Phase 3),LayoutSwitcher.tsxat 86.66% branches (one render-import side path runs under Vitest). The CT V8 stream from Phase 1 (iteration 114,coverage/ct/raw-v8.jsonwith 9 entries including all three migrated components at source-mapped.tsxURLs) is unaffected — Phase 3 will combine the two streams into a singlecoverage-summary.jsonand restore the per-package number to ≥ baseline. AC #5 satisfied at the source-file level; AC #5's per-file ≥80% gate naturally lives in Phase 3. AC #4 / AC #6 remain Phase 3 work. Phase 3 is unblocked: createpackages/ui/scripts/coverage-merge.ts, addpnpm coveragescript (root + per-package), wire MCR to read bothcoverage-final.json(Vitest) andraw-v8.json(CT).pnpm typecheck23/23,pnpm lint18/18 (both with FULL TURBO partial cache hits). Zero CT regression check this iteration — Phase 2 is purely a Vitest-config edit, no runtime effect on the CT runner. Iteration 114 history below.)Iteration 114 (history): Q22 follow-up #3 Phase 1 ✅ DONE — V8 coverage now flowing on every
pnpm test:ctrun.monocart-coverage-reports@^2.12.0+monocart-reporter@^2.10.0landed as@ever-works/uidevDependencies;playwright.ct.config.tsreporter array gained themonocart-reporterentry (withcoverage.entryFilteracceptinglocalhost:3100/assets/*.jschunks andcoverage.sourceFilternarrowing topackages/ui/src/); a newsrc/__tests__/ct/fixtures.tsextends the CT test with an auto-fixture that callspage.coverage.startJSCoverage()/stopJSCoverage()and pipes per-test V8 entries intoaddCoverageReport(); the three CT test files (filter-bar,layout-switcher,mobile-menu) now importtest/expectfrom this fixture instead of@playwright/experimental-ct-reactdirectly. Verification:pnpm --filter @ever-works/ui test:ctreports 43/43 passing in 1m 16s;packages/ui/coverage/ct/raw-v8.jsonwritten viacoverage.onEndhook with 9 V8 entries (well over the plan's ≥3 exit criterion), all carrying source-mapped.tsx/.tsURLs undersrc/preact/,src/primitives/,src/components/ui/,src/lib/— including all three migrated components (FilterBar.tsx,LayoutSwitcher.tsx,MobileMenu.tsx). MCR aggregate: branches 84.88% (73/86), functions 100% (40/40), lines 97.18% (482/496), statements 39.80% (39/98), bytes 60.73% — confirms AC #3 (URLs map to source files, not chunk hashes) and partially AC #5 (≥80% branches per migrated component, pending Phase 2's exclusion drop to verify per-file). Spec R6 risk now fully closed (was downgraded in 113): source-maps + Vite/Preact alias chain produce real.tsxURLs, not chunk hashes.tsconfig.jsonexclude list updated (src/__tests__/ct/**removed via inferred-type fix infixtures.tsas typeof basecast — typecheck stays clean for both regular and CT tsconfigs).packages/ui/.gitignoregained explicitcoverage/entry (defense in depth — root .gitignore already covers it). Phase 1 exit criterion satisfied; Phase 2 unblocked (drop the three Vitestcoverage.excludelines forFilterBar.tsx/LayoutSwitcher.tsx/MobileMenu.tsx; expected outcome per plan: branch number drops to ~70-72% pre-merge). Iteration 113 history below.)Iteration 113 (history): Q22 follow-up #3 Phase 0 ✅ PASS-API. monocart-coverage-reports 2.12.11 validated end-to-end on Windows 10 + Node 24.14.0 + Chromium 147 + Playwright 1.59.1: Playwright's
page.coverage.startJSCoverage()+stopJSCoverage()captured 1 V8 entry from a syntheticfile://-servedapp.js(3-branchmaybeBranch(x)function, intentional 2-of-3 branch exercise), MCRadd()+generate()succeeded without error, outputcoverage-report.jsoncarries every field the plan's Phase 1 needs (url,sourcePath,source, per-bytedataranges,summary). Per-file coverage stats: branches 75% (3/4), statements 85.71%, lines 88.89%, functions 100%, bytes 95% — all match the deliberately-instrumented synthetic test code. Q25 status flipped fromOPEN [DEFAULT]to CONFIRMED — Option A (monocart-coverage-reports@^2.12.0); Option B (@bgotink/playwright-coverage) remains a contingency only if Phase 1's source-map verification fails. Spec R6 risk DOWNGRADED from "library may not exist / mis-handle toolchain" to "library may mis-handle Vite/Preact alias source-maps" — a much narrower Phase 1 surface. Plan Phase 0 marked ✅ PASS-API; Phase 1 explicitly unblocked. Scratch dir created/used/deleted entirely within iteration 113 per plan step 4 — zero persistent code/dep/config changes;.gitignorescratch/rule from iteration 112 covered the entire transient tree.Iteration 112 (now superseded by 113 above for the front-page descriptor): Q25 npm-registry validation + Phase 0 prerequisite (
packages/ui/.gitignore) created. Two parallel docs/prep deliverables, both low-risk and gated. (1) Q25 npm-registry validation: before anypnpm addlands, verified[email protected](latestdist-tag, above the spec's^2.11.0floor — pin bumped to^2.12.0to lock the verified branch) and[email protected](latest, pin bumped to^2.10.0) are still actively published. README inspection confirmsplaywright-ct-reactis an explicitly listed integration example, the "Automatic Merging" / "Manual Merging" sections describe the Vitest-unit + Playwright-CT merge flow we need (matches AC #4), andentryFilter/sourceFilterAPI matches the plan's Phase 1 step 2 settings. Q25 default (Option A —monocart-coverage-reports) holds; the spec's "Library may not exist" risk (R6) drops to "library may mis-handle our specific Vite/Preact alias" — a much narrower Phase 0 surface. (2)packages/ui/.gitignorecreated (first per-package gitignore in the repo) with a singlescratch/line plus a header comment block referencing the plan and spec. Most generic patterns (node_modules/,coverage/,dist/,test-results/,playwright-report/) are already covered by the repo-root.gitignore; this file's only purpose is the scratch-dir convention required by Phase 0 step 1 of the plan. Phase 0 (the smoke test itself) was NOT executed in iteration 112 — three reasons documented in the log: (a) validation already shrank Phase 0's scope; (b) cron-task autonomy + browser-cold-start fragility argues against coupling a brand-new dev dep + new Playwright reporter + browser launch in one autonomous iteration; (c) the plan's iteration sequencing already lists Phase 0 alone as ~30 min Low-risk. Iteration 113 inherits a fully unblocked Phase 0 (gitignore exists, library version is verified, hand-off checklist sits at the bottom of the log entry). Files changed:docs/questions.mdQ25,.specify/features/q22-playwright-coverage.mdDecisions table,docs/plans/q22-playwright-coverage.mdheader + Phase 0/1 step 1. Files created:packages/ui/.gitignore. Iteration 111 history below.)Iteration 111 (now superseded by 112 above for the front-page descriptor): CLAUDE.md drift fix —
pnpm test:ct+pnpm test:ct:installnow listed in Common Commands and Safe Operations. The Playwright CT toolchain has been the canonical signal forFilterBar/LayoutSwitcher/MobileMenusince iteration 105, but CLAUDE.md never picked it up; new contributors / AI agents reading the file cold would have missed it. Also captures a CT-flake observation from iteration 111's verification (filter-bar.ct › selects category on clickfailed once, passed on retry; not opening Q26 yet — single-occurrence flake within Playwright cold-start tolerance, will revisit if it recurs ≥3× in the next 3 iterations). Q22 follow-up #3 (playwright-coverageintegration) verified upstream:[email protected]+[email protected]both above the spec's^2.11.0pin — Phase 0 smoke test is the cleanest single-iteration unit for the next run. Doc-only iteration; no code/dep changes.Iteration 110 (history): Q22 follow-up #2 SUPERSEDED + Q22 follow-up #3 spec/plan authored. Two parallel deliverables. (1) Follow-up #2 —
pnpm test:ui:saferemoval — SUPERSEDED: plainpnpm --filter @ever-works/ui testruns all 11 Vitest files (174 tests) in ~98s on Windows + Node 24.14.0, verified 2 of 2 consecutive runs. Q22 IPC-hang fingerprint does not reproduce. The cron-task instruction "Do NOT remove anything (move or improve is OK)" + AGENTS.md R15 ("Replace, don't remove") preclude outright deletion; the script is soft-deprecated via JSDoc + CLAUDE.md note as a defensive fallback for any future Vitest/jsdom/Node regression.docs/architecture/testing-runners.md"Future work" entry flipped from "OPEN" to "SUPERSEDED". Zero file deletions. (2) Follow-up #3 —playwright-coverageintegration — SPECIFIED + PLANNED: new spec at.specify/features/q22-playwright-coverage.md(10 acceptance criteria, library risk analysis, AGENTS.md R1-R15 cross-check) and 5-phase execution plan atdocs/plans/q22-playwright-coverage.md(Phase 0 smoke test gate before any code lands; Phase 5 status flip). New question Q25 indocs/questions.mdcaptures the library choice (monocart-coverage-reports2.x [DEFAULT] vs@bgotink/playwright-coveragevs custom harness vs defer-indefinitely). Default rationale: monocart explicitly supportsplaywright-ct-react, explicitly supports merging V8 coverage from multiple sources, emits V8-native reports matching Vitest's existing provider. When this lands across iterations 111-114, the three exclusions inpackages/ui/vitest.config.ts(FilterBar, LayoutSwitcher, MobileMenu) drop and the per-package branch number reflects the full surface area rather than measured-surface-only. Q22 / Q23 / Q24 remain CLOSED; Q22 follow-ups #1 / #2 are now CLOSED (#2 via supersession); only Q22 follow-up #3 + Q25 + CI-matrix-observation remain open.
Root Documents
These files live at the repository root and are not part of the Docusaurus docs site. View them on GitHub or in the cloned repository.
- CLAUDE.md — Claude Code instructions, project overview, commands (view on GitHub)
- AGENTS.md — AI agent rules (R1-R15 under Mandatory Rules), working process, data contracts, available pages/components/plugins (view on GitHub)
- SKILLS.md — Step-by-step AI agent skills for building directory sites (view on GitHub)
- README.md — Project README (view on GitHub)
Overview
- overview.md — Project overview, philosophy, tech stack, quick start
Architecture
- architecture/overview.md — High-level architecture overview, data flow, performance budget
- architecture/data-layer.md — Data layer design (git-first), content repo structure, all data types
- architecture/plugin-system.md — Plugin architecture, lifecycle hooks, plugin types
- architecture/adapter-system.md — Adapter pattern for data sources (git, filesystem)
- architecture/component-system.md — Headless UI component design, island architecture
- architecture/content-sync.md — Content synchronization, caching, ISR architecture
- architecture/testing-runners.md — Vitest vs. Playwright CT vs. Playwright E2E decision matrix; authoring conventions; Q22 background
Plans
- plans/phase-1-foundation.md — Phase 1: Monorepo scaffold, core types, data layer
- plans/phase-2-components.md — Phase 2: Headless UI components
- plans/phase-3-web-app.md — Phase 3: Astro web app with pages
- plans/phase-4-plugins.md — Phase 4: Built-in plugins (search, filters, etc.)
- plans/phase-4b-plugin-analytics.md — Phase 4b: Analytics plugin (Plausible, Umami, Fathom, GA4, custom)
- plans/phase-5-sample.md — Phase 5: Sample implementations
- plans/phase-5-sample-detail.md — Phase 5: Detailed implementation plan for sample-basic
- plans/phase-6-deployment.md — Phase 6: Deployment, CI/CD, docs site
- plans/phase-7-sample-events.md — Phase 7: Sample events/conferences directory
- plans/phase-8-sample-real-estate.md — Phase 8: Sample real estate/property listings directory
- plans/q22-playwright-ct.md — Q22: Migrate
FilterBartests to Playwright Component Testing (Option D) - plans/q22-upstream-repro.md — Q22: Minimal upstream repro template for
vitest-dev/vitest - plans/q22-mobilemenu-ct.md — Q22 follow-up #1: Preemptive
MobileMenuPlaywright CT migration - plans/q24-layoutswitcher-empty-modes.md — Q24:
LayoutSwitcherEMPTY_MODESallocation fix (mirror of iteration-105EMPTY_TAGS) - plans/q22-playwright-coverage.md — Q22 follow-up #3:
playwright-coverageintegration (5 phases,monocart-coverage-reportsdefault; gated on Phase 0 smoke test) - plans/q27-mobilemenu-empty-items-coverage.md — Q27:
MobileMenu3-branch outlier coverage closure (4 steps; default Option A.1 = synthetic Tab dispatch viapage.evaluate; ✅ RESOLVED iter 124) - plans/q28-eslint-10-upgrade.md — Q28: ESLint 9 → 10 major-version upgrade (7 steps; default Option A = single-iteration in-place peer-range bump; pre-investigated iter 129)
- plans/audit-docs-script.md —
scripts/audit-docs.ts— executable codification of the doc-quality audit checklist (iter 149: 6 audit classes + 1 cross-file parity check; ✅ RESOLVED iter 149 → wired into CI as PR-blocking step iter 150) - plans/audit-docs-self-parity.md —
audit-docs.tsself-parity audit class — checklist ↔ runner parity self-validation (iter 151: 7th audit class; closes iter-149's "Next Steps #1"; ✅ RESOLVED iter 151) - plans/audit-docs-matrix-prose.md —
audit-docs.tsmatrix-prose count parity audit class —**N-package matrix**total ↔ canonical 3-cohort breakdown sum parity (iter 161: 8th audit class; codify-trigger fired iter-160 after 2 drift instances per iter-156 deferral #9 codify-then-execute meta-pattern; ✅ RESOLVED iter 161) - plans/multi-option-support.md — Multi-option support execution plan (iter 218 user pivot, OPEN — phases queued): 8 independent phases each iteration-scale (~2-4h), per-phase verification gates, cross-cutting audit-script impact notes (Phase 3/4/7/8 each bump
**N packages**count), recommended sequencing starts with Phase 6 (Q10 Starlight docs alt; smallest surface). - plans/works-config-path.md —
.works/works.ymlsite config path migration plan (implemented 2026-05-09): core reads.works/works.yml.
Specifications
- specs/data-schema.md — Data schema specification (Item, Category, Tag, Collection, Comparison, Config)
- specs/plugin-interface.md — Plugin interface contract (hooks, context, lifecycle)
- specs/adapter-interface.md — Adapter interface contract (DataAdapter, AdapterConfig)
- specs/component-catalog.md — Component catalog (all Astro, Preact, and primitive components)
Spec Kit (.specify/)
These files live in the
.specify/directory at the repository root. View them on GitHub or in the cloned repository.
- project.md — Project specification (goals, non-goals, tech stack, timeline) (view on GitHub)
- features/data-layer.md — Data layer feature spec (view on GitHub)
- features/plugin-system.md — Plugin system feature spec (view on GitHub)
- features/ui-components.md — UI components feature spec (view on GitHub)
- features/web-app.md — Web app feature spec (all page routes) (view on GitHub)
- features/plugins-phase4.md — Phase 4 built-in plugins detailed spec (view on GitHub)
- features/sample-basic.md — Sample basic implementation spec (view on GitHub)
- features/plugin-breadcrumbs.md — Breadcrumbs plugin spec (view on GitHub)
- features/testing.md — Unit testing infrastructure spec (view on GitHub)
- features/static-pages.md — Static pages feature spec (view on GitHub)
- features/sample-git.md — Sample Git reference implementation spec (view on GitHub)
- features/content-sync.md — Content sync, caching & ISR spec (view on GitHub)
- features/sample-jobs.md — Sample Jobs (job board directory) spec (view on GitHub)
- features/sample-events.md — Sample Events (conferences/meetups directory) spec (view on GitHub)
- features/sample-real-estate.md — Sample Real Estate (property listings directory) spec (view on GitHub)
- features/lighthouse-ci.md — Lighthouse CI performance testing spec (view on GitHub)
- features/plugin-rss.md — RSS/Atom feed plugin spec (view on GitHub)
- features/plugin-analytics.md — Analytics plugin spec (Plausible, Umami, Fathom, GA4, custom) (view on GitHub)
- features/plugin-related-items.md — Related items plugin spec (tag/category scoring, build-time computation) (view on GitHub)
- features/plugin-filters.md — Filters plugin spec (category, tag, search filtering with URL sync) (view on GitHub)
- features/plugin-search.md — Search plugin spec (Pagefind static search indexing) (view on GitHub)
- features/plugin-pagination.md — Pagination plugin spec (page calculation, URL patterns) (view on GitHub)
- features/plugin-sort.md — Sort plugin spec (name, date, featured sorting) (view on GitHub)
- features/plugin-sitemap.md — Sitemap plugin spec (@astrojs/sitemap config wrapper) (view on GitHub)
- features/robots-txt.md — robots.txt generation spec (view on GitHub)
- features/visual-regression.md — Visual regression testing spec (view on GitHub)
- features/q22-playwright-ct.md — Q22 resolution: Playwright Component Testing migration spec for
FilterBar(view on GitHub) - features/q22-mobilemenu-ct.md — Q22 follow-up #1: Preemptive
MobileMenuPlaywright CT migration spec (view on GitHub) - features/q24-layoutswitcher-empty-modes.md — Q24:
LayoutSwitcherEMPTY_MODESallocation fix spec (view on GitHub) - features/q22-playwright-coverage.md — Q22 follow-up #3:
playwright-coverageintegration spec (V8 coverage merge for Vitest + Playwright CT runs) (view on GitHub) - features/q27-mobilemenu-empty-items-coverage.md — Q27:
MobileMenu3-branch outlier coverage closure spec (focus-trap empty-items + non-boundary Tab; default Option A.1 = synthetic Tab dispatch viapage.evaluate; ✅ RESOLVED iter 124) (view on GitHub) - features/q28-eslint-10-upgrade.md — Q28: ESLint 9 → 10 major-version upgrade spec (single-iteration in-place peer-range bump; pre-investigated iter 129; flat config + Node 24 +
@typescript-eslint@^8.59.0peer-range all already cover ESLint 10) (view on GitHub) - features/audit-docs-script.md —
scripts/audit-docs.tsexecutable codification ofAGENTS.md § Doc-Quality Audit Checklistgreps as a singlepnpm audit:docsrunner (iter 149: 6 audit classes + 1 cross-file parity check; ✅ RESOLVED iter 149 → wired into CI as PR-blocking step iter 150) (view on GitHub) - features/audit-docs-self-parity.md —
audit-docs.tsself-parity audit class — checklist ↔ runner parity self-validation (iter 151: 7th audit class;auditChecklistRunnerParity()readsAGENTS.mddirectly withnode:fsand asserts 1:1 parity between###sub-section headings and the in-scriptEXPECTED_MAPPINGtable; closes iter-149's "Next Steps #1"; ✅ RESOLVED iter 151) (view on GitHub) - features/audit-docs-matrix-prose.md —
audit-docs.tsmatrix-prose count parity audit class —**N-package matrix**total claim ↔ canonical 3-cohort breakdown sum parity (iter 161: 8th audit class;auditMatrixProseCountParity()reads.specify/project.mddirectly withnode:fsand asserts(high-churn cohort, X) + (iter-N lifted, Y) + (deferred cohort, Z) == N; codify-trigger fired iter-160 after 2 drift instances per iter-156 deferral #9 codify-then-execute meta-pattern; ✅ RESOLVED iter 161) (view on GitHub) - features/multi-option-support.md — Multi-option support umbrella spec (iter 218 user pivot, OPEN — phases queued): keep every existing default (Preact / Tailwind / config-file plugins / Pagefind / Astro built-in image / Docusaurus / isomorphic-git / pageview-only analytics) and add alternates for Q1 (UI framework), Q2 (CSS strategy), Q4 (plugin auto-discovery), Q5 (search backends), Q9 (image services), Q10 (Starlight docs), Q18 (git adapters), Q20 (analytics events + consent). 8 independent phases, paired plan at
docs/plans/multi-option-support.md. (view on GitHub) - features/works-config-path.md —
.works/works.ymlsite config path migration spec (implemented 2026-05-09): canonical config path is.works/works.yml. (view on GitHub)
Guides
- guides/quickstart.md — Quick start guide for getting up and running
- guides/getting-started.md — Step-by-step tutorial: build a full directory site from scratch
- guides/building-from-template.md — How AI builds a site from template
- guides/customizing.md — Customize theming, layouts, components, plugins, and data fields
- guides/creating-a-plugin.md — How to create a plugin
- guides/creating-an-adapter.md — How to create a data adapter
- guides/interactive-components.md — How to use Preact interactive islands (search, filter, sort, theme, back-to-top)
- guides/content-sync.md — Content sync setup (webhooks, polling, ISR)
- guides/analytics.md — How to add analytics (Plausible, Umami, Fathom, GA4, custom)
- guides/deployment.md — How to deploy to Vercel and other static hosts
- guides/performance-testing.md — Lighthouse CI performance testing setup and configuration
- guides/troubleshooting.md — Common issues and solutions
- guides/multi-option/docs-framework.md — Phase 6 of multi-option-support (iter 219): docs-framework alternates — keep Docusaurus 3.x as default, opt-in swap recipe to Starlight (Astro-native) with end-to-end scratch verification (
@astrojs/starlight ^0.38.4scaffolded vianpx --yes create-astro@latest,astro check0 errors,astro build4 pages in 6.96s with Pagefind index). Tradeoff matrix covers versioning / blog / search / stack consistency / bundle size; recipe documents three content-migration strategies, sidebar metadata conversion, Vercel deployment plumbing.
Reference
- questions.md — Open questions and decisions (Q1-Q28 with defaults)
- log.md — Change log (all iterations tracked)