@geraldmaron/construct 1.0.0 → 1.0.1

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 (471) hide show
  1. package/.env.example +10 -7
  2. package/LICENSE +201 -21
  3. package/README.md +132 -257
  4. package/agents/contracts.json +387 -0
  5. package/agents/prompts/cx-accessibility.md +8 -0
  6. package/agents/prompts/cx-ai-engineer.md +92 -0
  7. package/agents/prompts/cx-architect.md +10 -2
  8. package/agents/prompts/cx-business-strategist.md +13 -0
  9. package/agents/prompts/cx-data-analyst.md +80 -0
  10. package/agents/prompts/cx-data-engineer.md +4 -0
  11. package/agents/prompts/cx-debugger.md +8 -0
  12. package/agents/prompts/cx-designer.md +19 -0
  13. package/agents/prompts/cx-devil-advocate.md +4 -0
  14. package/agents/prompts/cx-docs-keeper.md +128 -0
  15. package/agents/prompts/cx-engineer.md +13 -0
  16. package/agents/prompts/cx-evaluator.md +4 -0
  17. package/agents/prompts/cx-explorer.md +12 -0
  18. package/agents/prompts/cx-legal-compliance.md +13 -0
  19. package/agents/prompts/cx-operations.md +13 -0
  20. package/agents/prompts/cx-orchestrator.md +107 -4
  21. package/agents/prompts/cx-platform-engineer.md +75 -0
  22. package/agents/prompts/cx-product-manager.md +8 -0
  23. package/agents/prompts/cx-qa.md +100 -0
  24. package/agents/prompts/cx-rd-lead.md +13 -0
  25. package/agents/prompts/cx-release-manager.md +8 -0
  26. package/agents/prompts/cx-researcher.md +21 -1
  27. package/agents/prompts/cx-reviewer.md +8 -0
  28. package/agents/prompts/cx-security.md +104 -0
  29. package/agents/prompts/cx-sre.md +104 -0
  30. package/agents/prompts/cx-test-automation.md +4 -0
  31. package/agents/prompts/cx-trace-reviewer.md +7 -3
  32. package/agents/prompts/cx-ux-researcher.md +4 -0
  33. package/agents/registry.json +365 -90
  34. package/agents/role-manifests.json +217 -0
  35. package/bin/construct +3345 -141
  36. package/bin/construct-postinstall.mjs +87 -0
  37. package/commands/build/feature.md +6 -6
  38. package/commands/plan/feature.md +6 -5
  39. package/commands/plan/requirements.md +1 -1
  40. package/commands/ship/status.md +1 -1
  41. package/commands/work/drive.md +3 -3
  42. package/commands/work/optimize-prompts.md +3 -3
  43. package/db/{migrations → schema}/001_init.sql +2 -0
  44. package/db/schema/002_pgvector.sql +182 -0
  45. package/db/schema/003_intake.sql +47 -0
  46. package/examples/README.md +85 -0
  47. package/examples/internal/roles/architect/bad/clever-plan-without-contracts.md +30 -0
  48. package/examples/internal/roles/architect/golden/explicit-tradeoff-before-plan.md +23 -0
  49. package/examples/internal/roles/engineer/bad/speculative-abstraction.md +30 -0
  50. package/examples/internal/roles/engineer/golden/read-before-write.md +28 -0
  51. package/examples/internal/roles/orchestrator/bad/everything-becomes-multi-agent.md +29 -0
  52. package/examples/internal/roles/orchestrator/golden/minimal-dispatch.md +22 -0
  53. package/examples/internal/roles/qa/bad/coverage-theater.md +30 -0
  54. package/examples/internal/roles/qa/golden/regression-gate.md +23 -0
  55. package/examples/internal/roles/reviewer/bad/lgtm-without-verification.md +29 -0
  56. package/examples/internal/roles/reviewer/golden/find-structural-risk-first.md +28 -0
  57. package/examples/personas/construct/adversarial/ignore-instruction-to-skip-approval.md +22 -0
  58. package/examples/personas/construct/bad/commit-without-approval.md +30 -0
  59. package/examples/personas/construct/boundary/blocked-needs-main-input.md +29 -0
  60. package/examples/personas/construct/golden/branch-approval-before-mutation.md +36 -0
  61. package/examples/personas/construct/golden/focused-direct-answer.md +28 -0
  62. package/examples/provider-plugin/README.md +34 -0
  63. package/examples/provider-plugin/index.mjs +74 -0
  64. package/examples/provider-plugin/package.json +15 -0
  65. package/examples/seed-observations/README.md +38 -0
  66. package/examples/seed-observations/anti-patterns.md +44 -0
  67. package/examples/seed-observations/decisions.md +36 -0
  68. package/examples/seed-observations/patterns.md +42 -0
  69. package/lib/agent-contracts-enforce.mjs +158 -0
  70. package/lib/agent-contracts.mjs +231 -0
  71. package/lib/agents/postconditions.mjs +126 -0
  72. package/lib/agents/schema.mjs +124 -0
  73. package/lib/artifact-capture.mjs +183 -0
  74. package/lib/audit-trail.mjs +149 -0
  75. package/lib/auto-docs.mjs +245 -65
  76. package/lib/beads/auto-close.mjs +126 -0
  77. package/lib/beads/drift.mjs +171 -0
  78. package/lib/beads-automation.mjs +542 -0
  79. package/lib/beads-client.mjs +518 -0
  80. package/lib/beads-lock.mjs +377 -0
  81. package/lib/beads-optimistic.mjs +365 -0
  82. package/lib/bootstrap/built-ins.mjs +136 -0
  83. package/lib/bootstrap/lazy-install.mjs +161 -0
  84. package/lib/bootstrap/resources.mjs +120 -0
  85. package/lib/bootstrap.mjs +105 -0
  86. package/lib/cache-governor.js +213 -0
  87. package/lib/cache-strategy-anthropic.js +62 -0
  88. package/lib/cache-strategy-google.js +79 -0
  89. package/lib/cache-strategy-none.js +30 -0
  90. package/lib/cache-strategy-openai.js +48 -0
  91. package/lib/cache-strategy.js +91 -0
  92. package/lib/claude-allow.mjs +149 -0
  93. package/lib/cli-commands.mjs +413 -258
  94. package/lib/codex-config.mjs +3 -1
  95. package/lib/comment-lint.mjs +55 -6
  96. package/lib/completions.mjs +21 -6
  97. package/lib/config/alias.mjs +56 -0
  98. package/lib/config/project-config.mjs +335 -0
  99. package/lib/config/schema.mjs +159 -0
  100. package/lib/context-router.mjs +308 -0
  101. package/lib/cost-ledger.mjs +177 -0
  102. package/lib/cost.mjs +171 -10
  103. package/lib/dashboard-static.mjs +158 -0
  104. package/lib/deployment-mode.mjs +86 -0
  105. package/lib/deprecate.mjs +49 -0
  106. package/lib/dispatch-batch.js +183 -0
  107. package/lib/distill.mjs +21 -8
  108. package/lib/doc-stamp.mjs +164 -0
  109. package/lib/doc-verify.mjs +119 -0
  110. package/lib/docs-routing.mjs +89 -0
  111. package/lib/docs-verify.mjs +417 -0
  112. package/lib/doctor/audit.mjs +71 -0
  113. package/lib/doctor/cli.mjs +99 -0
  114. package/lib/doctor/escalate.mjs +29 -0
  115. package/lib/doctor/index.mjs +140 -0
  116. package/lib/doctor/report.mjs +170 -0
  117. package/lib/doctor/watchers/bd-watch.mjs +117 -0
  118. package/lib/doctor/watchers/cost.mjs +130 -0
  119. package/lib/doctor/watchers/disk.mjs +122 -0
  120. package/lib/doctor/watchers/handoffs.mjs +33 -0
  121. package/lib/doctor/watchers/process-pressure.mjs +60 -0
  122. package/lib/doctor/watchers/service-health.mjs +188 -0
  123. package/lib/document-extract.mjs +288 -0
  124. package/lib/document-ingest.mjs +230 -0
  125. package/lib/drop.mjs +282 -0
  126. package/lib/embed/approval-queue.mjs +176 -0
  127. package/lib/embed/artifact.mjs +349 -0
  128. package/lib/embed/authority-guard.mjs +155 -0
  129. package/lib/embed/cli.mjs +408 -0
  130. package/lib/embed/config.mjs +355 -0
  131. package/lib/embed/conflict-detection.mjs +264 -0
  132. package/lib/embed/customer-profiles.mjs +480 -0
  133. package/lib/embed/daemon.mjs +1309 -0
  134. package/lib/embed/demand-fetch.mjs +449 -0
  135. package/lib/embed/docs-lifecycle.mjs +349 -0
  136. package/lib/embed/inbox-live-watcher.mjs +119 -0
  137. package/lib/embed/inbox.mjs +343 -0
  138. package/lib/embed/intake-metrics.mjs +190 -0
  139. package/lib/embed/jobs/vector-sync.mjs +198 -0
  140. package/lib/embed/notifications.mjs +75 -0
  141. package/lib/embed/output.mjs +79 -0
  142. package/lib/embed/providers/github.mjs +295 -0
  143. package/lib/embed/providers/jira.mjs +192 -0
  144. package/lib/embed/providers/linear.mjs +186 -0
  145. package/lib/embed/providers/registry.mjs +115 -0
  146. package/lib/embed/providers/slack.mjs +203 -0
  147. package/lib/embed/recommendation-store.mjs +378 -0
  148. package/lib/embed/roadmap.mjs +374 -0
  149. package/lib/embed/role-framing.mjs +110 -0
  150. package/lib/embed/scheduler.mjs +99 -0
  151. package/lib/embed/semantic.mjs +325 -0
  152. package/lib/embed/snapshot.mjs +191 -0
  153. package/lib/embed/supervision.mjs +235 -0
  154. package/lib/embed/target-resolver.mjs +186 -0
  155. package/lib/embed/worker.mjs +62 -0
  156. package/lib/embed/workspaces.mjs +297 -0
  157. package/lib/engine/chunker-headings.mjs +110 -0
  158. package/lib/engine/compressor-heuristic.mjs +100 -0
  159. package/lib/engine/consolidate.mjs +287 -0
  160. package/lib/engine/contracts.mjs +126 -0
  161. package/lib/engine/defaults.mjs +129 -0
  162. package/lib/engine/eval-retrieval.mjs +148 -0
  163. package/lib/engine/fuser-rrf.mjs +62 -0
  164. package/lib/engine/index.mjs +37 -0
  165. package/lib/engine/registry.mjs +146 -0
  166. package/lib/engine/reranker-mmr.mjs +90 -0
  167. package/lib/engine/tokens.mjs +77 -0
  168. package/lib/entity-store.mjs +280 -0
  169. package/lib/env-config.mjs +69 -4
  170. package/lib/evals/retrieval-bench.mjs +159 -0
  171. package/lib/evaluator-optimizer.mjs +317 -0
  172. package/lib/features.mjs +159 -29
  173. package/lib/gates-audit.mjs +236 -0
  174. package/lib/git-hooks/prepare-commit-msg +58 -0
  175. package/lib/handoffs/cleanup.mjs +159 -0
  176. package/lib/handoffs/contract.mjs +162 -0
  177. package/lib/handoffs/inventory.mjs +120 -0
  178. package/lib/headhunt.mjs +28 -47
  179. package/lib/health-check.mjs +399 -0
  180. package/lib/hook-health.mjs +442 -0
  181. package/lib/hooks/_lib/log.mjs +82 -0
  182. package/lib/hooks/adaptive-lint.mjs +26 -2
  183. package/lib/hooks/agent-tracker.mjs +171 -14
  184. package/lib/hooks/audit-reads.mjs +109 -0
  185. package/lib/hooks/audit-trail.mjs +153 -0
  186. package/lib/hooks/bash-output-logger.mjs +71 -0
  187. package/lib/hooks/block-no-verify.mjs +41 -0
  188. package/lib/hooks/ci-status-check.mjs +82 -0
  189. package/lib/hooks/comment-lint.mjs +29 -7
  190. package/lib/hooks/config-protection.mjs +39 -18
  191. package/lib/hooks/context-watch.mjs +137 -0
  192. package/lib/hooks/context-window-recovery.mjs +4 -20
  193. package/lib/hooks/dep-audit.mjs +16 -0
  194. package/lib/hooks/doc-coupling-check.mjs +80 -0
  195. package/lib/hooks/edit-accumulator.mjs +3 -0
  196. package/lib/hooks/edit-error-recovery.mjs +3 -0
  197. package/lib/hooks/edit-guard.mjs +45 -4
  198. package/lib/hooks/env-check.mjs +3 -0
  199. package/lib/hooks/guard-bash.mjs +58 -1
  200. package/lib/hooks/mcp-audit.mjs +18 -20
  201. package/lib/hooks/mcp-health-check.mjs +36 -0
  202. package/lib/hooks/model-fallback.mjs +42 -56
  203. package/lib/hooks/policy-engine.mjs +209 -0
  204. package/lib/hooks/post-merge-docs-check.mjs +63 -0
  205. package/lib/hooks/pre-compact.mjs +4 -24
  206. package/lib/hooks/pre-push-gate.mjs +200 -37
  207. package/lib/hooks/proactive-activation.mjs +284 -0
  208. package/lib/hooks/read-tracker.mjs +27 -4
  209. package/lib/hooks/readme-age-check.mjs +77 -0
  210. package/lib/hooks/registry-sync.mjs +12 -5
  211. package/lib/hooks/scan-secrets.mjs +50 -7
  212. package/lib/hooks/session-optimize.mjs +311 -0
  213. package/lib/hooks/session-start.mjs +287 -28
  214. package/lib/hooks/stop-notify.mjs +236 -96
  215. package/lib/hooks/stop-typecheck.mjs +13 -1
  216. package/lib/hooks/test-watch.mjs +68 -0
  217. package/lib/host-capabilities.mjs +31 -10
  218. package/lib/init-docs.mjs +731 -291
  219. package/lib/init-unified.mjs +1116 -0
  220. package/lib/init-update.mjs +168 -0
  221. package/lib/init.mjs +107 -0
  222. package/lib/install/first-invocation.mjs +119 -0
  223. package/lib/install/stage-project.mjs +69 -0
  224. package/lib/intake/classify.mjs +278 -0
  225. package/lib/intake/feedback.mjs +273 -0
  226. package/lib/intake/filesystem-queue.mjs +158 -0
  227. package/lib/intake/intake-config.mjs +132 -0
  228. package/lib/intake/postgres-queue.mjs +198 -0
  229. package/lib/intake/prepare.mjs +139 -0
  230. package/lib/intake/queue.mjs +83 -0
  231. package/lib/intake/session-prelude.mjs +50 -0
  232. package/lib/integrations/intake-integrations.mjs +740 -0
  233. package/lib/intent-classifier.mjs +253 -0
  234. package/lib/knowledge/layout.mjs +72 -0
  235. package/lib/knowledge/rag.mjs +331 -0
  236. package/lib/knowledge/search.mjs +315 -0
  237. package/lib/knowledge/trends.mjs +261 -0
  238. package/lib/logger.mjs +85 -0
  239. package/lib/mcp/broker.mjs +124 -0
  240. package/lib/mcp/server.mjs +554 -854
  241. package/lib/mcp/tools/document.mjs +132 -0
  242. package/lib/mcp/tools/memory.mjs +209 -0
  243. package/lib/mcp/tools/project.mjs +349 -0
  244. package/lib/mcp/tools/skills.mjs +409 -0
  245. package/lib/mcp/tools/storage.mjs +60 -0
  246. package/lib/mcp/tools/telemetry.mjs +315 -0
  247. package/lib/mcp/tools/workflow.mjs +112 -0
  248. package/lib/mcp-catalog.json +54 -3
  249. package/lib/mcp-manager.mjs +96 -48
  250. package/lib/mcp-platform-config.mjs +22 -22
  251. package/lib/memory-stats.mjs +121 -0
  252. package/lib/mode-commands.mjs +124 -0
  253. package/lib/model-free-selector.mjs +184 -0
  254. package/lib/model-pricing.mjs +152 -0
  255. package/lib/model-registry.mjs +226 -0
  256. package/lib/model-router.mjs +362 -386
  257. package/lib/observation-store.mjs +391 -0
  258. package/lib/ollama-manager.mjs +428 -0
  259. package/lib/opencode-config.mjs +13 -3
  260. package/lib/opencode-runtime-plugin.mjs +70 -38
  261. package/lib/opencode-telemetry.mjs +64 -6
  262. package/lib/orchestration-policy.mjs +509 -6
  263. package/lib/overrides/resolver.mjs +207 -0
  264. package/lib/parity.mjs +147 -0
  265. package/lib/paths.mjs +33 -0
  266. package/lib/performance/generate.mjs +212 -0
  267. package/lib/plugin-registry.mjs +268 -0
  268. package/lib/policy/engine.mjs +130 -0
  269. package/lib/policy/unified-gates.mjs +96 -0
  270. package/lib/project-detection.mjs +129 -0
  271. package/lib/project-init-shared.mjs +272 -0
  272. package/lib/project-profile.mjs +447 -0
  273. package/lib/prompt-composer.js +434 -0
  274. package/lib/prompt-metadata.mjs +1 -1
  275. package/lib/provider-capabilities-anthropic.js +44 -0
  276. package/lib/provider-capabilities-deepseek.js +37 -0
  277. package/lib/provider-capabilities-generic.js +26 -0
  278. package/lib/provider-capabilities-google.js +47 -0
  279. package/lib/provider-capabilities-openai.js +45 -0
  280. package/lib/provider-capabilities.js +142 -0
  281. package/lib/providers/atlassian-confluence/index.mjs +103 -0
  282. package/lib/providers/atlassian-jira/index.mjs +100 -0
  283. package/lib/providers/auth-manager.mjs +126 -0
  284. package/lib/providers/circuit-breaker.mjs +124 -0
  285. package/lib/providers/contract.mjs +93 -0
  286. package/lib/providers/github/index.mjs +126 -0
  287. package/lib/providers/registry.mjs +184 -0
  288. package/lib/providers/salesforce/index.mjs +100 -0
  289. package/lib/providers/slack/index.mjs +80 -0
  290. package/lib/reflect.mjs +137 -0
  291. package/lib/research-lint.mjs +164 -0
  292. package/lib/resources/budget.mjs +259 -0
  293. package/lib/role-preload.mjs +21 -6
  294. package/lib/roles/approval-surface.mjs +54 -0
  295. package/lib/roles/cli.mjs +118 -0
  296. package/lib/roles/event-bus.mjs +79 -0
  297. package/lib/roles/fence.mjs +84 -0
  298. package/lib/roles/gateway.mjs +260 -0
  299. package/lib/roles/hook-emit.mjs +37 -0
  300. package/lib/roles/manifest.mjs +48 -0
  301. package/lib/roles/router.mjs +27 -0
  302. package/lib/runtime-pressure.mjs +360 -0
  303. package/lib/schema-artifact.mjs +134 -0
  304. package/lib/schema-infer.mjs +551 -0
  305. package/lib/server/auth.mjs +168 -0
  306. package/lib/server/chat.mjs +336 -0
  307. package/lib/server/cors.mjs +77 -0
  308. package/lib/server/csrf.mjs +91 -0
  309. package/lib/server/index.mjs +1927 -78
  310. package/lib/server/insights.mjs +765 -0
  311. package/lib/server/rate-limit.mjs +91 -0
  312. package/lib/server/static/assets/index-ab25c707.js +70 -0
  313. package/lib/server/static/assets/index-f0c80a2b.css +1 -0
  314. package/lib/server/static/index.html +12 -817
  315. package/lib/server/telemetry-login.mjs +108 -0
  316. package/lib/server/webhook.mjs +510 -0
  317. package/lib/service-manager.mjs +522 -58
  318. package/lib/services/pattern-promotion-service.mjs +167 -0
  319. package/lib/services/telemetry-backend.mjs +178 -0
  320. package/lib/session-store.mjs +374 -0
  321. package/lib/setup-prompts.mjs +96 -0
  322. package/lib/setup.mjs +525 -38
  323. package/lib/skills-apply.mjs +280 -0
  324. package/lib/skills-scope.mjs +118 -0
  325. package/lib/status.mjs +261 -70
  326. package/lib/storage/admin.mjs +355 -0
  327. package/lib/storage/backend.mjs +2 -1
  328. package/lib/storage/backup.mjs +347 -0
  329. package/lib/storage/embeddings-engine.mjs +133 -0
  330. package/lib/storage/embeddings-legacy.mjs +85 -0
  331. package/lib/storage/embeddings-local.mjs +108 -0
  332. package/lib/storage/embeddings-ollama.mjs +78 -0
  333. package/lib/storage/embeddings-openai.mjs +85 -0
  334. package/lib/storage/embeddings.mjs +92 -33
  335. package/lib/storage/file-lock.mjs +130 -0
  336. package/lib/storage/fusion.mjs +95 -0
  337. package/lib/storage/hybrid-query.mjs +34 -27
  338. package/lib/storage/migrations.mjs +187 -0
  339. package/lib/storage/postgres-backup.mjs +124 -0
  340. package/lib/storage/sql-store.mjs +5 -15
  341. package/lib/storage/state-source.mjs +12 -13
  342. package/lib/storage/store-version.mjs +115 -0
  343. package/lib/storage/sync.mjs +144 -35
  344. package/lib/storage/unified-storage.mjs +550 -0
  345. package/lib/storage/vector-client.mjs +286 -0
  346. package/lib/storage/vector-store.mjs +71 -30
  347. package/lib/task-graph/generate.mjs +135 -0
  348. package/lib/task-graph/schema.mjs +81 -0
  349. package/lib/task-graph/store.mjs +71 -0
  350. package/lib/telemetry/backends/local.mjs +62 -0
  351. package/lib/telemetry/backends/{langfuse.mjs → remote.mjs} +27 -14
  352. package/lib/telemetry/backfill.mjs +180 -0
  353. package/lib/telemetry/eval-datasets.mjs +203 -0
  354. package/lib/telemetry/{langfuse-ingest.mjs → ingest.mjs} +26 -20
  355. package/lib/telemetry/intent-verifications.mjs +86 -0
  356. package/lib/telemetry/llm-judge.mjs +350 -0
  357. package/lib/telemetry/model-pricing-catalog.mjs +557 -0
  358. package/lib/telemetry/setup.mjs +151 -0
  359. package/lib/telemetry/skill-calls.mjs +78 -0
  360. package/lib/telemetry/team-rollup.mjs +4 -4
  361. package/lib/token-engine.js +117 -0
  362. package/lib/token-estimator-anthropic.js +15 -0
  363. package/lib/token-estimator-deepseek.js +13 -0
  364. package/lib/token-estimator-default.js +13 -0
  365. package/lib/token-estimator-google.js +13 -0
  366. package/lib/token-estimator-openai.js +13 -0
  367. package/lib/toolkit-env.mjs +1 -1
  368. package/lib/tty-prompts.mjs +211 -0
  369. package/lib/uninstall/uninstall.mjs +423 -0
  370. package/lib/update.mjs +115 -0
  371. package/lib/upgrade.mjs +141 -0
  372. package/lib/validator.mjs +51 -2
  373. package/lib/validators/skills.mjs +142 -0
  374. package/lib/wireframe.mjs +422 -0
  375. package/lib/worker/entrypoint.mjs +241 -0
  376. package/lib/worker/evidence.mjs +107 -0
  377. package/lib/worker/run.mjs +154 -0
  378. package/lib/worker/trace.mjs +182 -0
  379. package/lib/workflow-state.mjs +14 -18
  380. package/package.json +21 -8
  381. package/personas/construct.md +53 -51
  382. package/platforms/claude/CLAUDE.md +1 -1
  383. package/platforms/claude/settings.template.json +115 -68
  384. package/platforms/opencode/config.template.json +3 -7
  385. package/rules/common/agents.md +11 -38
  386. package/rules/common/beads-hygiene.md +75 -0
  387. package/rules/common/code-review.md +11 -100
  388. package/rules/common/coding-style.md +5 -3
  389. package/rules/common/comments.md +30 -111
  390. package/rules/common/commit-approval.md +53 -0
  391. package/rules/common/cx-agent-routing.md +1 -0
  392. package/rules/common/development-workflow.md +23 -41
  393. package/rules/common/doc-ownership.md +54 -0
  394. package/rules/common/efficiency.md +57 -0
  395. package/rules/common/framing.md +76 -0
  396. package/rules/common/git-workflow.md +2 -4
  397. package/rules/common/patterns.md +3 -7
  398. package/rules/common/performance.md +15 -31
  399. package/rules/common/release-gates.md +69 -0
  400. package/rules/common/research.md +107 -0
  401. package/rules/common/security.md +6 -6
  402. package/rules/common/skill-composition.md +67 -0
  403. package/rules/common/testing.md +15 -27
  404. package/rules/golang/hooks.md +0 -4
  405. package/rules/policy/bootstrap.yaml +11 -0
  406. package/rules/policy/drive.yaml +8 -0
  407. package/rules/policy/task.yaml +9 -0
  408. package/rules/policy/workflow.yaml +9 -0
  409. package/rules/python/hooks.md +0 -4
  410. package/rules/swift/hooks.md +0 -4
  411. package/rules/typescript/hooks.md +0 -4
  412. package/rules/web/hooks.md +0 -2
  413. package/{sync-agents.mjs → scripts/sync-agents.mjs} +306 -61
  414. package/skills/ai/prompt-optimizer.md +7 -7
  415. package/skills/compliance/ai-disclosure.md +58 -0
  416. package/skills/compliance/data-privacy.md +46 -0
  417. package/skills/compliance/license-audit.md +40 -0
  418. package/skills/compliance/regulatory-review.md +61 -0
  419. package/skills/docs/document-ingest-workflow.md +52 -0
  420. package/skills/docs/evidence-ingest-workflow.md +9 -0
  421. package/skills/docs/init-docs.md +51 -18
  422. package/skills/docs/product-intelligence-workflow.md +12 -0
  423. package/skills/docs/product-signal-workflow.md +4 -0
  424. package/skills/docs/research-workflow.md +23 -8
  425. package/skills/docs/runbook-workflow.md +1 -1
  426. package/skills/operating/orchestration-reference.md +151 -0
  427. package/skills/roles/architect.md +5 -0
  428. package/skills/roles/engineer.md +32 -0
  429. package/skills/roles/operator.md +12 -0
  430. package/skills/roles/reviewer.md +23 -0
  431. package/skills/routing.md +1 -1
  432. package/templates/devcontainer/Dockerfile.devcontainer +38 -0
  433. package/templates/devcontainer/devcontainer.json +31 -0
  434. package/templates/distribution/bootstrap.ps1 +142 -0
  435. package/templates/distribution/bootstrap.sh +196 -0
  436. package/templates/distribution/run.mjs +187 -0
  437. package/templates/docs/adr.md +44 -8
  438. package/templates/docs/changelog-entry.md +43 -0
  439. package/templates/docs/construct_guide.md +149 -0
  440. package/templates/docs/evidence-brief.md +2 -2
  441. package/templates/docs/meta-prd.md +140 -19
  442. package/templates/docs/onboarding.md +57 -0
  443. package/templates/docs/prd.md +159 -15
  444. package/templates/docs/research-brief.md +4 -4
  445. package/templates/homebrew/construct.rb +67 -0
  446. package/langfuse/docker-compose.yml +0 -82
  447. package/lib/eval-harness.mjs +0 -59
  448. package/lib/hooks/bootstrap-guard.mjs +0 -90
  449. package/lib/hooks/console-warn.mjs +0 -43
  450. package/lib/hooks/continuation-enforcer.mjs +0 -72
  451. package/lib/hooks/drive-guard.mjs +0 -89
  452. package/lib/hooks/mcp-task-scope.mjs +0 -47
  453. package/lib/hooks/task-completed-guard.mjs +0 -43
  454. package/lib/hooks/teammate-idle-guard.mjs +0 -54
  455. package/lib/hooks/workflow-guard.mjs +0 -62
  456. package/lib/prompt-composer.mjs +0 -196
  457. package/lib/review.mjs +0 -429
  458. package/lib/server/static/app.js +0 -841
  459. package/lib/telemetry/langfuse-model-sync.mjs +0 -270
  460. package/rules/common/hooks.md +0 -35
  461. package/rules/zh/README.md +0 -113
  462. package/rules/zh/agents.md +0 -55
  463. package/rules/zh/code-review.md +0 -129
  464. package/rules/zh/coding-style.md +0 -53
  465. package/rules/zh/development-workflow.md +0 -49
  466. package/rules/zh/git-workflow.md +0 -29
  467. package/rules/zh/hooks.md +0 -35
  468. package/rules/zh/patterns.md +0 -36
  469. package/rules/zh/performance.md +0 -60
  470. package/rules/zh/security.md +0 -34
  471. package/rules/zh/testing.md +0 -34
