@heyai-rules/pilo-masterkit 1.2.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (594) hide show
  1. package/.agent/agents/architect.md +211 -211
  2. package/.agent/agents/build-error-resolver.md +114 -114
  3. package/.agent/agents/chief-of-staff.md +151 -151
  4. package/.agent/agents/code-reviewer.md +237 -237
  5. package/.agent/agents/cpp-build-resolver.md +90 -90
  6. package/.agent/agents/cpp-reviewer.md +72 -72
  7. package/.agent/agents/csharp-reviewer.md +101 -0
  8. package/.agent/agents/dart-build-resolver.md +201 -0
  9. package/.agent/agents/database-reviewer.md +91 -91
  10. package/.agent/agents/doc-updater.md +107 -107
  11. package/.agent/agents/docs-lookup.md +68 -68
  12. package/.agent/agents/e2e-runner.md +107 -107
  13. package/.agent/agents/flutter-reviewer.md +243 -243
  14. package/.agent/agents/gan-evaluator.md +209 -0
  15. package/.agent/agents/gan-generator.md +131 -0
  16. package/.agent/agents/gan-planner.md +99 -0
  17. package/.agent/agents/go-build-resolver.md +94 -94
  18. package/.agent/agents/go-reviewer.md +76 -76
  19. package/.agent/agents/harness-optimizer.md +35 -35
  20. package/.agent/agents/healthcare-reviewer.md +83 -0
  21. package/.agent/agents/java-build-resolver.md +153 -153
  22. package/.agent/agents/java-reviewer.md +92 -92
  23. package/.agent/agents/kotlin-build-resolver.md +118 -118
  24. package/.agent/agents/kotlin-reviewer.md +159 -159
  25. package/.agent/agents/loop-operator.md +36 -36
  26. package/.agent/agents/opensource-forker.md +198 -0
  27. package/.agent/agents/opensource-packager.md +249 -0
  28. package/.agent/agents/opensource-sanitizer.md +188 -0
  29. package/.agent/agents/performance-optimizer.md +392 -133
  30. package/.agent/agents/personas/athena-agent/agent.json +10 -0
  31. package/.agent/agents/personas/athena-agent/athena-backend-logic-architecture-profile.md +189 -0
  32. package/.agent/agents/personas/athena-agent/context-files/agents.md +55 -0
  33. package/.agent/agents/personas/athena-agent/context-files/identity.md +23 -0
  34. package/.agent/agents/personas/athena-agent/context-files/soul.md +51 -0
  35. package/.agent/agents/personas/athena-agent/context-files/user-predefined.md +15 -0
  36. package/.agent/agents/personas/athena-agent/user-context-files/system/bootstrap.md +37 -0
  37. package/.agent/agents/personas/athena-agent/user-context-files/system/user.md +45 -0
  38. package/.agent/agents/personas/da-vinci-agent/agent.json +10 -0
  39. package/.agent/agents/personas/da-vinci-agent/context-files/agents.md +55 -0
  40. package/.agent/agents/personas/da-vinci-agent/context-files/identity.md +23 -0
  41. package/.agent/agents/personas/da-vinci-agent/context-files/soul.md +51 -0
  42. package/.agent/agents/personas/da-vinci-agent/context-files/user-predefined.md +15 -0
  43. package/.agent/agents/personas/da-vinci-agent/da-vinci-frontend-ui-ux-design-profile.md +189 -0
  44. package/.agent/agents/personas/da-vinci-agent/user-context-files/system/bootstrap.md +37 -0
  45. package/.agent/agents/personas/da-vinci-agent/user-context-files/system/user.md +45 -0
  46. package/.agent/agents/personas/duong-tang-agent/agent.json +10 -0
  47. package/.agent/agents/personas/duong-tang-agent/context-files/agents.md +55 -0
  48. package/.agent/agents/personas/duong-tang-agent/context-files/identity.md +23 -0
  49. package/.agent/agents/personas/duong-tang-agent/context-files/soul.md +51 -0
  50. package/.agent/agents/personas/duong-tang-agent/context-files/user-predefined.md +15 -0
  51. package/.agent/agents/personas/duong-tang-agent/tang-monk-quality-testing-documentation-profile.md +189 -0
  52. package/.agent/agents/personas/duong-tang-agent/user-context-files/system/bootstrap.md +37 -0
  53. package/.agent/agents/personas/duong-tang-agent/user-context-files/system/user.md +45 -0
  54. package/.agent/agents/personas/gia-cat-luong-agent/agent.json +10 -0
  55. package/.agent/agents/personas/gia-cat-luong-agent/context-files/agents.md +55 -0
  56. package/.agent/agents/personas/gia-cat-luong-agent/context-files/identity.md +23 -0
  57. package/.agent/agents/personas/gia-cat-luong-agent/context-files/soul.md +51 -0
  58. package/.agent/agents/personas/gia-cat-luong-agent/context-files/user-predefined.md +15 -0
  59. package/.agent/agents/personas/gia-cat-luong-agent/kongming-research-strategy-analysis-profile.md +189 -0
  60. package/.agent/agents/personas/gia-cat-luong-agent/user-context-files/system/bootstrap.md +37 -0
  61. package/.agent/agents/personas/gia-cat-luong-agent/user-context-files/system/user.md +45 -0
  62. package/.agent/agents/personas/mihata-agent/agent.json +10 -0
  63. package/.agent/agents/personas/mihata-agent/context-files/agents.md +55 -0
  64. package/.agent/agents/personas/mihata-agent/context-files/identity.md +23 -0
  65. package/.agent/agents/personas/mihata-agent/context-files/soul.md +51 -0
  66. package/.agent/agents/personas/mihata-agent/context-files/user-predefined.md +15 -0
  67. package/.agent/agents/personas/mihata-agent/mihata-multi-agent-orchestration-profile.md +189 -0
  68. package/.agent/agents/personas/mihata-agent/user-context-files/system/bootstrap.md +37 -0
  69. package/.agent/agents/personas/mihata-agent/user-context-files/system/user.md +45 -0
  70. package/.agent/agents/personas/tesla-agent/agent.json +10 -0
  71. package/.agent/agents/personas/tesla-agent/context-files/agents.md +55 -0
  72. package/.agent/agents/personas/tesla-agent/context-files/identity.md +23 -0
  73. package/.agent/agents/personas/tesla-agent/context-files/soul.md +51 -0
  74. package/.agent/agents/personas/tesla-agent/context-files/user-predefined.md +15 -0
  75. package/.agent/agents/personas/tesla-agent/tesla-fullstack-system-optimization-profile.md +189 -0
  76. package/.agent/agents/personas/tesla-agent/user-context-files/system/bootstrap.md +37 -0
  77. package/.agent/agents/personas/tesla-agent/user-context-files/system/user.md +45 -0
  78. package/.agent/agents/personas/tu-ma-y-agent/agent.json +10 -0
  79. package/.agent/agents/personas/tu-ma-y-agent/context-files/agents.md +55 -0
  80. package/.agent/agents/personas/tu-ma-y-agent/context-files/identity.md +23 -0
  81. package/.agent/agents/personas/tu-ma-y-agent/context-files/soul.md +51 -0
  82. package/.agent/agents/personas/tu-ma-y-agent/context-files/user-predefined.md +15 -0
  83. package/.agent/agents/personas/tu-ma-y-agent/simayi-feasibility-risk-control-profile.md +189 -0
  84. package/.agent/agents/personas/tu-ma-y-agent/user-context-files/system/bootstrap.md +37 -0
  85. package/.agent/agents/personas/tu-ma-y-agent/user-context-files/system/user.md +45 -0
  86. package/.agent/agents/personas/venti-agent/agent.json +10 -0
  87. package/.agent/agents/personas/venti-agent/context-files/agents.md +55 -0
  88. package/.agent/agents/personas/venti-agent/context-files/identity.md +23 -0
  89. package/.agent/agents/personas/venti-agent/context-files/soul.md +51 -0
  90. package/.agent/agents/personas/venti-agent/context-files/user-predefined.md +15 -0
  91. package/.agent/agents/personas/venti-agent/user-context-files/system/bootstrap.md +37 -0
  92. package/.agent/agents/personas/venti-agent/user-context-files/system/user.md +45 -0
  93. package/.agent/agents/personas/venti-agent/venti-learning-communication-mentoring-profile.md +189 -0
  94. package/.agent/agents/planner.md +212 -212
  95. package/.agent/agents/python-reviewer.md +98 -98
  96. package/.agent/agents/pytorch-build-resolver.md +120 -120
  97. package/.agent/agents/refactor-cleaner.md +85 -85
  98. package/.agent/agents/rust-build-resolver.md +148 -148
  99. package/.agent/agents/rust-reviewer.md +94 -94
  100. package/.agent/agents/security-reviewer.md +108 -108
  101. package/.agent/agents/tdd-guide.md +91 -91
  102. package/.agent/agents/typescript-reviewer.md +112 -112
  103. package/.agent/contexts/dev.md +20 -0
  104. package/.agent/contexts/research.md +26 -0
  105. package/.agent/contexts/review.md +22 -0
  106. package/.agent/hooks/hooks.json +395 -0
  107. package/.agent/hooks/readme.md +222 -0
  108. package/.agent/mcp-configs/mcp-servers.json +181 -0
  109. package/.agent/rules/common/agents.md +50 -0
  110. package/.agent/rules/common/code-review.md +124 -0
  111. package/.agent/rules/common/coding-style.md +48 -0
  112. package/.agent/rules/common/development-workflow.md +44 -0
  113. package/.agent/rules/common/git-workflow.md +24 -0
  114. package/.agent/rules/common/hooks.md +30 -0
  115. package/.agent/rules/common/patterns.md +31 -0
  116. package/.agent/rules/common/performance.md +55 -0
  117. package/.agent/rules/common/security.md +29 -0
  118. package/.agent/rules/common/testing.md +29 -0
  119. package/.agent/rules/cpp/coding-style.md +44 -0
  120. package/.agent/rules/cpp/hooks.md +39 -0
  121. package/.agent/rules/cpp/patterns.md +51 -0
  122. package/.agent/rules/cpp/security.md +51 -0
  123. package/.agent/rules/cpp/testing.md +44 -0
  124. package/.agent/rules/csharp/coding-style.md +72 -0
  125. package/.agent/rules/csharp/hooks.md +25 -0
  126. package/.agent/rules/csharp/patterns.md +50 -0
  127. package/.agent/rules/csharp/security.md +58 -0
  128. package/.agent/rules/csharp/testing.md +46 -0
  129. package/.agent/rules/dart/coding-style.md +159 -0
  130. package/.agent/rules/dart/hooks.md +66 -0
  131. package/.agent/rules/dart/patterns.md +261 -0
  132. package/.agent/rules/dart/security.md +135 -0
  133. package/.agent/rules/dart/testing.md +215 -0
  134. package/.agent/rules/golang/coding-style.md +32 -0
  135. package/.agent/rules/golang/hooks.md +17 -0
  136. package/.agent/rules/golang/patterns.md +45 -0
  137. package/.agent/rules/golang/security.md +34 -0
  138. package/.agent/rules/golang/testing.md +31 -0
  139. package/.agent/rules/java/coding-style.md +114 -0
  140. package/.agent/rules/java/hooks.md +18 -0
  141. package/.agent/rules/java/patterns.md +146 -0
  142. package/.agent/rules/java/security.md +100 -0
  143. package/.agent/rules/java/testing.md +131 -0
  144. package/.agent/rules/kotlin/coding-style.md +86 -0
  145. package/.agent/rules/kotlin/hooks.md +17 -0
  146. package/.agent/rules/kotlin/patterns.md +146 -0
  147. package/.agent/rules/kotlin/security.md +82 -0
  148. package/.agent/rules/kotlin/testing.md +128 -0
  149. package/.agent/rules/perl/coding-style.md +46 -0
  150. package/.agent/rules/perl/hooks.md +22 -0
  151. package/.agent/rules/perl/patterns.md +76 -0
  152. package/.agent/rules/perl/security.md +69 -0
  153. package/.agent/rules/perl/testing.md +54 -0
  154. package/.agent/rules/php/coding-style.md +40 -0
  155. package/.agent/rules/php/hooks.md +24 -0
  156. package/.agent/rules/php/patterns.md +33 -0
  157. package/.agent/rules/php/security.md +37 -0
  158. package/.agent/rules/php/testing.md +39 -0
  159. package/.agent/rules/python/coding-style.md +42 -0
  160. package/.agent/rules/python/hooks.md +19 -0
  161. package/.agent/rules/python/patterns.md +39 -0
  162. package/.agent/rules/python/security.md +30 -0
  163. package/.agent/rules/python/testing.md +38 -0
  164. package/.agent/rules/readme.md +111 -0
  165. package/.agent/rules/rust/coding-style.md +151 -0
  166. package/.agent/rules/rust/hooks.md +16 -0
  167. package/.agent/rules/rust/patterns.md +168 -0
  168. package/.agent/rules/rust/security.md +141 -0
  169. package/.agent/rules/rust/testing.md +154 -0
  170. package/.agent/rules/swift/coding-style.md +47 -0
  171. package/.agent/rules/swift/hooks.md +20 -0
  172. package/.agent/rules/swift/patterns.md +66 -0
  173. package/.agent/rules/swift/security.md +33 -0
  174. package/.agent/rules/swift/testing.md +45 -0
  175. package/.agent/rules/typescript/coding-style.md +199 -0
  176. package/.agent/rules/typescript/hooks.md +22 -0
  177. package/.agent/rules/typescript/patterns.md +52 -0
  178. package/.agent/rules/typescript/security.md +28 -0
  179. package/.agent/rules/typescript/testing.md +18 -0
  180. package/.agent/rules/web/coding-style.md +96 -0
  181. package/.agent/rules/web/design-quality.md +63 -0
  182. package/.agent/rules/web/hooks.md +120 -0
  183. package/.agent/rules/web/patterns.md +79 -0
  184. package/.agent/rules/web/performance.md +64 -0
  185. package/.agent/rules/web/security.md +57 -0
  186. package/.agent/rules/web/testing.md +55 -0
  187. package/.agent/rules/zh/agents.md +50 -0
  188. package/.agent/rules/zh/code-review.md +124 -0
  189. package/.agent/rules/zh/coding-style.md +48 -0
  190. package/.agent/rules/zh/development-workflow.md +44 -0
  191. package/.agent/rules/zh/git-workflow.md +24 -0
  192. package/.agent/rules/zh/hooks.md +30 -0
  193. package/.agent/rules/zh/patterns.md +31 -0
  194. package/.agent/rules/zh/performance.md +55 -0
  195. package/.agent/rules/zh/readme.md +108 -0
  196. package/.agent/rules/zh/security.md +29 -0
  197. package/.agent/rules/zh/testing.md +29 -0
  198. package/.agent/skills/agent-eval/SKILL.md +145 -0
  199. package/.agent/skills/agent-harness-construction/SKILL.md +73 -0
  200. package/.agent/skills/agent-payment-x402/SKILL.md +178 -0
  201. package/.agent/skills/agentic-engineering/SKILL.md +63 -0
  202. package/.agent/skills/ai-first-engineering/SKILL.md +51 -0
  203. package/.agent/skills/ai-regression-testing/SKILL.md +385 -0
  204. package/.agent/skills/android-clean-architecture/SKILL.md +339 -0
  205. package/.agent/skills/api-design/SKILL.md +523 -0
  206. package/.agent/skills/architecture-decision-records/SKILL.md +179 -0
  207. package/.agent/skills/article-writing/SKILL.md +79 -0
  208. package/.agent/skills/autonomous-agent-harness/SKILL.md +267 -0
  209. package/.agent/skills/autonomous-loops/SKILL.md +610 -0
  210. package/.agent/skills/backend-patterns/SKILL.md +598 -0
  211. package/.agent/skills/benchmark/SKILL.md +93 -0
  212. package/.agent/skills/blueprint/SKILL.md +105 -0
  213. package/.agent/skills/brand-voice/SKILL.md +97 -0
  214. package/.agent/skills/brand-voice/references/voice-profile-schema.md +55 -0
  215. package/.agent/skills/browser-qa/SKILL.md +87 -0
  216. package/.agent/skills/bun-runtime/SKILL.md +84 -0
  217. package/.agent/skills/canary-watch/SKILL.md +99 -0
  218. package/.agent/skills/carrier-relationship-management/SKILL.md +212 -0
  219. package/.agent/skills/ck/SKILL.md +147 -0
  220. package/.agent/skills/ck/commands/forget.mjs +44 -0
  221. package/.agent/skills/ck/commands/info.mjs +24 -0
  222. package/.agent/skills/ck/commands/init.mjs +143 -0
  223. package/.agent/skills/ck/commands/list.mjs +40 -0
  224. package/.agent/skills/ck/commands/migrate.mjs +202 -0
  225. package/.agent/skills/ck/commands/resume.mjs +36 -0
  226. package/.agent/skills/ck/commands/save.mjs +210 -0
  227. package/.agent/skills/ck/commands/shared.mjs +387 -0
  228. package/.agent/skills/ck/hooks/session-start.mjs +224 -0
  229. package/.agent/skills/claude-api/SKILL.md +337 -0
  230. package/.agent/skills/claude-devfleet/SKILL.md +103 -0
  231. package/.agent/skills/click-path-audit/SKILL.md +244 -0
  232. package/.agent/skills/clickhouse-io/SKILL.md +439 -0
  233. package/.agent/skills/codebase-onboarding/SKILL.md +233 -0
  234. package/.agent/skills/coding-standards/SKILL.md +530 -0
  235. package/.agent/skills/compose-multiplatform-patterns/SKILL.md +299 -0
  236. package/.agent/skills/configure-ecc/SKILL.md +367 -0
  237. package/.agent/skills/connections-optimizer/SKILL.md +189 -0
  238. package/.agent/skills/content-engine/SKILL.md +131 -0
  239. package/.agent/skills/content-hash-cache-pattern/SKILL.md +161 -0
  240. package/.agent/skills/context-budget/SKILL.md +135 -0
  241. package/.agent/skills/continuous-agent-loop/SKILL.md +45 -0
  242. package/.agent/skills/continuous-learning/SKILL.md +119 -0
  243. package/.agent/skills/continuous-learning/config.json +18 -0
  244. package/.agent/skills/continuous-learning/evaluate-session.sh +69 -0
  245. package/.agent/skills/continuous-learning-v2/SKILL.md +365 -0
  246. package/.agent/skills/continuous-learning-v2/agents/observer-loop.sh +271 -0
  247. package/.agent/skills/continuous-learning-v2/agents/observer.md +198 -0
  248. package/.agent/skills/continuous-learning-v2/agents/session-guardian.sh +150 -0
  249. package/.agent/skills/continuous-learning-v2/agents/start-observer.sh +244 -0
  250. package/.agent/skills/continuous-learning-v2/config.json +8 -0
  251. package/.agent/skills/continuous-learning-v2/hooks/observe.sh +428 -0
  252. package/.agent/skills/continuous-learning-v2/scripts/detect-project.sh +228 -0
  253. package/.agent/skills/continuous-learning-v2/scripts/instinct-cli.py +1426 -0
  254. package/.agent/skills/continuous-learning-v2/scripts/test-parse-instinct.py +984 -0
  255. package/.agent/skills/cost-aware-llm-pipeline/SKILL.md +183 -0
  256. package/.agent/skills/cpp-coding-standards/SKILL.md +723 -0
  257. package/.agent/skills/cpp-testing/SKILL.md +324 -0
  258. package/.agent/skills/crosspost/SKILL.md +111 -0
  259. package/.agent/skills/csharp-testing/SKILL.md +321 -0
  260. package/.agent/skills/customer-billing-ops/SKILL.md +140 -0
  261. package/.agent/skills/customs-trade-compliance/SKILL.md +263 -0
  262. package/.agent/skills/dart-flutter-patterns/SKILL.md +563 -0
  263. package/.agent/skills/data-scraper-agent/SKILL.md +764 -0
  264. package/.agent/skills/database-migrations/SKILL.md +429 -0
  265. package/.agent/skills/deep-research/SKILL.md +155 -0
  266. package/.agent/skills/deployment-patterns/SKILL.md +427 -0
  267. package/.agent/skills/design-system/SKILL.md +82 -0
  268. package/.agent/skills/django-patterns/SKILL.md +734 -0
  269. package/.agent/skills/django-security/SKILL.md +593 -0
  270. package/.agent/skills/django-tdd/SKILL.md +729 -0
  271. package/.agent/skills/django-verification/SKILL.md +469 -0
  272. package/.agent/skills/dmux-workflows/SKILL.md +191 -0
  273. package/.agent/skills/docker-patterns/SKILL.md +364 -0
  274. package/.agent/skills/documentation-lookup/SKILL.md +90 -0
  275. package/.agent/skills/dotnet-patterns/SKILL.md +321 -0
  276. package/.agent/skills/e2e-testing/SKILL.md +326 -0
  277. package/.agent/skills/energy-procurement/SKILL.md +228 -0
  278. package/.agent/skills/enterprise-agent-ops/SKILL.md +50 -0
  279. package/.agent/skills/eval-harness/SKILL.md +270 -0
  280. package/.agent/skills/exa-search/SKILL.md +103 -0
  281. package/.agent/skills/fal-ai-media/SKILL.md +284 -0
  282. package/.agent/skills/flutter-dart-code-review/SKILL.md +435 -0
  283. package/.agent/skills/foundation-models-on-device/SKILL.md +243 -0
  284. package/.agent/skills/frontend-patterns/SKILL.md +642 -0
  285. package/.agent/skills/frontend-slides/SKILL.md +184 -0
  286. package/.agent/skills/frontend-slides/style-presets.md +330 -0
  287. package/.agent/skills/gan-style-harness/SKILL.md +278 -0
  288. package/.agent/skills/git-workflow/SKILL.md +715 -0
  289. package/.agent/skills/golang-patterns/SKILL.md +674 -0
  290. package/.agent/skills/golang-testing/SKILL.md +720 -0
  291. package/.agent/skills/google-workspace-ops/SKILL.md +95 -0
  292. package/.agent/skills/healthcare-cdss-patterns/SKILL.md +245 -0
  293. package/.agent/skills/healthcare-emr-patterns/SKILL.md +159 -0
  294. package/.agent/skills/healthcare-eval-harness/SKILL.md +207 -0
  295. package/.agent/skills/healthcare-phi-compliance/SKILL.md +145 -0
  296. package/.agent/skills/hexagonal-architecture/SKILL.md +276 -0
  297. package/.agent/skills/inventory-demand-planning/SKILL.md +247 -0
  298. package/.agent/skills/investor-materials/SKILL.md +96 -0
  299. package/.agent/skills/investor-outreach/SKILL.md +91 -0
  300. package/.agent/skills/iterative-retrieval/SKILL.md +211 -0
  301. package/.agent/skills/java-coding-standards/SKILL.md +147 -0
  302. package/.agent/skills/jira-integration/SKILL.md +293 -0
  303. package/.agent/skills/jpa-patterns/SKILL.md +151 -0
  304. package/.agent/skills/kotlin-coroutines-flows/SKILL.md +284 -0
  305. package/.agent/skills/kotlin-exposed-patterns/SKILL.md +719 -0
  306. package/.agent/skills/kotlin-ktor-patterns/SKILL.md +689 -0
  307. package/.agent/skills/kotlin-patterns/SKILL.md +711 -0
  308. package/.agent/skills/kotlin-testing/SKILL.md +824 -0
  309. package/.agent/skills/laravel-patterns/SKILL.md +415 -0
  310. package/.agent/skills/laravel-plugin-discovery/SKILL.md +229 -0
  311. package/.agent/skills/laravel-security/SKILL.md +285 -0
  312. package/.agent/skills/laravel-tdd/SKILL.md +283 -0
  313. package/.agent/skills/laravel-verification/SKILL.md +179 -0
  314. package/.agent/skills/lead-intelligence/SKILL.md +321 -0
  315. package/.agent/skills/lead-intelligence/agents/enrichment-agent.md +85 -0
  316. package/.agent/skills/lead-intelligence/agents/mutual-mapper.md +75 -0
  317. package/.agent/skills/lead-intelligence/agents/outreach-drafter.md +98 -0
  318. package/.agent/skills/lead-intelligence/agents/signal-scorer.md +60 -0
  319. package/.agent/skills/liquid-glass-design/SKILL.md +279 -0
  320. package/.agent/skills/logistics-exception-management/SKILL.md +222 -0
  321. package/.agent/skills/manim-video/SKILL.md +89 -0
  322. package/.agent/skills/manim-video/assets/network-graph-scene.py +52 -0
  323. package/.agent/skills/market-research/SKILL.md +75 -0
  324. package/.agent/skills/mcp-builder/SKILL.md +173 -113
  325. package/.agent/skills/mcp-builder/license.txt +202 -0
  326. package/.agent/skills/mcp-builder/reference/evaluation.md +602 -0
  327. package/.agent/skills/mcp-builder/reference/mcp-best-practices.md +249 -0
  328. package/.agent/skills/mcp-builder/reference/node-mcp-server.md +970 -0
  329. package/.agent/skills/mcp-builder/reference/python-mcp-server.md +719 -0
  330. package/.agent/skills/mcp-builder/scripts/connections.py +151 -0
  331. package/.agent/skills/mcp-builder/scripts/evaluation.py +373 -0
  332. package/.agent/skills/mcp-builder/scripts/example-evaluation.xml +22 -0
  333. package/.agent/skills/mcp-builder/scripts/requirements.txt +2 -0
  334. package/.agent/skills/mcp-server-patterns/SKILL.md +67 -0
  335. package/.agent/skills/nanoclaw-repl/SKILL.md +33 -0
  336. package/.agent/skills/nestjs-patterns/SKILL.md +230 -0
  337. package/.agent/skills/nextjs-turbopack/SKILL.md +44 -0
  338. package/.agent/skills/nutrient-document-processing/SKILL.md +167 -0
  339. package/.agent/skills/nuxt4-patterns/SKILL.md +100 -0
  340. package/.agent/skills/openclaw-persona-forge/SKILL.md +296 -0
  341. package/.agent/skills/openclaw-persona-forge/gacha.py +224 -0
  342. package/.agent/skills/openclaw-persona-forge/gacha.sh +5 -0
  343. package/.agent/skills/openclaw-persona-forge/references/avatar-style.md +124 -0
  344. package/.agent/skills/openclaw-persona-forge/references/boundary-rules.md +53 -0
  345. package/.agent/skills/openclaw-persona-forge/references/error-handling.md +53 -0
  346. package/.agent/skills/openclaw-persona-forge/references/identity-tension.md +48 -0
  347. package/.agent/skills/openclaw-persona-forge/references/naming-system.md +39 -0
  348. package/.agent/skills/openclaw-persona-forge/references/output-template.md +166 -0
  349. package/.agent/skills/opensource-pipeline/SKILL.md +255 -0
  350. package/.agent/skills/perl-patterns/SKILL.md +504 -0
  351. package/.agent/skills/perl-security/SKILL.md +503 -0
  352. package/.agent/skills/perl-testing/SKILL.md +475 -0
  353. package/.agent/skills/plankton-code-quality/SKILL.md +236 -0
  354. package/.agent/skills/postgres-patterns/SKILL.md +147 -0
  355. package/.agent/skills/product-lens/SKILL.md +85 -0
  356. package/.agent/skills/production-scheduling/SKILL.md +238 -0
  357. package/.agent/skills/project-flow-ops/SKILL.md +111 -0
  358. package/.agent/skills/project-guidelines-example/SKILL.md +349 -0
  359. package/.agent/skills/prompt-optimizer/SKILL.md +397 -0
  360. package/.agent/skills/python-patterns/SKILL.md +622 -313
  361. package/.agent/skills/python-testing/SKILL.md +816 -0
  362. package/.agent/skills/pytorch-patterns/SKILL.md +396 -0
  363. package/.agent/skills/quality-nonconformance/SKILL.md +260 -0
  364. package/.agent/skills/ralphinho-rfc-pipeline/SKILL.md +67 -0
  365. package/.agent/skills/regex-vs-llm-structured-text/SKILL.md +220 -0
  366. package/.agent/skills/remotion-video-creation/SKILL.md +43 -0
  367. package/.agent/skills/remotion-video-creation/rules/3d.md +86 -0
  368. package/.agent/skills/remotion-video-creation/rules/animations.md +29 -0
  369. package/.agent/skills/remotion-video-creation/rules/assets/charts-bar-chart.tsx +173 -0
  370. package/.agent/skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx +100 -0
  371. package/.agent/skills/remotion-video-creation/rules/assets/text-animations-word-highlight.tsx +108 -0
  372. package/.agent/skills/remotion-video-creation/rules/assets.md +78 -0
  373. package/.agent/skills/remotion-video-creation/rules/audio.md +172 -0
  374. package/.agent/skills/remotion-video-creation/rules/calculate-metadata.md +104 -0
  375. package/.agent/skills/remotion-video-creation/rules/can-decode.md +75 -0
  376. package/.agent/skills/remotion-video-creation/rules/charts.md +58 -0
  377. package/.agent/skills/remotion-video-creation/rules/compositions.md +146 -0
  378. package/.agent/skills/remotion-video-creation/rules/display-captions.md +126 -0
  379. package/.agent/skills/remotion-video-creation/rules/extract-frames.md +229 -0
  380. package/.agent/skills/remotion-video-creation/rules/fonts.md +152 -0
  381. package/.agent/skills/remotion-video-creation/rules/get-audio-duration.md +58 -0
  382. package/.agent/skills/remotion-video-creation/rules/get-video-dimensions.md +68 -0
  383. package/.agent/skills/remotion-video-creation/rules/get-video-duration.md +58 -0
  384. package/.agent/skills/remotion-video-creation/rules/gifs.md +138 -0
  385. package/.agent/skills/remotion-video-creation/rules/images.md +130 -0
  386. package/.agent/skills/remotion-video-creation/rules/import-srt-captions.md +67 -0
  387. package/.agent/skills/remotion-video-creation/rules/lottie.md +67 -0
  388. package/.agent/skills/remotion-video-creation/rules/measuring-dom-nodes.md +34 -0
  389. package/.agent/skills/remotion-video-creation/rules/measuring-text.md +143 -0
  390. package/.agent/skills/remotion-video-creation/rules/sequencing.md +106 -0
  391. package/.agent/skills/remotion-video-creation/rules/tailwind.md +11 -0
  392. package/.agent/skills/remotion-video-creation/rules/text-animations.md +20 -0
  393. package/.agent/skills/remotion-video-creation/rules/timing.md +179 -0
  394. package/.agent/skills/remotion-video-creation/rules/transcribe-captions.md +19 -0
  395. package/.agent/skills/remotion-video-creation/rules/transitions.md +122 -0
  396. package/.agent/skills/remotion-video-creation/rules/trimming.md +52 -0
  397. package/.agent/skills/remotion-video-creation/rules/videos.md +171 -0
  398. package/.agent/skills/repo-scan/SKILL.md +78 -0
  399. package/.agent/skills/returns-reverse-logistics/SKILL.md +240 -0
  400. package/.agent/skills/rules-distill/SKILL.md +264 -0
  401. package/.agent/skills/rules-distill/scripts/scan-rules.sh +58 -0
  402. package/.agent/skills/rules-distill/scripts/scan-skills.sh +129 -0
  403. package/.agent/skills/rust-patterns/SKILL.md +499 -0
  404. package/.agent/skills/rust-testing/SKILL.md +500 -0
  405. package/.agent/skills/safety-guard/SKILL.md +75 -0
  406. package/.agent/skills/santa-method/SKILL.md +306 -0
  407. package/.agent/skills/search-first/SKILL.md +161 -0
  408. package/.agent/skills/security-review/SKILL.md +495 -0
  409. package/.agent/skills/security-review/cloud-infrastructure-security.md +361 -0
  410. package/.agent/skills/security-scan/SKILL.md +165 -0
  411. package/.agent/skills/skill-comply/SKILL.md +58 -0
  412. package/.agent/skills/skill-comply/fixtures/compliant-trace.jsonl +5 -0
  413. package/.agent/skills/skill-comply/fixtures/noncompliant-trace.jsonl +3 -0
  414. package/.agent/skills/skill-comply/fixtures/tdd-spec.yaml +44 -0
  415. package/.agent/skills/skill-comply/prompts/classifier.md +24 -0
  416. package/.agent/skills/skill-comply/prompts/scenario-generator.md +62 -0
  417. package/.agent/skills/skill-comply/prompts/spec-generator.md +42 -0
  418. package/.agent/skills/skill-comply/pyproject.toml +15 -0
  419. package/.agent/skills/skill-comply/scripts/classifier.py +85 -0
  420. package/.agent/skills/skill-comply/scripts/grader.py +122 -0
  421. package/.agent/skills/skill-comply/scripts/init.py +0 -0
  422. package/.agent/skills/skill-comply/scripts/parser.py +107 -0
  423. package/.agent/skills/skill-comply/scripts/report.py +170 -0
  424. package/.agent/skills/skill-comply/scripts/run.py +127 -0
  425. package/.agent/skills/skill-comply/scripts/runner.py +161 -0
  426. package/.agent/skills/skill-comply/scripts/scenario-generator.py +70 -0
  427. package/.agent/skills/skill-comply/scripts/spec-generator.py +72 -0
  428. package/.agent/skills/skill-comply/scripts/utils.py +13 -0
  429. package/.agent/skills/skill-comply/tests/test-grader.py +137 -0
  430. package/.agent/skills/skill-comply/tests/test-parser.py +90 -0
  431. package/.agent/skills/skill-creator/SKILL.md +485 -0
  432. package/.agent/skills/skill-creator/agents/analyzer.md +274 -0
  433. package/.agent/skills/skill-creator/agents/comparator.md +202 -0
  434. package/.agent/skills/skill-creator/agents/grader.md +223 -0
  435. package/.agent/skills/skill-creator/assets/eval-review.html +146 -0
  436. package/.agent/skills/skill-creator/eval-viewer/generate-review.py +471 -0
  437. package/.agent/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  438. package/.agent/skills/skill-creator/license.txt +202 -0
  439. package/.agent/skills/skill-creator/references/schemas.md +430 -0
  440. package/.agent/skills/skill-creator/scripts/aggregate-benchmark.py +401 -0
  441. package/.agent/skills/skill-creator/scripts/generate-report.py +326 -0
  442. package/.agent/skills/skill-creator/scripts/improve-description.py +247 -0
  443. package/.agent/skills/skill-creator/scripts/init.py +0 -0
  444. package/.agent/skills/skill-creator/scripts/package-skill.py +136 -0
  445. package/.agent/skills/skill-creator/scripts/quick-validate.py +103 -0
  446. package/.agent/skills/skill-creator/scripts/run-eval.py +310 -0
  447. package/.agent/skills/skill-creator/scripts/run-loop.py +328 -0
  448. package/.agent/skills/skill-creator/scripts/utils.py +47 -0
  449. package/.agent/skills/skill-stocktake/SKILL.md +193 -0
  450. package/.agent/skills/skill-stocktake/scripts/quick-diff.sh +87 -0
  451. package/.agent/skills/skill-stocktake/scripts/save-results.sh +56 -0
  452. package/.agent/skills/skill-stocktake/scripts/scan.sh +170 -0
  453. package/.agent/skills/social-graph-ranker/SKILL.md +154 -0
  454. package/.agent/skills/springboot-patterns/SKILL.md +314 -0
  455. package/.agent/skills/springboot-security/SKILL.md +272 -0
  456. package/.agent/skills/springboot-tdd/SKILL.md +158 -0
  457. package/.agent/skills/springboot-verification/SKILL.md +231 -0
  458. package/.agent/skills/strategic-compact/SKILL.md +131 -0
  459. package/.agent/skills/strategic-compact/suggest-compact.sh +54 -0
  460. package/.agent/skills/swift-actor-persistence/SKILL.md +143 -0
  461. package/.agent/skills/swift-concurrency-6-2/SKILL.md +216 -0
  462. package/.agent/skills/swift-protocol-di-testing/SKILL.md +190 -0
  463. package/.agent/skills/swiftui-patterns/SKILL.md +259 -0
  464. package/.agent/skills/tdd-workflow/SKILL.md +412 -98
  465. package/.agent/skills/team-builder/SKILL.md +168 -0
  466. package/.agent/skills/token-budget-advisor/SKILL.md +133 -0
  467. package/.agent/skills/ui-demo/SKILL.md +465 -0
  468. package/.agent/skills/ui-ux-pro-max/data/charts.csv +26 -26
  469. package/.agent/skills/ui-ux-pro-max/data/colors.csv +97 -97
  470. package/.agent/skills/ui-ux-pro-max/data/landing.csv +28 -28
  471. package/.agent/skills/ui-ux-pro-max/data/products.csv +96 -96
  472. package/.agent/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -53
  473. package/.agent/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -56
  474. package/.agent/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -53
  475. package/.agent/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -52
  476. package/.agent/skills/ui-ux-pro-max/data/stacks/react.csv +54 -54
  477. package/.agent/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -54
  478. package/.agent/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -51
  479. package/.agent/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -50
  480. package/.agent/skills/ui-ux-pro-max/data/styles.csv +68 -68
  481. package/.agent/skills/ui-ux-pro-max/data/ux-guidelines.csv +99 -99
  482. package/.agent/skills/ui-ux-pro-max/scripts/search.py +114 -114
  483. package/.agent/skills/verification-loop/SKILL.md +126 -0
  484. package/.agent/skills/video-editing/SKILL.md +310 -0
  485. package/.agent/skills/videodb/SKILL.md +374 -0
  486. package/.agent/skills/videodb/reference/api-reference.md +550 -0
  487. package/.agent/skills/videodb/reference/capture-reference.md +407 -0
  488. package/.agent/skills/videodb/reference/capture.md +101 -0
  489. package/.agent/skills/videodb/reference/editor.md +443 -0
  490. package/.agent/skills/videodb/reference/generative.md +331 -0
  491. package/.agent/skills/videodb/reference/rtstream-reference.md +564 -0
  492. package/.agent/skills/videodb/reference/rtstream.md +65 -0
  493. package/.agent/skills/videodb/reference/search.md +230 -0
  494. package/.agent/skills/videodb/reference/streaming.md +406 -0
  495. package/.agent/skills/videodb/reference/use-cases.md +118 -0
  496. package/.agent/skills/videodb/scripts/ws-listener.py +282 -0
  497. package/.agent/skills/visa-doc-translate/SKILL.md +117 -0
  498. package/.agent/skills/visa-doc-translate/readme.md +86 -0
  499. package/.agent/skills/workspace-surface-audit/SKILL.md +125 -0
  500. package/.agent/skills/x-api/SKILL.md +230 -0
  501. package/.agent/tasks/two-track-merge-contract.md +29 -0
  502. package/.agent/workflows/aside.md +164 -164
  503. package/.agent/workflows/build-fix.md +62 -62
  504. package/.agent/workflows/checkpoint.md +74 -74
  505. package/.agent/workflows/claw.md +23 -51
  506. package/.agent/workflows/clean-memory.md +34 -0
  507. package/.agent/workflows/code-review.md +289 -40
  508. package/.agent/workflows/context-budget.md +23 -29
  509. package/.agent/workflows/cpp-build.md +173 -173
  510. package/.agent/workflows/cpp-review.md +132 -132
  511. package/.agent/workflows/cpp-test.md +251 -251
  512. package/.agent/workflows/devfleet.md +23 -92
  513. package/.agent/workflows/docs.md +23 -31
  514. package/.agent/workflows/e2e.md +268 -365
  515. package/.agent/workflows/eval.md +23 -120
  516. package/.agent/workflows/evolve.md +178 -178
  517. package/.agent/workflows/flutter-build.md +164 -0
  518. package/.agent/workflows/flutter-review.md +116 -0
  519. package/.agent/workflows/flutter-test.md +144 -0
  520. package/.agent/workflows/gan-build.md +99 -0
  521. package/.agent/workflows/gan-design.md +35 -0
  522. package/.agent/workflows/go-build.md +183 -183
  523. package/.agent/workflows/go-review.md +148 -148
  524. package/.agent/workflows/go-test.md +268 -268
  525. package/.agent/workflows/gradle-build.md +70 -70
  526. package/.agent/workflows/harness-audit.md +73 -71
  527. package/.agent/workflows/instinct-export.md +66 -66
  528. package/.agent/workflows/instinct-import.md +114 -114
  529. package/.agent/workflows/instinct-status.md +59 -59
  530. package/.agent/workflows/jira.md +106 -0
  531. package/.agent/workflows/kotlin-build.md +174 -174
  532. package/.agent/workflows/kotlin-review.md +140 -140
  533. package/.agent/workflows/kotlin-test.md +312 -312
  534. package/.agent/workflows/learn-eval.md +116 -116
  535. package/.agent/workflows/learn.md +70 -70
  536. package/.agent/workflows/loop-start.md +32 -32
  537. package/.agent/workflows/loop-status.md +24 -24
  538. package/.agent/workflows/model-route.md +26 -26
  539. package/.agent/workflows/multi-backend.md +158 -158
  540. package/.agent/workflows/multi-execute.md +315 -315
  541. package/.agent/workflows/multi-frontend.md +158 -158
  542. package/.agent/workflows/multi-plan.md +268 -268
  543. package/.agent/workflows/multi-workflow.md +191 -191
  544. package/.agent/workflows/orchestrate.md +135 -231
  545. package/.agent/workflows/plan.md +117 -115
  546. package/.agent/workflows/pm2.md +272 -272
  547. package/.agent/workflows/projects.md +39 -39
  548. package/.agent/workflows/promote.md +41 -41
  549. package/.agent/workflows/prompt-optimize.md +23 -38
  550. package/.agent/workflows/prp-commit.md +112 -0
  551. package/.agent/workflows/prp-implement.md +385 -0
  552. package/.agent/workflows/prp-plan.md +502 -0
  553. package/.agent/workflows/prp-pr.md +184 -0
  554. package/.agent/workflows/prp-prd.md +447 -0
  555. package/.agent/workflows/prune.md +31 -31
  556. package/.agent/workflows/python-review.md +297 -297
  557. package/.agent/workflows/quality-gate.md +29 -29
  558. package/.agent/workflows/refactor-clean.md +80 -80
  559. package/.agent/workflows/resume-session.md +156 -156
  560. package/.agent/workflows/rules-distill.md +20 -11
  561. package/.agent/workflows/rust-build.md +187 -187
  562. package/.agent/workflows/rust-review.md +142 -142
  563. package/.agent/workflows/rust-test.md +308 -308
  564. package/.agent/workflows/santa-loop.md +175 -0
  565. package/.agent/workflows/save-session.md +275 -275
  566. package/.agent/workflows/sessions.md +333 -333
  567. package/.agent/workflows/setup-pm.md +80 -80
  568. package/.agent/workflows/skill-create.md +174 -174
  569. package/.agent/workflows/skill-health.md +54 -54
  570. package/.agent/workflows/tdd.md +231 -328
  571. package/.agent/workflows/test-coverage.md +69 -69
  572. package/.agent/workflows/update-codemaps.md +72 -72
  573. package/.agent/workflows/update-docs.md +84 -84
  574. package/.agent/workflows/verify.md +23 -59
  575. package/LICENSE +176 -176
  576. package/README.md +28 -20
  577. package/RELEASE.md +32 -36
  578. package/package.json +87 -79
  579. package/scripts/release-check.js +55 -55
  580. package/src/bin/cli.js +399 -53
  581. package/src/lib/installer.js +360 -114
  582. package/src/lib/manifests/stacks.js +122 -0
  583. package/src/lib/slash-commands.js +28 -0
  584. package/src/templates/claude/CLAUDE.en.md +42 -0
  585. package/src/templates/claude/CLAUDE.md +42 -0
  586. package/src/templates/claude/CLAUDE.vi.md +42 -0
  587. package/src/templates/codex/AGENTS.en.md +40 -0
  588. package/src/templates/codex/AGENTS.md +40 -0
  589. package/src/templates/codex/AGENTS.vi.md +40 -0
  590. package/src/templates/cursor/pilo-masterkit.mdc +20 -0
  591. package/src/templates/gemini/GEMINI.en.md +56 -0
  592. package/src/templates/gemini/GEMINI.md +56 -0
  593. package/src/templates/gemini/GEMINI.vi.md +56 -0
  594. package/src/templates/github/copilot-instructions.md +16 -0
