@cyberskill/design 1.2.0 → 1.3.9

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 (232) hide show
  1. package/DESIGN.md +11 -9
  2. package/README.md +28 -24
  3. package/SKILL.md +18 -9
  4. package/THIRD-PARTY-NOTICES.md +35 -0
  5. package/VERSION +1 -1
  6. package/_ds_bundle.js +701 -1342
  7. package/_esm/cs.mjs +2 -2
  8. package/_esm/react.mjs +6 -1
  9. package/_vendor/NOTICE.md +16 -0
  10. package/_vendor/babel/README.md +7 -0
  11. package/_vendor/babel/babel.min.js +4 -0
  12. package/_vendor/react/README.md +3 -0
  13. package/_vendor/react/react-dom.production.min.js +1 -0
  14. package/_vendor/react/react.production.min.js +1 -0
  15. package/assets/aurora-hoa.webp +0 -0
  16. package/assets/aurora-kim.webp +0 -0
  17. package/assets/aurora-moc.webp +0 -0
  18. package/assets/aurora-tho.webp +0 -0
  19. package/assets/aurora-thuy.webp +0 -0
  20. package/base/ai.css +8 -3
  21. package/base/collections.css +10 -4
  22. package/base/components.css +5 -2
  23. package/base/controls.css +58 -21
  24. package/base/data.css +1 -1
  25. package/base/feedback.css +9 -2
  26. package/base/forms.css +1 -1
  27. package/base/glass.css +1 -1
  28. package/base/interaction.css +6 -2
  29. package/base/navigation.css +1 -1
  30. package/base/reset.css +7 -1
  31. package/base/responsive.css +13 -12
  32. package/base/shell.css +8 -2
  33. package/components/_i18n/i18n.js +28 -3
  34. package/components/_i18n/strings.js +42 -24
  35. package/components/ai/ChatMessage.d.ts +2 -0
  36. package/components/ai/ChatMessage.jsx +8 -4
  37. package/components/ai/ConfidenceMeter.d.ts +2 -0
  38. package/components/ai/HumanReviewGate.d.ts +2 -0
  39. package/components/ai/PromptInput.d.ts +2 -0
  40. package/components/ai/TypingIndicator.d.ts +2 -0
  41. package/components/ai/ai-conversation.card.html +3 -3
  42. package/components/ai/ai-lumi.card.html +3 -3
  43. package/components/ai/ai.card.html +3 -3
  44. package/components/brand/brand.card.html +3 -3
  45. package/components/button/buttons.card.html +3 -3
  46. package/components/data/Image.jsx +18 -2
  47. package/components/data/Sortable.d.ts +5 -1
  48. package/components/data/Sortable.jsx +42 -9
  49. package/components/data/Sortable.prompt.md +4 -2
  50. package/components/data/Terminal.jsx +3 -2
  51. package/components/data/Tooltip.d.ts +2 -0
  52. package/components/data/Tooltip.jsx +6 -3
  53. package/components/data/Tree.d.ts +2 -1
  54. package/components/data/Tree.jsx +137 -16
  55. package/components/data/Tree.prompt.md +1 -1
  56. package/components/data/collections.card.html +3 -3
  57. package/components/data/data.card.html +3 -3
  58. package/components/datatable/DataTable.d.ts +24 -1
  59. package/components/datatable/DataTable.jsx +78 -5
  60. package/components/datatable/DataTable.prompt.md +2 -1
  61. package/components/datatable/datatable.card.html +20 -16
  62. package/components/dialog/dialog.card.html +3 -3
  63. package/components/feedback/Alert.d.ts +2 -0
  64. package/components/feedback/Alert.jsx +8 -2
  65. package/components/feedback/EmptyState.d.ts +2 -0
  66. package/components/feedback/EmptyState.jsx +6 -3
  67. package/components/feedback/ProgressBar.d.ts +2 -0
  68. package/components/feedback/ProgressBar.jsx +6 -3
  69. package/components/feedback/Toast.jsx +15 -1
  70. package/components/feedback/Toast.prompt.md +2 -1
  71. package/components/feedback/feedback-2.card.html +3 -3
  72. package/components/feedback/feedback.card.html +3 -3
  73. package/components/forms/Cascader.jsx +7 -2
  74. package/components/forms/FileUpload.d.ts +2 -0
  75. package/components/forms/Form.d.ts +3 -1
  76. package/components/forms/Form.jsx +9 -1
  77. package/components/forms/Form.prompt.md +1 -1
  78. package/components/forms/Mentions.d.ts +1 -1
  79. package/components/forms/Mentions.jsx +59 -7
  80. package/components/forms/Mentions.prompt.md +3 -1
  81. package/components/forms/Rating.d.ts +3 -2
  82. package/components/forms/Rating.jsx +34 -3
  83. package/components/forms/Rating.prompt.md +1 -1
  84. package/components/forms/Select.d.ts +2 -0
  85. package/components/forms/Select.jsx +6 -2
  86. package/components/forms/Slider.d.ts +2 -0
  87. package/components/forms/Slider.jsx +5 -2
  88. package/components/forms/Switch.d.ts +2 -0
  89. package/components/forms/Switch.jsx +7 -9
  90. package/components/forms/Toggle.d.ts +2 -0
  91. package/components/forms/Toggle.jsx +14 -2
  92. package/components/forms/forms-2.card.html +3 -3
  93. package/components/forms/forms.card.html +3 -3
  94. package/components/icon/Icon.d.ts +1 -1
  95. package/components/icon/Icon.prompt.md +1 -1
  96. package/components/icon/icon.card.html +3 -3
  97. package/components/logo/logo.card.html +3 -3
  98. package/components/navigation/CommandPalette.d.ts +2 -0
  99. package/components/navigation/Menu.d.ts +2 -0
  100. package/components/navigation/Menu.jsx +60 -6
  101. package/components/navigation/Steps.d.ts +2 -0
  102. package/components/navigation/Steps.jsx +6 -3
  103. package/components/navigation/Tabs.d.ts +2 -0
  104. package/components/navigation/Tabs.jsx +6 -3
  105. package/components/navigation/Toolbar.d.ts +3 -2
  106. package/components/navigation/Toolbar.jsx +117 -11
  107. package/components/navigation/Toolbar.prompt.md +1 -1
  108. package/components/navigation/navigation.card.html +3 -3
  109. package/components/navigation/shell.card.html +3 -3
  110. package/components/overlays/ContextMenu.d.ts +2 -0
  111. package/components/overlays/ContextMenu.jsx +6 -3
  112. package/components/overlays/Drawer.d.ts +2 -0
  113. package/components/overlays/alertdialog.card.html +3 -3
  114. package/components/overlays/overlays.card.html +3 -3
  115. package/components/textfield/textfield.card.html +3 -3
  116. package/dist/styles.min.css +312 -64
  117. package/docs/benchmark-rubric.md +2 -2
  118. package/docs/ci-cd.md +18 -13
  119. package/docs/consumer-grant.md +4 -1
  120. package/docs/consuming.md +16 -12
  121. package/docs/contrast-report.md +81 -1
  122. package/docs/conventions.md +18 -5
  123. package/docs/decisions.md +41 -3
  124. package/docs/deploy.md +19 -6
  125. package/docs/design-styles.md +2 -2
  126. package/docs/doctrine.md +51 -0
  127. package/docs/figma.md +2 -0
  128. package/docs/live-hub.md +3 -1
  129. package/docs/products.md +1 -1
  130. package/docs/quality-gates.md +24 -12
  131. package/docs/release-notes.md +1 -1
  132. package/docs/release-runbook.md +78 -0
  133. package/docs/storybook.md +3 -3
  134. package/docs/sync.md +8 -8
  135. package/docs/template-schema-v2.md +1 -1
  136. package/docs/vi/benchmark-rubric.md +2 -2
  137. package/docs/vi/ci-cd.md +17 -14
  138. package/docs/vi/consumer-grant.md +4 -1
  139. package/docs/vi/consuming.md +16 -12
  140. package/docs/vi/contrast-report.md +81 -1
  141. package/docs/vi/conventions.md +19 -6
  142. package/docs/vi/decisions.md +40 -3
  143. package/docs/vi/deploy.md +19 -6
  144. package/docs/vi/design-styles.md +1 -1
  145. package/docs/vi/doctrine.md +51 -0
  146. package/docs/vi/figma.md +2 -0
  147. package/docs/vi/live-hub.md +3 -1
  148. package/docs/vi/products.md +1 -1
  149. package/docs/vi/quality-gates.md +23 -12
  150. package/docs/vi/release-notes.md +1 -1
  151. package/docs/vi/release-runbook.md +78 -0
  152. package/docs/vi/storybook.md +3 -3
  153. package/docs/vi/sync.md +7 -7
  154. package/docs/vi/template-schema-v2.md +1 -1
  155. package/docs/viewer.html +16 -5
  156. package/fonts/OFL.txt +98 -0
  157. package/guidelines/atomic-view.html +2 -2
  158. package/guidelines/brand-imagery.html +1 -1
  159. package/guidelines/elements-variants.html +5 -5
  160. package/guidelines/spacing-breakpoints.html +2 -1
  161. package/guidelines/surfaces-glass.html +1 -1
  162. package/llms.txt +18 -11
  163. package/package.json +28 -8
  164. package/templates/app-shell/AppShell.dc.html +3 -3
  165. package/templates/app-shell/content-schema.json +7 -0
  166. package/templates/article/Article.dc.html +3 -3
  167. package/templates/article/content-schema.json +7 -0
  168. package/templates/auth/Auth.dc.html +26 -10
  169. package/templates/auth/content-schema.json +25 -0
  170. package/templates/dashboard/Dashboard.dc.html +4 -4
  171. package/templates/dashboard/content-schema.json +7 -0
  172. package/templates/delivery-change-note/DeliveryChangeNote.dc.html +2 -2
  173. package/templates/delivery-runbook/DeliveryRunbook.dc.html +2 -2
  174. package/templates/email-safe/email-announcement.html +2 -2
  175. package/templates/email-safe/email-dunning.html +2 -2
  176. package/templates/email-safe/email-investor.html +2 -2
  177. package/templates/email-safe/email-launch.html +2 -2
  178. package/templates/email-safe/email-newsletter.html +2 -2
  179. package/templates/email-safe/email-status.html +2 -2
  180. package/templates/email-safe/email-transactional.html +2 -2
  181. package/templates/finance-dunning-email/FinanceDunningEmail.dc.html +2 -2
  182. package/templates/finance-expense-report/FinanceExpenseReport.dc.html +2 -2
  183. package/templates/finance-invoice/FinanceInvoice.dc.html +2 -2
  184. package/templates/finance-quote/FinanceQuote.dc.html +4 -4
  185. package/templates/hr-interview-kit/HrInterviewKit.dc.html +1 -1
  186. package/templates/marketing-case-study/MarketingCaseStudy.dc.html +1 -1
  187. package/templates/marketing-page/MarketingPage.dc.html +3 -3
  188. package/templates/marketing-page/content-schema.json +1 -0
  189. package/templates/settings/Settings.dc.html +3 -3
  190. package/templates/settings/content-schema.json +7 -0
  191. package/tokens/element-seeds.json +2 -2
  192. package/tokens/elements.css +193 -19
  193. package/tokens/native/CSTokens.kt +3 -2
  194. package/tokens/native/CSTokens.swift +3 -2
  195. package/tokens/native/cs_tokens.dart +3 -2
  196. package/tokens/provenance.json +8 -8
  197. package/tokens/spacing.css +2 -1
  198. package/tokens/tokens.dtcg.json +19 -14
  199. package/tokens/tokens.js +16 -15
  200. package/tokens/tokens.json +15 -14
  201. package/ui_kits/deck/index.html +1 -1
  202. package/ui_kits/status-hub/StatusHub.jsx +1 -1
  203. package/ui_kits/status-hub/login.html +52 -10
  204. package/ui_kits/status-hub/project.html +1 -1
  205. package/ui_kits/status-hub/settings.html +1 -1
  206. package/ui_kits/website/Website.jsx +1 -1
  207. package/ui_kits/website/careers.html +2 -2
  208. package/ui_kits/website/chat.html +1 -1
  209. package/ui_kits/website/site.css +1 -1
  210. package/ui_kits/website/work.html +2 -2
  211. package/assets/aurora-hoa.png +0 -0
  212. package/assets/aurora-kim.png +0 -0
  213. package/assets/aurora-moc.png +0 -0
  214. package/assets/aurora-thuy.png +0 -0
  215. package/docs/decisions/container-query-migration.md +0 -18
  216. package/docs/decisions/overlay-manager-design.md +0 -101
  217. package/docs/plans/cyberskill-design-system-audit-and-12-month-evolution-plan.md +0 -1490
  218. package/docs/status/assets/favicon.svg +0 -5
  219. package/docs/status/assets/status-legacy.css +0 -399
  220. package/docs/status/assets/status-legacy.js +0 -505
  221. package/docs/status/assets/status.css +0 -644
  222. package/docs/status/assets/status.js +0 -1308
  223. package/docs/status/data/status-feed.json +0 -1
  224. package/docs/status/data/task/TASK-REL-001.js +0 -1
  225. package/docs/status/data/task/TASK-REL-002.js +0 -1
  226. package/docs/status/index.html +0 -46
  227. package/docs/status/roadmap.html +0 -4
  228. package/docs/status/status-legacy.html +0 -122
  229. package/docs/tasks/BACKLOG.md +0 -26
  230. package/docs/tasks/_state/commit-links.yaml +0 -14
  231. package/docs/tasks/release/TASK-REL-001-launch-1-1-0/spec.md +0 -55
  232. package/docs/tasks/release/TASK-REL-002-republish-1-1-1/spec.md +0 -54