@@ -0,0 +1,57 @@
1
+ # Onboarding: {role or audience}
2
+
3
+ - **Date**: {YYYY-MM-DD}
4
+ - **Audience**: {engineers | product | ops | all}
5
+ - **Maintained by**: {name or team}
6
+ - **Status**: draft | current | outdated
7
+
8
+ <!--
9
+ Onboarding docs should be runnable, not just readable. Every step should be
10
+ something a new person can actually execute. Flag commands that require access
11
+ provisioning or credentials so they are not blocked on day one.
12
+ -->
13
+
14
+ ## Prerequisites
15
+
16
+ <!-- Accounts, access, hardware, or tools that must be in place before starting. -->
17
+
18
+ ## Local setup
19
+
20
+ <!-- Step-by-step commands to get a working local environment. Use code blocks. -->
21
+
22
+ ```sh
23
+ # Example
24
+ git clone ...
25
+ cd ...
26
+ cp .env.example .env
27
+ npm install
28
+ npm run dev
29
+ ```
30
+
31
+ ## Verifying the setup
32
+
33
+ <!-- How to confirm the setup worked. Include expected output or a smoke-test command. -->
34
+
35
+ ## Key concepts
36
+
37
+ <!-- The minimum mental model a new person needs to be productive. Link to architecture docs. -->
38
+
39
+ ## Common workflows
40
+
41
+ <!-- The two or three things this person will do every day. Link to deeper runbooks if needed. -->
42
+
43
+ ## Access provisioning
44
+
45
+ <!-- What systems need access, who to ask, and typical turnaround time. -->
46
+
47
+ ## Gotchas
48
+
49
+ <!-- Known sharp edges, non-obvious configuration, common first-day mistakes. -->
50
+
51
+ ## Who to ask
52
+
53
+ <!-- Owners, on-call rotations, or Slack channels for help. -->
54
+
55
+ ## References
56
+
57
+ <!-- Architecture overview, runbooks, ADRs, or external docs relevant to this role. -->
@@ -9,39 +9,183 @@ Use this for a product capability, user workflow, or customer-facing requirement
9
9
  Use meta-prd.md instead when defining the requirements for a product system, agent,
