@tenkara/afm-linux-arm64 0.0.0-stage → 4.0.0-alpha.7

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 (276) hide show
  1. package/bin/afm +4 -0
  2. package/content/.coupling-baseline.tsv +1 -0
  3. package/content/.pending-commands.txt +2 -0
  4. package/content/CHANGELOG-archive.md +806 -0
  5. package/content/CHANGELOG.md +4256 -0
  6. package/content/PRINCIPLES.md +121 -0
  7. package/content/README-light.md +160 -0
  8. package/content/README.md +152 -0
  9. package/content/code-style/_any/file-size.md +62 -0
  10. package/content/code-style/_any/imports.md +68 -0
  11. package/content/code-style/_any/naming.md +72 -0
  12. package/content/code-style/_any/test-placement.md +57 -0
  13. package/content/code-style/nextjs-app-router/imports.md +50 -0
  14. package/content/code-style/nextjs-app-router/naming.md +50 -0
  15. package/content/code-style/prisma-postgres/error-boundary.md +55 -0
  16. package/content/code-style/prisma-postgres/imports.md +61 -0
  17. package/content/code-style/shadcn-ui/naming.md +48 -0
  18. package/content/code-style/stripe-billing/naming.md +76 -0
  19. package/content/code-style/trigger-dev-v4/imports.md +58 -0
  20. package/content/code-style/trigger-dev-v4/naming.md +49 -0
  21. package/content/code-style/trigger-dev-v4/test-placement.md +61 -0
  22. package/content/code-style/trpc-v11/error-boundary.md +51 -0
  23. package/content/code-style/trpc-v11/file-size.md +44 -0
  24. package/content/code-style/trpc-v11/naming.md +60 -0
  25. package/content/code-style/trpc-v11/test-placement.md +52 -0
  26. package/content/core/ach.md +265 -0
  27. package/content/core/afm.md +496 -0
  28. package/content/core/gotchas.md +18 -0
  29. package/content/core/prd.md +143 -0
  30. package/content/core/protocol.md +160 -0
  31. package/content/core/ust.md +65 -0
  32. package/content/guardrails/README.md +55 -0
  33. package/content/guardrails/dsl-com-ordem-obrigatoria.md +47 -0
  34. package/content/guardrails/exaustividade-de-union.md +48 -0
  35. package/content/guardrails/fronteira-de-import.md +57 -0
  36. package/content/hooks/README.md +72 -0
  37. package/content/interview/bootstrap.md +415 -0
  38. package/content/interview/promotion.md +117 -0
  39. package/content/interview/refactor.md +381 -0
  40. package/content/interview/triggers.md +109 -0
  41. package/content/modules/nextjs-app-router/ach.patch.md +44 -0
  42. package/content/modules/nextjs-app-router/gotchas.seed.md +78 -0
  43. package/content/modules/nextjs-app-router/rules.patch.md +35 -0
  44. package/content/modules/prisma-postgres/ach.patch.md +65 -0
  45. package/content/modules/prisma-postgres/rules.patch.md +28 -0
  46. package/content/modules/shadcn-ui/ach.patch.md +42 -0
  47. package/content/modules/stripe-billing/ach.patch.md +46 -0
  48. package/content/modules/stripe-billing/gotchas.seed.md +73 -0
  49. package/content/modules/stripe-billing/rules.patch.md +30 -0
  50. package/content/modules/trigger-dev-v4/ach.patch.md +64 -0
  51. package/content/modules/trigger-dev-v4/gotchas.seed.md +53 -0
  52. package/content/modules/trigger-dev-v4/rules.patch.md +35 -0
  53. package/content/modules/trpc-v11/ach.patch.md +56 -0
  54. package/content/modules/trpc-v11/rules.patch.md +34 -0
  55. package/content/modules/vireya-ui/ach.patch.md +85 -0
  56. package/content/modules/vireya-ui/gotchas.seed.md +98 -0
  57. package/content/modules/vireya-ui/rules.patch.md +36 -0
  58. package/content/ops/adr.md +54 -0
  59. package/content/ops/analyze.md +129 -0
  60. package/content/ops/clarify.md +86 -0
  61. package/content/ops/deliver.md +211 -0
  62. package/content/ops/diagnose.md +146 -0
  63. package/content/ops/evolve.md +317 -0
  64. package/content/ops/export-template.md +97 -0
  65. package/content/ops/generalize.md +120 -0
  66. package/content/ops/gotcha.md +46 -0
  67. package/content/ops/plan.md +61 -0
  68. package/content/ops/policy.md +63 -0
  69. package/content/ops/promote.md +72 -0
  70. package/content/ops/protocol.md +51 -0
  71. package/content/ops/reconcile.md +44 -0
  72. package/content/ops/reflect.md +180 -0
  73. package/content/ops/remediate.md +146 -0
  74. package/content/ops/restructure.md +145 -0
  75. package/content/ops/rule.md +165 -0
  76. package/content/ops/specify.md +62 -0
  77. package/content/ops/tasks.md +67 -0
  78. package/content/ops/update.md +223 -0
  79. package/content/ops/verify.md +69 -0
  80. package/content/patterns/adapter.md +46 -0
  81. package/content/patterns/facade.md +47 -0
  82. package/content/patterns/factory.md +46 -0
  83. package/content/patterns/null-object.md +55 -0
  84. package/content/patterns/result-vs-exception.md +52 -0
  85. package/content/patterns/strategy.md +45 -0
  86. package/content/patterns/template-method-vs-composition.md +50 -0
  87. package/content/questions/adr.questions.yaml +14 -0
  88. package/content/questions/analyze.questions.yaml +12 -0
  89. package/content/questions/bootstrap-mapping.questions.yaml +14 -0
  90. package/content/questions/bootstrap-rules.questions.yaml +10 -0
  91. package/content/questions/bootstrap-stack.questions.yaml +23 -0
  92. package/content/questions/clarify.questions.yaml +10 -0
  93. package/content/questions/code-style.questions.yaml +12 -0
  94. package/content/questions/confirm.questions.yaml +12 -0
  95. package/content/questions/deliver.questions.yaml +23 -0
  96. package/content/questions/evolve.questions.yaml +15 -0
  97. package/content/questions/export-template-apply.questions.yaml +11 -0
  98. package/content/questions/export-template.questions.yaml +23 -0
  99. package/content/questions/gates.questions.yaml +27 -0
  100. package/content/questions/generalize.questions.yaml +13 -0
  101. package/content/questions/gotcha.questions.yaml +11 -0
  102. package/content/questions/init-template.questions.yaml +10 -0
  103. package/content/questions/init.questions.yaml +28 -0
  104. package/content/questions/plan.questions.yaml +14 -0
  105. package/content/questions/refactor.questions.yaml +23 -0
  106. package/content/questions/reflect.questions.yaml +13 -0
  107. package/content/questions/remediate.questions.yaml +27 -0
  108. package/content/questions/restructure.questions.yaml +15 -0
  109. package/content/questions/rf-mapping.questions.yaml +12 -0
  110. package/content/questions/rule-scope.questions.yaml +12 -0
  111. package/content/questions/rule.questions.yaml +12 -0
  112. package/content/questions/specify.questions.yaml +23 -0
  113. package/content/questions/update-artifacts.questions.yaml +10 -0
  114. package/content/questions/update-strings.questions.yaml +14 -0
  115. package/content/questions/update.questions.yaml +10 -0
  116. package/content/questions/verify.questions.yaml +9 -0
  117. package/content/roles/executor.md +18 -0
  118. package/content/roles/explorer.md +22 -0
  119. package/content/roles/reviewer.md +23 -0
  120. package/content/rubrics/enum-vs-union-vs-branded.md +40 -0
  121. package/content/rubrics/episodic-vs-semantic-boundary.md +37 -0
  122. package/content/rubrics/error-classification.md +98 -0
  123. package/content/rubrics/failure-classification.md +113 -0
  124. package/content/rubrics/negative-filters.md +38 -0
  125. package/content/rubrics/solid-triggers.md +121 -0
  126. package/content/rubrics/template-vs-streaming-precedence.md +34 -0
  127. package/content/rubrics/validation-boundary.md +94 -0
  128. package/content/rubrics/when-to-create-dsl.md +65 -0
  129. package/content/rubrics/when-to-create-lib.md +49 -0
  130. package/content/rubrics/when-to-create-module.md +39 -0
  131. package/content/rubrics/when-to-evolve-methodology.md +62 -0
  132. package/content/skills/adr.md +42 -0
  133. package/content/skills/analyze.md +34 -0
  134. package/content/skills/clarify.md +34 -0
  135. package/content/skills/deliver.md +42 -0
  136. package/content/skills/diagnose.md +50 -0
  137. package/content/skills/evolve.md +67 -0
  138. package/content/skills/export-template.md +40 -0
  139. package/content/skills/generalize.md +47 -0
  140. package/content/skills/gotcha.md +40 -0
  141. package/content/skills/init.md +82 -0
  142. package/content/skills/plan.md +34 -0
  143. package/content/skills/policy.md +31 -0
  144. package/content/skills/promote.md +41 -0
  145. package/content/skills/protocol.md +42 -0
  146. package/content/skills/reconcile.md +49 -0
  147. package/content/skills/refactor.md +84 -0
  148. package/content/skills/reflect.md +53 -0
  149. package/content/skills/remediate.md +39 -0
  150. package/content/skills/restructure.md +52 -0
  151. package/content/skills/rule.md +44 -0
  152. package/content/skills/specify.md +34 -0
  153. package/content/skills/tasks.md +34 -0
  154. package/content/skills/update.md +56 -0
  155. package/content/skills/verify.md +31 -0
  156. package/content/templates/adr.template.md +51 -0
  157. package/content/templates/evolution-report.template.md +129 -0
  158. package/content/templates/feature-plan.template.md +86 -0
  159. package/content/templates/feature-research.template.md +57 -0
  160. package/content/templates/feature-spec.template.md +86 -0
  161. package/content/templates/feature-tasks.induced.template.md +67 -0
  162. package/content/templates/feature-tasks.template.md +60 -0
  163. package/content/templates/focus.template.md +30 -0
  164. package/content/templates/gotcha.template.md +31 -0
  165. package/content/templates/guardrail-runner.template.md +81 -0
  166. package/content/templates/guardrail.template.md +63 -0
  167. package/content/templates/learning.template.md +40 -0
  168. package/content/templates/procedure.template.md +47 -0
  169. package/content/templates/protocols/p1.md +29 -0
  170. package/content/templates/protocols/p2.md +28 -0
  171. package/content/templates/protocols/p3.md +47 -0
  172. package/content/templates/research.template.md +50 -0
  173. package/content/templates/session-handoff.template.md +58 -0
  174. package/content/templates/us.template.md +39 -0
  175. package/content/tools/gate/core-rules/PLUGIN-13-secrets.sh +36 -0
  176. package/content/tools/gate/core-rules/PLUGIN-21-code-language.sh +27 -0
  177. package/content/tools/gate/core-rules/PLUGIN-35-gate-complete.sh +19 -0
  178. package/content/tools/gate/core-rules/PLUGIN-36-absolute-path.sh +38 -0
  179. package/content/tools/gate/core-rules/PLUGIN-37-prose-language.sh +56 -0
  180. package/content/tools/gate/core-rules/PLUGIN-38-parser-marker.sh +82 -0
  181. package/content/tools/gate/core-rules/PLUGIN-39-frontmatter-ops.sh +325 -0
  182. package/content/tools/gate/core-rules/PLUGIN-40-dead-reference.sh +74 -0
  183. package/content/tools/gate/core-rules/README.md +55 -0
  184. package/content/tools/gate/guardrails.sh +740 -0
  185. package/content/tools/gate/lib/ratchet.sh +119 -0
  186. package/content/tools/gate/lib/scope.sh +85 -0
  187. package/content/tools/gate/ratchet.seed.tsv +1 -0
  188. package/content/tools/gate/rules/README.md +50 -0
  189. package/package.json +19 -5
  190. package/plugin/agy/hooks.json +29 -0
  191. package/plugin/agy/mcp_config.json +7 -0
  192. package/plugin/agy/plugin.json +6 -0
  193. package/plugin/agy/skills/afm-adr/SKILL.md +44 -0
  194. package/plugin/agy/skills/afm-analyze/SKILL.md +36 -0
  195. package/plugin/agy/skills/afm-clarify/SKILL.md +36 -0
  196. package/plugin/agy/skills/afm-deliver/SKILL.md +44 -0
  197. package/plugin/agy/skills/afm-diagnose/SKILL.md +50 -0
  198. package/plugin/agy/skills/afm-evolve/SKILL.md +69 -0
  199. package/plugin/agy/skills/afm-export-template/SKILL.md +42 -0
  200. package/plugin/agy/skills/afm-generalize/SKILL.md +49 -0
  201. package/plugin/agy/skills/afm-gotcha/SKILL.md +42 -0
  202. package/plugin/agy/skills/afm-init/SKILL.md +84 -0
  203. package/plugin/agy/skills/afm-plan/SKILL.md +36 -0
  204. package/plugin/agy/skills/afm-policy/SKILL.md +31 -0
  205. package/plugin/agy/skills/afm-promote/SKILL.md +41 -0
  206. package/plugin/agy/skills/afm-protocol/SKILL.md +42 -0
  207. package/plugin/agy/skills/afm-reconcile/SKILL.md +49 -0
  208. package/plugin/agy/skills/afm-refactor/SKILL.md +86 -0
  209. package/plugin/agy/skills/afm-reflect/SKILL.md +55 -0
  210. package/plugin/agy/skills/afm-remediate/SKILL.md +41 -0
  211. package/plugin/agy/skills/afm-restructure/SKILL.md +54 -0
  212. package/plugin/agy/skills/afm-rule/SKILL.md +46 -0
  213. package/plugin/agy/skills/afm-specify/SKILL.md +36 -0
  214. package/plugin/agy/skills/afm-tasks/SKILL.md +34 -0
  215. package/plugin/agy/skills/afm-update/SKILL.md +58 -0
  216. package/plugin/agy/skills/afm-verify/SKILL.md +33 -0
  217. package/plugin/claude-code/.claude-plugin/marketplace.json +15 -0
  218. package/plugin/claude-code/.claude-plugin/plugin.json +9 -0
  219. package/plugin/claude-code/.mcp.json +7 -0
  220. package/plugin/claude-code/agents/afm-executor.md +18 -0
  221. package/plugin/claude-code/agents/afm-explorer.md +20 -0
  222. package/plugin/claude-code/agents/afm-reviewer.md +21 -0
  223. package/plugin/claude-code/hooks/hooks.json +85 -0
  224. package/plugin/claude-code/skills/adr/SKILL.md +44 -0
  225. package/plugin/claude-code/skills/analyze/SKILL.md +36 -0
  226. package/plugin/claude-code/skills/clarify/SKILL.md +36 -0
  227. package/plugin/claude-code/skills/deliver/SKILL.md +44 -0
  228. package/plugin/claude-code/skills/diagnose/SKILL.md +50 -0
  229. package/plugin/claude-code/skills/evolve/SKILL.md +69 -0
  230. package/plugin/claude-code/skills/export-template/SKILL.md +42 -0
  231. package/plugin/claude-code/skills/generalize/SKILL.md +49 -0
  232. package/plugin/claude-code/skills/gotcha/SKILL.md +42 -0
  233. package/plugin/claude-code/skills/init/SKILL.md +84 -0
  234. package/plugin/claude-code/skills/plan/SKILL.md +36 -0
  235. package/plugin/claude-code/skills/policy/SKILL.md +31 -0
  236. package/plugin/claude-code/skills/promote/SKILL.md +41 -0
  237. package/plugin/claude-code/skills/protocol/SKILL.md +42 -0
  238. package/plugin/claude-code/skills/reconcile/SKILL.md +49 -0
  239. package/plugin/claude-code/skills/refactor/SKILL.md +86 -0
  240. package/plugin/claude-code/skills/reflect/SKILL.md +55 -0
  241. package/plugin/claude-code/skills/remediate/SKILL.md +41 -0
  242. package/plugin/claude-code/skills/restructure/SKILL.md +54 -0
  243. package/plugin/claude-code/skills/rule/SKILL.md +46 -0
  244. package/plugin/claude-code/skills/specify/SKILL.md +36 -0
  245. package/plugin/claude-code/skills/tasks/SKILL.md +34 -0
  246. package/plugin/claude-code/skills/update/SKILL.md +58 -0
  247. package/plugin/claude-code/skills/verify/SKILL.md +33 -0
  248. package/plugin/opencode/afm.js +196 -0
  249. package/plugin/opencode/agents/afm-executor.md +31 -0
  250. package/plugin/opencode/agents/afm-explorer.md +47 -0
  251. package/plugin/opencode/agents/afm-reviewer.md +48 -0
  252. package/plugin/opencode/skills/afm-adr/SKILL.md +44 -0
  253. package/plugin/opencode/skills/afm-analyze/SKILL.md +36 -0
  254. package/plugin/opencode/skills/afm-clarify/SKILL.md +36 -0
  255. package/plugin/opencode/skills/afm-deliver/SKILL.md +44 -0
  256. package/plugin/opencode/skills/afm-diagnose/SKILL.md +50 -0
  257. package/plugin/opencode/skills/afm-evolve/SKILL.md +69 -0
  258. package/plugin/opencode/skills/afm-export-template/SKILL.md +42 -0
  259. package/plugin/opencode/skills/afm-generalize/SKILL.md +49 -0
  260. package/plugin/opencode/skills/afm-gotcha/SKILL.md +42 -0
  261. package/plugin/opencode/skills/afm-init/SKILL.md +84 -0
  262. package/plugin/opencode/skills/afm-plan/SKILL.md +36 -0
  263. package/plugin/opencode/skills/afm-policy/SKILL.md +31 -0
  264. package/plugin/opencode/skills/afm-promote/SKILL.md +41 -0
  265. package/plugin/opencode/skills/afm-protocol/SKILL.md +42 -0
  266. package/plugin/opencode/skills/afm-reconcile/SKILL.md +49 -0
  267. package/plugin/opencode/skills/afm-refactor/SKILL.md +86 -0
  268. package/plugin/opencode/skills/afm-reflect/SKILL.md +55 -0
  269. package/plugin/opencode/skills/afm-remediate/SKILL.md +41 -0
  270. package/plugin/opencode/skills/afm-restructure/SKILL.md +54 -0
  271. package/plugin/opencode/skills/afm-rule/SKILL.md +46 -0
  272. package/plugin/opencode/skills/afm-specify/SKILL.md +36 -0
  273. package/plugin/opencode/skills/afm-tasks/SKILL.md +34 -0
  274. package/plugin/opencode/skills/afm-update/SKILL.md +58 -0
  275. package/plugin/opencode/skills/afm-verify/SKILL.md +33 -0
  276. package/README.md +0 -3
