aw-ecc 1.4.21

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 (764) hide show
  1. package/.agents/skills/api-design/SKILL.md +523 -0
  2. package/.agents/skills/api-design/agents/openai.yaml +7 -0
  3. package/.agents/skills/article-writing/SKILL.md +85 -0
  4. package/.agents/skills/article-writing/agents/openai.yaml +7 -0
  5. package/.agents/skills/backend-patterns/SKILL.md +598 -0
  6. package/.agents/skills/backend-patterns/agents/openai.yaml +7 -0
  7. package/.agents/skills/bun-runtime/SKILL.md +84 -0
  8. package/.agents/skills/bun-runtime/agents/openai.yaml +7 -0
  9. package/.agents/skills/claude-api/SKILL.md +337 -0
  10. package/.agents/skills/claude-api/agents/openai.yaml +7 -0
  11. package/.agents/skills/coding-standards/SKILL.md +530 -0
  12. package/.agents/skills/coding-standards/agents/openai.yaml +7 -0
  13. package/.agents/skills/content-engine/SKILL.md +88 -0
  14. package/.agents/skills/content-engine/agents/openai.yaml +7 -0
  15. package/.agents/skills/crosspost/SKILL.md +188 -0
  16. package/.agents/skills/crosspost/agents/openai.yaml +7 -0
  17. package/.agents/skills/deep-research/SKILL.md +155 -0
  18. package/.agents/skills/deep-research/agents/openai.yaml +7 -0
  19. package/.agents/skills/dmux-workflows/SKILL.md +144 -0
  20. package/.agents/skills/dmux-workflows/agents/openai.yaml +7 -0
  21. package/.agents/skills/documentation-lookup/SKILL.md +90 -0
  22. package/.agents/skills/documentation-lookup/agents/openai.yaml +7 -0
  23. package/.agents/skills/e2e-testing/SKILL.md +326 -0
  24. package/.agents/skills/e2e-testing/agents/openai.yaml +7 -0
  25. package/.agents/skills/eval-harness/SKILL.md +236 -0
  26. package/.agents/skills/eval-harness/agents/openai.yaml +7 -0
  27. package/.agents/skills/everything-claude-code/SKILL.md +442 -0
  28. package/.agents/skills/everything-claude-code/agents/openai.yaml +6 -0
  29. package/.agents/skills/exa-search/SKILL.md +170 -0
  30. package/.agents/skills/exa-search/agents/openai.yaml +7 -0
  31. package/.agents/skills/fal-ai-media/SKILL.md +277 -0
  32. package/.agents/skills/fal-ai-media/agents/openai.yaml +7 -0
  33. package/.agents/skills/frontend-patterns/SKILL.md +642 -0
  34. package/.agents/skills/frontend-patterns/agents/openai.yaml +7 -0
  35. package/.agents/skills/frontend-slides/SKILL.md +184 -0
  36. package/.agents/skills/frontend-slides/STYLE_PRESETS.md +330 -0
  37. package/.agents/skills/frontend-slides/agents/openai.yaml +7 -0
  38. package/.agents/skills/investor-materials/SKILL.md +96 -0
  39. package/.agents/skills/investor-materials/agents/openai.yaml +7 -0
  40. package/.agents/skills/investor-outreach/SKILL.md +76 -0
  41. package/.agents/skills/investor-outreach/agents/openai.yaml +7 -0
  42. package/.agents/skills/market-research/SKILL.md +75 -0
  43. package/.agents/skills/market-research/agents/openai.yaml +7 -0
  44. package/.agents/skills/mcp-server-patterns/SKILL.md +67 -0
  45. package/.agents/skills/nextjs-turbopack/SKILL.md +44 -0
  46. package/.agents/skills/nextjs-turbopack/agents/openai.yaml +7 -0
  47. package/.agents/skills/security-review/SKILL.md +495 -0
  48. package/.agents/skills/security-review/agents/openai.yaml +7 -0
  49. package/.agents/skills/strategic-compact/SKILL.md +103 -0
  50. package/.agents/skills/strategic-compact/agents/openai.yaml +7 -0
  51. package/.agents/skills/tdd-workflow/SKILL.md +410 -0
  52. package/.agents/skills/tdd-workflow/agents/openai.yaml +7 -0
  53. package/.agents/skills/verification-loop/SKILL.md +126 -0
  54. package/.agents/skills/verification-loop/agents/openai.yaml +7 -0
  55. package/.agents/skills/video-editing/SKILL.md +308 -0
  56. package/.agents/skills/video-editing/agents/openai.yaml +7 -0
  57. package/.agents/skills/x-api/SKILL.md +214 -0
  58. package/.agents/skills/x-api/agents/openai.yaml +7 -0
  59. package/.claude-plugin/README.md +17 -0
  60. package/.claude-plugin/plugin.json +24 -0
  61. package/.codex/AGENTS.md +93 -0
  62. package/.codex/INSTALL.md +64 -0
  63. package/.codex/agents/docs-researcher.toml +9 -0
  64. package/.codex/agents/explorer.toml +9 -0
  65. package/.codex/agents/reviewer.toml +9 -0
  66. package/.codex/config.toml +108 -0
  67. package/.codex/hooks/aw-post-tool-use.sh +5 -0
  68. package/.codex/hooks/aw-pre-tool-use.sh +5 -0
  69. package/.codex/hooks/aw-session-start.sh +21 -0
  70. package/.codex/hooks/aw-stop.sh +5 -0
  71. package/.codex/hooks/aw-user-prompt-submit.sh +9 -0
  72. package/.codex/hooks.json +62 -0
  73. package/.cursor/INSTALL.md +40 -0
  74. package/.cursor/hooks/adapter.js +120 -0
  75. package/.cursor/hooks/after-file-edit.js +11 -0
  76. package/.cursor/hooks/after-mcp-execution.js +11 -0
  77. package/.cursor/hooks/after-shell-execution.js +11 -0
  78. package/.cursor/hooks/after-tab-file-edit.js +12 -0
  79. package/.cursor/hooks/aw-phase-adapter.js +43 -0
  80. package/.cursor/hooks/before-mcp-execution.js +11 -0
  81. package/.cursor/hooks/before-read-file.js +13 -0
  82. package/.cursor/hooks/before-shell-execution.js +11 -0
  83. package/.cursor/hooks/before-submit-prompt.js +41 -0
  84. package/.cursor/hooks/before-tab-file-read.js +13 -0
  85. package/.cursor/hooks/pre-compact.js +11 -0
  86. package/.cursor/hooks/session-end.js +11 -0
  87. package/.cursor/hooks/session-start.js +11 -0
  88. package/.cursor/hooks/shared/aw-phase-definitions.js +190 -0
  89. package/.cursor/hooks/shared/aw-phase-runner.js +61 -0
  90. package/.cursor/hooks/shared/session-start.sh +20 -0
  91. package/.cursor/hooks/shared/user-prompt-submit.sh +155 -0
  92. package/.cursor/hooks/stop.js +11 -0
  93. package/.cursor/hooks/subagent-start.js +10 -0
  94. package/.cursor/hooks/subagent-stop.js +10 -0
  95. package/.cursor/hooks.json +115 -0
  96. package/.cursor/rules/common-agents.md +53 -0
  97. package/.cursor/rules/common-coding-style.md +52 -0
  98. package/.cursor/rules/common-development-workflow.md +33 -0
  99. package/.cursor/rules/common-git-workflow.md +28 -0
  100. package/.cursor/rules/common-hooks.md +34 -0
  101. package/.cursor/rules/common-patterns.md +35 -0
  102. package/.cursor/rules/common-performance.md +59 -0
  103. package/.cursor/rules/common-security.md +33 -0
  104. package/.cursor/rules/common-testing.md +33 -0
  105. package/.cursor/rules/golang-coding-style.md +31 -0
  106. package/.cursor/rules/golang-hooks.md +16 -0
  107. package/.cursor/rules/golang-patterns.md +44 -0
  108. package/.cursor/rules/golang-security.md +33 -0
  109. package/.cursor/rules/golang-testing.md +30 -0
  110. package/.cursor/rules/kotlin-coding-style.md +39 -0
  111. package/.cursor/rules/kotlin-hooks.md +16 -0
  112. package/.cursor/rules/kotlin-patterns.md +50 -0
  113. package/.cursor/rules/kotlin-security.md +58 -0
  114. package/.cursor/rules/kotlin-testing.md +38 -0
  115. package/.cursor/rules/php-coding-style.md +25 -0
  116. package/.cursor/rules/php-hooks.md +21 -0
  117. package/.cursor/rules/php-patterns.md +23 -0
  118. package/.cursor/rules/php-security.md +24 -0
  119. package/.cursor/rules/php-testing.md +26 -0
  120. package/.cursor/rules/python-coding-style.md +42 -0
  121. package/.cursor/rules/python-hooks.md +19 -0
  122. package/.cursor/rules/python-patterns.md +39 -0
  123. package/.cursor/rules/python-security.md +30 -0
  124. package/.cursor/rules/python-testing.md +38 -0
  125. package/.cursor/rules/swift-coding-style.md +47 -0
  126. package/.cursor/rules/swift-hooks.md +20 -0
  127. package/.cursor/rules/swift-patterns.md +66 -0
  128. package/.cursor/rules/swift-security.md +33 -0
  129. package/.cursor/rules/swift-testing.md +45 -0
  130. package/.cursor/rules/typescript-coding-style.md +63 -0
  131. package/.cursor/rules/typescript-hooks.md +20 -0
  132. package/.cursor/rules/typescript-patterns.md +50 -0
  133. package/.cursor/rules/typescript-security.md +26 -0
  134. package/.cursor/rules/typescript-testing.md +16 -0
  135. package/.cursor/skills/article-writing/SKILL.md +85 -0
  136. package/.cursor/skills/bun-runtime/SKILL.md +84 -0
  137. package/.cursor/skills/content-engine/SKILL.md +88 -0
  138. package/.cursor/skills/documentation-lookup/SKILL.md +90 -0
  139. package/.cursor/skills/frontend-slides/SKILL.md +184 -0
  140. package/.cursor/skills/frontend-slides/STYLE_PRESETS.md +330 -0
  141. package/.cursor/skills/investor-materials/SKILL.md +96 -0
  142. package/.cursor/skills/investor-outreach/SKILL.md +76 -0
  143. package/.cursor/skills/market-research/SKILL.md +75 -0
  144. package/.cursor/skills/mcp-server-patterns/SKILL.md +67 -0
  145. package/.cursor/skills/nextjs-turbopack/SKILL.md +44 -0
  146. package/.opencode/MIGRATION.md +368 -0
  147. package/.opencode/README.md +204 -0
  148. package/.opencode/commands/build-fix.md +56 -0
  149. package/.opencode/commands/checkpoint.md +67 -0
  150. package/.opencode/commands/code-review.md +68 -0
  151. package/.opencode/commands/e2e.md +105 -0
  152. package/.opencode/commands/eval.md +88 -0
  153. package/.opencode/commands/evolve.md +36 -0
  154. package/.opencode/commands/go-build.md +87 -0
  155. package/.opencode/commands/go-review.md +71 -0
  156. package/.opencode/commands/go-test.md +131 -0
  157. package/.opencode/commands/harness-audit.md +71 -0
  158. package/.opencode/commands/instinct-export.md +93 -0
  159. package/.opencode/commands/instinct-import.md +88 -0
  160. package/.opencode/commands/instinct-status.md +29 -0
  161. package/.opencode/commands/learn.md +61 -0
  162. package/.opencode/commands/loop-start.md +32 -0
  163. package/.opencode/commands/loop-status.md +24 -0
  164. package/.opencode/commands/model-route.md +26 -0
  165. package/.opencode/commands/orchestrate.md +88 -0
  166. package/.opencode/commands/plan.md +49 -0
  167. package/.opencode/commands/projects.md +23 -0
  168. package/.opencode/commands/promote.md +23 -0
  169. package/.opencode/commands/quality-gate.md +29 -0
  170. package/.opencode/commands/refactor-clean.md +102 -0
  171. package/.opencode/commands/rust-build.md +78 -0
  172. package/.opencode/commands/rust-review.md +65 -0
  173. package/.opencode/commands/rust-test.md +104 -0
  174. package/.opencode/commands/security.md +89 -0
  175. package/.opencode/commands/setup-pm.md +67 -0
  176. package/.opencode/commands/skill-create.md +117 -0
  177. package/.opencode/commands/tdd.md +66 -0
  178. package/.opencode/commands/test-coverage.md +80 -0
  179. package/.opencode/commands/update-codemaps.md +81 -0
  180. package/.opencode/commands/update-docs.md +67 -0
  181. package/.opencode/commands/verify.md +67 -0
  182. package/.opencode/index.ts +79 -0
  183. package/.opencode/instructions/INSTRUCTIONS.md +337 -0
  184. package/.opencode/opencode.json +319 -0
  185. package/.opencode/package.json +70 -0
  186. package/.opencode/plugins/ecc-hooks.ts +455 -0
  187. package/.opencode/plugins/index.ts +12 -0
  188. package/.opencode/prompts/agents/architect.txt +175 -0
  189. package/.opencode/prompts/agents/build-error-resolver.txt +233 -0
  190. package/.opencode/prompts/agents/code-reviewer.txt +103 -0
  191. package/.opencode/prompts/agents/database-reviewer.txt +247 -0
  192. package/.opencode/prompts/agents/doc-updater.txt +192 -0
  193. package/.opencode/prompts/agents/e2e-runner.txt +305 -0
  194. package/.opencode/prompts/agents/go-build-resolver.txt +325 -0
  195. package/.opencode/prompts/agents/go-reviewer.txt +241 -0
  196. package/.opencode/prompts/agents/planner.txt +112 -0
  197. package/.opencode/prompts/agents/refactor-cleaner.txt +241 -0
  198. package/.opencode/prompts/agents/rust-build-resolver.txt +93 -0
  199. package/.opencode/prompts/agents/rust-reviewer.txt +61 -0
  200. package/.opencode/prompts/agents/security-reviewer.txt +207 -0
  201. package/.opencode/prompts/agents/tdd-guide.txt +211 -0
  202. package/.opencode/tools/check-coverage.ts +170 -0
  203. package/.opencode/tools/format-code.ts +68 -0
  204. package/.opencode/tools/git-summary.ts +54 -0
  205. package/.opencode/tools/index.ts +13 -0
  206. package/.opencode/tools/lint-check.ts +85 -0
  207. package/.opencode/tools/run-tests.ts +139 -0
  208. package/.opencode/tools/security-audit.ts +277 -0
  209. package/.opencode/tsconfig.json +29 -0
  210. package/AGENTS.md +124 -0
  211. package/LICENSE +21 -0
  212. package/README.md +146 -0
  213. package/README.zh-CN.md +552 -0
  214. package/agents/architect.md +211 -0
  215. package/agents/build-error-resolver.md +114 -0
  216. package/agents/chief-of-staff.md +151 -0
  217. package/agents/code-reviewer.md +237 -0
  218. package/agents/cpp-build-resolver.md +90 -0
  219. package/agents/cpp-reviewer.md +72 -0
  220. package/agents/database-reviewer.md +91 -0
  221. package/agents/doc-updater.md +107 -0
  222. package/agents/docs-lookup.md +68 -0
  223. package/agents/e2e-runner.md +107 -0
  224. package/agents/evals/code-reviewer-scenarios.json +23 -0
  225. package/agents/flutter-reviewer.md +243 -0
  226. package/agents/go-build-resolver.md +94 -0
  227. package/agents/go-reviewer.md +76 -0
  228. package/agents/harness-optimizer.md +35 -0
  229. package/agents/java-build-resolver.md +153 -0
  230. package/agents/java-reviewer.md +92 -0
  231. package/agents/kotlin-build-resolver.md +118 -0
  232. package/agents/kotlin-reviewer.md +159 -0
  233. package/agents/loop-operator.md +36 -0
  234. package/agents/planner.md +212 -0
  235. package/agents/python-reviewer.md +98 -0
  236. package/agents/pytorch-build-resolver.md +120 -0
  237. package/agents/refactor-cleaner.md +85 -0
  238. package/agents/rust-build-resolver.md +148 -0
  239. package/agents/rust-reviewer.md +94 -0
  240. package/agents/security-reviewer.md +108 -0
  241. package/agents/tdd-guide.md +91 -0
  242. package/agents/typescript-reviewer.md +112 -0
  243. package/commands/aside.md +164 -0
  244. package/commands/brainstorm.md +16 -0
  245. package/commands/build-fix.md +70 -0
  246. package/commands/build.md +91 -0
  247. package/commands/checkpoint.md +74 -0
  248. package/commands/claw.md +51 -0
  249. package/commands/code-review.md +24 -0
  250. package/commands/context-budget.md +29 -0
  251. package/commands/cpp-build.md +174 -0
  252. package/commands/cpp-review.md +132 -0
  253. package/commands/cpp-test.md +252 -0
  254. package/commands/deploy.md +75 -0
  255. package/commands/devfleet.md +92 -0
  256. package/commands/docs.md +31 -0
  257. package/commands/e2e.md +373 -0
  258. package/commands/eval.md +120 -0
  259. package/commands/evolve.md +178 -0
  260. package/commands/execute.md +51 -0
  261. package/commands/finish.md +22 -0
  262. package/commands/go-build.md +184 -0
  263. package/commands/go-review.md +148 -0
  264. package/commands/go-test.md +269 -0
  265. package/commands/gradle-build.md +70 -0
  266. package/commands/harness-audit.md +71 -0
  267. package/commands/instinct-export.md +66 -0
  268. package/commands/instinct-import.md +114 -0
  269. package/commands/instinct-status.md +59 -0
  270. package/commands/investigate.md +63 -0
  271. package/commands/kotlin-build.md +175 -0
  272. package/commands/kotlin-review.md +140 -0
  273. package/commands/kotlin-test.md +313 -0
  274. package/commands/learn-eval.md +116 -0
  275. package/commands/learn.md +70 -0
  276. package/commands/loop-start.md +32 -0
  277. package/commands/loop-status.md +24 -0
  278. package/commands/model-route.md +26 -0
  279. package/commands/multi-backend.md +166 -0
  280. package/commands/multi-execute.md +324 -0
  281. package/commands/multi-frontend.md +165 -0
  282. package/commands/multi-plan.md +277 -0
  283. package/commands/multi-workflow.md +200 -0
  284. package/commands/orchestrate.md +240 -0
  285. package/commands/plan.md +130 -0
  286. package/commands/pm2.md +272 -0
  287. package/commands/projects.md +39 -0
  288. package/commands/promote.md +41 -0
  289. package/commands/prompt-optimize.md +38 -0
  290. package/commands/prune.md +31 -0
  291. package/commands/python-review.md +297 -0
  292. package/commands/quality-gate.md +29 -0
  293. package/commands/refactor-clean.md +89 -0
  294. package/commands/resume-session.md +155 -0
  295. package/commands/review.md +64 -0
  296. package/commands/rules-distill.md +11 -0
  297. package/commands/rust-build.md +188 -0
  298. package/commands/rust-review.md +142 -0
  299. package/commands/rust-test.md +309 -0
  300. package/commands/save-session.md +275 -0
  301. package/commands/sessions.md +333 -0
  302. package/commands/setup-pm.md +80 -0
  303. package/commands/ship.md +77 -0
  304. package/commands/skill-create.md +174 -0
  305. package/commands/skill-health.md +54 -0
  306. package/commands/tdd.md +20 -0
  307. package/commands/test-coverage.md +77 -0
  308. package/commands/test.md +64 -0
  309. package/commands/update-codemaps.md +72 -0
  310. package/commands/update-docs.md +84 -0
  311. package/commands/verify.md +55 -0
  312. package/contexts/dev.md +20 -0
  313. package/contexts/research.md +26 -0
  314. package/contexts/review.md +22 -0
  315. package/examples/CLAUDE.md +100 -0
  316. package/examples/statusline.json +19 -0
  317. package/examples/user-CLAUDE.md +109 -0
  318. package/hooks/README.md +219 -0
  319. package/hooks/hooks.json +320 -0
  320. package/hooks/run-hook.cmd +31 -0
  321. package/hooks/session-start +6 -0
  322. package/install.ps1 +38 -0
  323. package/install.sh +17 -0
  324. package/manifests/install-components.json +415 -0
  325. package/manifests/install-modules.json +500 -0
  326. package/manifests/install-profiles.json +80 -0
  327. package/mcp-configs/mcp-servers.json +153 -0
  328. package/package.json +131 -0
  329. package/plugins/README.md +85 -0
  330. package/rules/README.md +106 -0
  331. package/rules/common/agents.md +50 -0
  332. package/rules/common/coding-style.md +48 -0
  333. package/rules/common/development-workflow.md +38 -0
  334. package/rules/common/git-workflow.md +24 -0
  335. package/rules/common/hooks.md +30 -0
  336. package/rules/common/patterns.md +31 -0
  337. package/rules/common/performance.md +55 -0
  338. package/rules/common/security.md +29 -0
  339. package/rules/common/testing.md +29 -0
  340. package/rules/cpp/coding-style.md +44 -0
  341. package/rules/cpp/hooks.md +39 -0
  342. package/rules/cpp/patterns.md +51 -0
  343. package/rules/cpp/security.md +51 -0
  344. package/rules/cpp/testing.md +44 -0
  345. package/rules/csharp/coding-style.md +72 -0
  346. package/rules/csharp/hooks.md +25 -0
  347. package/rules/csharp/patterns.md +50 -0
  348. package/rules/csharp/security.md +58 -0
  349. package/rules/csharp/testing.md +46 -0
  350. package/rules/golang/coding-style.md +32 -0
  351. package/rules/golang/hooks.md +17 -0
  352. package/rules/golang/patterns.md +45 -0
  353. package/rules/golang/security.md +34 -0
  354. package/rules/golang/testing.md +31 -0
  355. package/rules/java/coding-style.md +114 -0
  356. package/rules/java/hooks.md +18 -0
  357. package/rules/java/patterns.md +146 -0
  358. package/rules/java/security.md +100 -0
  359. package/rules/java/testing.md +131 -0
  360. package/rules/kotlin/coding-style.md +86 -0
  361. package/rules/kotlin/hooks.md +17 -0
  362. package/rules/kotlin/patterns.md +146 -0
  363. package/rules/kotlin/security.md +82 -0
  364. package/rules/kotlin/testing.md +128 -0
  365. package/rules/perl/coding-style.md +46 -0
  366. package/rules/perl/hooks.md +22 -0
  367. package/rules/perl/patterns.md +76 -0
  368. package/rules/perl/security.md +69 -0
  369. package/rules/perl/testing.md +54 -0
  370. package/rules/php/coding-style.md +40 -0
  371. package/rules/php/hooks.md +24 -0
  372. package/rules/php/patterns.md +33 -0
  373. package/rules/php/security.md +37 -0
  374. package/rules/php/testing.md +39 -0
  375. package/rules/python/coding-style.md +42 -0
  376. package/rules/python/hooks.md +19 -0
  377. package/rules/python/patterns.md +39 -0
  378. package/rules/python/security.md +30 -0
  379. package/rules/python/testing.md +38 -0
  380. package/rules/rust/coding-style.md +151 -0
  381. package/rules/rust/hooks.md +16 -0
  382. package/rules/rust/patterns.md +168 -0
  383. package/rules/rust/security.md +141 -0
  384. package/rules/rust/testing.md +154 -0
  385. package/rules/swift/coding-style.md +47 -0
  386. package/rules/swift/hooks.md +20 -0
  387. package/rules/swift/patterns.md +66 -0
  388. package/rules/swift/security.md +33 -0
  389. package/rules/swift/testing.md +45 -0
  390. package/rules/typescript/coding-style.md +199 -0
  391. package/rules/typescript/hooks.md +22 -0
  392. package/rules/typescript/patterns.md +52 -0
  393. package/rules/typescript/security.md +28 -0
  394. package/rules/typescript/testing.md +18 -0
  395. package/schemas/ecc-install-config.schema.json +58 -0
  396. package/schemas/hooks.schema.json +197 -0
  397. package/schemas/install-components.schema.json +58 -0
  398. package/schemas/install-modules.schema.json +105 -0
  399. package/schemas/install-profiles.schema.json +45 -0
  400. package/schemas/install-state.schema.json +210 -0
  401. package/schemas/package-manager.schema.json +23 -0
  402. package/schemas/plugin.schema.json +58 -0
  403. package/schemas/provenance.schema.json +31 -0
  404. package/schemas/state-store.schema.json +316 -0
  405. package/scripts/ci/catalog.js +245 -0
  406. package/scripts/ci/validate-agents.js +81 -0
  407. package/scripts/ci/validate-commands.js +136 -0
  408. package/scripts/ci/validate-hooks.js +239 -0
  409. package/scripts/ci/validate-install-manifests.js +214 -0
  410. package/scripts/ci/validate-no-personal-paths.js +63 -0
  411. package/scripts/ci/validate-rules.js +81 -0
  412. package/scripts/ci/validate-skills.js +56 -0
  413. package/scripts/claw.js +473 -0
  414. package/scripts/codex/merge-mcp-config.js +304 -0
  415. package/scripts/cursor-aw-home/hooks.json +115 -0
  416. package/scripts/cursor-aw-hooks/adapter.js +120 -0
  417. package/scripts/cursor-aw-hooks/after-file-edit.js +11 -0
  418. package/scripts/cursor-aw-hooks/after-mcp-execution.js +11 -0
  419. package/scripts/cursor-aw-hooks/after-shell-execution.js +11 -0
  420. package/scripts/cursor-aw-hooks/aw-phase-adapter.js +43 -0
  421. package/scripts/cursor-aw-hooks/before-mcp-execution.js +11 -0
  422. package/scripts/cursor-aw-hooks/before-shell-execution.js +11 -0
  423. package/scripts/cursor-aw-hooks/before-submit-prompt.js +41 -0
  424. package/scripts/cursor-aw-hooks/pre-compact.js +11 -0
  425. package/scripts/cursor-aw-hooks/session-end.js +11 -0
  426. package/scripts/cursor-aw-hooks/session-start.js +11 -0
  427. package/scripts/cursor-aw-hooks/stop.js +11 -0
  428. package/scripts/doctor.js +110 -0
  429. package/scripts/ecc.js +208 -0
  430. package/scripts/generate-aw-hooks.js +110 -0
  431. package/scripts/harness-audit.js +512 -0
  432. package/scripts/hooks/auto-tmux-dev.js +88 -0
  433. package/scripts/hooks/check-console-log.js +71 -0
  434. package/scripts/hooks/check-hook-enabled.js +12 -0
  435. package/scripts/hooks/config-protection.js +125 -0
  436. package/scripts/hooks/cost-tracker.js +78 -0
  437. package/scripts/hooks/doc-file-warning.js +63 -0
  438. package/scripts/hooks/evaluate-session.js +100 -0
  439. package/scripts/hooks/governance-capture.js +280 -0
  440. package/scripts/hooks/insaits-security-monitor.py +269 -0
  441. package/scripts/hooks/insaits-security-wrapper.js +88 -0
  442. package/scripts/hooks/mcp-health-check.js +588 -0
  443. package/scripts/hooks/post-bash-build-complete.js +27 -0
  444. package/scripts/hooks/post-bash-pr-created.js +37 -0
  445. package/scripts/hooks/post-edit-console-warn.js +54 -0
  446. package/scripts/hooks/post-edit-format.js +109 -0
  447. package/scripts/hooks/post-edit-typecheck.js +96 -0
  448. package/scripts/hooks/post-mcp-log.js +27 -0
  449. package/scripts/hooks/pre-bash-dev-server-block.js +187 -0
  450. package/scripts/hooks/pre-bash-git-push-reminder.js +28 -0
  451. package/scripts/hooks/pre-bash-tmux-reminder.js +33 -0
  452. package/scripts/hooks/pre-compact.js +48 -0
  453. package/scripts/hooks/pre-mcp-log.js +26 -0
  454. package/scripts/hooks/pre-write-doc-warn.js +9 -0
  455. package/scripts/hooks/quality-gate.js +168 -0
  456. package/scripts/hooks/run-with-flags-shell.sh +32 -0
  457. package/scripts/hooks/run-with-flags.js +120 -0
  458. package/scripts/hooks/session-end-marker.js +29 -0
  459. package/scripts/hooks/session-end.js +301 -0
  460. package/scripts/hooks/session-start-rules-context.sh +5 -0
  461. package/scripts/hooks/session-start.js +98 -0
  462. package/scripts/hooks/shared/aw-phase-definitions.js +190 -0
  463. package/scripts/hooks/shared/aw-phase-runner.js +61 -0
  464. package/scripts/hooks/shared/session-start.sh +20 -0
  465. package/scripts/hooks/shared/user-prompt-submit.sh +155 -0
  466. package/scripts/hooks/suggest-compact.js +80 -0
  467. package/scripts/install-apply.js +140 -0
  468. package/scripts/install-plan.js +254 -0
  469. package/scripts/lib/agent-compress.js +244 -0
  470. package/scripts/lib/aw-harness-registry.js +122 -0
  471. package/scripts/lib/aw-hook-contract.js +86 -0
  472. package/scripts/lib/claude-aw-hook-files.js +28 -0
  473. package/scripts/lib/claude-hook-config.js +76 -0
  474. package/scripts/lib/codex-aw-hook-files.js +38 -0
  475. package/scripts/lib/codex-hook-config.js +88 -0
  476. package/scripts/lib/cursor-aw-hook-files.js +62 -0
  477. package/scripts/lib/cursor-hook-config.js +148 -0
  478. package/scripts/lib/hook-flags.js +74 -0
  479. package/scripts/lib/inspection.js +212 -0
  480. package/scripts/lib/install/apply.js +23 -0
  481. package/scripts/lib/install/config.js +82 -0
  482. package/scripts/lib/install/request.js +120 -0
  483. package/scripts/lib/install/runtime.js +54 -0
  484. package/scripts/lib/install-executor.js +778 -0
  485. package/scripts/lib/install-lifecycle.js +1311 -0
  486. package/scripts/lib/install-manifests.js +448 -0
  487. package/scripts/lib/install-state.js +313 -0
  488. package/scripts/lib/install-targets/antigravity-project.js +69 -0
  489. package/scripts/lib/install-targets/claude-home.js +54 -0
  490. package/scripts/lib/install-targets/codex-home.js +62 -0
  491. package/scripts/lib/install-targets/cursor-project.js +80 -0
  492. package/scripts/lib/install-targets/helpers.js +307 -0
  493. package/scripts/lib/install-targets/opencode-home.js +10 -0
  494. package/scripts/lib/install-targets/registry.js +66 -0
  495. package/scripts/lib/orchestration-session.js +299 -0
  496. package/scripts/lib/package-manager.d.ts +119 -0
  497. package/scripts/lib/package-manager.js +431 -0
  498. package/scripts/lib/project-detect.js +428 -0
  499. package/scripts/lib/resolve-ecc-root.js +89 -0
  500. package/scripts/lib/resolve-formatter.js +185 -0
  501. package/scripts/lib/session-adapters/canonical-session.js +531 -0
  502. package/scripts/lib/session-adapters/claude-history.js +160 -0
  503. package/scripts/lib/session-adapters/dmux-tmux.js +90 -0
  504. package/scripts/lib/session-adapters/registry.js +127 -0
  505. package/scripts/lib/session-aliases.d.ts +136 -0
  506. package/scripts/lib/session-aliases.js +481 -0
  507. package/scripts/lib/session-manager.d.ts +131 -0
  508. package/scripts/lib/session-manager.js +464 -0
  509. package/scripts/lib/shell-split.js +86 -0
  510. package/scripts/lib/skill-evolution/dashboard.js +401 -0
  511. package/scripts/lib/skill-evolution/health.js +263 -0
  512. package/scripts/lib/skill-evolution/index.js +20 -0
  513. package/scripts/lib/skill-evolution/provenance.js +187 -0
  514. package/scripts/lib/skill-evolution/tracker.js +146 -0
  515. package/scripts/lib/skill-evolution/versioning.js +237 -0
  516. package/scripts/lib/skill-improvement/amendify.js +89 -0
  517. package/scripts/lib/skill-improvement/evaluate.js +59 -0
  518. package/scripts/lib/skill-improvement/health.js +118 -0
  519. package/scripts/lib/skill-improvement/observations.js +108 -0
  520. package/scripts/lib/state-store/index.js +191 -0
  521. package/scripts/lib/state-store/migrations.js +178 -0
  522. package/scripts/lib/state-store/queries.js +697 -0
  523. package/scripts/lib/state-store/schema.js +92 -0
  524. package/scripts/lib/tmux-worktree-orchestrator.js +475 -0
  525. package/scripts/lib/utils.d.ts +183 -0
  526. package/scripts/lib/utils.js +564 -0
  527. package/scripts/list-installed.js +90 -0
  528. package/scripts/orchestrate-codex-worker.sh +107 -0
  529. package/scripts/orchestrate-worktrees.js +40 -0
  530. package/scripts/orchestration-status.js +82 -0
  531. package/scripts/repair.js +97 -0
  532. package/scripts/session-inspect.js +150 -0
  533. package/scripts/sessions-cli.js +177 -0
  534. package/scripts/setup-package-manager.js +204 -0
  535. package/scripts/skill-create-output.js +244 -0
  536. package/scripts/status.js +176 -0
  537. package/scripts/uninstall.js +96 -0
  538. package/skills/agent-eval/SKILL.md +145 -0
  539. package/skills/agent-harness-construction/SKILL.md +73 -0
  540. package/skills/agentic-engineering/SKILL.md +63 -0
  541. package/skills/ai-first-engineering/SKILL.md +51 -0
  542. package/skills/ai-regression-testing/SKILL.md +385 -0
  543. package/skills/android-clean-architecture/SKILL.md +339 -0
  544. package/skills/api-and-interface-design/SKILL.md +75 -0
  545. package/skills/api-design/SKILL.md +523 -0
  546. package/skills/architecture-decision-records/SKILL.md +179 -0
  547. package/skills/article-writing/SKILL.md +85 -0
  548. package/skills/autonomous-loops/SKILL.md +610 -0
  549. package/skills/aw-brainstorm/SKILL.md +115 -0
  550. package/skills/aw-build/SKILL.md +189 -0
  551. package/skills/aw-build/evals/build-stage-cases.json +28 -0
  552. package/skills/aw-debug/SKILL.md +49 -0
  553. package/skills/aw-deploy/SKILL.md +101 -0
  554. package/skills/aw-deploy/evals/deploy-stage-cases.json +32 -0
  555. package/skills/aw-execute/SKILL.md +47 -0
  556. package/skills/aw-execute/references/mode-code.md +47 -0
  557. package/skills/aw-execute/references/mode-docs.md +28 -0
  558. package/skills/aw-execute/references/mode-infra.md +44 -0
  559. package/skills/aw-execute/references/mode-migration.md +58 -0
  560. package/skills/aw-execute/references/worker-implementer.md +26 -0
  561. package/skills/aw-execute/references/worker-parallel-worker.md +23 -0
  562. package/skills/aw-execute/references/worker-quality-reviewer.md +23 -0
  563. package/skills/aw-execute/references/worker-spec-reviewer.md +23 -0
  564. package/skills/aw-execute/scripts/build-worker-bundle.js +229 -0
  565. package/skills/aw-finish/SKILL.md +111 -0
  566. package/skills/aw-investigate/SKILL.md +109 -0
  567. package/skills/aw-plan/SKILL.md +399 -0
  568. package/skills/aw-prepare/SKILL.md +118 -0
  569. package/skills/aw-review/SKILL.md +123 -0
  570. package/skills/aw-rules/SKILL.md +129 -0
  571. package/skills/aw-rules/references/known-hallucinations.md +43 -0
  572. package/skills/aw-rules/references/verification-sources.md +50 -0
  573. package/skills/aw-ship/SKILL.md +115 -0
  574. package/skills/aw-spec/SKILL.md +128 -0
  575. package/skills/aw-tasks/SKILL.md +155 -0
  576. package/skills/aw-test/SKILL.md +118 -0
  577. package/skills/aw-verify/SKILL.md +51 -0
  578. package/skills/aw-yolo/SKILL.md +111 -0
  579. package/skills/backend-patterns/SKILL.md +598 -0
  580. package/skills/benchmark/SKILL.md +87 -0
  581. package/skills/blueprint/SKILL.md +105 -0
  582. package/skills/browser-qa/SKILL.md +81 -0
  583. package/skills/browser-testing-with-devtools/SKILL.md +81 -0
  584. package/skills/bun-runtime/SKILL.md +84 -0
  585. package/skills/canary-watch/SKILL.md +93 -0
  586. package/skills/carrier-relationship-management/SKILL.md +212 -0
  587. package/skills/ci-cd-and-automation/SKILL.md +71 -0
  588. package/skills/claude-api/SKILL.md +337 -0
  589. package/skills/claude-devfleet/SKILL.md +103 -0
  590. package/skills/click-path-audit/SKILL.md +244 -0
  591. package/skills/clickhouse-io/SKILL.md +439 -0
  592. package/skills/code-simplification/SKILL.md +74 -0
  593. package/skills/codebase-onboarding/SKILL.md +233 -0
  594. package/skills/coding-standards/SKILL.md +530 -0
  595. package/skills/compose-multiplatform-patterns/SKILL.md +299 -0
  596. package/skills/configure-ecc/SKILL.md +367 -0
  597. package/skills/content-engine/SKILL.md +88 -0
  598. package/skills/content-hash-cache-pattern/SKILL.md +161 -0
  599. package/skills/context-budget/SKILL.md +135 -0
  600. package/skills/context-engineering/SKILL.md +74 -0
  601. package/skills/continuous-agent-loop/SKILL.md +45 -0
  602. package/skills/continuous-learning/SKILL.md +119 -0
  603. package/skills/continuous-learning/config.json +18 -0
  604. package/skills/continuous-learning/evaluate-session.sh +69 -0
  605. package/skills/continuous-learning-v2/SKILL.md +365 -0
  606. package/skills/continuous-learning-v2/agents/observer-loop.sh +191 -0
  607. package/skills/continuous-learning-v2/agents/observer.md +198 -0
  608. package/skills/continuous-learning-v2/agents/session-guardian.sh +150 -0
  609. package/skills/continuous-learning-v2/agents/start-observer.sh +240 -0
  610. package/skills/continuous-learning-v2/config.json +8 -0
  611. package/skills/continuous-learning-v2/hooks/observe.sh +412 -0
  612. package/skills/continuous-learning-v2/scripts/detect-project.sh +228 -0
  613. package/skills/continuous-learning-v2/scripts/instinct-cli.py +1426 -0
  614. package/skills/continuous-learning-v2/scripts/test_parse_instinct.py +984 -0
  615. package/skills/cost-aware-llm-pipeline/SKILL.md +183 -0
  616. package/skills/cpp-coding-standards/SKILL.md +723 -0
  617. package/skills/cpp-testing/SKILL.md +324 -0
  618. package/skills/crosspost/SKILL.md +190 -0
  619. package/skills/customs-trade-compliance/SKILL.md +263 -0
  620. package/skills/data-scraper-agent/SKILL.md +764 -0
  621. package/skills/database-migrations/SKILL.md +429 -0
  622. package/skills/deep-research/SKILL.md +155 -0
  623. package/skills/deployment-patterns/SKILL.md +427 -0
  624. package/skills/deprecation-and-migration/SKILL.md +75 -0
  625. package/skills/design-system/SKILL.md +76 -0
  626. package/skills/django-patterns/SKILL.md +734 -0
  627. package/skills/django-security/SKILL.md +593 -0
  628. package/skills/django-tdd/SKILL.md +729 -0
  629. package/skills/django-verification/SKILL.md +469 -0
  630. package/skills/dmux-workflows/SKILL.md +191 -0
  631. package/skills/docker-patterns/SKILL.md +364 -0
  632. package/skills/documentation-and-adrs/SKILL.md +75 -0
  633. package/skills/documentation-lookup/SKILL.md +90 -0
  634. package/skills/e2e-testing/SKILL.md +326 -0
  635. package/skills/energy-procurement/SKILL.md +228 -0
  636. package/skills/enterprise-agent-ops/SKILL.md +50 -0
  637. package/skills/eval-harness/SKILL.md +270 -0
  638. package/skills/exa-search/SKILL.md +103 -0
  639. package/skills/fal-ai-media/SKILL.md +284 -0
  640. package/skills/flutter-dart-code-review/SKILL.md +435 -0
  641. package/skills/foundation-models-on-device/SKILL.md +243 -0
  642. package/skills/frontend-patterns/SKILL.md +642 -0
  643. package/skills/frontend-slides/SKILL.md +184 -0
  644. package/skills/frontend-slides/STYLE_PRESETS.md +330 -0
  645. package/skills/frontend-ui-engineering/SKILL.md +68 -0
  646. package/skills/git-workflow-and-versioning/SKILL.md +75 -0
  647. package/skills/golang-patterns/SKILL.md +674 -0
  648. package/skills/golang-testing/SKILL.md +720 -0
  649. package/skills/idea-refine/SKILL.md +84 -0
  650. package/skills/incremental-implementation/SKILL.md +86 -0
  651. package/skills/inventory-demand-planning/SKILL.md +247 -0
  652. package/skills/investor-materials/SKILL.md +96 -0
  653. package/skills/investor-outreach/SKILL.md +76 -0
  654. package/skills/iterative-retrieval/SKILL.md +211 -0
  655. package/skills/java-coding-standards/SKILL.md +147 -0
  656. package/skills/jpa-patterns/SKILL.md +151 -0
  657. package/skills/kotlin-coroutines-flows/SKILL.md +284 -0
  658. package/skills/kotlin-exposed-patterns/SKILL.md +719 -0
  659. package/skills/kotlin-ktor-patterns/SKILL.md +689 -0
  660. package/skills/kotlin-patterns/SKILL.md +711 -0
  661. package/skills/kotlin-testing/SKILL.md +824 -0
  662. package/skills/laravel-patterns/SKILL.md +415 -0
  663. package/skills/laravel-security/SKILL.md +285 -0
  664. package/skills/laravel-tdd/SKILL.md +283 -0
  665. package/skills/laravel-verification/SKILL.md +179 -0
  666. package/skills/liquid-glass-design/SKILL.md +279 -0
  667. package/skills/logistics-exception-management/SKILL.md +222 -0
  668. package/skills/market-research/SKILL.md +75 -0
  669. package/skills/mcp-server-patterns/SKILL.md +67 -0
  670. package/skills/nanoclaw-repl/SKILL.md +33 -0
  671. package/skills/nextjs-turbopack/SKILL.md +44 -0
  672. package/skills/nutrient-document-processing/SKILL.md +167 -0
  673. package/skills/nuxt4-patterns/SKILL.md +100 -0
  674. package/skills/performance-optimization/SKILL.md +77 -0
  675. package/skills/perl-patterns/SKILL.md +504 -0
  676. package/skills/perl-security/SKILL.md +503 -0
  677. package/skills/perl-testing/SKILL.md +475 -0
  678. package/skills/plankton-code-quality/SKILL.md +236 -0
  679. package/skills/postgres-patterns/SKILL.md +147 -0
  680. package/skills/product-lens/SKILL.md +79 -0
  681. package/skills/production-scheduling/SKILL.md +238 -0
  682. package/skills/project-guidelines-example/SKILL.md +349 -0
  683. package/skills/prompt-optimizer/SKILL.md +397 -0
  684. package/skills/python-patterns/SKILL.md +750 -0
  685. package/skills/python-testing/SKILL.md +816 -0
  686. package/skills/pytorch-patterns/SKILL.md +396 -0
  687. package/skills/quality-nonconformance/SKILL.md +260 -0
  688. package/skills/ralphinho-rfc-pipeline/SKILL.md +67 -0
  689. package/skills/regex-vs-llm-structured-text/SKILL.md +220 -0
  690. package/skills/returns-reverse-logistics/SKILL.md +240 -0
  691. package/skills/rules-distill/SKILL.md +264 -0
  692. package/skills/rules-distill/scripts/scan-rules.sh +58 -0
  693. package/skills/rules-distill/scripts/scan-skills.sh +129 -0
  694. package/skills/rust-patterns/SKILL.md +499 -0
  695. package/skills/rust-testing/SKILL.md +500 -0
  696. package/skills/safety-guard/SKILL.md +69 -0
  697. package/skills/santa-method/SKILL.md +306 -0
  698. package/skills/search-first/SKILL.md +161 -0
  699. package/skills/security-and-hardening/SKILL.md +70 -0
  700. package/skills/security-review/SKILL.md +495 -0
  701. package/skills/security-review/cloud-infrastructure-security.md +361 -0
  702. package/skills/security-scan/SKILL.md +165 -0
  703. package/skills/skill-comply/SKILL.md +58 -0
  704. package/skills/skill-comply/fixtures/compliant_trace.jsonl +5 -0
  705. package/skills/skill-comply/fixtures/noncompliant_trace.jsonl +3 -0
  706. package/skills/skill-comply/fixtures/tdd_spec.yaml +44 -0
  707. package/skills/skill-comply/prompts/classifier.md +24 -0
  708. package/skills/skill-comply/prompts/scenario_generator.md +62 -0
  709. package/skills/skill-comply/prompts/spec_generator.md +42 -0
  710. package/skills/skill-comply/pyproject.toml +15 -0
  711. package/skills/skill-comply/scripts/__init__.py +0 -0
  712. package/skills/skill-comply/scripts/classifier.py +85 -0
  713. package/skills/skill-comply/scripts/grader.py +122 -0
  714. package/skills/skill-comply/scripts/parser.py +107 -0
  715. package/skills/skill-comply/scripts/report.py +170 -0
  716. package/skills/skill-comply/scripts/run.py +127 -0
  717. package/skills/skill-comply/scripts/runner.py +161 -0
  718. package/skills/skill-comply/scripts/scenario_generator.py +70 -0
  719. package/skills/skill-comply/scripts/spec_generator.py +72 -0
  720. package/skills/skill-comply/scripts/utils.py +13 -0
  721. package/skills/skill-comply/tests/test_grader.py +137 -0
  722. package/skills/skill-comply/tests/test_parser.py +90 -0
  723. package/skills/skill-quality-review/SKILL.md +102 -0
  724. package/skills/skill-quality-review/references/review-rubric.md +112 -0
  725. package/skills/skill-stocktake/SKILL.md +197 -0
  726. package/skills/skill-stocktake/scripts/quick-diff.sh +87 -0
  727. package/skills/skill-stocktake/scripts/save-results.sh +56 -0
  728. package/skills/skill-stocktake/scripts/scan.sh +170 -0
  729. package/skills/springboot-patterns/SKILL.md +314 -0
  730. package/skills/springboot-security/SKILL.md +272 -0
  731. package/skills/springboot-tdd/SKILL.md +158 -0
  732. package/skills/springboot-verification/SKILL.md +231 -0
  733. package/skills/strategic-compact/SKILL.md +131 -0
  734. package/skills/strategic-compact/suggest-compact.sh +54 -0
  735. package/skills/swift-actor-persistence/SKILL.md +143 -0
  736. package/skills/swift-concurrency-6-2/SKILL.md +216 -0
  737. package/skills/swift-protocol-di-testing/SKILL.md +190 -0
  738. package/skills/swiftui-patterns/SKILL.md +259 -0
  739. package/skills/tdd-workflow/SKILL.md +145 -0
  740. package/skills/team-builder/SKILL.md +161 -0
  741. package/skills/using-aw-skills/SKILL.md +290 -0
  742. package/skills/using-aw-skills/evals/skill-trigger-cases.tsv +25 -0
  743. package/skills/using-aw-skills/evals/test-skill-triggers.sh +171 -0
  744. package/skills/using-aw-skills/hooks/hooks.json +9 -0
  745. package/skills/using-aw-skills/hooks/session-start.sh +188 -0
  746. package/skills/using-platform-skills/SKILL.md +163 -0
  747. package/skills/using-platform-skills/evals/platform-selection-cases.json +52 -0
  748. package/skills/verification-loop/SKILL.md +126 -0
  749. package/skills/video-editing/SKILL.md +310 -0
  750. package/skills/videodb/SKILL.md +374 -0
  751. package/skills/videodb/reference/api-reference.md +550 -0
  752. package/skills/videodb/reference/capture-reference.md +407 -0
  753. package/skills/videodb/reference/capture.md +101 -0
  754. package/skills/videodb/reference/editor.md +443 -0
  755. package/skills/videodb/reference/generative.md +331 -0
  756. package/skills/videodb/reference/rtstream-reference.md +564 -0
  757. package/skills/videodb/reference/rtstream.md +65 -0
  758. package/skills/videodb/reference/search.md +230 -0
  759. package/skills/videodb/reference/streaming.md +406 -0
  760. package/skills/videodb/reference/use-cases.md +118 -0
  761. package/skills/videodb/scripts/ws_listener.py +282 -0
  762. package/skills/visa-doc-translate/README.md +86 -0
  763. package/skills/visa-doc-translate/SKILL.md +117 -0
  764. package/skills/x-api/SKILL.md +208 -0