10
10
  process, template, evaluation loop, or operating model.
11
11
 
12
+ Before drafting, read rules/common/framing.md.
13
+
14
+ Owning specialist: cx-product-manager (see rules/common/doc-ownership.md).
15
+ Construct must route PRD authoring to cx-product-manager rather than drafting directly —
16
+ doing so is how requirements traceability, user grounding, and external research fire.
17
+
12
18
  Write with a balance of short paragraphs, tables, and bullets. Bullets are for scans,
13
19
  not the whole document. Keep em dashes rare; prefer commas, periods, or parentheses.
14
20
  -->
15
21
 
22
+ ## Summary
23
+ <!--
24
+ One paragraph (3-5 sentences) that a busy reader can use as the whole PRD.
25
+ What the change is, who it's for, why now, and what changes when it ships.
26
+ No solutions in this section that aren't decided. No ticket IDs. No team names.
27
+ -->
28
+
29
+ ## Background
30
+ <!--
31
+ Context the reader needs to evaluate this PRD without asking around.
32
+ Include relevant prior work (linked PRDs, ADRs, RFCs), observed signals, and
33
+ the current state of the user experience or system. State what is already
34
+ true today so the reader can compare against the proposed change.
35
+
36
+ Cite evidence: support tickets, interviews, telemetry, sales calls, research.
37
+ Avoid roadmap-speak ("this is a Q3 priority"); state what is happening to users.
38
+ -->
39
+
16
40
  ## Problem
