jekyll-theme-zer0 1.29.0 → 1.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +715 -2
  3. data/_data/README.md +2 -0
  4. data/_data/ai.yml +5 -3
  5. data/_data/ai_pricing.yml +36 -0
  6. data/_data/backlog.yml +169 -18
  7. data/_data/consumers.yml +48 -5
  8. data/_data/features.yml +146 -20
  9. data/_data/feedback_types.yml +17 -12
  10. data/_data/landing.yml +5 -2
  11. data/_data/navigation/quickstart.yml +4 -0
  12. data/_data/site_builder.yml +874 -0
  13. data/_data/theme-manifest.yml +122 -114
  14. data/_data/ui-text.yml +18 -0
  15. data/_includes/README.md +11 -1
  16. data/_includes/analytics/posthog.html +2 -2
  17. data/_includes/components/admin-links.html +2 -2
  18. data/_includes/components/admin-tabs.html +2 -2
  19. data/_includes/components/ai-chat.html +14 -11
  20. data/_includes/components/analytics-dashboard.html +8 -8
  21. data/_includes/components/author-bio.html +1 -1
  22. data/_includes/components/author-card.html +10 -2
  23. data/_includes/components/author-eeat.html +4 -4
  24. data/_includes/components/background-customizer.html +8 -8
  25. data/_includes/components/background-image.html +114 -0
  26. data/_includes/components/background-settings.html +28 -15
  27. data/_includes/components/collection-manager.html +5 -5
  28. data/_includes/components/component-showcase.html +13 -13
  29. data/_includes/components/config-editor.html +12 -12
  30. data/_includes/components/config-viewer.html +8 -8
  31. data/_includes/components/cookie-consent.html +11 -11
  32. data/_includes/components/cta-button.html +7 -2
  33. data/_includes/components/dev-shortcuts.html +7 -7
  34. data/_includes/components/env-dashboard.html +8 -8
  35. data/_includes/components/env-switcher.html +9 -9
  36. data/_includes/components/feature-card.html +2 -2
  37. data/_includes/components/halfmoon.html +2 -2
  38. data/_includes/components/info-section.html +36 -36
  39. data/_includes/components/js-cdn.html +15 -15
  40. data/_includes/components/language-toggle.html +4 -4
  41. data/_includes/components/mermaid.html +72 -435
  42. data/_includes/components/nanobar.html +5 -5
  43. data/_includes/components/nav-editor.html +2 -2
  44. data/_includes/components/nav-export.html +2 -2
  45. data/_includes/components/nav-overview.html +2 -2
  46. data/_includes/components/page-feedback.html +45 -30
  47. data/_includes/components/page-views-init.html +1 -1
  48. data/_includes/components/post-card.html +22 -22
  49. data/_includes/components/post-type-badge.html +2 -2
  50. data/_includes/components/powered-by.html +2 -2
  51. data/_includes/components/preview-image.html +6 -0
  52. data/_includes/components/quick-index.html +2 -2
  53. data/_includes/components/search-modal.html +27 -2
  54. data/_includes/components/searchbar.html +2 -2
  55. data/_includes/components/svg-background.html +2 -2
  56. data/_includes/components/theme-customizer.html +2 -2
  57. data/_includes/components/theme-info.html +6 -6
  58. data/_includes/components/theme-preview-gallery.html +22 -22
  59. data/_includes/content/giscus.html +2 -2
  60. data/_includes/content/intro.html +8 -8
  61. data/_includes/content/jsonld-faq.html +2 -2
  62. data/_includes/content/jsonld-software.html +2 -2
  63. data/_includes/content/seo.html +4 -4
  64. data/_includes/content/sitemap.html +27 -27
  65. data/_includes/content/toc.html +183 -183
  66. data/_includes/core/branding.html +6 -6
  67. data/_includes/core/console-capture.html +32 -74
  68. data/_includes/core/favicon.html +49 -7
  69. data/_includes/core/footer-fabs.html +17 -3
  70. data/_includes/core/footer.html +31 -18
  71. data/_includes/core/head.html +102 -90
  72. data/_includes/core/header.html +71 -52
  73. data/_includes/docs/bootstrap-docs.html +8 -8
  74. data/_includes/landing/landing-install-cards.html +2 -2
  75. data/_includes/landing/landing-quick-links.html +1 -1
  76. data/_includes/navigation/admin-nav.html +2 -2
  77. data/_includes/navigation/nav-tree.html +8 -8
  78. data/_includes/navigation/navbar.html +12 -12
  79. data/_includes/navigation/section-sidebar.html +16 -16
  80. data/_includes/navigation/sidebar-config.html +36 -2
  81. data/_includes/navigation/sidebar-left.html +15 -15
  82. data/_includes/navigation/sidebar-right.html +6 -6
  83. data/_includes/obsidian/full-graph.html +2 -2
  84. data/_includes/setup/claude-session.html +72 -0
  85. data/_includes/setup/prereq-checklist.html +90 -0
  86. data/_includes/setup/wizard.html +906 -291
  87. data/_includes/stats/stats-categories.html +8 -8
  88. data/_includes/stats/stats-header.html +14 -14
  89. data/_includes/stats/stats-metrics.html +12 -12
  90. data/_includes/stats/stats-no-data.html +12 -12
  91. data/_includes/stats/stats-overview.html +6 -6
  92. data/_includes/stats/stats-tags.html +8 -8
  93. data/_layouts/404.html +38 -24
  94. data/_layouts/admin.html +22 -22
  95. data/_layouts/article.html +39 -34
  96. data/_layouts/author.html +20 -20
  97. data/_layouts/authors.html +2 -2
  98. data/_layouts/book-abc.html +12 -12
  99. data/_layouts/book-story.html +15 -15
  100. data/_layouts/book.html +12 -12
  101. data/_layouts/collection.html +33 -33
  102. data/_layouts/cookbook.html +12 -12
  103. data/_layouts/default.html +27 -24
  104. data/_layouts/home.html +23 -23
  105. data/_layouts/index.html +10 -10
  106. data/_layouts/landing.html +17 -17
  107. data/_layouts/news.html +44 -44
  108. data/_layouts/note.html +38 -38
  109. data/_layouts/notebook.html +34 -34
  110. data/_layouts/recipe.html +24 -24
  111. data/_layouts/root.html +73 -55
  112. data/_layouts/section.html +23 -23
  113. data/_layouts/setup.html +3 -3
  114. data/_layouts/sitemap-collection.html +49 -49
  115. data/_layouts/stats.html +40 -40
  116. data/_layouts/tag.html +12 -12
  117. data/_layouts/welcome.html +21 -21
  118. data/_sass/components/_mermaid.scss +375 -0
  119. data/_sass/components/_setup-wizard.scss +569 -40
  120. data/_sass/core/_navbar.scss +11 -31
  121. data/_sass/layouts/_navbar-extras.scss +14 -4
  122. data/assets/css/main.scss +1 -0
  123. data/assets/js/ai-chat.js +47 -5
  124. data/assets/js/fleet-feedback-capture.js +124 -0
  125. data/assets/js/fleet-feedback.js +853 -0
  126. data/assets/js/mermaid-diagrams.js +1267 -0
  127. data/assets/js/modules/navigation/config.js +9 -6
  128. data/assets/js/modules/navigation/scroll-spy.js +315 -80
  129. data/assets/js/modules/theme/appearance.js +8 -2
  130. data/assets/js/obsidian-wiki-links.js +8 -3
  131. data/assets/js/page-feedback.js +125 -192
  132. data/assets/js/search-modal.js +26 -0
  133. data/assets/js/setup-wizard.js +2112 -361
  134. data/assets/js/site-builder.js +1834 -0
  135. data/assets/js/ui-enhancements.js +11 -3
  136. data/scripts/README.md +15 -0
  137. data/scripts/ai/README.md +38 -0
  138. data/scripts/ai/api_call.rb +124 -0
  139. data/scripts/ai/usage.rb +314 -0
  140. data/scripts/ai/usage_report.rb +225 -0
  141. data/scripts/ci/test_visual_evidence_autogen.py +341 -0
  142. data/scripts/ci/visual_evidence_autogen.py +1060 -0
  143. data/scripts/content-review.rb +20 -1
  144. data/scripts/test/integration/mermaid +22 -8
  145. data/scripts/test/lib/run_tests.sh +1 -0
  146. data/scripts/test/lib/test_visual_evidence_autogen.sh +24 -0
  147. data/scripts/translate.rb +23 -1
  148. metadata +19 -2