@@ -0,0 +1,412 @@
1
+ #!/bin/bash
2
+ # Continuous Learning v2 - Observation Hook
3
+ #
4
+ # Captures tool use events for pattern analysis.
5
+ # Claude Code passes hook data via stdin as JSON.
6
+ #
7
+ # v2.1: Project-scoped observations — detects current project context
8
+ # and writes observations to project-specific directory.
9
+ #
10
+ # Registered via plugin hooks/hooks.json (auto-loaded when plugin is enabled).
11
+ # Can also be registered manually in ~/.claude/settings.json.
12
+
13
+ set -e
14
+
15
+ # Hook phase from CLI argument: "pre" (PreToolUse) or "post" (PostToolUse)
16
+ HOOK_PHASE="${1:-post}"
17
+
18
+ # ─────────────────────────────────────────────
19
+ # Read stdin first (before project detection)
20
+ # ─────────────────────────────────────────────
21
+
22
+ # Read JSON from stdin (Claude Code hook format)
23
+ INPUT_JSON=$(cat)
24
+
25
+ # Exit if no input
26
+ if [ -z "$INPUT_JSON" ]; then
27
+ exit 0
28
+ fi
29
+
30
+ resolve_python_cmd() {
31
+ if [ -n "${CLV2_PYTHON_CMD:-}" ] && command -v "$CLV2_PYTHON_CMD" >/dev/null 2>&1; then
32
+ printf '%s\n' "$CLV2_PYTHON_CMD"
33
+ return 0
34
+ fi
35
+
36
+ if command -v python3 >/dev/null 2>&1; then
37
+ printf '%s\n' python3
38
+ return 0
39
+ fi
40
+
41
+ if command -v python >/dev/null 2>&1; then
42
+ printf '%s\n' python
43
+ return 0
44
+ fi
45
+
46
+ return 1
47
+ }
48
+
49
+ PYTHON_CMD="$(resolve_python_cmd 2>/dev/null || true)"
50
+ if [ -z "$PYTHON_CMD" ]; then
51
+ echo "[observe] No python interpreter found, skipping observation" >&2
52
+ exit 0
53
+ fi
54
+
55
+ # ─────────────────────────────────────────────
56
+ # Extract cwd from stdin for project detection
57
+ # ─────────────────────────────────────────────
58
+
59
+ # Extract cwd from the hook JSON to use for project detection.
60
+ # This avoids spawning a separate git subprocess when cwd is available.
61
+ STDIN_CWD=$(echo "$INPUT_JSON" | "$PYTHON_CMD" -c '
62
+ import json, sys
63
+ try:
64
+ data = json.load(sys.stdin)
65
+ cwd = data.get("cwd", "")
66
+ print(cwd)
67
+ except(KeyError, TypeError, ValueError):
68
+ print("")
69
+ ' 2>/dev/null || echo "")
70
+
71
+ # If cwd was provided in stdin, use it for project detection
72
+ if [ -n "$STDIN_CWD" ] && [ -d "$STDIN_CWD" ]; then
73
+ export CLAUDE_PROJECT_DIR="$STDIN_CWD"
74
+ fi
75
+
76
+ # ─────────────────────────────────────────────
77
+ # Lightweight config and automated session guards
78
+ # ─────────────────────────────────────────────
79
+ #
80
+ # IMPORTANT: keep these guards above detect-project.sh.
81
+ # Sourcing detect-project.sh creates project-scoped directories and updates
82
+ # projects.json, so automated sessions must return before that point.
83
+
84
+ CONFIG_DIR="${HOME}/.claude/homunculus"
85
+
86
+ # Skip if disabled (check both default and CLV2_CONFIG-derived locations)
87
+ if [ -f "$CONFIG_DIR/disabled" ]; then
88
+ exit 0
89
+ fi
90
+ if [ -n "${CLV2_CONFIG:-}" ] && [ -f "$(dirname "$CLV2_CONFIG")/disabled" ]; then
91
+ exit 0
92
+ fi
93
+
94
+ # Prevent observe.sh from firing on non-human sessions to avoid:
95
+ # - ECC observing its own Haiku observer sessions (self-loop)
96
+ # - ECC observing other tools' automated sessions
97
+ # - automated sessions creating project-scoped homunculus metadata
98
+
99
+ # Layer 1: entrypoint. Only interactive terminal sessions should continue.
100
+ # sdk-ts: Agent SDK sessions can be human-interactive (e.g. via Happy).
101
+ # Non-interactive SDK automation is still filtered by Layers 2-5 below
102
+ # (ECC_HOOK_PROFILE=minimal, ECC_SKIP_OBSERVE=1, agent_id, path exclusions).
103
+ case "${CLAUDE_CODE_ENTRYPOINT:-cli}" in
104
+ cli|sdk-ts) ;;
105
+ *) exit 0 ;;
106
+ esac
107
+
108
+ # Layer 2: minimal hook profile suppresses non-essential hooks.
109
+ [ "${ECC_HOOK_PROFILE:-standard}" = "minimal" ] && exit 0
110
+
111
+ # Layer 3: cooperative skip env var for automated sessions.
112
+ [ "${ECC_SKIP_OBSERVE:-0}" = "1" ] && exit 0
113
+
114
+ # Layer 4: subagent sessions are automated by definition.
115
+ _ECC_AGENT_ID=$(echo "$INPUT_JSON" | "$PYTHON_CMD" -c "import json,sys; print(json.load(sys.stdin).get('agent_id',''))" 2>/dev/null || true)
116
+ [ -n "$_ECC_AGENT_ID" ] && exit 0
117
+
118
+ # Layer 5: known observer-session path exclusions.
119
+ _ECC_SKIP_PATHS="${ECC_OBSERVE_SKIP_PATHS:-observer-sessions,.claude-mem}"
120
+ if [ -n "$STDIN_CWD" ]; then
121
+ IFS=',' read -ra _ECC_SKIP_ARRAY <<< "$_ECC_SKIP_PATHS"
122
+ for _pattern in "${_ECC_SKIP_ARRAY[@]}"; do
123
+ _pattern="${_pattern#"${_pattern%%[![:space:]]*}"}"
124
+ _pattern="${_pattern%"${_pattern##*[![:space:]]}"}"
125
+ [ -z "$_pattern" ] && continue
126
+ case "$STDIN_CWD" in *"$_pattern"*) exit 0 ;; esac
127
+ done
128
+ fi
129
+
130
+ # ─────────────────────────────────────────────
131
+ # Project detection
132
+ # ─────────────────────────────────────────────
133
+
134
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
135
+ SKILL_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
136
+
137
+ # Source shared project detection helper
138
+ # This sets: PROJECT_ID, PROJECT_NAME, PROJECT_ROOT, PROJECT_DIR
139
+ source "${SKILL_ROOT}/scripts/detect-project.sh"
140
+ PYTHON_CMD="${CLV2_PYTHON_CMD:-$PYTHON_CMD}"
141
+
142
+ # ─────────────────────────────────────────────
143
+ # Configuration
144
+ # ─────────────────────────────────────────────
145
+
146
+ OBSERVATIONS_FILE="${PROJECT_DIR}/observations.jsonl"
147
+ MAX_FILE_SIZE_MB=10
148
+
149
+ # Auto-purge observation files older than 30 days (runs once per session)
150
+ PURGE_MARKER="${PROJECT_DIR}/.last-purge"
151
+ if [ ! -f "$PURGE_MARKER" ] || [ "$(find "$PURGE_MARKER" -mtime +1 2>/dev/null)" ]; then
152
+ find "${PROJECT_DIR}" -name "observations-*.jsonl" -mtime +30 -delete 2>/dev/null || true
153
+ touch "$PURGE_MARKER" 2>/dev/null || true
154
+ fi
155
+
156
+ # Parse using Python via stdin pipe (safe for all JSON payloads)
157
+ # Pass HOOK_PHASE via env var since Claude Code does not include hook type in stdin JSON
158
+ PARSED=$(echo "$INPUT_JSON" | HOOK_PHASE="$HOOK_PHASE" "$PYTHON_CMD" -c '
159
+ import json
160
+ import sys
161
+ import os
162
+
163
+ try:
164
+ data = json.load(sys.stdin)
165
+
166
+ # Determine event type from CLI argument passed via env var.
167
+ # Claude Code does NOT include a "hook_type" field in the stdin JSON,
168
+ # so we rely on the shell argument ("pre" or "post") instead.
169
+ hook_phase = os.environ.get("HOOK_PHASE", "post")
170
+ event = "tool_start" if hook_phase == "pre" else "tool_complete"
171
+
172
+ # Extract fields - Claude Code hook format
173
+ tool_name = data.get("tool_name", data.get("tool", "unknown"))
174
+ tool_input = data.get("tool_input", data.get("input", {}))
175
+ tool_output = data.get("tool_response")
176
+ if tool_output is None:
177
+ tool_output = data.get("tool_output", data.get("output", ""))
178
+ session_id = data.get("session_id", "unknown")
179
+ tool_use_id = data.get("tool_use_id", "")
180
+ cwd = data.get("cwd", "")
181
+
182
+ # Truncate large inputs/outputs
183
+ if isinstance(tool_input, dict):
184
+ tool_input_str = json.dumps(tool_input)[:5000]
185
+ else:
186
+ tool_input_str = str(tool_input)[:5000]
187
+
188
+ if isinstance(tool_output, dict):
189
+ tool_response_str = json.dumps(tool_output)[:5000]
190
+ else:
191
+ tool_response_str = str(tool_output)[:5000]
192
+
193
+ print(json.dumps({
194
+ "parsed": True,
195
+ "event": event,
196
+ "tool": tool_name,
197
+ "input": tool_input_str if event == "tool_start" else None,
198
+ "output": tool_response_str if event == "tool_complete" else None,
199
+ "session": session_id,
200
+ "tool_use_id": tool_use_id,
201
+ "cwd": cwd
202
+ }))
203
+ except Exception as e:
204
+ print(json.dumps({"parsed": False, "error": str(e)}))
205
+ ')
206
+
207
+ # Check if parsing succeeded
208
+ PARSED_OK=$(echo "$PARSED" | "$PYTHON_CMD" -c "import json,sys; print(json.load(sys.stdin).get('parsed', False))" 2>/dev/null || echo "False")
209
+
210
+ if [ "$PARSED_OK" != "True" ]; then
211
+ # Fallback: log raw input for debugging (scrub secrets before persisting)
212
+ timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
213
+ export TIMESTAMP="$timestamp"
214
+ echo "$INPUT_JSON" | "$PYTHON_CMD" -c '
215
+ import json, sys, os, re
216
+
217
+ _SECRET_RE = re.compile(
218
+ r"(?i)(api[_-]?key|token|secret|password|authorization|credentials?|auth)"
219
+ r"""(["'"'"'\s:=]+)"""
220
+ r"([A-Za-z]+\s+)?"
221
+ r"([A-Za-z0-9_\-/.+=]{8,})"
222
+ )
223
+
224
+ raw = sys.stdin.read()[:2000]
225
+ raw = _SECRET_RE.sub(lambda m: m.group(1) + m.group(2) + (m.group(3) or "") + "[REDACTED]", raw)
226
+ print(json.dumps({"timestamp": os.environ["TIMESTAMP"], "event": "parse_error", "raw": raw}))
227
+ ' >> "$OBSERVATIONS_FILE"
228
+ exit 0
229
+ fi
230
+
231
+ # Archive if file too large (atomic: rename with unique suffix to avoid race)
232
+ if [ -f "$OBSERVATIONS_FILE" ]; then
233
+ file_size_mb=$(du -m "$OBSERVATIONS_FILE" 2>/dev/null | cut -f1)
234
+ if [ "${file_size_mb:-0}" -ge "$MAX_FILE_SIZE_MB" ]; then
235
+ archive_dir="${PROJECT_DIR}/observations.archive"
236
+ mkdir -p "$archive_dir"
237
+ mv "$OBSERVATIONS_FILE" "$archive_dir/observations-$(date +%Y%m%d-%H%M%S)-$$.jsonl" 2>/dev/null || true
238
+ fi
239
+ fi
240
+
241
+ # Build and write observation (now includes project context)
242
+ # Scrub common secret patterns from tool I/O before persisting
243
+ timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
244
+
245
+ export PROJECT_ID_ENV="$PROJECT_ID"
246
+ export PROJECT_NAME_ENV="$PROJECT_NAME"
247
+ export TIMESTAMP="$timestamp"
248
+
249
+ echo "$PARSED" | "$PYTHON_CMD" -c '
250
+ import json, sys, os, re
251
+
252
+ parsed = json.load(sys.stdin)
253
+ observation = {
254
+ "timestamp": os.environ["TIMESTAMP"],
255
+ "event": parsed["event"],
256
+ "tool": parsed["tool"],
257
+ "session": parsed["session"],
258
+ "project_id": os.environ.get("PROJECT_ID_ENV", "global"),
259
+ "project_name": os.environ.get("PROJECT_NAME_ENV", "global")
260
+ }
261
+
262
+ # Scrub secrets: match common key=value, key: value, and key"value patterns
263
+ # Includes optional auth scheme (e.g., "Bearer", "Basic") before token
264
+ _SECRET_RE = re.compile(
265
+ r"(?i)(api[_-]?key|token|secret|password|authorization|credentials?|auth)"
266
+ r"""(["'"'"'\s:=]+)"""
267
+ r"([A-Za-z]+\s+)?"
268
+ r"([A-Za-z0-9_\-/.+=]{8,})"
269
+ )
270
+
271
+ def scrub(val):
272
+ if val is None:
273
+ return None
274
+ return _SECRET_RE.sub(lambda m: m.group(1) + m.group(2) + (m.group(3) or "") + "[REDACTED]", str(val))
275
+
276
+ if parsed["input"]:
277
+ observation["input"] = scrub(parsed["input"])
278
+ if parsed["output"] is not None:
279
+ observation["output"] = scrub(parsed["output"])
280
+
281
+ print(json.dumps(observation))
282
+ ' >> "$OBSERVATIONS_FILE"
283
+
284
+ # Lazy-start observer if enabled but not running (first-time setup)
285
+ # Use flock for atomic check-then-act to prevent race conditions
286
+ # Fallback for macOS (no flock): use lockfile or skip
287
+ LAZY_START_LOCK="${PROJECT_DIR}/.observer-start.lock"
288
+ _CHECK_OBSERVER_RUNNING() {
289
+ local pid_file="$1"
290
+ if [ -f "$pid_file" ]; then
291
+ local pid
292
+ pid=$(cat "$pid_file" 2>/dev/null)
293
+ # Validate PID is a positive integer (>1) to prevent signaling invalid targets
294
+ case "$pid" in
295
+ ''|*[!0-9]*|0|1)
296
+ rm -f "$pid_file" 2>/dev/null || true
297
+ return 1
298
+ ;;
299
+ esac
300
+ if kill -0 "$pid" 2>/dev/null; then
301
+ return 0 # Process is alive
302
+ fi
303
+ # Stale PID file - remove it
304
+ rm -f "$pid_file" 2>/dev/null || true
305
+ fi
306
+ return 1 # No PID file or process dead
307
+ }
308
+
309
+ if [ -f "${CONFIG_DIR}/disabled" ]; then
310
+ OBSERVER_ENABLED=false
311
+ else
312
+ OBSERVER_ENABLED=false
313
+ CONFIG_FILE="${SKILL_ROOT}/config.json"
314
+ # Allow CLV2_CONFIG override
315
+ if [ -n "${CLV2_CONFIG:-}" ]; then
316
+ CONFIG_FILE="$CLV2_CONFIG"
317
+ fi
318
+ # Use effective config path for both existence check and reading
319
+ EFFECTIVE_CONFIG="$CONFIG_FILE"
320
+ if [ -f "$EFFECTIVE_CONFIG" ] && [ -n "$PYTHON_CMD" ]; then
321
+ _enabled=$(CLV2_CONFIG_PATH="$EFFECTIVE_CONFIG" "$PYTHON_CMD" -c "
322
+ import json, os
323
+ with open(os.environ['CLV2_CONFIG_PATH']) as f:
324
+ cfg = json.load(f)
325
+ print(str(cfg.get('observer', {}).get('enabled', False)).lower())
326
+ " 2>/dev/null || echo "false")
327
+ if [ "$_enabled" = "true" ]; then
328
+ OBSERVER_ENABLED=true
329
+ fi
330
+ fi
331
+ fi
332
+
333
+ # Check both project-scoped AND global PID files (with stale PID recovery)
334
+ if [ "$OBSERVER_ENABLED" = "true" ]; then
335
+ # Clean up stale PID files first
336
+ _CHECK_OBSERVER_RUNNING "${PROJECT_DIR}/.observer.pid" || true
337
+ _CHECK_OBSERVER_RUNNING "${CONFIG_DIR}/.observer.pid" || true
338
+
339
+ # Check if observer is now running after cleanup
340
+ if [ ! -f "${PROJECT_DIR}/.observer.pid" ] && [ ! -f "${CONFIG_DIR}/.observer.pid" ]; then
341
+ # Use flock if available (Linux), fallback for macOS
342
+ if command -v flock >/dev/null 2>&1; then
343
+ (
344
+ flock -n 9 || exit 0
345
+ # Double-check PID files after acquiring lock
346
+ _CHECK_OBSERVER_RUNNING "${PROJECT_DIR}/.observer.pid" || true
347
+ _CHECK_OBSERVER_RUNNING "${CONFIG_DIR}/.observer.pid" || true
348
+ if [ ! -f "${PROJECT_DIR}/.observer.pid" ] && [ ! -f "${CONFIG_DIR}/.observer.pid" ]; then
349
+ nohup "${SKILL_ROOT}/agents/start-observer.sh" start >/dev/null 2>&1 &
350
+ fi
351
+ ) 9>"$LAZY_START_LOCK"
352
+ else
353
+ # macOS fallback: use lockfile if available, otherwise skip
354
+ if command -v lockfile >/dev/null 2>&1; then
355
+ # Use subshell to isolate exit and add trap for cleanup
356
+ (
357
+ trap 'rm -f "$LAZY_START_LOCK" 2>/dev/null || true' EXIT
358
+ lockfile -r 1 -l 30 "$LAZY_START_LOCK" 2>/dev/null || exit 0
359
+ _CHECK_OBSERVER_RUNNING "${PROJECT_DIR}/.observer.pid" || true
360
+ _CHECK_OBSERVER_RUNNING "${CONFIG_DIR}/.observer.pid" || true
361
+ if [ ! -f "${PROJECT_DIR}/.observer.pid" ] && [ ! -f "${CONFIG_DIR}/.observer.pid" ]; then
362
+ nohup "${SKILL_ROOT}/agents/start-observer.sh" start >/dev/null 2>&1 &
363
+ fi
364
+ rm -f "$LAZY_START_LOCK" 2>/dev/null || true
365
+ )
366
+ fi
367
+ fi
368
+ fi
369
+ fi
370
+
371
+ # Throttle SIGUSR1: only signal observer every N observations (#521)
372
+ # This prevents rapid signaling when tool calls fire every second,
373
+ # which caused runaway parallel Claude analysis processes.
374
+ SIGNAL_EVERY_N="${ECC_OBSERVER_SIGNAL_EVERY_N:-20}"
375
+ SIGNAL_COUNTER_FILE="${PROJECT_DIR}/.observer-signal-counter"
376
+
377
+ should_signal=0
378
+ if [ -f "$SIGNAL_COUNTER_FILE" ]; then
379
+ counter=$(cat "$SIGNAL_COUNTER_FILE" 2>/dev/null || echo 0)
380
+ counter=$((counter + 1))
381
+ if [ "$counter" -ge "$SIGNAL_EVERY_N" ]; then
382
+ should_signal=1
383
+ counter=0
384
+ fi
385
+ echo "$counter" > "$SIGNAL_COUNTER_FILE"
386
+ else
387
+ echo "1" > "$SIGNAL_COUNTER_FILE"
388
+ fi
389
+
390
+ # Signal observer if running and throttle allows (check both project-scoped and global observer, deduplicate)
391
+ if [ "$should_signal" -eq 1 ]; then
392
+ signaled_pids=" "
393
+ for pid_file in "${PROJECT_DIR}/.observer.pid" "${CONFIG_DIR}/.observer.pid"; do
394
+ if [ -f "$pid_file" ]; then
395
+ observer_pid=$(cat "$pid_file" 2>/dev/null || true)
396
+ # Validate PID is a positive integer (>1)
397
+ case "$observer_pid" in
398
+ ''|*[!0-9]*|0|1) rm -f "$pid_file" 2>/dev/null || true; continue ;;
399
+ esac
400
+ # Deduplicate: skip if already signaled this pass
401
+ case "$signaled_pids" in
402
+ *" $observer_pid "*) continue ;;
403
+ esac
404
+ if kill -0 "$observer_pid" 2>/dev/null; then
405
+ kill -USR1 "$observer_pid" 2>/dev/null || true
406
+ signaled_pids="${signaled_pids}${observer_pid} "
407
+ fi
408
+ fi
409
+ done
410
+ fi
411
+
412
+ exit 0
@@ -0,0 +1,228 @@
1
+ #!/bin/bash
2
+ # Continuous Learning v2 - Project Detection Helper
3
+ #
4
+ # Shared logic for detecting current project context.
5
+ # Sourced by observe.sh and start-observer.sh.
6
+ #
7
+ # Exports:
8
+ # _CLV2_PROJECT_ID - Short hash identifying the project (or "global")
9
+ # _CLV2_PROJECT_NAME - Human-readable project name
10
+ # _CLV2_PROJECT_ROOT - Absolute path to project root
11
+ # _CLV2_PROJECT_DIR - Project-scoped storage directory under homunculus
12
+ #
13
+ # Also sets unprefixed convenience aliases:
14
+ # PROJECT_ID, PROJECT_NAME, PROJECT_ROOT, PROJECT_DIR
15
+ #
16
+ # Detection priority:
17
+ # 1. CLAUDE_PROJECT_DIR env var (if set)
18
+ # 2. git remote URL (hashed for uniqueness across machines)
19
+ # 3. git repo root path (fallback, machine-specific)
20
+ # 4. "global" (no project context detected)
21
+
22
+ _CLV2_HOMUNCULUS_DIR="${HOME}/.claude/homunculus"
23
+ _CLV2_PROJECTS_DIR="${_CLV2_HOMUNCULUS_DIR}/projects"
24
+ _CLV2_REGISTRY_FILE="${_CLV2_HOMUNCULUS_DIR}/projects.json"
25
+
26
+ _clv2_resolve_python_cmd() {
27
+ if [ -n "${CLV2_PYTHON_CMD:-}" ] && command -v "$CLV2_PYTHON_CMD" >/dev/null 2>&1; then
28
+ printf '%s\n' "$CLV2_PYTHON_CMD"
29
+ return 0
30
+ fi
31
+
32
+ if command -v python3 >/dev/null 2>&1; then
33
+ printf '%s\n' python3
34
+ return 0
35
+ fi
36
+
37
+ if command -v python >/dev/null 2>&1; then
38
+ printf '%s\n' python
39
+ return 0
40
+ fi
41
+
42
+ return 1
43
+ }
44
+
45
+ _CLV2_PYTHON_CMD="$(_clv2_resolve_python_cmd 2>/dev/null || true)"
46
+ CLV2_PYTHON_CMD="$_CLV2_PYTHON_CMD"
47
+ export CLV2_PYTHON_CMD
48
+
49
+ CLV2_OBSERVER_PROMPT_PATTERN='Can you confirm|requires permission|Awaiting (user confirmation|confirmation|approval|permission)|confirm I should proceed|once granted access|grant.*access'
50
+ export CLV2_OBSERVER_PROMPT_PATTERN
51
+
52
+ _clv2_detect_project() {
53
+ local project_root=""
54
+ local project_name=""
55
+ local project_id=""
56
+ local source_hint=""
57
+
58
+ # 1. Try CLAUDE_PROJECT_DIR env var
59
+ if [ -n "$CLAUDE_PROJECT_DIR" ] && [ -d "$CLAUDE_PROJECT_DIR" ]; then
60
+ project_root="$CLAUDE_PROJECT_DIR"
61
+ source_hint="env"
62
+ fi
63
+
64
+ # 2. Try git repo root from CWD (only if git is available)
65
+ if [ -z "$project_root" ] && command -v git &>/dev/null; then
66
+ project_root=$(git rev-parse --show-toplevel 2>/dev/null || true)
67
+ if [ -n "$project_root" ]; then
68
+ source_hint="git"
69
+ fi
70
+ fi
71
+
72
+ # 3. No project detected — fall back to global
73
+ if [ -z "$project_root" ]; then
74
+ _CLV2_PROJECT_ID="global"
75
+ _CLV2_PROJECT_NAME="global"
76
+ _CLV2_PROJECT_ROOT=""
77
+ _CLV2_PROJECT_DIR="${_CLV2_HOMUNCULUS_DIR}"
78
+ return 0
79
+ fi
80
+
81
+ # Derive project name from directory basename
82
+ project_name=$(basename "$project_root")
83
+
84
+ # Derive project ID: prefer git remote URL hash (portable across machines),
85
+ # fall back to path hash (machine-specific but still useful)
86
+ local remote_url=""
87
+ if command -v git &>/dev/null; then
88
+ if [ "$source_hint" = "git" ] || [ -e "${project_root}/.git" ]; then
89
+ remote_url=$(git -C "$project_root" remote get-url origin 2>/dev/null || true)
90
+ fi
91
+ fi
92
+
93
+ # Compute hash from the original remote URL (legacy, for backward compatibility)
94
+ local legacy_hash_input="${remote_url:-$project_root}"
95
+
96
+ # Strip embedded credentials from remote URL (e.g., https://ghp_xxxx@github.com/...)
97
+ if [ -n "$remote_url" ]; then
98
+ remote_url=$(printf '%s' "$remote_url" | sed -E 's|://[^@]+@|://|')
99
+ fi
100
+
101
+ local hash_input="${remote_url:-$project_root}"
102
+ # Prefer Python for consistent SHA256 behavior across shells/platforms.
103
+ if [ -n "$_CLV2_PYTHON_CMD" ]; then
104
+ project_id=$(printf '%s' "$hash_input" | "$_CLV2_PYTHON_CMD" -c "import sys,hashlib; print(hashlib.sha256(sys.stdin.buffer.read()).hexdigest()[:12])" 2>/dev/null)
105
+ fi
106
+
107
+ # Fallback if Python is unavailable or hash generation failed.
108
+ if [ -z "$project_id" ]; then
109
+ project_id=$(printf '%s' "$hash_input" | shasum -a 256 2>/dev/null | cut -c1-12 || \
110
+ printf '%s' "$hash_input" | sha256sum 2>/dev/null | cut -c1-12 || \
111
+ echo "fallback")
112
+ fi
113
+
114
+ # Backward compatibility: if credentials were stripped and the hash changed,
115
+ # check if a project dir exists under the legacy hash and reuse it
116
+ if [ "$legacy_hash_input" != "$hash_input" ] && [ -n "$_CLV2_PYTHON_CMD" ]; then
117
+ local legacy_id=""
118
+ legacy_id=$(printf '%s' "$legacy_hash_input" | "$_CLV2_PYTHON_CMD" -c "import sys,hashlib; print(hashlib.sha256(sys.stdin.buffer.read()).hexdigest()[:12])" 2>/dev/null)
119
+ if [ -n "$legacy_id" ] && [ -d "${_CLV2_PROJECTS_DIR}/${legacy_id}" ] && [ ! -d "${_CLV2_PROJECTS_DIR}/${project_id}" ]; then
120
+ # Migrate legacy directory to new hash
121
+ mv "${_CLV2_PROJECTS_DIR}/${legacy_id}" "${_CLV2_PROJECTS_DIR}/${project_id}" 2>/dev/null || project_id="$legacy_id"
122
+ fi
123
+ fi
124
+
125
+ # Export results
126
+ _CLV2_PROJECT_ID="$project_id"
127
+ _CLV2_PROJECT_NAME="$project_name"
128
+ _CLV2_PROJECT_ROOT="$project_root"
129
+ _CLV2_PROJECT_DIR="${_CLV2_PROJECTS_DIR}/${project_id}"
130
+
131
+ # Ensure project directory structure exists
132
+ mkdir -p "${_CLV2_PROJECT_DIR}/instincts/personal"
133
+ mkdir -p "${_CLV2_PROJECT_DIR}/instincts/inherited"
134
+ mkdir -p "${_CLV2_PROJECT_DIR}/observations.archive"
135
+ mkdir -p "${_CLV2_PROJECT_DIR}/evolved/skills"
136
+ mkdir -p "${_CLV2_PROJECT_DIR}/evolved/commands"
137
+ mkdir -p "${_CLV2_PROJECT_DIR}/evolved/agents"
138
+
139
+ # Update project registry (lightweight JSON mapping)
140
+ _clv2_update_project_registry "$project_id" "$project_name" "$project_root" "$remote_url"
141
+ }
142
+
143
+ _clv2_update_project_registry() {
144
+ local pid="$1"
145
+ local pname="$2"
146
+ local proot="$3"
147
+ local premote="$4"
148
+ local pdir="$_CLV2_PROJECT_DIR"
149
+
150
+ mkdir -p "$(dirname "$_CLV2_REGISTRY_FILE")"
151
+
152
+ if [ -z "$_CLV2_PYTHON_CMD" ]; then
153
+ return 0
154
+ fi
155
+
156
+ # Pass values via env vars to avoid shell→python injection.
157
+ # Python reads them with os.environ, which is safe for any string content.
158
+ _CLV2_REG_PID="$pid" \
159
+ _CLV2_REG_PNAME="$pname" \
160
+ _CLV2_REG_PROOT="$proot" \
161
+ _CLV2_REG_PREMOTE="$premote" \
162
+ _CLV2_REG_PDIR="$pdir" \
163
+ _CLV2_REG_FILE="$_CLV2_REGISTRY_FILE" \
164
+ "$_CLV2_PYTHON_CMD" -c '
165
+ import json, os, tempfile
166
+ from datetime import datetime, timezone
167
+
168
+ registry_path = os.environ["_CLV2_REG_FILE"]
169
+ project_dir = os.environ["_CLV2_REG_PDIR"]
170
+ project_file = os.path.join(project_dir, "project.json")
171
+
172
+ os.makedirs(project_dir, exist_ok=True)
173
+
174
+ def atomic_write_json(path, payload):
175
+ fd, tmp_path = tempfile.mkstemp(
176
+ prefix=f".{os.path.basename(path)}.tmp.",
177
+ dir=os.path.dirname(path),
178
+ text=True,
179
+ )
180
+ try:
181
+ with os.fdopen(fd, "w") as f:
182
+ json.dump(payload, f, indent=2)
183
+ f.write("\n")
184
+ os.replace(tmp_path, path)
185
+ finally:
186
+ if os.path.exists(tmp_path):
187
+ os.unlink(tmp_path)
188
+
189
+ try:
190
+ with open(registry_path) as f:
191
+ registry = json.load(f)
192
+ except (FileNotFoundError, json.JSONDecodeError):
193
+ registry = {}
194
+
195
+ now = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
196
+ entry = registry.get(os.environ["_CLV2_REG_PID"], {})
197
+
198
+ metadata = {
199
+ "id": os.environ["_CLV2_REG_PID"],
200
+ "name": os.environ["_CLV2_REG_PNAME"],
201
+ "root": os.environ["_CLV2_REG_PROOT"],
202
+ "remote": os.environ["_CLV2_REG_PREMOTE"],
203
+ "created_at": entry.get("created_at", now),
204
+ "last_seen": now,
205
+ }
206
+
207
+ registry[os.environ["_CLV2_REG_PID"]] = metadata
208
+
209
+ atomic_write_json(project_file, metadata)
210
+ atomic_write_json(registry_path, registry)
211
+ ' 2>/dev/null || true
212
+ }
213
+
214
+ # Auto-detect on source
215
+ _clv2_detect_project
216
+
217
+ # Convenience aliases for callers (short names pointing to prefixed vars)
218
+ PROJECT_ID="$_CLV2_PROJECT_ID"
219
+ PROJECT_NAME="$_CLV2_PROJECT_NAME"
220
+ PROJECT_ROOT="$_CLV2_PROJECT_ROOT"
221
+ PROJECT_DIR="$_CLV2_PROJECT_DIR"
222
+
223
+ if [ -n "$PROJECT_ROOT" ]; then
224
+ CLV2_OBSERVER_SENTINEL_FILE="${PROJECT_ROOT}/.observer.lock"
225
+ else
226
+ CLV2_OBSERVER_SENTINEL_FILE="${PROJECT_DIR}/.observer.lock"
227
+ fi
228
+ export CLV2_OBSERVER_SENTINEL_FILE