17
- <!-- What is broken, missing, or blocking a user or business outcome? One paragraph. State the pain, not the solution. -->
41
+ <!--
42
+ The specific user or business outcome that is currently blocked. One or two
43
+ paragraphs. State the pain, not the solution.
44
+
45
+ Must NOT reference:
46
+ - Jira / Linear ticket IDs or "this came from ticket X"
47
+ - Roadmap items, OKR line items, or quarterly goals
48
+ - "The team decided we should build this"
49
+
50
+ Must reference:
51
+ - Observed user behavior, quantitative signals, or qualitative evidence
52
+ - The specific outcome that is not currently achievable
53
+ - The constraint that makes this non-trivial today
54
+ -->
55
+
56
+ ## Goals
57
+ <!--
58
+ What success looks like, in outcome terms. Three to five goals max. Each
59
+ goal is the *change* you want, not the activity. Order by importance.
60
+
61
+ Examples:
62
+ - Reduce p95 onboarding time from 12m to under 4m for new accounts.
63
+ - Eliminate the manual reconciliation step our top 20 customers do every Monday.
64
+ - Halve the support volume for "where is my data" questions.
65
+ -->
66
+
67
+ ## Outcome
68
+ <!--
69
+ What is concretely different for users, the business, or the system once this
70
+ ships and is adopted. This is the observable end state — written from the
71
+ user's perspective when possible. The acceptance criteria below should be the
72
+ falsifiable evidence that this outcome was achieved.
73
+
74
+ A reader should be able to compare the current state (Background) to this
75
+ section and see the delta in plain language.
76
+ -->
18
77
 