data/_data/README.md CHANGED
@@ -7,6 +7,8 @@ This directory contains YAML data files that power the Zer0-Mistakes Jekyll them
7
7
  | File | Purpose | Auto-Generated |
8
8
  |------|---------|----------------|
9
9
  | `navigation/` | Site navigation menus | No |
10
+ | `ai.yml` | The one place the AI model is configured (read by the hub's `bamr87/bamr87/.github/actions/claude-run@main` runner, consumed by reference) | No |
11
+ | `ai_pricing.yml` | API list prices used to *estimate* AI spend for calls that report tokens but no cost (part of the shared `ai-runner` kit) | No |
10
12
  | `authors.yml` | Author profile information | No |
11
13
  | `content_statistics.yml` | Site content analytics | **Yes** |
12
14
  | `roadmap.yml` | Single source of truth for the project roadmap (drives the README mermaid diagram and the `/roadmap/` Jekyll page) | No |
data/_data/ai.yml CHANGED
@@ -1,9 +1,11 @@
1
1
  # =============================================================================
2
2
  # _data/ai.yml — one place the AI model is configured for zer0-mistakes agents
3
3
  # -----------------------------------------------------------------------------
4
- # Read by .github/actions/claude-run (the issue-autopilot's AI step). Change the
5
- # model here and every autopilot agent call uses it. Auth is NOT here — it comes
6
- # from the CLAUDE_CODE_OAUTH_TOKEN (preferred) or ANTHROPIC_API_KEY secret.
4
+ # Read by the fleet's ai-runner kit — bamr87/bamr87/.github/actions/claude-run
5
+ # (consumed by reference; the issue-autopilot's AI step). Change the model
6
+ # here and every agent call uses it; AI_MODEL (or the action's `model` input)
7
+ # overrides it for one run. Auth is NOT here — it comes from the
8
+ # CLAUDE_CODE_OAUTH_TOKEN (preferred) or ANTHROPIC_API_KEY secret.
7
9
  # =============================================================================
8
10
  provider: anthropic
9
11
  model: claude-opus-4-8
@@ -0,0 +1,36 @@
1
+ # =============================================================================
2
+ # ai_pricing.yml — API list prices used to ESTIMATE AI spend (per million tokens)
3
+ # -----------------------------------------------------------------------------
4
+ # The telemetry layer (scripts/ai/usage.rb) prefers the cost the Claude Code CLI
5
+ # itself reports (`total_cost_usd`) — that number is authoritative and this file
6
+ # is never consulted for it. This table exists for the paths that report tokens
7
+ # but no dollars: the raw Claude API fallback (scripts/ai/api_call.rb) and any
8
+ # execution log that predates cost reporting. Those records get cost_source:
9
+ # "estimated", computed as
10
+ #
11
+ # input×in + output×out + cache_read×(0.1×in)
12
+ # + cache_write_5m×(1.25×in) + cache_write_1h×(2×in)
13
+ #
14
+ # which reproduces the CLI's own arithmetic to the cent (validated 2026-07-14
15
+ # against a live run). Prices are USD per MTok at standard API list rates —
16
+ # subscription (OAuth) runs have no marginal dollar cost, so every published
17
+ # figure is labeled "API-equivalent". Source: platform.claude.com/docs/en/pricing
18
+ # (cached 2026-07-14). Update this file when Anthropic changes list prices;
19
+ # estimates are marked as such everywhere they surface.
20
+ # =============================================================================
21
+ multipliers:
22
+ cache_read: 0.1 # × input price
23
+ cache_write_5m: 1.25 # × input price (5-minute TTL — the CLI default)
24
+ cache_write_1h: 2.0 # × input price (1-hour TTL)
25
+
26
+ # Matched by longest model-id prefix, so dated snapshots (claude-haiku-4-5-20251001)
27
+ # resolve to their family row. `default` catches unknown models (opus-tier, so an
28
+ # unknown model over- rather than under-estimates).
29
+ models:
30
+ claude-opus-4-8: { input: 5.00, output: 25.00 }
31
+ claude-opus-4-7: { input: 5.00, output: 25.00 }
32
+ claude-opus-4-6: { input: 5.00, output: 25.00 }
33
+ claude-sonnet-5: { input: 3.00, output: 15.00 }
34
+ claude-sonnet-4-6: { input: 3.00, output: 15.00 }
35
+ claude-haiku-4-5: { input: 1.00, output: 5.00 }
36
+ default: { input: 5.00, output: 25.00 }
data/_data/backlog.yml CHANGED
@@ -62,8 +62,8 @@
62
62
 
63
63
  meta:
64
64
  title: "zer0-mistakes Backlog"
65
- updated: 2026-08-18
66
- next_id: 46
65
+ updated: 2026-09-05
66
+ next_id: 52
67
67
 
68
68
  tasks:
69
69
  # --- Housekeeping (seeded so the loop has work on day one) ------------------
@@ -951,7 +951,7 @@ tasks:
951
951
 
952
952
  - id: T-036
953
953
  title: "Remove hover transforms that cause pointer-edge flicker in the navbar"
954
- status: open
954
+ status: done
955
955
  priority: P1
956
956
  area: feat
957
957
  risk: standard
@@ -968,13 +968,34 @@ tasks:
968
968
  _sass/components/_ui-enhancements.scss and card hover styles for the same
969
969
  pattern.
970
970
  acceptance:
971
- - "No transform in any :hover rule under _sass/ (grep for translateY/scale in hover context returns nothing)."
972
- - "Pointer parked on the top edge of any nav item or utility button does not flicker."
971
+ # Scoped to the navbar per the issue's Option A. Criterion 1 was
972
+ # originally "no transform in any :hover rule under _sass/" — that is 42
973
+ # rules across ~15 files (card lifts, book tilts, recipe hovers) and a
974
+ # visual redesign of a published theme, not this defect. It also flagged
975
+ # `transform: none`, which is the CORRECTIVE pattern this repo already
976
+ # uses in _post-navigation.scss and the prefers-reduced-motion blocks.
977
+ # A theme-wide motion policy belongs in its own task.
978
+ # Stated as the COMPUTED value, not "no matching rule": these controls
979
+ # are `.btn`s and _ui-enhancements.scss's theme-wide
980
+ # `.btn:hover { translateY(-2px) }` still matches them and always will.
981
+ # It is overridden by `transform: none`, not deleted, so a rule-existence
982
+ # check would be permanently red. That inherited lift is why deleting the
983
+ # navbar's own translateY was not sufficient on its own.
984
+ - "getComputedStyle(control).transform is `none` while hovered, for every navbar control."
985
+ # Direction corrected: translateY(-1px) moves the element UP, so the row
986
+ # it stops covering is the BOTTOM one. A test parked on the top edge
987
+ # passes without exercising the bug.
988
+ - "Pointer parked on the bottom edge of any nav item or utility button does not flicker."
989
+ # Note: `#bdNavbar .nav-link:hover`, named in the summary as the primary
990
+ # cause, was dead code — its lift sits inside a container query that never
991
+ # matches at desktop widths (measured 1040/1140/1200/1280px on the built
992
+ # site, `none` at every one, on main too). The observable flicker was on
993
+ # the utility buttons and the FABs.
973
994
  - "regression test added"
974
995
  - "before/after evidence committed"
975
- links: { issue: null, pr: null, roadmap: null }
996
+ links: { issue: 404, pr: null, roadmap: null }
976
997
  created: 2026-08-18
977
- updated: 2026-08-18
998
+ updated: 2026-09-03
978
999
 
979
1000
  - id: T-037
980
1001
  title: "Navbar width recovery: two clean label tiers, merged chevron, centered grid, no subtitle"
@@ -1009,7 +1030,7 @@ tasks:
1009
1030
 
1010
1031
  - id: T-038
1011
1032
  title: "Language switcher: icon-only trigger and a compact, positive menu"
1012
- status: open
1033
+ status: done
1013
1034
  priority: P2
1014
1035
  area: feat
1015
1036
  risk: standard
@@ -1029,10 +1050,9 @@ tasks:
1029
1050
  - "Trigger is icon-only at all widths with an accessible name."
1030
1051
  - "regression test added"
1031
1052
  - "before/after evidence committed"
1032
- links: { issue: null, pr: null, roadmap: null }
1053
+ links: { issue: 406, pr: 431, roadmap: null }
1033
1054
  created: 2026-08-18
1034
- updated: 2026-08-18
1035
-
1055
+ updated: 2026-09-01
1036
1056
  - id: T-039
1037
1057
  title: "Eliminate page-transition layout shift (fixed-nav offset, scrollbar gutter, server-rendered slots)"
1038
1058
  status: open
@@ -1064,7 +1084,7 @@ tasks:
1064
1084
 
1065
1085
  - id: T-040
1066
1086
  title: "Setup wizard: live YAML preview, vertical stepper, draft persistence, stable panel height, inline validation"
1067
- status: open
1087
+ status: done
1068
1088
  priority: P2
1069
1089
  area: feat
1070
1090
  risk: standard
@@ -1087,10 +1107,9 @@ tasks:
1087
1107
  - "Reload mid-wizard restores the draft; invalid email/URL flagged on blur."
1088
1108
  - "regression test added"
1089
1109
  - "before/after evidence committed"
1090
- links: { issue: null, pr: null, roadmap: null }
1110
+ links: { issue: 408, pr: 432, roadmap: null }
1091
1111
  created: 2026-08-18
1092
- updated: 2026-08-18
1093
-
1112
+ updated: 2026-09-01
1094
1113
  - id: T-041
1095
1114
  title: "Admin layout: actions reachable on mobile, grouped sidebar, shared sticky offset, single heading"
1096
1115
  status: open
@@ -1216,7 +1235,7 @@ tasks:
1216
1235
 
1217
1236
  - id: T-045
1218
1237
  title: "Homepage snapshot baselines were regenerated without the 1967px drift being diagnosed"
1219
- status: open
1238
+ status: done
1220
1239
  priority: P2
1221
1240
  area: tests
1222
1241
  risk: low
@@ -1267,6 +1286,138 @@ tasks:
1267
1286
  - "Any genuinely time- or build-varying content inside the snapshot region is masked or stubbed, so the tier cannot drift again."
1268
1287
  - "No baseline PNG is regenerated as part of this work; any diff is diagnosed in the PR before it is blessed."
1269
1288
  - "The y626 band is explained, or recorded as unrecoverable with the reason. (Recorded: artifacts past 14-day retention.)"
1270
- links: { issue: 417, pr: null, roadmap: null }
1289
+ links: { issue: 417, pr: 425, roadmap: null }
1271
1290
  created: 2026-08-23
1272
- updated: 2026-08-25
1291
+ updated: 2026-09-01
1292
+
1293
+ - id: T-046
1294
+ title: "Retire the now-dead gotoBeforeScrollSpy fixture and cover the mobile offcanvas TOC spy"
1295
+ status: open
1296
+ priority: P3
1297
+ area: tests
1298
+ risk: low
1299
+ effort: S
1300
+ source: issue
1301
+ route: test-author
1302
+ summary: >-
1303
+ Discovered while fixing the TOC scroll spy: test/visual/fixtures.js
1304
+ exports gotoBeforeScrollSpy(), which strips data-bs-spy/data-bs-target
1305
+ from <body> before Bootstrap auto-initializes so its native ScrollSpy
1306
+ cannot clear server-rendered .active classes off admin sidebar links.
1307
+ That attribute no longer exists — _layouts/root.html dropped it (and
1308
+ _layouts/default.html dropped the second copy on .bd-main) so the theme's
1309
+ own scroll-spy.js is the single owner of .active on TOC links — which
1310
+ makes the fixture a no-op that still reads as load-bearing. Replace its
1311
+ call sites in test/visual/features/admin.spec.js with the plain
1312
+ waitForJekyll/gotoOrSkip helpers and delete it, keeping the admin
1313
+ active-link assertions that motivated it. While there, add the coverage
1314
+ test/visual/features/scroll-spy.spec.js deliberately left out: the mobile
1315
+ offcanvas TOC, where .offcanvas-body rather than .bd-toc is the scroll
1316
+ container the spy keeps the active link visible in.
1317
+ acceptance:
1318
+ - "gotoBeforeScrollSpy is removed from test/visual/fixtures.js and from its call sites; no spec references it."
1319
+ - "The admin specs that used it still pass, asserting the same server-rendered active nav links."
1320
+ - "A spec exercises the TOC scroll spy below the lg breakpoint with the offcanvas TOC open, asserting the active entry tracks scrolling and stays visible inside .offcanvas-body."
1321
+ - "npm run test:smoke is green."
1322
+ links: { issue: null, pr: null, roadmap: null }
1323
+ created: 2026-09-05
1324
+ updated: 2026-09-05
1325
+
1326
+ - id: T-047
1327
+ title: "pages/_docs/features/toc.md documents a TOC API the theme does not implement"
1328
+ status: open
1329
+ priority: P3
1330
+ area: docs
1331
+ risk: low
1332
+ effort: S
1333
+ source: issue
1334
+ route: content-reviewer
1335
+ summary: >-
1336
+ Discovered while correcting the scroll-spy sections of
1337
+ pages/_docs/features/toc.md: the page's Implementation and Configuration
1338
+ halves describe a table of contents this theme does not have. "TOC
1339
+ Generation" shows a Kramdown `{{ content | toc_only }}` snippet and a
1340
+ hand-rolled `page.content | split: '<h'` extractor, neither of which the
1341
+ theme uses — the real TOC comes from _includes/content/toc.html (the
1342
+ allejo/jekyll-toc parser) invoked by _includes/navigation/sidebar-right.html.
1343
+ "Enable TOC" documents front-matter keys that nothing reads; the
1344
+ `toc.min_level` / `toc.max_level` pair in the same section was already
1345
+ corrected (grep confirms no include, layout, plugin or _config.yml
1346
+ references either key). A reader following this page cannot reproduce the
1347
+ theme's behaviour. Rewrite the two sections against the actual include,
1348
+ its parameters, and the front-matter keys that really gate the panel.
1349
+ acceptance:
1350
+ - "Every Liquid snippet in toc.md matches an include the theme actually ships, verified by path."
1351
+ - "Front-matter keys documented on the page are read somewhere in _includes, _layouts, _plugins or _config.yml."
1352
+ - "scripts/content-review.rb still scores the page in the green band."
1353
+ - "Jekyll build with the layered dev configs is green and the page's anchors keep resolving."
1354
+
1355
+ - id: T-048
1356
+ title: "Site-level theme_color re-pins --zer0-color-primary over the active skin"
1357
+ status: open
1358
+ priority: P2
1359
+ area: feat
1360
+ risk: low
1361
+ effort: S
1362
+ source: issue
1363
+ summary: "Discovered while making Mermaid diagrams follow the skin (ZER0-013 rework): the skin mixin (_sass/theme/_skins.scss) writes both --bs-primary and --zer0-color-primary under [data-theme-skin], but _includes/core/tokens-inline.html emits `:root { --zer0-color-primary: <theme_color.main> }` AFTER main.css, and :root ties [data-theme-skin] on specificity, so the later inline rule wins. Result on this site: buttons/links follow the skin (#6fa8dc on air, #8338ec on neon) while every custom component that reads --zer0-color-primary (callouts, code-block accent border, focus rings) stays on the config #007bff regardless of skin. Mermaid works around it by reading --bs-primary first; the token layer should agree with itself instead."
1364
+ acceptance:
1365
+ - "With theme_color.main set, switching skin changes --zer0-color-primary as well as --bs-primary (probe getComputedStyle on <html>)."
1366
+ - "Decide and document the precedence: skin over site theme_color (recommended) or the reverse — one rule, applied to every --zer0-color-* the mixin sets."
1367
+ - "A smoke test asserts --zer0-color-primary === --bs-primary after setSkin('neon')."
1368
+ - "before/after evidence committed"
1369
+ links: { issue: null, pr: null, roadmap: null }
1370
+ created: 2026-09-05
1371
+ updated: 2026-09-05
1372
+
1373
+ - id: T-049
1374
+ title: "test_core.sh: Liquid nested-tag check and gem-content check can never fail"
1375
+ status: open
1376
+ priority: P3
1377
+ area: tests
1378
+ risk: low
1379
+ effort: S
1380
+ source: audit
1381
+ summary: "Found while reviewing CI logs for PR #455: test/test_core.sh prints '[ERROR] Nested Liquid output tags found in _includes/navigation/sidebar-pagetree.html' on every run and still reports the Liquid validation as passed. Two defects: (1) the check is `grep -q \"{{.*{{\"`, which flags any line with two output tags — sidebar-pagetree.html:65 is `{{ _base }}{{ _section }}` inside a capture, valid Liquid — and the `return 1` sits inside a `find | while read` pipeline subshell, so it can never fail the function; (2) the gem-content check runs `tar -tzf` on the .gem, but a gem is an uncompressed tar (metadata.gz, data.tar.gz, checksums.yaml.gz), so gzip prints 'stdin: not in gzip format' four times and both branches always fall through to the 'Gem may not contain…' warnings without inspecting anything."
1382
+ acceptance:
1383
+ - "The nested-tag check only flags a genuinely nested output tag (e.g. `{{ a {{ b }} }}`), not two sibling tags on one line, and a positive match fails the test (no subshell swallowing the return)."
1384
+ - "The gem-content check lists data.tar.gz inside the .gem (`tar -xOf … data.tar.gz | tar -tzf -`) and asserts _layouts/ and assets/ are present; a gem missing them fails the test."
1385
+ - "./test/test_core.sh runs clean: no '[ERROR]' line on a passing run and no gzip/tar noise."
1386
+ links: { issue: null, pr: null, roadmap: null }
1387
+ created: 2026-09-05
1388
+ updated: 2026-09-05
1389
+
1390
+ - id: T-050
1391
+ title: "Visual Snapshots tier: LiveReload reloads the page mid-test because npm ci lands after Jekyll starts watching"
1392
+ status: open
1393
+ priority: P2
1394
+ area: tests
1395
+ risk: low
1396
+ effort: S
1397
+ source: audit
1398
+ summary: "The snapshots project shows a retried test on most CI runs — '[snapshots] › appearance-snapshot.spec.js › skin: <random> › homepage visual snapshot' fails with 'page.evaluate: Execution context was destroyed, most likely because of a navigation' and passes on retry (aqua on PR #455, mint on main 5ff38bf). Nothing on the homepage navigates; the likely trigger is Jekyll's LiveReload. test/update-snapshots.sh runs `docker compose up -d` (jekyll serve --watch --livereload, repo bind-mounted at /site) and only then starts the Playwright container, which runs `npm ci` into the same bind mount. jekyll-watch 2.2.1 registers an ignore pattern only for exclude paths that EXIST when serve starts (`next unless absolute_path.exist?` in listen_ignore_paths), and a fresh CI checkout has no node_modules/, so the thousands of files npm ci writes fire the watcher, the site regenerates, and LiveReload pushes a reload to every open page over localhost:35729 (reachable: the Playwright container uses --network host). Whichever skin is mid-step when the regeneration finishes fails; Playwright's CI retry (retries: 1) masks it, at the cost of one retry per run and a false 'flaky' signal that would hide a real regression."
1399
+ acceptance:
1400
+ - "Jekyll in the snapshot stack cannot reload the browser during a run: either node_modules/ exists before `docker compose up` (run `npm ci` first, or `mkdir -p node_modules`) or the test stack serves without --livereload (compose override or a JEKYLL_LIVERELOAD toggle)."
1401
+ - "Confirmed with the Playwright trace or `docker compose logs jekyll` showing no 'Regenerating' during a run."
1402
+ - "Ten consecutive CI runs of the snapshots project report 0 flaky tests."
1403
+ - "Root cause noted in the header of test/update-snapshots.sh so the ordering is not undone."
1404
+ links: { issue: null, pr: null, roadmap: null }
1405
+ created: 2026-09-05
1406
+ updated: 2026-09-05
1407
+
1408
+ - id: T-051
1409
+ title: "Preview-image engine: the xAI default model grok-2-image is retired — default to grok-imagine-image-2.0"
1410
+ status: open
1411
+ priority: P2
1412
+ area: infra
1413
+ risk: low
1414
+ effort: S
1415
+ source: issue
1416
+ summary: "Discovered while adding the xAI provider to the chat proxy and Site Builder (ZER0-087): scripts/lib/preview_generator.py's XAIProvider.default_model() still returns 'grok-2-image', which xAI has retired in favour of the Grok Imagine family (grok-imagine-image-2.0, per docs.x.ai release notes). A site with preview_images.provider: xai and no explicit model gets an upstream error. The Site Builder now writes preview_images.model explicitly for generated sites, so only the engine default (and the .env.example comment for IMAGE_MODEL) is stale. scripts/lib/ is CODEOWNERS-owned, so this is a human-review change."
1417
+ acceptance:
1418
+ - "XAIProvider.default_model() returns grok-imagine-image-2.0 and the provider table comment in the engine header matches."
1419
+ - "The image request keeps working with the current xAI response shape (data[0].url or b64_json)."
1420
+ - "scripts/lib/README.md / .env.example mention the new default."
1421
+ links: { issue: null, pr: null, roadmap: null }
1422
+ created: 2026-09-07
1423
+ updated: 2026-09-07
data/_data/consumers.yml CHANGED
@@ -44,6 +44,9 @@
44
44
  # version; tracked so a bump doesn't miss the config that
45
45
  # activates it
46
46
  # path_gem local path gem, unversioned (development only)
47
+ # gem_unconstrained `gem 'jekyll-theme-zer0'` with no version — resolves
48
+ # whatever RubyGems has at `bundle update` time; tracked
49
+ # only (like resolved_lockfile), never reports drift
47
50
  # ==============================================================================
48
51
 
49
52
  version: 1
@@ -117,6 +120,39 @@ consumers:
117
120
  kind: path_gem
118
121
  note: line 40 — dev checkout via ZER0_MISTAKES_PATH; never bumped
119
122
 
123
+ # ---------------------------------------------------------------------------
124
+ - repo: amr-bash/bash-365.com
125
+ mode: remote_theme_floating
126
+ site: https://bash-365.com
127
+ dispatch: false
128
+ note: >-
129
+ BASH Consulting's site, forked from bamr87/bashconsultants (which stays
130
+ registered above) and carrying the same three-stack shape: GitHub Pages
131
+ via remote_theme, Azure Static Web Apps via Gemfile.azure +
132
+ _config.azure.yml, local dev via a path gem. Unlike its parent, nothing
133
+ here carries a version any more — remote_theme is untagged and
134
+ Gemfile.azure names the gem with no constraint — so there is no pin for a
135
+ bump PR to rewrite. Declares its intentional forks in .theme-overrides.yml.
136
+ risk: >-
137
+ Unpinned on Pages; the Azure stack advances only when someone runs
138
+ `bundle update jekyll-theme-zer0`, so the two production stacks can
139
+ render different theme versions with nothing here to notice. Recommend
140
+ pinning remote_theme and constraining Gemfile.azure together and joining
141
+ the fan-out.
142
+ pins:
143
+ - file: _config.yml
144
+ kind: remote_theme
145
+ note: line 33, no tag — floats main
146
+ - file: Gemfile.azure
147
+ kind: gem_unconstrained
148
+ note: line 10 — no version; `bundle update jekyll-theme-zer0` advances it
149
+ - file: _config.azure.yml
150
+ kind: theme_name
151
+ note: line 3 — activates the gem; no version of its own
152
+ - file: Gemfile
153
+ kind: path_gem
154
+ note: line 59 — dev checkout via ZER0_MISTAKES_PATH; never bumped
155
+
120
156
  # ---------------------------------------------------------------------------
