@schneiderjoseph/devia 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. package/AGENTS.md +149 -0
  2. package/CHANGELOG.md +78 -0
  3. package/GOVERNANCE.md +51 -0
  4. package/LEVELS.md +78 -0
  5. package/LICENSE +21 -0
  6. package/MATURITY.md +79 -0
  7. package/MEMORY.md +122 -0
  8. package/MIGRATION.md +62 -0
  9. package/PRINCIPLES.md +110 -0
  10. package/README.md +125 -0
  11. package/REFERENCES.md +30 -0
  12. package/VERSION +5 -0
  13. package/bin/devia.mjs +13 -0
  14. package/checklists/README.md +39 -0
  15. package/checklists/design/accessibility-review.md +11 -0
  16. package/checklists/design/design-to-code-review.md +10 -0
  17. package/checklists/design/responsive-review.md +7 -0
  18. package/checklists/design/ui-review.md +8 -0
  19. package/checklists/design/ux-review.md +10 -0
  20. package/checklists/engineering/accessibility.md +8 -0
  21. package/checklists/engineering/api.md +12 -0
  22. package/checklists/engineering/architecture.md +8 -0
  23. package/checklists/engineering/database.md +11 -0
  24. package/checklists/engineering/devops.md +9 -0
  25. package/checklists/engineering/disaster-recovery.md +9 -0
  26. package/checklists/engineering/frontend.md +9 -0
  27. package/checklists/engineering/incident.md +9 -0
  28. package/checklists/engineering/performance.md +7 -0
  29. package/checklists/engineering/production.md +26 -0
  30. package/checklists/engineering/release.md +17 -0
  31. package/checklists/engineering/security.md +33 -0
  32. package/checklists/engineering/testing.md +8 -0
  33. package/compliance/COVERAGE.md +46 -0
  34. package/compliance/REQUIREMENTS.md +8 -0
  35. package/compliance/TRACEABILITY.md +160 -0
  36. package/compliance/WAIVERS.md +13 -0
  37. package/package.json +74 -0
  38. package/rules/LIFECYCLE.md +16 -0
  39. package/rules/README.md +166 -0
  40. package/rules/accessibility/A11Y-001.md +42 -0
  41. package/rules/accessibility/A11Y-002.md +41 -0
  42. package/rules/accessibility/A11Y-003.md +40 -0
  43. package/rules/accessibility/A11Y-004.md +40 -0
  44. package/rules/accessibility/A11Y-005.md +39 -0
  45. package/rules/accessibility/A11Y-006.md +42 -0
  46. package/rules/accessibility/A11Y-007.md +39 -0
  47. package/rules/accessibility/A11Y-008.md +40 -0
  48. package/rules/accessibility/A11Y-009.md +41 -0
  49. package/rules/accessibility/A11Y-010.md +40 -0
  50. package/rules/accessibility/A11Y-011.md +39 -0
  51. package/rules/accessibility/A11Y-012.md +39 -0
  52. package/rules/agent/AGT-001.md +42 -0
  53. package/rules/agent/AGT-002.md +39 -0
  54. package/rules/agent/AGT-003.md +38 -0
  55. package/rules/agent/AGT-004.md +39 -0
  56. package/rules/agent/AGT-005.md +38 -0
  57. package/rules/agent/AGT-006.md +38 -0
  58. package/rules/agent/AGT-007.md +38 -0
  59. package/rules/agent/AGT-008.md +38 -0
  60. package/rules/agent/AGT-009.md +39 -0
  61. package/rules/agent/AGT-010.md +38 -0
  62. package/rules/agent/AGT-011.md +38 -0
  63. package/rules/ai/AI-001.md +44 -0
  64. package/rules/ai/AI-002.md +39 -0
  65. package/rules/ai/AI-003.md +40 -0
  66. package/rules/ai/AI-004.md +39 -0
  67. package/rules/ai/AI-005.md +38 -0
  68. package/rules/api/API-001.md +39 -0
  69. package/rules/api/API-002.md +39 -0
  70. package/rules/api/API-003.md +39 -0
  71. package/rules/api/API-004.md +38 -0
  72. package/rules/api/API-005.md +39 -0
  73. package/rules/api/API-006.md +40 -0
  74. package/rules/architecture/ARC-001.md +41 -0
  75. package/rules/architecture/ARC-002.md +43 -0
  76. package/rules/architecture/ARC-003.md +43 -0
  77. package/rules/architecture/ARC-004.md +40 -0
  78. package/rules/architecture/ARC-005.md +39 -0
  79. package/rules/architecture/ARC-006.md +39 -0
  80. package/rules/components/CMP-001.md +39 -0
  81. package/rules/components/CMP-002.md +38 -0
  82. package/rules/components/CMP-003.md +39 -0
  83. package/rules/components/CMP-004.md +40 -0
  84. package/rules/components/CMP-005.md +39 -0
  85. package/rules/content/CNT-001.md +39 -0
  86. package/rules/data-display/DATA-001.md +39 -0
  87. package/rules/data-display/DATA-002.md +39 -0
  88. package/rules/data-display/DATA-003.md +40 -0
  89. package/rules/data-display/DATA-004.md +40 -0
  90. package/rules/database/DB-001.md +43 -0
  91. package/rules/database/DB-002.md +38 -0
  92. package/rules/database/DB-003.md +40 -0
  93. package/rules/database/DB-004.md +44 -0
  94. package/rules/database/DB-005.md +39 -0
  95. package/rules/database/DB-006.md +38 -0
  96. package/rules/database/DB-007.md +40 -0
  97. package/rules/database/DB-008.md +40 -0
  98. package/rules/design-system/DS-001.md +39 -0
  99. package/rules/design-system/DS-002.md +40 -0
  100. package/rules/design-system/DS-003.md +38 -0
  101. package/rules/devops/OPS-001.md +43 -0
  102. package/rules/devops/OPS-002.md +39 -0
  103. package/rules/devops/OPS-003.md +38 -0
  104. package/rules/devops/OPS-004.md +40 -0
  105. package/rules/devops/OPS-005.md +43 -0
  106. package/rules/devops/OPS-006.md +38 -0
  107. package/rules/devops/OPS-007.md +40 -0
  108. package/rules/interaction/INT-001.md +39 -0
  109. package/rules/interaction/INT-002.md +39 -0
  110. package/rules/localization/I18N-001.md +38 -0
  111. package/rules/localization/I18N-002.md +40 -0
  112. package/rules/localization/I18N-003.md +39 -0
  113. package/rules/memory/MEM-001.md +44 -0
  114. package/rules/memory/MEM-002.md +39 -0
  115. package/rules/memory/MEM-003.md +38 -0
  116. package/rules/memory/MEM-004.md +38 -0
  117. package/rules/memory/MEM-005.md +38 -0
  118. package/rules/memory/MEM-006.md +38 -0
  119. package/rules/memory/MEM-007.md +38 -0
  120. package/rules/memory/MEM-008.md +38 -0
  121. package/rules/memory/MEM-009.md +39 -0
  122. package/rules/memory/MEM-010.md +38 -0
  123. package/rules/memory/MEM-011.md +38 -0
  124. package/rules/motion/MOT-001.md +38 -0
  125. package/rules/observability/OBS-001.md +40 -0
  126. package/rules/observability/OBS-002.md +40 -0
  127. package/rules/observability/OBS-003.md +38 -0
  128. package/rules/observability/OBS-004.md +38 -0
  129. package/rules/privacy/PRIV-001.md +38 -0
  130. package/rules/privacy/PRIV-002.md +44 -0
  131. package/rules/privacy/PRIV-003.md +40 -0
  132. package/rules/privacy/PRIV-004.md +41 -0
  133. package/rules/responsive/RWD-001.md +40 -0
  134. package/rules/responsive/RWD-002.md +39 -0
  135. package/rules/responsive/RWD-003.md +39 -0
  136. package/rules/security/SEC-001.md +44 -0
  137. package/rules/security/SEC-002.md +44 -0
  138. package/rules/security/SEC-003.md +41 -0
  139. package/rules/security/SEC-004.md +40 -0
  140. package/rules/security/SEC-005.md +42 -0
  141. package/rules/security/SEC-006.md +40 -0
  142. package/rules/security/SEC-007.md +44 -0
  143. package/rules/security/SEC-008.md +39 -0
  144. package/rules/security/SEC-009.md +40 -0
  145. package/rules/security/SEC-010.md +40 -0
  146. package/rules/security/SEC-011.md +40 -0
  147. package/rules/security/SEC-012.md +40 -0
  148. package/rules/states/STATE-001.md +38 -0
  149. package/rules/states/STATE-002.md +39 -0
  150. package/rules/states/STATE-003.md +39 -0
  151. package/rules/states/STATE-004.md +38 -0
  152. package/rules/testing/TST-001.md +39 -0
  153. package/rules/testing/TST-002.md +39 -0
  154. package/rules/testing/TST-003.md +39 -0
  155. package/rules/testing/TST-004.md +38 -0
  156. package/rules/testing/TST-005.md +40 -0
  157. package/rules/testing/TST-006.md +39 -0
  158. package/rules/ui/UI-001.md +40 -0
  159. package/rules/ui/UI-002.md +38 -0
  160. package/rules/ui/UI-003.md +41 -0
  161. package/rules/ui/UI-004.md +41 -0
  162. package/rules/ui/UI-005.md +41 -0
  163. package/rules/ui/UI-006.md +40 -0
  164. package/rules/ui/UI-007.md +41 -0
  165. package/rules/ux/UX-001.md +41 -0
  166. package/rules/ux/UX-002.md +41 -0
  167. package/rules/ux/UX-003.md +39 -0
  168. package/rules/ux/UX-004.md +39 -0
  169. package/rules/ux/UX-005.md +40 -0
  170. package/rules/ux/UX-006.md +40 -0
  171. package/rules/ux/UX-007.md +44 -0
  172. package/rules/ux/UX-008.md +41 -0
  173. package/rules/ux/UX-009.md +39 -0
  174. package/rules/ux/UX-010.md +40 -0
  175. package/rules/ux/UX-011.md +40 -0
  176. package/rules/ux/UX-012.md +40 -0
  177. package/rules/ux/UX-013.md +39 -0
  178. package/schema/README.md +19 -0
  179. package/schema/checklist.schema.json +34 -0
  180. package/schema/component.schema.json +37 -0
  181. package/schema/project-config.schema.json +70 -0
  182. package/schema/rule.schema.json +104 -0
  183. package/schema/token.schema.json +15 -0
  184. package/schema/waiver.schema.json +33 -0
  185. package/scripts/build-index.mjs +178 -0
  186. package/scripts/validate-links.mjs +43 -0
  187. package/scripts/validate-rules.mjs +42 -0
  188. package/skills/devia/SKILL.md +114 -0
  189. package/src/cli.mjs +107 -0
  190. package/src/commands/check.mjs +483 -0
  191. package/src/commands/doctor.mjs +139 -0
  192. package/src/commands/init.mjs +186 -0
  193. package/src/commands/registry.mjs +154 -0
  194. package/src/commands/rules.mjs +101 -0
  195. package/src/commands/skills.mjs +97 -0
  196. package/src/commands/sync.mjs +83 -0
  197. package/src/commands/validate.mjs +194 -0
  198. package/src/lib/fs.mjs +89 -0
  199. package/src/lib/git.mjs +31 -0
  200. package/src/lib/rules.mjs +85 -0
  201. package/src/lib/ui.mjs +52 -0
  202. package/src/lib/vendor.mjs +74 -0
  203. package/src/lib/version.mjs +19 -0
  204. package/src/lib/yaml.mjs +152 -0
  205. package/standard/README.md +31 -0
  206. package/standard/design/README.md +51 -0
  207. package/standard/design/REFERENCES.md +39 -0
  208. package/standard/design/accessibility/aria.md +7 -0
  209. package/standard/design/accessibility/contrast.md +6 -0
  210. package/standard/design/accessibility/focus.md +6 -0
  211. package/standard/design/accessibility/forms.md +3 -0
  212. package/standard/design/accessibility/keyboard.md +6 -0
  213. package/standard/design/accessibility/reduced-motion.md +3 -0
  214. package/standard/design/accessibility/reflow.md +3 -0
  215. package/standard/design/accessibility/screen-readers.md +3 -0
  216. package/standard/design/accessibility/target-size.md +3 -0
  217. package/standard/design/accessibility/testing.md +3 -0
  218. package/standard/design/accessibility/wcag-2.2.md +16 -0
  219. package/standard/design/accessibility/zoom.md +3 -0
  220. package/standard/design/ai/ai-design-rules.md +8 -0
  221. package/standard/design/ai/anti-patterns.md +1 -0
  222. package/standard/design/ai/compliance-format.md +22 -0
  223. package/standard/design/ai/design-review.md +10 -0
  224. package/standard/design/ai/evals/README.md +1 -0
  225. package/standard/design/ai/instructions.md +7 -0
  226. package/standard/design/ai/prompts/accessibility-review.md +5 -0
  227. package/standard/design/ai/prompts/design-system-review.md +5 -0
  228. package/standard/design/ai/prompts/ui-review.md +5 -0
  229. package/standard/design/ai/prompts/ux-review.md +5 -0
  230. package/standard/design/ai/review-protocol.md +11 -0
  231. package/standard/design/anti-patterns/accessibility.md +7 -0
  232. package/standard/design/anti-patterns/ai-generated.md +6 -0
  233. package/standard/design/anti-patterns/dashboards.md +5 -0
  234. package/standard/design/anti-patterns/forms.md +5 -0
  235. package/standard/design/anti-patterns/responsive.md +5 -0
  236. package/standard/design/anti-patterns/ui.md +6 -0
  237. package/standard/design/anti-patterns/ux.md +5 -0
  238. package/standard/design/components/buttons.md +6 -0
  239. package/standard/design/components/dialogs.md +5 -0
  240. package/standard/design/components/feedback.md +3 -0
  241. package/standard/design/components/forms.md +3 -0
  242. package/standard/design/components/navigation.md +3 -0
  243. package/standard/design/components/tables.md +6 -0
  244. package/standard/design/content/error-messages.md +4 -0
  245. package/standard/design/content/ux-writing.md +5 -0
  246. package/standard/design/data-display/README.md +5 -0
  247. package/standard/design/data-display/currency.md +3 -0
  248. package/standard/design/data-display/dates.md +3 -0
  249. package/standard/design/data-display/density.md +3 -0
  250. package/standard/design/data-display/filtering.md +3 -0
  251. package/standard/design/data-display/localization.md +3 -0
  252. package/standard/design/data-display/numbers.md +3 -0
  253. package/standard/design/data-display/pagination.md +3 -0
  254. package/standard/design/data-display/percentages.md +3 -0
  255. package/standard/design/data-display/sorting.md +3 -0
  256. package/standard/design/data-display/tables.md +3 -0
  257. package/standard/design/data-display/time.md +3 -0
  258. package/standard/design/decisions/ADR-001-token-naming.md +13 -0
  259. package/standard/design/decisions/ADR-002-radius-scale.md +9 -0
  260. package/standard/design/decisions/ADR-003-color-system.md +9 -0
  261. package/standard/design/decisions/ADR-004-component-versioning.md +9 -0
  262. package/standard/design/decisions/README.md +3 -0
  263. package/standard/design/design-system/components.md +9 -0
  264. package/standard/design/design-system/naming.md +19 -0
  265. package/standard/design/design-system/tokens.md +7 -0
  266. package/standard/design/design-system/variants.md +5 -0
  267. package/standard/design/design-system/versioning.md +5 -0
  268. package/standard/design/health/coverage.md +1 -0
  269. package/standard/design/health/dashboard.md +14 -0
  270. package/standard/design/health/maturity-model.md +9 -0
  271. package/standard/design/health/score.md +14 -0
  272. package/standard/design/interaction/README.md +10 -0
  273. package/standard/design/interaction/keyboard.md +3 -0
  274. package/standard/design/interaction/mouse.md +2 -0
  275. package/standard/design/interaction/pen.md +1 -0
  276. package/standard/design/interaction/touch.md +3 -0
  277. package/standard/design/interaction/touchscreen.md +6 -0
  278. package/standard/design/interaction/voice.md +2 -0
  279. package/standard/design/localization/README.md +5 -0
  280. package/standard/design/localization/currency.md +3 -0
  281. package/standard/design/localization/date-time.md +3 -0
  282. package/standard/design/localization/i18n.md +3 -0
  283. package/standard/design/localization/locale-testing.md +3 -0
  284. package/standard/design/localization/number-formatting.md +3 -0
  285. package/standard/design/localization/pluralization.md +3 -0
  286. package/standard/design/localization/rtl.md +3 -0
  287. package/standard/design/localization/text-expansion.md +3 -0
  288. package/standard/design/motion/animation.md +6 -0
  289. package/standard/design/penpot/WORKFLOW.md +27 -0
  290. package/standard/design/platforms/README.md +12 -0
  291. package/standard/design/platforms/desktop/README.md +5 -0
  292. package/standard/design/platforms/mobile/android.md +5 -0
  293. package/standard/design/platforms/mobile/ios.md +5 -0
  294. package/standard/design/platforms/tablet/README.md +5 -0
  295. package/standard/design/platforms/web/README.md +1 -0
  296. package/standard/design/principles/design-principles.md +9 -0
  297. package/standard/design/principles/ui-principles.md +7 -0
  298. package/standard/design/principles/ux-principles.md +14 -0
  299. package/standard/design/references/atlassian.md +3 -0
  300. package/standard/design/references/carbon.md +3 -0
  301. package/standard/design/references/figma-sds.md +5 -0
  302. package/standard/design/references/govuk.md +3 -0
  303. package/standard/design/references/material.md +3 -0
  304. package/standard/design/references/nng.md +3 -0
  305. package/standard/design/references/openui.md +3 -0
  306. package/standard/design/references/primer.md +5 -0
  307. package/standard/design/references/storybook.md +3 -0
  308. package/standard/design/references/uswds.md +3 -0
  309. package/standard/design/references/w3c.md +3 -0
  310. package/standard/design/responsive/desktop.md +4 -0
  311. package/standard/design/responsive/mobile.md +6 -0
  312. package/standard/design/responsive/tablet.md +3 -0
  313. package/standard/design/states/async.md +3 -0
  314. package/standard/design/states/conflict.md +3 -0
  315. package/standard/design/states/empty.md +3 -0
  316. package/standard/design/states/error.md +3 -0
  317. package/standard/design/states/interaction.md +5 -0
  318. package/standard/design/states/loading.md +3 -0
  319. package/standard/design/states/offline.md +3 -0
  320. package/standard/design/states/optimistic.md +3 -0
  321. package/standard/design/states/partial.md +3 -0
  322. package/standard/design/states/permission-denied.md +3 -0
  323. package/standard/design/states/rate-limited.md +3 -0
  324. package/standard/design/states/read-only.md +3 -0
  325. package/standard/design/states/retry.md +3 -0
  326. package/standard/design/states/skeleton.md +3 -0
  327. package/standard/design/states/stale.md +3 -0
  328. package/standard/design/states/success.md +3 -0
  329. package/standard/design/states/timeout.md +3 -0
  330. package/standard/design/states/unsaved-changes.md +3 -0
  331. package/standard/design/ui/color.md +6 -0
  332. package/standard/design/ui/grids.md +5 -0
  333. package/standard/design/ui/icons.md +5 -0
  334. package/standard/design/ui/imagery.md +5 -0
  335. package/standard/design/ui/layout.md +5 -0
  336. package/standard/design/ui/spacing.md +5 -0
  337. package/standard/design/ui/typography.md +6 -0
  338. package/standard/design/ui/visual-design.md +7 -0
  339. package/standard/design/ux/cognitive-load.md +5 -0
  340. package/standard/design/ux/errors.md +6 -0
  341. package/standard/design/ux/feedback.md +5 -0
  342. package/standard/design/ux/forms.md +7 -0
  343. package/standard/design/ux/heuristics.md +14 -0
  344. package/standard/design/ux/information-architecture.md +6 -0
  345. package/standard/design/ux/navigation.md +6 -0
  346. package/standard/design/ux/usability.md +6 -0
  347. package/standard/engineering/README.md +29 -0
  348. package/standard/engineering/REFERENCES.md +42 -0
  349. package/standard/engineering/ai/AI_SECURITY.md +15 -0
  350. package/standard/engineering/ai/PROMPT_SECURITY.md +6 -0
  351. package/standard/engineering/architecture/ADR.md +11 -0
  352. package/standard/engineering/architecture/ARCHITECTURE.md +25 -0
  353. package/standard/engineering/architecture/PRINCIPLES.md +17 -0
  354. package/standard/engineering/architecture/THREAT_MODEL.md +14 -0
  355. package/standard/engineering/backend/API.md +29 -0
  356. package/standard/engineering/backend/BACKGROUND_JOBS.md +12 -0
  357. package/standard/engineering/backend/ERROR_HANDLING.md +26 -0
  358. package/standard/engineering/backend/LOGGING.md +12 -0
  359. package/standard/engineering/compliance/DATA_RETENTION.md +10 -0
  360. package/standard/engineering/compliance/PRIVACY.md +11 -0
  361. package/standard/engineering/database/BACKUPS.md +19 -0
  362. package/standard/engineering/database/DATABASE.md +30 -0
  363. package/standard/engineering/database/MIGRATIONS.md +12 -0
  364. package/standard/engineering/devops/BRANCH_PROTECTION.md +17 -0
  365. package/standard/engineering/devops/CI_CD.md +48 -0
  366. package/standard/engineering/devops/DEPLOYMENT.md +12 -0
  367. package/standard/engineering/devops/DOCKER.md +9 -0
  368. package/standard/engineering/devops/ENVIRONMENTS.md +12 -0
  369. package/standard/engineering/devops/RELEASE.md +6 -0
  370. package/standard/engineering/devops/ROLLBACK.md +9 -0
  371. package/standard/engineering/frontend/ACCESSIBILITY.md +16 -0
  372. package/standard/engineering/frontend/DESIGN_SYSTEM.md +10 -0
  373. package/standard/engineering/frontend/FRONTEND.md +17 -0
  374. package/standard/engineering/frontend/UX.md +15 -0
  375. package/standard/engineering/observability/ALERTING.md +11 -0
  376. package/standard/engineering/observability/INCIDENTS.md +10 -0
  377. package/standard/engineering/observability/MONITORING.md +17 -0
  378. package/standard/engineering/payments/PAYMENTS.md +15 -0
  379. package/standard/engineering/performance/PERFORMANCE.md +19 -0
  380. package/standard/engineering/security/API_SECURITY.md +22 -0
  381. package/standard/engineering/security/ASVS_5.0/V10_MALICIOUS_CODE.md +31 -0
  382. package/standard/engineering/security/ASVS_5.0/V11_BUSINESS_LOGIC.md +31 -0
  383. package/standard/engineering/security/ASVS_5.0/V12_FILES.md +31 -0
  384. package/standard/engineering/security/ASVS_5.0/V13_API.md +31 -0
  385. package/standard/engineering/security/ASVS_5.0/V14_CONFIGURATION.md +31 -0
  386. package/standard/engineering/security/ASVS_5.0/V1_ARCHITECTURE.md +31 -0
  387. package/standard/engineering/security/ASVS_5.0/V2_AUTHENTICATION.md +31 -0
  388. package/standard/engineering/security/ASVS_5.0/V3_SESSION.md +31 -0
  389. package/standard/engineering/security/ASVS_5.0/V4_ACCESS_CONTROL.md +31 -0
  390. package/standard/engineering/security/ASVS_5.0/V5_VALIDATION.md +31 -0
  391. package/standard/engineering/security/ASVS_5.0/V6_CRYPTOGRAPHY.md +31 -0
  392. package/standard/engineering/security/ASVS_5.0/V7_ERROR_HANDLING.md +31 -0
  393. package/standard/engineering/security/ASVS_5.0/V8_DATA_PROTECTION.md +31 -0
  394. package/standard/engineering/security/ASVS_5.0/V9_COMMUNICATION.md +31 -0
  395. package/standard/engineering/security/ASVS_REGISTRY.md +31 -0
  396. package/standard/engineering/security/AUTHENTICATION.md +28 -0
  397. package/standard/engineering/security/AUTHORIZATION.md +27 -0
  398. package/standard/engineering/security/DATA_SECURITY.md +14 -0
  399. package/standard/engineering/security/OWASP_ASVS.md +31 -0
  400. package/standard/engineering/security/SECRETS.md +28 -0
  401. package/standard/engineering/security/SECURITY.md +28 -0
  402. package/standard/engineering/testing/TESTING.md +27 -0
  403. package/templates/agents/AGENTS.md +34 -0
  404. package/templates/agents/CLAUDE.md +33 -0
  405. package/templates/agents/copilot-instructions.md +15 -0
  406. package/templates/agents/cursor.mdc +27 -0
  407. package/templates/agents/windsurfrules.md +17 -0
  408. package/templates/docs/ADR.md +16 -0
  409. package/templates/docs/FEATURE.md +19 -0
  410. package/templates/docs/SECURITY_REPORT.md +15 -0
  411. package/templates/docs/accessibility-review.md +9 -0
  412. package/templates/docs/component.md +9 -0
  413. package/templates/docs/decision-record.md +9 -0
  414. package/templates/docs/design-review.md +9 -0
  415. package/templates/docs/exception.md +9 -0
  416. package/templates/docs/page.md +9 -0
  417. package/templates/docs/pattern.md +9 -0
  418. package/templates/docs/user-flow.md +9 -0
  419. package/templates/github/workflows/app-ci.yml +91 -0
  420. package/templates/project/00_OVERVIEW.md +51 -0
  421. package/templates/project/01_ARCHITECTURE.md +37 -0
  422. package/templates/project/02_SURFACES.md +30 -0
  423. package/templates/project/03_DATA_MODEL.md +31 -0
  424. package/templates/project/04_PERMISSIONS.md +32 -0
  425. package/templates/project/05_FLOWS.md +20 -0
  426. package/templates/project/06_INTEGRATIONS.md +21 -0
  427. package/templates/project/07_DESIGN.md +33 -0
  428. package/templates/project/10_NEVER_ALWAYS.md +26 -0
  429. package/templates/project/11_GAPS.md +18 -0
  430. package/templates/project/12_DEBT.md +19 -0
  431. package/templates/project/13_RECIPES.md +35 -0
  432. package/templates/project/14_INDEX.md +50 -0
  433. package/templates/project/AGENTS.md +51 -0
  434. package/templates/project/README.md +49 -0
  435. package/templates/project/impact-map.yaml +41 -0