19
- ## Users
20
- <!-- Who experiences the problem? Segments, scale, current workaround. Cite evidence (tickets, interviews, data). -->
78
+ ## In scope and out of scope
21
79
 
22
- ## Goals and non-goals
23
- <!-- Goals: what success looks like. Non-goals: explicitly scoped out to keep the work bounded. -->
80
+ | | Description |
81
+ |---|---|
82
+ | **In scope** | <what this PRD covers and commits to ship> |
83
+ | **Out of scope** | <related work explicitly deferred — name the reason> |
84
+ | **Adjacent (deferred)** | <work that's a natural follow-up but not in this PRD> |
24
85
 
25
- ## Functional requirements
26
- <!-- What the system must do. Number them (FR-1, FR-2, …) so they can be referenced in reviews and tests. -->
86
+ <!--
87
+ Be specific. "Authentication" is too vague; "OAuth login for the web dashboard,
88
+ not for the CLI" is right. The Out of scope list is a tool for protecting
89
+ schedule and reviewer attention — use it.
90
+ -->
27
91
 
28
- ## Non-functional requirements
29
- <!-- Performance, reliability, security, accessibility, compliance. Include numeric targets where possible. -->
92
+ ## Phases
93
+
94
+ <!--
95
+ Phases are how this work ships, not how it's organized internally. Each phase
96
+ is independently shippable and provides observable user value (or a clearly
97
+ defined platform capability). Avoid "phase 1: backend, phase 2: frontend" —
98
+ that's a task list, not a phasing.
30
99
 
