@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,140 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { flagBool, flagString, parseArgs } from "../lib/args.js";
4
+ import { buildWorkflowLearningProjection, readWorkflowLearningSources } from "../lib/workflow-learning-projection.js";
5
+
6
+ type Summary = {
7
+ scanned_learning_file_count: number;
8
+ emitted_learning_count: number;
9
+ destination: string | null;
10
+ producer: string;
11
+ scope: {
12
+ kind: string;
13
+ id: string;
14
+ };
15
+ dry_run: boolean;
16
+ };
17
+
18
+ const SAFE_SEGMENT = /^[A-Za-z0-9._-]+$/;
19
+
20
+ function printHelp(): void {
21
+ console.log("Usage: flow-agents console-learning-projection [options]");
22
+ console.log("");
23
+ console.log("Build an inert Console learning projection from local workflow learning sidecars.");
24
+ console.log("");
25
+ console.log("Options:");
26
+ console.log(" --artifact-root <path> Workflow artifact root to scan (default: .flow-agents)");
27
+ console.log(" --kontour-root <path> Local Kontour root to write under (default: .kontour)");
28
+ console.log(" --scope <id> Projection scope id (default: current directory name)");
29
+ console.log(" --scope-kind <kind> Projection scope kind (default: repo)");
30
+ console.log(" --producer <id> Projection producer id (default: flow-agents-learning)");
31
+ console.log(" --generated-at <ISO> Override generated timestamp for deterministic output");
32
+ console.log(" --dry-run Do not write a projection file");
33
+ console.log(" --json Print stable JSON summary");
34
+ console.log(" --help Show this help");
35
+ }
36
+
37
+ function defaultScopeId(): string {
38
+ return path.basename(process.cwd()) || "local";
39
+ }
40
+
41
+ function requireSafeSegment(value: string, label: string): string {
42
+ if (!SAFE_SEGMENT.test(value)) {
43
+ throw new Error(`${label} must contain only letters, numbers, dot, underscore, or hyphen: ${value}`);
44
+ }
45
+ return value;
46
+ }
47
+
48
+ function ensureNoSymlinkPath(target: string): void {
49
+ const resolved = path.resolve(target);
50
+ const root = path.parse(resolved).root;
51
+ const parts = path.relative(root, resolved).split(path.sep).filter(Boolean);
52
+ let cursor = root;
53
+ for (const part of parts) {
54
+ cursor = path.join(cursor, part);
55
+ if (fs.existsSync(cursor) && fs.lstatSync(cursor).isSymbolicLink()) {
56
+ throw new Error(`refusing to write through symlink path: ${cursor}`);
57
+ }
58
+ }
59
+ }
60
+
61
+ function ensureDirectory(target: string): void {
62
+ ensureNoSymlinkPath(target);
63
+ fs.mkdirSync(target, { recursive: true });
64
+ ensureNoSymlinkPath(target);
65
+ const stat = fs.statSync(target);
66
+ if (!stat.isDirectory()) throw new Error(`destination directory is not a directory: ${target}`);
67
+ }
68
+
69
+ function containedPath(root: string, destination: string): void {
70
+ const relative = path.relative(root, destination);
71
+ if (relative === "" || relative.startsWith("..") || path.isAbsolute(relative)) {
72
+ throw new Error(`destination escapes kontour root: ${destination}`);
73
+ }
74
+ }
75
+
76
+ function destinationPath(kontourRoot: string, producer: string, scopeKind: string, scopeId: string): string {
77
+ const root = path.resolve(kontourRoot);
78
+ const destination = path.resolve(root, "projections", producer, `${scopeKind}-${scopeId}.json`);
79
+ containedPath(root, destination);
80
+ return destination;
81
+ }
82
+
83
+ function writeProjection(file: string, root: string, projection: unknown): void {
84
+ containedPath(root, file);
85
+ ensureDirectory(path.dirname(file));
86
+ if (fs.existsSync(file) && fs.lstatSync(file).isSymbolicLink()) {
87
+ throw new Error(`refusing to write symlinked projection file: ${file}`);
88
+ }
89
+ fs.writeFileSync(file, `${JSON.stringify(projection, null, 2)}\n`, "utf8");
90
+ }
91
+
92
+ function printText(summary: Summary): void {
93
+ console.log(`Scanned learning files: ${summary.scanned_learning_file_count}`);
94
+ console.log(`Emitted learnings: ${summary.emitted_learning_count}`);
95
+ if (summary.dry_run) console.log("Dry run: no projection written");
96
+ else console.log(`Projection: ${summary.destination}`);
97
+ }
98
+
99
+ export function main(argv = process.argv.slice(2)): number {
100
+ const { flags } = parseArgs(argv);
101
+ if (flagBool(flags, "help") || flagBool(flags, "h")) {
102
+ printHelp();
103
+ return 0;
104
+ }
105
+
106
+ try {
107
+ const artifactRoot = path.resolve(flagString(flags, "artifact-root", ".flow-agents") ?? ".flow-agents");
108
+ const kontourRoot = path.resolve(flagString(flags, "kontour-root", ".kontour") ?? ".kontour");
109
+ const producer = requireSafeSegment(flagString(flags, "producer", "flow-agents-learning") ?? "flow-agents-learning", "--producer");
110
+ const scope = {
111
+ kind: requireSafeSegment(flagString(flags, "scope-kind", "repo") ?? "repo", "--scope-kind"),
112
+ id: requireSafeSegment(flagString(flags, "scope", defaultScopeId()) ?? defaultScopeId(), "--scope"),
113
+ };
114
+ const dryRun = flagBool(flags, "dry-run");
115
+ const sources = readWorkflowLearningSources(artifactRoot);
116
+ const projection = buildWorkflowLearningProjection(sources, {
117
+ scope,
118
+ producer: { id: producer, product: "flow-agents" },
119
+ generatedAt: flagString(flags, "generated-at"),
120
+ });
121
+ const destination = dryRun ? null : destinationPath(kontourRoot, producer, scope.kind, scope.id);
122
+ if (destination) writeProjection(destination, kontourRoot, projection);
123
+ const summary: Summary = {
124
+ scanned_learning_file_count: sources.length,
125
+ emitted_learning_count: projection.learnings.length,
126
+ destination,
127
+ producer,
128
+ scope,
129
+ dry_run: dryRun,
130
+ };
131
+ if (flagBool(flags, "json")) console.log(JSON.stringify(summary, null, 2));
132
+ else printText(summary);
133
+ return 0;
134
+ } catch (error) {
135
+ console.error(`console-learning-projection: ${error instanceof Error ? error.message : String(error)}`);
136
+ return 1;
137
+ }
138
+ }
139
+
140
+ if (import.meta.url === `file://${process.argv[1]}`) process.exit(main());
@@ -0,0 +1,99 @@
1
+ import * as child_process from "node:child_process";
2
+ import * as fs from "node:fs";
3
+ import * as os from "node:os";
4
+ import * as path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { parseArgs, flagString, flagBool } from "../lib/args.js";
7
+ import { readJson } from "../lib/fs.js";
8
+
9
+ const PROJECT_SETTINGS_RELATIVE_PATH = path.join("context", "settings", "backlog-provider-settings.json");
10
+
11
+ function loadSettings(file: string): Record<string, unknown> | null {
12
+ if (!fs.existsSync(file)) return null;
13
+ const data = readJson(file) as Record<string, unknown>;
14
+ if (data.schema_version !== "1.0") throw new Error(`${file}: unsupported schema_version ${String(data.schema_version)}`);
15
+ return data;
16
+ }
17
+
18
+ function repoFromText(text: string): { owner: string; name: string } | null {
19
+ const match = text.trim().match(/github\.com[:/]([^/]+)\/([^/.]+)(?:\.git)?$/);
20
+ return match ? { owner: match[1], name: match[2] } : null;
21
+ }
22
+
23
+ function currentRepo(repoPath: string): { owner: string; name: string } | null {
24
+ try {
25
+ const out = child_process.execFileSync("git", ["-C", repoPath, "remote", "get-url", "origin"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
26
+ const repo = repoFromText(out);
27
+ if (repo) return repo;
28
+ } catch {}
29
+ const packagePath = path.join(repoPath, "package.json");
30
+ if (fs.existsSync(packagePath)) {
31
+ const data = readJson(packagePath) as Record<string, unknown>;
32
+ const repository = data.repository;
33
+ const url = typeof repository === "object" && repository !== null ? (repository as Record<string, unknown>).url : repository;
34
+ if (typeof url === "string") return repoFromText(url);
35
+ }
36
+ return null;
37
+ }
38
+
39
+ function merge(base: unknown, override: unknown): Record<string, unknown> | null {
40
+ if (!base && !override) return null;
41
+ if (!base) return structuredClone(override) as Record<string, unknown>;
42
+ if (!override) return structuredClone(base) as Record<string, unknown>;
43
+ const out = structuredClone(base) as Record<string, unknown>;
44
+ for (const [key, value] of Object.entries(override as Record<string, unknown>)) {
45
+ out[key] = typeof value === "object" && value !== null && typeof out[key] === "object" && out[key] !== null && !Array.isArray(value)
46
+ ? merge(out[key], value)
47
+ : structuredClone(value);
48
+ }
49
+ return out;
50
+ }
51
+
52
+ function findProject(settings: Record<string, unknown> | null, repo: { owner: string; name: string }): Record<string, unknown> | null {
53
+ const projects = settings?.projects;
54
+ if (!Array.isArray(projects)) return null;
55
+ return (projects.find((project) => {
56
+ const projectRepo = (((project as Record<string, unknown>).project as Record<string, unknown> | undefined)?.repo ?? {}) as Record<string, unknown>;
57
+ return projectRepo.owner === repo.owner && projectRepo.name === repo.name;
58
+ }) as Record<string, unknown> | undefined) ?? null;
59
+ }
60
+
61
+ function defaultProjectSettingsPath(): string {
62
+ let cursor = path.dirname(fileURLToPath(import.meta.url));
63
+ while (true) {
64
+ const candidate = path.join(cursor, PROJECT_SETTINGS_RELATIVE_PATH);
65
+ if (fs.existsSync(candidate)) return candidate;
66
+ const parent = path.dirname(cursor);
67
+ if (parent === cursor) return path.resolve(PROJECT_SETTINGS_RELATIVE_PATH);
68
+ cursor = parent;
69
+ }
70
+ }
71
+
72
+ function effective(repoPath: string, projectSettings: string, globalSettings: string): [Record<string, unknown>, number] {
73
+ const repo = currentRepo(repoPath);
74
+ const projectDoc = loadSettings(projectSettings);
75
+ const globalDoc = loadSettings(globalSettings);
76
+ if (!repo) return [{ status: "ask_user", reason: "could_not_identify_current_repo", message: "Ask the user which backlog WorkItemProvider and BoardProvider to use for this workspace.", resolution: { project_settings_path: projectSettings, global_settings_path: globalSettings } }, 2];
77
+ const effectiveSettings = merge(merge(merge(globalDoc?.defaults, findProject(globalDoc, repo)), projectDoc?.defaults), findProject(projectDoc, repo));
78
+ if (!effectiveSettings) return [{ status: "ask_user", reason: "no_backlog_provider_settings", message: "Ask the user which backlog WorkItemProvider and BoardProvider to use before selecting work.", current_repo: repo, resolution: { project_settings_path: projectSettings, global_settings_path: globalSettings, checked: ["project", "global"] } }, 2];
79
+ return [{ status: "configured", current_repo: repo, source: findProject(projectDoc, repo) || projectDoc?.defaults ? "project" : "global", precedence: ["project.projects match", "project.defaults", "global.projects match", "global.defaults"], settings: effectiveSettings }, 0];
80
+ }
81
+
82
+ export function main(argv = process.argv.slice(2)): number {
83
+ const args = parseArgs(argv);
84
+ try {
85
+ const [result, code] = effective(
86
+ path.resolve(flagString(args.flags, "repo-path", ".") ?? "."),
87
+ path.resolve(flagString(args.flags, "project-settings", defaultProjectSettingsPath()) ?? ""),
88
+ path.resolve(flagString(args.flags, "global-settings", path.join(os.homedir(), ".config", "flow-agents", "backlog-provider-settings.json")) ?? ""),
89
+ );
90
+ if (flagBool(args.flags, "json")) console.log(JSON.stringify(result, null, 2));
91
+ else console.log(`status: ${String(result.status)}`);
92
+ return code;
93
+ } catch (error) {
94
+ console.error(`error: ${(error as Error).message}`);
95
+ return 1;
96
+ }
97
+ }
98
+
99
+ if (import.meta.url === `file://${process.argv[1]}`) process.exit(main());
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+
5
+ type FixtureAuditItem = {
6
+ fixture: string;
7
+ classification: "kept" | "retire_candidate";
8
+ owners: string[];
9
+ direct_refs: string[];
10
+ reasons: string[];
11
+ };
12
+
13
+ type FixtureAuditResult = {
14
+ fixture_root: string;
15
+ totals: {
16
+ scanned: number;
17
+ kept: number;
18
+ retire_candidates: number;
19
+ };
20
+ fixtures: FixtureAuditItem[];
21
+ };
22
+
23
+ const root = path.resolve(".");
24
+ const fixtureRoot = "evals/fixtures";
25
+ const ownerScanRoots = ["evals/static", "evals/integration", "scripts"];
26
+ const textExtensions = new Set([".md", ".yaml", ".yml", ".json", ".sh", ".js", ".ts"]);
27
+ const selfAuditRefs = new Set([
28
+ "evals/integration/test_fixture_retirement_audit.sh",
29
+ ]);
30
+
31
+ function printHelp(): void {
32
+ console.log("Usage: flow-agents fixture-retirement-audit [--json]");
33
+ console.log("");
34
+ console.log("Read-only audit for canonical eval fixture retirement candidates.");
35
+ console.log("");
36
+ console.log("A fixture group is kept when docs/fixture-ownership.md lists existing");
37
+ console.log("owners and at least one live eval/script reference still points at it.");
38
+ console.log("The command never deletes, archives, or rewrites fixtures.");
39
+ }
40
+
41
+ function readText(file: string): string {
42
+ return fs.readFileSync(path.join(root, file), "utf8");
43
+ }
44
+
45
+ function walkFiles(dir: string): string[] {
46
+ const abs = path.join(root, dir);
47
+ if (!fs.existsSync(abs)) return [];
48
+ const out: string[] = [];
49
+ for (const entry of fs.readdirSync(abs, { withFileTypes: true })) {
50
+ const full = path.join(abs, entry.name);
51
+ if (entry.isDirectory()) out.push(...walkFiles(path.relative(root, full).split(path.sep).join("/")));
52
+ else if (entry.isFile()) out.push(path.relative(root, full).split(path.sep).join("/"));
53
+ }
54
+ return out;
55
+ }
56
+
57
+ function fixtureDirs(): string[] {
58
+ const abs = path.join(root, fixtureRoot);
59
+ return fs.readdirSync(abs, { withFileTypes: true })
60
+ .filter((entry) => entry.isDirectory())
61
+ .map((entry) => `${fixtureRoot}/${entry.name}`)
62
+ .sort();
63
+ }
64
+
65
+ function ownerInventory(): Map<string, string[]> {
66
+ const doc = readText("docs/fixture-ownership.md");
67
+ const rows = new Map<string, string[]>();
68
+ for (const line of doc.split(/\r?\n/)) {
69
+ if (!line.startsWith("| `evals/fixtures/")) continue;
70
+ const cells = line.split("|").map((cell) => cell.trim());
71
+ const fixture = cells[1]?.replace(/^`|`$/g, "");
72
+ const ownersCell = cells[3] ?? "";
73
+ if (!fixture) continue;
74
+ const owners = [...ownersCell.matchAll(/`([^`]+)`/g)].map((match) => match[1]).sort();
75
+ rows.set(fixture, owners);
76
+ }
77
+ return rows;
78
+ }
79
+
80
+ function scanFiles(): string[] {
81
+ return ownerScanRoots
82
+ .flatMap((dir) => walkFiles(dir))
83
+ .filter((file) => textExtensions.has(path.extname(file)))
84
+ .sort();
85
+ }
86
+
87
+ function audit(): FixtureAuditResult {
88
+ const inventory = ownerInventory();
89
+ const files = scanFiles();
90
+ const fixtures = fixtureDirs().map((fixture): FixtureAuditItem => {
91
+ const owners = inventory.get(fixture) ?? [];
92
+ const directRefs = files
93
+ .filter((file) => readText(file).includes(fixture))
94
+ .filter((file) => !file.startsWith(`${fixture}/`))
95
+ .filter((file) => !selfAuditRefs.has(file))
96
+ .sort();
97
+ const reasons: string[] = [];
98
+ if (!inventory.has(fixture)) reasons.push("missing from docs/fixture-ownership.md");
99
+ const missingOwners = owners.filter((owner) => !fs.existsSync(path.join(root, owner)));
100
+ if (missingOwners.length) reasons.push(`owner path missing: ${missingOwners.join(", ")}`);
101
+ if (!owners.length) reasons.push("no owners listed");
102
+ if (!directRefs.length) reasons.push("no direct eval/script references");
103
+ const unlistedRefs = directRefs.filter((ref) => !owners.includes(ref));
104
+ if (unlistedRefs.length) reasons.push(`direct references not listed as owners: ${unlistedRefs.join(", ")}`);
105
+ return {
106
+ fixture,
107
+ classification: reasons.length ? "retire_candidate" : "kept",
108
+ owners,
109
+ direct_refs: directRefs,
110
+ reasons: reasons.length ? reasons : ["owned fixture with live eval/script references"],
111
+ };
112
+ });
113
+ return {
114
+ fixture_root: path.join(root, fixtureRoot),
115
+ totals: {
116
+ scanned: fixtures.length,
117
+ kept: fixtures.filter((item) => item.classification === "kept").length,
118
+ retire_candidates: fixtures.filter((item) => item.classification === "retire_candidate").length,
119
+ },
120
+ fixtures,
121
+ };
122
+ }
123
+
124
+ function printText(result: FixtureAuditResult): void {
125
+ console.log("Fixture retirement audit (dry run, read-only)");
126
+ console.log(`Fixture root: ${result.fixture_root}`);
127
+ console.log(`Scanned fixture groups: ${result.totals.scanned}`);
128
+ console.log(`Kept: ${result.totals.kept}`);
129
+ console.log(`Retire candidates: ${result.totals.retire_candidates}`);
130
+ for (const item of result.fixtures) {
131
+ console.log(`- ${item.classification}: ${item.fixture}`);
132
+ console.log(` owners: ${item.owners.join(", ") || "none"}`);
133
+ console.log(` direct_refs: ${item.direct_refs.join(", ") || "none"}`);
134
+ for (const reason of item.reasons) console.log(` reason: ${reason}`);
135
+ }
136
+ }
137
+
138
+ export function main(argv = process.argv.slice(2)): number {
139
+ try {
140
+ if (argv.includes("--help") || argv.includes("-h")) {
141
+ printHelp();
142
+ return 0;
143
+ }
144
+ const result = audit();
145
+ if (argv.includes("--json")) console.log(JSON.stringify(result, null, 2));
146
+ else printText(result);
147
+ return 0;
148
+ } catch (error) {
149
+ console.error(`fixture-retirement-audit: ${error instanceof Error ? error.message : String(error)}`);
150
+ return 1;
151
+ }
152
+ }
153
+
154
+ if (import.meta.url === `file://${process.argv[1]}`) process.exit(main());
@@ -0,0 +1,139 @@
1
+ import * as crypto from "node:crypto";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { parseArgs, flagBool, flagString } from "../lib/args.js";
5
+ import { assertPathContained, copyDir, isoNow, readJson, walkFiles, writeJson } from "../lib/fs.js";
6
+ import { assertKitRepository } from "../flow-kit/validate.js";
7
+ import { activateCodexLocal } from "../runtime-adapters.js";
8
+
9
+ const REGISTRY_REL = path.join("kits", "local", "installed-kits.json");
10
+ const REPOSITORIES_REL = path.join("kits", "local", "repositories");
11
+
12
+ function registryPath(dest: string): string { return path.join(dest, REGISTRY_REL); }
13
+ function installedPath(dest: string, kitId: string): string { return path.join(dest, REPOSITORIES_REL, kitId); }
14
+
15
+ function loadRegistry(dest: string): { schema_version: string; kits: Record<string, unknown>[] } {
16
+ const file = registryPath(dest);
17
+ if (!fs.existsSync(file)) return { schema_version: "1.0", kits: [] };
18
+ const data = readJson(file) as { schema_version?: string; kits?: unknown[] };
19
+ return { schema_version: data.schema_version ?? "1.0", kits: Array.isArray(data.kits) ? data.kits.filter((item): item is Record<string, unknown> => typeof item === "object" && item !== null) : [] };
20
+ }
21
+
22
+ function contentHash(root: string): string {
23
+ const hash = crypto.createHash("sha256");
24
+ for (const file of walkFiles(root)) {
25
+ const rel = path.relative(root, file).split(path.sep).join("/");
26
+ hash.update(rel);
27
+ hash.update("\0");
28
+ hash.update(fs.readFileSync(file));
29
+ hash.update("\0");
30
+ }
31
+ return `sha256:${hash.digest("hex")}`;
32
+ }
33
+
34
+ function installLocal(argv: string[]): number {
35
+ const args = parseArgs(argv);
36
+ const source = path.resolve(args.positionals[0] ?? "");
37
+ const dest = path.resolve(flagString(args.flags, "dest", ".") ?? ".");
38
+ let manifest: Record<string, unknown>;
39
+ try {
40
+ manifest = assertKitRepository(source);
41
+ } catch (error) {
42
+ console.log("warning: Flow validation surface unavailable; local kit check uses the minimal Flow Definition fallback");
43
+ console.log("Flow Kit repository validation failed:");
44
+ for (const diagnostic of ((error as Error & { diagnostics?: string[] }).diagnostics ?? [(error as Error).message])) console.log(` - ${diagnostic}`);
45
+ return 1;
46
+ }
47
+ console.log("warning: Flow validation surface unavailable; local kit check uses the minimal Flow Definition fallback");
48
+ const kitId = String(manifest.id);
49
+ const hash = contentHash(source);
50
+ const registry = loadRegistry(dest);
51
+ const existing = registry.kits.find((entry) => entry.id === kitId);
52
+ const target = installedPath(dest, kitId);
53
+ assertPathContained(dest, target);
54
+ const sourceText = source;
55
+ if (existing && existing.source !== sourceText && !flagBool(args.flags, "update")) {
56
+ console.log(`conflict: kit '${kitId}' is already installed from ${existing.source}; rerun with --update to replace it`);
57
+ return 2;
58
+ }
59
+ if (existing && existing.source === sourceText && existing.hash === hash && fs.existsSync(target) && !flagBool(args.flags, "force")) {
60
+ console.log(`kit '${kitId}' is already installed from ${sourceText}`);
61
+ return 0;
62
+ }
63
+ copyDir(source, target);
64
+ const entry: Record<string, unknown> = {
65
+ id: kitId,
66
+ source: sourceText,
67
+ hash,
68
+ installed_at: existing && existing.source === sourceText && !flagBool(args.flags, "update") ? existing.installed_at : isoNow(),
69
+ installed_path: target,
70
+ state: "installed",
71
+ };
72
+ if (typeof manifest.version === "string" && manifest.version) entry.version = manifest.version;
73
+ registry.kits = existing ? registry.kits.map((item) => item.id === kitId ? entry : item) : [...registry.kits, entry];
74
+ writeJson(registryPath(dest), registry);
75
+ console.log(`${existing ? "updated" : "installed"} local kit '${kitId}' at ${target}`);
76
+ return 0;
77
+ }
78
+
79
+ function list(argv: string[]): number {
80
+ const args = parseArgs(argv);
81
+ const dest = path.resolve(flagString(args.flags, "dest", ".") ?? ".");
82
+ const entries = loadRegistry(dest).kits;
83
+ if (!entries.length) {
84
+ console.log("No local Flow Kits installed.");
85
+ return 0;
86
+ }
87
+ for (const entry of entries.sort((a, b) => String(a.id ?? "").localeCompare(String(b.id ?? "")))) {
88
+ console.log(`${entry.id} | source=${entry.source} | hash=${entry.hash} | installed_at=${entry.installed_at} | path=${entry.installed_path} | state=${entry.state ?? "unknown"}`);
89
+ }
90
+ return 0;
91
+ }
92
+
93
+ function status(argv: string[]): number {
94
+ const args = parseArgs(argv);
95
+ const dest = path.resolve(flagString(args.flags, "dest", ".") ?? ".");
96
+ let entries = loadRegistry(dest).kits;
97
+ const kitId = args.positionals[0];
98
+ if (kitId) {
99
+ entries = entries.filter((entry) => entry.id === kitId);
100
+ if (!entries.length) {
101
+ console.log(`local Flow Kit '${kitId}' is not installed`);
102
+ return 1;
103
+ }
104
+ }
105
+ if (!entries.length) {
106
+ console.log("No local Flow Kits installed.");
107
+ return 0;
108
+ }
109
+ for (const entry of entries.sort((a, b) => String(a.id ?? "").localeCompare(String(b.id ?? "")))) {
110
+ console.log(JSON.stringify({ ...entry, state: fs.existsSync(String(entry.installed_path ?? "")) ? "installed" : "missing" }, null, 2));
111
+ }
112
+ return 0;
113
+ }
114
+
115
+ function activate(argv: string[]): number {
116
+ const args = parseArgs(argv);
117
+ const dest = path.resolve(flagString(args.flags, "dest", ".") ?? ".");
118
+ const sourceRoot = path.resolve(flagString(args.flags, "source-root", path.resolve(path.dirname(process.argv[1]), "..")) ?? ".");
119
+ const adapter = flagString(args.flags, "adapter");
120
+ if (adapter && adapter !== "codex-local") {
121
+ console.log(JSON.stringify({ selected_adapter: null, available_adapters: ["codex-local"], supported_asset_classes: [], generated_runtime_files: [], skipped_assets: [], warnings: [], errors: [`unknown runtime adapter '${adapter}'; available adapters: codex-local`] }, null, 2));
122
+ return 2;
123
+ }
124
+ const result = activateCodexLocal(sourceRoot, dest);
125
+ console.log(JSON.stringify(result, null, 2));
126
+ return Array.isArray(result.errors) && result.errors.length ? 1 : 0;
127
+ }
128
+
129
+ export function main(argv = process.argv.slice(2)): number {
130
+ const [command, ...rest] = argv;
131
+ if (command === "install-local") return installLocal(rest);
132
+ if (command === "list") return list(rest);
133
+ if (command === "status") return status(rest);
134
+ if (command === "activate") return activate(rest);
135
+ console.error("usage: flow-kit <install-local|list|status|activate> ...");
136
+ return 2;
137
+ }
138
+
139
+ if (import.meta.url === `file://${process.argv[1]}`) process.exit(main());