package/src/cli.mjs ADDED
@@ -0,0 +1,107 @@
1
+ import process from "node:process";
2
+ import path from "node:path";
3
+ import { packageRoot, findProjectRoot } from "./lib/fs.mjs";
4
+ import { cliVersion, standardVersion } from "./lib/version.mjs";
5
+ import { color } from "./lib/ui.mjs";
6
+
7
+ const COMMANDS = {
8
+ init: () => import("./commands/init.mjs"),
9
+ validate: () => import("./commands/validate.mjs"),
10
+ check: () => import("./commands/check.mjs"),
11
+ doctor: () => import("./commands/doctor.mjs"),
12
+ rules: () => import("./commands/rules.mjs"),
13
+ sync: () => import("./commands/sync.mjs"),
14
+ skills: () => import("./commands/skills.mjs"),
15
+ gap: () => import("./commands/registry.mjs"),
16
+ debt: () => import("./commands/registry.mjs"),
17
+ };
18
+
19
+ const HELP = `
20
+ ${color.bold("devia")} — one standard, one memory
21
+
22
+ ${color.bold("devia init")} create .devia/ and the agent adapters in this repository
23
+ ${color.bold("devia validate")} check memory integrity (structure, registries, placeholders)
24
+ ${color.bold("devia check")} readiness gates — P0 failures exit non-zero
25
+ ${color.bold("devia doctor")} adoption, drift and staleness diagnosis
26
+ ${color.bold("devia rules")} list or show rules from the registry
27
+ ${color.bold("devia sync")} refresh the vendored standard after upgrading devia
28
+ ${color.bold("devia skills")} install the agent adapters (install --agent all)
29
+ ${color.bold("devia gap")} add or close a line in 11_GAPS.md
30
+ ${color.bold("devia debt")} add or close a line in 12_DEBT.md
31
+
32
+ Common flags
33
+
34
+ --root <dir> operate on another directory (default: the repository root)
35
+ --json machine-readable output where supported
36
+ --help command help
37
+ --version print the devia and standard versions
38
+
39
+ Docs: AGENTS.md · MEMORY.md · rules/README.md
40
+ `;
41
+
42
+ export function parseArgs(argv) {
43
+ const args = { _: [], flags: {} };
44
+ for (let i = 0; i < argv.length; i++) {
45
+ const a = argv[i];
46
+ if (a.startsWith("--")) {
47
+ const [key, inline] = a.slice(2).split("=");
48
+ const next = argv[i + 1];
49
+ if (inline !== undefined) args.flags[key] = inline;
50
+ else if (next && !next.startsWith("--")) args.flags[key] = argv[++i];
51
+ else args.flags[key] = true;
52
+ } else if (a.startsWith("-") && a.length > 1) {
53
+ args.flags[a.slice(1)] = true;
54
+ } else {
55
+ args._.push(a);
56
+ }
57
+ }
58
+ return args;
59
+ }
60
+
61
+ export function context(args) {
62
+ const cwd = path.resolve(process.cwd());
63
+ const given = args.flags.root ? path.resolve(String(args.flags.root)) : null;
64
+ const root = given || findProjectRoot(cwd);
65
+ return {
66
+ root,
67
+ cwd,
68
+ // The root was inferred by walking up, and it is not where the user is standing. A command
69
+ // that writes asks before acting on it; commands that only read do not care.
70
+ rootAwayFromCwd: !given && root !== cwd,
71
+ deviaDir: path.join(root, ".devia"),
72
+ packageRoot,
73
+ args,
74
+ flags: args.flags,
75
+ json: Boolean(args.flags.json),
76
+ };
77
+ }
78
+
79
+ export function versions() {
80
+ return { cli: cliVersion(), standard: standardVersion() };
81
+ }
82
+
83
+ export async function run(argv) {
84
+ const args = parseArgs(argv);
85
+ const command = args._[0];
86
+
87
+ if (args.flags.version || command === "version") {
88
+ const { cli, standard } = versions();
89
+ console.log(`devia ${cli} · standard ${standard}`);
90
+ return 0;
91
+ }
92
+ if (!command || command === "help" || (args.flags.help && !command)) {
93
+ console.log(HELP.trim());
94
+ return 0;
95
+ }
96
+
97
+ const load = COMMANDS[command];
98
+ if (!load) {
99
+ console.error(`unknown command: ${command}`);
100
+ console.log(HELP.trim());
101
+ return 2;
102
+ }
103
+
104
+ const mod = await load();
105
+ const code = await mod.default(context(args), command);
106
+ return typeof code === "number" ? code : 0;
107
+ }
@@ -0,0 +1,483 @@
1
+ import path from "node:path";
2
+ import { exists, read, readJSON, walk } from "../lib/fs.mjs";
3
+ import { trackedFiles } from "../lib/git.mjs";
4
+ import { color, heading, status, line } from "../lib/ui.mjs";
5
+
6
+ /**
7
+ * Readiness gates (LEVELS.md level 2).
8
+ *
9
+ * Every check answers from evidence in the repository. A check that cannot answer returns SKIP
10
+ * with the reason — it never rounds up to PASS, because "I did not check" is reported, not
11
+ * assumed (AGT-006).
12
+ */
13
+
14
+ const SKIP_DIRS = new Set([
15
+ ".git",
16
+ "node_modules",
17
+ "dist",
18
+ "build",
19
+ "out",
20
+ "coverage",
21
+ "vendor",
22
+ ".next",
23
+ ".venv",
24
+ "__pycache__",
25
+ ".devia",
26
+ ]);
27
+
28
+ const SECRET_PATTERNS = [
29
+ [/AKIA[0-9A-Z]{16}/, "AWS access key id"],
30
+ [/-----BEGIN (RSA |EC |OPENSSH |PGP )?PRIVATE KEY-----/, "private key"],
31
+ [/sk_live_[0-9a-zA-Z]{16,}/, "live secret key"],
32
+ [/gh[pousr]_[0-9A-Za-z]{30,}/, "GitHub token"],
33
+ [/xox[baprs]-[0-9A-Za-z-]{10,}/, "Slack token"],
34
+ [/AIza[0-9A-Za-z_-]{35}/, "Google API key"],
35
+ [/eyJ[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/, "JWT"],
36
+ ];
37
+
38
+ /**
39
+ * A line carrying this marker is exempt from the secret and bypass scanners. It exists so an
40
+ * exemption is visible in the diff and reviewable — never as a silent allowlist elsewhere.
41
+ */
42
+ const ALLOW = "devia:allow";
43
+
44
+ /** Where a bypass can actually be wired in: scripts, hooks and pipeline configuration. */
45
+ const EXECUTABLE_SURFACE =
46
+ /(^|\/)(package\.json|Makefile|Justfile|\.husky\/|\.github\/workflows\/|\.gitlab-ci\.yml|azure-pipelines\.yml|Jenkinsfile)|\.(sh|bash|ps1|cmd|bat|mk)$/;
47
+
48
+ const TEXT_EXT = new Set([
49
+ ".js", ".mjs", ".cjs", ".ts", ".tsx", ".jsx", ".py", ".rb", ".go", ".rs", ".java", ".php",
50
+ ".json", ".yml", ".yaml", ".toml", ".env", ".sh", ".ps1", ".sql", ".md", ".txt", ".html",
51
+ ".css", ".ini", ".cfg", ".conf",
52
+ ]);
53
+
54
+ /**
55
+ * The files this repository actually carries: what git tracks, plus what is untracked and not
56
+ * ignored — the content a push would publish. An ignored path is a local artefact, and failing a
57
+ * P0 gate on someone's build cache or downloaded fixture is a false positive, not vigilance.
58
+ * Without git the tree is walked instead, which is wider: SKIP is not an option here, because a
59
+ * secret scan that silently scanned nothing is worse than one that over-reports.
60
+ */
61
+ function sourceFiles(root) {
62
+ const skipped = (rel) => rel.split(/[\/]/).some((seg) => SKIP_DIRS.has(seg));
63
+ const wanted = (rel) => TEXT_EXT.has(path.extname(rel).toLowerCase());
64
+
65
+ const tracked = trackedFiles(root);
66
+ if (tracked) {
67
+ return tracked
68
+ .filter((rel) => !skipped(rel) && wanted(rel))
69
+ .map((rel) => rel.split("/").join(path.sep))
70
+ .sort();
71
+ }
72
+
73
+ return walk(root, {
74
+ skip: (rel) => skipped(rel),
75
+ filter: (rel) => wanted(rel),
76
+ });
77
+ }
78
+
79
+ function anyExists(root, candidates) {
80
+ return candidates.find((c) => exists(path.join(root, c))) || null;
81
+ }
82
+
83
+ function makeChecks(root, ctx) {
84
+ const pkg = readJSON(path.join(root, "package.json"));
85
+ const scripts = pkg?.scripts || {};
86
+ const deps = { ...(pkg?.dependencies || {}), ...(pkg?.devDependencies || {}) };
87
+ const config = readJSON(path.join(root, ".devia", "devia.json"));
88
+ const files = sourceFiles(root);
89
+ const rel = (p) => p.split(path.sep).join("/");
90
+
91
+ const hasDep = (...names) => names.some((n) => n in deps);
92
+ const grepFiles = (re, limit = 40) => {
93
+ const hits = [];
94
+ for (const f of files) {
95
+ const text = read(path.join(root, f));
96
+ if (text && re.test(text)) {
97
+ hits.push(rel(f));
98
+ if (hits.length >= limit) break;
99
+ }
100
+ }
101
+ return hits;
102
+ };
103
+
104
+ return [
105
+ {
106
+ id: "MEM-PRESENT",
107
+ priority: "P0",
108
+ rule: "AGT-002",
109
+ title: "Project memory exists",
110
+ run: () =>
111
+ exists(path.join(root, ".devia"))
112
+ ? { kind: "PASS" }
113
+ : { kind: "FAIL", detail: "run `devia init` before working here" },
114
+ },
115
+ {
116
+ id: "MEM-FILLED",
117
+ priority: "P1",
118
+ rule: "MEM-009",
119
+ title: "Overview is filled in",
120
+ run: () => {
121
+ const text = read(path.join(root, ".devia", "00_OVERVIEW.md"));
122
+ if (text === null) return { kind: "SKIP", detail: "no .devia/00_OVERVIEW.md" };
123
+ const n = (text.match(/TODO\(devia\)/g) || []).length;
124
+ return n
125
+ ? { kind: "WARN", detail: `${n} placeholders left` }
126
+ : { kind: "PASS" };
127
+ },
128
+ },
129
+ {
130
+ id: "MEM-DEBT-P0",
131
+ priority: "P0",
132
+ rule: "MEM-002",
133
+ title: "No P0 debt recorded as unbuilt",
134
+ run: () => {
135
+ const text = read(path.join(root, ".devia", "12_DEBT.md"));
136
+ if (text === null) return { kind: "SKIP", detail: "no debt registry" };
137
+ const rows = (text.match(/^\|\s*D\d+\s*\|.*$/gm) || []).filter(
138
+ (r) => /\bP0\b/.test(r) && !/TODO\(devia\)/.test(r)
139
+ );
140
+ return rows.length
141
+ ? { kind: "FAIL", detail: `${rows.length} P0 debt line(s) open` }
142
+ : { kind: "PASS" };
143
+ },
144
+ },
145
+ {
146
+ id: "MEM-WAIVERS",
147
+ priority: "P1",
148
+ rule: "GOVERNANCE",
149
+ title: "No expired waiver",
150
+ run: () => {
151
+ const waivers = config?.waivers || [];
152
+ if (!waivers.length) return { kind: "PASS", detail: "none" };
153
+ const today = new Date().toISOString().slice(0, 10);
154
+ const expired = waivers.filter((w) => !w.expires || w.expires < today);
155
+ return expired.length
156
+ ? { kind: "FAIL", detail: `${expired.length} expired or undated` }
157
+ : { kind: "PASS", detail: `${waivers.length} active` };
158
+ },
159
+ },
160
+ {
161
+ id: "CI-PRESENT",
162
+ priority: "P0",
163
+ rule: "OPS-001",
164
+ title: "CI runs on pull requests",
165
+ run: () => {
166
+ const wf = path.join(root, ".github", "workflows");
167
+ const found =
168
+ (exists(wf) && walk(wf, { filter: (f) => /\.ya?ml$/.test(f) }).length) ||
169
+ anyExists(root, [".gitlab-ci.yml", "azure-pipelines.yml", "Jenkinsfile", ".circleci"]);
170
+ return found
171
+ ? { kind: "PASS" }
172
+ : { kind: "FAIL", detail: "no CI configuration found" };
173
+ },
174
+ },
175
+ {
176
+ id: "CI-GATES",
177
+ priority: "P1",
178
+ rule: "OPS-001",
179
+ title: "CI runs tests and static checks",
180
+ run: () => {
181
+ const wf = path.join(root, ".github", "workflows");
182
+ if (!exists(wf)) return { kind: "SKIP", detail: "no GitHub workflows to read" };
183
+ const text = walk(wf, { filter: (f) => /\.ya?ml$/.test(f) })
184
+ .map((f) => read(path.join(wf, f)) || "")
185
+ .join("\n");
186
+ const has = (re) => re.test(text);
187
+ const missing = [];
188
+ if (!has(/\btest\b/i)) missing.push("test");
189
+ if (!has(/\blint\b|eslint|ruff|flake8/i)) missing.push("lint");
190
+ if (!has(/audit|snyk|dependabot|osv/i)) missing.push("dependency audit");
191
+ return missing.length
192
+ ? { kind: "WARN", detail: `not referenced: ${missing.join(", ")}` }
193
+ : { kind: "PASS" };
194
+ },
195
+ },
196
+ {
197
+ id: "SEC-ENV",
198
+ priority: "P0",
199
+ rule: "SEC-002",
200
+ title: "No environment file committed",
201
+ run: () => {
202
+ const ignore = read(path.join(root, ".gitignore")) || "";
203
+ const envs = [".env", ".env.local", ".env.production"].filter((f) =>
204
+ exists(path.join(root, f))
205
+ );
206
+ if (!envs.length) return { kind: "PASS" };
207
+ const ignored = /^\s*\.env/m.test(ignore);
208
+ return ignored
209
+ ? { kind: "WARN", detail: `${envs.join(", ")} present locally but gitignored` }
210
+ : { kind: "FAIL", detail: `${envs.join(", ")} is not gitignored` };
211
+ },
212
+ },
213
+ {
214
+ id: "SEC-SECRETS",
215
+ priority: "P0",
216
+ rule: "SEC-002",
217
+ title: "No secret-shaped strings in the tree",
218
+ run: () => {
219
+ const hits = [];
220
+ let exempted = 0;
221
+ for (const f of files) {
222
+ if (/(^|\/)(\.env\.example|.*\.lock|package-lock\.json)$/.test(rel(f))) continue;
223
+ const text = read(path.join(root, f));
224
+ if (!text) continue;
225
+ const lines = text.split(/\r?\n/);
226
+ for (let i = 0; i < lines.length; i++) {
227
+ const hit = SECRET_PATTERNS.find(([re]) => re.test(lines[i]));
228
+ if (!hit) continue;
229
+ if (lines[i].includes(ALLOW)) {
230
+ exempted++;
231
+ continue;
232
+ }
233
+ hits.push(`${rel(f)}:${i + 1} (${hit[1]})`);
234
+ break;
235
+ }
236
+ if (hits.length >= 5) break;
237
+ }
238
+ return hits.length
239
+ ? { kind: "FAIL", detail: hits.join("; ") }
240
+ : {
241
+ kind: "PASS",
242
+ detail: `${files.length} files scanned${exempted ? `, ${exempted} exempted` : ""}`,
243
+ };
244
+ },
245
+ },
246
+ {
247
+ id: "OPS-BYPASS",
248
+ priority: "P0",
249
+ rule: "OPS-003",
250
+ title: "No check bypass wired into the repository",
251
+ run: () => {
252
+ // Only scripts, hooks and pipeline configuration can wire a bypass in. Prose that
253
+ // forbids `--no-verify` is not a bypass, so documentation is out of scope here.
254
+ const hits = [];
255
+ for (const f of files) {
256
+ if (!EXECUTABLE_SURFACE.test(rel(f))) continue;
257
+ const text = read(path.join(root, f));
258
+ if (!text) continue;
259
+ const lines = text.split(/\r?\n/);
260
+ for (let i = 0; i < lines.length; i++) {
261
+ if (!/--no-verify|SKIP_HOOKS=1|HUSKY=0|\[skip ci\]/.test(lines[i])) continue;
262
+ if (lines[i].includes(ALLOW)) continue;
263
+ hits.push(`${rel(f)}:${i + 1}`);
264
+ break;
265
+ }
266
+ if (hits.length >= 5) break;
267
+ }
268
+ return hits.length ? { kind: "FAIL", detail: hits.join(", ") } : { kind: "PASS" };
269
+ },
270
+ },
271
+ {
272
+ id: "TST-PRESENT",
273
+ priority: "P0",
274
+ rule: "TST-001",
275
+ title: "Automated tests exist",
276
+ run: () => {
277
+ const testFiles = files.filter((f) =>
278
+ /(^|\/)(tests?|spec|__tests__)\//.test(rel(f)) ||
279
+ /\.(test|spec)\.[a-z]+$/.test(rel(f)) ||
280
+ /(^|\/)test_[^/]+\.py$/.test(rel(f))
281
+ );
282
+ return testFiles.length
283
+ ? { kind: "PASS", detail: `${testFiles.length} test files` }
284
+ : { kind: "FAIL", detail: "no test files found" };
285
+ },
286
+ },
287
+ {
288
+ id: "TST-SKIPPED",
289
+ priority: "P1",
290
+ rule: "TST-003",
291
+ title: "No disabled tests",
292
+ run: () => {
293
+ const hits = grepFiles(
294
+ /\b(it|test|describe)\.skip\(|\bxit\(|\bxdescribe\(|@pytest\.mark\.skip|t\.Skip\(/,
295
+ 20
296
+ );
297
+ return hits.length
298
+ ? { kind: "WARN", detail: `${hits.length} file(s): ${hits.slice(0, 3).join(", ")}` }
299
+ : { kind: "PASS" };
300
+ },
301
+ },
302
+ {
303
+ id: "TST-SCRIPT",
304
+ priority: "P1",
305
+ rule: "TST-001",
306
+ title: "A test command exists",
307
+ run: () => {
308
+ if (!pkg) return { kind: "SKIP", detail: "no package.json" };
309
+ const t = scripts.test;
310
+ if (!t) return { kind: "WARN", detail: "no npm test script" };
311
+ return /no test specified/.test(t)
312
+ ? { kind: "FAIL", detail: "test script is the npm placeholder" }
313
+ : { kind: "PASS" };
314
+ },
315
+ },
316
+ {
317
+ id: "OPS-LOCKFILE",
318
+ priority: "P1",
319
+ rule: "OPS-004",
320
+ title: "Dependency lockfile committed",
321
+ run: () => {
322
+ const manifests = ["package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile"];
323
+ if (!anyExists(root, manifests)) return { kind: "SKIP", detail: "no manifest" };
324
+ const lock = anyExists(root, [
325
+ "package-lock.json",
326
+ "pnpm-lock.yaml",
327
+ "yarn.lock",
328
+ "poetry.lock",
329
+ "uv.lock",
330
+ "requirements.txt",
331
+ "go.sum",
332
+ "Cargo.lock",
333
+ "Gemfile.lock",
334
+ ]);
335
+ return lock
336
+ ? { kind: "PASS", detail: lock }
337
+ : { kind: "FAIL", detail: "no lockfile" };
338
+ },
339
+ },
340
+ {
341
+ id: "DB-MIGRATIONS",
342
+ priority: "P1",
343
+ rule: "DB-001",
344
+ title: "Schema changes are versioned migrations",
345
+ run: () => {
346
+ const usesDb =
347
+ hasDep("pg", "mysql2", "prisma", "@prisma/client", "typeorm", "sequelize", "knex",
348
+ "drizzle-orm", "mongoose", "sqlalchemy") ||
349
+ files.some((f) => /\.sql$/.test(rel(f)));
350
+ if (!usesDb) return { kind: "SKIP", detail: "no database detected" };
351
+ const dir = anyExists(root, [
352
+ "migrations",
353
+ "db/migrate",
354
+ "prisma/migrations",
355
+ "alembic",
356
+ path.join("src", "migrations"),
357
+ ]);
358
+ return dir
359
+ ? { kind: "PASS", detail: dir }
360
+ : { kind: "FAIL", detail: "database in use, no migrations directory" };
361
+ },
362
+ },
363
+ {
364
+ id: "AGT-CONTRACT",
365
+ priority: "P1",
366
+ rule: "AGT-001",
367
+ title: "Agent contract at the repository root",
368
+ run: () =>
369
+ exists(path.join(root, "AGENTS.md"))
370
+ ? { kind: "PASS" }
371
+ : { kind: "WARN", detail: "run `devia skills install`" },
372
+ },
373
+ {
374
+ id: "DOC-README",
375
+ priority: "P2",
376
+ rule: "—",
377
+ title: "README present",
378
+ run: () =>
379
+ anyExists(root, ["README.md", "README.rst", "readme.md"])
380
+ ? { kind: "PASS" }
381
+ : { kind: "WARN", detail: "no README" },
382
+ },
383
+ {
384
+ id: "UI-A11Y-TOOLING",
385
+ priority: "P2",
386
+ rule: "A11Y-001",
387
+ title: "Accessibility tooling available",
388
+ run: () => {
389
+ if (config && config.modules && config.modules.design === false)
390
+ return { kind: "SKIP", detail: "design module disabled" };
391
+ if (!pkg) return { kind: "SKIP", detail: "no package.json" };
392
+ const found = hasDep(
393
+ "axe-core", "@axe-core/react", "@axe-core/playwright", "jest-axe",
394
+ "eslint-plugin-jsx-a11y", "pa11y", "@storybook/addon-a11y", "lighthouse"
395
+ );
396
+ return found
397
+ ? { kind: "PASS" }
398
+ : { kind: "WARN", detail: "no automated accessibility check configured" };
399
+ },
400
+ },
401
+ {
402
+ id: "OBS-ERRORS",
403
+ priority: "P2",
404
+ rule: "OBS-002",
405
+ title: "Errors reach something a human watches",
406
+ run: () => {
407
+ const profile = config?.project?.profile;
408
+ if (["cli", "library", "docs"].includes(profile))
409
+ return { kind: "SKIP", detail: `${profile} does not run as a watched service` };
410
+ if (!pkg) return { kind: "SKIP", detail: "no package.json" };
411
+ const found = hasDep("@sentry/node", "@sentry/browser", "@sentry/nextjs", "bugsnag",
412
+ "rollbar", "datadog-lambda-js", "dd-trace", "@opentelemetry/api");
413
+ return found
414
+ ? { kind: "PASS" }
415
+ : { kind: "WARN", detail: "no error tracker detected — verify manually" };
416
+ },
417
+ },
418
+ ];
419
+ }
420
+
421
+ export default async function check(ctx) {
422
+ const { root, flags } = ctx;
423
+
424
+ if (flags.help) {
425
+ line(`
426
+ ${color.bold("devia check")} — readiness gates
427
+
428
+ --root <dir> repository to check
429
+ --json machine-readable output
430
+ --all show passing checks too
431
+
432
+ Exit code is 1 when a P0 gate fails.
433
+ `.trim());
434
+ return 0;
435
+ }
436
+
437
+ const checks = makeChecks(root, ctx);
438
+ const results = checks.map((c) => ({ ...c, ...c.run(), run: undefined }));
439
+ const counts = results.reduce((a, r) => ((a[r.kind] = (a[r.kind] || 0) + 1), a), {});
440
+ const p0Failures = results.filter((r) => r.kind === "FAIL" && r.priority === "P0");
441
+ const failures = results.filter((r) => r.kind === "FAIL");
442
+
443
+ if (ctx.json) {
444
+ console.log(
445
+ JSON.stringify(
446
+ { ok: p0Failures.length === 0, counts, blocking: p0Failures.map((r) => r.id), results },
447
+ null,
448
+ 2
449
+ )
450
+ );
451
+ return p0Failures.length ? 1 : 0;
452
+ }
453
+
454
+ heading(`devia check — ${path.basename(root)}`);
455
+ for (const r of results) {
456
+ if (!flags.all && r.kind === "PASS") continue;
457
+ status(r.kind, `${r.priority} ${r.title}`, [r.detail, r.rule !== "—" ? r.rule : ""]
458
+ .filter(Boolean)
459
+ .join(" · "));
460
+ }
461
+
462
+ line("");
463
+ const parts = ["PASS", "WARN", "FAIL", "SKIP"]
464
+ .filter((k) => counts[k])
465
+ .map((k) => `${counts[k]} ${k.toLowerCase()}`)
466
+ .join(" · ");
467
+ line(` ${parts}`);
468
+
469
+ if (p0Failures.length) {
470
+ line(
471
+ ` ${color.red("BLOCKED")} — ${p0Failures.length} P0 gate(s) failing: ${p0Failures
472
+ .map((r) => r.id)
473
+ .join(", ")}`
474
+ );
475
+ line(color.dim(" Not production ready. Do not report done (AGT-005)."));
476
+ } else if (failures.length) {
477
+ line(` ${color.yellow("PASSES P0")} — ${failures.length} non-blocking failure(s) to schedule`);
478
+ } else {
479
+ line(` ${color.green("P0 clear")} — list the warnings for the human before claiming done`);
480
+ }
481
+ line("");
482
+ return p0Failures.length ? 1 : 0;
483
+ }