121
157
  - repo: year-of-ai/year-of-ai.github.io
122
158
  mode: remote_theme_pinned
@@ -139,20 +175,27 @@ consumers:
139
175
 
140
176
  # ---------------------------------------------------------------------------
141
177
  - repo: ai-world-view/ai-world-view.github.io
142
- mode: remote_theme_pinned
178
+ mode: remote_theme_floating
143
179
  site: https://ai-world-view.github.io
144
- dispatch: true
180
+ dispatch: false
145
181
  fans_out_to_members: true
146
182
  note: >-
147
183
  Same two-file hub shape as year-of-ai; members join by auto_discover, so
148
- the member count grows without this file changing.
184
+ the member count grows without this file changing. Was registered as
185
+ remote_theme_pinned until the 2026-09 fleet harmonization, but both its
186
+ _config.yml remote_theme and its hub.yml theme_repo carry NO tag — the
187
+ hub and every member it stamps float on this theme's main.
188
+ risk: >-
189
+ Unpinned, and an org hub: a theme break here reaches every auto-discovered
190
+ member site at once. Recommend pinning both files together and joining
191
+ the fan-out (dispatch: true) like year-of-ai.
149
192
  pins:
150
193
  - file: _config.yml
151
194
  kind: remote_theme
152
- note: line 35
195
+ note: line 36, no tag — floats main
153
196
  - file: _data/hub.yml