@@ -0,0 +1,244 @@
1
+ #!/bin/bash
2
+ # Continuous Learning v2 - Observer Agent Launcher
3
+ #
4
+ # Starts the background observer agent that analyzes observations
5
+ # and creates instincts. Uses Haiku model for cost efficiency.
6
+ #
7
+ # v2.1: Project-scoped — detects current project and analyzes
8
+ # project-specific observations into project-scoped instincts.
9
+ #
10
+ # Usage:
11
+ # start-observer.sh # Start observer for current project (or global)
12
+ # start-observer.sh --reset # Clear lock and restart observer for current project
13
+ # start-observer.sh stop # Stop running observer
14
+ # start-observer.sh status # Check if observer is running
15
+
16
+ set -e
17
+
18
+ # NOTE: set -e is disabled inside the background subshell below
19
+ # to prevent claude CLI failures from killing the observer loop.
20
+
21
+ # ─────────────────────────────────────────────
22
+ # Project detection
23
+ # ─────────────────────────────────────────────
24
+
25
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
26
+ SKILL_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
27
+ OBSERVER_LOOP_SCRIPT="${SCRIPT_DIR}/observer-loop.sh"
28
+
29
+ # Source shared project detection helper
30
+ # This sets: PROJECT_ID, PROJECT_NAME, PROJECT_ROOT, PROJECT_DIR
31
+ source "${SKILL_ROOT}/scripts/detect-project.sh"
32
+ PYTHON_CMD="${CLV2_PYTHON_CMD:-}"
33
+
34
+ # ─────────────────────────────────────────────
35
+ # Configuration
36
+ # ─────────────────────────────────────────────
37
+
38
+ CONFIG_DIR="${HOME}/.claude/homunculus"
39
+ if [ -n "${CLV2_CONFIG:-}" ]; then
40
+ CONFIG_FILE="$CLV2_CONFIG"
41
+ else
42
+ CONFIG_FILE="${SKILL_ROOT}/config.json"
43
+ fi
44
+ # PID file is project-scoped so each project can have its own observer
45
+ PID_FILE="${PROJECT_DIR}/.observer.pid"
46
+ LOG_FILE="${PROJECT_DIR}/observer.log"
47
+ OBSERVATIONS_FILE="${PROJECT_DIR}/observations.jsonl"
48
+ INSTINCTS_DIR="${PROJECT_DIR}/instincts/personal"
49
+ SENTINEL_FILE="${CLV2_OBSERVER_SENTINEL_FILE:-${PROJECT_ROOT:-$PROJECT_DIR}/.observer.lock}"
50
+
51
+ write_guard_sentinel() {
52
+ printf '%s\n' 'observer paused: confirmation or permission prompt detected; rerun start-observer.sh --reset after reviewing observer.log' > "$SENTINEL_FILE"
53
+ }
54
+
55
+ stop_observer_if_running() {
56
+ if [ -f "$PID_FILE" ]; then
57
+ pid=$(cat "$PID_FILE")
58
+ if kill -0 "$pid" 2>/dev/null; then
59
+ echo "Stopping observer for ${PROJECT_NAME} (PID: $pid)..."
60
+ kill "$pid"
61
+ rm -f "$PID_FILE"
62
+ echo "Observer stopped."
63
+ return 0
64
+ fi
65
+
66
+ echo "Observer not running (stale PID file)."
67
+ rm -f "$PID_FILE"
68
+ return 1
69
+ fi
70
+
71
+ echo "Observer not running."
72
+ return 1
73
+ }
74
+
75
+ # Read config values from config.json
76
+ OBSERVER_INTERVAL_MINUTES=5
77
+ MIN_OBSERVATIONS=20
78
+ OBSERVER_ENABLED=false
79
+ if [ -f "$CONFIG_FILE" ]; then
80
+ if [ -z "$PYTHON_CMD" ]; then
81
+ echo "No python interpreter found; using built-in observer defaults." >&2
82
+ else
83
+ _config=$(CLV2_CONFIG="$CONFIG_FILE" "$PYTHON_CMD" -c "
84
+ import json, os
85
+ with open(os.environ['CLV2_CONFIG']) as f:
86
+ cfg = json.load(f)
87
+ obs = cfg.get('observer', {})
88
+ print(obs.get('run_interval_minutes', 5))
89
+ print(obs.get('min_observations_to_analyze', 20))
90
+ print(str(obs.get('enabled', False)).lower())
91
+ " 2>/dev/null || echo "5
92
+ 20
93
+ false")
94
+ _interval=$(echo "$_config" | sed -n '1p')
95
+ _min_obs=$(echo "$_config" | sed -n '2p')
96
+ _enabled=$(echo "$_config" | sed -n '3p')
97
+ if [ "$_interval" -gt 0 ] 2>/dev/null; then
98
+ OBSERVER_INTERVAL_MINUTES="$_interval"
99
+ fi
100
+ if [ "$_min_obs" -gt 0 ] 2>/dev/null; then
101
+ MIN_OBSERVATIONS="$_min_obs"
102
+ fi
103
+ if [ "$_enabled" = "true" ]; then
104
+ OBSERVER_ENABLED=true
105
+ fi
106
+ fi
107
+ fi
108
+ OBSERVER_INTERVAL_SECONDS=$((OBSERVER_INTERVAL_MINUTES * 60))
109
+
110
+ echo "Project: ${PROJECT_NAME} (${PROJECT_ID})"
111
+ echo "Storage: ${PROJECT_DIR}"
112
+
113
+ # Windows/Git-Bash detection (Issue #295)
114
+ UNAME_LOWER="$(uname -s 2>/dev/null | tr '[:upper:]' '[:lower:]')"
115
+ IS_WINDOWS=false
116
+ case "$UNAME_LOWER" in
117
+ *mingw*|*msys*|*cygwin*) IS_WINDOWS=true ;;
118
+ esac
119
+
120
+ ACTION="start"
121
+ RESET_OBSERVER=false
122
+
123
+ for arg in "$@"; do
124
+ case "$arg" in
125
+ start|stop|status)
126
+ ACTION="$arg"
127
+ ;;
128
+ --reset)
129
+ RESET_OBSERVER=true
130
+ ;;
131
+ *)
132
+ echo "Usage: $0 [start|stop|status] [--reset]"
133
+ exit 1
134
+ ;;
135
+ esac
136
+ done
137
+
138
+ if [ "$RESET_OBSERVER" = "true" ]; then
139
+ rm -f "$SENTINEL_FILE"
140
+ fi
141
+
142
+ case "$ACTION" in
143
+ stop)
144
+ stop_observer_if_running || true
145
+ exit 0
146
+ ;;
147
+
148
+ status)
149
+ if [ -f "$PID_FILE" ]; then
150
+ pid=$(cat "$PID_FILE")
151
+ if kill -0 "$pid" 2>/dev/null; then
152
+ echo "Observer is running (PID: $pid)"
153
+ echo "Log: $LOG_FILE"
154
+ echo "Observations: $(wc -l < "$OBSERVATIONS_FILE" 2>/dev/null || echo 0) lines"
155
+ # Also show instinct count
156
+ instinct_count=$(find "$INSTINCTS_DIR" -name "*.yaml" 2>/dev/null | wc -l)
157
+ echo "Instincts: $instinct_count"
158
+ exit 0
159
+ else
160
+ echo "Observer not running (stale PID file)"
161
+ rm -f "$PID_FILE"
162
+ exit 1
163
+ fi
164
+ else
165
+ echo "Observer not running"
166
+ exit 1
167
+ fi
168
+ ;;
169
+
170
+ start)
171
+ # Check if observer is disabled in config
172
+ if [ "$OBSERVER_ENABLED" != "true" ]; then
173
+ echo "Observer is disabled in config.json (observer.enabled: false)."
174
+ echo "Set observer.enabled to true in config.json to enable."
175
+ exit 1
176
+ fi
177
+
178
+ # Check if already running
179
+ if [ -f "$PID_FILE" ]; then
180
+ pid=$(cat "$PID_FILE")
181
+ if kill -0 "$pid" 2>/dev/null; then
182
+ echo "Observer already running for ${PROJECT_NAME} (PID: $pid)"
183
+ exit 0
184
+ fi
185
+ rm -f "$PID_FILE"
186
+ fi
187
+
188
+ echo "Starting observer agent for ${PROJECT_NAME}..."
189
+
190
+ if [ ! -x "$OBSERVER_LOOP_SCRIPT" ]; then
191
+ echo "Observer loop script not found or not executable: $OBSERVER_LOOP_SCRIPT"
192
+ exit 1
193
+ fi
194
+
195
+ mkdir -p "$PROJECT_DIR"
196
+ touch "$LOG_FILE"
197
+ start_line=$(wc -l < "$LOG_FILE" 2>/dev/null || echo 0)
198
+
199
+ nohup env \
200
+ CONFIG_DIR="$CONFIG_DIR" \
201
+ PID_FILE="$PID_FILE" \
202
+ LOG_FILE="$LOG_FILE" \
203
+ OBSERVATIONS_FILE="$OBSERVATIONS_FILE" \
204
+ INSTINCTS_DIR="$INSTINCTS_DIR" \
205
+ PROJECT_DIR="$PROJECT_DIR" \
206
+ PROJECT_NAME="$PROJECT_NAME" \
207
+ PROJECT_ID="$PROJECT_ID" \
208
+ MIN_OBSERVATIONS="$MIN_OBSERVATIONS" \
209
+ OBSERVER_INTERVAL_SECONDS="$OBSERVER_INTERVAL_SECONDS" \
210
+ CLV2_IS_WINDOWS="$IS_WINDOWS" \
211
+ CLV2_OBSERVER_PROMPT_PATTERN="$CLV2_OBSERVER_PROMPT_PATTERN" \
212
+ "$OBSERVER_LOOP_SCRIPT" >> "$LOG_FILE" 2>&1 &
213
+
214
+ # Wait for PID file
215
+ sleep 2
216
+
217
+ # Check for confirmation-seeking output in the observer log
218
+ if tail -n +"$((start_line + 1))" "$LOG_FILE" 2>/dev/null | grep -E -i -q "$CLV2_OBSERVER_PROMPT_PATTERN"; then
219
+ echo "OBSERVER_ABORT: Confirmation or permission prompt detected in observer output. Failing closed."
220
+ stop_observer_if_running >/dev/null 2>&1 || true
221
+ write_guard_sentinel
222
+ exit 2
223
+ fi
224
+
225
+ if [ -f "$PID_FILE" ]; then
226
+ pid=$(cat "$PID_FILE")
227
+ if kill -0 "$pid" 2>/dev/null; then
228
+ echo "Observer started (PID: $pid)"
229
+ echo "Log: $LOG_FILE"
230
+ else
231
+ echo "Failed to start observer (process died immediately, check $LOG_FILE)"
232
+ exit 1
233
+ fi
234
+ else
235
+ echo "Failed to start observer"
236
+ exit 1
237
+ fi
238
+ ;;
239
+
240
+ *)
241
+ echo "Usage: $0 [start|stop|status] [--reset]"
242
+ exit 1
243
+ ;;
244
+ esac
@@ -0,0 +1,8 @@
1
+ {
2
+ "version": "2.1",
3
+ "observer": {
4
+ "enabled": false,
5
+ "run_interval_minutes": 5,
6
+ "min_observations_to_analyze": 20
7
+ }
8
+ }
@@ -0,0 +1,428 @@
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
+ # If cwd is a subdirectory inside a git repo, resolve it to the repo root so
61
+ # observations attach to the project instead of a nested path.
62
+ STDIN_CWD=$(echo "$INPUT_JSON" | "$PYTHON_CMD" -c '
63
+ import json, sys
64
+ try:
65
+ data = json.load(sys.stdin)
66
+ cwd = data.get("cwd", "")
67
+ print(cwd)
68
+ except(KeyError, TypeError, ValueError):
69
+ print("")
70
+ ' 2>/dev/null || echo "")
71
+
72
+ # If cwd was provided in stdin, use it for project detection
73
+ if [ -n "$STDIN_CWD" ] && [ -d "$STDIN_CWD" ]; then
74
+ _GIT_ROOT=$(git -C "$STDIN_CWD" rev-parse --show-toplevel 2>/dev/null || true)
75
+ export CLAUDE_PROJECT_DIR="${_GIT_ROOT:-$STDIN_CWD}"
76
+ fi
77
+
78
+ # ─────────────────────────────────────────────
79
+ # Lightweight config and automated session guards
80
+ # ─────────────────────────────────────────────
81
+ #
82
+ # IMPORTANT: keep these guards above detect-project.sh.
83
+ # Sourcing detect-project.sh creates project-scoped directories and updates
84
+ # projects.json, so automated sessions must return before that point.
85
+
86
+ CONFIG_DIR="${HOME}/.claude/homunculus"
87
+
88
+ # Skip if disabled (check both default and CLV2_CONFIG-derived locations)
89
+ if [ -f "$CONFIG_DIR/disabled" ]; then
90
+ exit 0
91
+ fi
92
+ if [ -n "${CLV2_CONFIG:-}" ] && [ -f "$(dirname "$CLV2_CONFIG")/disabled" ]; then
93
+ exit 0
94
+ fi
95
+
96
+ # Prevent observe.sh from firing on non-human sessions to avoid:
97
+ # - ECC observing its own Haiku observer sessions (self-loop)
98
+ # - ECC observing other tools' automated sessions
99
+ # - automated sessions creating project-scoped homunculus metadata
100
+
101
+ # Layer 1: entrypoint. Only interactive terminal sessions should continue.
102
+ # sdk-ts: Agent SDK sessions can be human-interactive (e.g. via Happy).
103
+ # Non-interactive SDK automation is still filtered by Layers 2-5 below
104
+ # (ECC_HOOK_PROFILE=minimal, ECC_SKIP_OBSERVE=1, agent_id, path exclusions).
105
+ case "${CLAUDE_CODE_ENTRYPOINT:-cli}" in
106
+ cli|sdk-ts) ;;
107
+ *) exit 0 ;;
108
+ esac
109
+
110
+ # Layer 2: minimal hook profile suppresses non-essential hooks.
111
+ [ "${ECC_HOOK_PROFILE:-standard}" = "minimal" ] && exit 0
112
+
113
+ # Layer 3: cooperative skip env var for automated sessions.
114
+ [ "${ECC_SKIP_OBSERVE:-0}" = "1" ] && exit 0
115
+
116
+ # Layer 4: subagent sessions are automated by definition.
117
+ _ECC_AGENT_ID=$(echo "$INPUT_JSON" | "$PYTHON_CMD" -c "import json,sys; print(json.load(sys.stdin).get('agent_id',''))" 2>/dev/null || true)
118
+ [ -n "$_ECC_AGENT_ID" ] && exit 0
119
+
120
+ # Layer 5: known observer-session path exclusions.
121
+ _ECC_SKIP_PATHS="${ECC_OBSERVE_SKIP_PATHS:-observer-sessions,.claude-mem}"
122
+ if [ -n "$STDIN_CWD" ]; then
123
+ IFS=',' read -ra _ECC_SKIP_ARRAY <<< "$_ECC_SKIP_PATHS"
124
+ for _pattern in "${_ECC_SKIP_ARRAY[@]}"; do
125
+ _pattern="${_pattern#"${_pattern%%[![:space:]]*}"}"
126
+ _pattern="${_pattern%"${_pattern##*[![:space:]]}"}"
127
+ [ -z "$_pattern" ] && continue
128
+ case "$STDIN_CWD" in *"$_pattern"*) exit 0 ;; esac
129
+ done
130
+ fi
131
+
132
+ # ─────────────────────────────────────────────
133
+ # Project detection
134
+ # ─────────────────────────────────────────────
135
+
136
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
137
+ SKILL_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
138
+
139
+ # Source shared project detection helper
140
+ # This sets: PROJECT_ID, PROJECT_NAME, PROJECT_ROOT, PROJECT_DIR
141
+ source "${SKILL_ROOT}/scripts/detect-project.sh"
142
+ PYTHON_CMD="${CLV2_PYTHON_CMD:-$PYTHON_CMD}"
143
+
144
+ # ─────────────────────────────────────────────
145
+ # Configuration
146
+ # ─────────────────────────────────────────────
147
+
148
+ OBSERVATIONS_FILE="${PROJECT_DIR}/observations.jsonl"
149
+ MAX_FILE_SIZE_MB=10
150
+
151
+ # Auto-purge observation files older than 30 days (runs once per session)
152
+ PURGE_MARKER="${PROJECT_DIR}/.last-purge"
153
+ if [ ! -f "$PURGE_MARKER" ] || [ "$(find "$PURGE_MARKER" -mtime +1 2>/dev/null)" ]; then
154
+ find "${PROJECT_DIR}" -name "observations-*.jsonl" -mtime +30 -delete 2>/dev/null || true
155
+ touch "$PURGE_MARKER" 2>/dev/null || true
156
+ fi
157
+
158
+ # Parse using Python via stdin pipe (safe for all JSON payloads)
159
+ # Pass HOOK_PHASE via env var since Claude Code does not include hook type in stdin JSON
160
+ PARSED=$(echo "$INPUT_JSON" | HOOK_PHASE="$HOOK_PHASE" "$PYTHON_CMD" -c '
161
+ import json
162
+ import sys
163
+ import os
164
+
165
+ try:
166
+ data = json.load(sys.stdin)
167
+
168
+ # Determine event type from CLI argument passed via env var.
169
+ # Claude Code does NOT include a "hook_type" field in the stdin JSON,
170
+ # so we rely on the shell argument ("pre" or "post") instead.
171
+ hook_phase = os.environ.get("HOOK_PHASE", "post")
172
+ event = "tool_start" if hook_phase == "pre" else "tool_complete"
173
+
174
+ # Extract fields - Claude Code hook format
175
+ tool_name = data.get("tool_name", data.get("tool", "unknown"))
176
+ tool_input = data.get("tool_input", data.get("input", {}))
177
+ tool_output = data.get("tool_response")
178
+ if tool_output is None:
179
+ tool_output = data.get("tool_output", data.get("output", ""))
180
+ session_id = data.get("session_id", "unknown")
181
+ tool_use_id = data.get("tool_use_id", "")
182
+ cwd = data.get("cwd", "")
183
+
184
+ # Truncate large inputs/outputs
185
+ if isinstance(tool_input, dict):
186
+ tool_input_str = json.dumps(tool_input)[:5000]
187
+ else:
188
+ tool_input_str = str(tool_input)[:5000]
189
+
190
+ if isinstance(tool_output, dict):
191
+ tool_response_str = json.dumps(tool_output)[:5000]
192
+ else:
193
+ tool_response_str = str(tool_output)[:5000]
194
+
195
+ print(json.dumps({
196
+ "parsed": True,
197
+ "event": event,
198
+ "tool": tool_name,
199
+ "input": tool_input_str if event == "tool_start" else None,
200
+ "output": tool_response_str if event == "tool_complete" else None,
201
+ "session": session_id,
202
+ "tool_use_id": tool_use_id,
203
+ "cwd": cwd
204
+ }))
205
+ except Exception as e:
206
+ print(json.dumps({"parsed": False, "error": str(e)}))
207
+ ')
208
+
209
+ # Check if parsing succeeded
210
+ PARSED_OK=$(echo "$PARSED" | "$PYTHON_CMD" -c "import json,sys; print(json.load(sys.stdin).get('parsed', False))" 2>/dev/null || echo "False")
211
+
212
+ if [ "$PARSED_OK" != "True" ]; then
213
+ # Fallback: log raw input for debugging (scrub secrets before persisting)
214
+ timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
215
+ export TIMESTAMP="$timestamp"
216
+ echo "$INPUT_JSON" | "$PYTHON_CMD" -c '
217
+ import json, sys, os, re
218
+
219
+ _SECRET_RE = re.compile(
220
+ r"(?i)(api[_-]?key|token|secret|password|authorization|credentials?|auth)"
221
+ r"""(["'"'"'\s:=]+)"""
222
+ r"([A-Za-z]+\s+)?"
223
+ r"([A-Za-z0-9_\-/.+=]{8,})"
224
+ )
225
+
226
+ raw = sys.stdin.read()[:2000]
227
+ raw = _SECRET_RE.sub(lambda m: m.group(1) + m.group(2) + (m.group(3) or "") + "[REDACTED]", raw)
228
+ print(json.dumps({"timestamp": os.environ["TIMESTAMP"], "event": "parse_error", "raw": raw}))
229
+ ' >> "$OBSERVATIONS_FILE"
230
+ exit 0
231
+ fi
232
+
233
+ # Archive if file too large (atomic: rename with unique suffix to avoid race)
234
+ if [ -f "$OBSERVATIONS_FILE" ]; then
235
+ file_size_mb=$(du -m "$OBSERVATIONS_FILE" 2>/dev/null | cut -f1)
236
+ if [ "${file_size_mb:-0}" -ge "$MAX_FILE_SIZE_MB" ]; then
237
+ archive_dir="${PROJECT_DIR}/observations.archive"
238
+ mkdir -p "$archive_dir"
239
+ mv "$OBSERVATIONS_FILE" "$archive_dir/observations-$(date +%Y%m%d-%H%M%S)-$$.jsonl" 2>/dev/null || true
240
+ fi
241
+ fi
242
+
243
+ # Build and write observation (now includes project context)
244
+ # Scrub common secret patterns from tool I/O before persisting
245
+ timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
246
+
247
+ export PROJECT_ID_ENV="$PROJECT_ID"
248
+ export PROJECT_NAME_ENV="$PROJECT_NAME"
249
+ export TIMESTAMP="$timestamp"
250
+
251
+ echo "$PARSED" | "$PYTHON_CMD" -c '
252
+ import json, sys, os, re
253
+
254
+ parsed = json.load(sys.stdin)
255
+ observation = {
256
+ "timestamp": os.environ["TIMESTAMP"],
257
+ "event": parsed["event"],
258
+ "tool": parsed["tool"],
259
+ "session": parsed["session"],
260
+ "project_id": os.environ.get("PROJECT_ID_ENV", "global"),
261
+ "project_name": os.environ.get("PROJECT_NAME_ENV", "global")
262
+ }
263
+
264
+ # Scrub secrets: match common key=value, key: value, and key"value patterns
265
+ # Includes optional auth scheme (e.g., "Bearer", "Basic") before token
266
+ _SECRET_RE = re.compile(
267
+ r"(?i)(api[_-]?key|token|secret|password|authorization|credentials?|auth)"
268
+ r"""(["'"'"'\s:=]+)"""
269
+ r"([A-Za-z]+\s+)?"
270
+ r"([A-Za-z0-9_\-/.+=]{8,})"
271
+ )
272
+
273
+ def scrub(val):
274
+ if val is None:
275
+ return None
276
+ return _SECRET_RE.sub(lambda m: m.group(1) + m.group(2) + (m.group(3) or "") + "[REDACTED]", str(val))
277
+
278
+ if parsed["input"]:
279
+ observation["input"] = scrub(parsed["input"])
280
+ if parsed["output"] is not None:
281
+ observation["output"] = scrub(parsed["output"])
282
+
283
+ print(json.dumps(observation))
284
+ ' >> "$OBSERVATIONS_FILE"
285
+
286
+ # Lazy-start observer if enabled but not running (first-time setup)
287
+ # Use flock for atomic check-then-act to prevent race conditions
288
+ # Fallback for macOS (no flock): use lockfile or skip
289
+ LAZY_START_LOCK="${PROJECT_DIR}/.observer-start.lock"
290
+ _CHECK_OBSERVER_RUNNING() {
291
+ local pid_file="$1"
292
+ if [ -f "$pid_file" ]; then
293
+ local pid
294
+ pid=$(cat "$pid_file" 2>/dev/null)
295
+ # Validate PID is a positive integer (>1) to prevent signaling invalid targets
296
+ case "$pid" in
297
+ ''|*[!0-9]*|0|1)
298
+ rm -f "$pid_file" 2>/dev/null || true
299
+ return 1
300
+ ;;
301
+ esac
302
+ if kill -0 "$pid" 2>/dev/null; then
303
+ return 0 # Process is alive
304
+ fi
305
+ # Stale PID file - remove it
306
+ rm -f "$pid_file" 2>/dev/null || true
307
+ fi
308
+ return 1 # No PID file or process dead
309
+ }
310
+
311
+ if [ -f "${CONFIG_DIR}/disabled" ]; then
312
+ OBSERVER_ENABLED=false
313
+ else
314
+ OBSERVER_ENABLED=false
315
+ CONFIG_FILE="${SKILL_ROOT}/config.json"
316
+ # Allow CLV2_CONFIG override
317
+ if [ -n "${CLV2_CONFIG:-}" ]; then
318
+ CONFIG_FILE="$CLV2_CONFIG"
319
+ fi
320
+ # Use effective config path for both existence check and reading
321
+ EFFECTIVE_CONFIG="$CONFIG_FILE"
322
+ if [ -f "$EFFECTIVE_CONFIG" ] && [ -n "$PYTHON_CMD" ]; then
323
+ _enabled=$(CLV2_CONFIG_PATH="$EFFECTIVE_CONFIG" "$PYTHON_CMD" -c "
324
+ import json, os
325
+ with open(os.environ['CLV2_CONFIG_PATH']) as f:
326
+ cfg = json.load(f)
327
+ print(str(cfg.get('observer', {}).get('enabled', False)).lower())
328
+ " 2>/dev/null || echo "false")
329
+ if [ "$_enabled" = "true" ]; then
330
+ OBSERVER_ENABLED=true
331
+ fi
332
+ fi
333
+ fi
334
+
335
+ # Check both project-scoped AND global PID files (with stale PID recovery)
336
+ if [ "$OBSERVER_ENABLED" = "true" ]; then
337
+ # Clean up stale PID files first
338
+ _CHECK_OBSERVER_RUNNING "${PROJECT_DIR}/.observer.pid" || true
339
+ _CHECK_OBSERVER_RUNNING "${CONFIG_DIR}/.observer.pid" || true
340
+
341
+ # Check if observer is now running after cleanup
342
+ if [ ! -f "${PROJECT_DIR}/.observer.pid" ] && [ ! -f "${CONFIG_DIR}/.observer.pid" ]; then
343
+ # Use flock if available (Linux), fallback for macOS
344
+ if command -v flock >/dev/null 2>&1; then
345
+ (
346
+ flock -n 9 || exit 0
347
+ # Double-check PID files after acquiring lock
348
+ _CHECK_OBSERVER_RUNNING "${PROJECT_DIR}/.observer.pid" || true
349
+ _CHECK_OBSERVER_RUNNING "${CONFIG_DIR}/.observer.pid" || true
350
+ if [ ! -f "${PROJECT_DIR}/.observer.pid" ] && [ ! -f "${CONFIG_DIR}/.observer.pid" ]; then
351
+ nohup "${SKILL_ROOT}/agents/start-observer.sh" start >/dev/null 2>&1 &
352
+ fi
353
+ ) 9>"$LAZY_START_LOCK"
354
+ else
355
+ # macOS fallback: use lockfile if available, otherwise mkdir-based lock
356
+ if command -v lockfile >/dev/null 2>&1; then
357
+ # Use subshell to isolate exit and add trap for cleanup
358
+ (
359
+ trap 'rm -f "$LAZY_START_LOCK" 2>/dev/null || true' EXIT
360
+ lockfile -r 1 -l 30 "$LAZY_START_LOCK" 2>/dev/null || exit 0
361
+ _CHECK_OBSERVER_RUNNING "${PROJECT_DIR}/.observer.pid" || true
362
+ _CHECK_OBSERVER_RUNNING "${CONFIG_DIR}/.observer.pid" || true
363
+ if [ ! -f "${PROJECT_DIR}/.observer.pid" ] && [ ! -f "${CONFIG_DIR}/.observer.pid" ]; then
364
+ nohup "${SKILL_ROOT}/agents/start-observer.sh" start >/dev/null 2>&1 &
365
+ fi
366
+ rm -f "$LAZY_START_LOCK" 2>/dev/null || true
367
+ )
368
+ else
369
+ # POSIX fallback: mkdir is atomic -- fails if dir already exists
370
+ (
371
+ trap 'rmdir "${LAZY_START_LOCK}.d" 2>/dev/null || true' EXIT
372
+ mkdir "${LAZY_START_LOCK}.d" 2>/dev/null || exit 0
373
+ _CHECK_OBSERVER_RUNNING "${PROJECT_DIR}/.observer.pid" || true
374
+ _CHECK_OBSERVER_RUNNING "${CONFIG_DIR}/.observer.pid" || true
375
+ if [ ! -f "${PROJECT_DIR}/.observer.pid" ] && [ ! -f "${CONFIG_DIR}/.observer.pid" ]; then
376
+ nohup "${SKILL_ROOT}/agents/start-observer.sh" start >/dev/null 2>&1 &
377
+ fi
378
+ )
379
+ fi
380
+ fi
381
+ fi
382
+ fi
383
+
384
+ # Throttle SIGUSR1: only signal observer every N observations (#521)
385
+ # This prevents rapid signaling when tool calls fire every second,
386
+ # which caused runaway parallel Claude analysis processes.
387
+ SIGNAL_EVERY_N="${ECC_OBSERVER_SIGNAL_EVERY_N:-20}"
388
+ SIGNAL_COUNTER_FILE="${PROJECT_DIR}/.observer-signal-counter"
389
+ ACTIVITY_FILE="${PROJECT_DIR}/.observer-last-activity"
390
+
391
+ touch "$ACTIVITY_FILE" 2>/dev/null || true
392
+
393
+ should_signal=0
394
+ if [ -f "$SIGNAL_COUNTER_FILE" ]; then
395
+ counter=$(cat "$SIGNAL_COUNTER_FILE" 2>/dev/null || echo 0)
396
+ counter=$((counter + 1))
397
+ if [ "$counter" -ge "$SIGNAL_EVERY_N" ]; then
398
+ should_signal=1
399
+ counter=0
400
+ fi
401
+ echo "$counter" > "$SIGNAL_COUNTER_FILE"
402
+ else
403
+ echo "1" > "$SIGNAL_COUNTER_FILE"
404
+ fi
405
+
406
+ # Signal observer if running and throttle allows (check both project-scoped and global observer, deduplicate)
407
+ if [ "$should_signal" -eq 1 ]; then
408
+ signaled_pids=" "
409
+ for pid_file in "${PROJECT_DIR}/.observer.pid" "${CONFIG_DIR}/.observer.pid"; do
410
+ if [ -f "$pid_file" ]; then
411
+ observer_pid=$(cat "$pid_file" 2>/dev/null || true)
412
+ # Validate PID is a positive integer (>1)
413
+ case "$observer_pid" in
414
+ ''|*[!0-9]*|0|1) rm -f "$pid_file" 2>/dev/null || true; continue ;;
415
+ esac
416
+ # Deduplicate: skip if already signaled this pass
417
+ case "$signaled_pids" in
418
+ *" $observer_pid "*) continue ;;
419
+ esac
420
+ if kill -0 "$observer_pid" 2>/dev/null; then
421
+ kill -USR1 "$observer_pid" 2>/dev/null || true
422
+ signaled_pids="${signaled_pids}${observer_pid} "
423
+ fi
424
+ fi
425
+ done
426
+ fi
427
+
428
+ exit 0