@@ -0,0 +1,51 @@
1
+ # Doctrine
2
+
3
+ Normative rules for extending and verifying the CyberSkill Design System. Host-specific files (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`) are shims that point here. Consumers start at `SKILL.md` and the Storybook **Docs** sidebar at `design.cyberskill.world`. Published on Storybook **Docs** at `design.cyberskill.world`.
4
+
5
+ ## When to use
6
+
7
+ - You are adding or changing an element, variant, icon, component, token role, language, or template pattern.
8
+ - You are verifying a change before calling it done.
9
+ - You need the immutables that must never be redesigned ad hoc.
10
+
11
+ ## Non-goals
12
+
13
+ This file is not a changelog, not a product registry, and not a consume guide. Product → element mappings live in `docs/products.md`. Adoption paths live in `docs/consuming.md`.
14
+
15
+ ## Expansion rule
16
+
17
+ When **anything** in this system grows, update **every deliverable in the same change**:
18
+
19
+ 1. Tokens and source (`tokens/`, component `.jsx` + `.d.ts` + `.prompt.md`).
20
+ 2. Specimen cards (guidelines plus the component group card) **and any related guideline pages**.
21
+ 3. **All** templates (tweak enums, EL/EX maps, swept accents).
22
+ 4. UI kits — Thổ-faithful kit pages; axis demos via Storybook toolbar and Atomic View (Identity Lab is retired).
23
+ 5. Docs: README (counts follow the compiler), `SKILL.md`, this file, `docs/conventions.md`, **and every related document the change touches** (kit READMEs, `docs/products.md`, `docs/contrast-report.md` regeneration after token changes). Publish the same pages through Storybook Docs (see `docs/storybook.md`). **`VERSION` auto-bumps on push to `main`** from Conventional Commits (`.github/workflows/version.yml` → tag `v*` → `npm-publish.yml`); the owner may still force a bump via `Release-As:` / `workflow_dispatch`. **Do not maintain a changelog file** — LAUNCHED at **1.1.0**; pin tracks `VERSION`. Continuity is git history plus curated Release Notes.
24
+ 6. Browsable and health surfaces: a new or changed component gets an Atomic View story in `guidelines/atomic-view.html` (plus a live playground if it has tweakable props — `_audit/story-coverage.html` enforces the story) and behavior coverage in `_audit/component-behavior-test.html` if interactive; any new axis, tool, or tab is wired into `_audit/index.html` and Storybook **Status** (full-bleed `_audit/run.html` — `dashboard.html` is redirect-only); the matching deterministic gate is added or updated (`contrast-guard` for new colour rules, `token-contract` plus the contrast matrix for tokens, `story-coverage` for components, `docs-storybook-coverage` for published docs).
25
+
26
+ **Gate:** `check_design_system` clean (compiler sessions only) **plus** `_audit/run.html` (all fast gates) green **plus** `docs-consistency` green **plus** a grep for the old enum or list to prove nothing was left behind. On a portable clone, the equivalent is the fast board plus `npm run test:unit`.
27
+
28
+ Documented scope boundaries (doctrine, not gaps): UI-kit pages remain Thổ-faithful recreations; bilingual EN·VN covers emails plus team, legal, and finance docs (client and media collateral is EN-first); text never sits on the mid-tone `-accent`.
29
+
30
+ ## Verification depth
31
+
32
+ Deep checks, never surface spot-checks. Cover the **whole set and every relevant state** — not a sample. Prefer deterministic, programmatic scans that touch **every** item (for example EN/VI key-parity, hole-coverage, and leak scan across all templates; computed-style and overflow probes at every breakpoint via the `_audit/` harnesses using `__dcSetProps` for language and the `__dc_theme` postMessage for theme), then add representative visual or export confirmation on top. A few screenshots are evidence, not proof. Never call work verified because it was “spot-checked” when a complete check is feasible; if a full check truly is not feasible, say so explicitly and state what was and was not covered. Language, theme, and responsive states each get their own pass — one language, width, or theme rendering cleanly is not evidence for the others.
33
+
34
+ ## Immutables
35
+
36
+ | Immutable | Value |
37
+ |---|---|
38
+ | Slogan | *Turn Your Will Into Real* / *Hiện Thực Hoá Ý Chí* |
39
+ | Primary brand | Umber `#45210E` |
40
+ | Primary accent | Ochre `#F4BA17` |
41
+ | Voice | warm · direct · honest · respectful (all four at once) |
42
+ | Language | Vietnamese-first; every UI string ships an EN + VN pair |
43
+ | Accessibility floor | APCA Lc ≥ 75 body text; focus rings never removed; ≥ 44px touch targets |
44
+ | Axes | Theme × Element × Language × Style (independent) |
45
+ | Style pack | liquid-glass (sole pack; absent ≡ default) |
46
+
47
+ One accent per surface. Semantic statuses and the composite focus indicator (text-primary contour + ochre halo) are never elemental. Lumi stays golden in every element.
48
+
49
+ ## Published documentation
50
+
51
+ Operator and entrance docs are canonical as markdown in this repository. They are **also** required on the live Storybook site: every tracked page must appear in the Docs sidebar and in the Documentation Library (`docs/viewer.html`). Repo-only documentation that is not in that published set is a defect, caught by `docs-storybook-coverage` and `docs-link-check`.
package/docs/figma.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Figma / Tokens Studio notes
2
2
 
3
+
4
+ Published on Storybook **Docs** at `design.cyberskill.world`.
3
5
  ## What ships in-repo
4
6
  - Design tokens in CSS + DTCG (`tokens/tokens.dtcg.json`) with native Swift/Kotlin/Flutter mirrors.
5
7
  - UI kits under `ui_kits/` are HTML recreations that stay pixel-faithful to the brand doctrine (Thổ-first kits; axis demos in Storybook / Atomic View).
package/docs/live-hub.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Live hub = Storybook
2
2
 
3
+ Published on Storybook **Docs** at `design.cyberskill.world`.
4
+
3
5
  ## Decision
4
6
 
5
7
  **Storybook is the single live interactive hub** for operators on `design.cyberskill.world`. There is no separate Live View page and no separate HTML dashboard product shell. Production **`/`** is Storybook.
@@ -8,7 +10,7 @@
8
10
 
9
11
  | Group | Role |
10
12
  |---|---|
11
- | **Docs** | Public MDX guides (consuming, deploy, conventions, styles, products, schema, Figma, contrast, voice, axes) |
13
+ | **Docs** | Published operator docs: **Start** (Introduction, README, SKILL, Contributing, llms, Library) · **Guides** (consuming, grant, deploy, schema, conventions, styles, products, Figma, contrast, storybook, live-hub, release runbook, benchmark, …) · **Maintainers** (doctrine, decisions, CI/CD, quality gates, sync). Curated MDX plus one sidebar entry per tracked page. EN·VI via the Documentation Library (`/docs/viewer.html`) |
12
14
  | **Foundations** | Colors, typography, spacing, elevation, motion, elements |
13
15
  | **Components** | Full CSF library |
14
16
  | **Release Notes** | Curated product prose (**no CHANGELOG.md**) |
package/docs/products.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Product registry — element mapping
2
2
 
3
- > **Locked** (Jul 2026). Canonical product → element registry for agents and kits. Do **not** invent new product → element assignments; add or change rows only via a maintainer decision in `docs/decisions.md`.
3
+ > **Locked** (Jul 2026). Canonical product → element registry for agents and kits. Do **not** invent new product → element assignments; add or change rows only via a maintainer decision in `docs/decisions.md`. Published on Storybook **Docs** at `design.cyberskill.world`.
4
4
 
5
5
  **Source of truth.** Maps CyberSkill portfolio products to Ngũ Hành element packs. One element per product; secondary accents only in gradient washes along Tương sinh.
6
6
 
@@ -1,10 +1,10 @@
1
1
  # Quality gates — the benchmark reference
2
2
 
3
- Every deterministic quality gate in the system, what it asserts, its pass criterion, whether it blocks (hard) or informs (advisory), and where it runs.
3
+ Every deterministic quality gate in the system, what it asserts, its pass criterion, whether it blocks (hard) or informs (advisory), and where it runs. Published on Storybook **Docs** at `design.cyberskill.world`.
4
4
 
5
- **Where gates run.** *Fast board CI* = the `fast-gates` job in `.github/workflows/design-system-gates.yml`, which serves the repo and drives `_audit/run.html` headless via `_audit/ci/run-gates.mjs` (every push/PR + nightly + manual) — new board rows are picked up automatically. Two gates additionally run standalone as *merge blockers* (`docs-consistency-blocker` job, via `_audit/ci/run-single-gate.mjs`). *Whole-set CI* = the `whole-set-audits` job (every push/PR + nightly — owner decision B). *Unit test* = `npm run test:unit` in the `unit-tests` job (plain Node, no browser). *Node pre-checks* = the `node-prechecks` job (browser-free authorities: bundle freshness, DESIGN.md freshness) plus the `token-provenance` job. Every browser gate publishes a verdict global (`window.__*`) that the headless runners read.
5
+ **Where gates run.** *Fast board CI* = the `fast-gates` job in `.github/workflows/design-system-gates.yml`, which serves the repo and drives `_audit/run.html` headless via `_audit/ci/run-gates.mjs` (every push/PR + nightly + manual) — new board rows are picked up automatically. Two gates additionally run standalone as *merge blockers* (`docs-consistency-blocker` job, via `_audit/ci/run-single-gate.mjs`). *Whole-set CI* = the `whole-set-audits` job (every push/PR + nightly — owner decision B). *Unit test* = `npm run test:unit` in the `unit-tests` job (plain Node, no browser). *Node pre-checks* = the `node-prechecks` job (browser-free authorities: bundle freshness, DESIGN.md freshness, styles.min.css + contrast-report freshness, manifest coverage) plus the `token-provenance` job. *Storybook CI* = the `storybook-build` job (`build:storybook` + freshness `--require`). Every browser gate publishes a verdict global (`window.__*`) that the headless runners read.
6
6
 
7
- ## Fast board — 39 gates in `_audit/run.html`
7
+ ## Fast board — 42 gates in `_audit/run.html`
8
8
 
9
9
  Benchmark principles (WCAG · APCA · OKLCH · DTCG · CDS doctrine + style expansion): [`docs/benchmark-rubric.md`](benchmark-rubric.md).
10
10
 
@@ -13,8 +13,11 @@ Benchmark principles (WCAG · APCA · OKLCH · DTCG · CDS doctrine + style expa
13
13
  | Contrast guard | `_audit/contrast-guard.html` | No base rule paints umber on a themeable surface without a dark override; every semantic text×surface pair scores in light and dark | 0 unshielded rules and 0 failing pairs (`__contrastguard`) | Hard | Fast board CI |
14
14
  | Axes guard | `_audit/axis-guard.html` | No live source reintroduces the retired Expression/Density product surface | 0 hits across manifest-indexed sources (`__axisguard`) | Hard | Fast board CI |
15
15
  | Manifest CSS paths | `_audit/manifest-css-guard.html` | Every `_ds_manifest.json` `globalCssPaths` entry exists as raw CSS; every `styles.css` `@import` is listed | 0 missing / 0 unlisted (`__cssguard`) | Hard | Fast board CI |
16
- | Docs consistency | `_audit/docs-consistency.html` | Every count claim in README/SKILL/llms.txt matches the compiler manifest; audit prose card-count claims (`_audit/index` / README / namespace-portability) match `manifest.cards`; `VERSION` is semver and `package.json` matches it (LAUNCHED 1.1.0; auto-bump on main); no changelog-file reference; stale-phrase blacklist (the retired suite/pack counts the Jul 2026 audit removed) clean across README/SKILL/llms + `docs/*.md` (historical notes under `_audit/archive/` are not scanned); `DESIGN.md` exists with front-matter version = `VERSION`; agent routing honesty — Claude path cites `_esm/cs.mjs` + bundle prefix; Stitch path forbids `*.dc.html` as SoT; package name `@cyberskill/design` | 0 mismatched claims, 0 blacklist hits, VERSION sync + stamp + routing intact (`__docs`) | Hard | Fast board CI + merge blocker |
16
+ | Docs consistency | `_audit/docs-consistency.html` | Every count claim in README/SKILL/llms.txt matches the compiler manifest; audit prose card-count claims (`_audit/index` / README / namespace-portability) match `manifest.cards`; `VERSION` is semver and `package.json` matches it (LAUNCHED 1.1.0; auto-bump on main); no changelog-file reference; stale-phrase blacklist (the retired suite/pack counts the Jul 2026 audit removed) clean across README/SKILL/llms + `docs/*.md` (historical notes under `_audit/archive/` are not scanned); `DESIGN.md` exists with front-matter version = `VERSION`; agent routing honesty — SKILL/llms cite `_esm/cs.mjs` + bundle prefix; Stitch path forbids `*.dc.html` as SoT; package name `@cyberskill/design`; doctrine↔source parity — 10 accent roles incl. `on-strong`, full depth scale, default lang `vi` vs `i18n.js`, breakpoint CSS↔JSON, `base/` depth fallbacks vs `elevation.css` | 0 mismatched claims, 0 blacklist hits, VERSION sync + stamp + routing + doctrine parity intact (`__docs`) | Hard | Fast board CI + merge blocker |
17
+ | Asset-weight budget | `_audit/asset-weight-budget.html` | Elemental aurora WebPs (`assets/aurora-{tho,hoa,thuy,moc,kim}.webp`) stay under regression ceilings (≤300 KB each, ≤1.2 MB set); legacy aurora PNGs fail; wash CSS must not point at the Thổ JPEG | All five present under ceilings (`__assetweight`) | Hard | Fast board CI (+ Node twin in `test-docs-consistency.mjs`) |
17
18
  | Docs language parity | `_audit/docs-lang-parity.html` | Every operator-facing EN `docs/*.md` has a `docs/vi/` counterpart; VI is not an empty/TODO stub (≥40% EN length); stale-phrase blacklist clean on both EN and VI (historical notes under `_audit/archive/` are not tracked) | 0 missing pairs, 0 stubs, 0 blacklist hits (`__docslangparity`) | Hard | Fast board CI |
19
+ | Docs Storybook coverage | `_audit/docs-storybook-coverage.html` | Live HTML: published catalog + `/docs/**` + viewer + entrance files; Storybook `index.json` titles when present (never unpublished `.storybook/` / `stories/`). Node twin: CSF/MDX source + `staticDirs` | 0 missing published pages / viewer entries (`__docssbcoverage`) | Hard | Fast board CI + unit twin |
20
+ | Docs link check | `_audit/docs-link-check.html` | Live HTML: published markdown + viewer links resolve; no retired paths. Node twin also scans unpublished MDX `href`/`src` | 0 broken in-repo links (`__docslinkcheck`) | Hard | Fast board CI + unit twin |
18
21
  | DESIGN.md parity | `_audit/design-md-parity.html` | The root `DESIGN.md` (Stitch open-spec surface) byte-equals an in-browser regeneration from `tokens.dtcg.json` + `_ds_manifest.json` + `VERSION` via the shared `scripts/design-md-lib.mjs`; every token row re-checked individually (the count is printed with the verdict) | Byte-identical + 0 drifted rows (`__designmd`) | Hard | Fast board CI |
19
22
  | Version stamp | `_audit/version-stamp.html` | `package.json`, `tokens.json`/`tokens.js` metas, DTCG `$extensions`, `provenance.json` release + dtcgStamp, `DESIGN.md` front matter, and `_esm/cs.mjs` `export const VERSION` all equal `VERSION` (pin tracks file; LAUNCHED at 1.1.0) | All 9 stamps equal (`__versionstamp`) | Hard | Fast board CI |
20
23
  | Namespace portability | `_audit/namespace-portability.html` | No manifest-indexed source hardcodes the compiler's project-id bundle suffix | 0 hardcoded suffixes (`__nsguard`) | Hard | Fast board CI |
@@ -35,7 +38,7 @@ Benchmark principles (WCAG · APCA · OKLCH · DTCG · CDS doctrine + style expa
35
38
  | Package exports integrity | `_audit/package-exports-integrity.html` | Every `package.json` `files` entry and every `module`/`types`/`style`/`exports` target exists; every entry-point target is covered by `files` (pack-safe); dual entries — `_esm/react.mjs` (default / `./react`, React peer) + `_esm/cs.mjs` (`./legacy`) — are ESM-shaped and their re-exports ⊆ the bundle header's exposed exports | 0 missing / uncovered / unknown (`__pkgexports`) | Hard | Fast board CI |
36
39
  | Component children | `_audit/component-children-test.html` | Void-element components (Checkbox, Radio, Switch, SearchField, NumberField, Slider, Divider, TextField) mount with stray children without throwing React #137 | 0 throws (`__result.anyThrew === false`) | Hard | Fast board CI |
37
40
  | Component behavior | `_audit/component-behavior-test.html` | 79 real interaction assertions — every interactive public primary with a user-driven contract (overlays, forms, AI gates, shell chrome, media/copy) plus toast-over-dialog depth; display-only primaries excluded by design | 79/79 assertions pass (`__behavior`) | Hard | Fast board CI |
38
- | A11y interactions | `_audit/a11y-gate.html` | Focus management (Dialog/Drawer trap + restore + Escape), roving tabindex, combobox `aria-activedescendant`, role/label contracts, plus open-state Esc/focus for Cascader · TreeSelect · Tour · HoverCard · ContextMenu | All keyboard/ARIA assertions pass (`__a11y`) | Hard | Fast board CI |
41
+ | A11y interactions | `_audit/a11y-gate.html` | Focus management (Dialog/Drawer trap + restore + Escape), roving tabindex, combobox `aria-activedescendant`, Mentions APG + Sortable move buttons (hard-fail), role/label contracts, plus open-state Esc/focus for Cascader · TreeSelect · Tour · HoverCard · ContextMenu | All keyboard/ARIA assertions pass (`__a11y`) | Hard | Fast board CI |
39
42
  | A11y CSSOM | `_audit/a11y-harness.html` | Every interactive `.cs-*` control meets its documented touch-target floor under coarse pointer; focus-ring, reduced-motion, and contrast rules proven in source CSS | 0 floor violations, all source proofs found (`__a11ycss`) | Hard | Fast board CI |
40
43
  | Template schema v2 | `_audit/template-schema-test.html` | Every `content-schema.json` sidecar validates against the JSON Schema, every declared slot id resolves to a real `{{ hole }}` in its template, and every template exposing an authorable **content** hole ships a sidecar (axis/control-flow and boolean tweak holes excluded — see `docs/template-schema-v2.md`) | 0 invalid sidecars, 0 dangling slot ids, 0 hole-driven templates without a sidecar (`__schemav2`) | Hard | Fast board CI |
41
44
  | Support runtime identity | `_audit/support-runtime-identity.html` | All `templates/*/support.js` copies (one per template, 84) are byte-identical: sha-256 via SubtleCrypto, exactly one unique hash, copy count == manifest template count | 1 unique hash, count match (`__supportid`) | Hard | Fast board CI |
@@ -65,13 +68,20 @@ Benchmark principles (WCAG · APCA · OKLCH · DTCG · CDS doctrine + style expa
65
68
  | Token provenance | `_audit/ci/check-token-provenance.mjs` | `tokens/native/` + `tokens/provenance.json` are in lockstep with `tokens/tokens.dtcg.json` (same sha-256 drift authority as the token-pipeline gate) | Exit 0 on hash match | Hard | CI `token-provenance` job |
66
69
  | Bundle freshness (authority) | `_audit/ci/check-bundle-freshness.mjs` | The committed `_ds_bundle.js` was built from the component sources as they exist now — full source discovery (walks `components/`, `ui_kits/`, root sources), so new/deleted files are caught too, which the browser row cannot do | Exit 0, 0 drifted/new/deleted sources | Hard | CI `node-prechecks` job |
67
70
  | DESIGN.md freshness | `scripts/generate-design-md.mjs --check` | The root `DESIGN.md` byte-equals a fresh regeneration from DTCG + manifest + `VERSION` | Exit 0 on byte match | Hard | CI `node-prechecks` job |
71
+ | styles.min.css freshness | `scripts/flatten-styles.mjs --check` | Committed `dist/styles.min.css` byte-equals flatten of `styles.css` + tokens/base (FIND-026) | Exit 0 on byte match | Hard | CI `node-prechecks` job |
72
+ | contrast-report freshness | `scripts/generate-contrast-report.mjs --check` | EN + VI contrast reports match regeneration from element packs (FIND-026) | Exit 0 on byte match | Hard | CI `node-prechecks` job |
73
+ | Manifest coverage | `_audit/ci/check-manifest-coverage.mjs` | Shipped `templates/` + `.card.html` + startingPoints match `_ds_manifest.json` (allowlisted: `_vendor`, `schema`, `email-safe`) | Exit 0 | Hard | CI `node-prechecks` + unit |
74
+ | Storybook build + freshness | `npm run build:storybook` + `test-storybook-freshness.mjs --require` | Storybook builds in CI; stamp matches `stories/` + `.storybook/` (FIND-074 / FIND-075) | Exit 0 | Hard | CI `storybook-build` job |
68
75
 
69
- ## Unit tests — `npm run test:unit` (13)
76
+ ## Unit tests — `npm run test:unit`
70
77
 
71
78
  | Test | File | What it asserts | Pass criterion | Type | Where it runs |
72
79
  |---|---|---|---|---|---|
73
80
  | Nav model | `_audit/ci/test-nav-model.mjs` | The shipped `guidelines/nav-model.js` classify/group logic behaves (drives the real module) | All assertions pass (exit 0) | Hard | Unit test |
74
81
  | Health/Tokens UI contract | `_audit/ci/test-health-tokens-contract.mjs` | Structural contracts of the Health + Tokens HTML entry points hold | All assertions pass (exit 0) | Hard | Unit test |
82
+ | Docs consistency (Node twin) | `_audit/ci/test-docs-consistency.mjs` | Doctrine↔source parity (roles/depth/lang/breakpoints/fallbacks) + aurora asset-weight ceilings | All assertions pass (exit 0) | Hard | Unit test |
83
+ | Docs Storybook coverage (Node twin) | `_audit/ci/test-docs-storybook-coverage.mjs` | Tracked docs + entrance + doctrine each have a Storybook story title and a viewer nav path; `staticDirs` includes `docs/` | Exit 0 | Hard | Unit test |
84
+ | Docs link check (Node twin) | `_audit/ci/test-docs-link-check.mjs` | In-repo relative links in the required published set resolve; retired paths absent as live hrefs | Exit 0 | Hard | Unit test |
75
85
  | Form paths | `_audit/ci/test-form-paths.mjs` | Form path helpers behave (drives the shipped `Form.jsx` via dynamic import) | All assertions pass (exit 0) | Hard | Unit test |
76
86
  | Storybook contract | `_audit/ci/test-storybook-contract.mjs` | Live hub is Storybook only; SB10 ESM main + addon-docs/a11y; complete CSF for every public primary; Matrix/AllVariants + AllSizes when `argTypes.size`; States/Matrix cover disabled/loading/error/busy; every discrete size/variant enum mounted; FullMatrix required when ≥1 of {size, variant, state} axes exist (≥28 qualifiers) | All assertions pass (exit 0) | Hard | Unit test |
77
87
  | Axe coverage | `_audit/ci/test-axe-coverage.mjs` | Fixture `NAMES` ≡ `listPublicComponents()`; axe-smoke loads inventory-locked fixtures | All assertions pass (exit 0) | Hard | Unit test |
@@ -82,9 +92,11 @@ Benchmark principles (WCAG · APCA · OKLCH · DTCG · CDS doctrine + style expa
82
92
  | React entry | `_audit/ci/test-react-entry.mjs` | Dual package exports (`.` / `./react` → `_esm/react.mjs`, `./legacy` → `_esm/cs.mjs`); `package.json` version equals `VERSION`; React peerDeps; react.mjs has no CDN/bundle bridge and re-exports match the bundle header; `generate-react-entry --check` green | All assertions pass (exit 0) | Hard | Unit test |
83
93
  | Element packs | `_audit/ci/test-element-packs.mjs` | `tokens/elements.css` + JSON/JS/DTCG mirrors byte-equal regeneration from `tokens/element-seeds.json` | `generate-element-packs --check` exit 0 | Hard | Unit test |
84
94
  | i18n builtins + doc/font residuals | `_audit/ci/test-i18n-builtins.mjs` | No hardcoded EN UI literals outside the registry path; 0 doc-palette hexes in templates; 0 raw font-size px in `base/` | Exit 0 | Hard | Unit test |
85
- | Storybook static freshness | `_audit/ci/test-storybook-freshness.mjs` | When `storybook-static/` exists, `.cs-freshness.json` `sourceHash` matches `stories/` + `.storybook/` (UX-030). Absent static tree skips. | Exit 0 | Hard | Unit test |
95
+ | Manifest coverage | `_audit/ci/check-manifest-coverage.mjs` | Disk templates/cards/startingPoints ⊆ manifest (`email-safe` allowlisted) | Exit 0 | Hard | Unit test |
96
+ | Pack hygiene | `_audit/ci/test-pack-hygiene.mjs` | Tarball excludes `docs/tasks|audits|plans|status`; includes notices + fonts + `_vendor/` (FIND-064) | Exit 0 | Hard | Unit test |
97
+ | CI verdict selftest | `_audit/ci/ci-verdict.mjs --selftest` | Soft-skip vs success annotation helper (FIND-095) | Exit 0 | Hard | Unit test |
86
98
 
87
- The `test:unit` suite is wired into the CI workflow as part of the July 2026 hardening change (it previously only ran locally).
99
+ The `test:unit` suite is wired into the CI workflow as part of the July 2026 hardening change (it previously only ran locally). Storybook freshness runs in `storybook-build` with `--require` (not skipped in CI).
88
100
 
89
101
  ## Audit probe suite — `npm run test:audit-probe`
90
102
 
@@ -92,20 +104,20 @@ Promoted entry for UX audit proxies (`_audit/ci/audit-probe-suite.mjs`): unit su
92
104
 
93
105
  ## Sync / distribution jobs (soft-skip)
94
106
 
95
- Soft-skip means the job exits 0 with a report when secrets/plan/API cannot complete the real write — **not** that Code Connect or Figma Variables are live. npm CI publish uses Trusted Publishing; soft-skip covers auth/conflict honesty. Treat remaining maintainer tasks in `docs/decisions.md` as the open list (Code Connect deferred; consumer grant is in `docs/consumer-grant.md`). Storybook `FullMatrix` is required for every public primary with ≥1 of {size enums, variant enums, state keys} — shared helpers in `stories/lib/matrix.jsx`.
107
+ Soft-skip means the job exits 0 with a report when secrets/plan/API cannot complete the real write — **not** that Code Connect or Figma Variables are live. Soft-skip writes `$GITHUB_STEP_SUMMARY` and emits a distinct CI annotation (`::error::` on schedule/main, `::warning::` elsewhere) so it is never identical silent green to live success (FIND-095). npm CI publish uses Trusted Publishing; soft-skip covers **already-published** and true non-GHA `missing_secrets` only — auth/404/402 on GHA release fail closed (see `docs/release-runbook.md`). Treat remaining maintainer tasks in `docs/decisions.md` as the open list (Code Connect deferred; consumer grant is in `docs/consumer-grant.md`). Storybook `FullMatrix` is required for every public primary with ≥1 of {size enums, variant enums, state keys} — shared helpers in `stories/lib/matrix.jsx`.
96
108
 
97
109
  | Job | Script / workflow | What it asserts | Soft-skip when | Where it runs |
98
110
  |---|---|---|---|---|
99
111
  | Figma Variables | `_audit/ci/push-figma-variables.mjs` + `figma-variables-push` job | Secrets open the file; optional Variables write | Soft-skip when secrets missing (same honesty as Code Connect) or non-Enterprise / missing `file_variables:*` scopes / API **403** after secrets are present. Soft-skip ≠ live sync | `main` push + manual |
100
112
  | Code Connect | `_audit/ci/code-connect-publish.mjs` + `code-connect` job | Config + 105 mappings; optional publish | Missing `FIGMA_TOKEN`/`FIGMA_FILE_KEY` or API 403/404/429 | PR + `main` + manual |
101
- | npm publish | `_audit/ci/npm-publish.mjs` + `npm-publish.yml` | Pack-safe `files`/`exports`; `npm publish` via OIDC Trusted Publishing (tokens disallowed on package) | Auth / 403 / 404 / EOTP / version conflict | `workflow_dispatch` / `v*` tags |
113
+ | npm publish | `_audit/ci/npm-publish.mjs` + `npm-publish.yml` | Pack-safe `files`/`exports` (incl. `_vendor/`); `npm publish` via OIDC Trusted Publishing (tokens disallowed on package); post-publish `npm view` version **and** `dist-tags.latest === VERSION` (FIND-094) | Soft-skip: `already_published` / non-GHA `missing_secrets` only. **Fail on GHA release:** ENEEDAUTH / 404 / 402 / 403 / EOTP / missing registry presence or wrong `latest` | `workflow_dispatch` / `v*` tags |
102
114
  | Native store | `_audit/ci/native-store-dry-run.mjs` + `native-store.yml` | Fastlane scaffolds + metadata; signed-release secrets check | Missing `ASC_*` / `PLAY_SERVICE_ACCOUNT_JSON` (submit always disabled) | PR + `main` (paths) + manual |
103
115
 
104
- ## Registry consumer smoke (hard)
116
+ ## Registry consumer smoke (fail-closed)
105
117
 
106
118
  | Job | Script / workflow | What it asserts | Pass criterion | Where it runs |
107
119
  |---|---|---|---|---|
108
- | npm-hello smoke | `examples/npm-hello` + `npm-hello-smoke` job | Public registry install of `@cyberskill/design@1.1.1` resolves package name + exports (`npm install` + `npm run smoke`; local pack proof if VERSION not on registry yet) | Exit 0 (**hard fail** once published; soft-skip pack proof if VERSION not on registry yet) | Path-filtered push/PR + nightly + manual |
120
+ | npm-hello smoke | `examples/npm-hello` + `npm-hello-smoke` job | Public registry install of `@cyberskill/design@$VERSION` resolves package name + exports (`npm install` + `npm run smoke`) | Exit 0 only when VERSION is on the registry (**fail-closed**, FIND-087). Local-pack proof only if fork sets `NPM_HELLO_ALLOW_LOCAL_PACK=true` | Path-filtered push/PR + nightly + manual |
109
121
 
110
122
  ## July 2026 hardening — delivered
111
123
 
@@ -1,6 +1,6 @@
1
1
  # Release Notes
2
2
 
3
- Curated product highlights for operators. This is **not** a git log and **not** a `CHANGELOG.md` — the design system does not maintain a changelog file. Version is **LAUNCHED at 1.1.0**; **pin tracks `VERSION`** (auto-bump on push to `main` from Conventional Commits; owner may still force a bump). Technical continuity is the repo tip; product-facing continuity is this page (mirrored in Storybook **Release Notes**).
3
+ Curated product highlights for operators. This is **not** a git log and **not** a `CHANGELOG.md` — the design system does not maintain a changelog file. Version is **LAUNCHED at 1.1.0**; **pin tracks `VERSION`** (auto-bump on push to `main` from Conventional Commits; owner may still force a bump). Technical continuity is the repo tip; product-facing continuity is this page (mirrored in Storybook **Release Notes**). Published on Storybook **Docs** at `design.cyberskill.world`.
4
4
 
5
5
  ## Patch — `@cyberskill/design@1.1.1`
6
6
 
@@ -0,0 +1,78 @@
1
+ # Release runbook (authoritative)
2
+
3
+ One page for how a release happens and how to tell it worked. Consolidates areas 21/23. Related detail: `docs/ci-cd.md`, `docs/deploy.md`, `docs/decisions.md` §7 / §13. Published on Storybook **Docs** at `design.cyberskill.world`.
4
+
5
+ ## Trigger
6
+
7
+ | Path | When |
8
+ |------|------|
9
+ | **Auto** | Push to `main` with Conventional Commits → `version.yml` bumps `VERSION`, stamps artifacts, commits `chore(release): X.Y.Z`, tags `vX.Y.Z` |
10
+ | **Force** | `Release-As: X.Y.Z` trailer on a commit, or `workflow_dispatch` on `version.yml` with a level |
11
+ | **Manual publish** | `workflow_dispatch` on `npm-publish.yml` (also runs on `v*` tags) |
12
+
13
+ Never push/deploy/merge without an explicit operator instruction when operating as an agent.
14
+
15
+ ## What fires (happy path)
16
+
17
+ ```
18
+ main push (feat/fix/…)
19
+ → version.yml (bump VERSION + stamps + bundle + tag vX.Y.Z)
20
+ → npm-publish.yml (OIDC Trusted Publishing; post-publish version + dist-tags.latest)
21
+ → Vercel (host) (build:site → .vercel-static; headers from vercel.json)
22
+ → sbom.yml on tag (CycloneDX artifact)
23
+ ```
24
+
25
+ Scorecard runs on a weekly schedule + `main` pushes (`.github/workflows/scorecard.yml`).
26
+
27
+ ## Success signals
28
+
29
+ 1. GitHub Actions: `version` green; `npm-publish` green (**not** soft-skip) with registry presence **and** `dist-tags.latest === VERSION` (FIND-094).
30
+ 2. `npm view @cyberskill/design version` **and** `npm view @cyberskill/design dist-tags.latest` both equal root `VERSION`.
31
+ 3. `npm-hello-smoke` green on the tip (fail-closed registry install of that VERSION — FIND-087).
32
+ 4. Production: `/` is Storybook; `/VERSION` is plain semver; `/_audit/run.html` fast board green.
33
+ 5. Artifacts: `cyclonedx-sbom` on the tag run; Scorecard SARIF on Security / Actions artifacts.
34
+ 6. Post-deploy Health protocol in `docs/deploy.md`.
35
+
36
+ ## Historical unpublished tags (do not backfill)
37
+
38
+ | Tag | Status | Operator action |
39
+ |-----|--------|-----------------|
40
+ | `v1.2.1` | Historical git tag; **not** published to npm as `latest` | Leave unpublished |
41
+ | `v1.3.0` | Historical git tag; **not** published to npm as `latest` | Leave unpublished |
42
+ | `v1.3.1` (current tip) | **Publish target** when operator instructs | Publish **only** `1.3.1` as `dist-tags.latest` |
43
+
44
+ Do **not** publish `1.2.1` or `1.3.0` to close registry drift — close FIND-102 by publishing **`1.3.1` only** (operator-gated). npm `latest` may still read `1.2.0` until that publish lands.
45
+
46
+ ## Failure / recovery
47
+
48
+ | Symptom | Action |
49
+ |---------|--------|
50
+ | `npm-publish` 403 / EOTP / ENEEDAUTH / 404 / 402 on tag or `workflow_dispatch` | **Fail-closed.** Fix Trusted Publisher binding for repo **`cyberskill-official/design`** (FIND-088) / 2FA / OIDC; re-run on the tag. Soft-skip must **not** report success for these. |
51
+ | Soft-skip `already_published` | Expected no-op — confirm registry; do not treat as success if you intended a new version. |
52
+ | Soft-skip `missing_secrets` | Expected only **off** GitHub Actions (local). On GHA release this is a hard fail. |
53
+ | `version.yml` push soft-warn | Set `PUSH_TOKEN` or allow Actions to push past branch protection (see `docs/ci-cd.md`). |
54
+ | `npm-hello-smoke` red (VERSION missing on registry) | Expected until publish lands (FIND-087). Follow **Incident: unpublished release** below — do not set `NPM_HELLO_ALLOW_LOCAL_PACK` on the canonical repo. |
55
+ | Nightly `design-system-gates` red | GitHub notifies the default workflow subscribers; see “Scheduled-job alerting” below. Re-run `workflow_dispatch`. |
56
+ | Partial Vercel deploy | Re-run deploy; follow Health re-run protocol; do not invent live header claims without `curl -sSI`. |
57
+
58
+ ## Incident: unpublished release (FIND-100 / FIND-101 / FIND-107)
59
+
60
+ Use when git/`VERSION`/site are ahead of npm `dist-tags.latest` (e.g. tip `1.3.1`, registry still `1.2.0`).
61
+
62
+ 1. **Confirm skew** — `cat VERSION`; `npm view @cyberskill/design version`; `npm view @cyberskill/design dist-tags.latest`; note git tags `v1.2.1` / `v1.3.0` / `v1.3.1` as historical vs publish target.
63
+ 2. **Do not** treat a green `npm-publish` soft-skip (or a green `npm-hello` local-pack proof) as evidence the version is public — smoke is fail-closed; publish auth errors hard-fail on GHA.
64
+ 3. **Fix Trusted Publisher** if needed — npm package settings must list org/repo **`cyberskill-official/design`**, workflow **`npm-publish.yml`**, and the correct environment (FIND-088). Classic `NPM_TOKEN` is disallowed. CI uses a clean OIDC userconfig (no empty `_authToken` from `actions/setup-node`) so Trusted Publishing can exchange the GitHub OIDC token.
65
+ 4. **Operator-gated publish** — only after an explicit instruction: re-run `npm-publish.yml` on tag **`v1.3.1`** (or `workflow_dispatch` at that tip). Publish target is **`1.3.1` only**; do not backfill `1.2.1` / `1.3.0`.
66
+ 5. **Verify** — `npm view @cyberskill/design@1.3.1 version` and `dist-tags.latest` both `1.3.1`; re-run `npm-hello-smoke` (or wait for the next gates run) to green.
67
+ 6. **Rollback / deprecate (if a bad version reached `latest`)** — `npm deprecate @cyberskill/design@<bad> "…"` and/or `npm dist-tag add @cyberskill/design@<good> latest`. npm does not allow unpublishing recent public versions in the normal case — prefer deprecate + retag `latest`. Site/Vercel rollback is independent (`docs/deploy.md`).
68
+
69
+ ## Scheduled-job alerting (area 27)
70
+
71
+ - Nightly cron `0 3 * * *` on `design-system-gates.yml`.
72
+ - On schedule failure the workflow’s `notify-schedule-failure` job (`needs` every scheduled job — FIND-108) emits an Actions error annotation and fails when `contains(needs.*.result, 'failure')`, which triggers **GitHub’s native workflow-failure email** to repository watchers / the last actor as configured under Settings → Notifications.
73
+ - Optional: add a repo Actions variable / secret for Slack webhook later; do not require it for green CI.
74
+ - Operators should watch the Actions badge in `docs/ci-cd.md` and enable “Actions” notification for failed workflows.
75
+
76
+ ## Product vs CyberOS
77
+
78
+ See `docs/decisions.md` §13. The npm package and portable tree are the product; `.cyberos/` is orchestration only.
package/docs/storybook.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Storybook — product surface at `/` (host)
2
2
 
3
- Storybook **10** is the **product site** for operators on `design.cyberskill.world` (`/`). It is still **not** part of the portable consumer contract.
3
+ Storybook **10** is the **product site** for operators on `design.cyberskill.world` (`/`). It is still **not** part of the portable consumer contract. Published on Storybook **Docs** at `design.cyberskill.world`.
4
4
 
5
5
  ## URL
6
6
 
@@ -20,7 +20,7 @@ Storybook **10** is the **product site** for operators on `design.cyberskill.wor
20
20
  - Every discrete `size` / `variant` enum option mounted in a matrix-family story
21
21
  - `FullMatrix` when ≥1 of {size enums, variant enums, state keys} exist — the size × variant × key-state product via shared helpers in `stories/lib/matrix.jsx`
22
22
  - Toolbar globals: Theme (light · dark · **system**) × Element × Language × Style (same axes as templates / Atomic View). Element lists **all 15** Ngũ Hành packs (`tokens.elements` / template EL maps / Storybook toolbar) — not a subset. Style’s sole pack is **liquid-glass**.
23
- - **Docs/** public MDX guides; **Release Notes/** curated product prose (**no CHANGELOG.md**); **Status/** embeds `_audit/run.html` full-bleed
23
+ - **Docs/** published operator documentation — nested **Start / Guides / Maintainers**, curated MDX for high-traffic pages, one sidebar story per tracked markdown page, and a Documentation Library iframe of `/docs/viewer.html` (EN·VI). Canonical prose remains `docs/*.md`; Storybook is the live reading surface. **Release Notes/** curated product prose (**no CHANGELOG.md**); **Status/** embeds `_audit/run.html` full-bleed
24
24
  - **Maintainer/** stories for portable HTML surfaces (Motion, templates, kitchen-sink, AI cluster, RTL; Atomic View buried for gates)
25
25
  - Same `styles.css` as production
26
26
  - Addons: `@storybook/addon-docs` + `@storybook/addon-a11y` (essentials folded into core in SB10)
@@ -40,7 +40,7 @@ Storybook **10** is the **product site** for operators on `design.cyberskill.wor
40
40
  | ESM (bundler) | `_esm/react.mjs` (default / `@cyberskill/design/react`) |
41
41
  | ESM (browser legacy) | `_esm/cs.mjs` (`@cyberskill/design/legacy`) |
42
42
  | Tokens | `tokens/*` |
43
- | Claude Design | `templates/**/*.dc.html` |
43
+ | DC-capable authoring | `templates/**/*.dc.html` |
44
44
 
45
45
  ## Commands
46
46
 
package/docs/sync.md CHANGED
@@ -1,10 +1,10 @@
1
- # Repo ↔ Claude Design — round-trip fidelity & two-way sync
1
+ # Repo ↔ authoring environment — round-trip fidelity & two-way sync
2
2
 
3
- The GitHub repo (`cyberskill-official/design-system`) is the **source of truth**. Claude Design sessions are ephemeral project filesystems — this doc is how they stay in sync without losing work.
3
+ The GitHub repo (`cyberskill-official/design`) is the **source of truth**. Compiler sessions (for example Claude Design) are ephemeral project filesystems — this doc is how they stay in sync without losing work. Published on Storybook **Docs** at `design.cyberskill.world`.
4
4
 
5
5
  ## Does the repo restore the full system intact?
6
6
 
7
- **In a Claude-Design session — yes.** Everything that defines the system is plain text/asset files and round-trips losslessly:
7
+ **In a DC-capable compiler session — yes.** Everything that defines the system is plain text/asset files and round-trips losslessly:
8
8
  - `styles.css` + `tokens/` + `base/` (all CSS + `tokens.json`/`tokens.js`)
9
9
  - `components/**` (`.jsx` + `.d.ts` + `.prompt.md` + `*.card.html`)
10
10
  - `templates/**/*.dc.html` (+ `ds-base.js`, `support.js`)
@@ -13,15 +13,15 @@ The GitHub repo (`cyberskill-official/design-system`) is the **source of truth**
13
13
  - **`_esm/react.mjs`** — bundler-native React entry (default package export; React peer). Regenerated via `npm run build:react-entry`.
14
14
  - **`_esm/cs.mjs`** — the browser / no-build legacy ESM entry (`@cyberskill/design/legacy`). Underscore-prefixed does **not** mean build artifact or gitignored here (only `uploads/`, `scraps/`, `_audit/exports/` are — see Hygiene below); `_esm/` is source, same tier as `templates/` or `docs/`. A prior port of this repo skipped it on exactly this assumption and broke the ESM smoke gate — if you're porting/copying this tree by hand, **explicitly include every top-level folder this list names**, don't infer from the `_` prefix.
15
15
 
16
- - `README.md`, `CONTRIBUTING.md`, `SKILL.md`, `CLAUDE.md`, `VERSION`, `DESIGN.md` (generated open-spec surface — committed, regenerated only via `npm run build:design-md`, pinned by the `design-md-parity` gate)
16
+ - `README.md`, `CONTRIBUTING.md`, `SKILL.md`, `docs/doctrine.md`, host shims (`CLAUDE.md`), `VERSION`, `DESIGN.md` (generated open-spec surface — committed, regenerated only via `npm run build:design-md`, pinned by the `design-md-parity` gate)
17
17
 
18
- Pull them back into a fresh project (see below) and the compiler re-recognizes it as a design system — it keys off `styles.css`, the `.d.ts`/`.jsx` pairs, `@dsCard` HTML, and `templates/`. The **derived** files (`_ds_bundle.js`, `_ds_manifest.json`, `_adherence.oxlintrc.json`) are regenerated every turn from source, so they need not be trusted from the repo — they rebuild.
18
+ Pull them back into a fresh project (see below) and the compiler re-recognizes it as a design system — it keys off `styles.css`, the `.d.ts`/`.jsx` pairs, `@dsCard` HTML, and `templates/`. Committed compiled artifacts (`_ds_bundle.js`, `_ds_manifest.json`, `_adherence.oxlintrc.json`, `dist/styles.min.css`, `DESIGN.md`) are part of the consumer contract — keep them in the tree and regenerate them with the documented npm scripts rather than treating them as disposable.
19
19
 
20
- **In other agents (Google Stitch, generic LLM tools) — partially.** They can consume the **portable** layer — `tokens/tokens.json` + `tokens.js`, the raw CSS, the component `.jsx`, fonts, and the Markdown docs — but they do **not** understand the `.dc.html` Design-Component format or the compiler that drives it. So a non-Claude-Design agent gets the tokens, styles, and component source as files, not the live DC/tweak/compile behavior. Point those tools at the root **`DESIGN.md`** first (the generated Stitch-style open-spec surface: doctrine + every token value + inventory, regenerated from DTCG via `npm run build:design-md` and pinned by the `design-md-parity` gate), then `tokens.json` / `tokens.dtcg.json` and the CSS for the machine contract; treat `.dc.html` + the compiler as Claude-Design-native.
20
+ **In other agents (Google Stitch, generic LLM tools) — partially.** They can consume the **portable** layer — `tokens/tokens.json` + `tokens.js`, the raw CSS, the component `.jsx`, fonts, and the Markdown docs — but they do **not** understand the `.dc.html` Design-Component format or the compiler that drives it. So a non-compiler agent gets the tokens, styles, and component source as files, not the live DC/tweak/compile behavior. Point those tools at the root **`DESIGN.md`** first (the generated Stitch-style open-spec surface: doctrine + every token value + inventory, regenerated from DTCG via `npm run build:design-md` and pinned by the `design-md-parity` gate), then `tokens.json` / `tokens.dtcg.json` and the CSS for the machine contract; treat `.dc.html` + the compiler as DC-native.
21
21
 
22
22
  ## Two-way sync (repo = source of truth)
23
23
 
24
- Claude Design can **read/copy from** GitHub but **cannot push to** it. So sync is *automatic pull, manual push*:
24
+ Compiler sessions can **read/copy from** GitHub but typically **cannot push to** it. So sync is *automatic pull, manual push*:
25
25
  **Session START — pull (reliable, automated):** tell the agent to load the repo. It copies the tree into the fresh project (the `github_copy_files` path), the compiler validates, and you continue from the committed truth — never from stale project state. Always begin here; do not resume from a half-remembered project.
26
26
 
27
27
  **Session END — push (manual, reviewed):** download the project, then from a clone:
@@ -37,7 +37,7 @@ git push -u origin session/<date-or-topic> # branch, never --force, never stra
37
37
  The PR diff is the safety net — it shows exactly what changed since the last committed truth.
38
38
 
39
39
  ## Hygiene that keeps round-trips clean
40
- - **`.gitignore`** the transient (`uploads/`, `scraps/`, `_audit/exports/`); commit everything else, **including `_esm/`** (see above — it is source, not a build artifact, despite the `_` prefix). The compiled `_ds_bundle.js`/manifest are committed for consumers that have no build step, but expect churn — or ignore them and let each session regenerate.
40
+ - **`.gitignore`** the transient (`uploads/`, `scraps/`, `_audit/exports/`); commit everything else, **including `_esm/`** (see above — it is source, not a build artifact, despite the `_` prefix). The compiled `_ds_bundle.js`, `_ds_manifest.json`, and `_adherence.oxlintrc.json` are **committed consumer artifacts** — they ship in the npm package so consumers with no build step can load the system. Do not gitignore them. Regenerate via `npm run build:bundle` after source changes; the bundle-freshness gate fails on drift.
41
41
 
42
42
  - **`VERSION` is LAUNCHED at 1.1.0; pin tracks `VERSION`** — auto-bump on push to `main` (`.github/workflows/version.yml` → tag `v*` → `npm-publish.yml`); owner may still force a bump. Do not maintain a changelog file. Continuity is the git history; open maintainer tasks live in `docs/decisions.md`.
43
43
 
@@ -1,6 +1,6 @@
1
1
  # Template content-schema v2 — typed content slots
2
2
 
3
- Purely additive, opt-in metadata: a sidecar `templates/<slug>/content-schema.json` next to a template's `.dc.html`, declaring the **type** of each `{{ hole }}` already in the template — so an agent or pipeline can populate/validate real client content programmatically without parsing HTML or guessing.
3
+ Purely additive, opt-in metadata: a sidecar `templates/<slug>/content-schema.json` next to a template's `.dc.html`, declaring the **type** of each `{{ hole }}` already in the template — so an agent or pipeline can populate/validate real client content programmatically without parsing HTML or guessing. Published on Storybook **Docs** at `design.cyberskill.world`.
4
4
 
5
5
  **Zero template-markup changes required.** The slot `id` is the hole name already used in the `.dc.html` (e.g. `{{ heroH }}`) and already bound in the logic class's `renderVals()` — the schema just describes it.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Rubric benchmark Design System
2
2
 
3
- Checklist tự kiểm khi tiến hóa CyberSkill Design System — chuẩn bên ngoài cộng rule CDS. Ghép với [`docs/vi/quality-gates.md`](quality-gates.md) (gate xác định) và [`docs/vi/design-styles.md`](design-styles.md) (hợp đồng màu Element).
3
+ Checklist tự kiểm khi tiến hóa CyberSkill Design System — chuẩn bên ngoài cộng rule CDS. Ghép với [`docs/vi/quality-gates.md`](quality-gates.md) (gate xác định) và [`docs/vi/design-styles.md`](design-styles.md) (hợp đồng màu Element). Xuất bản trên Storybook **Docs** tại `design.cyberskill.world`.
4
4
 
5
5
  ## Chuẩn bên ngoài
6
6
 
@@ -22,7 +22,7 @@ Checklist tự kiểm khi tiến hóa CyberSkill Design System — chuẩn bên
22
22
  | Chữ không trên mid `-accent`; focus Ochre không remap; màu status không remap | Hợp đồng `elements.css` · contrast-report · conventions |
23
23
  | Một element mỗi bề mặt; gradient chỉ Tương sinh | Registry products · conventions |
24
24
  | Registry product→element khóa; UI kit trung thành Thổ | [`docs/vi/products.md`](products.md) |
25
- | Expansion Rule đủ + `_audit/run.html` xanh + docs EN·VI parity | CLAUDE.md · docs-consistency · docs-lang-parity |
25
+ | Expansion Rule đủ + `_audit/run.html` xanh + docs EN·VI parity | `docs/doctrine.md` · docs-consistency · docs-lang-parity · docs-storybook-coverage |
26
26
  | VERSION theo file (LAUNCH 1.1.0; auto-bump trên main) | version-stamp · docs-consistency |
27
27
  | Pack Element chỉ từ seed (30 bộ) | `element-geometry` · `tokens:elements` |
28
28
 
package/docs/vi/ci-cd.md CHANGED
@@ -1,29 +1,30 @@
1
1
  # CI/CD — tự động hóa bảng gate
2
2
 
3
- **Gate CI** (workflow này) vẫn coi design system như cây tĩnh: serve repo, mở `_audit/run.html` headless, đọc verdict globals. Không cần product bundler cho gates.
3
+ **Gate CI** (workflow này) vẫn coi design system như cây tĩnh: serve repo, mở `_audit/run.html` headless, đọc verdict globals. Không cần product bundler cho gates. Xuất bản trên Storybook **Docs** tại `design.cyberskill.world`.
4
4
 
5
5
  **Host deploy** (Vercel, tách khỏi workflow này) chạy `npm install` + `npm run build:site` để Storybook ship làm bề mặt sản phẩm tại `/` — xem `docs/deploy.md` và `docs/storybook.md`. Đường đóng gói host đó không bắt buộc cho consuming project hay các job gate bên dưới.
6
6
 
7
7
  ## Badge
8
8
 
9
- [![Design System Gates](https://github.com/cyberskill-official/design-system/actions/workflows/design-system-gates.yml/badge.svg)](https://github.com/cyberskill-official/design-system/actions/workflows/design-system-gates.yml)
9
+ [![Design System Gates](https://github.com/cyberskill-official/design/actions/workflows/design-system-gates.yml/badge.svg)](https://github.com/cyberskill-official/design/actions/workflows/design-system-gates.yml)
10
10
 
11
11
  ## Những gì đã nối (`.github/workflows/design-system-gates.yml`)
12
12
 
13
13
  1. **`fast-gates`** — `npm ci` + Playwright Chromium cache, serve repo, mở `_audit/run.html` headless (`_audit/ci/run-gates.mjs`), fail khi hard-gate fail. Upload import-report khi fail. Hàng mới trên board (hardening Th7 2026 thêm 8: token-format-parity, version-stamp, support-runtime-identity, package-exports-integrity, template-lang-parity, dtcg-typing, design-md-parity, bundle-freshness) được nhận tự động — runner đọc `window.__run`, không phải danh sách gate phía job.
14
14
  2. **`token-provenance`** — kiểm Node không trình duyệt: natives + `provenance.json` khớp sha-256 nguồn DTCG.
15
15
  3. **`unit-tests`** — `npm run test:unit` (11 contract test Node thuần; nối vào CI bởi hardening Th7 2026 — trước đó chỉ local). Gồm `test-element-packs` (freshness `node scripts/generate-element-packs.mjs --check`).
16
- 4. **`node-prechecks`** — authority Node không trình duyệt: `_audit/ci/check-bundle-freshness.mjs` (nguồn chân lý bundle-freshness — khám phá source đầy đủ gồm file mới/xóa; hàng board chỉ re-hash file ghi trong header) và `scripts/generate-design-md.mjs --check` (`DESIGN.md` gốc byte-equals regeneration).
16
+ 4. **`node-prechecks`** — authority Node không trình duyệt: `_audit/ci/check-bundle-freshness.mjs` (nguồn chân lý bundle-freshness — khám phá source đầy đủ gồm file mới/xóa; hàng board chỉ re-hash file ghi trong header), `scripts/generate-design-md.mjs --check` (`DESIGN.md` gốc byte-equals regeneration), `scripts/flatten-styles.mjs --check` + `scripts/generate-contrast-report.mjs --check` (FIND-026), và `_audit/ci/check-manifest-coverage.mjs` (FIND-078).
17
+ 4b. **`storybook-build`** — `npm run build:storybook` rồi `test-storybook-freshness.mjs --require` (FIND-074 / FIND-075). Storybook gãy sẽ fail CI trước deploy.
17
18
  5. **`docs-consistency-blocker`** — merge blocker `docs-consistency` + `bilingual-parity`.
18
19
  6. **`whole-set-audits`** — quyết định B của owner: mọi push/PR, cộng nightly `0 3 * * *` và `workflow_dispatch` (responsive + language + theme overflow, ~15–20 phút).
19
20
  7. **`figma-variables-push`** — trên push `main` + thủ công. **`FIGMA_TOKEN` / `FIGMA_FILE_KEY` trống → soft-skip** (exit 0 + report — cùng trung thực với Code Connect). Quyết định A (non-Enterprise): Variables REST cũng **soft-skip khi API 403** (và lỗi plan/scope liên quan) sau khi secret chứng minh mở file. Soft-skip ≠ sync Variables live. Xem `docs/figma.md`.
20
21
  8. **`code-connect`** — trên PR + `main` + thủ công. Quyết định 1C: dry-run luôn (config + 105 mapping); publish soft-skip khi thiếu `FIGMA_TOKEN` / `FIGMA_FILE_KEY` hoặc API 403/404/429. Xem `docs/figma.md`.
21
- 9. **`regenerate-tokens`** (pull request) + **`regenerate-tokens-push`** (push `main` / schedule / thủ công) — path filter phủ element seeds/packs (`element-seeds.json`, `elements.css`, mirror JSON/JS/DTCG, `generate-element-packs.mjs`) cộng natives / `VERSION`. Regenerate chạy `npm run tokens:elements` rồi `node _audit/ci/generate-native-tokens.mjs`. Trên **pull request** job chạy với `contents: read`, không bao giờ push, và **exit 1** khi có drift: chạy cả hai ở local rồi commit. Chỉ job song sinh push/schedule/thủ công giữ `contents: write` và auto-commit với `DS_PUSH_TOKEN` (hoặc `github.token`).
22
- 10. **`npm-hello-smoke`** — chứng minh consumer registry: `cd examples/npm-hello && npm ci && npm run smoke` (**hard fail**; package public). Path-filtered trên push/PR khi `examples/npm-hello/**`, bề mặt publish package, hoặc workflow này đổi; luôn chạy trên schedule / `workflow_dispatch`.
22
+ 9. **`regenerate-tokens`** (pull request) + **`regenerate-tokens-push`** (push `main` / schedule / thủ công) — path filter phủ element seeds/packs (`element-seeds.json`, `elements.css`, mirror JSON/JS/DTCG, `generate-element-packs.mjs`) cộng natives / `VERSION`. Regenerate chạy `npm run tokens:elements` rồi `node _audit/ci/generate-native-tokens.mjs`. Trên **pull request** job chạy với `contents: read`, không bao giờ push, và **exit 1** khi có drift: chạy cả hai ở local rồi commit (freshness bắt buộc trên PR). Chỉ job song sinh push/schedule/thủ công giữ `contents: write` và có thể auto-commit với `PUSH_TOKEN` (hoặc `github.token`). Auto-commit **không** dùng `[skip ci]` — tip được push phải chạy lại bảng gate (FIND-021 / TASK-IMP-008); lần chạy thứ hai deterministic là no-op.
23
+ 10. **`npm-hello-smoke`** — chứng minh consumer registry cho `@cyberskill/design@$VERSION` (**fail-closed**, FIND-087): `examples/npm-hello` → `npm install` từ registry + `npm run smoke`. Nếu VERSION **không** có trên registry, job **fail** (không soft-skip pack proof trên `cyberskill-official/design`). Fork chỉ được opt-in pack local khi đặt biến repo **`NPM_HELLO_ALLOW_LOCAL_PACK=true`**. Path-filtered trên push/PR khi `examples/npm-hello/**`, bề mặt publish package, hoặc workflow này đổi; luôn chạy trên schedule / `workflow_dispatch`.
23
24
 
24
- Workflow riêng **`version`** (`.github/workflows/version.yml`): mỗi push lên `main`, bump `VERSION` theo Conventional Commits + stamp artifact; commit `chore(release): X.Y.Z`, push, và tạo tag `vX.Y.Z`. Bỏ qua chính commit release (an toàn vòng lặp). Owner có thể force level qua `workflow_dispatch` hoặc trailer `Release-As:`. Cần `contents: write` (cùng pattern `DS_PUSH_TOKEN` như `regenerate-tokens-push` nếu branch protection chặn `github.token`).
25
+ Workflow riêng **`version`** (`.github/workflows/version.yml`): mỗi push lên `main`, bump `VERSION` theo Conventional Commits + stamp artifact; rồi regen natives/provenance hash và `npm run build:bundle` để tip sạch gate; commit `chore(release): X.Y.Z`, push, và tạo tag `vX.Y.Z`. Bỏ qua chính commit release (an toàn vòng lặp). Owner có thể force level qua `workflow_dispatch` hoặc trailer `Release-As:`. Cần `contents: write`. Checkout dùng `secrets.PUSH_TOKEN || github.token` — nếu branch protection yêu cầu status checks (hoặc chặn `github.token`), đặt repository secret **`PUSH_TOKEN`** (fine-grained PAT, Contents: Read and write); không thì bump tính được nhưng push soft-warn và không land.
25
26
 
26
- Workflow riêng **`npm-publish`** (`.github/workflows/npm-publish.yml`): `workflow_dispatch` + tag `v*` (thường do `version.yml` tạo); pack dry-run luôn; publish qua **npm Trusted Publishing (OIDC)** (`id-token: write`, không `NPM_TOKEN` trên bước publish). Soft-skip khi auth / 403 / 404 / EOTP / conflict phiên bản. License **UNLICENSED**. Trusted Publisher trên npmjs phải khớp filename workflow `npm-publish.yml`. Publishing access package: **Require 2FA and disallow tokens** (OIDC vẫn chạy; token classic bị từ chối).
27
+ Workflow riêng **`npm-publish`** (`.github/workflows/npm-publish.yml`): `workflow_dispatch` + tag `v*` (thường do `version.yml` tạo); pack dry-run luôn; publish qua **npm Trusted Publishing (OIDC)** (`id-token: write`, không `NPM_TOKEN` trên bước publish). Soft-skip chỉ **`already_published`** và `missing_secrets` thật sự **ngoài GHA**. Trên tag / `workflow_dispatch`, **ENEEDAUTH** / **404** / **402** / **403** / **EOTP** **fail closed**. Sau publish assert `npm view @cyberskill/design@VERSION` **và** `dist-tags.latest === VERSION` (FIND-094). License **UNLICENSED**. Trusted Publisher trên npmjs phải khớp filename workflow `npm-publish.yml` cho repo **`cyberskill-official/design`** (FIND-088). Publishing access package: **Require 2FA and disallow tokens** (OIDC vẫn chạy; token classic bị từ chối).
27
28
 
28
29
  Workflow riêng **`native-store`** (`.github/workflows/native-store.yml`): PR + `main` (path-filtered) + `workflow_dispatch`; dry-run scaffold luôn; kiểm signed-release soft-skip khi thiếu `ASC_KEY_ID` / `ASC_ISSUER_ID` / `ASC_KEY_P8` / `PLAY_SERVICE_ACCOUNT_JSON`. **Không bao giờ submit** lên App Store / Play — sample vẫn là sample. Xem `examples/native/README.md`.
29
30
 
@@ -42,16 +43,18 @@ Node **22** trên runner (tránh deprecation action Node 20). Cache key Playwrig
42
43
 
43
44
  ## Quyền auto-commit token
44
45
 
45
- Chỉ `regenerate-tokens-push` yêu cầu `permissions: contents: write`; job song sinh cho pull request `regenerate-tokens` giữ `contents: read` và checkout không lưu credential, nên PR không bao giờ kích hoạt push của bot. Nếu org khóa default token read-only, đặt repository secret `DS_PUSH_TOKEN` (fine-grained PAT, Contents read/write) hoặc mở write tại org Actions settings. Xem ghi chú trước trong git history / org settings.
46
+ `regenerate-tokens-push` và `version.yml` yêu cầu `permissions: contents: write` và checkout với `secrets.PUSH_TOKEN || github.token`. Job song sinh pull request `regenerate-tokens` giữ `contents: read` và không bao giờ push. Nếu ruleset/branch protection yêu cầu status checks trước khi push (hoặc khóa default Actions token), đặt repository secret **`PUSH_TOKEN`** (fine-grained PAT, Contents: Read and write trên repo này) hoặc cho phép GitHub Actions bypass ruleset. Không có thì bot push soft-warn và exit 0; drift nội dung vẫn hard-fail qua `token-provenance` / fast-gates / `node-prechecks`.
46
47
 
47
- ## Branch protection (khuyến nghị)
48
+ ## Branch protection (khuyến nghị) — NV-18.1 ngoài repo
48
49
 
49
- Require status checks trên `main` trước merge:
50
+ **NV-18.1 (assessment):** check nào **bắt buộc** trước khi merge `main`, admin có bị ràng buộc không, và CODEOWNERS / review / conversation-resolution có được enforce — đều là **cài đặt GitHub, không nằm trong repo**. Trạng thái quan sát từ clone: **không biết / xác nhận ngoài băng**. Không bịa giá trị ruleset live từ YAML workflow.
51
+
52
+ **Khuyến nghị** (chỉ tài liệu — áp dụng trong GitHub Settings → Branches / Rulesets, hoặc `gh api` admin):
50
53
 
51
54
  - `fast-gates`
52
55
  - `docs-consistency-blocker`
53
56
 
54
- Tùy chọn: `whole-set-audits` (dài). Cấu hình dưới repo **Settings → Branches** hoặc qua `gh api` (admin).
57
+ Tùy chọn: `whole-set-audits` (dài).
55
58
 
56
59
  ## Chạy local
57
60
 
@@ -74,11 +77,11 @@ node _audit/ci/generate-native-tokens.mjs
74
77
  - **Hàng visual / component baseline side-by-side** — chỉ advisory (drift đánh giá bằng mắt). So sánh `%` pixel Playwright là gate **hard** (job `pixel-diff` + hàng Pixel CI trên board).
75
78
  - **Figma Variables** — soft-skip khi thiếu secret (cùng trung thực với Code Connect) hoặc write Variables gặp non-Enterprise / API **403**; report artifact ghi lại skip. Soft-skip ≠ sync live.
76
79
  - **Code Connect publish** — soft-skip khi thiếu secret hoặc API 403/404/429 (Quyết định 1C).
77
- - **npm publish** — Trusted Publishing (OIDC) trên `npm-publish.yml`; soft-skip khi auth / conflict (Quyết định 1C).
80
+ - **npm publish** — Trusted Publishing (OIDC) trên `npm-publish.yml`; soft-skip khi `already_published` / `missing_secrets` ngoài GHA; trên GHA release **ENEEDAUTH** / **404** / **402** / **403** / **EOTP** fail closed + kiểm version **và** `dist-tags.latest` sau publish (Quyết định §7 / FIND-020 / FIND-094).
78
81
  - **Native store signed release** — soft-skip khi thiếu `ASC_*` / `PLAY_SERVICE_ACCOUNT_JSON` (Quyết định 1C); submit store vẫn tắt.
79
- - **npm-hello registry smoke** — **hard fail** (`examples/npm-hello` → `npm ci` + `npm run smoke`); chứng minh đường install public `@cyberskill/design` (không soft-skip).
82
+ - **npm-hello registry smoke** — **fail-closed** (`examples/npm-hello` → install registry + `npm run smoke`); thiếu `@cyberskill/design@$VERSION` thì job fail (FIND-087). Pack proof local chỉ opt-in trên fork (`NPM_HELLO_ALLOW_LOCAL_PACK`).
80
83
 
81
- Job `figma-variables-push` hay `code-connect` xanh — và do đó badge hay hàng Status xanh — chỉ có nghĩa job exit 0; nó **không** chứng minh sync Figma live, vì soft-skip và publish thật nhìn từ ngoài giống hệt nhau. Mở report artifact của run (`figma-push-report.json` / `code-connect-report.json`) để biết cái nào đã xảy ra.
84
+ Job `figma-variables-push` hay `code-connect` vẫn exit 0 khi soft-skip (Quyết định 1C), nhưng FIND-095 làm outcome hiện trên trang run công khai qua `$GITHUB_STEP_SUMMARY` kèm annotation riêng (`::error::` trên schedule/main, `::warning::` nơi khác) — soft-skip không còn xanh im lặng giống publish thật. Report artifact (`figma-push-report.json` / `code-connect-report.json`) vẫn mang chi tiết.
82
85
 
83
86
  ## Soft-skip dry-run (local)
84
87
 
@@ -1,6 +1,6 @@
1
1
  # Grant consumer — `@cyberskill/design`
2
2
 
3
- **Trạng thái: có hiệu lực** (Th7 2026). Văn bản chính sách — không phải secret. License trên package vẫn **UNLICENSED**; grant này là lớp duyệt dùng trong các sản phẩm đã nêu.
3
+ **Trạng thái: có hiệu lực** (Th7 2026). Văn bản chính sách — không phải secret. License trên package vẫn **UNLICENSED**; grant này là lớp duyệt dùng trong các sản phẩm đã nêu. Xuất bản trên Storybook **Docs** tại `design.cyberskill.world`.
4
4
 
5
5
  ## Grant
6
6
 
@@ -19,10 +19,13 @@ CyberSkill cấp cho **CyberSkill** (công ty và các team kỹ thuật sản p
19
19
 
20
20
  Package vẫn **UNLICENSED**. Cài từ npm registry **không** tự cấp quyền redistribution. Redistribution ngoài các sản phẩm trên — gồm publish fork, đổi license, hoặc ship package như dependency của sản phẩm bên thứ ba không liên quan — cần **grant viết thêm** ghi trong file này (hoặc văn bản thay thế).
21
21
 
22
+ **Ngoại lệ bên thứ ba:** font OFL trong `fonts/`, runtime MIT trong `_vendor/`, và các asset liệt kê ở `THIRD-PARTY-NOTICES.md` giữ license **upstream**. Khẳng định UNLICENSED và grant này **không** thay thế các điều khoản đó; người redistribute phải tuân `fonts/OFL.txt` và file notices.
23
+
22
24
  ## Ghi chú phạm vi
23
25
 
24
26
  - **Clone / subtree / link tĩnh** repo này cho cùng các sản phẩm trên được cover giống npm install.
25
27
  - **Tooling chỉ-host** (Storybook, `_audit/`) không nằm trong tarball npm và không redistribution theo grant này.
28
+ - **Notices bên thứ ba:** xem `THIRD-PARTY-NOTICES.md` và `fonts/OFL.txt` ở root.
26
29
  - Thêm sản phẩm CyberSkill mới: cập nhật `docs/products.md` (+ VI) qua quyết định maintainer, rồi thêm hàng sản phẩm tại đây trong cùng change.
27
30
  - Duyệt **team/client bên ngoài**: thêm stanza grant có ngày bên dưới (team/org, sản phẩm đã nêu, liên hệ). Không invent ánh xạ product → element tại đây — giữ ở `docs/products.md`.
28
31