154
197
  kind: hub_registry
155
- note: "line 39 (pages.theme_repo) — re-roll members after bumping"
198
+ note: "line 39 (pages.theme_repo), no tag — members float too"
156
199
 
157
200
  # ---------------------------------------------------------------------------
158
201
  # The four entries below were missing entirely until the 2026-08 fleet audit.
data/_data/features.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  # zer0-mistakes Theme Features Registry
2
2
  # Comprehensive feature tracking for the zer0-mistakes Jekyll theme
3
- # Version: 1.26.0
4
- # Last Updated: 2026-07-17
3
+ # Version: 1.29.0
4
+ # Last Updated: 2026-09-07
5
5
 
6
6
  features:
7
7
  # ============================================================================
@@ -435,22 +435,25 @@ features:
435
435
 
436
436
  - id: ZER0-013
437
437
  title: "Mermaid Diagram Support"
438
- description: "Client-side Mermaid.js integration for 10+ diagram types. GitHub Pages compatible with no build plugins required"
438
+ description: "Client-side Mermaid.js diagrams for 10+ diagram types, rendered as accessible figures: a zoom / fullscreen / copy-source / SVG-export toolbar, accTitle captions, an error card that keeps the source visible, and colours derived from the live design tokens so diagrams follow the colour mode and skin. GitHub Pages compatible with no build plugins required"
439
439
  implemented: true