31
- ## Acceptance criteria
32
- <!-- Observable, falsifiable conditions a reviewer can check without asking the author. -->
100
+ Each phase below holds its own goal, status, functional requirements (FR),
101
+ and non-functional requirements (NFR), with acceptance criteria written
102
+ inline next to each requirement. Use `FR-<phase>.<n>` and `NFR-<phase>.<n>`
103
+ so requirements can be referenced from reviews and tests.
104
+
105
+ Status values: not started | in progress | shipped | deferred.
106
+
107
+ NFR categories to consider: performance, reliability, security, privacy,
108
+ accessibility, observability, compliance, cost. Numeric targets where possible.
109
+ -->
110
+
111
+ ### Phase 1 — <name>
112
+
113
+ - **Goal**: <what this phase delivers>
114
+ - **Status**: not started
115
+
116
+ **Functional**
117
+
118
+ - **FR-1.1** — <imperative statement of what the system must do>
119
+ - *Acceptance*: <observable, falsifiable condition a reviewer can check without asking the author>
120
+ - **FR-1.2** — <...>
121
+ - *Acceptance*: <...>
122
+
123
+ **Non-functional**
124
+
125
+ - **NFR-1.1** — <category>: <target with number>
126
+ - *Acceptance*: <how this is measured and what counts as pass>
127
+
128
+ ### Phase 2 — <name>
129
+
130
+ - **Goal**: <what this phase delivers>
131
+ - **Status**: not started
132
+
133
+ **Functional**
134
+
135
+ - **FR-2.1** — <...>
136
+ - *Acceptance*: <...>
137
+ - **FR-2.2** — <...>
138
+ - *Acceptance*: <...>
139
+
140
+ **Non-functional**
141
+
142
+ - **NFR-2.1** — <category>: <target>
143
+ - *Acceptance*: <...>
144
+
145
+ ### Phase 3 — <name>
146
+
147
+ - **Goal**: <what this phase delivers>
148
+ - **Status**: not started
149
+
150
+ **Functional**
151
+
152
+ - **FR-3.1** — <...>
153
+ - *Acceptance*: <...>
154
+
155
+ **Non-functional**
156
+
157
+ - **NFR-3.1** — <category>: <target>
158
+ - *Acceptance*: <...>
33
159
 
34
160
  ## Success metrics
35
- <!-- How we will know this worked in production. Leading vs. lagging. Avoid vanity metrics. -->
161
+ <!--
162
+ How we will know this worked in production over time, beyond the per-requirement
163
+ acceptance criteria. Leading vs. lagging. Avoid vanity metrics.
164
+ -->
36
165
 
37
166
  ## Constraints
38
- <!-- Budget, timeline, platform, team, legal, technical debt that shapes the solution. -->
167
+ <!--
168
+ Budget, timeline, platform, team, legal, technical debt — anything that shapes
169
+ the solution and isn't a requirement.
170
+ -->
39
171
 
40
172
  ## Dependencies
41
- <!-- Teams, services, contracts, data sources, vendor timelines. -->
173
+ <!--
174
+ Teams, services, contracts, data sources, vendor timelines. Each dependency
175
+ should name an owner and the date it must be ready by.
176
+ -->
177
+
178
+ ## Risks and mitigations
179
+
180
+ | Risk | Likelihood | Impact | Mitigation |
181
+ |---|---|---|---|
182
+ | <risk> | low / med / high | low / med / high | <how this is reduced or what we accept> |
42
183
 
43
184
  ## Open questions
44
- <!-- Genuine unknowns. Each question should name an owner and a decision deadline. -->
185
+
186
+ | Question | Owner | Decision needed by |
187
+ |---|---|---|
188
+ | <unknown> | <name> | <YYYY-MM-DD> |
45
189
 
46
190
  ## References
47
191
  <!-- Linked research, prior PRDs, ADRs, tickets, designs. -->
@@ -8,13 +8,13 @@
8
8
  <!-- The specific, falsifiable question this research is trying to answer. One sentence. -->
9
9
 
10
10
  ## Method
11
- <!-- How the question was investigated. Sources consulted, queries run, experiments performed, people interviewed. Enough detail that another person could reproduce it. -->
11
+ <!-- How the question was investigated. Start order, queries run, internal paths checked, experiments performed, and systems consulted. Enough detail that another person could reproduce it. -->
12
12
 
13
13
  ## Sources
14
- <!-- Primary sources, with links and access dates. Separate primary from secondary. Note where sources disagree. -->
14
+ <!-- For each source record: title/path, source class (internal/primary/secondary/tertiary), version or revision if relevant, and publication/access date. Separate primary from secondary. Note where sources disagree. -->
15
15
 
16
16
  ## Findings
17
- <!-- What the evidence says. Separate observation from inference. Label each finding with its confidence level. -->
17
+ <!-- What the evidence says. Separate observation from inference. Label each finding with its confidence level and cite the supporting source(s). -->
18
18
 
19
19
  ## Confidence
20
20
  <!-- Per finding: high / medium / low, and why. Name the biggest unknowns. -->
@@ -26,4 +26,4 @@
26
26
  <!-- What this research did not resolve. What would be needed to answer each. -->
27
27
 
28
28
  ## References