@@ -0,0 +1,85 @@
1
+ ---
2
+ type: module
3
+ description: 'Adds Vireya token-first primitive, package, and provider conventions to the materialized ACH. It replaces the shadcn-style module.'
4
+ load: cold
5
+ stack: vireya-ui
6
+ patches: 'docs/ach.md'
7
+ detect: |
8
+ if command -v jq >/dev/null 2>&1; then jq -e '(.dependencies//{})+(.devDependencies//{})+(.peerDependencies//{})|keys|any(startswith("@vireya/"))' package.json >/dev/null 2>&1; else grep -q '"@vireya/' package.json 2>/dev/null; fi
9
+ ---
10
+
11
+ # Patch — ACH for projects with Vireya Design System
12
+
13
+ > Applies to `/docs/ach.md`. It adds conventions for UI primitives, tokens, packages, and providers.
14
+ >
15
+ > **Context:** Vireya is a token-first design system in React 19. It ships as a pnpm monorepo. It replaces shadcn-style primitives. It does not use `components.json` or `npx shadcn add`. It uses the private Gitea registry (`@vireya:registry`).
16
+
17
+ ## §3.2 — UI primitives via Vireya
18
+
19
+ ```md
20
+ #### UI primitives — `@vireya/ui` (per-component subpaths)
21
+
22
+ - **What it is:** 67 React components in `@vireya/ui` plus 26 composed blocks in `@vireya/blocks`. Token-first: all styling uses CSS Modules with `--v-*` tokens.
23
+ - **Responsibility:** presentation and interaction. Forms keep local state. Remote state goes through the transport client (tRPC + React Query, etc).
24
+ - **Stack:** React 19.2.1 (pinned), `@vireya/core` (tokens + `createTheme`), `@vireya/ui` (components), `@vireya/next` (server `ThemeProvider` and client `useTheme`), `@vireya/blocks` (pre-composed sections).
25
+
26
+ ##### Imports — per-component subpath, NEVER the root barrel
27
+
28
+ ```ts
29
+ // ✅
30
+ import { Button } from "@vireya/ui/form/button";
31
+ import { Dialog } from "@vireya/ui/overlay/dialog";
32
+ import { HeroCentered } from "@vireya/blocks/hero/centered";
33
+ import enUS from "@vireya/ui/locales/enUS";
34
+
35
+ // ❌ root barrel (forbidden for Button, Dialog, etc.)
36
+ import { Button } from "@vireya/ui";
37
+ ```
38
+
39
+ **One exception:** `AppProvider` is exported from the `@vireya/ui` root barrel. It is the only allowed root import.
40
+
41
+ ##### Next.js setup
42
+
43
+ ```tsx
44
+ // app/layout.tsx
45
+ import { ThemeProvider } from "@vireya/next";
46
+ import { AppProvider } from "@vireya/ui";
47
+ import enUS from "@vireya/ui/locales/enUS";
48
+
49
+ <ThemeProvider>
50
+ <AppProvider locale={enUS} icons={...}>
51
+ {children}
52
+ </AppProvider>
53
+ </ThemeProvider>
54
+ ```
55
+
56
+ ##### Tokens — absolute `--v-*` tokens
57
+
58
+ Every visual CSS property must use a `--v-*` token. A hardcoded `px`, `#hex`, or `rgb()` value is a bug. The only allowed literals are: `0`, `100%`, `9999px` (a true pill), `1px`/`1.4px` for inline-SVG hairlines, `currentColor` in icons, and percentages inside `calc()`.
59
+
60
+ The full token catalog lives in `@vireya/core` (reference) and in the Vireya skill file `references/tokens.md`.
61
+
62
+ ##### `primary` is not `accent`
63
+
64
+ - `primary` — neutral-strong (near-black in light mode, near-white in dark mode). Use it for body text and default CTAs.
65
+ - `accent` — brand-vivid (magenta, teal, etc.). It is **optional** and falls back to `primary`. Use it only for promotional or highlight elements (a popular badge, a focus ring, a hero CTA).
66
+
67
+ Always chain the fallback in CSS:
68
+
69
+ ```css
70
+ background-color: var(--v-accent-fill, var(--v-primary-fill));
71
+ color: var(--v-accent-foreground, var(--v-primary-foreground));
72
+ border-color: var(--v-accent-border, var(--v-primary-border));
73
+ ```
74
+ ```
75
+
76
+ ## §6 — Add Vireya conventions
77
+
78
+ ```md
79
+ ### Vireya Design System
80
+
81
+ - **Skill:** if you use Claude Code, the `vireya` skill (at `vireya.mapree.dev/skills/vireya/`) has the full catalog of components, blocks, and tokens. It triggers automatically on "vireya", "@vireya/*", or "create a Vireya component".
82
+ - **Per-component prop details:** open the component's `index.tsx` file. The `IProps` interfaces live next to the code and are authoritative. Do not memorize props. Navigate to the source instead.
83
+ - **CSS Modules + forwardRef + asChild:** this pattern is mandatory for Vireya components. Each component needs a CSS Module, a forwarded ref, and `asChild` support for polymorphism through Radix.
84
+ - **New component in the consumer project:** never duplicate a visual that already exists in `@vireya/ui`. Extend it with a wrapper, or open an upstream issue to add it.
85
+ ```
@@ -0,0 +1,98 @@
1
+ ---
2
+ type: module
3
+ description: 'Seed gotchas for the Vireya Design System, starting with the root barrel import breaking tree-shaking.'
4
+ load: cold
5
+ stack: vireya-ui
6
+ patches: 'docs/gotchas/*.md'
7
+ detect: |
8
+ if command -v jq >/dev/null 2>&1; then jq -e '(.dependencies//{})+(.devDependencies//{})+(.peerDependencies//{})|keys|any(startswith("@vireya/"))' package.json >/dev/null 2>&1; else grep -q '"@vireya/' package.json 2>/dev/null; fi
9
+ ---
10
+
11
+ # Gotchas seed — Vireya Design System
12
+
13
+ > Each entry below is a complete gotcha file. Copy one to `docs/gotchas/NNN-slug.md` (the first `---` of the entry as line 1) only when it bites in real use. Re-date `last_bite` on copy.
14
+
15
+ ---
16
+ type: gotcha
17
+ description: 'The root barrel import from @vireya/ui adds every component to the bundle because the bundler cannot tree-shake the eager re-exports.'
18
+ load: warm
19
+ fires_on: event
20
+ fires_when: 'you import a component from @vireya/ui and you consider the root barrel.'
21
+ bites: 1
22
+ last_bite: 2026-10
23
+ ---
24
+
25
+ ## Vireya — root barrel import breaks tree-shaking
26
+
27
+ ## Behavior
28
+
29
+ The root barrel (`import { Button } from "@vireya/ui"`) adds all 67 components to the bundle, even if you use 1. The bundler cannot tree-shake because `index.ts` re-exports everything eagerly.
30
+
31
+ ## Solution
32
+
33
+ Always use a per-component subpath: `import { Button } from "@vireya/ui/form/button"`. The same rule applies to `@vireya/blocks/<category>/<name>`. One exception: `AppProvider` (exposed at the root on purpose, for ergonomic setup).
34
+
35
+ ---
36
+ type: gotcha
37
+ description: 'CI rewrites package.json versions to 0.0.0-rc.N on push to dev, so the working directory shows a version that is not the published one.'
38
+ load: warm
39
+ fires_on: event
40
+ fires_when: 'you debug an install, or you try to find the @vireya/ui version in use.'
41
+ bites: 1
42
+ last_bite: 2026-10
43
+ ---
44
+
45
+ ## Vireya — `package.json` versions show `0.0.0-rc.<N>` in the working directory
46
+
47
+ ## Behavior
48
+
49
+ The Gitea CI release workflow rewrites the `version` field of every `packages/*/package.json` to `0.0.0-rc.{commitCount}` on push to `dev`. The local working directory shows `0.0.0` or similar. This is not the real published version.
50
+
51
+ ## Solution
52
+
53
+ Check the real version with `pnpm list @vireya/ui` after install. It matches the registry `rc.{commitCount}`. Do not trust the local `package.json` to track the version.
54
+
55
+ ---
56
+ type: gotcha
57
+ description: 'The @vireya scope is a private Gitea registry; without credentials in .npmrc the install fails silently or pulls the wrong version from the public registry.'
58
+ load: warm
59
+ fires_on: event
60
+ fires_when: 'pnpm install fails with a 401 or 404 error on @vireya/*.'
61
+ bites: 1
62
+ last_bite: 2026-10
63
+ ---
64
+
65
+ ## Vireya — the private registry needs a configured `.npmrc`
66
+
67
+ ## Behavior
68
+
69
+ `@vireya:registry` is a private Gitea registry. Without valid credentials in `.npmrc`, the install fails silently or pulls the wrong version from the public registry.
70
+
71
+ ## Solution
72
+
73
+ Make sure the project `.npmrc` has the two lines below, with the registry URL and the token of your Gitea instance. Pass the token through an env var in CI.
74
+
75
+ ```
76
+ @vireya:registry=<GITEA_REGISTRY_URL>
77
+ //<GITEA_HOST>/api/packages/vireya/npm/:_authToken=<TOKEN>
78
+ ```
79
+
80
+ ---
81
+ type: gotcha
82
+ description: 'Docs and Storybook can lag behind the code; the IProps type exported next to a Vireya component is always current.'
83
+ load: warm
84
+ fires_on: event
85
+ fires_when: 'you check the docs or Storybook for a Vireya component prop and the behavior does not match.'
86
+ bites: 1
87
+ last_bite: 2026-10
88
+ ---
89
+
90
+ ## Vireya — `IProps` is the authoritative source, NOT external documentation
91
+
92
+ ## Behavior
93
+
94
+ The docs and Storybook can lag behind the code. The `IProps` type exported next to the component's `index.tsx` is always current.
95
+
96
+ ## Solution
97
+
98
+ When in doubt, open `node_modules/@vireya/ui/<category>/<component>/index.d.ts` (or the monorepo source). Do not memorize props from the skill or the docs. Go to the source instead.
@@ -0,0 +1,36 @@
1
+ ---
2
+ type: module
3
+ description: 'Hard rules for projects that use Vireya UI, split between executable triggers and review-only principles.'
4
+ load: cold
5
+ stack: vireya-ui
6
+ patches: 'docs/rules/*.md'
7
+ detect: |
8
+ if command -v jq >/dev/null 2>&1; then jq -e '(.dependencies//{})+(.devDependencies//{})+(.peerDependencies//{})|keys|any(startswith("@vireya/"))' package.json >/dev/null 2>&1; else grep -q '"@vireya/' package.json 2>/dev/null; fi
9
+ ---
10
+
11
+ # Patch — Hard rules for projects that use Vireya UI
12
+
13
+ > Hard rules (with an executable trigger) go after the last hard rule in `/docs/afm.md` §3.
14
+ > Principles (checked only by review) go in `/docs/afm.md` §1.3. They do **not** become hard rules. The §3 contract needs an executable trigger.
15
+
16
+ ## Hard rules (executable trigger)
17
+
18
+ - **Absolute tokens. Zero hardcoded values in visual CSS.** Every visual CSS property must use a `--v-*` token. A hardcoded `px`, `#hex`, `rgb()`, or `rgba()` in a style file is a bug. Allowed literals: `0`, `100%`, `9999px`, `1px` or `1.4px` (inline-SVG hairlines), `currentColor`, and percentages inside `calc()`.
19
+ *Verification:* `grep -rnE "#[0-9a-fA-F]{3,6}|rgba?\(|[0-9]+px" --include='*.css' {{src-path}}` (this covers `*.module.css`). Review the context and exclude the allowed literals.
20
+ - **Per-component subpath imports. Never the root barrel.** Import `@vireya/ui` and `@vireya/blocks` only through subpaths. The one exception is `AppProvider` from the root barrel.
21
+ *Verification:* `grep -rnE 'from "@vireya/(ui|blocks)"' {{src-path}}` must return 0 results, except for `AppProvider`.
22
+ - **Use `:focus-visible`, never `:focus`.** Style disabled elements as `opacity: 0.5; cursor: not-allowed;`. Do not use a custom gray color for disabled state.
23
+ *Verification:* `grep -rnE ":focus([^-]|$)" --include='*.css' {{src-path}}` must return 0 results (`[^-]|$` excludes `:focus-visible` without needing PCRE lookahead). Review `grep -rnE "color.*#[0-9a-fA-F]{3,6}.*disabled" --include='*.css' {{src-path}}` by hand.
24
+ - **`accent` must always fall back to `primary`.** The `--v-accent-*` token is optional. Chain the CSS as `var(--v-accent-fill, var(--v-primary-fill))`.
25
+ *Verification:* `grep -rnE "var\(--v-accent-[^,)]+\)" --include='*.css' {{src-path}}` flags any accent use without a fallback.
26
+
27
+ > The React-version pin ("sync the whole monorepo to 19.2.1") used to be a hard rule here. A
28
+ > version pin is an operator decision that goes stale the moment React ships a patch release, not
29
+ > a Vireya fact — Vireya itself only requires React 19. It is not migrated to a
30
+ > `code-style/vireya-ui/` seed: none of the five code-style concerns (naming, test-placement,
31
+ > file-size, error-boundary, imports) fit a version-pinning policy. If a workspace needs one,
32
+ > state it in that project's own `docs/afm.md` §3, with a version the operator owns and updates.
33
+
34
+ ## Principles (insert in §1.3 — review, not a trigger)
35
+
36
+ - **A custom component must not copy an existing Vireya component's look.** Check `@vireya/ui` for a match first. *(No grep can detect "this copies that" — it needs review. A PR that adds a component must explain why `@vireya/ui` does not already cover the need.)*
@@ -0,0 +1,54 @@
1
+ ---
2
+ type: op
3
+ description: Records one load-bearing decision as an ADR, with its context and its consequence.
4
+ load: warm
5
+ writes: ["docs/adr/*.md"]
6
+ composes: []
7
+ ---
8
+ # Sub-flow: create an ADR
9
+
10
+ > **Form** — effect: `docs/adr/NNNN-*.md` · trigger: `afm adr`, composition · precondition: `.afm-version` · used by: `evolve`, `restructure` · **degree of freedom: low**
11
+
12
+ Triggers: `afm adr`, or natural language ("create ADR", "architecture decision").
13
+
14
+ The CLI owns the mechanics: the next number, the template, the frontmatter keys the template names
15
+ (`type: adr`, `description`, `load: warm`, `status`, `date`, `decided_by`), the supersede link and the index. This op owns
16
+ what only the operator knows: the decision itself.
17
+
18
+ ## Procedure
19
+
20
+ 1. `afm preflight`. Exit 3 means there is no instance: stop and run `afm init` (greenfield) or
21
+ `afm refactor` (brownfield).
22
+ 2. **Ask the status** with `afm ask adr` (questions in `content/questions/adr.questions.yaml`).
23
+ Status is intent, not discoverable state.
24
+ 3. **Collect the content as free text**, because it describes and does not choose: the **title**
25
+ (short, names the decision, not the problem), the **context**, the **decision**, the
26
+ **alternatives** and the **consequence**, and the **refs** (commit, RF, gotcha, when they apply).
27
+ 4. **Create the file**: `afm adr new <slug> --title "<title>" --description "<one sentence saying what the reader learns>" --status <proposed|accepted|deprecated> --decided-by "<who>"` (the status answer of step 2; omit `--decided-by` when nobody said and it stays `[TBD]`). Add `--supersedes N` when the decision replaces ADR N. The command
28
+ retires ADR N in the same step and refreshes the indexes. It prints the path.
29
+ 5. **Fill the sections** of the printed file with the free-text answers. Everything the operator did
30
+ not say stays `[TBD]`; inventing a context or a consequence is worse than leaving it open.
31
+ 6. **Adjust the frontmatter only where the answer needs it:**
32
+ - The metadata lives only in the frontmatter; the body starts at its H1 and carries no
33
+ `> **Status:**` line.
34
+ - **Superseded by ADR-NNNN** is set by `--supersedes N` on the new ADR (the old one gets
35
+ `status: superseded` and `superseded_by`); by hand it is both keys.
36
+ - Add `trigger_path` only when the decision constrains one path or glob. Most decisions bind
37
+ none, and a guessed path is worse than an absent key.
38
+ - After a hand edit of the frontmatter run `afm index --materialize`; hard rule 39 fails on a
39
+ stale index.
40
+ 7. **Report the path.** Writing is autonomy-first (invariant principle #6): the operator reviews with
41
+ `git diff`.
42
+
43
+ ## Additional step in a refactored project
44
+
45
+ > Applies only if the project adopted AFM through `afm refactor` (signal: `afm.md` § 3.1
46
+ > forward-only exists, or the README or history shows retroactive adoption). In a greenfield project
47
+ > skip it: a retroactive ADR is forbidden after `afm init`.
48
+
49
+ A retroactive ADR is allowed here, with a load-bearing guardrail:
50
+
51
+ - The decision must still be load-bearing today. Swapping or removing it would break something visible.
52
+ - A dead decision (once relevant, not relevant now) does not become an ADR. Record it as a note in
53
+ `ach.md` instead.
54
+ - See invariant principle #9 in `afm path PRINCIPLES`.
@@ -0,0 +1,129 @@
1
+ ---
2
+ type: op
3
+ description: Validates spec, plan and tasks against each other and reports what disagrees.
4
+ load: warm
5
+ writes: []
6
+ composes: []
7
+ needs: ["feature"]
8
+ ---
9
+ # Sub-flow: Cross-Artifact Validation for the Feature (`analyze`)
10
+
11
+ > **Form** — effect: **read-only** (chat) · trigger: `afm analyze`, composition · precondition: spec+plan+tasks · composed by: `deliver` 1.E · **degree of freedom: medium**
12
+
13
+ Triggers: `afm analyze [<feature>]`, or natural language ("audit the feature", "check coverage", "validate consistency").
14
+
15
+ > Suggested (not a hard gate) between `afm tasks` and the start of T001. It writes no file: the output is read-only in chat, with remediation on demand.
16
+
17
+ The fixed question of this op is data: `questions/analyze.questions.yaml`, asked with `afm ask analyze --scope <slug>`. Choosing among several features is a dynamic list: ask it in plain words.
18
+
19
+ ## The mechanical part is a command
20
+
21
+ `afm feature lint <NNN>` runs passes **A** (coverage), **C** (inconsistency), **D** (ambiguity), **E** (underspecification) and the structure of `tasks.md` (pass **T**). It applies the severity matrix below, caps the list at 50 findings, groups the rest as an overflow count, and exits 1 on CRITICAL or HIGH. `--json` gives `{findings, overflow}` for machines. **Run it first and start from its findings.** Do not recompute them by reading.
22
+
23
+ What stays judgment, and is yours: pass **B** (constitution violations), pass **F** (duplication), the semantic side of C and D (terminology drift, a `Then` that is not observable, a plan § 7 rule marked applicable but contradicted by the content), the load-bearing sort of the gating mode, and the coverage table. You add those on top of the command's output.
24
+
25
+ ## Two Modes
26
+
27
+ `analyze` is the **verification engine** of AFM (the verification corollary of #6 in [`../PRINCIPLES.md`](../PRINCIPLES.md)). It runs in two modes. The detection passes are identical. Only what happens to the findings changes.
28
+
29
+ - **Advisory mode (default, `afm analyze` à la carte):** the full flow below. Read-only in chat, a suggestion and not a gate, remediation on demand. This is what the operator invokes to audit a feature.
30
+ - **Gating mode (in-loop, called by `deliver` Phase 1.E):** detection is the same. It **sorts** each finding into the three buckets of the verification corollary and writes **no** report in chat. The caller presents the result:
31
+ - **(a) resolvable by evidence:** the fix comes from code, `docs/` or a page read. It **auto-corrects** the artifact and notes it in the summary. Example: the spec says "saves to the database" without naming the store, and the code already uses Prisma with Postgres.
32
+ - **(b) load-bearing and not resolvable alone**, by the **structural test of #6**: the wrong choice changes *which components, boundaries or tasks get created* (the structural inventory), not just their content. Example: "the US says 'recurring subscription', I inferred Stripe subscriptions. If it is one-time, the task and webhook inventory changes entirely" is (b). "The spec does not state the button copy" changes only content, so it is **not** (b). It becomes an **earned question** (recommendation-first, with the evidence and "what changes in the structure if this is wrong") and goes back to the caller for the gate. **CRITICAL** changes the inventory of the whole plan (layer, module, contract). **HIGH** changes the inventory of one isolated feature or task.
33
+ - **(c) not load-bearing and not resolvable** (cosmetic or deferrable): it becomes `[TBD]` or `[NEEDS CLARIFICATION:]` for reconcile.
34
+ - **Loop until zero.** After auto-correcting (a), **re-run** `afm feature lint` and the judgment passes. Repeat until **CRITICAL and HIGH are 0**, or until nothing new gets auto-corrected. The cap is 3 auto-fix rounds. A stuck CRITICAL or HIGH after 3 rounds goes to (b); a CRITICAL never becomes deferrable. Remaining MEDIUM and LOW findings do not block: they become a note in the gate summary, and a stuck one becomes (c).
35
+ - **Anti-oscillation history (Self-Refine, arXiv:2303.17651).** Keep the list `finding -> fix applied` across rounds. A finding that reappears after an earlier round "fixed" it is an **oscillation**: the loop undid and redid the same edit. Do not auto-correct it again. Promote it straight to (b) with the note "oscillated: fix X applied and reverted N times".
36
+ - Questions of bucket (b) follow the holistic cap of #8: at most `QUESTION_CAP` per call, added to the discovery questions inside the flow's `ROUND_CAP` (read both with `afm protocol`).
37
+
38
+ Procedure (advisory mode; gating mode reuses steps 2 to 5 and replaces 6 to 8 with the sorting above):
39
+
40
+ 1. **Pre-check.** Run `afm preflight` (exit 3: no `docs/.afm-version`, redirect to `afm init` or `afm refactor`). Find the feature: the `<feature>` argument, or the folder with a materialized `docs/features/NNN-*/tasks.md`.
41
+ - Zero features with tasks: say "Nothing to analyze: run `afm tasks` first." and stop.
42
+ - Several: ask in plain words with up to 4 candidates.
43
+
44
+ 2. **Progressive load** (token-efficient, read only what is needed):
45
+ - `docs/features/NNN-feature/spec.md`: § 1, § 2, § 3, § 5, § 6 and, if present, § 7 Clarifications.
46
+ - `docs/features/NNN-feature/plan.md`: § 1, § 2, § 4, § 5, § 6 and § 7 (validation against the invariants).
47
+ - `docs/features/NNN-feature/tasks.md`: the full list with US and RF refs, `[P]` markers and phases.
48
+ - `docs/prd.md`: § 3 persona and § 4 RFs (only the sections relevant to the linked US).
49
+ - `docs/ust.md`: the US row linked to the feature.
50
+ - `docs/ach.md`: § 1 stack and § 3.1 component-type mapping.
51
+ - `docs/afm.md` § 3: the hard rules that apply to the feature's scope.
52
+ - [`../PRINCIPLES.md`](../PRINCIPLES.md): the universal invariants (the constitution).
53
+
54
+ 3. **Build the semantic models** (in memory, not in a file):
55
+ - **Requirements inventory:** each Gherkin scenario of spec § 3 gets an id `S1`, `S2`, ...; each success-criterion checkbox of § 2 becomes `C1`, `C2`, ...
56
+ - **Component inventory:** each row of plan § 2 with its file path.
57
+ - **Boundary inventory:** each boundary of plan § 5.
58
+ - **Task coverage map:** each task `T0NN` maps to a scenario (S?), a component (§ 2) or a hard rule (§ 7).
59
+ - **Constitution rule set:** the universal invariants (`PRINCIPLES.md` § 1 to 8) plus the hard rules (`afm.md` § 3) marked in `plan.md` § 7.
60
+
61
+ 4. **Detection passes** (limit: **50 findings in total**; group the excess in an "overflow summary"). `afm feature lint` already produced A, C, D, E and T. You add B and F, and what is semantic in C and D.
62
+
63
+ - **A. Coverage gaps** (HIGH by default): a scenario with no RED+GREEN pair; a new component with no creation task in Phase 1 or 2; an applicable hard rule with no task that adds the check (rule 16 needs a Zod schema at the boundary); a missing Phase 4 reconciliation (ach update, ADR, US status, the `status` frontmatter key of the three files set to `done`); an external boundary with no input-validation task plus a procedure task that consumes it.
64
+ - **B. Constitution violation** (CRITICAL by default): the plan chose a stack that diverges from `ach.md § 1` (#5, do not invent); the spec invented a § 2 criterion not derivable from the linked US (#5); a task skips RED (rule 1, TDD: any GREEN with no RED immediately before it); a plan § 4 decision with no rejected alternative and reason; a plan § 6 item with no rejected simpler alternative; a #6 bright line crossed with no confirmation (a destructive operation with no diff, an automatic push, a plugin edit with no confirmation). Check the session history when you can infer it. *Applying autonomously inside the scope of an invoked op is NOT a violation: #6 expects it.*
65
+ - **C. Inconsistency** (HIGH or MEDIUM): terminology drift (an entity with different names across spec, plan and ust); a plan § 2 component type not mapped in `ach.md § 3.1`; tasks citing a `US-NNN` missing from `ust.md`; a plan § 7 rule marked `[x]` applicable but contradicted by the content (rule 16 marked, but § 5 has no Zod); a spec § 3 scenario citing an entity field absent from the `ach.md` mini-ER.
66
+ - **D. Ambiguity** (LOW or MEDIUM): vague adjectives with no measurable criterion (`fast`, `scalable`, `secure`, `intuitive`, `robust`) in § 2; unresolved placeholders (`TODO`, `TKTK`, `???`, `{{x}}`) in required sections; open `[NEEDS CLARIFICATION:]` markers (a strong signal for `afm clarify`).
67
+ - **E. Underspecification** (HIGH or MEDIUM): a scenario with no observable `Then` ("Then it works correctly"); a task with no `US-NNN` or `RF-NN`; a § 2 criterion with no testable `[ ]`; a plan § 5 boundary with no `errors` codes.
68
+ - **F. Duplication** (LOW): near-duplicate Gherkin scenarios; repetitive tasks in the same file or scope; redundant § 2 criteria.
69
+ - **INVENTION** (HIGH by default): the artifact states something its source does not contain, for example a plan component, a spec criterion or a number that no US, RF, code or page read supports. The fix is to cite the source or mark it `[TBD]` (#4, #5).
70
+
71
+ **Verifying a produced artifact.** When you check an artifact against its source (a summary, a port, a migration, a generated doc), check three failures: **loss** (the source holds it, the artifact dropped it), **invention** (the artifact holds it, the source does not), and **inversion** (the artifact says the opposite of the source). A check of loss alone passes an artifact that is wrong in the other two ways.
72
+
73
+ 5. **Severity assignment:**
74
+
75
+ | Severity | Criterion |
76
+ |---|---|
77
+ | **CRITICAL** | Violates a universal invariant (`PRINCIPLES.md` § 1 to 8) OR an applicable hard rule of `afm.md § 3` fails its mechanical trigger |
78
+ | **HIGH** | A functional coverage gap (scenario or component with no task), OR blocking underspecification, OR a load-bearing finding that changes the inventory of one isolated feature or task |
79
+ | **MEDIUM** | A guiding principle (`afm.md § 1.3`) is violated (this includes the downgraded rules: types at boundaries, Rule of Three, saga ordering), terminology drift, incomplete complexity tracking, ambiguity in an optional section |
80
+ | **LOW** | Style or wording. A placeholder in an optional section. Minor duplication with no effect on execution |
81
+
82
+ 6. **Produce a compact report**, markdown in chat. It does **NOT** write to a file:
83
+
84
+ ```markdown
85
+ ## Analysis of Feature {{NNN}} — {{title}}
86
+
87
+ | ID | Category | Severity | Location(s) | Summary | Recommendation |
88
+ |---|---|---|---|---|---|
89
+ | F01 | Coverage Gap | HIGH | tasks.md (no T for scenario S2) | Scenario "<name>" has no RED/GREEN | Add T0NN RED + T0NN+1 GREEN before Phase 3 |
90
+ | F02 | Constitution | CRITICAL | plan.md § 7 + § 5 | Rule 16 marked [x] but Zod missing from § 5 contracts | Add the Zod schema to § 5 boundary <name> |
91
+ | F03 | Ambiguity | MEDIUM | spec.md § 2 | "Works fast" with no measurable criterion | Replace with "p95 < Xms" or similar |
92
+
93
+ ### Coverage Summary
94
+
95
+ | Scenario/Component/Rule | Has task? | Task IDs | Notes |
96
+ |---|---|---|---|
97
+ | S1 (happy path) | yes | T004 (RED), T005 (GREEN) | |
98
+ | S2 (error) | no | — | F01 |
99
+ | Component: `src/features/<feature>/domain/x.ts` (new) | yes | T001, T004, T005 | |
100
+ | Component: `src/lib/storage/presigned.ts` (new) | partial | T009, T010 | no retry test task |
101
+ | Hard rule 16 (Zod boundary) | no | — | F02 |
102
+
103
+ ### Metrics
104
+
105
+ - Total scenarios: X / Total tasks: Y
106
+ - Scenario-to-task coverage: Z%
107
+ - Open `[NEEDS CLARIFICATION:]` markers: N
108
+ - Critical issues: M / High: K / Medium: L / Low: P
109
+ - Total findings: X (of 50 max, overflow: Y grouped)
110
+ ```
111
+
112
+ 7. **Next actions:**
113
+ - A **CRITICAL** exists: "N CRITICAL issue(s). Resolve before you start T001 (use `afm clarify` for ambiguity, or edit manually)."
114
+ - Only **MEDIUM** or **LOW**: "OK to proceed. Optional suggestions are in the tables above."
115
+ - A **HIGH** with no CRITICAL: "Consider resolving before T001: coverage gaps tend to surface as production bugs."
116
+
117
+ 8. **Offer remediation:** ask the question `remediation` (`afm ask analyze --scope <slug>`). `top-5` applies the 5 edits in severity order and reports what changed with the paths (#6: "yes" is the approval; review with `git diff`). `top-10` does the same with 10. `report-only` closes with "Report complete. Addressing manually." Edits to `spec.md`, `plan.md` or `tasks.md` invalidate a recorded delivery approval (`afm approve --check <NNN>`); the next gate asks again.
118
+
119
+ ## Anti-patterns
120
+
121
+ - ❌ **Advisory mode:** applying fixes the operator did NOT ask for. The report is read-only; remediation runs only on `top-5` or `top-10` (then #6 authorizes applying and reporting). *(In gating mode it is the opposite: bucket (a) auto-corrects with no question, because the `deliver` gate is the approval.)*
122
+ - ❌ **Advisory mode:** writing the report to a file. It is chat-only: a visual audit, not a versioned artifact. *(In gating mode there is no chat report: the sorted result goes back to the caller.)*
123
+ - ❌ Recomputing by hand what `afm feature lint` already reported. Start from its findings.
124
+ - ❌ Exceeding 50 findings. Group the overflow at the end of the report.
125
+ - ❌ Inventing a finding with no evidence (#5). List only what is visible in the files read.
126
+ - ❌ **Advisory mode:** blocking T001. Analyze is a suggestion and the operator decides. *(In gating mode the loop until zero CRITICAL and HIGH before proceeding is the point.)*
127
+ - ❌ **Gating mode:** turning a cosmetic finding into a gate question. Only load-bearing bucket (b) findings, with an articulable "what breaks if this is wrong", become a question. The rest auto-corrects or becomes `[TBD]` (#6 corollary and #8 earned).
128
+ - ❌ Marking everything CRITICAL. Apply the severity matrix strictly: CRITICAL is an invariant violation or a hard rule with a failing mechanical trigger.
129
+ - ❌ Skipping the coverage table. It is the most valuable output: an explicit map of gaps.
@@ -0,0 +1,86 @@
1
+ ---
2
+ type: op
3
+ description: Finds the ambiguities in a spec and asks at most five questions to close them.
4
+ load: warm
5
+ writes: ["docs/features/*/spec.md"]
6
+ composes: []
7
+ needs: ["feature"]
8
+ ---
9
+ # Sub-flow: clarify feature ambiguities (`clarify`)
10
+
11
+ > **Form** — effect: `spec.md § 7` · trigger: `afm clarify`, composition · precondition: `spec.md` with marker · composed by: `deliver` 0.E · **degree of freedom: low**
12
+
13
+ Triggers: `afm clarify [<feature>]`, or natural language ("resolve markers", "clear ambiguity in feature X", "scan for gaps").
14
+
15
+ > This replaces the "soft inline block" of [`plan.md`](plan.md) step 3: `afm plan` suggests `afm clarify` as the recommended path.
16
+ >
17
+ > **Orchestrated mode:** when [`deliver.md`](deliver.md) calls this op, it batches the irreducible questions (up to `QUESTION_CAP` per call) instead of one question per turn. See its suppression contract.
18
+
19
+ **Questions.** Every question this op puts to the operator is derived from the spec, so its text cannot live in a question file. Ask each as a dynamic question: a header of at most 12 characters, 2 to 4 options with the recommended one first and its reason, through whatever question facility the host offers, or in plain chat. The fixed decision of this op is data: `questions/clarify.questions.yaml`, asked with `afm ask clarify --scope <slug>`.
20
+
21
+ Procedure:
22
+
23
+ 1. **Pre-check.** Run `afm preflight` (exit 3: no `docs/.afm-version`, redirect to `afm init` or `afm refactor`). Find the feature. With the `<feature>` argument, use it. Without it, run `afm feature status <NNN> --json` over the folders of `docs/features/` and keep those whose `blockers` name an open `[NEEDS CLARIFICATION:]`.
24
+ - Zero features with markers: say "No feature has an open [NEEDS CLARIFICATION:]. To run a structured scan anyway, name the feature." and stop.
25
+ - Several: auto-detect the active feature (discover-first #2): the branch, the most recently touched spec, the hint. Ask in plain words (up to 4 candidates) only when it is genuinely ambiguous.
26
+
27
+ 2. **Structured scan (9-category taxonomy).** Read `spec.md` (and `plan.md`, when it exists) of the feature. Classify each category as `Clear`, `Partial` or `Missing`. Build an internal coverage map and do not write it to a file.
28
+
29
+ | # | Category | What it checks |
30
+ |---|---|---|
31
+ | 1 | Functional Scope & Behavior | spec § 1 problem, § 2 criteria, explicit out-of-scope |
32
+ | 2 | Domain & Data Model | entities, attributes, relations, lifecycle (cross-checks `docs/ach.md` when relevant) |
33
+ | 3 | Interaction & UX Flow | spec § 3 Gherkin scenarios: happy path plus errors |
34
+ | 4 | Non-Functional Quality | performance, scalability, reliability, observability, security, compliance (spec § 2 or § 5) |
35
+ | 5 | Integration & External Dependencies | external boundaries in plan § 5 (if it exists) or marked in the assumptions |
36
+ | 6 | Edge Cases & Failure Handling | the most likely error scenario of spec § 3, plus others |
37
+ | 7 | Constraints & Tradeoffs | technical constraints, rejected alternatives |
38
+ | 8 | Terminology & Consistency | canonical terms against synonym drift |
39
+ | 9 | Completion Signals | the spec § 2 criteria are testable and measurable |
40
+
41
+ 3. **Build a prioritized question queue** (5 questions at most per session). Heuristic: **Impact x Uncertainty**. Rank higher-impact categories first (architecture, data modeling, task decomposition, test design, UX behavior, compliance), then higher uncertainty first (`Missing` before `Partial`).
42
+ - Skip `Clear` categories.
43
+ - **Auto-resolve through discovery (principle #2)** before you ask: try to answer each candidate from the code, `docs/` or a nasca research (`nasca-research`). A question with an evidence-backed answer becomes an auto-resolved clarification, logged in § 7 with the note `(inferred from discovery)`. It does not enter the queue. Only irreducible product-intent questions reach the operator.
44
+ - Filter: a question must materially affect a downstream step. A stylistic question does not count.
45
+ - Each question needs 2 to 5 options, or an answer of 5 words or fewer.
46
+ - If more than 5 categories are `Missing` AND more than 5 markers are open, this is severe underspecification: ask the question `underspecified`.
47
+
48
+ 4. **Sequential loop: ask ONE question per turn** (universal principle #8, see [`../PRINCIPLES.md`](../PRINCIPLES.md)). These are the irreducible product-intent questions left after the auto-resolve, and they are the point of this op.
49
+ - **Recommendation-first.** Weigh the options (best practice, common patterns, risk reduction, alignment with the goals of the spec and the PRD) and pick the strongest. **The first option is always the recommendation**, marked as recommended with a 1 to 2 sentence reason.
50
+ - List the other options neutrally, with the trade-off of each. The operator can always answer outside the list.
51
+ - For a question with no natural 2 to 5 options (a field name, say), offer "Accept suggestion: X" as the recommendation and let the operator type another value.
52
+ - Never reveal future questions of the queue.
53
+
54
+ 5. **After each accepted answer** (principle #6: materialize the integration and continue, with no blocking gate):
55
+ - Add a line `- Q: <question> → A: <answer>` to the `## Clarifications` section under `### Session YYYY-MM-DD` in `spec.md`. Create the section right after § 6 Dependencies and today's subheading when they do not exist.
56
+ - Apply the clarification to the section it concerns:
57
+ - **Functional ambiguity** → § 1 problem or § 2 success criterion (replace the vague statement, do not duplicate it).
58
+ - **User interaction or actor** → § 3 Gherkin scenarios (update Given/When/Then).
59
+ - **Domain and data** → § 5 assumptions (field, type, reason).
60
+ - **Non-functional** → § 2 criterion (turn a vague adjective into a metric: `fast` becomes `p95 < 200ms`).
61
+ - **Edge case** → a new § 3 error scenario or a § 5 assumption.
62
+ - **Terminology** → normalize the term across all sections; keep the original once, marked `(previously "X")`, when needed.
63
+ - **Constraints** → § 4 out of scope or § 5 assumption.
64
+ - **Completion signals** → a § 2 criterion with a testable checkbox.
65
+ - If the clarification invalidates an earlier vague statement, replace it and leave no contradiction.
66
+ - Remove the matching `[NEEDS CLARIFICATION:]` marker from its section.
67
+ - **Save atomically after each integration.** Do not buffer several answers. Review happens through `git diff`.
68
+ - Editing the spec invalidates a recorded delivery approval (`afm approve --check <NNN>` exits 1). That is expected: the next gate asks again.
69
+
70
+ 6. **Stop when** any of these is true: all critical ambiguities are resolved (the queue is empty); the operator signals completion ("done", "good", "no more", "proceed", "stop"); the session reached 5 questions asked (a retry of the same question does not count). When no `[NEEDS CLARIFICATION:]` marker remains and the spec frontmatter `status` is `draft`, set it to `clarified` (the frontmatter, never a body line).
71
+
72
+ 7. **Report to the operator:**
73
+ - The path of the updated spec, the number of questions asked and answered, the sections touched (§ 1, § 3, § 5, ...).
74
+ - **Coverage summary**, one value per category: `Resolved` (was Partial or Missing, now addressed), `Deferred` (past the quota, or better suited to `plan`), `Clear` (already sufficient), `Outstanding` (still Partial or Missing but low impact).
75
+ - Re-run `afm feature status <NNN> --json` and report the remaining `blockers`.
76
+ - **Next step:** if high-priority `Outstanding` or `Deferred` items remain, "run `afm clarify` again after starting the plan" or consider re-running `afm specify`. Otherwise "the spec is ready, run `afm plan`".
77
+
78
+ ## Anti-patterns
79
+
80
+ - ❌ Asking more than 5 questions in one session. Severe underspecification calls for a re-spec, not an endless clarify.
81
+ - ❌ Skipping principle #8: every question carries a recommendation as its first option.
82
+ - ❌ Asking a question that discovery (#2) already answered. Only irreducible product questions reach the queue.
83
+ - ❌ Inventing an answer when the operator disagrees with the recommendation. The recommendation is a rejectable hypothesis, not a guess (#4: `[TBD]` beats invention).
84
+ - ❌ Buffering several integrations. Save after each answer.
85
+ - ❌ Modifying `plan.md` or `tasks.md`. `afm clarify` touches **only** `spec.md`; everything else comes from re-running `afm plan` and `afm tasks`.
86
+ - ❌ Revealing future questions of the queue before reaching them.