440
- version: "0.3.0"
441
- link: "/"
440
+ version: "1.30.0"
441
+ link: "/docs/features/mermaid-diagrams/"
442
442
  docs: "/docs/features/mermaid-diagrams/"
443
- tags: [mermaid, diagrams, visualization, documentation]
444
- date: 2025-01-27
443
+ tags: [mermaid, diagrams, visualization, documentation, accessibility, ui]
444
+ date: 2026-09-05
445
445
  provenance:
446
446
  introduced_in: "0.3.0"
447
447
  pr: null
448
448
  commit: "1a6184b"
449
449
  issue: null
450
450
  tests:
451
- - "test/test_core.sh"
451
+ - "test/visual/features/mermaid.spec.js"
452
452
  references:
453
453
  include: "_includes/components/mermaid.html"
454
+ script: "assets/js/mermaid-diagrams.js"
455
+ styles: "_sass/components/_mermaid.scss"
456
+ evidence: "test/visual/mermaid-evidence.mjs"
454
457
  config: "_config.yml"
455
458
  diagram_types:
456
459
  - "Flowchart (graph TD)"
@@ -1753,14 +1756,14 @@ features:
1753
1756
  includes:
1754
1757
  - "_includes/content/backlinks.html"
1755
1758
  - id: ZER0-060
1756
- title: "AI Chat Assistant (Claude + GitHub)"
1757
- description: "Claude-powered floating chat grounded in the current page: streaming replies, GitHub issue/PR actions (after confirmation), and a dev-only mode that edits the page source file live"
1759
+ title: "AI Chat Assistant (Claude or Grok + GitHub)"
1760
+ description: "Floating chat grounded in the current page, answered by Claude or Grok through the proxy: streaming replies, GitHub issue/PR actions (after confirmation), and a dev-only mode that edits the page source file live"
1758
1761
  implemented: true
1759
- version: "1.18.0"
1762
+ version: "1.30.0"
1760
1763
  link: "/docs/features/ai-chat-assistant/"
1761
1764
  docs: "/docs/features/ai-chat-assistant/"
1762
- tags: [ai, chatbot, claude, github, proxy, accessibility]
1763
- date: 2026-06-13
1765
+ tags: [ai, chatbot, claude, grok, github, proxy, accessibility]
1766
+ date: 2026-09-07
1764
1767
  provenance:
1765
1768
  introduced_in: "1.18.0"
1766
1769
  pr: 33
@@ -1771,7 +1774,7 @@ features:
1771
1774
  references:
1772
1775
  includes: ["_includes/components/ai-chat.html"]
1773
1776
  layouts: ["_layouts/root.html"]
1774
- scripts: ["assets/js/ai-chat.js", "templates/deploy/chat-proxy/worker.js", "templates/deploy/chat-proxy/dev-proxy.mjs", "templates/deploy/chat-proxy/page-store.mjs"]
1777
+ scripts: ["assets/js/ai-chat.js", "templates/deploy/chat-proxy/worker.js", "templates/deploy/chat-proxy/providers.js", "templates/deploy/chat-proxy/dev-proxy.mjs", "templates/deploy/chat-proxy/page-store.mjs"]
1775
1778
  config: "_config.yml"