29
- <!-- Full citation list. -->
29
+ <!-- Full citation list. Include URLs, document paths, versions, and dates. -->
@@ -0,0 +1,67 @@
1
+ # Construct — Homebrew formula template.
2
+ #
3
+ # Authoritative copy lives in the construct repo at templates/homebrew/
4
+ # construct.rb. The tap repo (geraldmaron/homebrew-construct) carries the
5
+ # active formula at Formula/construct.rb and is updated by the release
6
+ # workflow's Homebrew bump step on every tag push.
7
+ #
8
+ # When the release pipeline fires for `vX.Y.Z`, dawidd6/action-homebrew-bump-
9
+ # formula rewrites the url + sha256 fields for each platform from the
10
+ # matching GitHub Release asset. The placeholder SHAs below are only used
11
+ # when seeding the tap by hand the first time.
12
+ class Construct < Formula
13
+ desc "Deployable AI R&D operating system for coding agents — runs locally or for teams"
14
+ homepage "https://github.com/geraldmaron/construct"
15
+ version "0.1.0"
16
+ license "Elastic-2.0"
17
+
18
+ livecheck do
19
+ url :stable
20
+ strategy :github_latest
21
+ end
22
+
23
+ on_macos do
24
+ on_arm do
25
+ url "https://github.com/geraldmaron/construct/releases/download/v0.1.0/construct-darwin-arm64"
26
+ sha256 "REPLACE_ON_FIRST_RELEASE_DARWIN_ARM64"
27
+ end
28
+ on_intel do
29
+ url "https://github.com/geraldmaron/construct/releases/download/v0.1.0/construct-darwin-x64"
30
+ sha256 "REPLACE_ON_FIRST_RELEASE_DARWIN_X64"
31
+ end
32
+ end
33
+
34
+ on_linux do
35
+ on_arm do
36
+ url "https://github.com/geraldmaron/construct/releases/download/v0.1.0/construct-linux-arm64"
37
+ sha256 "REPLACE_ON_FIRST_RELEASE_LINUX_ARM64"
38
+ end
39
+ on_intel do
40
+ url "https://github.com/geraldmaron/construct/releases/download/v0.1.0/construct-linux-x64"
41
+ sha256 "REPLACE_ON_FIRST_RELEASE_LINUX_X64"
42
+ end
43
+ end
44
+
45
+ def install
46
+ bin.install Dir["construct-*"].first => "construct"
47
+ end
48
+
49
+ def caveats
50
+ <<~EOS
51
+ To finish setup on this machine, run:
52
+ construct init
53
+
54
+ Construct uses a local Postgres container (via Docker) for hybrid
55
+ retrieval. If Docker is not installed, Construct falls back to a JSON
56
+ vector index — no hard requirement.
57
+
58
+ To wire up hooks and agents per project, add Construct as a dev
59
+ dependency in that project:
60
+ npm install -D @geraldmaron/construct
61
+ EOS
62
+ end
63
+
64
+ test do
65
+ assert_match version.to_s, shell_output("#{bin}/construct version")
66
+ end
67
+ end
@@ -1,82 +0,0 @@
1
- # Construct — Langfuse Self-Hosted
2
- # Auto-provisioned: keys are seeded at container startup via LANGFUSE_INIT_* vars.
3
- # No browser setup required. 'construct setup' writes keys to .env automatically.
4
- #
5
- # Manual usage:
6
- # docker-compose -f langfuse/docker-compose.yml -p construct-langfuse up -d
7
- # # Keys are ready immediately — see LANGFUSE_INIT_PROJECT_* below
8
-
9
- name: construct-langfuse
10
-
11
- services:
12
- langfuse-server:
13
- image: langfuse/langfuse:2
14
- container_name: construct-langfuse
15
- restart: unless-stopped
16
- depends_on:
17
- langfuse-db:
18
- condition: service_healthy
19
- ports:
20
- - "3000:3000"
21
- environment:
22
- DATABASE_URL: postgresql://langfuse:langfuse@langfuse-db:5432/langfuse
23
- NEXTAUTH_SECRET: ${LANGFUSE_NEXTAUTH_SECRET:-construct-nextauth-secret}
24
- SALT: ${LANGFUSE_SALT:-construct-salt-value}
25
- NEXTAUTH_URL: http://localhost:3000
26
- TELEMETRY_ENABLED: "false"
27
- LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: "true"
28
- AUTH_DISABLE_SIGNUP: "false"
29
- # ── Auto-provisioning (no browser setup needed) ──────────────────
30
- LANGFUSE_INIT_ORG_ID: "construct-org"
31
- LANGFUSE_INIT_ORG_NAME: "Construct"
32
- LANGFUSE_INIT_PROJECT_ID: "construct-project"
33
- LANGFUSE_INIT_PROJECT_NAME: "Construct"
34
- LANGFUSE_INIT_PROJECT_PUBLIC_KEY: "pk-lf-construct-local"
35
- LANGFUSE_INIT_PROJECT_SECRET_KEY: "sk-lf-construct-local"
36
- LANGFUSE_INIT_USER_EMAIL: "admin@construct.local"
37
- LANGFUSE_INIT_USER_NAME: "Admin"
38
- LANGFUSE_INIT_USER_PASSWORD: "construct-admin"
39
- healthcheck:
40
- test: ["CMD-SHELL", "curl -sf http://localhost:3000/api/public/health || exit 1"]
41
- interval: 10s
42
- timeout: 5s
43
- retries: 10
44
- start_period: 30s
45
-
46
- langfuse-db:
47
- image: postgres:15-alpine
48
- container_name: construct-langfuse-db
49
- restart: unless-stopped
50
- environment:
51
- POSTGRES_USER: langfuse
52
- POSTGRES_PASSWORD: langfuse
53
- POSTGRES_DB: langfuse
54
- volumes:
55
- - langfuse_db_data:/var/lib/postgresql/data
56
- healthcheck:
57
- test: ["CMD-SHELL", "pg_isready -U langfuse -d langfuse"]
58
- interval: 3s
59
- timeout: 3s
60
- retries: 10
61
-
62
- dspy-optimizer:
63
- build:
64
- context: ./dspy-optimizer
65
- dockerfile: Dockerfile
66
- container_name: construct-dspy-optimizer
67
- restart: "no"
68
- profiles:
69
- - optimize
70
- env_file:
71
- - ../.env
72
- environment:
73
- LANGFUSE_BASEURL: http://langfuse-server:3000
74
- depends_on:
75
- langfuse-server:
76
- condition: service_healthy
77
- volumes:
78
- - ../.cx:/app/.cx
79
-
80
- volumes:
81
- langfuse_db_data:
82
- driver: local
@@ -1,59 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * lib/eval-harness.mjs — <one-line purpose>
4
- *
5
- * <2–6 line summary.>
6
- */
7
- import fs from "node:fs";
8
- import path from "node:path";
9
- import { fileURLToPath } from "node:url";
10
-
11
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
- const root = path.join(__dirname, "..");
13
-
14
- /**
15
- * Basic evaluation harness for Construct agents.
16
- * This script runs "dry runs" or simulated interactions against agent prompts
17
- * to verify they would call the right tools or produce the right outcomes.
18
- */
19
-
20
- export async function runEval(agentName, input, expectedPatterns = []) {
21
- const registry = JSON.parse(fs.readFileSync(path.join(root, "agents", "registry.json"), "utf8"));
22
- const agent = registry.agents.find(a => a.name === agentName) ||
23
- registry.personas.find(p => p.name === agentName);
24
-
25
- if (!agent) throw new Error(`Agent ${agentName} not found in registry`);
26
-
27
- // In a real production setup, this would call the LLM.
28
- // For this harness, we are checking the "Static Intent" —
29
- // can the agent logically fulfill the request based on its prompt?
30
-
31
- const results = {
32
- agent: agentName,
33
- input,
34
- passed: true,
35
- findings: []
36
- };
37
-
38
- for (const pattern of expectedPatterns) {
39
- const regex = new RegExp(pattern, "i");
40
- const foundInPrompt = regex.test(agent.prompt || "");
41
- const foundInShared = (registry.sharedGuidance || []).some(g => regex.test(g));
42
-
43
- if (!foundInPrompt && !foundInShared) {
44
- results.passed = false;
45
- results.findings.push(`MISSING: Pattern "${pattern}" not supported by agent prompt or shared guidance`);
46
- } else {
47
- results.findings.push(`OK: Pattern "${pattern}" is supported`);
48
- }
49
- }
50
-
51
- return results;
52
- }
53
-
54
- if (process.argv[1] && import.meta.url === `file://${process.argv[1]}`) {
55
- // Simple example run
56
- const testAgent = process.argv[2] || "engineer";
57
- const result = await runEval(testAgent, "Fix the bug", ["Edit", "Read", "Bash"]);
58
- console.log(JSON.stringify(result, null, 2));
59
- }
@@ -1,90 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * lib/hooks/bootstrap-guard.mjs — enforce start-of-session bootstrap trio.
4
- *
5
- * Blocks Write/Edit/MultiEdit/NotebookEdit/TodoWrite and destructive Bash
6
- * until the session has invoked workflow_status + project_context + memory_search
7
- * (or accumulated 3+ read-style tool calls, the equivalent signal that the
8
- * agent has grounded itself before acting).
9
- */
10
- import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
11
- import { join } from 'path';
12
- import { homedir } from 'os';
13
-
14
- let payload = {};
15
- try { payload = JSON.parse(readFileSync(0, 'utf8')) || {}; } catch { process.exit(0); }
16
-
17
- const sessionId = payload.session_id || payload.sessionId || 'default';
18
- const toolName = payload.tool_name || payload.tool || '';
19
- const toolInput = payload.tool_input || payload.toolInput || {};
20
-
21
- const BOOTSTRAP_TOOLS = new Set([
22
- 'mcp__construct-mcp__workflow_status',
23
- 'mcp__construct-mcp__project_context',
24
- 'mcp__construct-mcp__memory_search',
25
- 'mcp__cass__memory_search',
26
- 'workflow_status', 'project_context', 'memory_search',
27
- ]);
28
- const READ_TOOLS = new Set(['Read', 'Grep', 'Glob', 'LS', 'NotebookRead']);
29
- const BLOCKED_TOOLS = new Set(['Write', 'Edit', 'MultiEdit', 'NotebookEdit', 'TodoWrite']);
30
- const COMPATIBLE_TOOLS = new Set(['Read', 'Grep', 'Glob', 'LS', 'NotebookRead']);
31
-
32
- const BENIGN_BASH = /^(git (status|log|diff|branch|show|rev-parse)|ls|cat|head|tail|pwd|wc|file|echo|which|node --version|npm --version)\b/;
33
-
34
- const stateDir = join(homedir(), '.cx');
35
- const statePath = join(stateDir, 'bootstrap-state.json');
36
-
37
- let state = {};
38
- if (existsSync(statePath)) {
39
- try { state = JSON.parse(readFileSync(statePath, 'utf8')) || {}; } catch { state = {}; }
40
- }
41
-
42
- const now = Date.now();
43
- for (const [k, v] of Object.entries(state)) {
44
- if (!v?.ts || now - v.ts > 24 * 60 * 60 * 1000) delete state[k];
45
- }
46
-
47
- const s = state[sessionId] || { ts: now, reads: 0, bootstrap: new Set(), done: false };
48
- if (Array.isArray(s.bootstrap)) s.bootstrap = new Set(s.bootstrap);
49
- else if (!(s.bootstrap instanceof Set)) s.bootstrap = new Set();
50
- s.ts = now;
51
-
52
- if (BOOTSTRAP_TOOLS.has(toolName)) s.bootstrap.add(toolName.replace(/^.*__/, ''));
53
- if (READ_TOOLS.has(toolName)) s.reads = (s.reads || 0) + 1;
54
-
55
- if (!s.done) {
56
- const hasTrio = s.bootstrap.has('workflow_status') && s.bootstrap.has('project_context') && s.bootstrap.has('memory_search');
57
- if (hasTrio || (s.reads || 0) >= 3) s.done = true;
58
- }
59
-
60
- if (!s.done && toolName && COMPATIBLE_TOOLS.has(toolName) && (s.reads || 0) >= 2) {
61
- s.done = true;
62
- }
63
-
64
- let block = false;
65
- let reason = '';
66
- if (!s.done) {
67
- if (BLOCKED_TOOLS.has(toolName)) {
68
- block = true;
69
- reason = `${toolName} requires session bootstrap.`;
70
- } else if (toolName === 'Bash') {
71
- const cmd = (toolInput.command || '').trim();
72
- if (cmd && !BENIGN_BASH.test(cmd)) { block = true; reason = 'Bash mutations require session bootstrap.'; }
73
- }
74
- }
75
-
76
- try {
77
- mkdirSync(stateDir, { recursive: true });
78
- state[sessionId] = { ...s, bootstrap: Array.from(s.bootstrap) };
79
- writeFileSync(statePath, JSON.stringify(state));
80
- } catch { /* best effort */ }
81
-
82
- if (block) {
83
- process.stderr.write(
84
- `[bootstrap-guard] ${reason}\n` +
85
- `Run in parallel first: workflow_status, project_context, memory_search.\n` +
86
- `(Or do 3+ exploratory reads — Read/Grep/Glob/LS — if this is a pure exploration task.)\n`
87
- );
88
- process.exit(2);
89
- }
90
- process.exit(0);
@@ -1,43 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * lib/hooks/console-warn.mjs — Console warn hook — warns when console.log/debug statements are left in code.
4
- *
5
- * Runs as PostToolUse after Edit/Write. Detects console.log and console.debug statements in edited files and emits a warning. Does not block — informational only.
6
- */
7
- import { readFileSync, appendFileSync, existsSync } from 'fs';
8
- import { homedir } from 'os';
9
- import { basename } from 'path';
10
-
11
- const CODE_EXTS = new Set(['.js','.mjs','.cjs','.ts','.tsx','.jsx']);
12
- const filePath = process.env.TOOL_INPUT_FILE_PATH || '';
13
-
14
- if (!filePath) process.exit(0);
15
-
16
- const ext = '.' + filePath.split('.').pop();
17
- if (!CODE_EXTS.has(ext)) process.exit(0);
18
-
19
- if (!existsSync(filePath)) process.exit(0);
20
-
21
- const lines = readFileSync(filePath, 'utf8').split('\n');
22
- const hits = [];
23
-
24
- for (let i = 0; i < lines.length; i++) {
25
- const line = lines[i];
26
- const stripped = line.replace(/\/\/.*$/, '').replace(/\/\*.*?\*\//g, '');
27
- if (/\bconsole\.(log|warn|error|info|debug)\s*\(/.test(stripped) || /\bdebugger\s*;/.test(stripped)) {
28
- hits.push(i + 1);
29
- }
30
- }
31
-
32
- if (hits.length === 0) process.exit(0);
33
-
34
- const file = basename(filePath);
35
- const lineList = hits.slice(0, 5).join(', ') + (hits.length > 5 ? '…' : '');
36
- const msg = `Heads up: debug statements left in ${file} — console.log on line${hits.length > 1 ? 's' : ''} ${lineList}. Remove before shipping.`;
37
-
38
- process.stderr.write(`[console-warn] ${msg}\n`);
39
-
40
- const flagsPath = `${homedir()}/.cx/warn-flags.txt`;
41
- try { appendFileSync(flagsPath, `console.log in ${file} (lines ${lineList})\n`); } catch { /* best effort */ }
42
-
43
- process.exit(0);