@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,337 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Stop Hook: warn when an active workflow is about to stop short of its goal.
4
+ *
5
+ * The hook reads .flow-agents artifacts, looks for the most recent active
6
+ * delivery/session file, and reports missing Definition Of Done, Goal Fit, or
7
+ * Final Acceptance state. It is warning-only by default. Set
8
+ * FLOW_AGENTS_GOAL_FIT_STRICT=true to return exit code 2 when local goal fit is
9
+ * incomplete.
10
+ */
11
+
12
+ 'use strict';
13
+
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+ const { spawnSync } = require('child_process');
17
+
18
+ const MAX_STDIN = 1024 * 1024;
19
+ const ACTIVE_STATUSES = new Set([
20
+ 'planning',
21
+ 'planned',
22
+ 'executing',
23
+ 'executed',
24
+ 'reviewing',
25
+ 'verifying',
26
+ 'failed',
27
+ 'needs-decision',
28
+ 'in-progress',
29
+ 'blocked',
30
+ 'partial',
31
+ ]);
32
+ const DELIVERY_TYPES = new Set(['deliver', 'delivery', 'fix-bug', 'execute-plan', 'verify-work']);
33
+ const SIDECAR_NAMES = new Set(['state.json', 'acceptance.json', 'evidence.json', 'handoff.json']);
34
+ const OPTIONAL_SIDECAR_NAMES = new Set(['critique.json']);
35
+
36
+ function parseJson(raw) {
37
+ try { return JSON.parse(raw || '{}'); } catch { return {}; }
38
+ }
39
+
40
+ function findRepoRoot(startDir) {
41
+ let dir = path.resolve(startDir || process.cwd());
42
+ const root = path.parse(dir).root;
43
+ for (let depth = 0; dir && depth < 40; depth++) {
44
+ if (fs.existsSync(path.join(dir, '.git')) || fs.existsSync(path.join(dir, 'AGENTS.md'))) return dir;
45
+ if (dir === root) break;
46
+ dir = path.dirname(dir);
47
+ }
48
+ return path.resolve(startDir || process.cwd());
49
+ }
50
+
51
+ function walkMarkdown(dir, out = []) {
52
+ if (!fs.existsSync(dir)) return out;
53
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
54
+ const full = path.join(dir, entry.name);
55
+ if (entry.isDirectory()) {
56
+ if (entry.name === 'archive') continue;
57
+ walkMarkdown(full, out);
58
+ } else if (entry.isFile() && entry.name.endsWith('.md')) {
59
+ out.push(full);
60
+ }
61
+ }
62
+ return out;
63
+ }
64
+
65
+ function readArtifact(file) {
66
+ let text = '';
67
+ try { text = fs.readFileSync(file, 'utf8'); } catch { return null; }
68
+ const stat = fs.statSync(file);
69
+ const status = (text.match(/^status:\s*([A-Za-z0-9_-]+)/m) || [])[1] || '';
70
+ const type = (text.match(/^type:\s*([A-Za-z0-9_-]+)/m) || [])[1] || '';
71
+ const role = (text.match(/^role:\s*([A-Za-z0-9_-]+)/m) || [])[1] || '';
72
+ return { file, text, status, type, role, mtimeMs: stat.mtimeMs };
73
+ }
74
+
75
+ function hasSidecars(dir) {
76
+ try {
77
+ return fs.readdirSync(dir).some(name => SIDECAR_NAMES.has(name));
78
+ } catch {
79
+ return false;
80
+ }
81
+ }
82
+
83
+ function sidecarValidation(root, artifactDir) {
84
+ const requireSidecars = String(process.env.FLOW_AGENTS_REQUIRE_SIDECARS || '').toLowerCase() === 'true';
85
+ const requireCritique = String(process.env.FLOW_AGENTS_REQUIRE_CRITIQUE || '').toLowerCase() === 'true';
86
+ if (!requireSidecars && !requireCritique && !hasSidecars(artifactDir)) return [];
87
+
88
+ const packageRoot = fs.existsSync(path.join(root, 'package.json'))
89
+ ? root
90
+ : path.resolve(__dirname, '..', '..');
91
+ const packageJson = path.join(packageRoot, 'package.json');
92
+ if (!fs.existsSync(packageJson)) return [`${relative(root, artifactDir)} sidecar validation: package.json is missing; cannot run TypeScript workflow validator.`];
93
+
94
+ let sidecarFiles = [];
95
+ try {
96
+ sidecarFiles = fs.readdirSync(artifactDir)
97
+ .filter(name => SIDECAR_NAMES.has(name) || OPTIONAL_SIDECAR_NAMES.has(name))
98
+ .map(name => path.join(artifactDir, name));
99
+ } catch {
100
+ sidecarFiles = [];
101
+ }
102
+
103
+ if (requireSidecars || requireCritique) {
104
+ const present = new Set(sidecarFiles.map(file => path.basename(file)));
105
+ const requiredNames = new Set(requireSidecars ? SIDECAR_NAMES : []);
106
+ if (requireCritique) requiredNames.add('critique.json');
107
+ const missing = [...requiredNames].filter(name => !present.has(name)).sort();
108
+ if (missing.length > 0) {
109
+ return missing.map(name => `${relative(root, path.join(artifactDir, name))} sidecar validation: required sidecar is missing`);
110
+ }
111
+ }
112
+
113
+ if (sidecarFiles.length === 0) return [];
114
+
115
+ const args = ['run', 'workflow:validate-artifacts', '--silent', '--'];
116
+ args.push('--skip-markdown-validation');
117
+ if (requireSidecars) args.push('--require-sidecars');
118
+ if (requireCritique) args.push('--require-critique');
119
+ args.push(artifactDir);
120
+
121
+ const result = spawnSync('npm', args, {
122
+ cwd: packageRoot,
123
+ encoding: 'utf8',
124
+ timeout: 30000,
125
+ });
126
+
127
+ if (result.status === 0) return [];
128
+ const output = `${result.stdout || ''}\n${result.stderr || ''}`
129
+ .split('\n')
130
+ .map(line => line.trim())
131
+ .filter(Boolean)
132
+ .slice(0, 12);
133
+ if (output.length === 0) output.push(`validator exited with status ${result.status ?? 'unknown'}`);
134
+ return output.map(line => `${relative(root, artifactDir)} sidecar validation: ${line}`);
135
+ }
136
+
137
+ function isWorkflowArtifact(artifact) {
138
+ if (!artifact) return false;
139
+ if (artifact.role === 'plan' || artifact.role === 'review') return false;
140
+ if (artifact.file.endsWith('-plan.md') || artifact.file.endsWith('-review.md')) return false;
141
+ if (DELIVERY_TYPES.has(artifact.type)) return true;
142
+ return /--(deliver|fix-bug|execute-plan|verify-work)\b/.test(path.basename(artifact.file));
143
+ }
144
+
145
+ function uncheckedInSection(text, heading) {
146
+ const start = text.indexOf(`## ${heading}`);
147
+ if (start < 0) return [];
148
+ const rest = text.slice(start + heading.length + 3);
149
+ const next = rest.search(/\n##\s+/);
150
+ const section = next >= 0 ? rest.slice(0, next) : rest;
151
+ return section
152
+ .split('\n')
153
+ .filter(line => /^\s*-\s+\[\s\]/.test(line))
154
+ .map(line => line.replace(/^\s*-\s+\[\s\]\s*/, '').trim())
155
+ .filter(Boolean);
156
+ }
157
+
158
+ function hasHeading(text, heading) {
159
+ return new RegExp(`^##\\s+${heading.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*$`, 'm').test(text);
160
+ }
161
+
162
+ function relative(root, file) {
163
+ return path.relative(root, file).split(path.sep).join('/');
164
+ }
165
+
166
+ function readJsonFile(file) {
167
+ try {
168
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
169
+ } catch {
170
+ return null;
171
+ }
172
+ }
173
+
174
+ function safeOneLine(value, maxLength = 220) {
175
+ const text = String(value || '').replace(/\s+/g, ' ').trim();
176
+ if (text.length <= maxLength) return text;
177
+ return `${text.slice(0, maxLength - 3)}...`;
178
+ }
179
+
180
+ function normalizedStatus(value) {
181
+ return safeOneLine(value, 80).toLowerCase();
182
+ }
183
+
184
+ function sidecarGuidance(root, artifactDir) {
185
+ const warnings = [];
186
+ const state = readJsonFile(path.join(artifactDir, 'state.json'));
187
+ const evidence = readJsonFile(path.join(artifactDir, 'evidence.json'));
188
+ const critique = readJsonFile(path.join(artifactDir, 'critique.json'));
189
+ const base = relative(root, artifactDir);
190
+
191
+ if (state) {
192
+ const status = normalizedStatus(state.status || 'unknown');
193
+ const phase = normalizedStatus(state.phase || 'unknown');
194
+ const next = state.next_action && typeof state.next_action === 'object' ? state.next_action : null;
195
+ if (!['done', 'delivered', 'archived', 'accepted', 'complete', 'completed'].includes(status)) {
196
+ const nextStatus = next ? normalizedStatus(next.status || 'unknown') : 'unknown';
197
+ const nextSummary = next && next.summary ? `; next_action:${nextStatus} "${safeOneLine(next.summary)}"` : '';
198
+ warnings.push(`${base} workflow state: status:${status} phase:${phase}${nextSummary}`);
199
+ }
200
+ }
201
+
202
+ if (state && state.next_action && normalizedStatus(state.next_action.status) !== 'done') {
203
+ const next = state.next_action;
204
+ warnings.push(`${base} next action: ${safeOneLine(next.summary)}${next.target_phase ? ` (target phase: ${safeOneLine(next.target_phase, 80)})` : ''}`);
205
+ }
206
+
207
+ if (evidence && normalizedStatus(evidence.verdict) && normalizedStatus(evidence.verdict) !== 'pass') {
208
+ warnings.push(`${base} evidence verdict:${safeOneLine(evidence.verdict, 40)}; do not deliver without accepted gap or new evidence.`);
209
+ }
210
+ if (evidence && Array.isArray(evidence.not_verified_gaps) && evidence.not_verified_gaps.length > 0) {
211
+ for (const gap of evidence.not_verified_gaps.slice(0, 3)) {
212
+ warnings.push(`${base} evidence NOT_VERIFIED gap: ${safeOneLine(gap)}`);
213
+ }
214
+ }
215
+ if (evidence && Array.isArray(evidence.checks)) {
216
+ const blockingChecks = evidence.checks.filter(check => {
217
+ const status = normalizedStatus(check && check.status);
218
+ return status === 'fail' || status === 'failed' || status === 'not_verified' || status === 'not-verified';
219
+ });
220
+ for (const check of blockingChecks.slice(0, 4)) {
221
+ const status = safeOneLine(check.status || 'unknown', 40);
222
+ warnings.push(`${base} evidence check ${safeOneLine(check.id || 'unknown', 80)} status:${status}: ${safeOneLine(check.summary)}`);
223
+ }
224
+ }
225
+
226
+ if (critique && critique.required === true && normalizedStatus(critique.status) !== 'pass') {
227
+ warnings.push(`${base} critique status:${safeOneLine(critique.status || 'unknown', 40)}; required critique must pass or findings be accepted.`);
228
+ const critiques = Array.isArray(critique.critiques) ? critique.critiques : [];
229
+ let openCount = 0;
230
+ for (const review of critiques) {
231
+ const findings = Array.isArray(review && review.findings) ? review.findings : [];
232
+ for (const finding of findings) {
233
+ if (!finding || normalizedStatus(finding.status) !== 'open') continue;
234
+ warnings.push(`${base} critique open ${safeOneLine(finding.severity || 'unknown', 40)}: ${safeOneLine(finding.description)}`);
235
+ openCount += 1;
236
+ if (openCount >= 3) break;
237
+ }
238
+ if (openCount >= 3) break;
239
+ }
240
+ }
241
+
242
+ return warnings;
243
+ }
244
+
245
+ function markdownVerdict(text) {
246
+ const verdict = (/###\s+Verdict:\s*([A-Za-z_ -]+)/i.exec(text) || [])[1]
247
+ || (/^Build:\s*\[?([A-Za-z_ -]+)\]?/im.exec(text) || [])[1]
248
+ || '';
249
+ return normalizedStatus(verdict).replace(/[^a-z_ -].*$/, '').trim();
250
+ }
251
+
252
+ function analyze(root, now = Date.now()) {
253
+ const dirs = [path.join(root, '.flow-agents')];
254
+ const artifacts = dirs
255
+ .flatMap(dir => walkMarkdown(dir))
256
+ .map(readArtifact)
257
+ .filter(isWorkflowArtifact)
258
+ .sort((a, b) => b.mtimeMs - a.mtimeMs);
259
+
260
+ if (artifacts.length === 0) return { warnings: [], blocking: false };
261
+
262
+ const latest = artifacts[0];
263
+ const warnings = [];
264
+ const relPath = relative(root, latest.file);
265
+ const status = latest.status || 'unknown';
266
+ const ageMinutes = Math.max(0, Math.round((now - latest.mtimeMs) / 60000));
267
+
268
+ if (ACTIVE_STATUSES.has(status)) {
269
+ warnings.push(`${relPath} is still status:${status} (${ageMinutes}m old). Do not final-answer as complete unless the next step is explicit.`);
270
+ }
271
+
272
+ if (!hasHeading(latest.text, 'Definition Of Done')) {
273
+ warnings.push(`${relPath} is missing ## Definition Of Done, so the user-facing finish line is not explicit.`);
274
+ }
275
+
276
+ if (!hasHeading(latest.text, 'Goal Fit Gate')) {
277
+ warnings.push(`${relPath} is missing ## Goal Fit Gate, so local acceptance has not been checked.`);
278
+ } else {
279
+ for (const item of uncheckedInSection(latest.text, 'Goal Fit Gate').slice(0, 6)) {
280
+ warnings.push(`${relPath} Goal Fit unchecked: ${item}`);
281
+ }
282
+ }
283
+
284
+ if (status === 'delivered' && hasHeading(latest.text, 'Final Acceptance')) {
285
+ const uncheckedFinal = uncheckedInSection(latest.text, 'Final Acceptance');
286
+ if (uncheckedFinal.length > 0) {
287
+ warnings.push(`${relPath} local delivery is marked delivered, but Final Acceptance still has ${uncheckedFinal.length} open item(s) for CI/merge/docs promotion.`);
288
+ }
289
+ }
290
+
291
+ warnings.push(...sidecarValidation(root, path.dirname(latest.file)));
292
+ const evidence = readJsonFile(path.join(path.dirname(latest.file), 'evidence.json'));
293
+ if (evidence && markdownVerdict(latest.text) === 'pass' && normalizedStatus(evidence.verdict) === 'fail') {
294
+ warnings.push(`${relPath} Markdown PASS contradicts evidence.json verdict fail.`);
295
+ }
296
+ warnings.push(...sidecarGuidance(root, path.dirname(latest.file)));
297
+
298
+ const blocking = warnings.some(w => /status:|Definition Of Done|Goal Fit|sidecar validation|contradicts evidence\.json|workflow state|evidence verdict|evidence check|NOT_VERIFIED gap|critique status|critique open|next action/.test(w));
299
+ return { warnings, blocking };
300
+ }
301
+
302
+ function run(rawInput) {
303
+ const input = parseJson(rawInput);
304
+ const root = findRepoRoot(input.cwd || process.cwd());
305
+ const result = analyze(root);
306
+ if (result.warnings.length === 0) return rawInput;
307
+
308
+ const message = [
309
+ '[Hook] Goal Fit warning:',
310
+ ...result.warnings.map(w => ` - ${w}`),
311
+ ].join('\n');
312
+ const strict = String(process.env.FLOW_AGENTS_GOAL_FIT_STRICT || '').toLowerCase() === 'true';
313
+ return {
314
+ stdout: rawInput,
315
+ stderr: message,
316
+ exitCode: strict && result.blocking ? 2 : 0,
317
+ };
318
+ }
319
+
320
+ if (require.main === module) {
321
+ let data = '';
322
+ process.stdin.setEncoding('utf8');
323
+ process.stdin.on('data', chunk => {
324
+ if (data.length < MAX_STDIN) data += chunk.substring(0, MAX_STDIN - data.length);
325
+ });
326
+ process.stdin.on('end', () => {
327
+ const output = run(data);
328
+ if (output && typeof output === 'object') {
329
+ if (output.stderr) process.stderr.write(output.stderr.endsWith('\n') ? output.stderr : `${output.stderr}\n`);
330
+ process.stdout.write(String(output.stdout ?? data));
331
+ process.exit(Number.isInteger(output.exitCode) ? output.exitCode : 0);
332
+ }
333
+ process.stdout.write(String(output));
334
+ });
335
+ }
336
+
337
+ module.exports = { analyze, run, uncheckedInSection, findRepoRoot, sidecarGuidance, safeOneLine };
@@ -0,0 +1,250 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Workflow Steering Hook
4
+ *
5
+ * Injects phase-transition reminders after use_subagent calls complete and
6
+ * ambient workflow-state reminders at the start of the next user turn.
7
+ *
8
+ * Non-blocking — always exits 0.
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+
16
+ const STEERING = {
17
+ 'tool-planner': [
18
+ '⚡ PLAN COMPLETE — Next: execute-plan (step 3).',
19
+ 'Present plan to user. Get approval before executing.',
20
+ ].join(' '),
21
+
22
+ 'tool-worker': [
23
+ '⚡ EXECUTION COMPLETE — Next: review (step 4) then verify (step 5).',
24
+ 'Delegate to review-work for critique (report only — it cannot fix code).',
25
+ 'Then delegate to verify-work for evidence (report only — it cannot fix code).',
26
+ 'Do NOT deliver until review + verify are both clean.',
27
+ 'If this was a VISUAL change (UI, CSS, HTML), you MUST delegate to tool-playwright for screenshot verification before delivering.',
28
+ ].join(' '),
29
+
30
+ 'tool-code-reviewer': [
31
+ '⚡ REVIEW COMPLETE — Next: verify (step 5).',
32
+ 'Reviewer reported findings only — it did NOT fix anything.',
33
+ 'If CRITICAL/HIGH findings: route back to execute-plan, then re-review + re-verify.',
34
+ 'If clean: proceed to verify-work. If findings exist, route back through execute-plan or a user decision.',
35
+ ].join(' '),
36
+
37
+ 'tool-security-reviewer': [
38
+ '⚡ SECURITY REVIEW COMPLETE — Check findings.',
39
+ 'If CRITICAL security findings: route back to execute-plan, then re-review + re-verify.',
40
+ 'If clean: proceed to next step.',
41
+ ].join(' '),
42
+
43
+ 'tool-verifier': [
44
+ '⚡ VERIFICATION COMPLETE — Route on verdict.',
45
+ 'All PASS + no review issues → deliver.',
46
+ 'Any FAIL or unfixed findings → route back to execute-plan, then re-review + re-verify.',
47
+ 'Loop exits ONLY when review + verify are BOTH clean in the same iteration.',
48
+ ].join(' '),
49
+ };
50
+
51
+ const ACTIVE_STATE_STATUSES = new Set([
52
+ 'new',
53
+ 'planning',
54
+ 'planned',
55
+ 'in_progress',
56
+ 'blocked',
57
+ 'verifying',
58
+ 'verified',
59
+ 'needs_decision',
60
+ 'not_verified',
61
+ 'failed',
62
+ 'delivered',
63
+ ]);
64
+
65
+ function findRepoRoot(startDir) {
66
+ let dir = path.resolve(startDir || process.cwd());
67
+ const root = path.parse(dir).root;
68
+ for (let depth = 0; dir && depth < 40; depth++) {
69
+ if (fs.existsSync(path.join(dir, '.git')) || fs.existsSync(path.join(dir, 'AGENTS.md'))) return dir;
70
+ if (dir === root) break;
71
+ dir = path.dirname(dir);
72
+ }
73
+ return path.resolve(startDir || process.cwd());
74
+ }
75
+
76
+ function walkStateFiles(dir, out = []) {
77
+ if (!fs.existsSync(dir)) return out;
78
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
79
+ const full = path.join(dir, entry.name);
80
+ if (entry.isDirectory()) {
81
+ if (entry.name === 'archive') continue;
82
+ walkStateFiles(full, out);
83
+ } else if (entry.isFile() && entry.name === 'state.json') {
84
+ out.push(full);
85
+ }
86
+ }
87
+ return out;
88
+ }
89
+
90
+ function readJson(file) {
91
+ try {
92
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
93
+ } catch {
94
+ return null;
95
+ }
96
+ }
97
+
98
+ function latestWorkflowState(root) {
99
+ const states = walkStateFiles(path.join(root, '.flow-agents'))
100
+ .map(file => {
101
+ let stat;
102
+ try { stat = fs.statSync(file); } catch { return null; }
103
+ const payload = readJson(file);
104
+ if (!payload || !ACTIVE_STATE_STATUSES.has(payload.status)) return null;
105
+ return { file, payload, mtimeMs: stat.mtimeMs };
106
+ })
107
+ .filter(Boolean)
108
+ .sort((a, b) => b.mtimeMs - a.mtimeMs);
109
+ return states[0] || null;
110
+ }
111
+
112
+ function safeStateText(value, maxLength = 240) {
113
+ const text = String(value || '').replace(/\s+/g, ' ').trim();
114
+ if (text.length <= maxLength) return text;
115
+ return `${text.slice(0, maxLength - 3)}...`;
116
+ }
117
+
118
+ function normalizedStateValue(value) {
119
+ return safeStateText(value, 80).toLowerCase();
120
+ }
121
+
122
+ function stateNeedsAmbientSteering(state) {
123
+ if (!state || typeof state !== 'object') return false;
124
+ const status = normalizedStateValue(state.status);
125
+ const nextStatus = normalizedStateValue(state.next_action && state.next_action.status);
126
+ return (
127
+ status === 'blocked' ||
128
+ status === 'failed' ||
129
+ status === 'needs_decision' ||
130
+ status === 'not_verified' ||
131
+ nextStatus === 'needs_user'
132
+ );
133
+ }
134
+
135
+ function critiqueSteering(workflowDir) {
136
+ const critique = readJson(path.join(workflowDir, 'critique.json'));
137
+ if (!critique || critique.required !== true) return '';
138
+ if (critique.status === 'pass' || critique.status === 'not_required') return '';
139
+ const critiques = Array.isArray(critique.critiques) ? critique.critiques : [];
140
+ const openFindings = [];
141
+ let nonPassReviews = 0;
142
+ for (const review of critiques) {
143
+ if (!review || typeof review !== 'object') continue;
144
+ if (review.verdict === 'fail' || review.verdict === 'not_verified') nonPassReviews += 1;
145
+ const findings = Array.isArray(review.findings) ? review.findings : [];
146
+ for (const finding of findings) {
147
+ if (finding && finding.status === 'open') openFindings.push(finding);
148
+ }
149
+ }
150
+ const parts = [
151
+ `CRITIQUE: required critique is status:${safeStateText(critique.status, 60)}.`,
152
+ ];
153
+ if (nonPassReviews) parts.push(`${nonPassReviews} review(s) have fail/not_verified verdicts.`);
154
+ if (openFindings.length) {
155
+ const severityCounts = openFindings.reduce((acc, finding) => {
156
+ const severity = safeStateText(finding.severity || 'unknown', 30);
157
+ acc[severity] = (acc[severity] || 0) + 1;
158
+ return acc;
159
+ }, {});
160
+ const counts = Object.entries(severityCounts)
161
+ .map(([severity, count]) => `${severity}:${count}`)
162
+ .join(', ');
163
+ parts.push(`Open findings: ${counts}.`);
164
+ parts.push(`First open finding: "${safeStateText(openFindings[0].description)}"`);
165
+ }
166
+ parts.push('Do not deliver as complete until required critique is pass or findings are explicitly accepted.');
167
+ return parts.join(' ');
168
+ }
169
+
170
+ function stateSteering(root) {
171
+ const current = latestWorkflowState(root);
172
+ if (!current) return '';
173
+ const state = current.payload;
174
+ const next = state.next_action || {};
175
+ if (next.status === 'done' || state.status === 'archived' || state.status === 'accepted') return '';
176
+ const parts = [
177
+ `STATE: ${state.task_slug || path.basename(path.dirname(current.file))} is status:${state.status} phase:${state.phase}.`,
178
+ ];
179
+ if (next.summary) parts.push(`Recorded next_action.summary: "${safeStateText(next.summary)}"`);
180
+ if (next.target_phase) parts.push(`Target phase: ${safeStateText(next.target_phase, 80)}.`);
181
+ if (next.status === 'needs_user' || state.status === 'needs_decision' || state.status === 'not_verified') {
182
+ parts.push('Do not deliver as complete until the user decision or accepted gap is recorded.');
183
+ }
184
+ if (state.status === 'failed') {
185
+ parts.push('Route back through execution, then re-review and re-verify.');
186
+ }
187
+ const critiqueHint = critiqueSteering(path.dirname(current.file));
188
+ if (critiqueHint) parts.push(critiqueHint);
189
+ return parts.join(' ');
190
+ }
191
+
192
+ function contextMapSteering(root) {
193
+ const mapPath = path.join(root, 'docs', 'context-map.md');
194
+ if (!fs.existsSync(mapPath)) return '';
195
+ return [
196
+ 'CONTEXT MAP: use docs/context-map.md before broad repo rediscovery.',
197
+ 'If structure, commands, schemas, skills, agents, or packs changed, run `npm run context-map -- --check`.',
198
+ ].join(' ');
199
+ }
200
+
201
+ function run(rawInput) {
202
+ try {
203
+ const input = JSON.parse(rawInput);
204
+ const event = input.hook_event_name || '';
205
+ const toolOutput = input.tool_response || input.tool_output || '';
206
+ const toolInput = input.tool_input || {};
207
+ const root = findRepoRoot(input.cwd || process.cwd());
208
+ const current = latestWorkflowState(root);
209
+ const hints = [];
210
+ let shouldAppendWorkflowContext = false;
211
+
212
+ if (toolInput.command === 'InvokeSubagents') {
213
+ const subagents = toolInput.content?.subagents || [];
214
+ hints.push(...subagents
215
+ .map(s => STEERING[s.agent_name])
216
+ .filter(Boolean));
217
+ shouldAppendWorkflowContext = hints.length > 0;
218
+ }
219
+
220
+ if (event === 'UserPromptSubmit' && current && stateNeedsAmbientSteering(current.payload)) {
221
+ hints.push('WORKFLOW STATE ATTENTION: current sidecars show unresolved workflow state at turn start.');
222
+ shouldAppendWorkflowContext = true;
223
+ }
224
+
225
+ if (shouldAppendWorkflowContext) {
226
+ const stateHint = stateSteering(root);
227
+ if (stateHint) hints.push(stateHint);
228
+ const contextHint = contextMapSteering(root);
229
+ if (contextHint) hints.push(contextHint);
230
+ }
231
+ if (hints.length === 0) return rawInput;
232
+
233
+ const steering = '\n\n---\n' + hints.join('\n') + '\n---';
234
+ return rawInput + steering;
235
+ } catch { /* pass through */ }
236
+ return rawInput;
237
+ }
238
+
239
+ if (require.main === module) {
240
+ let data = '';
241
+ process.stdin.setEncoding('utf8');
242
+ process.stdin.on('data', chunk => {
243
+ data += chunk;
244
+ });
245
+ process.stdin.on('end', () => {
246
+ process.stdout.write(String(run(data)));
247
+ });
248
+ }
249
+
250
+ module.exports = { run, stateSteering, critiqueSteering, contextMapSteering, latestWorkflowState, findRepoRoot, safeStateText, stateNeedsAmbientSteering };
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env bash
2
+ # install-codex-home.sh - Install Flow Agents as an isolated Codex home.
3
+ set -euo pipefail
4
+
5
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
6
+ usage() {
7
+ cat >&2 <<'EOF'
8
+ usage: install-codex-home.sh [destination] [options]
9
+
10
+ Options:
11
+ --telemetry-sink NAME local-files, local-kontour-console,
12
+ kontour-hosted-console, user-hosted-console,
13
+ or legacy aliases. May be repeated.
14
+ --console-url URL Persist Console telemetry base URL.
15
+ --console-endpoint URL Persist full Console telemetry records endpoint URL.
16
+ --console-token-file PATH
17
+ Read Console telemetry bearer token from a file.
18
+ --console-tenant ID Persist Console tenant identifier.
19
+ EOF
20
+ }
21
+
22
+ DEST="$HOME/.flow-agents/codex"
23
+ DEST_SET=0
24
+ CONSOLE_CONFIG_ARGS=()
25
+ while [[ $# -gt 0 ]]; do
26
+ case "$1" in
27
+ --telemetry-sink|--telemetry-sinks|--console-url|--console-endpoint|--console-endpoint-url|--console-token-file|--console-tenant|--console-tenant-id)
28
+ [[ $# -ge 2 ]] || { echo "install-codex-home.sh: $1 requires a value" >&2; exit 2; }
29
+ CONSOLE_CONFIG_ARGS+=("$1" "$2")
30
+ shift 2
31
+ ;;
32
+ --help|-h)
33
+ usage
34
+ exit 0
35
+ ;;
36
+ -*)
37
+ echo "install-codex-home.sh: unknown option: $1" >&2
38
+ usage
39
+ exit 2
40
+ ;;
41
+ *)
42
+ if [[ "$DEST_SET" -eq 1 ]]; then
43
+ echo "install-codex-home.sh: unexpected argument: $1" >&2
44
+ usage
45
+ exit 2
46
+ fi
47
+ DEST="$1"
48
+ DEST_SET=1
49
+ shift
50
+ ;;
51
+ esac
52
+ done
53
+ REAL_CODEX_HOME="${CODEX_REAL_HOME:-$HOME/.codex}"
54
+ if command -v npm >/dev/null 2>&1; then
55
+ (cd "$ROOT_DIR" && FLOW_AGENTS_EXPORT_DIAGNOSTICS=0 npm run build:bundles --silent >/dev/null)
56
+ else
57
+ echo "install-codex-home.sh: requires npm on PATH" >&2
58
+ exit 1
59
+ fi
60
+
61
+ mkdir -p "$DEST"
62
+
63
+ # This is an isolated generated Codex home. Clean generated bundle content before
64
+ # overlaying so renamed/deleted source files do not survive across installs.
65
+ rm -rf \
66
+ "$DEST/.flow-agents" \
67
+ "$DEST/.codex" \
68
+ "$DEST/AGENTS.md" \
69
+ "$DEST/README.md" \
70
+ "$DEST/console.telemetry.json" \
71
+ "$DEST/install.sh" \
72
+ "$DEST/config.toml" \
73
+ "$DEST/hooks.json" \
74
+ "$DEST/agent-cards" \
75
+ "$DEST/agents" \
76
+ "$DEST/context" \
77
+ "$DEST/docs" \
78
+ "$DEST/evals" \
79
+ "$DEST/integrations" \
80
+ "$DEST/kits" \
81
+ "$DEST/packaging" \
82
+ "$DEST/powers" \
83
+ "$DEST/prompts" \
84
+ "$DEST/schemas" \
85
+ "$DEST/scripts" \
86
+ "$DEST/skills"
87
+ find "$DEST" -maxdepth 1 -type f -name 'k*.config.toml' -delete
88
+
89
+ rsync -a "$ROOT_DIR/dist/codex/." "$DEST/"
90
+ rsync -a "$ROOT_DIR/dist/codex/.codex/." "$DEST/"
91
+ rm -rf "$DEST/.codex" 2>/dev/null || true
92
+
93
+ for auth_file in auth.json version.json installation_id models_cache.json; do
94
+ if [[ -f "$REAL_CODEX_HOME/$auth_file" ]]; then
95
+ cp "$REAL_CODEX_HOME/$auth_file" "$DEST/$auth_file"
96
+ fi
97
+ done
98
+
99
+ chmod 700 "$DEST" 2>/dev/null || true
100
+ [[ -f "$DEST/auth.json" ]] && chmod 600 "$DEST/auth.json" 2>/dev/null || true
101
+ if [[ ${#CONSOLE_CONFIG_ARGS[@]} -gt 0 || -n "${FLOW_AGENTS_TELEMETRY_SINK:-}" || -n "${FLOW_AGENTS_TELEMETRY_SINKS:-}" || -n "${FLOW_AGENTS_CONSOLE_URL:-}" || -n "${CONSOLE_TELEMETRY_URL:-}" || -n "${CONSOLE_URL:-}" || -n "${FLOW_AGENTS_CONSOLE_TOKEN_FILE:-}" || -n "${CONSOLE_TELEMETRY_TOKEN_FILE:-}" ]]; then
102
+ bash "$DEST/scripts/telemetry/install-console-config.sh" "$DEST/scripts/telemetry/telemetry.conf" "${CONSOLE_CONFIG_ARGS[@]}"
103
+ fi
104
+
105
+ echo "Installed isolated Flow Agents Codex home at $DEST"
106
+ echo "Use: CODEX_HOME=$DEST codex --profile kdev"
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }