@kontourai/flow-agents 0.1.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 (418) hide show
  1. package/.githooks/pre-push +11 -0
  2. package/.github/workflows/ci.yml +210 -0
  3. package/.github/workflows/docs-pages.yml +52 -0
  4. package/.github/workflows/publish-npm.yml +104 -0
  5. package/AGENTS.md +26 -0
  6. package/CHANGELOG.md +66 -0
  7. package/CODE_OF_CONDUCT.md +25 -0
  8. package/CONTEXT.md +300 -0
  9. package/CONTRIBUTING.md +44 -0
  10. package/LICENSE +201 -0
  11. package/README.md +129 -0
  12. package/SECURITY.md +33 -0
  13. package/agent-cards/dev.json +19 -0
  14. package/agents/dev.json +127 -0
  15. package/agents/tool-code-reviewer.json +61 -0
  16. package/agents/tool-dependencies-updater.json +118 -0
  17. package/agents/tool-explore-config.json +92 -0
  18. package/agents/tool-explore-deps.json +92 -0
  19. package/agents/tool-explore-entry.json +92 -0
  20. package/agents/tool-explore-patterns.json +92 -0
  21. package/agents/tool-explore-structure.json +92 -0
  22. package/agents/tool-explore-tests.json +92 -0
  23. package/agents/tool-planner.json +57 -0
  24. package/agents/tool-playwright.json +145 -0
  25. package/agents/tool-security-reviewer.json +56 -0
  26. package/agents/tool-verifier.json +61 -0
  27. package/agents/tool-worker.json +58 -0
  28. package/build/src/cli/console-learning-projection.js +123 -0
  29. package/build/src/cli/docs-preview.js +39 -0
  30. package/build/src/cli/effective-backlog-settings.js +102 -0
  31. package/build/src/cli/export-bookmarks.js +38 -0
  32. package/build/src/cli/fixture-retirement-audit.js +140 -0
  33. package/build/src/cli/flow-kit.js +138 -0
  34. package/build/src/cli/import-bookmarks.js +50 -0
  35. package/build/src/cli/init.js +239 -0
  36. package/build/src/cli/instinct-cli.js +93 -0
  37. package/build/src/cli/promote-workflow-artifact.js +63 -0
  38. package/build/src/cli/publish-change-helper.js +154 -0
  39. package/build/src/cli/pull-work-provider.js +469 -0
  40. package/build/src/cli/runtime-adapter.js +23 -0
  41. package/build/src/cli/telemetry-doctor.js +221 -0
  42. package/build/src/cli/usage-feedback.js +443 -0
  43. package/build/src/cli/validate-hook-influence.js +152 -0
  44. package/build/src/cli/validate-source-tree.js +31 -0
  45. package/build/src/cli/validate-workflow-artifacts.js +486 -0
  46. package/build/src/cli/veritas-governance.js +262 -0
  47. package/build/src/cli/workflow-artifact-cleanup-audit.js +272 -0
  48. package/build/src/cli/workflow-sidecar.js +816 -0
  49. package/build/src/cli.js +89 -0
  50. package/build/src/flow-kit/validate.js +75 -0
  51. package/build/src/lib/args.js +45 -0
  52. package/build/src/lib/fs.js +62 -0
  53. package/build/src/lib/workflow-learning-projection.js +334 -0
  54. package/build/src/runtime-adapters.js +146 -0
  55. package/build/src/tools/build-universal-bundles.js +397 -0
  56. package/build/src/tools/common.js +56 -0
  57. package/build/src/tools/filter-installed-packs.js +132 -0
  58. package/build/src/tools/generate-context-map.js +198 -0
  59. package/build/src/tools/validate-package.js +64 -0
  60. package/build/src/tools/validate-source-tree.js +622 -0
  61. package/console.telemetry.json +176 -0
  62. package/context/base-rules.md +17 -0
  63. package/context/code-review-standards.md +62 -0
  64. package/context/coding-standards.md +42 -0
  65. package/context/common/orchestrators.md +12 -0
  66. package/context/common/subagents.md +28 -0
  67. package/context/contracts/artifact-contract.md +182 -0
  68. package/context/contracts/builder-kit-workflow-state-contract.md +319 -0
  69. package/context/contracts/delivery-contract.md +69 -0
  70. package/context/contracts/execution-contract.md +53 -0
  71. package/context/contracts/governance-adapter-contract.md +67 -0
  72. package/context/contracts/planning-contract.md +85 -0
  73. package/context/contracts/review-contract.md +104 -0
  74. package/context/contracts/sandbox-policy.md +52 -0
  75. package/context/contracts/verification-contract.md +134 -0
  76. package/context/contracts/work-item-contract.md +215 -0
  77. package/context/deferred/demo-mode.md +33 -0
  78. package/context/deferred/languages/go.md +31 -0
  79. package/context/deferred/languages/python.md +31 -0
  80. package/context/deferred/languages/typescript.md +34 -0
  81. package/context/deferred/parallelization.md +35 -0
  82. package/context/deferred/worktree-isolation.md +24 -0
  83. package/context/development-workflow.md +50 -0
  84. package/context/scripts/context-budget/budget-scan.sh +166 -0
  85. package/context/scripts/detect-tools.sh +3 -0
  86. package/context/scripts/discover-agents.sh +28 -0
  87. package/context/scripts/git-status.sh +49 -0
  88. package/context/scripts/hooks/config-protection.js +79 -0
  89. package/context/scripts/hooks/desktop-notify.sh +39 -0
  90. package/context/scripts/hooks/governance-audit.sh +135 -0
  91. package/context/scripts/hooks/lib/audit-transport.sh +40 -0
  92. package/context/scripts/hooks/lib/hook-flags.js +49 -0
  93. package/context/scripts/hooks/lib/patterns.sh +57 -0
  94. package/context/scripts/hooks/lib/resolve-formatter.js +80 -0
  95. package/context/scripts/hooks/post-edit-accumulator.js +66 -0
  96. package/context/scripts/hooks/pre-commit-quality.js +194 -0
  97. package/context/scripts/hooks/quality-gate.js +93 -0
  98. package/context/scripts/hooks/report-only-guard.js +21 -0
  99. package/context/scripts/hooks/run-hook.js +136 -0
  100. package/context/scripts/hooks/stop-format-typecheck.js +141 -0
  101. package/context/scripts/hooks/stop-goal-fit.js +337 -0
  102. package/context/scripts/hooks/workflow-steering.js +250 -0
  103. package/context/scripts/telemetry/console-presets.sh +14 -0
  104. package/context/scripts/telemetry/install-console-config.sh +214 -0
  105. package/context/scripts/telemetry/lib/config.sh +85 -0
  106. package/context/scripts/telemetry/lib/enrich.sh +115 -0
  107. package/context/scripts/telemetry/lib/redact.sh +22 -0
  108. package/context/scripts/telemetry/lib/session.sh +63 -0
  109. package/context/scripts/telemetry/lib/transport.sh +183 -0
  110. package/context/scripts/telemetry/lib/usage.sh +29 -0
  111. package/context/scripts/telemetry/sync-agents.sh +173 -0
  112. package/context/scripts/telemetry/telemetry.conf +23 -0
  113. package/context/scripts/telemetry/telemetry.sh +387 -0
  114. package/context/scripts/validate-package.sh +89 -0
  115. package/context/settings/backlog-provider-settings.json +54 -0
  116. package/context/templates/core/identity.md +26 -0
  117. package/context/templates/core/user.md +15 -0
  118. package/docs/_config.yml +15 -0
  119. package/docs/_layouts/default.html +87 -0
  120. package/docs/adr/0001-flow-agents-consumes-flow.md +77 -0
  121. package/docs/adr/0002-flow-kits-as-extension-unit.md +13 -0
  122. package/docs/adr/0003-flow-agents-coordinates-kits-and-adapters.md +13 -0
  123. package/docs/adr/0004-gates-expect-surface-claims.md +15 -0
  124. package/docs/adr/0005-kubernetes-inspired-resource-contracts.md +48 -0
  125. package/docs/adr/0006-typescript-first-source-policy.md +98 -0
  126. package/docs/agent-system-guidebook.md +391 -0
  127. package/docs/agent-usage-feedback-loop.md +351 -0
  128. package/docs/assets/favicon.svg +13 -0
  129. package/docs/assets/og-image.png +0 -0
  130. package/docs/assets/site.css +774 -0
  131. package/docs/assets/site.js +139 -0
  132. package/docs/configurable-workflow-routing.md +174 -0
  133. package/docs/context-map.md +145 -0
  134. package/docs/developer-architecture.md +145 -0
  135. package/docs/developer-hook-setup.md +61 -0
  136. package/docs/fixture-ownership.md +44 -0
  137. package/docs/flow-kit-repository-contract.md +180 -0
  138. package/docs/index.md +129 -0
  139. package/docs/kontour-resource-contract.md +358 -0
  140. package/docs/migrations.md +64 -0
  141. package/docs/north-star.md +322 -0
  142. package/docs/operating-layers.md +110 -0
  143. package/docs/repository-structure.md +132 -0
  144. package/docs/sandbox-policy.md +56 -0
  145. package/docs/skills-map.md +203 -0
  146. package/docs/standards-register.md +96 -0
  147. package/docs/veritas-integration.md +165 -0
  148. package/docs/work-item-adapters.md +72 -0
  149. package/docs/workflow-artifact-lifecycle.md +141 -0
  150. package/docs/workflow-eval-strategy.md +295 -0
  151. package/docs/workflow-shared-contracts.md +51 -0
  152. package/docs/workflow-usage-guide.md +443 -0
  153. package/evals/ARCHITECTURE.md +143 -0
  154. package/evals/CONVENTIONS.md +58 -0
  155. package/evals/README.md +128 -0
  156. package/evals/acceptance/run.sh +29 -0
  157. package/evals/acceptance/test_claude_harness.sh +242 -0
  158. package/evals/acceptance/test_codex_harness.sh +108 -0
  159. package/evals/acceptance/test_kiro_harness.sh +128 -0
  160. package/evals/cases/dev/404.html +97 -0
  161. package/evals/cases/dev/code-review.yaml +44 -0
  162. package/evals/cases/dev/dashboard.html +300 -0
  163. package/evals/cases/dev/deliver.yaml +66 -0
  164. package/evals/cases/dev/dependency-update.yaml +16 -0
  165. package/evals/cases/dev/explore.yaml +20 -0
  166. package/evals/cases/dev/index.html +370 -0
  167. package/evals/cases/dev/package-lock.json +28 -0
  168. package/evals/cases/dev/package.json +16 -0
  169. package/evals/cases/dev/plan-work.yaml +20 -0
  170. package/evals/cases/dev/promptfooconfig.yaml +666 -0
  171. package/evals/cases/dev/search-first.yaml +20 -0
  172. package/evals/cases/dev/tdd-workflow.yaml +48 -0
  173. package/evals/cases/dev/verify-work.yaml +44 -0
  174. package/evals/cases/dev/workflow.yaml +34 -0
  175. package/evals/ci/run-baseline.sh +283 -0
  176. package/evals/fixtures/backlog-provider-settings/global-default.json +44 -0
  177. package/evals/fixtures/backlog-provider-settings/project-override.json +53 -0
  178. package/evals/fixtures/builder-kit-workflow-state/baseline-freshness-resolution-hint.json +139 -0
  179. package/evals/fixtures/builder-kit-workflow-state/direct-primitive-stop.json +59 -0
  180. package/evals/fixtures/builder-kit-workflow-state/empty-board-route-shape.json +55 -0
  181. package/evals/fixtures/builder-kit-workflow-state/happy-path.json +71 -0
  182. package/evals/fixtures/builder-kit-workflow-state/mid-work-resume.json +80 -0
  183. package/evals/fixtures/builder-kit-workflow-state/missing-prestep-recovery.json +65 -0
  184. package/evals/fixtures/builder-kit-workflow-state/product-build-chaining.json +60 -0
  185. package/evals/fixtures/builder-kit-workflow-state/stale-continuation-requires-new-probe.json +57 -0
  186. package/evals/fixtures/console-learning-projection/artifacts/console-learning-correction/learning.json +50 -0
  187. package/evals/fixtures/console-learning-projection/artifacts/console-learning-open-route/learning.json +41 -0
  188. package/evals/fixtures/flow-kit-repository/invalid-absolute-path/kit.json +8 -0
  189. package/evals/fixtures/flow-kit-repository/invalid-asset-section/flows/review.flow.json +6 -0
  190. package/evals/fixtures/flow-kit-repository/invalid-asset-section/kit.json +11 -0
  191. package/evals/fixtures/flow-kit-repository/invalid-duplicate-flow/flows/review.flow.json +6 -0
  192. package/evals/fixtures/flow-kit-repository/invalid-duplicate-flow/kit.json +9 -0
  193. package/evals/fixtures/flow-kit-repository/invalid-id/flows/review.flow.json +6 -0
  194. package/evals/fixtures/flow-kit-repository/invalid-id/kit.json +8 -0
  195. package/evals/fixtures/flow-kit-repository/invalid-malformed-json/kit.json +8 -0
  196. package/evals/fixtures/flow-kit-repository/invalid-missing-flow/kit.json +8 -0
  197. package/evals/fixtures/flow-kit-repository/invalid-missing-id/flows/review.flow.json +6 -0
  198. package/evals/fixtures/flow-kit-repository/invalid-missing-id/kit.json +7 -0
  199. package/evals/fixtures/flow-kit-repository/invalid-missing-schema-version/flows/review.flow.json +6 -0
  200. package/evals/fixtures/flow-kit-repository/invalid-missing-schema-version/kit.json +7 -0
  201. package/evals/fixtures/flow-kit-repository/invalid-name/flows/review.flow.json +6 -0
  202. package/evals/fixtures/flow-kit-repository/invalid-name/kit.json +8 -0
  203. package/evals/fixtures/flow-kit-repository/invalid-schema-version/flows/review.flow.json +6 -0
  204. package/evals/fixtures/flow-kit-repository/invalid-schema-version/kit.json +8 -0
  205. package/evals/fixtures/flow-kit-repository/invalid-traversal/kit.json +8 -0
  206. package/evals/fixtures/flow-kit-repository/mixed-runtime-kit/adapters/example.json +3 -0
  207. package/evals/fixtures/flow-kit-repository/mixed-runtime-kit/assets/example.txt +1 -0
  208. package/evals/fixtures/flow-kit-repository/mixed-runtime-kit/docs/README.md +3 -0
  209. package/evals/fixtures/flow-kit-repository/mixed-runtime-kit/flows/runtime.flow.json +26 -0
  210. package/evals/fixtures/flow-kit-repository/mixed-runtime-kit/kit-evals/example.json +3 -0
  211. package/evals/fixtures/flow-kit-repository/mixed-runtime-kit/kit-skills/mixed/SKILL.md +3 -0
  212. package/evals/fixtures/flow-kit-repository/mixed-runtime-kit/kit.json +44 -0
  213. package/evals/fixtures/flow-kit-repository/valid-local-kit/docs/README.md +3 -0
  214. package/evals/fixtures/flow-kit-repository/valid-local-kit/flows/review.flow.json +26 -0
  215. package/evals/fixtures/flow-kit-repository/valid-local-kit/kit.json +20 -0
  216. package/evals/fixtures/hook-influence/cases.json +336 -0
  217. package/evals/fixtures/pull-work-provider/github-issues.json +170 -0
  218. package/evals/fixtures/pull-work-wip-shepherding/global-wip-informs.json +43 -0
  219. package/evals/fixtures/pull-work-wip-shepherding/personal-wip-blocks.json +42 -0
  220. package/evals/fixtures/surface-trust/accepted-claim-trust-report.json +31 -0
  221. package/evals/fixtures/surface-trust/artifact-absent.json +19 -0
  222. package/evals/fixtures/surface-trust/integrity-mismatch-trust-report.json +32 -0
  223. package/evals/fixtures/surface-trust/missing-authority-trust-report.json +27 -0
  224. package/evals/fixtures/surface-trust/provider-absent.json +19 -0
  225. package/evals/fixtures/surface-trust/rejected-claim-trust-report.json +30 -0
  226. package/evals/fixtures/surface-trust/stale-claim-trust-snapshot.json +31 -0
  227. package/evals/fixtures/usage-feedback/sample-full.jsonl +11 -0
  228. package/evals/fixtures/usage-feedback/sample-outcomes.jsonl +1 -0
  229. package/evals/fixtures/veritas-governance-adapter/fake-veritas-pass.sh +18 -0
  230. package/evals/fixtures/veritas-governance-adapter/fake-veritas-secret-fail.sh +10 -0
  231. package/evals/fixtures/veritas-governance-adapter/fake-veritas-unconfigured.sh +4 -0
  232. package/evals/integration/test_bundle_install.sh +541 -0
  233. package/evals/integration/test_console_learning_projection.sh +192 -0
  234. package/evals/integration/test_context_map.sh +65 -0
  235. package/evals/integration/test_effective_backlog_settings.sh +58 -0
  236. package/evals/integration/test_fixture_retirement_audit.sh +58 -0
  237. package/evals/integration/test_flow_agents_statusline.sh +93 -0
  238. package/evals/integration/test_flow_kit_repository.sh +90 -0
  239. package/evals/integration/test_goal_fit_hook.sh +482 -0
  240. package/evals/integration/test_hook_category_behaviors.sh +190 -0
  241. package/evals/integration/test_hook_influence_cases.sh +69 -0
  242. package/evals/integration/test_local_flow_kit_install.sh +145 -0
  243. package/evals/integration/test_publish_change_helper.sh +176 -0
  244. package/evals/integration/test_pull_work_provider.sh +140 -0
  245. package/evals/integration/test_runtime_adapter_activation.sh +106 -0
  246. package/evals/integration/test_telemetry.sh +485 -0
  247. package/evals/integration/test_telemetry_doctor.sh +193 -0
  248. package/evals/integration/test_usage_feedback_dashboard.sh +169 -0
  249. package/evals/integration/test_usage_feedback_global.sh +117 -0
  250. package/evals/integration/test_usage_feedback_import.sh +227 -0
  251. package/evals/integration/test_usage_feedback_outcomes.sh +165 -0
  252. package/evals/integration/test_usage_feedback_report.sh +263 -0
  253. package/evals/integration/test_veritas_governance_adapter.sh +235 -0
  254. package/evals/integration/test_workflow_artifact_cleanup_audit.sh +287 -0
  255. package/evals/integration/test_workflow_artifacts.sh +1247 -0
  256. package/evals/integration/test_workflow_sidecar_writer.sh +2112 -0
  257. package/evals/integration/test_workflow_steering_hook.sh +337 -0
  258. package/evals/lib/assertions/delegated-to.js +40 -0
  259. package/evals/lib/assertions/max-tool-calls.js +15 -0
  260. package/evals/lib/assertions/no-write-tools.js +27 -0
  261. package/evals/lib/assertions/pass-at-k.js +39 -0
  262. package/evals/lib/assertions/telemetry-utils.js +105 -0
  263. package/evals/lib/assertions/tool-called.js +39 -0
  264. package/evals/lib/assertions/verify-after-fix.js +61 -0
  265. package/evals/lib/claude-judge.sh +40 -0
  266. package/evals/lib/claude-provider.sh +74 -0
  267. package/evals/lib/codex-judge.sh +39 -0
  268. package/evals/lib/codex-provider.sh +81 -0
  269. package/evals/lib/eval-dev.sh +5 -0
  270. package/evals/lib/eval-judge.sh +22 -0
  271. package/evals/lib/eval-provider.sh +26 -0
  272. package/evals/lib/eval-report.sh +73 -0
  273. package/evals/lib/kiro-dev.sh +4 -0
  274. package/evals/lib/kiro-judge.sh +17 -0
  275. package/evals/lib/kiro-provider.sh +62 -0
  276. package/evals/lib/node.sh +111 -0
  277. package/evals/promptfooconfig.yaml +70 -0
  278. package/evals/run.sh +309 -0
  279. package/evals/static/test_evidence_refs.sh +141 -0
  280. package/evals/static/test_package.sh +407 -0
  281. package/evals/static/test_repo_hooks.sh +68 -0
  282. package/evals/static/test_universal_bundles.sh +274 -0
  283. package/evals/static/test_workflow_skills.sh +1207 -0
  284. package/install.sh +64 -0
  285. package/integrations/veritas/flow-agents.adapter.json +138 -0
  286. package/integrations/veritas/flow-agents.authority-settings.json +26 -0
  287. package/integrations/veritas/flow-agents.repo-standards.json +82 -0
  288. package/kits/builder/flows/build.flow.json +218 -0
  289. package/kits/builder/flows/shape.flow.json +127 -0
  290. package/kits/builder/kit.json +19 -0
  291. package/kits/catalog.json +11 -0
  292. package/package.json +130 -0
  293. package/packaging/README.md +60 -0
  294. package/packaging/manifest.json +173 -0
  295. package/packaging/packs.json +69 -0
  296. package/powers/dependency-checker/POWER.md +20 -0
  297. package/powers/dependency-checker/mcp.json +20 -0
  298. package/powers/playwright/POWER.md +25 -0
  299. package/powers/playwright/mcp.json +12 -0
  300. package/prompts/code-audit.md +123 -0
  301. package/prompts/kcommit.md +88 -0
  302. package/schemas/backlog-provider-settings.schema.json +138 -0
  303. package/schemas/workflow-acceptance.schema.json +216 -0
  304. package/schemas/workflow-critique.schema.json +113 -0
  305. package/schemas/workflow-evidence.schema.json +357 -0
  306. package/schemas/workflow-handoff.schema.json +52 -0
  307. package/schemas/workflow-learning.schema.json +223 -0
  308. package/schemas/workflow-release.schema.json +172 -0
  309. package/schemas/workflow-state.schema.json +80 -0
  310. package/scripts/README.md +111 -0
  311. package/scripts/build-universal-bundles.js +3 -0
  312. package/scripts/check-content-boundary.cjs +99 -0
  313. package/scripts/context-budget/budget-scan.sh +166 -0
  314. package/scripts/detect-tools.sh +3 -0
  315. package/scripts/discover-agents.sh +28 -0
  316. package/scripts/effective-backlog-settings.js +2 -0
  317. package/scripts/filter-installed-packs.js +2 -0
  318. package/scripts/flow-kit.js +2 -0
  319. package/scripts/generate-context-map.js +2 -0
  320. package/scripts/git-status.sh +49 -0
  321. package/scripts/hooks/claude-hook-adapter.js +174 -0
  322. package/scripts/hooks/claude-telemetry-hook.js +115 -0
  323. package/scripts/hooks/codex-hook-adapter.js +176 -0
  324. package/scripts/hooks/codex-telemetry-hook.js +95 -0
  325. package/scripts/hooks/config-protection.js +79 -0
  326. package/scripts/hooks/desktop-notify.sh +39 -0
  327. package/scripts/hooks/governance-audit.sh +135 -0
  328. package/scripts/hooks/lib/audit-transport.sh +40 -0
  329. package/scripts/hooks/lib/hook-flags.js +49 -0
  330. package/scripts/hooks/lib/patterns.sh +57 -0
  331. package/scripts/hooks/lib/resolve-formatter.js +80 -0
  332. package/scripts/hooks/post-edit-accumulator.js +66 -0
  333. package/scripts/hooks/pre-commit-quality.js +194 -0
  334. package/scripts/hooks/quality-gate.js +93 -0
  335. package/scripts/hooks/report-only-guard.js +21 -0
  336. package/scripts/hooks/run-hook.js +136 -0
  337. package/scripts/hooks/stop-format-typecheck.js +141 -0
  338. package/scripts/hooks/stop-goal-fit.js +337 -0
  339. package/scripts/hooks/workflow-steering.js +250 -0
  340. package/scripts/install-codex-home.sh +106 -0
  341. package/scripts/package.json +3 -0
  342. package/scripts/promote-workflow-artifact.js +2 -0
  343. package/scripts/publish-change-helper.js +2 -0
  344. package/scripts/pull-work-provider.js +2 -0
  345. package/scripts/setup-repo-hooks.sh +8 -0
  346. package/scripts/statusline/flow-agents-statusline.js +157 -0
  347. package/scripts/telemetry/console-presets.sh +14 -0
  348. package/scripts/telemetry/install-console-config.sh +214 -0
  349. package/scripts/telemetry/lib/config.sh +85 -0
  350. package/scripts/telemetry/lib/enrich.sh +115 -0
  351. package/scripts/telemetry/lib/redact.sh +22 -0
  352. package/scripts/telemetry/lib/session.sh +63 -0
  353. package/scripts/telemetry/lib/transport.sh +183 -0
  354. package/scripts/telemetry/lib/usage.sh +29 -0
  355. package/scripts/telemetry/sync-agents.sh +173 -0
  356. package/scripts/telemetry/telemetry.conf +23 -0
  357. package/scripts/telemetry/telemetry.sh +387 -0
  358. package/scripts/usage-feedback.js +2 -0
  359. package/scripts/validate-hook-influence-cases.js +2 -0
  360. package/scripts/validate-package.sh +89 -0
  361. package/scripts/validate-source-tree.js +9 -0
  362. package/skills/agentic-engineering/SKILL.md +62 -0
  363. package/skills/browser-test/SKILL.md +51 -0
  364. package/skills/builder-shape/SKILL.md +76 -0
  365. package/skills/context-budget/SKILL.md +40 -0
  366. package/skills/deliver/SKILL.md +241 -0
  367. package/skills/dependency-update/SKILL.md +68 -0
  368. package/skills/design-probe/SKILL.md +107 -0
  369. package/skills/eval-rebuild/SKILL.md +39 -0
  370. package/skills/evidence-gate/SKILL.md +186 -0
  371. package/skills/execute-plan/SKILL.md +110 -0
  372. package/skills/explore/SKILL.md +137 -0
  373. package/skills/feedback-loop/SKILL.md +87 -0
  374. package/skills/fix-bug/SKILL.md +133 -0
  375. package/skills/frontend-design/SKILL.md +80 -0
  376. package/skills/github-cli/SKILL.md +63 -0
  377. package/skills/idea-to-backlog/SKILL.md +267 -0
  378. package/skills/knowledge-capture/SKILL.md +55 -0
  379. package/skills/learning-review/SKILL.md +115 -0
  380. package/skills/pickup-probe/SKILL.md +114 -0
  381. package/skills/plan-work/SKILL.md +176 -0
  382. package/skills/pull-work/SKILL.md +309 -0
  383. package/skills/release-readiness/SKILL.md +121 -0
  384. package/skills/review-work/SKILL.md +161 -0
  385. package/skills/search-first/SKILL.md +66 -0
  386. package/skills/tdd-workflow/SKILL.md +140 -0
  387. package/skills/verify-work/SKILL.md +109 -0
  388. package/src/cli/console-learning-projection.ts +140 -0
  389. package/src/cli/effective-backlog-settings.ts +99 -0
  390. package/src/cli/fixture-retirement-audit.ts +154 -0
  391. package/src/cli/flow-kit.ts +139 -0
  392. package/src/cli/init.ts +248 -0
  393. package/src/cli/promote-workflow-artifact.ts +64 -0
  394. package/src/cli/publish-change-helper.ts +143 -0
  395. package/src/cli/pull-work-provider.ts +481 -0
  396. package/src/cli/runtime-adapter.ts +24 -0
  397. package/src/cli/telemetry-doctor.ts +243 -0
  398. package/src/cli/usage-feedback.ts +418 -0
  399. package/src/cli/validate-hook-influence.ts +119 -0
  400. package/src/cli/validate-source-tree.ts +30 -0
  401. package/src/cli/validate-workflow-artifacts.ts +411 -0
  402. package/src/cli/veritas-governance.ts +322 -0
  403. package/src/cli/workflow-artifact-cleanup-audit.ts +281 -0
  404. package/src/cli/workflow-sidecar.ts +676 -0
  405. package/src/cli.ts +95 -0
  406. package/src/flow-kit/validate.ts +74 -0
  407. package/src/lib/args.ts +43 -0
  408. package/src/lib/fs.ts +62 -0
  409. package/src/lib/workflow-learning-projection.ts +491 -0
  410. package/src/runtime-adapters.ts +154 -0
  411. package/src/tools/build-universal-bundles.ts +366 -0
  412. package/src/tools/common.ts +61 -0
  413. package/src/tools/filter-installed-packs.ts +129 -0
  414. package/src/tools/generate-context-map.ts +199 -0
  415. package/src/tools/validate-package.ts +57 -0
  416. package/src/tools/validate-source-tree.ts +488 -0
  417. package/tsconfig.json +19 -0
  418. package/veritas.claims.json +6 -0
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env bash
2
+ # desktop-notify.sh — macOS desktop notification on agent session stop
3
+ # Usage: echo '<hook_event_json>' | bash desktop-notify.sh stop <agent_name>
4
+ # Non-blocking: wraps osascript in background subshell
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ TELEMETRY_DIR="$(cd "${SCRIPT_DIR}/../telemetry" && pwd)"
8
+ source "${TELEMETRY_DIR}/lib/config.sh"
9
+
10
+ main() {
11
+ # Feature gate
12
+ [[ "$TELEMETRY_NOTIFICATIONS" != "true" ]] && return 0
13
+
14
+ # Profile gate
15
+ case "$TELEMETRY_NOTIFICATION_PROFILE" in
16
+ standard|strict) ;;
17
+ *) return 0 ;;
18
+ esac
19
+
20
+ local hook_type="${1:-stop}" agent_name="${2:-agent}"
21
+ local stdin_json="$3"
22
+
23
+ # Extract summary from last_assistant_message
24
+ local summary
25
+ summary=$(echo "$stdin_json" | jq -r '.last_assistant_message // ""' 2>/dev/null)
26
+ # Take first non-empty line
27
+ summary=$(echo "$summary" | grep -m1 '.' || echo "Session complete")
28
+ # Truncate to 100 chars
29
+ [[ ${#summary} -gt 100 ]] && summary="${summary:0:100}..."
30
+
31
+ # Send notification (async, non-blocking)
32
+ osascript -e "display notification \"${summary//\"/\\\"}\" with title \"Kiro — ${agent_name}\"" &>/dev/null &
33
+ }
34
+
35
+ _stdin=$(cat)
36
+ echo "$_stdin"
37
+ (main "$@" "$_stdin") </dev/null &>/dev/null &
38
+ disown 2>/dev/null
39
+ exit 0
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env bash
2
+ # governance-audit.sh — Governance detection hook for preToolUse/postToolUse
3
+ # Usage: echo '<hook_event_json>' | bash governance-audit.sh <hookType> <agentName>
4
+ set -o pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ TELEMETRY_DIR="$(cd "${SCRIPT_DIR}/../telemetry" && pwd)"
8
+
9
+ source "${TELEMETRY_DIR}/lib/config.sh"
10
+ source "${SCRIPT_DIR}/lib/patterns.sh"
11
+ source "${SCRIPT_DIR}/lib/audit-transport.sh"
12
+
13
+ # Max input size to inspect (bytes) — truncate beyond this
14
+ MAX_INSPECT_SIZE=50000
15
+
16
+ _build_event() {
17
+ local finding_type="$1" severity="$2" tool_name="$3" hook_phase="$4" details="$5"
18
+ local session_id agent_name="$6"
19
+ session_id=$(ls -t "${TELEMETRY_SESSION_DIR}"/*.session 2>/dev/null | head -n1 | xargs -I{} jq -r '.session_id' {} 2>/dev/null || echo "no-session")
20
+ local event_id timestamp_ms
21
+ event_id="gov-$(date +%s)-$(head -c4 /dev/urandom 2>/dev/null | od -An -tx1 | tr -d ' \n' || echo $$)"
22
+ timestamp_ms=$(date +%s)000
23
+
24
+ jq -nc \
25
+ --arg sv "0.3.0" \
26
+ --arg ts "$timestamp_ms" \
27
+ --arg sid "$session_id" \
28
+ --arg eid "$event_id" \
29
+ --arg et "governance.${finding_type}" \
30
+ --arg an "$agent_name" \
31
+ --arg ft "$finding_type" \
32
+ --arg sev "$severity" \
33
+ --arg tn "$tool_name" \
34
+ --arg hp "$hook_phase" \
35
+ --argjson det "$details" \
36
+ '{
37
+ schema_version: $sv,
38
+ timestamp: $ts,
39
+ session_id: $sid,
40
+ event_id: $eid,
41
+ event_type: $et,
42
+ agent: {name: $an, runtime: "kiro-cli"},
43
+ governance: {finding_type: $ft, severity: $sev, tool_name: $tn, hook_phase: $hp, details: $det}
44
+ }'
45
+ }
46
+
47
+ main() {
48
+ [[ "$TELEMETRY_GOVERNANCE" != "true" ]] && return 0
49
+
50
+ local hook_type="${1:-preToolUse}" agent_name="${2:-unknown}"
51
+ local stdin_json="$3"
52
+ local hook_phase
53
+ case "$hook_type" in
54
+ preToolUse) hook_phase="pre" ;;
55
+ postToolUse) hook_phase="post" ;;
56
+ *) return 0 ;;
57
+ esac
58
+
59
+ local tool_name text
60
+ tool_name=$(echo "$stdin_json" | jq -r '.tool_name // ""' 2>/dev/null)
61
+
62
+ # Combine tool_input and tool_response for scanning
63
+ local tool_input tool_response
64
+ tool_input=$(echo "$stdin_json" | jq -r '.tool_input // "" | if type == "object" then tostring else . end' 2>/dev/null)
65
+ tool_response=$(echo "$stdin_json" | jq -r '.tool_response // "" | if type == "object" then tostring else . end' 2>/dev/null)
66
+ text="${tool_input}${tool_response}"
67
+
68
+ # Truncation check
69
+ if [[ ${#text} -gt $MAX_INSPECT_SIZE ]]; then
70
+ local trunc_event
71
+ trunc_event=$(_build_event "audit_input_truncated" "warning" "$tool_name" "$hook_phase" \
72
+ "{\"original_size\":${#text},\"max_size\":${MAX_INSPECT_SIZE}}" "$agent_name")
73
+ audit_emit "$trunc_event"
74
+ text="${text:0:$MAX_INSPECT_SIZE}"
75
+ fi
76
+
77
+ # Secret detection
78
+ local secrets
79
+ secrets=$(_detect_secrets "$text")
80
+ if [[ -n "$secrets" ]]; then
81
+ local types_json location
82
+ types_json=$(echo "$secrets" | jq -Rsc 'split("\n") | map(select(. != ""))')
83
+ [[ "$hook_phase" == "pre" ]] && location="input" || location="output"
84
+ local evt
85
+ evt=$(_build_event "secret_detected" "critical" "$tool_name" "$hook_phase" \
86
+ "{\"secret_types\":${types_json},\"location\":\"${location}\"}" "$agent_name")
87
+ audit_emit "$evt"
88
+ fi
89
+
90
+ # AWS policy violations
91
+ local violations
92
+ violations=$(_detect_aws_violations "$text")
93
+ if [[ -n "$violations" ]]; then
94
+ local vtypes_json
95
+ vtypes_json=$(echo "$violations" | jq -Rsc 'split("\n") | map(select(. != ""))')
96
+ local evt
97
+ evt=$(_build_event "aws_policy_violation" "critical" "$tool_name" "$hook_phase" \
98
+ "{\"violation_types\":${vtypes_json}}" "$agent_name")
99
+ audit_emit "$evt"
100
+ fi
101
+
102
+ # Destructive operations (primarily preToolUse on bash commands)
103
+ if _detect_destructive_ops "$text"; then
104
+ local evt
105
+ evt=$(_build_event "destructive_operation" "high" "$tool_name" "$hook_phase" \
106
+ '{"location":"command"}' "$agent_name")
107
+ audit_emit "$evt"
108
+ fi
109
+
110
+ # Sensitive file access (preToolUse on file writes)
111
+ local file_path
112
+ file_path=$(echo "$stdin_json" | jq -r '.tool_input.path // .tool_input.file_path // ""' 2>/dev/null)
113
+ if [[ -n "$file_path" ]] && _detect_sensitive_paths "$file_path"; then
114
+ local evt
115
+ evt=$(_build_event "sensitive_file_access" "warning" "$tool_name" "$hook_phase" \
116
+ "{\"path\":\"${file_path}\"}" "$agent_name")
117
+ audit_emit "$evt"
118
+ fi
119
+
120
+ # Elevated privilege
121
+ if _detect_elevated_privilege "$text"; then
122
+ local evt
123
+ evt=$(_build_event "elevated_privilege" "medium" "$tool_name" "$hook_phase" \
124
+ '{"location":"command"}' "$agent_name")
125
+ audit_emit "$evt"
126
+ fi
127
+
128
+ audit_maybe_rotate
129
+ }
130
+
131
+ _stdin=$(cat)
132
+ echo "$_stdin"
133
+ (main "$@" "$_stdin") </dev/null &>/dev/null &
134
+ disown 2>/dev/null
135
+ exit 0
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bash
2
+ # audit-transport.sh — Audit-specific JSONL transport (separate from telemetry channels)
3
+
4
+ audit_emit() {
5
+ local event_json="$1"
6
+ [[ -z "$event_json" ]] && return
7
+ local audit_file="${TELEMETRY_DATA_DIR}/audit.jsonl"
8
+ echo "$event_json" >> "$audit_file" 2>/dev/null
9
+ }
10
+
11
+ audit_maybe_rotate() {
12
+ local audit_file="${TELEMETRY_DATA_DIR}/audit.jsonl"
13
+ [[ ! -f "$audit_file" ]] && return
14
+
15
+ local file_size_bytes=0
16
+ if stat -c %s "$audit_file" >/dev/null 2>&1; then
17
+ file_size_bytes=$(stat -c %s "$audit_file")
18
+ else
19
+ file_size_bytes=$(stat -f %z "$audit_file" 2>/dev/null || echo "0")
20
+ fi
21
+
22
+ local max_bytes=$(( TELEMETRY_GOVERNANCE_AUDIT_MAX_SIZE_MB * 1024 * 1024 ))
23
+ [[ "$file_size_bytes" -lt "$max_bytes" ]] && return
24
+
25
+ local base="${audit_file%.*}"
26
+ local ext="${audit_file##*.}"
27
+
28
+ # Remove oldest
29
+ local oldest="${base}.$((TELEMETRY_GOVERNANCE_AUDIT_MAX_FILES - 1)).${ext}"
30
+ [[ -f "$oldest" ]] && rm -f "$oldest"
31
+
32
+ # Shift existing
33
+ for ((i = TELEMETRY_GOVERNANCE_AUDIT_MAX_FILES - 2; i >= 1; i--)); do
34
+ local cur="${base}.${i}.${ext}"
35
+ local nxt="${base}.$((i + 1)).${ext}"
36
+ [[ -f "$cur" ]] && mv "$cur" "$nxt"
37
+ done
38
+
39
+ mv "$audit_file" "${base}.1.${ext}"
40
+ }
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Shared hook enable/disable controls.
4
+ *
5
+ * Controls:
6
+ * - SA_HOOK_PROFILE=minimal|standard|strict (default: standard)
7
+ * - SA_DISABLED_HOOKS=comma,separated,hook,ids
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const VALID_PROFILES = new Set(['minimal', 'standard', 'strict']);
13
+
14
+ function normalizeId(value) {
15
+ return String(value || '').trim().toLowerCase();
16
+ }
17
+
18
+ function getHookProfile() {
19
+ const raw = String(process.env.SA_HOOK_PROFILE || 'standard').trim().toLowerCase();
20
+ return VALID_PROFILES.has(raw) ? raw : 'standard';
21
+ }
22
+
23
+ function getDisabledHookIds() {
24
+ const raw = String(process.env.SA_DISABLED_HOOKS || '');
25
+ if (!raw.trim()) return new Set();
26
+ return new Set(raw.split(',').map(v => normalizeId(v)).filter(Boolean));
27
+ }
28
+
29
+ function parseProfiles(rawProfiles, fallback = ['standard', 'strict']) {
30
+ if (!rawProfiles) return [...fallback];
31
+ if (Array.isArray(rawProfiles)) {
32
+ const parsed = rawProfiles.map(v => String(v || '').trim().toLowerCase()).filter(v => VALID_PROFILES.has(v));
33
+ return parsed.length > 0 ? parsed : [...fallback];
34
+ }
35
+ const parsed = String(rawProfiles).split(',').map(v => v.trim().toLowerCase()).filter(v => VALID_PROFILES.has(v));
36
+ return parsed.length > 0 ? parsed : [...fallback];
37
+ }
38
+
39
+ function isHookEnabled(hookId, options = {}) {
40
+ const id = normalizeId(hookId);
41
+ if (!id) return true;
42
+ const disabled = getDisabledHookIds();
43
+ if (disabled.has(id)) return false;
44
+ const profile = getHookProfile();
45
+ const allowedProfiles = parseProfiles(options.profiles);
46
+ return allowedProfiles.includes(profile);
47
+ }
48
+
49
+ module.exports = { VALID_PROFILES, normalizeId, getHookProfile, getDisabledHookIds, parseProfiles, isHookEnabled };
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env bash
2
+ # patterns.sh — Shared detection patterns for governance audit
3
+ # Compatible with bash 3.2+ (no associative arrays)
4
+
5
+ # --- Secret patterns ---
6
+ _detect_secrets() {
7
+ local text="$1"
8
+ local found=""
9
+ echo "$text" | grep -qE 'AKIA[A-Z0-9]{16}' 2>/dev/null && found="${found}aws_key "
10
+ echo "$text" | grep -qE 'ASIA[A-Z0-9]{16}' 2>/dev/null && found="${found}aws_sts "
11
+ echo "$text" | grep -qE '(secret|password|token|api[_-]?key)[[:space:]]*[:=][[:space:]]*["'"'"'][^"'"'"']{8,}' 2>/dev/null && found="${found}generic_secret "
12
+ echo "$text" | grep -q 'BEGIN.*PRIVATE KEY' 2>/dev/null && found="${found}private_key "
13
+ echo "$text" | grep -qE 'eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}' 2>/dev/null && found="${found}jwt "
14
+ echo "$text" | grep -qE 'gh[pousr]_[A-Za-z0-9_]{36,}' 2>/dev/null && found="${found}github_token "
15
+ # Output one per line (trimmed)
16
+ for t in $found; do echo "$t"; done
17
+ }
18
+
19
+ # --- AWS policy violation patterns (from internal-rules.md) ---
20
+ _detect_aws_violations() {
21
+ local text="$1"
22
+ local found=""
23
+ echo "$text" | grep -qE '0\.0\.0\.0/0' 2>/dev/null && found="${found}open_cidr "
24
+ echo "$text" | grep -qF '::/0' 2>/dev/null && found="${found}open_ipv6 "
25
+ echo "$text" | grep -qEi 'PublicRead|public-read|PublicReadWrite|public-read-write' 2>/dev/null && found="${found}public_acl "
26
+ echo "$text" | grep -qEi 'BlockPublicAccess.*false|block_public_access.*false' 2>/dev/null && found="${found}block_public_false "
27
+ echo "$text" | grep -qE '"Effect"[[:space:]]*:[[:space:]]*"Allow".*"Principal"[[:space:]]*:[[:space:]]*"\*"' 2>/dev/null && found="${found}wildcard_principal "
28
+ echo "$text" | grep -qE '"Scheme"[[:space:]]*:[[:space:]]*"internet-facing"' 2>/dev/null && found="${found}internet_facing "
29
+ echo "$text" | grep -qEi 'AssignPublicIp.*ENABLED|assign_public_ip.*true' 2>/dev/null && found="${found}public_ip "
30
+ echo "$text" | grep -qE '"EndpointType"[[:space:]]*:[[:space:]]*"EDGE"' 2>/dev/null && found="${found}public_apigw "
31
+ for t in $found; do echo "$t"; done
32
+ }
33
+
34
+ # --- Destructive command patterns ---
35
+ _detect_destructive_ops() {
36
+ local text="$1"
37
+ echo "$text" | grep -qEi 'rm[[:space:]]+-[a-zA-Z]*r[a-zA-Z]*f|rm[[:space:]]+-[a-zA-Z]*f[a-zA-Z]*r' 2>/dev/null && return 0
38
+ echo "$text" | grep -qEi 'git[[:space:]]+push[[:space:]]+.*--force' 2>/dev/null && return 0
39
+ echo "$text" | grep -qEi 'git[[:space:]]+reset[[:space:]]+--hard' 2>/dev/null && return 0
40
+ echo "$text" | grep -qEi 'DROP[[:space:]]+TABLE' 2>/dev/null && return 0
41
+ echo "$text" | grep -qEi 'DELETE[[:space:]]+FROM' 2>/dev/null && return 0
42
+ return 1
43
+ }
44
+
45
+ # --- Sensitive file path patterns ---
46
+ _detect_sensitive_paths() {
47
+ local text="$1"
48
+ echo "$text" | grep -qEi '\.env|credentials|\.pem$|\.key$|id_rsa' 2>/dev/null && return 0
49
+ return 1
50
+ }
51
+
52
+ # --- Elevated privilege patterns ---
53
+ _detect_elevated_privilege() {
54
+ local text="$1"
55
+ echo "$text" | grep -qE 'sudo[[:space:]]+|\bchmod[[:space:]]+|\bchown[[:space:]]+' 2>/dev/null && return 0
56
+ return 1
57
+ }
@@ -0,0 +1,80 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const BIOME_CONFIGS = ['biome.json', 'biome.jsonc'];
7
+ const PRETTIER_CONFIGS = [
8
+ '.prettierrc', '.prettierrc.json', '.prettierrc.js', '.prettierrc.cjs',
9
+ '.prettierrc.mjs', '.prettierrc.yml', '.prettierrc.yaml', '.prettierrc.toml',
10
+ 'prettier.config.js', 'prettier.config.cjs', 'prettier.config.mjs',
11
+ ];
12
+ const ROOT_MARKERS = ['package.json', ...BIOME_CONFIGS, ...PRETTIER_CONFIGS];
13
+
14
+ const FORMATTER_PACKAGES = {
15
+ biome: { binName: 'biome', pkgName: '@biomejs/biome' },
16
+ prettier: { binName: 'prettier', pkgName: 'prettier' },
17
+ };
18
+
19
+ const rootCache = new Map();
20
+ const formatterCache = new Map();
21
+ const binCache = new Map();
22
+
23
+ function findProjectRoot(startDir) {
24
+ if (rootCache.has(startDir)) return rootCache.get(startDir);
25
+ let dir = startDir;
26
+ while (dir !== path.dirname(dir)) {
27
+ if (ROOT_MARKERS.some(m => fs.existsSync(path.join(dir, m)))) {
28
+ rootCache.set(startDir, dir);
29
+ return dir;
30
+ }
31
+ dir = path.dirname(dir);
32
+ }
33
+ rootCache.set(startDir, startDir);
34
+ return startDir;
35
+ }
36
+
37
+ function detectFormatter(projectRoot) {
38
+ if (formatterCache.has(projectRoot)) return formatterCache.get(projectRoot);
39
+ if (BIOME_CONFIGS.some(f => fs.existsSync(path.join(projectRoot, f)))) {
40
+ formatterCache.set(projectRoot, 'biome');
41
+ return 'biome';
42
+ }
43
+ try {
44
+ const pkgPath = path.join(projectRoot, 'package.json');
45
+ if (fs.existsSync(pkgPath)) {
46
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
47
+ if ('prettier' in pkg) {
48
+ formatterCache.set(projectRoot, 'prettier');
49
+ return 'prettier';
50
+ }
51
+ }
52
+ } catch { /* malformed package.json */ }
53
+ if (PRETTIER_CONFIGS.some(f => fs.existsSync(path.join(projectRoot, f)))) {
54
+ formatterCache.set(projectRoot, 'prettier');
55
+ return 'prettier';
56
+ }
57
+ formatterCache.set(projectRoot, null);
58
+ return null;
59
+ }
60
+
61
+ function resolveFormatterBin(projectRoot, formatter) {
62
+ const key = `${projectRoot}:${formatter}`;
63
+ if (binCache.has(key)) return binCache.get(key);
64
+ const pkg = FORMATTER_PACKAGES[formatter];
65
+ if (!pkg) { binCache.set(key, null); return null; }
66
+ const localBin = path.join(projectRoot, 'node_modules', '.bin', pkg.binName);
67
+ const result = fs.existsSync(localBin)
68
+ ? { bin: localBin, prefix: [] }
69
+ : { bin: 'npx', prefix: [pkg.pkgName] };
70
+ binCache.set(key, result);
71
+ return result;
72
+ }
73
+
74
+ function clearCaches() {
75
+ rootCache.clear();
76
+ formatterCache.clear();
77
+ binCache.clear();
78
+ }
79
+
80
+ module.exports = { findProjectRoot, detectFormatter, resolveFormatterBin, clearCaches };
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Post-Edit Accumulator
4
+ *
5
+ * Records edited JS/TS file paths to a session-scoped temp file.
6
+ * stop-format-typecheck.js reads this list at stop time for batch processing.
7
+ *
8
+ * Uses telemetry session ID when available, falls back to CWD hash.
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ const crypto = require('crypto');
14
+ const fs = require('fs');
15
+ const os = require('os');
16
+ const path = require('path');
17
+
18
+ const MAX_STDIN = 1024 * 1024;
19
+ const JS_TS_EXT = /\.(ts|tsx|js|jsx)$/;
20
+
21
+ function getSessionId() {
22
+ // Try telemetry session file first
23
+ const hooksDir = __dirname;
24
+ const sessionDir = path.resolve(hooksDir, '..', 'telemetry', '..', '..', '.telemetry', 'sessions');
25
+ try {
26
+ const files = fs.readdirSync(sessionDir).filter(f => f.endsWith('.session'));
27
+ if (files.length > 0) {
28
+ // Most recent by mtime
29
+ const sorted = files
30
+ .map(f => ({ name: f, mtime: fs.statSync(path.join(sessionDir, f)).mtimeMs }))
31
+ .sort((a, b) => b.mtime - a.mtime);
32
+ const data = JSON.parse(fs.readFileSync(path.join(sessionDir, sorted[0].name), 'utf8'));
33
+ if (data.session_id) return data.session_id.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 64);
34
+ }
35
+ } catch { /* fall through */ }
36
+ return crypto.createHash('sha1').update(process.cwd()).digest('hex').slice(0, 12);
37
+ }
38
+
39
+ function getAccumFile() {
40
+ return path.join(os.tmpdir(), `flow-agents-edited-${getSessionId()}.txt`);
41
+ }
42
+
43
+ function run(rawInput) {
44
+ try {
45
+ const input = JSON.parse(rawInput);
46
+ const filePath = input.tool_input?.path || input.tool_input?.file_path || '';
47
+ if (filePath && JS_TS_EXT.test(filePath)) {
48
+ fs.appendFileSync(getAccumFile(), filePath + '\n', 'utf8');
49
+ }
50
+ } catch { /* pass through */ }
51
+ return rawInput;
52
+ }
53
+
54
+ if (require.main === module) {
55
+ let data = '';
56
+ process.stdin.setEncoding('utf8');
57
+ process.stdin.on('data', chunk => {
58
+ if (data.length < MAX_STDIN) data += chunk.substring(0, MAX_STDIN - data.length);
59
+ });
60
+ process.stdin.on('end', () => {
61
+ process.stdout.write(run(data));
62
+ process.exit(0);
63
+ });
64
+ }
65
+
66
+ module.exports = { run, getAccumFile };
@@ -0,0 +1,194 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Pre-Commit Quality Gate
4
+ *
5
+ * Intercepts git commit commands and runs quality checks:
6
+ * - Staged file content scanning (secrets, debugger, console.log, TODO)
7
+ * - Commit message validation (conventional commits)
8
+ * - Linter execution (ESLint, Pylint, golint)
9
+ *
10
+ * Exit codes: 0 = allow (warnings only), 2 = block (errors found)
11
+ */
12
+
13
+ 'use strict';
14
+
15
+ const { spawnSync } = require('child_process');
16
+ const path = require('path');
17
+ const fs = require('fs');
18
+
19
+ const MAX_STDIN = 1024 * 1024;
20
+ const CHECKABLE_EXT = ['.js', '.jsx', '.ts', '.tsx', '.py', '.go', '.rs'];
21
+
22
+ const SECRET_PATTERNS = [
23
+ { pattern: /sk-[a-zA-Z0-9]{20,}/, name: 'OpenAI API key' },
24
+ { pattern: /ghp_[a-zA-Z0-9]{36}/, name: 'GitHub PAT' },
25
+ { pattern: /AKIA[A-Z0-9]{16}/, name: 'AWS Access Key' },
26
+ { pattern: /api[_-]?key\s*[=:]\s*['"][^'"]+['"]/i, name: 'API key' },
27
+ ];
28
+
29
+ function getStagedFiles() {
30
+ const r = spawnSync('git', ['diff', '--cached', '--name-only', '--diff-filter=ACMR'], { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
31
+ return r.status === 0 ? r.stdout.trim().split('\n').filter(Boolean) : [];
32
+ }
33
+
34
+ function getStagedContent(filePath) {
35
+ const r = spawnSync('git', ['show', `:${filePath}`], { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
36
+ return r.status === 0 ? r.stdout : null;
37
+ }
38
+
39
+ function findFileIssues(filePath) {
40
+ const issues = [];
41
+ const content = getStagedContent(filePath);
42
+ if (!content) return issues;
43
+
44
+ content.split('\n').forEach((line, i) => {
45
+ const lineNum = i + 1;
46
+ if (line.includes('console.log') && !line.trim().startsWith('//') && !line.trim().startsWith('*')) {
47
+ issues.push({ severity: 'warning', message: `console.log at line ${lineNum}` });
48
+ }
49
+ if (/\bdebugger\b/.test(line) && !line.trim().startsWith('//')) {
50
+ issues.push({ severity: 'error', message: `debugger statement at line ${lineNum}` });
51
+ }
52
+ const todo = line.match(/\/\/\s*(TODO|FIXME):?\s*(.+)/);
53
+ if (todo && !todo[2].match(/#\d+|issue/i)) {
54
+ issues.push({ severity: 'info', message: `${todo[1]} without issue ref at line ${lineNum}` });
55
+ }
56
+ for (const { pattern, name } of SECRET_PATTERNS) {
57
+ if (pattern.test(line)) {
58
+ issues.push({ severity: 'error', message: `Potential ${name} at line ${lineNum}` });
59
+ }
60
+ }
61
+ });
62
+ return issues;
63
+ }
64
+
65
+ function validateCommitMessage(command) {
66
+ const m = command.match(/(?:-m|--message)[=\s]+["']?([^"']+)["']?/);
67
+ if (!m) return null;
68
+ const msg = m[1];
69
+ const issues = [];
70
+ const conventional = /^(feat|fix|docs|style|refactor|test|chore|build|ci|perf|revert)(\(.+\))?!?:\s*.+/;
71
+ if (!conventional.test(msg)) {
72
+ issues.push({ message: 'Not conventional commit format', suggestion: 'type(scope): description' });
73
+ }
74
+ if (msg.length > 72) issues.push({ message: `Too long (${msg.length}/72 chars)` });
75
+ if (conventional.test(msg)) {
76
+ const after = msg.split(':')[1];
77
+ if (after && /^\s*[A-Z]/.test(after)) issues.push({ message: 'Lowercase after colon' });
78
+ }
79
+ if (msg.endsWith('.')) issues.push({ message: 'No trailing period' });
80
+ return { message: msg, issues };
81
+ }
82
+
83
+ function runLinter(files) {
84
+ const results = {};
85
+ const jsFiles = files.filter(f => /\.(js|jsx|ts|tsx)$/.test(f));
86
+ if (jsFiles.length > 0) {
87
+ const eslintPath = path.join(process.cwd(), 'node_modules', '.bin', 'eslint');
88
+ if (fs.existsSync(eslintPath)) {
89
+ const r = spawnSync(eslintPath, ['--format', 'compact', ...jsFiles], { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 30000 });
90
+ results.eslint = { success: r.status === 0, output: r.stdout || r.stderr };
91
+ }
92
+ }
93
+ const pyFiles = files.filter(f => f.endsWith('.py'));
94
+ if (pyFiles.length > 0) {
95
+ try {
96
+ const r = spawnSync('pylint', ['--output-format=text', ...pyFiles], { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 30000 });
97
+ if (!r.error || r.error.code !== 'ENOENT') results.pylint = { success: r.status === 0, output: r.stdout || r.stderr };
98
+ } catch { /* not available */ }
99
+ }
100
+ const goFiles = files.filter(f => f.endsWith('.go'));
101
+ if (goFiles.length > 0) {
102
+ try {
103
+ const r = spawnSync('golint', goFiles, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 30000 });
104
+ if (!r.error || r.error.code !== 'ENOENT') results.golint = { success: !r.stdout || !r.stdout.trim(), output: r.stdout };
105
+ } catch { /* not available */ }
106
+ }
107
+ return results;
108
+ }
109
+
110
+ function evaluate(rawInput) {
111
+ try {
112
+ const input = JSON.parse(rawInput);
113
+ const command = input.tool_input?.command || '';
114
+ if (!command.includes('git commit') || command.includes('--amend')) {
115
+ return { output: rawInput, exitCode: 0 };
116
+ }
117
+
118
+ const staged = getStagedFiles();
119
+ if (staged.length === 0) {
120
+ process.stderr.write('[Hook] No staged files found.\n');
121
+ return { output: rawInput, exitCode: 0 };
122
+ }
123
+
124
+ process.stderr.write(`[Hook] Checking ${staged.length} staged file(s)...\n`);
125
+ const checkable = staged.filter(f => CHECKABLE_EXT.some(ext => f.endsWith(ext)));
126
+ let errors = 0, warnings = 0, infos = 0;
127
+
128
+ for (const file of checkable) {
129
+ const issues = findFileIssues(file);
130
+ if (issues.length > 0) {
131
+ process.stderr.write(`\n[FILE] ${file}\n`);
132
+ for (const issue of issues) {
133
+ const label = issue.severity === 'error' ? 'ERROR' : issue.severity === 'warning' ? 'WARNING' : 'INFO';
134
+ process.stderr.write(` ${label} ${issue.message}\n`);
135
+ if (issue.severity === 'error') errors++;
136
+ else if (issue.severity === 'warning') warnings++;
137
+ else infos++;
138
+ }
139
+ }
140
+ }
141
+
142
+ const msgResult = validateCommitMessage(command);
143
+ if (msgResult && msgResult.issues.length > 0) {
144
+ process.stderr.write('\nCommit Message Issues:\n');
145
+ for (const issue of msgResult.issues) {
146
+ process.stderr.write(` WARNING ${issue.message}\n`);
147
+ if (issue.suggestion) process.stderr.write(` TIP ${issue.suggestion}\n`);
148
+ warnings++;
149
+ }
150
+ }
151
+
152
+ const lintResults = runLinter(checkable);
153
+ for (const [name, result] of Object.entries(lintResults)) {
154
+ if (result && !result.success) {
155
+ process.stderr.write(`\n${name} Issues:\n${result.output}\n`);
156
+ errors++;
157
+ }
158
+ }
159
+
160
+ const total = errors + warnings + infos;
161
+ if (total > 0) {
162
+ process.stderr.write(`\nSummary: ${total} issue(s) (${errors} error, ${warnings} warning, ${infos} info)\n`);
163
+ if (errors > 0) {
164
+ process.stderr.write('[Hook] ERROR: Commit blocked. Fix critical issues first.\n');
165
+ return { output: rawInput, exitCode: 2 };
166
+ }
167
+ process.stderr.write('[Hook] WARNING: Warnings found but commit allowed.\n');
168
+ } else {
169
+ process.stderr.write('[Hook] PASS: All checks passed!\n');
170
+ }
171
+ } catch (e) {
172
+ process.stderr.write(`[Hook] Error: ${e.message}\n`);
173
+ }
174
+ return { output: rawInput, exitCode: 0 };
175
+ }
176
+
177
+ function run(rawInput) {
178
+ return evaluate(rawInput).output;
179
+ }
180
+
181
+ if (require.main === module) {
182
+ let data = '';
183
+ process.stdin.setEncoding('utf8');
184
+ process.stdin.on('data', chunk => {
185
+ if (data.length < MAX_STDIN) data += chunk.substring(0, MAX_STDIN - data.length);
186
+ });
187
+ process.stdin.on('end', () => {
188
+ const result = evaluate(data);
189
+ process.stdout.write(result.output);
190
+ process.exit(result.exitCode);
191
+ });
192
+ }
193
+
194
+ module.exports = { run, evaluate };