@tyroneross/build-loop 0.30.3

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 (389) hide show
  1. package/.agents/plugins/marketplace.json +10 -0
  2. package/.claude-plugin/marketplace.json +38 -0
  3. package/.claude-plugin/plugin.json +30 -0
  4. package/.codex-plugin/plugin.json +41 -0
  5. package/.cursor/rules/build-loop-surface.mdc +22 -0
  6. package/AGENTS.md +498 -0
  7. package/LICENSE +202 -0
  8. package/README.md +403 -0
  9. package/agents/alignment-checker.md +124 -0
  10. package/agents/api-assessor.md +136 -0
  11. package/agents/architecture-scout.md +185 -0
  12. package/agents/assessment-orchestrator.md +163 -0
  13. package/agents/build-orchestrator.md +198 -0
  14. package/agents/database-assessor.md +133 -0
  15. package/agents/design-contract-specialist.md +239 -0
  16. package/agents/fact-checker.md +69 -0
  17. package/agents/fix-critique.md +161 -0
  18. package/agents/frontend-assessor.md +136 -0
  19. package/agents/implementer.md +185 -0
  20. package/agents/independent-auditor.md +143 -0
  21. package/agents/mock-scanner.md +78 -0
  22. package/agents/optimize-runner.md +112 -0
  23. package/agents/overfitting-reviewer.md +96 -0
  24. package/agents/performance-assessor.md +159 -0
  25. package/agents/plan-critic.md +85 -0
  26. package/agents/promotion-reviewer.md +121 -0
  27. package/agents/recurring-pattern-detector.md +248 -0
  28. package/agents/retrospective-synthesizer.md +109 -0
  29. package/agents/root-cause-investigator.md +285 -0
  30. package/agents/scope-auditor.md +121 -0
  31. package/agents/security-reviewer.md +151 -0
  32. package/agents/self-improvement-architect.md +125 -0
  33. package/agents/synthesis-critic.md +99 -0
  34. package/agents/transcript-pattern-miner.md +165 -0
  35. package/agents/ui-validator.md +193 -0
  36. package/codex-skills/build-loop/SKILL.md +20 -0
  37. package/codex-skills/debug-loop/SKILL.md +18 -0
  38. package/codex-skills/handoff/SKILL.md +22 -0
  39. package/codex-skills/knowledge/SKILL.md +21 -0
  40. package/codex-skills/optimize/SKILL.md +18 -0
  41. package/codex-skills/research/SKILL.md +18 -0
  42. package/commands/agent-rally-point.md +301 -0
  43. package/commands/assess.md +41 -0
  44. package/commands/debug.md +20 -0
  45. package/commands/debugger-detail.md +34 -0
  46. package/commands/debugger-scan.md +15 -0
  47. package/commands/debugger-status.md +20 -0
  48. package/commands/debugger.md +32 -0
  49. package/commands/handoff.md +113 -0
  50. package/commands/knowledge-review.md +16 -0
  51. package/commands/optimize.md +31 -0
  52. package/commands/plan-verify.md +39 -0
  53. package/commands/promote-experiment.md +129 -0
  54. package/commands/research.md +22 -0
  55. package/commands/run.md +12 -0
  56. package/commands/self-review.md +51 -0
  57. package/commands/start-prd.md +57 -0
  58. package/commands/test.md +34 -0
  59. package/dist/src/assessment-orchestrator.d.ts +78 -0
  60. package/dist/src/assessment-orchestrator.d.ts.map +1 -0
  61. package/dist/src/assessment-orchestrator.js +304 -0
  62. package/dist/src/assessment-orchestrator.js.map +1 -0
  63. package/dist/src/audit-miner.d.ts +21 -0
  64. package/dist/src/audit-miner.d.ts.map +1 -0
  65. package/dist/src/audit-miner.js +421 -0
  66. package/dist/src/audit-miner.js.map +1 -0
  67. package/dist/src/batch-operations.d.ts +30 -0
  68. package/dist/src/batch-operations.d.ts.map +1 -0
  69. package/dist/src/batch-operations.js +339 -0
  70. package/dist/src/batch-operations.js.map +1 -0
  71. package/dist/src/config.d.ts +83 -0
  72. package/dist/src/config.d.ts.map +1 -0
  73. package/dist/src/config.js +176 -0
  74. package/dist/src/config.js.map +1 -0
  75. package/dist/src/context-engine.d.ts +45 -0
  76. package/dist/src/context-engine.d.ts.map +1 -0
  77. package/dist/src/context-engine.js +135 -0
  78. package/dist/src/context-engine.js.map +1 -0
  79. package/dist/src/debug-wrapper.d.ts +58 -0
  80. package/dist/src/debug-wrapper.d.ts.map +1 -0
  81. package/dist/src/debug-wrapper.js +285 -0
  82. package/dist/src/debug-wrapper.js.map +1 -0
  83. package/dist/src/index.d.ts +31 -0
  84. package/dist/src/index.d.ts.map +1 -0
  85. package/dist/src/index.js +149 -0
  86. package/dist/src/index.js.map +1 -0
  87. package/dist/src/interactive-verifier.d.ts +26 -0
  88. package/dist/src/interactive-verifier.d.ts.map +1 -0
  89. package/dist/src/interactive-verifier.js +435 -0
  90. package/dist/src/interactive-verifier.js.map +1 -0
  91. package/dist/src/lessons.d.ts +59 -0
  92. package/dist/src/lessons.d.ts.map +1 -0
  93. package/dist/src/lessons.js +172 -0
  94. package/dist/src/lessons.js.map +1 -0
  95. package/dist/src/log-reader.d.ts +39 -0
  96. package/dist/src/log-reader.d.ts.map +1 -0
  97. package/dist/src/log-reader.js +291 -0
  98. package/dist/src/log-reader.js.map +1 -0
  99. package/dist/src/logger.d.ts +59 -0
  100. package/dist/src/logger.d.ts.map +1 -0
  101. package/dist/src/logger.js +328 -0
  102. package/dist/src/logger.js.map +1 -0
  103. package/dist/src/parallel-retrieval.d.ts +52 -0
  104. package/dist/src/parallel-retrieval.d.ts.map +1 -0
  105. package/dist/src/parallel-retrieval.js +309 -0
  106. package/dist/src/parallel-retrieval.js.map +1 -0
  107. package/dist/src/pattern-extractor.d.ts +30 -0
  108. package/dist/src/pattern-extractor.d.ts.map +1 -0
  109. package/dist/src/pattern-extractor.js +386 -0
  110. package/dist/src/pattern-extractor.js.map +1 -0
  111. package/dist/src/result-aggregator.d.ts +44 -0
  112. package/dist/src/result-aggregator.d.ts.map +1 -0
  113. package/dist/src/result-aggregator.js +315 -0
  114. package/dist/src/result-aggregator.js.map +1 -0
  115. package/dist/src/retrieval.d.ts +139 -0
  116. package/dist/src/retrieval.d.ts.map +1 -0
  117. package/dist/src/retrieval.js +724 -0
  118. package/dist/src/retrieval.js.map +1 -0
  119. package/dist/src/setup/auto-setup.d.ts +15 -0
  120. package/dist/src/setup/auto-setup.d.ts.map +1 -0
  121. package/dist/src/setup/auto-setup.js +157 -0
  122. package/dist/src/setup/auto-setup.js.map +1 -0
  123. package/dist/src/setup/configure-hooks.d.ts +8 -0
  124. package/dist/src/setup/configure-hooks.d.ts.map +1 -0
  125. package/dist/src/setup/configure-hooks.js +16 -0
  126. package/dist/src/setup/configure-hooks.js.map +1 -0
  127. package/dist/src/setup/create-slash-commands.d.ts +8 -0
  128. package/dist/src/setup/create-slash-commands.d.ts.map +1 -0
  129. package/dist/src/setup/create-slash-commands.js +101 -0
  130. package/dist/src/setup/create-slash-commands.js.map +1 -0
  131. package/dist/src/setup/index.d.ts +8 -0
  132. package/dist/src/setup/index.d.ts.map +1 -0
  133. package/dist/src/setup/index.js +17 -0
  134. package/dist/src/setup/index.js.map +1 -0
  135. package/dist/src/setup/inject-claude-md.d.ts +10 -0
  136. package/dist/src/setup/inject-claude-md.d.ts.map +1 -0
  137. package/dist/src/setup/inject-claude-md.js +150 -0
  138. package/dist/src/setup/inject-claude-md.js.map +1 -0
  139. package/dist/src/setup/uninstall.d.ts +22 -0
  140. package/dist/src/setup/uninstall.d.ts.map +1 -0
  141. package/dist/src/setup/uninstall.js +235 -0
  142. package/dist/src/setup/uninstall.js.map +1 -0
  143. package/dist/src/storage.d.ts +192 -0
  144. package/dist/src/storage.d.ts.map +1 -0
  145. package/dist/src/storage.js +1037 -0
  146. package/dist/src/storage.js.map +1 -0
  147. package/dist/src/string-similarity.d.ts +8 -0
  148. package/dist/src/string-similarity.d.ts.map +1 -0
  149. package/dist/src/string-similarity.js +57 -0
  150. package/dist/src/string-similarity.js.map +1 -0
  151. package/dist/src/traces/adapters/browser.d.ts +69 -0
  152. package/dist/src/traces/adapters/browser.d.ts.map +1 -0
  153. package/dist/src/traces/adapters/browser.js +280 -0
  154. package/dist/src/traces/adapters/browser.js.map +1 -0
  155. package/dist/src/traces/adapters/index.d.ts +23 -0
  156. package/dist/src/traces/adapters/index.d.ts.map +1 -0
  157. package/dist/src/traces/adapters/index.js +67 -0
  158. package/dist/src/traces/adapters/index.js.map +1 -0
  159. package/dist/src/traces/adapters/langchain.d.ts +42 -0
  160. package/dist/src/traces/adapters/langchain.d.ts.map +1 -0
  161. package/dist/src/traces/adapters/langchain.js +151 -0
  162. package/dist/src/traces/adapters/langchain.js.map +1 -0
  163. package/dist/src/traces/adapters/opentelemetry.d.ts +46 -0
  164. package/dist/src/traces/adapters/opentelemetry.d.ts.map +1 -0
  165. package/dist/src/traces/adapters/opentelemetry.js +164 -0
  166. package/dist/src/traces/adapters/opentelemetry.js.map +1 -0
  167. package/dist/src/traces/adapters/sentry.d.ts +58 -0
  168. package/dist/src/traces/adapters/sentry.d.ts.map +1 -0
  169. package/dist/src/traces/adapters/sentry.js +212 -0
  170. package/dist/src/traces/adapters/sentry.js.map +1 -0
  171. package/dist/src/traces/index.d.ts +10 -0
  172. package/dist/src/traces/index.d.ts.map +1 -0
  173. package/dist/src/traces/index.js +45 -0
  174. package/dist/src/traces/index.js.map +1 -0
  175. package/dist/src/traces/storage.d.ts +78 -0
  176. package/dist/src/traces/storage.d.ts.map +1 -0
  177. package/dist/src/traces/storage.js +399 -0
  178. package/dist/src/traces/storage.js.map +1 -0
  179. package/dist/src/traces/summarizer.d.ts +83 -0
  180. package/dist/src/traces/summarizer.d.ts.map +1 -0
  181. package/dist/src/traces/summarizer.js +247 -0
  182. package/dist/src/traces/summarizer.js.map +1 -0
  183. package/dist/src/traces/types.d.ts +365 -0
  184. package/dist/src/traces/types.d.ts.map +1 -0
  185. package/dist/src/traces/types.js +14 -0
  186. package/dist/src/traces/types.js.map +1 -0
  187. package/dist/src/types.d.ts +495 -0
  188. package/dist/src/types.d.ts.map +1 -0
  189. package/dist/src/types.js +27 -0
  190. package/dist/src/types.js.map +1 -0
  191. package/docs/agent-surface-policy.md +45 -0
  192. package/docs/memory-setup.md +226 -0
  193. package/hooks/_arch_scan_bg.py +88 -0
  194. package/hooks/_plugin_drift_check_bg.py +85 -0
  195. package/hooks/_session_start_lib.sh +42 -0
  196. package/hooks/git/pre-push +141 -0
  197. package/hooks/hooks.json +126 -0
  198. package/hooks/post-commit +30 -0
  199. package/hooks/pre-commit +29 -0
  200. package/hooks/pre-edit-apppulse.sh +6 -0
  201. package/hooks/pre-edit-architecture.sh +106 -0
  202. package/hooks/pre-edit-rally-point.sh +92 -0
  203. package/hooks/session-start-apppulse.sh +6 -0
  204. package/hooks/session-start-architecture.sh +10 -0
  205. package/hooks/session-start-git-hooks.sh +12 -0
  206. package/hooks/session-start-plugin-drift.sh +27 -0
  207. package/hooks/session-start-rally-point.sh +44 -0
  208. package/hooks/session-start-retrieval.sh +24 -0
  209. package/hooks/session-start-worktree-gc.sh +105 -0
  210. package/hooks/test_apppulse_hooks.sh +6 -0
  211. package/hooks/test_rally_point_hooks.sh +388 -0
  212. package/hooks/test_sec008_hooks.sh +66 -0
  213. package/package.json +111 -0
  214. package/scripts/README.md +301 -0
  215. package/scripts/_db_url.py +61 -0
  216. package/scripts/_paths.py +445 -0
  217. package/scripts/blm.py +162 -0
  218. package/scripts/blm_api.py +263 -0
  219. package/scripts/check_cache_sync.py +490 -0
  220. package/scripts/embed_backend.py +475 -0
  221. package/scripts/install_memory.py +556 -0
  222. package/scripts/lessons_index/__init__.py +77 -0
  223. package/scripts/lessons_index/__main__.py +135 -0
  224. package/scripts/lessons_index/ingest.py +288 -0
  225. package/scripts/lessons_index/query.py +285 -0
  226. package/scripts/lessons_index/schema.py +114 -0
  227. package/scripts/memory_context/__init__.py +610 -0
  228. package/scripts/memory_graph/__init__.py +393 -0
  229. package/scripts/project_resolver.py +172 -0
  230. package/scripts/prune_codex_plugin_cache.py +23 -0
  231. package/scripts/prune_plugin_cache.py +359 -0
  232. package/scripts/semantic_index/__init__.py +482 -0
  233. package/scripts/semantic_index/_bench_hybrid.py +175 -0
  234. package/scripts/semantic_index/backfill.py +263 -0
  235. package/scripts/semantic_index/hybrid.py +174 -0
  236. package/scripts/semantic_index/test_backfill.py +292 -0
  237. package/scripts/semantic_index/test_hybrid.py +541 -0
  238. package/scripts/sync_navgator_lessons.py +666 -0
  239. package/scripts/sync_plugin_cache.py +388 -0
  240. package/skills/agent-rally-point/SKILL.md +165 -0
  241. package/skills/agent-rally-watcher/SKILL.md +83 -0
  242. package/skills/api-registry-bridge/SKILL.md +59 -0
  243. package/skills/architecture/dead/SKILL.md +56 -0
  244. package/skills/architecture/impact/SKILL.md +88 -0
  245. package/skills/architecture/review/SKILL.md +227 -0
  246. package/skills/architecture/rules/SKILL.md +72 -0
  247. package/skills/architecture/scan/SKILL.md +79 -0
  248. package/skills/architecture/trace/SKILL.md +65 -0
  249. package/skills/attribution-standard/SKILL.md +122 -0
  250. package/skills/authentication/SKILL.md +81 -0
  251. package/skills/authentication/references/better-auth-magic-link.md +135 -0
  252. package/skills/authentication/references/better-auth-setup.md +224 -0
  253. package/skills/authentication/references/google-calendar-sync.md +278 -0
  254. package/skills/authentication/references/google-cloud-console.md +159 -0
  255. package/skills/authentication/references/google-geocoding-directions.md +126 -0
  256. package/skills/authentication/references/google-lessons-example-web-app.md +177 -0
  257. package/skills/authentication/references/google-maps.md +162 -0
  258. package/skills/authentication/references/google-oauth-setup.md +343 -0
  259. package/skills/authentication/references/google-places.md +173 -0
  260. package/skills/authentication/references/lessons-example-web-app-better-auth.md +126 -0
  261. package/skills/authentication/references/resend-email.md +227 -0
  262. package/skills/authentication/references/resend-otp-magic-link.md +153 -0
  263. package/skills/authentication/references/supabase-auth.md +172 -0
  264. package/skills/auto-decision-capture/SKILL.md +419 -0
  265. package/skills/build-loop/SKILL.md +516 -0
  266. package/skills/build-loop/detect-plugins.mjs +82 -0
  267. package/skills/build-loop/eval-guide.md +65 -0
  268. package/skills/build-loop/fallbacks.md +549 -0
  269. package/skills/build-loop/phases/fact-check.md +42 -0
  270. package/skills/build-loop/phases/ui-validation.md +267 -0
  271. package/skills/build-loop/references/apple-native-planning.md +439 -0
  272. package/skills/build-loop/references/capability-routing.md +181 -0
  273. package/skills/build-loop/references/codex-subagents.md +98 -0
  274. package/skills/build-loop/references/coordination.md +161 -0
  275. package/skills/build-loop/references/correction-aware-capture.md +177 -0
  276. package/skills/build-loop/references/independent-auditor.md +72 -0
  277. package/skills/build-loop/references/intent-capability-pack.md +170 -0
  278. package/skills/build-loop/references/intent-exploration-prompts.md +96 -0
  279. package/skills/build-loop/references/leadership.md +72 -0
  280. package/skills/build-loop/references/memory.md +284 -0
  281. package/skills/build-loop/references/modular-systems-pack.md +96 -0
  282. package/skills/build-loop/references/output-style.md +129 -0
  283. package/skills/build-loop/references/pay-it-forward-arch.md +98 -0
  284. package/skills/build-loop/references/phase-1-assess.md +218 -0
  285. package/skills/build-loop/references/phase-2-plan.md +77 -0
  286. package/skills/build-loop/references/phase-3-execute.md +47 -0
  287. package/skills/build-loop/references/phase-4-review.md +310 -0
  288. package/skills/build-loop/references/phase-5-iterate.md +71 -0
  289. package/skills/build-loop/references/phase-6-learn.md +56 -0
  290. package/skills/build-loop/references/recent-design-structures.md +274 -0
  291. package/skills/build-loop/references/refactor-history/ASSESSMENT.md +85 -0
  292. package/skills/build-loop/references/refactor-history/STANDALONE_TEST_RUN.md +149 -0
  293. package/skills/build-loop/references/refactor-history/scenarios/01-simple-bugfix.md +32 -0
  294. package/skills/build-loop/references/refactor-history/scenarios/02-ui-build-with-iteration.md +48 -0
  295. package/skills/build-loop/references/refactor-history/scenarios/03-multi-failure-escalation.md +60 -0
  296. package/skills/build-loop/references/refactor-history/scenarios/04-ui-build-ibr-absent.md +51 -0
  297. package/skills/build-loop/references/refactor-history/scenarios/05-refactor-navgator-absent.md +71 -0
  298. package/skills/build-loop/references/refactor-history/scenarios/06-recurring-bug-debugger-absent.md +52 -0
  299. package/skills/build-loop/references/refactor-history/trace-comparison.md +202 -0
  300. package/skills/build-loop/references/self-recursive-dev.md +77 -0
  301. package/skills/build-loop/references/self-review.md +232 -0
  302. package/skills/build-loop/references/ui-io-contract.md +116 -0
  303. package/skills/build-loop/scanners/audit-design-rules.mjs +476 -0
  304. package/skills/build-loop/scanners/require-visual-evidence.mjs +239 -0
  305. package/skills/build-loop/templates/backlog-item.md +35 -0
  306. package/skills/build-loop/templates/codex-worker-prompt.md +89 -0
  307. package/skills/build-loop/templates/ui-subagent-prompt.md +179 -0
  308. package/skills/build-loop/templates/ux-fix-plan.md +40 -0
  309. package/skills/building-with-deepagents/SKILL.md +195 -0
  310. package/skills/building-with-deepagents/references/anti-patterns.md +141 -0
  311. package/skills/building-with-deepagents/references/api-quick-reference.md +184 -0
  312. package/skills/capabilities/SKILL.md +91 -0
  313. package/skills/debug-loop/SKILL.md +278 -0
  314. package/skills/debug-loop/references/convergence-rules.md +145 -0
  315. package/skills/debug-loop/references/swiftui-macos-clunky-ui-debugger.html +823 -0
  316. package/skills/debugging/assess/SKILL.md +111 -0
  317. package/skills/debugging/debug-loop/SKILL.md +231 -0
  318. package/skills/debugging/memory/SKILL.md +147 -0
  319. package/skills/debugging/store/SKILL.md +153 -0
  320. package/skills/debugging-memory/SKILL.md +440 -0
  321. package/skills/debugging-memory/examples/incident-example.json +67 -0
  322. package/skills/debugging-memory/references/incident-documentation.md +280 -0
  323. package/skills/debugging-memory/references/ios-notification-alarm-playbook.md +300 -0
  324. package/skills/debugging-memory/references/pattern-extraction.md +163 -0
  325. package/skills/debugging-memory/references/subagent-integration.md +312 -0
  326. package/skills/defenseclaw-bridge/SKILL.md +156 -0
  327. package/skills/defenseclaw-bridge/references/dc-config-mapping.md +162 -0
  328. package/skills/defenseclaw-bridge/references/output-format.md +108 -0
  329. package/skills/handoff/SKILL.md +94 -0
  330. package/skills/ibr-bridge/SKILL.md +68 -0
  331. package/skills/knowledge/SKILL.md +127 -0
  332. package/skills/knowledge/references/recall-integration.md +83 -0
  333. package/skills/knowledge/templates/madr-minimal.md +56 -0
  334. package/skills/knowledge-review/SKILL.md +112 -0
  335. package/skills/logging-tracer/SKILL.md +202 -0
  336. package/skills/logging-tracer/references/log-analysis.md +128 -0
  337. package/skills/logging-tracer/references/stack-templates.md +274 -0
  338. package/skills/logging-tracer-bridge/SKILL.md +70 -0
  339. package/skills/mcp-builder/SKILL.md +278 -0
  340. package/skills/mcp-builder/references/mcp-security.md +106 -0
  341. package/skills/model-tiering/SKILL.md +216 -0
  342. package/skills/native-ax-driver/SKILL.md +220 -0
  343. package/skills/native-ax-driver/scripts/layout_fill.py +222 -0
  344. package/skills/native-ax-driver/scripts/native_driver.py +495 -0
  345. package/skills/native-ax-driver/swift/bl-ax-driver/Package.swift +20 -0
  346. package/skills/native-ax-driver/swift/bl-ax-driver/Sources/main.swift +542 -0
  347. package/skills/optimize/SKILL.md +202 -0
  348. package/skills/optimize/profiles.md +61 -0
  349. package/skills/plan-verify/SKILL.md +115 -0
  350. package/skills/plan-verify/test-fixtures/example-app-v20-findings.json +27 -0
  351. package/skills/plan-verify/test-fixtures/example-app-v20.md +42 -0
  352. package/skills/plan-verify/test-fixtures/example-app-v22-findings.json +15 -0
  353. package/skills/plan-verify/test-fixtures/example-app-v22.md +1608 -0
  354. package/skills/plan-verify/test-fixtures/unrelated-good-plan-findings.json +15 -0
  355. package/skills/plan-verify/test-fixtures/unrelated-good-plan.md +55 -0
  356. package/skills/plugin-builder/SKILL.md +329 -0
  357. package/skills/plugin-builder/references/authoritative-sources.md +104 -0
  358. package/skills/plugin-builder/references/build-loop-phase-guidance.md +94 -0
  359. package/skills/plugin-builder/references/components-guide.md +221 -0
  360. package/skills/plugin-builder/references/distribution.md +317 -0
  361. package/skills/plugin-builder/references/dual-host-claude-codex.md +220 -0
  362. package/skills/plugin-builder/references/hooks-reference.md +210 -0
  363. package/skills/plugin-builder/references/manifest-schema.md +111 -0
  364. package/skills/plugin-builder/references/plugin-hygiene-lessons.md +307 -0
  365. package/skills/plugin-tests/SKILL.md +94 -0
  366. package/skills/prd-bridge/SKILL.md +135 -0
  367. package/skills/research/SKILL.md +80 -0
  368. package/skills/security-methodology/SKILL.md +105 -0
  369. package/skills/security-methodology/references/cross-source-matrix.md +77 -0
  370. package/skills/security-methodology/references/mitre-atlas-starter.md +83 -0
  371. package/skills/security-methodology/references/nist-600-1-mapping.md +119 -0
  372. package/skills/security-methodology/references/owasp-agentic-top-10.md +157 -0
  373. package/skills/security-methodology/references/owasp-llm-top-10.md +144 -0
  374. package/skills/security-methodology/references/owasp-web-top-10.md +65 -0
  375. package/skills/self-improve/SKILL.md +298 -0
  376. package/skills/spec-writing/SKILL.md +548 -0
  377. package/skills/spec-writing/scripts/check_checklist.py +478 -0
  378. package/skills/sync-skills/SKILL.md +132 -0
  379. package/skills/telemetry/SKILL.md +66 -0
  380. package/skills/ui-design/SKILL.md +75 -0
  381. package/skills/ui-design/references/design-patterns-multi.md +165 -0
  382. package/skills/ui-design/references/design-preferences-from-owned-apps.md +150 -0
  383. package/skills/ui-design/references/evidence-capture-policy.md +55 -0
  384. package/skills/ui-design/references/ui-guidance-sources.md +330 -0
  385. package/skills/ui-design/references/universal-design-principles.alt.md +182 -0
  386. package/skills/ui-design/references/universal-design-principles.md +419 -0
  387. package/templates/memory/MEMORY.md.template +55 -0
  388. package/templates/memory/constitution.md.template +64 -0
  389. package/templates/memory/manifest.json +47 -0