1776
1779
  instructions: ".github/instructions/ai-chat.instructions.md"
1777
1780
 
@@ -1918,25 +1921,27 @@ features:
1918
1921
 
1919
1922
  - id: ZER0-067
1920
1923
  title: "Setup Wizard"
1921
- description: "Multi-step in-browser wizard that assembles a complete _config.yml and lets you download or copy it, lowering first-run setup friction"
1924
+ description: "Nine-step in-browser wizard that assembles a complete starter project — _config.yml, dev config, Gemfile, docker-compose, navigation, first pages — with per-file download and a self-extracting bundle; the form half of the Site Builder"
1922
1925
  implemented: true
1923
- version: "0.22.7"
1926
+ version: "1.30.0"
1924
1927
  link: "/setup/"
1925
- docs: "/docs/quickstart/bare-minimum/"
1928
+ docs: "/docs/features/site-builder/"
1926
1929
  tags: [setup, onboarding, configuration]
1927
- date: 2026-04-03
1930
+ date: 2026-09-05
1928
1931
  provenance:
1929
1932
  introduced_in: "0.22.7"
1930
1933
  pr: 51
1931
1934
  commit: "a70ae8a5"
1932
1935
  issue: null
1933
1936
  tests:
1934
- - na: "Client-side config generator; exercised manually and via the build"
1937
+ - "test/visual/features/setup-wizard.spec.js"
1935
1938
  references:
1936
1939
  include: "_includes/setup/wizard.html"
1937
1940
  scripts:
1938
1941
  - "assets/js/setup-wizard.js"
1942
+ styles: ["_sass/components/_setup-wizard.scss"]
1939
1943
  layout: "_layouts/setup.html"
1944
+ data: "_data/site_builder.yml"
1940
1945
 
1941
1946
  - id: ZER0-068
1942
1947
  title: "Table CSV Copy"
@@ -2219,7 +2224,7 @@ features:
2219
2224
  features:
2220
2225
  - "Zero-config default: explicit /favicon.ico link on every page (fixes silent 404s and baseurl project sites)"
2221
2226
  - "Optional SVG favicon, PNG sizes, apple-touch-icon, and web manifest links"
2222
- - "theme-color meta sourced from favicon.theme_color with fallback to theme_color.main design token"
2227
+ - "scheme-aware theme-color metas tracking --bs-body-bg (light #ffffff / dark #212529), emitted even with no config; favicon.theme_color pins a single value"
2223
2228
 
2224
2229
  - id: ZER0-080
2225
2230
  title: "Books Collection — Children's Picture-Book Publishing"
@@ -2413,3 +2418,124 @@ features:
2413
2418
  - "Volume↔weight conversion driven by _data/ingredient_densities.yml, overridable per ingredient with grams_per_cup"
2414
2419
  - "Baker's-percentage ratio table computed at build time, so percentages are correct with JavaScript disabled"
2415
2420
  - "Progressive enhancement: quantities render as authored by Jekyll; the control bar stays hidden until the script reveals it"
