@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,475 @@
1
+ #!/usr/bin/env python3
2
+ # SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com>
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ """Embedding backend abstraction for repo-local episodic memory.
5
+
6
+ Default: MLX (`mlx-community/mxbai-embed-large-v1`, 1024-dim). Faster
7
+ per-call once warm (~10ms) and dramatically faster on batches (~2ms
8
+ amortized at batch=10) compared to Ollama HTTP (~15ms warm).
9
+
10
+ Fallback: Ollama (`bge-m3`, 1024-dim). Hybrid recall Phase A migrated
11
+ the Ollama default from `mxbai-embed-large` to BGE-M3 — same dimension,
12
+ better hybrid retrieval performance, ColBERT-mode-ready for Phase E
13
+ late-interaction. The MLX default stays at mxbai-embed-large-v1 because
14
+ no `mlx-community/bge-m3` weights are cached locally; cross-backend
15
+ vectors are NOT comparable, so callers writing rows must record
16
+ `embedding_model_version` and recall must re-embed when querying rows
17
+ written by a different model. See research entry
18
+ `build-loop-search-architecture` for rationale.
19
+
20
+ The active backend is chosen on first call from $EMBED_BACKEND
21
+ ({"mlx","ollama"}, default "mlx"). If MLX init fails (import error,
22
+ model load error, first-call failure), the module logs a warning to
23
+ stderr and falls through to Ollama for the rest of the process. Once
24
+ fallen through, MLX is not retried — keeps stop-hook latency
25
+ predictable.
26
+
27
+ Public API:
28
+ embed(text) -> list[float] (single text)
29
+ embed([t1, t2, ...]) -> list[list[float]] (batched)
30
+ dimension() -> int (always 1024)
31
+ active_backend() -> "mlx" | "ollama" (after first call)
32
+ active_model() -> model id string (after first call)
33
+
34
+ Env vars:
35
+ EMBED_BACKEND "mlx" (default) or "ollama"
36
+ EMBED_MODEL model id (defaults: mxbai-embed-large-v1 for MLX,
37
+ bge-m3 for Ollama)
38
+ MLX_FORCE_FAIL any truthy value forces fallback (used by tests)
39
+
40
+ Output format: Python lists of floats. Callers don't need numpy / mlx.
41
+
42
+ Exit semantics: this module never calls sys.exit. On total backend
43
+ failure (MLX broken AND Ollama unreachable), embed() raises
44
+ RuntimeError. Callers decide policy (write_decision.py logs and
45
+ swallows; recall.py exits 2).
46
+ """
47
+ from __future__ import annotations
48
+
49
+ import json
50
+ import os
51
+ import sys
52
+ import urllib.request
53
+ from typing import Sequence
54
+
55
+ EMBED_DIM = 1024
56
+ MLX_DEFAULT_MODEL = "mlx-community/mxbai-embed-large-v1"
57
+ # Phase A hybrid-recall migration: Ollama default switched from
58
+ # `mxbai-embed-large` to `bge-m3`. Both are 1024-dim, so the pgvector
59
+ # column dimension is unchanged, but the vector spaces are NOT
60
+ # comparable. Rows written by mxbai must be re-embedded with bge-m3
61
+ # before recall can fuse them with bge-m3-embedded queries — see
62
+ # scripts/migrate_reembed_to_bgem3.py.
63
+ OLLAMA_DEFAULT_MODEL = "bge-m3"
64
+ OLLAMA_HOST = "127.0.0.1"
65
+ OLLAMA_PORT = 11434
66
+ OLLAMA_TIMEOUT_S = 60
67
+
68
+ # Daemon-side keep-alive override. Default Ollama evicts an idle model
69
+ # after 5 minutes — re-paying ~250-500ms model-load on the next call.
70
+ # 24h matches the cadence of a typical work session and amortizes warmup
71
+ # across every Stop hook firing in that window. Override per-process via
72
+ # OLLAMA_KEEP_ALIVE env (matches Ollama's own env var name).
73
+ OLLAMA_KEEP_ALIVE = os.environ.get("OLLAMA_KEEP_ALIVE", "24h")
74
+
75
+ # ---- Daemon (Phase H) ---------------------------------------------------
76
+ # Long-running stdlib HTTP server that holds the embedder backend in
77
+ # memory across recall.py invocations. Probed once per process; cached.
78
+ # When the daemon is up, every embed() call routes through it (~10-20ms
79
+ # loopback overhead vs ~3000ms cold MLX load per fresh process).
80
+ EMBED_DAEMON_HOST = os.environ.get("EMBED_DAEMON_HOST", "127.0.0.1")
81
+ try:
82
+ EMBED_DAEMON_PORT = int(os.environ.get("EMBED_DAEMON_PORT", "8766"))
83
+ except ValueError:
84
+ EMBED_DAEMON_PORT = 8766
85
+ EMBED_DAEMON_PROBE_TIMEOUT_S = 0.1 # 100ms — fast fail when daemon is down.
86
+ EMBED_DAEMON_CALL_TIMEOUT_S = 30.0 # generous; covers MLX cold-loaded large batches.
87
+
88
+
89
+ def _log(msg: str) -> None:
90
+ print(f"[embed_backend] {msg}", file=sys.stderr, flush=True)
91
+
92
+
93
+ # ---------- Ollama backend ----------
94
+
95
+
96
+ class OllamaBackend:
97
+ """Persistent-HTTP Ollama backend. Reuses one HTTPConnection across calls."""
98
+
99
+ def __init__(self, model: str = OLLAMA_DEFAULT_MODEL) -> None:
100
+ self.model = model
101
+ self._conn = None # lazy
102
+
103
+ def _ensure_conn(self):
104
+ # Stdlib http.client; recreate on broken-pipe-style errors.
105
+ import http.client
106
+
107
+ if self._conn is None:
108
+ self._conn = http.client.HTTPConnection(OLLAMA_HOST, OLLAMA_PORT, timeout=OLLAMA_TIMEOUT_S)
109
+ return self._conn
110
+
111
+ def _post_one(self, text: str) -> list[float]:
112
+ body = json.dumps({
113
+ "model": self.model,
114
+ "prompt": text,
115
+ "keep_alive": OLLAMA_KEEP_ALIVE,
116
+ }).encode("utf-8")
117
+ # Try persistent conn; on failure recreate once.
118
+ for attempt in (1, 2):
119
+ try:
120
+ conn = self._ensure_conn()
121
+ conn.request(
122
+ "POST",
123
+ "/api/embeddings",
124
+ body=body,
125
+ headers={"Content-Type": "application/json", "Connection": "keep-alive"},
126
+ )
127
+ resp = conn.getresponse()
128
+ payload = resp.read()
129
+ if resp.status != 200:
130
+ raise RuntimeError(f"ollama HTTP {resp.status}: {payload[:200]!r}")
131
+ data = json.loads(payload)
132
+ emb = data.get("embedding")
133
+ if not isinstance(emb, list):
134
+ raise RuntimeError("ollama: missing 'embedding' in response")
135
+ return [float(x) for x in emb]
136
+ except (ConnectionError, OSError, RuntimeError):
137
+ # Reset and retry once.
138
+ try:
139
+ if self._conn is not None:
140
+ self._conn.close()
141
+ except Exception: # noqa: BLE001
142
+ pass
143
+ self._conn = None
144
+ if attempt == 2:
145
+ raise
146
+
147
+ raise RuntimeError("ollama: unreachable")
148
+
149
+ def embed(self, text: str) -> list[float]:
150
+ return self._post_one(text)
151
+
152
+ def embed_batch(self, texts: Sequence[str]) -> list[list[float]]:
153
+ # Ollama /api/embeddings does not natively batch; loop on persistent conn.
154
+ return [self._post_one(t) for t in texts]
155
+
156
+ def name(self) -> str:
157
+ return "ollama"
158
+
159
+
160
+ # ---------- MLX backend ----------
161
+
162
+
163
+ class MLXBackend:
164
+ """Local MLX backend using mlx-embeddings.
165
+
166
+ Lazy-loads the model on first call (~220ms warm cache). The model
167
+ object is cached for the process lifetime.
168
+ """
169
+
170
+ def __init__(self, model_id: str = MLX_DEFAULT_MODEL) -> None:
171
+ self.model_id = model_id
172
+ self._model = None
173
+ self._tokenizer = None
174
+ self._generate = None
175
+
176
+ def _ensure_loaded(self) -> None:
177
+ if self._model is not None:
178
+ return
179
+ if os.environ.get("MLX_FORCE_FAIL"):
180
+ raise RuntimeError("MLX_FORCE_FAIL set; simulated failure")
181
+ # Local import keeps Linux installs (where mlx-embeddings is not
182
+ # available) from blowing up at module import time.
183
+ from mlx_embeddings import generate, load # type: ignore
184
+
185
+ self._model, self._tokenizer = load(self.model_id)
186
+ self._generate = generate
187
+
188
+ def embed(self, text: str) -> list[float]:
189
+ self._ensure_loaded()
190
+ if not text:
191
+ raise ValueError("embed_backend: empty text not supported")
192
+ out = self._generate(self._model, self._tokenizer, texts=[text])
193
+ return [float(x) for x in out.text_embeds[0].tolist()]
194
+
195
+ def embed_batch(self, texts: Sequence[str]) -> list[list[float]]:
196
+ self._ensure_loaded()
197
+ if not texts:
198
+ return []
199
+ if any((not t) for t in texts):
200
+ raise ValueError("embed_backend: empty text in batch not supported")
201
+ out = self._generate(self._model, self._tokenizer, texts=list(texts))
202
+ return [[float(x) for x in row.tolist()] for row in out.text_embeds]
203
+
204
+ def name(self) -> str:
205
+ return "mlx"
206
+
207
+
208
+ # ---------- Daemon backend (Phase H) ----------
209
+
210
+
211
+ class DaemonBackend:
212
+ """HTTP client for `scripts/embed_daemon.py`.
213
+
214
+ Speaks the same `embed`/`embed_batch`/`name` interface as the in-process
215
+ backends so `_select_backend()` can hand it to callers unchanged. The
216
+ daemon holds the model in memory across recall.py invocations,
217
+ eliminating the ~3000ms MLX cold-load cliff on every fresh process.
218
+
219
+ Failure handling: any HTTP error is raised so `_select_backend()` can
220
+ fall back to the in-process MLX/Ollama path. Once the in-process
221
+ backend is selected for this process, the daemon is not retried —
222
+ keeps latency predictable and avoids per-call probe cost.
223
+ """
224
+
225
+ def __init__(
226
+ self,
227
+ *,
228
+ host: str = EMBED_DAEMON_HOST,
229
+ port: int = EMBED_DAEMON_PORT,
230
+ backend_name: str = "unknown",
231
+ model: str = "unknown",
232
+ ) -> None:
233
+ self.host = host
234
+ self.port = port
235
+ # Carries the BACKEND the daemon advertises (mlx|ollama) plus its
236
+ # model id, so callers asking active_backend() / active_model()
237
+ # see the underlying truth, not the literal string "daemon".
238
+ self._daemon_backend = backend_name
239
+ self.model = model
240
+ self._conn = None # lazy http.client.HTTPConnection
241
+
242
+ def _ensure_conn(self):
243
+ import http.client # noqa: PLC0415
244
+
245
+ if self._conn is None:
246
+ self._conn = http.client.HTTPConnection(
247
+ self.host, self.port, timeout=EMBED_DAEMON_CALL_TIMEOUT_S
248
+ )
249
+ return self._conn
250
+
251
+ def _post_embed(self, texts: list[str]) -> list[list[float]]:
252
+ body = json.dumps({"texts": texts}).encode("utf-8")
253
+ for attempt in (1, 2):
254
+ try:
255
+ conn = self._ensure_conn()
256
+ conn.request(
257
+ "POST",
258
+ "/embed",
259
+ body=body,
260
+ headers={
261
+ "Content-Type": "application/json",
262
+ "Connection": "keep-alive",
263
+ },
264
+ )
265
+ resp = conn.getresponse()
266
+ payload = resp.read()
267
+ if resp.status != 200:
268
+ raise RuntimeError(
269
+ f"embed daemon HTTP {resp.status}: {payload[:200]!r}"
270
+ )
271
+ data = json.loads(payload)
272
+ if not data.get("ok"):
273
+ raise RuntimeError(
274
+ f"embed daemon not-ok: {data.get('error', 'unknown')}"
275
+ )
276
+ embs = data.get("embeddings")
277
+ if not isinstance(embs, list):
278
+ raise RuntimeError(
279
+ "embed daemon: missing 'embeddings' in response"
280
+ )
281
+ return [[float(x) for x in row] for row in embs]
282
+ except (ConnectionError, OSError, RuntimeError):
283
+ # Reset and retry once. If the daemon was up at probe but
284
+ # has since died, this gives us one shot to reconnect
285
+ # before kicking back to the caller for fallback.
286
+ try:
287
+ if self._conn is not None:
288
+ self._conn.close()
289
+ except Exception: # noqa: BLE001
290
+ pass
291
+ self._conn = None
292
+ if attempt == 2:
293
+ raise
294
+ raise RuntimeError("embed daemon: unreachable")
295
+
296
+ def embed(self, text: str) -> list[float]:
297
+ out = self._post_embed([text])
298
+ if not out:
299
+ raise RuntimeError("embed daemon returned empty embeddings list")
300
+ return out[0]
301
+
302
+ def embed_batch(self, texts: Sequence[str]) -> list[list[float]]:
303
+ if not texts:
304
+ return []
305
+ return self._post_embed(list(texts))
306
+
307
+ def name(self) -> str:
308
+ # Surface the underlying backend rather than "daemon" so callers
309
+ # writing rows tag them with the actual model that produced them.
310
+ return self._daemon_backend or "daemon"
311
+
312
+
313
+ # ---------- module-level singleton ----------
314
+
315
+ _BACKEND = None # type: ignore # OllamaBackend | MLXBackend | DaemonBackend | None
316
+ _FALLBACK_REASON: str | None = None
317
+ _DAEMON_PROBED: bool = False # Per-process probe latch.
318
+
319
+
320
+ def _probe_daemon() -> DaemonBackend | None:
321
+ """One-shot probe of the embed daemon's /health endpoint.
322
+
323
+ Latched via `_DAEMON_PROBED` so we never re-probe within the same
324
+ process. If `EMBED_FORCE_INPROCESS` is set, the probe is skipped
325
+ entirely and returns None — used by tests and by users diagnosing
326
+ a degraded daemon.
327
+
328
+ Returns a configured `DaemonBackend` when the daemon is up AND
329
+ reports `warm: true`, else None.
330
+ """
331
+ global _DAEMON_PROBED
332
+ if _DAEMON_PROBED:
333
+ # Caller checks this through the cached _BACKEND singleton.
334
+ return None
335
+ _DAEMON_PROBED = True
336
+ if os.environ.get("EMBED_FORCE_INPROCESS"):
337
+ return None
338
+ try:
339
+ import urllib.request # noqa: PLC0415
340
+
341
+ url = f"http://{EMBED_DAEMON_HOST}:{EMBED_DAEMON_PORT}/health"
342
+ req = urllib.request.Request(url, method="GET")
343
+ with urllib.request.urlopen(req, timeout=EMBED_DAEMON_PROBE_TIMEOUT_S) as resp: # noqa: S310
344
+ body = json.loads(resp.read().decode("utf-8"))
345
+ # Daemon is "available" iff it claims the backend is warm. A
346
+ # daemon serving in degraded mode (backend not loaded) returns
347
+ # 503 on POST, so treating warm=False as unavailable lets us
348
+ # fall back to the in-process path which may succeed via a
349
+ # different load path.
350
+ if body.get("ok") and body.get("warm"):
351
+ backend_name = body.get("backend", "unknown")
352
+ model_name = body.get("model", "unknown")
353
+ _log(
354
+ f"embed daemon up at {EMBED_DAEMON_HOST}:{EMBED_DAEMON_PORT} "
355
+ f"(backend={backend_name} model={model_name})"
356
+ )
357
+ return DaemonBackend(
358
+ backend_name=backend_name,
359
+ model=model_name,
360
+ )
361
+ except Exception as e: # noqa: BLE001
362
+ # Quiet by design — probe failures are routine when the daemon
363
+ # isn't running. Logged at debug level only.
364
+ _log_debug = os.environ.get("EMBED_BACKEND_DEBUG")
365
+ if _log_debug:
366
+ _log(f"embed daemon probe failed: {e!r}")
367
+ return None
368
+
369
+
370
+ def _select_backend():
371
+ global _BACKEND, _FALLBACK_REASON
372
+ if _BACKEND is not None:
373
+ return _BACKEND
374
+
375
+ # Phase H: try the daemon FIRST. When it's up, this is the entire
376
+ # selection — we don't load MLX/Ollama in-process at all.
377
+ daemon = _probe_daemon()
378
+ if daemon is not None:
379
+ _BACKEND = daemon
380
+ return _BACKEND
381
+
382
+ requested = os.environ.get("EMBED_BACKEND", "mlx").lower().strip()
383
+ custom_model = os.environ.get("EMBED_MODEL")
384
+
385
+ if requested == "ollama":
386
+ _BACKEND = OllamaBackend(model=custom_model or OLLAMA_DEFAULT_MODEL)
387
+ return _BACKEND
388
+
389
+ if requested != "mlx":
390
+ _log(f"unknown EMBED_BACKEND={requested!r}; using mlx")
391
+
392
+ # Try MLX; fall through to Ollama on any error.
393
+ candidate = MLXBackend(model_id=custom_model or MLX_DEFAULT_MODEL)
394
+ try:
395
+ # Force the lazy load NOW so failure is detected before first
396
+ # production call. Adds ~220ms one-time cold start; we eat it
397
+ # here so the first user-facing call is steady-state.
398
+ candidate._ensure_loaded()
399
+ _BACKEND = candidate
400
+ return _BACKEND
401
+ except Exception as e: # noqa: BLE001
402
+ _FALLBACK_REASON = f"MLX init failed: {e!r}"
403
+ _log(f"falling back to ollama ({_FALLBACK_REASON})")
404
+ _BACKEND = OllamaBackend(model=OLLAMA_DEFAULT_MODEL)
405
+ return _BACKEND
406
+
407
+
408
+ def embed(text): # type: ignore[no-untyped-def]
409
+ """Embed a single string or a list of strings.
410
+
411
+ Single → list[float] of length 1024.
412
+ Batch → list[list[float]] (each length 1024).
413
+ """
414
+ backend = _select_backend()
415
+ if isinstance(text, str):
416
+ return backend.embed(text)
417
+ if isinstance(text, (list, tuple)):
418
+ return backend.embed_batch(list(text))
419
+ raise TypeError(f"embed() expects str or list[str], got {type(text).__name__}")
420
+
421
+
422
+ def dimension() -> int:
423
+ """Return the embedding dimensionality (1024)."""
424
+ return EMBED_DIM
425
+
426
+
427
+ def active_backend() -> str:
428
+ """Return 'mlx' or 'ollama' (after first embed call)."""
429
+ return _select_backend().name()
430
+
431
+
432
+ def active_model() -> str:
433
+ """Return the model identifier the active backend is configured to use.
434
+
435
+ Useful for `embedding_model_version` provenance: every write should
436
+ record which model produced the vector so cross-space mismatches can
437
+ be detected at recall time.
438
+ """
439
+ backend = _select_backend()
440
+ return getattr(backend, "model", None) or getattr(backend, "model_id", "unknown")
441
+
442
+
443
+ def fallback_reason() -> str | None:
444
+ """Return why we fell through to Ollama, or None if MLX is active."""
445
+ _select_backend()
446
+ return _FALLBACK_REASON
447
+
448
+
449
+ def reset_for_tests() -> None:
450
+ """Clear the singleton so tests can re-select with new env.
451
+
452
+ Closes the Ollama / Daemon HTTP connection if one was open to avoid
453
+ ResourceWarning on rapid backend switches. Also clears the
454
+ per-process daemon-probe latch so `_select_backend()` will probe
455
+ the daemon again on the next call.
456
+ """
457
+ global _BACKEND, _FALLBACK_REASON, _DAEMON_PROBED
458
+ if _BACKEND is not None and isinstance(_BACKEND, (OllamaBackend, DaemonBackend)):
459
+ try:
460
+ if _BACKEND._conn is not None:
461
+ _BACKEND._conn.close()
462
+ except Exception: # noqa: BLE001
463
+ pass
464
+ _BACKEND = None
465
+ _FALLBACK_REASON = None
466
+ _DAEMON_PROBED = False
467
+
468
+
469
+ if __name__ == "__main__":
470
+ # CLI: `python3 embed_backend.py 'some text'` → print dim and first 5 floats
471
+ if len(sys.argv) < 2:
472
+ print("usage: embed_backend.py <text>", file=sys.stderr)
473
+ sys.exit(1)
474
+ v = embed(sys.argv[1])
475
+ print(f"backend={active_backend()} dim={len(v)} preview={v[:5]}")