@@ -0,0 +1,476 @@
1
+ #!/usr/bin/env node
2
+ // SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com>
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ /**
5
+ * build-loop Phase 7, Gate C: Design Rule Scanner
6
+ *
7
+ * Zero-dependency, single-file static scanner for UI design-rule violations.
8
+ * Mirrors audit-hardcoded-secrets.mjs architecture (Node >= 18, stdlib only).
9
+ *
10
+ * Pattern library covers:
11
+ * - SwiftUI / iOS: status pills, animation accessibility, raw UIColor RGB,
12
+ * literal font sizes, literal corner radii, icon-only accessibility labels
13
+ * - React / Web: Tailwind pill patterns, missing motion-reduce, raw hex colors,
14
+ * arbitrary text size values
15
+ *
16
+ * Exit codes:
17
+ * 0 = clean
18
+ * 1 = warnings only
19
+ * 2 = must-fix findings present
20
+ *
21
+ * Usage:
22
+ * node audit-design-rules.mjs # scan cwd, auto-detect platform
23
+ * node audit-design-rules.mjs --root=/path/to/project
24
+ * node audit-design-rules.mjs --platform=swiftui
25
+ * node audit-design-rules.mjs --platform=react
26
+ * node audit-design-rules.mjs --targets=Views,Components
27
+ * node audit-design-rules.mjs --exts=.swift
28
+ * node audit-design-rules.mjs --json
29
+ */
30
+
31
+ import fs from 'fs';
32
+ import path from 'path';
33
+
34
+ // =============================================================================
35
+ // ARG PARSING
36
+ // =============================================================================
37
+
38
+ function parseArgs(argv) {
39
+ const out = {
40
+ targets: null,
41
+ exts: null,
42
+ root: process.cwd(),
43
+ platform: null,
44
+ json: false,
45
+ };
46
+ for (const arg of argv.slice(2)) {
47
+ if (arg.startsWith('--targets=')) {
48
+ out.targets = arg.slice('--targets='.length).split(',').map((s) => s.trim()).filter(Boolean);
49
+ } else if (arg.startsWith('--exts=')) {
50
+ out.exts = arg.slice('--exts='.length).split(',').map((s) => s.trim()).filter(Boolean);
51
+ } else if (arg.startsWith('--root=')) {
52
+ out.root = path.resolve(arg.slice('--root='.length));
53
+ } else if (arg.startsWith('--platform=')) {
54
+ out.platform = arg.slice('--platform='.length).trim().toLowerCase();
55
+ } else if (arg === '--json') {
56
+ out.json = true;
57
+ }
58
+ }
59
+ return out;
60
+ }
61
+
62
+ const args = parseArgs(process.argv);
63
+ const root = args.root;
64
+
65
+ // =============================================================================
66
+ // PATTERN LIBRARIES
67
+ // =============================================================================
68
+
69
+ /**
70
+ * Rule shape:
71
+ * id string unique rule identifier
72
+ * severity 'must-fix' | 'warn' | 'info'
73
+ * description string human message
74
+ * pattern RegExp match in (comment-stripped) file content
75
+ * contextRequired RegExp? the match is skipped unless this regex also
76
+ * matches within ±contextWindow chars of the match
77
+ * contextWindow number? characters each side to check (default 300)
78
+ * fileMustContain RegExp? whole-file guard (before comment stripping)
79
+ * invertFileCheck boolean? if true, rule fires when file does NOT contain
80
+ * fileMustContain (i.e. it's the absence check)
81
+ * pathExclude RegExp? skip this rule entirely if the file path matches
82
+ */
83
+
84
+ const SWIFTUI_RULES = [
85
+ {
86
+ // Fires when .background(...) immediately followed (possibly with
87
+ // intervening whitespace/newline) by .clipShape(Capsule()) and the
88
+ // surrounding context contains a chip/badge/status/trend/score indicator.
89
+ // The background argument itself must contain a color expression
90
+ // (not just Theme.surfacePrimary which is fine for layouts).
91
+ // We look for .opacity( or a status/score color variable as the tell
92
+ // that this is a status pill, not just a card container.
93
+ id: 'status-pill-background',
94
+ severity: 'must-fix',
95
+ description: 'Status indicators must use text color only, not background fills (CLAUDE.md "Signal" rule)',
96
+ // Matches .background(<anything with opacity or color>).clipShape(Capsule())
97
+ // allowing whitespace between the two modifiers.
98
+ pattern: /\.background\([^)]*(?:\.opacity\([^)]+\)|[Cc]olor[^)]*)\)[\s\S]{0,60}?\.clipShape\(Capsule\(\)\)/,
99
+ contextRequired: /(Chip|chip|Badge|badge|Status|status|Trend|trend|Score|score|Rating|rating|Label|label|Tag|tag|filterChip|dimChip|paceRating|trendColor)/,
100
+ contextWindow: 400,
101
+ },
102
+ {
103
+ // .repeatForever( in a file that does NOT have accessibilityReduceMotion
104
+ id: 'animation-without-reducemotion',
105
+ severity: 'must-fix',
106
+ description: 'Continuous animations must respect accessibilityReduceMotion',
107
+ pattern: /\.repeatForever\(/,
108
+ fileMustContain: /accessibilityReduceMotion/,
109
+ invertFileCheck: true,
110
+ },
111
+ {
112
+ // Raw UIColor(red:green:blue:) literals outside Theme/
113
+ id: 'uicolor-rgb-outside-theme',
114
+ severity: 'must-fix',
115
+ description: 'Use Theme tokens, not raw UIColor(red:green:blue:) literals',
116
+ pattern: /UIColor\(red:\s*[\d.]+,\s*green:\s*[\d.]+,\s*blue:\s*[\d.]+/,
117
+ pathExclude: /\/Theme\//,
118
+ },
119
+ {
120
+ // Matches Text(...)\n? .font(.system(size: N)) where the .font is NOT
121
+ // chained on Image. We use a positive contextRequired to require "Text("
122
+ // in the preceding 80 chars AND a negative contextRequired-style guard
123
+ // (_preContextRequired) that we handle in the scanner loop.
124
+ id: 'system-font-size-body-copy',
125
+ severity: 'warn',
126
+ description: 'Body copy should use Theme.fontBody/fontCaption tokens for Dynamic Type support',
127
+ // Only capture the simple .font(.system(size: N)) form (no weight/design)
128
+ // — weight-bearing calls like .system(size:weight:design:) are intentional
129
+ pattern: /\.font\(\.system\(size:\s*\d+\)\)/,
130
+ contextRequired: /Text\(/,
131
+ contextWindow: 120,
132
+ _preContextOnly: true, // custom flag: contextRequired must match BEFORE the offset
133
+ pathExclude: /\/Theme\/|Chip|chip|Badge|badge|Tabular|Numeric/,
134
+ },
135
+ {
136
+ id: 'literal-corner-radius',
137
+ severity: 'warn',
138
+ description: 'Use Theme.cornerSmall/Medium/Large/XL tokens, not bare numeric corner radii',
139
+ pattern: /(\.cornerRadius\(\s*\d+\s*\)|RoundedRectangle\(cornerRadius:\s*\d+\s*\))/,
140
+ pathExclude: /\/Theme\//,
141
+ },
142
+ {
143
+ // withAnimation(.easeInOut(duration:) or similar in file without reduceMotion guard
144
+ id: 'animation-duration-without-reducemotion',
145
+ severity: 'warn',
146
+ description: 'Animations with duration should be gated on accessibilityReduceMotion',
147
+ pattern: /(withAnimation\(\.\w+\(duration:|\.easeInOut\(duration:)/,
148
+ fileMustContain: /accessibilityReduceMotion/,
149
+ invertFileCheck: true,
150
+ },
151
+ {
152
+ // Icon-only Image(systemName:) without an .accessibilityLabel within 300 chars
153
+ id: 'sf-symbol-without-label',
154
+ severity: 'warn',
155
+ description: 'Icon-only Image(systemName:) should have explicit accessibilityLabel',
156
+ // Negative lookahead is not reliable across multiline — use contextRequired inversion below
157
+ pattern: /Image\(systemName:\s*"[^"]+"\)/,
158
+ // We invert this: skip the finding IF accessibilityLabel appears nearby
159
+ contextRequired: /^(?![\s\S]*accessibilityLabel)/, // placeholder — handled in code
160
+ contextWindow: 300,
161
+ pathExclude: /Tests/,
162
+ _accessibilityCheck: true, // custom flag handled in scanner loop
163
+ },
164
+ ];
165
+
166
+ const WEB_RULES = [
167
+ {
168
+ id: 'status-pill-tailwind',
169
+ severity: 'must-fix',
170
+ description: 'Status indicators must use text color only, not background fills',
171
+ pattern: /className="[^"]*\bbg-\w+-\d{3}\b[^"]*\brounded-(full|2xl|xl)\b[^"]*"/,
172
+ contextRequired: /(chip|badge|status|trend|tag)/i,
173
+ contextWindow: 300,
174
+ },
175
+ {
176
+ id: 'animation-without-motion-reduce',
177
+ severity: 'must-fix',
178
+ description: 'Continuous animations must have motion-reduce: variant',
179
+ pattern: /\b(animate-pulse|animate-spin|animate-bounce|animate-ping)\b(?![^"]*motion-reduce)/,
180
+ },
181
+ {
182
+ id: 'hex-color-outside-theme',
183
+ severity: 'warn',
184
+ description: 'Use theme tokens, not raw hex color literals',
185
+ pattern: /[:'"]\s*#[0-9a-fA-F]{3,6}\s*[;'"]?/,
186
+ pathExclude: /tailwind\.config|theme|tokens|\.css$|\.scss$/,
187
+ },
188
+ {
189
+ id: 'arbitrary-text-size',
190
+ severity: 'warn',
191
+ description: 'Use theme text size tokens, not arbitrary px values',
192
+ pattern: /\btext-\[\d+px\]/,
193
+ },
194
+ ];
195
+
196
+ // =============================================================================
197
+ // PLATFORM CONFIG
198
+ // =============================================================================
199
+
200
+ const PLATFORM_CONFIG = {
201
+ swiftui: {
202
+ rules: SWIFTUI_RULES,
203
+ defaultTargets: ['Views', 'Components', 'View.swift'],
204
+ defaultExts: ['.swift'],
205
+ },
206
+ react: {
207
+ rules: WEB_RULES,
208
+ defaultTargets: ['src', 'components', 'app', 'pages'],
209
+ defaultExts: ['.tsx', '.jsx', '.ts', '.js', '.html', '.vue'],
210
+ },
211
+ web: {
212
+ rules: WEB_RULES,
213
+ defaultTargets: ['src', 'components', 'app', 'pages'],
214
+ defaultExts: ['.tsx', '.jsx', '.ts', '.js', '.html', '.vue'],
215
+ },
216
+ };
217
+
218
+ // Dirs always skipped during walk
219
+ const SKIP_DIRS = new Set([
220
+ 'node_modules', '.build', 'DerivedData', '__tests__', '.git',
221
+ '.turbo', '.vercel', 'out', '.cache', 'dist', 'build', 'coverage',
222
+ ]);
223
+
224
+ const SKIP_PATH_FRAGMENTS = ['/Tests/', '/test/', '/__tests__/'];
225
+
226
+ // =============================================================================
227
+ // PLATFORM AUTO-DETECTION
228
+ // =============================================================================
229
+
230
+ function* walkForDetect(dir, depth = 0) {
231
+ if (depth > 4) return;
232
+ let entries;
233
+ try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }
234
+ for (const e of entries) {
235
+ if (SKIP_DIRS.has(e.name)) continue;
236
+ const full = path.join(dir, e.name);
237
+ if (e.isDirectory()) yield* walkForDetect(full, depth + 1);
238
+ else yield full;
239
+ }
240
+ }
241
+
242
+ function detectPlatform(scanRoot, targets) {
243
+ const checkDirs = targets
244
+ ? targets.map((t) => path.join(scanRoot, t))
245
+ : [scanRoot];
246
+
247
+ let hasSwift = false;
248
+ let hasTsxJsx = false;
249
+
250
+ outer: for (const dir of checkDirs) {
251
+ if (!fs.existsSync(dir)) continue;
252
+ const stat = fs.statSync(dir);
253
+ const files = stat.isDirectory() ? [...walkForDetect(dir)] : [dir];
254
+ for (const f of files) {
255
+ const ext = path.extname(f);
256
+ if (ext === '.swift') { hasSwift = true; break outer; }
257
+ if (ext === '.tsx' || ext === '.jsx') hasTsxJsx = true;
258
+ }
259
+ }
260
+ if (hasSwift) return 'swiftui';
261
+ if (hasTsxJsx) return 'react';
262
+ return 'web';
263
+ }
264
+
265
+ // =============================================================================
266
+ // FILE WALKER
267
+ // =============================================================================
268
+
269
+ function* walk(dir) {
270
+ let entries;
271
+ try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }
272
+ for (const entry of entries) {
273
+ if (entry.name.startsWith('.') && SKIP_DIRS.has(entry.name.slice(1))) continue;
274
+ if (SKIP_DIRS.has(entry.name)) continue;
275
+ const fullPath = path.join(dir, entry.name);
276
+ if (entry.isDirectory()) yield* walk(fullPath);
277
+ else yield fullPath;
278
+ }
279
+ }
280
+
281
+ // =============================================================================
282
+ // COMMENT STRIPPING (Swift and JS/TS)
283
+ // For design rules we strip comments — commented-out code is not rendered UI.
284
+ // =============================================================================
285
+
286
+ function stripComments(source, ext) {
287
+ if (ext === '.swift' || ext === '.ts' || ext === '.tsx' || ext === '.js' || ext === '.jsx' || ext === '.mjs') {
288
+ return source
289
+ .replace(/\/\*[\s\S]*?\*\//g, (m) => ' '.repeat(m.length)) // block comments → spaces (preserve offsets)
290
+ .replace(/(^|\s)\/\/.*$/gm, (m, p1) => p1 + ' '.repeat(m.length - p1.length)); // line comments → spaces
291
+ }
292
+ if (ext === '.html' || ext === '.vue') {
293
+ return source.replace(/<!--[\s\S]*?-->/g, (m) => ' '.repeat(m.length));
294
+ }
295
+ return source;
296
+ }
297
+
298
+ // =============================================================================
299
+ // OFFSET → LINE NUMBER
300
+ // =============================================================================
301
+
302
+ function lineNumberAt(source, offset) {
303
+ let line = 1;
304
+ for (let i = 0; i < offset && i < source.length; i++) {
305
+ if (source[i] === '\n') line++;
306
+ }
307
+ return line;
308
+ }
309
+
310
+ // =============================================================================
311
+ // SNIPPET: single line of context around match
312
+ // =============================================================================
313
+
314
+ function snippetAt(source, offset) {
315
+ const start = source.lastIndexOf('\n', offset) + 1;
316
+ const end = source.indexOf('\n', offset);
317
+ return source.slice(start, end === -1 ? undefined : end).trim();
318
+ }
319
+
320
+ // =============================================================================
321
+ // MAIN SCAN
322
+ // =============================================================================
323
+
324
+ const platform = args.platform ?? detectPlatform(root, args.targets);
325
+ const config = PLATFORM_CONFIG[platform] ?? PLATFORM_CONFIG.swiftui;
326
+ const rules = config.rules;
327
+ const exts = new Set(args.exts ?? config.defaultExts);
328
+ const scanTargets = args.targets ?? config.defaultTargets;
329
+
330
+ // Collect files
331
+ const filesToScan = [];
332
+
333
+ for (const target of scanTargets) {
334
+ // Target can be a path fragment (substring match) or a resolvable path
335
+ const absoluteTarget = path.isAbsolute(target) ? target : path.join(root, target);
336
+
337
+ if (fs.existsSync(absoluteTarget)) {
338
+ const stat = fs.statSync(absoluteTarget);
339
+ const candidates = stat.isDirectory() ? [...walk(absoluteTarget)] : [absoluteTarget];
340
+ for (const f of candidates) {
341
+ if (exts.has(path.extname(f)) && !filesToScan.includes(f)) {
342
+ // Apply global path exclusions
343
+ const skip = SKIP_PATH_FRAGMENTS.some((frag) => f.includes(frag));
344
+ if (!skip) filesToScan.push(f);
345
+ }
346
+ }
347
+ } else {
348
+ // Treat as substring: walk root and include files whose paths contain this target
349
+ for (const f of walk(root)) {
350
+ if (!exts.has(path.extname(f))) continue;
351
+ if (!f.includes(target)) continue;
352
+ if (filesToScan.includes(f)) continue;
353
+ const skip = SKIP_PATH_FRAGMENTS.some((frag) => f.includes(frag));
354
+ if (!skip) filesToScan.push(f);
355
+ }
356
+ }
357
+ }
358
+
359
+ const findings = [];
360
+
361
+ for (const filePath of filesToScan) {
362
+ const ext = path.extname(filePath);
363
+ let source;
364
+ try { source = fs.readFileSync(filePath, 'utf8'); } catch { continue; }
365
+
366
+ const stripped = stripComments(source, ext);
367
+
368
+ for (const rule of rules) {
369
+ // pathExclude check
370
+ if (rule.pathExclude && rule.pathExclude.test(filePath)) continue;
371
+
372
+ // fileMustContain / invertFileCheck — whole-file guard (use original source)
373
+ if (rule.fileMustContain) {
374
+ const fileHas = rule.fileMustContain.test(source);
375
+ if (rule.invertFileCheck) {
376
+ // Fire only when file does NOT contain the guard — skip file if it does
377
+ if (fileHas) continue;
378
+ } else {
379
+ if (!fileHas) continue;
380
+ }
381
+ }
382
+
383
+ // Reset regex state
384
+ rule.pattern.lastIndex = 0;
385
+
386
+ let match;
387
+ const re = new RegExp(rule.pattern.source, rule.pattern.flags.includes('g') ? rule.pattern.flags : rule.pattern.flags + 'g');
388
+
389
+ while ((match = re.exec(stripped)) !== null) {
390
+ const matchOffset = match.index;
391
+ const cw = rule.contextWindow ?? 300;
392
+ const contextStart = Math.max(0, matchOffset - cw);
393
+ const contextEnd = Math.min(stripped.length, matchOffset + match[0].length + cw);
394
+ const context = stripped.slice(contextStart, contextEnd);
395
+
396
+ // Special accessibility check: skip if accessibilityLabel appears nearby
397
+ if (rule._accessibilityCheck) {
398
+ if (/accessibilityLabel/.test(context)) continue;
399
+ }
400
+
401
+ // contextRequired check (skip if nearby context doesn't match)
402
+ if (rule.contextRequired && !rule._accessibilityCheck) {
403
+ if (rule._preContextOnly) {
404
+ // Only check the content BEFORE the match (preceding contextWindow chars)
405
+ const preContext = stripped.slice(contextStart, matchOffset);
406
+ if (!rule.contextRequired.test(preContext)) continue;
407
+ } else {
408
+ if (!rule.contextRequired.test(context)) continue;
409
+ }
410
+ }
411
+
412
+ const lineNum = lineNumberAt(source, matchOffset);
413
+ const snippet = snippetAt(source, matchOffset);
414
+ const relPath = path.relative(root, filePath);
415
+
416
+ findings.push({
417
+ rule: rule.id,
418
+ severity: rule.severity,
419
+ file: relPath,
420
+ line: lineNum,
421
+ snippet: snippet.length > 120 ? snippet.slice(0, 120) + '...' : snippet,
422
+ description: rule.description,
423
+ });
424
+
425
+ // For rules without 'g' flag in original, only match once per file
426
+ if (!rule.pattern.flags.includes('g')) break;
427
+ }
428
+ }
429
+ }
430
+
431
+ // =============================================================================
432
+ // OUTPUT
433
+ // =============================================================================
434
+
435
+ const summary = {
436
+ mustFix: findings.filter((f) => f.severity === 'must-fix').length,
437
+ warn: findings.filter((f) => f.severity === 'warn').length,
438
+ info: findings.filter((f) => f.severity === 'info').length,
439
+ };
440
+
441
+ const exitCode = summary.mustFix > 0 ? 2 : summary.warn > 0 ? 1 : 0;
442
+
443
+ if (args.json) {
444
+ const output = {
445
+ platform,
446
+ rulesEvaluated: rules.length,
447
+ filesScanned: filesToScan.length,
448
+ findings,
449
+ summary,
450
+ exit: exitCode,
451
+ };
452
+ console.log(JSON.stringify(output, null, 2));
453
+ process.exit(exitCode);
454
+ }
455
+
456
+ // Text mode
457
+ console.log(`audit-design-rules: ${platform} pack, ${rules.length} rules`);
458
+ console.log(`files scanned: ${filesToScan.length}`);
459
+ console.log('');
460
+
461
+ function printGroup(severity, label) {
462
+ const group = findings.filter((f) => f.severity === severity);
463
+ console.log(`${label}: ${group.length}`);
464
+ for (const f of group) {
465
+ console.log(` ${f.file}:${f.line} [${f.rule}] ${f.description}`);
466
+ console.log(` → ${f.snippet}`);
467
+ }
468
+ if (group.length) console.log('');
469
+ }
470
+
471
+ printGroup('must-fix', 'must-fix');
472
+ printGroup('warn', 'warn');
473
+ printGroup('info', 'info');
474
+
475
+ console.log(`Exit: ${exitCode}`);
476
+ process.exit(exitCode);