2421
+
2422
+ - id: ZER0-085
2423
+ title: "Visual Evidence Autogen"
2424
+ description: "CI produces a UI pull request's visual artifacts instead of only verifying them: before/after evidence from the PR's generator or a generic base-vs-head render, and 9-skin pixel baselines refreshed only when the reviewer agent judges the diff to be the change the PR describes"
2425
+ implemented: true
2426
+ version: "1.30.0"
2427
+ link: "/"
2428
+ docs: "/docs/development/testing/"
2429
+ tags: [ci-cd, testing, automation, ai, quality]
2430
+ date: 2026-09-05
2431
+ provenance:
2432
+ introduced_in: "1.30.0"
2433
+ pr: 462
2434
+ commit: "d0bfc0d1"
2435
+ issue: null
2436
+ tests:
2437
+ - "scripts/ci/test_visual_evidence_autogen.py"
2438
+ references:
2439
+ workflow: ".github/workflows/visual-evidence-autogen.yml"
2440
+ scripts:
2441
+ - "scripts/ci/visual_evidence_autogen.py"
2442
+ - "test/visual/pr-evidence.mjs"
2443
+ - "test/visual/snapshot-diff-montage.mjs"
2444
+ - "test/update-snapshots.sh"
2445
+ agent: ".claude/agents/visual-evidence-reviewer.md"
2446
+ docs: "docs/systems/continuous-evolution.md"
2447
+ features:
2448
+ - "Runs on every same-repo PR event: plans from the diff, brings Jekyll up with docker compose, and renders inside the same jammy Playwright image the snapshot gate compares with"
2449
+ - "Evidence from the PR's own test/visual/*-evidence.mjs generators, or from the generic base-vs-head generator that renders the base branch and the head side by side — no hand-written unfixCss needed"
2450
+ - "Pixel baselines are refreshed only on an 'intentional' verdict from the visual-evidence-reviewer agent, which views the expected | actual | diff montage; a code step disposes, the model only proposes (#417)"
2451
+ - "Loop guard on its own [visual-autogen] commits, a three-commit budget per PR, per-folder manifests so author-made evidence is never overwritten, kill switch VISUAL_EVIDENCE_AUTOGEN_ENABLED=false, and the evidence gate's opt-out labels"
2452
+ - "One sticky PR comment with the montages and the verdict; render output uploaded as an artifact on every run; the evidence gate now requires generated proof and ci-self-repair hands a red Visual Snapshots job to this lane"
2453
+
2454
+ - id: ZER0-086
2455
+ title: "Claude-Guided Site Builder"
2456
+ description: "An embedded Claude session that rides alongside the setup wizard: it sees every answer, fills in the forms, checks the machine, reads the theme's real source, writes the generated project to disk and starts Docker — through the local dev proxy, with a confirmation card before every action"
2457
+ implemented: true
2458
+ version: "1.30.0"
2459
+ link: "/setup/"
2460
+ docs: "/docs/features/site-builder/"
2461
+ tags: [ai, claude, grok, setup, onboarding, docker, proxy]
2462
+ date: 2026-09-07
2463
+ provenance:
2464
+ introduced_in: "1.30.0"
2465
+ pr: null
2466
+ commit: "331ae16c"
2467
+ issue: null
2468
+ tests:
2469
+ - "test/visual/features/setup-wizard.spec.js"
2470
+ - "test/test_wizard_store.mjs"
2471
+ references:
2472
+ includes:
2473
+ - "_includes/setup/wizard.html"
2474
+ - "_includes/setup/claude-session.html"
2475
+ - "_includes/setup/prereq-checklist.html"
2476
+ scripts:
2477
+ - "assets/js/site-builder.js"
2478
+ - "templates/deploy/chat-proxy/wizard-store.mjs"
2479
+ - "templates/deploy/chat-proxy/dev-proxy.mjs"
2480
+ - "test/visual/site-builder-walkthrough.mjs"
2481
+ - "test/visual/site-builder-scenarios.mjs"
2482
+ data: "_data/site_builder.yml"
2483
+ config: "_config.yml"
2484
+ instructions: ".github/instructions/ai-chat.instructions.md"
2485
+ pages:
2486
+ - "pages/_quickstart/site-builder.md"
2487
+ - "pages/_docs/features/site-builder.md"
2488
+ components:
2489
+ - "Connect step — detects the dev proxy, shows the three commands to connect (claude setup-token → .env → node --env-file), re-checks every 15 s"
2490
+ - "Prerequisites — live Docker/Git/gh/VS Code/Node/Claude CLI checks through a fixed command table, per-OS install commands from machine-setup, manual toggles offline"
2491
+ - "Tools — get/set wizard fields, go to step, get/override generated files, read theme source, list theme dirs, search the docs index, resolve target, write project, docker compose up/ps/logs/down, check the site is live"
2492
+ - "Context propagation — the whole wizard state, field schema and generated-file list are in the system prompt on every turn; the form is the single source of truth"
2493
+ - "Safety — proxy-only (no credential in the page), escape-first rendering, confirmation cards for every mutation, scaffold confined to a new folder beside the theme"
2494
+ - "Validation — test/visual/site-builder-walkthrough.mjs samples a random brief per site type (site-builder-scenarios.mjs), drives the wizard on video, builds the site with Docker and asserts routes/title/skin; replayable by seed"
2495
+ - "Site plan — plan_schema in _data/site_builder.yml (JSON-Schema subset, validated in the browser) describes landing templates/sections, navigation style + sidebar, palette/font/radius overrides and example pages; set_site_plan applies it behind a confirmation card and the generators emit index.md + _data/landing.yml, navigation data, assets/css/user-overrides.css + _includes/custom/head.html and one file per planned page"
2496
+ - "Providers, bring-your-own token, open sessions, project editing and image generation — see ZER0-087"
2497
+
2498
+ - id: ZER0-087
2499
+ title: "Bring-Your-Own AI Provider (Claude or Grok) and Open Site Builder Sessions"
2500
+ description: "The Site Builder and chat proxy answer with Claude (Anthropic) or Grok (xAI): users paste their own token on the Connect step, pick a model and an image renderer, and run a guided or open session that can also modify an existing site file by file and render images with Grok Imagine"
2501
+ implemented: true
2502
+ version: "1.30.0"
2503
+ link: "/setup/"
2504
+ docs: "/docs/features/site-builder/"
2505
+ tags: [ai, claude, grok, xai, setup, onboarding, proxy, images]
2506
+ date: 2026-09-07
2507
+ provenance:
2508
+ introduced_in: "1.30.0"
2509
+ pr: null
2510
+ commit: "b43a2bf6"
2511
+ issue: null
2512
+ tests:
2513
+ - "test/test_providers.mjs"
2514
+ - "test/test_wizard_store.mjs"
2515
+ - "test/visual/features/setup-wizard.spec.js"
2516
+ references:
2517
+ includes:
2518
+ - "_includes/setup/wizard.html"
2519
+ - "_includes/setup/claude-session.html"
2520
+ scripts:
2521
+ - "assets/js/site-builder.js"
2522
+ - "assets/js/setup-wizard.js"
2523
+ - "templates/deploy/chat-proxy/providers.js"
2524
+ - "templates/deploy/chat-proxy/credential-store.mjs"
2525
+ - "templates/deploy/chat-proxy/worker.js"
2526
+ - "templates/deploy/chat-proxy/dev-proxy.mjs"
2527
+ - "templates/deploy/chat-proxy/wizard-store.mjs"
2528
+ - "test/visual/site-builder-providers-evidence.mjs"
2529
+ data: "_data/site_builder.yml"
2530
+ config: "_config.yml"
2531
+ instructions: ".github/instructions/ai-chat.instructions.md"
2532
+ pages:
2533
+ - "pages/_docs/features/site-builder.md"
2534
+ - "pages/_quickstart/site-builder.md"
2535
+ components:
2536
+ - "Provider layer (providers.js, Worker + Node) — Anthropic Messages dialect translated to and from xAI's OpenAI-compatible chat API, streaming tool calls included, so ai-chat.js, site-builder.js and the feedback triage are unchanged; CHAT_PROVIDER / CHAT_MODEL / XAI_CHAT_MODEL pinned server-side, client models accepted only from the selected provider's family"
2537
+ - "Connect step — Claude and Grok cards with masked key state, a password token field posted once to the localhost proxy (memory only, probed upstream, optional .env save with mode 600, Forget), model catalog, image renderer (Grok Imagine / OpenAI Images) and guided vs open session; the dev proxy starts without a credential"
2538
+ - "Open session — chat-driven, any order, up to 24 tool rounds per turn with a Stop button; interrupted tool calls get synthetic results so the history stays valid"
2539
+ - "Project session — list/open an existing site under WIZARD_TARGET_ROOT, tree/read, write/edit (unique snippet)/delete text files behind confirmation cards, git status/diff/log/init, jekyll build inside the container"
2540
+ - "Image generation — generate_image renders with grok-imagine-image-2.0 (or gpt-image-2) into assets/ (PNG/JPEG/WebP sniffed, 8 MB cap) with a thumbnail card; generated sites carry ai_chat.provider, preview_images and the matching .env.example keys"
2541
+ - "Validation — test/test_providers.mjs (mock xAI + Anthropic upstreams), test/test_wizard_store.mjs (project + asset rules), setup-wizard.spec.js (mocked proxy: connect as Grok, token never stored, open mode, existing sites), evidence in test/visual/evidence/site-builder-providers/"