@kontourai/flow-agents 2.3.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/.github/CODEOWNERS +16 -0
  2. package/.github/workflows/ci.yml +44 -0
  3. package/.github/workflows/trust-reconcile.yml +62 -4
  4. package/AGENTS.md +4 -4
  5. package/CHANGELOG.md +62 -0
  6. package/CONTEXT.md +35 -0
  7. package/README.md +9 -3
  8. package/agents/dev.json +1 -1
  9. package/agents/tool-code-reviewer.json +1 -1
  10. package/agents/tool-planner.json +3 -3
  11. package/agents/tool-verifier.json +3 -3
  12. package/build/src/cli/assignment-provider.d.ts +1 -0
  13. package/build/src/cli/assignment-provider.js +748 -0
  14. package/build/src/cli/console-learning-projection.js +3 -2
  15. package/build/src/cli/effective-assignment-provider-settings.d.ts +1 -0
  16. package/build/src/cli/effective-assignment-provider-settings.js +125 -0
  17. package/build/src/cli/init.js +104 -21
  18. package/build/src/cli/kit.js +37 -6
  19. package/build/src/cli/pull-work-provider.js +1 -1
  20. package/build/src/cli/usage-feedback.js +3 -3
  21. package/build/src/cli/validate-hook-influence.js +1 -0
  22. package/build/src/cli/validate-workflow-artifacts.js +27 -7
  23. package/build/src/cli/workflow-artifact-cleanup-audit.js +36 -2
  24. package/build/src/cli/workflow-sidecar.d.ts +14 -7
  25. package/build/src/cli/workflow-sidecar.js +938 -168
  26. package/build/src/cli.js +6 -0
  27. package/build/src/flow-kit/validate.d.ts +23 -0
  28. package/build/src/flow-kit/validate.js +67 -1
  29. package/build/src/index.d.ts +1 -1
  30. package/build/src/index.js +1 -1
  31. package/build/src/lib/flow-resolver.d.ts +6 -4
  32. package/build/src/lib/flow-resolver.js +125 -58
  33. package/build/src/lib/local-artifact-root.d.ts +14 -2
  34. package/build/src/lib/local-artifact-root.js +22 -5
  35. package/build/src/lib/workflow-learning-projection.js +2 -2
  36. package/build/src/runtime-adapters.d.ts +12 -0
  37. package/build/src/runtime-adapters.js +56 -16
  38. package/build/src/tools/build-universal-bundles.js +49 -16
  39. package/build/src/tools/generate-context-map.js +10 -8
  40. package/build/src/tools/validate-source-tree.js +24 -1
  41. package/console.telemetry.json +22 -0
  42. package/context/contracts/artifact-contract.md +40 -7
  43. package/context/contracts/assignment-provider-contract.md +239 -0
  44. package/context/contracts/builder-kit-workflow-state-contract.md +5 -2
  45. package/context/contracts/decision-registry-contract.md +265 -0
  46. package/context/contracts/delivery-contract.md +3 -1
  47. package/context/contracts/execution-contract.md +25 -0
  48. package/context/contracts/governance-adapter-contract.md +2 -0
  49. package/context/contracts/knowledge-store-contract.md +197 -0
  50. package/context/contracts/planning-contract.md +4 -1
  51. package/context/contracts/review-contract.md +7 -3
  52. package/context/contracts/sandbox-policy.md +2 -0
  53. package/context/contracts/standing-directives.md +13 -0
  54. package/context/contracts/verification-contract.md +11 -1
  55. package/context/contracts/work-item-contract.md +3 -1
  56. package/context/deferred/parallelization.md +1 -1
  57. package/context/gate-awareness.md +4 -4
  58. package/context/scripts/git-status.sh +2 -2
  59. package/context/scripts/hooks/config-protection.js +502 -2
  60. package/context/scripts/hooks/lib/config-protection-remedies.js +69 -0
  61. package/context/scripts/hooks/run-hook.js +14 -1
  62. package/context/scripts/hooks/stop-goal-fit.js +1140 -99
  63. package/context/scripts/hooks/workflow-steering.js +212 -6
  64. package/context/settings/assignment-provider-settings.json +33 -0
  65. package/docs/adr/0007-flow-skill-kit-tool-boundary.md +2 -0
  66. package/docs/adr/0015-flow-flow-agents-boundary-reconciliation.md +35 -0
  67. package/docs/adr/0019-kit-dependency-ownership.md +62 -0
  68. package/docs/adr/0020-trust-reconcile-manifest-and-claim-classification.md +290 -0
  69. package/docs/adr/0021-assignment-leases-and-stale-claim-takeover.md +221 -0
  70. package/docs/adr/0022-fail-closed-delivery-reconciliation-with-governed-exemptions.md +463 -0
  71. package/docs/agent-system-guidebook.md +3 -3
  72. package/docs/agent-usage-feedback-loop.md +6 -6
  73. package/docs/context-map.md +10 -7
  74. package/docs/decisions/decision-records.md +57 -0
  75. package/docs/decisions/index.md +17 -0
  76. package/docs/decisions/knowledge-store-provider.md +51 -0
  77. package/docs/decisions/model-routing.md +63 -0
  78. package/docs/decisions/promotion-gate.md +52 -0
  79. package/docs/decisions/standing-directives.md +66 -0
  80. package/docs/developer-architecture.md +1 -1
  81. package/docs/fixture-ownership.md +4 -0
  82. package/docs/flow-kit-repository-contract.md +5 -5
  83. package/docs/getting-started.md +12 -2
  84. package/docs/integrations/harness-install.md +2 -1
  85. package/docs/kit-authoring-guide.md +64 -5
  86. package/docs/knowledge-kit.md +5 -1
  87. package/docs/learnings/2026-07-improvement-program.md +203 -0
  88. package/docs/migrations.md +6 -5
  89. package/docs/north-star.md +2 -2
  90. package/docs/operating-layers.md +4 -3
  91. package/docs/repository-structure.md +5 -5
  92. package/docs/skills-map.md +8 -8
  93. package/docs/spec/runtime-hook-surface.md +19 -15
  94. package/docs/spikes/graph-provider-2026-07.md +155 -0
  95. package/docs/standards-register.md +7 -7
  96. package/docs/trust-anchor-adoption.md +105 -4
  97. package/docs/work-item-adapters.md +1 -1
  98. package/docs/workflow-artifact-lifecycle.md +72 -9
  99. package/docs/workflow-eval-strategy.md +3 -3
  100. package/docs/workflow-shared-contracts.md +3 -2
  101. package/docs/workflow-usage-guide.md +260 -21
  102. package/evals/acceptance/DEMO-false-completion.md +20 -11
  103. package/evals/acceptance/prove-capture-teeth-declared.sh +15 -15
  104. package/evals/acceptance/prove-capture-teeth.sh +11 -11
  105. package/evals/acceptance/test_kiro_harness.sh +1 -1
  106. package/evals/ci/antigaming-suite.sh +5 -0
  107. package/evals/ci/run-baseline.sh +71 -1
  108. package/evals/fixtures/assignment-provider/actor-a.json +6 -0
  109. package/evals/fixtures/assignment-provider/actor-b.json +6 -0
  110. package/evals/fixtures/assignment-provider/github-issue-claimed.json +27 -0
  111. package/evals/fixtures/assignment-provider/github-issue-unassigned.json +7 -0
  112. package/evals/fixtures/assignment-provider/liveness-fresh.json +9 -0
  113. package/evals/fixtures/assignment-provider/liveness-stale.json +9 -0
  114. package/evals/fixtures/flow-kit-repository/invalid-bad-dependency/flows/review.flow.json +26 -0
  115. package/evals/fixtures/flow-kit-repository/invalid-bad-dependency/kit.json +13 -0
  116. package/evals/fixtures/flow-kit-repository/valid-with-dependency/flows/review.flow.json +26 -0
  117. package/evals/fixtures/flow-kit-repository/valid-with-dependency/kit.json +13 -0
  118. package/evals/fixtures/hook-influence/cases.json +32 -0
  119. package/evals/fixtures/pull-work-provider/github-issues.json +6 -6
  120. package/evals/fixtures/trust-reconcile-exploits/fabricated-attestation.json +59 -0
  121. package/evals/fixtures/trust-reconcile-exploits/no-label-bypass.json +36 -0
  122. package/evals/fixtures/trust-reconcile-exploits/skip-assumed-bypass.json +59 -0
  123. package/evals/fixtures/trust-reconcile-exploits/status-misassertion.json +48 -0
  124. package/evals/fixtures/trust-reconcile-exploits/waived-command-check.json +44 -0
  125. package/evals/fixtures/trust-reconcile-mixed-bundle/mixed-bundle.json +159 -0
  126. package/evals/fixtures/trust-reconcile-ws3/ws3-bundle.json +920 -0
  127. package/evals/integration/test_actor_identity.sh +254 -0
  128. package/evals/integration/test_assignment_provider_github.sh +318 -0
  129. package/evals/integration/test_assignment_provider_local_file.sh +222 -0
  130. package/evals/integration/test_builder_step_producers.sh +33 -23
  131. package/evals/integration/test_bundle_install.sh +22 -16
  132. package/evals/integration/test_bundle_lifecycle.sh +11 -11
  133. package/evals/integration/test_captured_fail_reconciliation.sh +50 -50
  134. package/evals/integration/test_checkpoint_signing.sh +43 -0
  135. package/evals/integration/test_claim_lookup.sh +4 -4
  136. package/evals/integration/test_codex_hook_resolution.sh +114 -0
  137. package/evals/integration/test_command_log_concurrency.sh +8 -8
  138. package/evals/integration/test_command_log_fork_classification.sh +3 -3
  139. package/evals/integration/test_command_log_integrity.sh +16 -16
  140. package/evals/integration/test_console_learning_projection.sh +1 -1
  141. package/evals/integration/test_critique_supersession_roundtrip.sh +182 -0
  142. package/evals/integration/test_dual_emit_flow_step.sh +145 -0
  143. package/evals/integration/test_enforcer_expects_driven.sh +12 -12
  144. package/evals/integration/test_evidence_capture_hook.sh +14 -13
  145. package/evals/integration/test_fixture_retirement_audit.sh +2 -2
  146. package/evals/integration/test_flow_agents_statusline.sh +2 -2
  147. package/evals/integration/test_flow_kit_install_git.sh +52 -0
  148. package/evals/integration/test_flow_kit_repository.sh +2 -0
  149. package/evals/integration/test_flowdef_session_activation.sh +6 -6
  150. package/evals/integration/test_flowdef_union_floor_regression.sh +429 -0
  151. package/evals/integration/test_gate_bypass_chain.sh +52 -40
  152. package/evals/integration/test_gate_lockdown.sh +97 -73
  153. package/evals/integration/test_gate_review_inquiry_records.sh +3 -3
  154. package/evals/integration/test_goal_fit_escape_hatch.sh +10 -10
  155. package/evals/integration/test_goal_fit_ghost_session.sh +104 -0
  156. package/evals/integration/test_goal_fit_hook.sh +32 -32
  157. package/evals/integration/test_goal_fit_rederive.sh +9 -9
  158. package/evals/integration/test_hook_category_behaviors.sh +103 -0
  159. package/evals/integration/test_hook_influence_cases.sh +1 -0
  160. package/evals/integration/test_install_merge.sh +262 -1
  161. package/evals/integration/test_kit_identity_trust.sh +6 -6
  162. package/evals/integration/test_liveness_conflict_injection.sh +587 -0
  163. package/evals/integration/test_liveness_heartbeat.sh +677 -0
  164. package/evals/integration/test_liveness_verdict.sh +394 -0
  165. package/evals/integration/test_local_flow_kit_install.sh +15 -0
  166. package/evals/integration/test_phase_map_and_gate_claim.sh +63 -11
  167. package/evals/integration/test_promote_gate.sh +178 -0
  168. package/evals/integration/test_publish_delivery.sh +23 -6
  169. package/evals/integration/test_pull_work_assignment_join.sh +132 -0
  170. package/evals/integration/test_pull_work_liveness_preflight.sh +394 -0
  171. package/evals/integration/test_pull_work_provider.sh +2 -2
  172. package/evals/integration/test_reconcile_soundness.sh +37 -13
  173. package/evals/integration/test_resolvefirststep_security.sh +22 -0
  174. package/evals/integration/test_runtime_adapter_activation.sh +87 -18
  175. package/evals/integration/test_session_resume_roundtrip.sh +147 -0
  176. package/evals/integration/test_sidecar_field_preservation.sh +249 -0
  177. package/evals/integration/test_trust_reconcile.sh +11 -10
  178. package/evals/integration/test_trust_reconcile_manifest.sh +79 -0
  179. package/evals/integration/test_trust_reconcile_mixed_bundle.sh +96 -0
  180. package/evals/integration/test_trust_reconcile_negatives.sh +759 -0
  181. package/evals/integration/test_usage_feedback_global.sh +5 -5
  182. package/evals/integration/test_validate_artifacts_portability.sh +60 -0
  183. package/evals/integration/test_verify_cli.sh +2 -2
  184. package/evals/integration/test_veritas_governance_kit.sh +117 -0
  185. package/evals/integration/test_workflow_artifact_cleanup_audit.sh +26 -1
  186. package/evals/integration/test_workflow_artifacts.sh +33 -0
  187. package/evals/integration/test_workflow_sidecar_writer.sh +802 -74
  188. package/evals/integration/test_workflow_steering_hook.sh +175 -5
  189. package/evals/lib/codex-provider.sh +1 -1
  190. package/evals/lib/node.sh +19 -1
  191. package/evals/run.sh +32 -0
  192. package/evals/static/test_decisions.sh +150 -0
  193. package/evals/static/test_flowdef_codeowners_coverage.sh +62 -0
  194. package/evals/static/test_knowledge_providers.sh +23 -0
  195. package/evals/static/test_package.sh +19 -10
  196. package/evals/static/test_universal_bundles.sh +48 -3
  197. package/evals/static/test_workflow_skills.sh +41 -8
  198. package/kits/builder/flows/build.flow.json +3 -74
  199. package/kits/builder/flows/publish-learn.flow.json +90 -0
  200. package/kits/builder/kit.json +11 -0
  201. package/kits/builder/skills/builder-shape/SKILL.md +1 -1
  202. package/kits/builder/skills/deliver/SKILL.md +32 -11
  203. package/kits/builder/skills/design-probe/SKILL.md +4 -4
  204. package/kits/builder/skills/evidence-gate/SKILL.md +26 -1
  205. package/kits/builder/skills/execute-plan/SKILL.md +2 -2
  206. package/kits/builder/skills/fix-bug/SKILL.md +2 -0
  207. package/kits/builder/skills/gate-review/SKILL.md +6 -6
  208. package/kits/builder/skills/idea-to-backlog/SKILL.md +1 -1
  209. package/kits/builder/skills/learning-review/SKILL.md +7 -7
  210. package/kits/builder/skills/pickup-probe/SKILL.md +5 -4
  211. package/kits/builder/skills/plan-work/SKILL.md +27 -5
  212. package/kits/builder/skills/pull-work/SKILL.md +148 -5
  213. package/kits/builder/skills/release-readiness/SKILL.md +4 -4
  214. package/kits/builder/skills/review-work/SKILL.md +24 -1
  215. package/kits/builder/skills/tdd-workflow/SKILL.md +2 -0
  216. package/kits/builder/skills/verify-work/SKILL.md +8 -1
  217. package/kits/catalog.json +6 -0
  218. package/kits/knowledge/kit.json +35 -0
  219. package/kits/knowledge/providers/conformance/fixtures/git-repo/CONTEXT.md +12 -0
  220. package/kits/knowledge/providers/conformance/fixtures/git-repo/docs/decisions/old-sprocket-shape.md +13 -0
  221. package/kits/knowledge/providers/conformance/fixtures/git-repo/docs/decisions/sprocket-shape.md +14 -0
  222. package/kits/knowledge/providers/conformance/fixtures/git-repo/docs/decisions/widget-format.md +14 -0
  223. package/kits/knowledge/providers/conformance/fixtures/git-repo/docs/learnings/fixture-learning.md +7 -0
  224. package/kits/knowledge/providers/conformance/fixtures/work-item/issues.json +30 -0
  225. package/kits/knowledge/providers/conformance/suite.test.js +125 -0
  226. package/kits/knowledge/providers/git-repo/index.js +236 -0
  227. package/kits/knowledge/providers/health/health-pass.test.js +99 -0
  228. package/kits/knowledge/providers/health/index.js +153 -0
  229. package/kits/knowledge/providers/index.js +24 -0
  230. package/kits/knowledge/providers/lib/model.js +91 -0
  231. package/kits/knowledge/providers/lib/schema-validate.js +119 -0
  232. package/kits/knowledge/providers/markdown-vault/index.js +169 -0
  233. package/kits/knowledge/providers/work-item/index.js +204 -0
  234. package/kits/veritas-governance/adapter/readiness-to-trust-bundle.mjs +178 -0
  235. package/kits/veritas-governance/docs/README.md +75 -0
  236. package/kits/veritas-governance/fixtures/readiness/not-ready.readiness-report.json +4645 -0
  237. package/kits/veritas-governance/fixtures/readiness/ready.readiness-report.json +4403 -0
  238. package/kits/veritas-governance/flows/readiness-check.flow.json +35 -0
  239. package/kits/veritas-governance/kit.json +16 -0
  240. package/package.json +11 -5
  241. package/packaging/README.md +2 -2
  242. package/packaging/conformance/fixtures/config-protection--allow-read-state-json.json +20 -0
  243. package/packaging/conformance/fixtures/config-protection--block-write-state-json.json +20 -0
  244. package/packaging/conformance/fixtures/stop-goal-fit--block-bundle-disputed-claim.json +1 -1
  245. package/packaging/conformance/fixtures/stop-goal-fit--block-capture-contradicts-claimed-pass.json +1 -1
  246. package/packaging/manifest.json +9 -10
  247. package/schemas/assignment-provider-settings.schema.json +125 -0
  248. package/schemas/decision-record.schema.json +109 -0
  249. package/schemas/knowledge/edge.schema.json +54 -0
  250. package/schemas/knowledge/health-report.schema.json +45 -0
  251. package/schemas/knowledge/node.schema.json +49 -0
  252. package/schemas/knowledge/proposal.schema.json +53 -0
  253. package/schemas/workflow-evidence.schema.json +1 -1
  254. package/schemas/workflow-state.schema.json +5 -0
  255. package/scripts/README.md +8 -3
  256. package/scripts/check-content-boundary.cjs +1 -1
  257. package/scripts/check-decisions.cjs +356 -0
  258. package/scripts/ci/derive-claim-status.mjs +74 -0
  259. package/scripts/ci/trust-reconcile.js +957 -103
  260. package/scripts/git-status.sh +2 -2
  261. package/scripts/hooks/claude-telemetry-hook.js +37 -3
  262. package/scripts/hooks/codex-telemetry-hook.js +36 -2
  263. package/scripts/hooks/config-protection.js +102 -30
  264. package/scripts/hooks/evidence-capture.js +3 -3
  265. package/scripts/hooks/lib/actor-identity.js +368 -0
  266. package/scripts/hooks/lib/config-protection-remedies.js +69 -0
  267. package/scripts/hooks/lib/liveness-heartbeat.js +361 -0
  268. package/scripts/hooks/lib/liveness-policy.js +127 -0
  269. package/scripts/hooks/lib/liveness-read.js +105 -12
  270. package/scripts/hooks/lib/liveness-write.js +46 -0
  271. package/scripts/hooks/lib/local-artifact-paths.js +12 -6
  272. package/scripts/hooks/opencode-telemetry-hook.js +27 -1
  273. package/scripts/hooks/pi-telemetry-hook.js +27 -1
  274. package/scripts/hooks/stop-goal-fit.js +157 -26
  275. package/scripts/hooks/workflow-steering.js +77 -3
  276. package/scripts/install-codex-home.sh +138 -38
  277. package/scripts/statusline/flow-agents-statusline.js +2 -2
  278. package/src/cli/assignment-provider.ts +845 -0
  279. package/src/cli/console-learning-projection.ts +3 -2
  280. package/src/cli/effective-assignment-provider-settings.ts +112 -0
  281. package/src/cli/init.ts +101 -21
  282. package/src/cli/kit.ts +37 -6
  283. package/src/cli/public-api.test.mjs +58 -6
  284. package/src/cli/pull-work-provider.ts +1 -1
  285. package/src/cli/trust-bundle-policy-order.test.mjs +87 -0
  286. package/src/cli/usage-feedback.ts +3 -3
  287. package/src/cli/validate-hook-influence.ts +1 -0
  288. package/src/cli/validate-workflow-artifacts.ts +27 -7
  289. package/src/cli/veritas-readiness-adapter.test.mjs +267 -0
  290. package/src/cli/workflow-artifact-cleanup-audit.ts +35 -2
  291. package/src/cli/workflow-sidecar.ts +933 -168
  292. package/src/cli.ts +6 -0
  293. package/src/flow-kit/validate.ts +74 -1
  294. package/src/index.ts +6 -2
  295. package/src/lib/flow-resolver.ts +123 -55
  296. package/src/lib/local-artifact-root.ts +24 -5
  297. package/src/lib/workflow-learning-projection.ts +2 -2
  298. package/src/runtime-adapters.ts +61 -15
  299. package/src/tools/build-universal-bundles.ts +49 -16
  300. package/src/tools/generate-context-map.ts +10 -8
  301. package/src/tools/validate-source-tree.ts +24 -1
@@ -0,0 +1,203 @@
1
+ ---
2
+ title: "2026-07 Improvement Program — Learning Review"
3
+ ---
4
+
5
+ # 2026-07 Improvement Program — Learning Review
6
+
7
+ This document records durable learnings from a multi-week, multi-repository improvement
8
+ program run across the Kontour portfolio in June and July 2026. The program touched
9
+ Flow Agents, Surface, Veritas, Flow, Survey, Traverse, and the shared hachure trust-bundle
10
+ schema. Every finding below was hit empirically during the program and resolved or worked
11
+ around; none are speculative.
12
+
13
+ It is written for a future maintainer who was not present for the program. Where a finding
14
+ implies a rule you should keep following, that rule is stated explicitly. Cross-repository
15
+ pull requests and issues are linked so you can trace the underlying change.
16
+
17
+ ## Scope and source material
18
+
19
+ - Corroborating provider issues: [flow-agents#267](https://github.com/kontourai/flow-agents/issues/267),
20
+ [flow-agents#268](https://github.com/kontourai/flow-agents/issues/268),
21
+ [flow-agents#281](https://github.com/kontourai/flow-agents/issues/281).
22
+ - Representative pull requests:
23
+ - Flow Agents: [#264](https://github.com/kontourai/flow-agents/pull/264) (cross-kit
24
+ dependencies, skill-collision fixes, sidecar governance),
25
+ [#266](https://github.com/kontourai/flow-agents/pull/266) (manifest-based reconcile,
26
+ claim classification, loud attestations),
27
+ [#269](https://github.com/kontourai/flow-agents/pull/269) (veritas-governance kit —
28
+ readiness→trust-bundle adapter),
29
+ [#277](https://github.com/kontourai/flow-agents/pull/277) (migrate to
30
+ `@kontourai/surface` 2.0.0, `Claim.facet` rename).
31
+ - Surface: [#103](https://github.com/kontourai/surface/pull/103) (order-independent
32
+ multi-producer merge; hachure 0.7.0 conformance),
33
+ [#104](https://github.com/kontourai/surface/pull/104) (sync to hachure 0.8.0,
34
+ vendor-neutral `$id`s), [#105](https://github.com/kontourai/surface/pull/105)
35
+ (`Claim.surface` → `facet`, spec 0.9.0 parity — a breaking change).
36
+ - Veritas: [#107](https://github.com/kontourai/veritas/pull/107) (blocking failures win
37
+ over `promotion_allowed` short-circuit), [#109](https://github.com/kontourai/veritas/pull/109)
38
+ (migrate `Claim.surface` → `facet`, Surface ^2.0.0, schemaVersion 5).
39
+ - Flow: [#100](https://github.com/kontourai/flow/pull/100) (migrate to Surface 2.0.0 —
40
+ shipped as a `chore:` and therefore went unreleased; see Finding 6),
41
+ [#101](https://github.com/kontourai/flow/pull/101) (trust bundles emit `facet` +
42
+ schemaVersion 5; Surface 2.0, hachure 0.9).
43
+ - Survey: [#100](https://github.com/kontourai/survey/pull/100) (migrate to Surface 2.0.0
44
+ facet rename), released via [#99](https://github.com/kontourai/survey/pull/99) /
45
+ [#101](https://github.com/kontourai/survey/pull/101).
46
+ - hachure trust-bundle schema releases 0.6.0 through 0.9.0, which drove the coordinated
47
+ Surface / Veritas / Flow / Survey / Flow Agents migrations above.
48
+
49
+ The rest of this document is organized by finding. Each finding states what happened, why
50
+ it matters, and the working discipline or fix to carry forward.
51
+
52
+ ## 1. Trust-ledger write discipline
53
+
54
+ The trust ledger (`trust.bundle` plus its `evidence.json` / critique inputs) has write
55
+ semantics that are easy to corrupt if you interleave commands:
56
+
57
+ - `record-evidence` **replaces** `trust.bundle` wholesale. At the time of the program it
58
+ rebuilt the bundle with a hardcoded `critiques: []`, so any previously recorded critique
59
+ was silently dropped.
60
+ - `record-critique` is **append-only** and has no supersession mechanism: a reviewer cannot
61
+ close or retract a disputed finding once written ([flow-agents#267](https://github.com/kontourai/flow-agents/issues/267)).
62
+ - The checks/critiques round-trip through the bundle is contaminating: prior critique claims
63
+ get re-absorbed as command-less `test_output` checks, turning a critique claim into a
64
+ divergent, command-less check ([flow-agents#268](https://github.com/kontourai/flow-agents/issues/268)).
65
+ This is amplified under `--flow-id`, where a **single** critique write is enough to
66
+ contaminate the ledger.
67
+
68
+ **Working discipline until the tooling is fixed:**
69
+
70
+ 1. Record **all** evidence first.
71
+ 2. Record **at most one** critique write, and make it the **last** write.
72
+ 3. Never run any `record-*` command after that final critique write.
73
+ 4. If a ledger becomes contaminated, **restart the session** rather than trying to iterate
74
+ or repair a contaminated ledger in place.
75
+
76
+ This program's learning-review session itself follows the rule: it was created with
77
+ `ensure-session` **without** `--flow-id` precisely to avoid the single-critique-write
78
+ amplification described above.
79
+
80
+ ## 2. Post-merge ledger staleness
81
+
82
+ A session whose `trust.bundle` was frozen mid-iteration causes stop-gate "caught
83
+ false-completion" storms after the branch merges. The stale iteration claims are recomputed
84
+ in a changed context (the merged tree no longer matches the frozen claims), and the stop gate
85
+ repeatedly flags the session as falsely complete.
86
+
87
+ **Pattern to recover:** rebuild the bundle from the current `evidence.json` via
88
+ `record-evidence`, then re-advance state. Do not hand-edit the frozen bundle; regenerate it
89
+ from current evidence so the claims match the post-merge tree.
90
+
91
+ ## 3. Evidence must be executable in the CI/backstop context
92
+
93
+ Evidence checks are re-run by CI and by the backstop reconciler, not just locally. Several
94
+ checks passed locally but failed in CI because they were not executable in that context. Keep
95
+ evidence portable:
96
+
97
+ - Check commands must be **repo-root-relative** and must reference files that live **inside
98
+ the session directory** (for example under `verify-scratch/`), never an agent's private
99
+ scratchpad that does not exist in CI.
100
+ - Summaries must be **runnable commands**. For prose that is not a command, use the
101
+ `true # ...` form so the "command" still exits zero when executed.
102
+ - Reconcilable claims need **manifest-exact bare labels** — no environment-variable
103
+ annotations on the label — so the reconciler can match them against the manifest.
104
+ - Keep reconcilable sets **small**. `runCommand` enforces a 180-second per-command timeout;
105
+ heavy test suites trip that timeout in CI while passing locally. Split or scope the suite
106
+ so each reconciled command finishes well under the limit.
107
+
108
+ ## 4. Critique semantics and resolved sessions
109
+
110
+ Under the current validator rule, a top-level `pass` verdict forbids any `fail` or
111
+ `not_verified` member claims. Consequently a **resolved** session cannot retain historical
112
+ `verdict: fail` critiques — the validator rejects the bundle even though the failure was
113
+ genuine and later fixed.
114
+
115
+ **Reconciliation pattern:** move the historical failing critique to `superseded` and then
116
+ `comment`, preserving the original outcome in the summary text so the audit trail survives.
117
+ The `fail` verdict is not deleted from history; it is superseded, and the summary records
118
+ what the original verdict was and how it was resolved.
119
+
120
+ This deserves an explicit convention note, and possibly a validator/schema affordance for a
121
+ first-class `superseded_by` relationship so the original verdict can be preserved structurally
122
+ rather than only in prose. That tooling gap is filed as a follow-up issue (see below).
123
+
124
+ ## 5. Shim scope coupling in cross-repo schema migrations
125
+
126
+ Surface 2.0's read-tolerance shim (the compatibility layer that accepts both the old
127
+ `Claim.surface` and new `Claim.facet` shapes) only protects consumers that go through
128
+ **Surface's JavaScript API**. Anything that validates against the hachure JSON Schema
129
+ **directly** bypasses the shim and breaks. During this program that included:
130
+
131
+ - Flow's Ajv gate (validates bundles against the raw schema),
132
+ - Veritas's schema dependency,
133
+ - Flow Agents `attach-evidence` using a **vendored** copy of the old hachure schema.
134
+
135
+ Each of these had to bump hachure **in lockstep** with the Surface bump; the shim did not
136
+ cover them.
137
+
138
+ **Rule for future cross-repo schema migrations:** map **both** axes before you start —
139
+ (a) the JS-API consumers, which the shim protects, and (b) the raw-schema validators, which
140
+ it does not. Every raw-schema validator (including vendored schema copies) must be bumped in
141
+ the same coordinated wave. See Surface [#105](https://github.com/kontourai/surface/pull/105),
142
+ Veritas [#109](https://github.com/kontourai/veritas/pull/109), Flow
143
+ [#101](https://github.com/kontourai/flow/pull/101), Survey
144
+ [#100](https://github.com/kontourai/survey/pull/100), and Flow Agents
145
+ [#277](https://github.com/kontourai/flow-agents/pull/277) for the coordinated set.
146
+
147
+ ## 6. Release mechanics
148
+
149
+ Two independent release-mechanics traps surfaced:
150
+
151
+ - **release-please ignores `chore:` commits.** Flow [#100](https://github.com/kontourai/flow/pull/100)
152
+ shipped real functionality (the Surface 2.0 migration) as a `chore:` commit, so
153
+ release-please never cut a release and the functionality sat unreleased until a subsequent
154
+ `feat!:` signal commit ([#101](https://github.com/kontourai/flow/pull/101)) triggered the
155
+ release. If a `chore:` PR changes shipped behavior, it will not be released on its own —
156
+ pair it with a `feat:`/`fix:`/`feat!:` signal commit or it stays dark.
157
+ - **GitHub App installation repo-access is a separate axis from org secrets/vars grants.**
158
+ A Traverse release was blocked because the GitHub App was not installed on that repository,
159
+ which is distinct from whether org-level secrets and variables were granted. App
160
+ installation repo-access is org-owner-only, so this class of block cannot be self-resolved
161
+ by the release author and must be escalated to an org owner.
162
+
163
+ ## 7. Runtime-artifact hygiene
164
+
165
+ Bulk worktree operations reset filesystem `mtime`s en masse. Any recency heuristic based on
166
+ `mtime` is therefore unreliable after a sweep. Session recency must be read from
167
+ `state.json`'s `updated_at` field, not from file `mtime` (established during the WS6 sweep —
168
+ the WS6 sweep was the pass that audited and pruned stale local runtime sessions).
169
+
170
+ The `workflow-artifact-cleanup-audit` CLI is **dry-run only**: it classifies sessions into
171
+ active WIP, cleanup candidates, terminal done records, active learning follow-ups, and
172
+ invalid sidecars, but it does not delete, archive, or rewrite anything and has no apply mode.
173
+ An apply mode may be worth filing so cleanup can be executed, not just recommended. That
174
+ tooling gap is filed as a follow-up issue (see below).
175
+
176
+ ## 8. Gate operations
177
+
178
+ Operational discipline for running gates and merging, learned the hard way during parallel
179
+ waves:
180
+
181
+ - **Never dispatch fixes while gates are running.** Wait for **all** outstanding gates to
182
+ finish before acting on any result; dispatching a fix mid-run races the gate and produces
183
+ confusing, interleaved state.
184
+ - **Run mutation testing only in scratch copies**, never against the working tree the gate is
185
+ evaluating.
186
+ - **Keep `gh pr merge` stderr visible.** Do not swallow it; the merge failure reasons you
187
+ need (behind-base, pending checks, blocked) come through stderr.
188
+ - Use `gh pr merge --auto` for pending checks so the merge lands when checks go green, and use
189
+ branch update (`update-branch`) when a PR is `BEHIND` the base.
190
+
191
+ ## Follow-up tooling issues
192
+
193
+ Findings 4 and 7 imply concrete Flow Agents tool changes. Both were checked against the open
194
+ issue list for duplicates and filed fresh:
195
+
196
+ - Finding 4 → [flow-agents#282](https://github.com/kontourai/flow-agents/issues/282): a
197
+ validator/schema affordance for `superseded_by` on critique claims, so a resolved session
198
+ can preserve a historical `fail` verdict structurally rather than only in the summary prose.
199
+ - Finding 7 → [flow-agents#283](https://github.com/kontourai/flow-agents/issues/283): an
200
+ apply mode for `workflow-artifact-cleanup-audit`, so the dry-run classification can be
201
+ executed.
202
+
203
+ Both issues were checked against the open issue list before filing; no duplicates existed.
@@ -6,11 +6,12 @@ title: Migrations
6
6
 
7
7
  ## Unreleased
8
8
 
9
- - Workflow runtime artifacts now live under `.flow-agents/` instead of
10
- `.agents/flow-agents/`. Move any local session directories, sidecars, or
11
- `current.json` pointers you want to keep into the new root. Runtime state
12
- remains ignored; promote durable outcomes into docs, source, schemas, or
13
- provider records before merge.
9
+ - Workflow runtime artifacts now live under `.kontourai/flow-agents/` instead
10
+ of earlier runtime roots such as `.flow-agents/` or `.agents/flow-agents/`.
11
+ Move any local session directories, sidecars, or `current.json` pointers you
12
+ want to keep into the new root. Runtime readers do not fall back to old roots.
13
+ Runtime state remains ignored; promote durable outcomes into docs, source,
14
+ schemas, or provider records before merge.
14
15
  - Flow Agents setup no longer accepts Console bearer tokens as CLI arguments.
15
16
  Replace `--console-token TOKEN` with `--console-token-file PATH` for
16
17
  headless installs, or use the prompted `flow-agents init` flow. Interactive
@@ -206,7 +206,7 @@ Exit criteria:
206
206
 
207
207
  - A workflow can resume from artifacts without relying on the model remembering prior turns.
208
208
  - Goal Fit, evidence status, and next action can be read mechanically.
209
- - Multiple agents can share one workflow root by resolving `.flow-agents/current.json` and appending agent-local events instead of racing on root state.
209
+ - Multiple agents can share one workflow root by resolving `.kontourai/flow-agents/current.json` and appending agent-local events instead of racing on root state.
210
210
 
211
211
  ## Phase 3: Add Just-In-Time Guidance
212
212
 
@@ -261,7 +261,7 @@ Tasks:
261
261
  - Add promotion gates so guidance becomes stricter only after evidence shows it helps.
262
262
  - Make dashboards answer whether Flow Agents is improving outcomes over time.
263
263
  - Dogfood the workflow artifacts on Flow Agents changes: each substantial pass should produce sidecars, run artifact validation, delegate critique, update durable docs, and route accepted critique into the next slice. **Started:** `npm run workflow:sidecar -- dogfood-pass` records evidence, required critique, optional release readiness, optional learning, state, and handoff in one fail-closed validated pass.
264
- - Automatically create or select the current session artifact so self-validation does not depend on the user or orchestrator hand-picking `.flow-agents/<slug>`. **Started:** `npm run workflow:sidecar -- ensure-session` creates or selects a delivery session artifact plus initial state, acceptance, and handoff sidecars.
264
+ - Automatically create or select the current session artifact so self-validation does not depend on the user or orchestrator hand-picking `.kontourai/flow-agents/<slug>`. **Started:** `npm run workflow:sidecar -- ensure-session` creates or selects a delivery session artifact plus initial state, acceptance, and handoff sidecars.
265
265
 
266
266
  Exit criteria:
267
267
 
@@ -18,7 +18,7 @@ For the concrete directory-by-directory source map, generated output policy, run
18
18
  | Skills | Reusable procedures an agent can invoke when a task matches | Always-on policy, credentials, or long-lived memory | Agent Skills / `SKILL.md` |
19
19
  | Powers | Tool bundles, MCP configs, and activation guidance | Workflow gates or repo-specific policy semantics | MCP, OpenAPI, OAuth/OIDC |
20
20
  | Agents | Role prompts, delegation boundaries, and scoped tool access | Generic task procedures that should be skills | Harness-native subagents/profiles |
21
- | Workflows | Durable state, gates, handoffs, acceptance criteria, and phase transitions | Domain-specific knowledge records or tool internals | JSON Schema sidecars plus Markdown summaries |
21
+ | Workflows | Resumable state, gates, handoffs, acceptance criteria, and phase transitions | Domain-specific knowledge records or tool internals | JSON Schema sidecars plus Markdown summaries |
22
22
  | Knowledge | People, organizations, meetings, decisions, commitments, notes, and follow-ups | Verification verdicts or runtime telemetry | CommonMark, JSContact, iCalendar, JMAP, WebVTT/SRT, JSON-LD |
23
23
  | Evidence | Proof, telemetry, findings, evals, provenance, and quality outcomes | User-facing procedure instructions | OpenTelemetry, SARIF, CycloneDX, SLSA, JSON Schema |
24
24
 
@@ -37,7 +37,8 @@ Governance tools such as Veritas belong at the Evidence boundary. Flow Agents sh
37
37
  | `kits/` | Flow Kits | Kit Catalog entries, Flow Kit manifests, Flow Definitions, and supporting assets. Builder Kit is the first proof point. |
38
38
  | `prompts/` | Skills / Rules | Saved invocations. Promote repeatable procedures into skills when they grow stable. |
39
39
  | `docs/workflow-*.md` | Workflows | Human-readable workflow contracts and usage guidance. |
40
- | `.flow-agents/` | Workflows | Cross-session task artifacts. Runtime state stays local and ignored; durable outcomes are promoted into docs, source, schemas, or provider records before merge. |
40
+ | `.kontourai/flow-agents/` | Workflows | Non-durable cross-session task artifacts and generated projections. Runtime state stays local and ignored; durable outcomes are promoted into docs, source, schemas, or provider records before merge. |
41
+ | `.flow-agents/` | Workflows | Flow Agents-owned durable config/install state when a distribution explicitly owns that path. Not a runtime artifact fallback. |
41
42
  | `scripts/` | Evidence / Workflows / Packaging | Validation, build, telemetry, hooks, and artifact tooling. |
42
43
  | `src/` | Workflows / Evidence / Packaging | TypeScript CLI, runtime adapter, Flow Kit, shared library, build, validation, context-map, packaging, and CLI helper source compiled into `build/src/`. |
43
44
  | `evals/` | Evidence | Static, behavioral, integration, and acceptance checks. |
@@ -80,7 +81,7 @@ Builder Kit evidence gates can reference Surface trust state without naming a pr
80
81
  Workflow artifacts have their own lifecycle policy:
81
82
  https://github.com/kontourai/flow-agents/blob/main/docs/workflow-artifact-lifecycle.md
82
83
 
83
- Use `.flow-agents/<slug>/` for local runtime/session state. If in-progress planning needs review or handoff, promote the durable decision, behavior, and evidence summary into normal docs or provider records before merge; keep runtime artifacts out of git.
84
+ Use `.kontourai/flow-agents/<slug>/` for local runtime/session state. Keep `.flow-agents/` for explicit durable Flow Agents config/install state. If in-progress planning needs review or handoff, promote the durable decision, behavior, and evidence summary into normal docs or provider records before merge; keep runtime artifacts out of git.
84
85
 
85
86
  If a proposed artifact seems to belong to multiple layers, split it. For example, a dependency-checking capability may have:
86
87
 
@@ -10,7 +10,7 @@ This is the canonical developer-facing map for the Flow Agents repository. Use i
10
10
 
11
11
  - Edit canonical source in the repo root areas listed below, then regenerate derived output with the documented commands.
12
12
  - Do not edit `dist/`, `build/`, or `_site/` by hand. They are generated from tracked source.
13
- - Do not commit local runtime state from `.flow-agents/<slug>/`, `.kontourai/`, `.codex/`, `.claude/`, `.omx/`, `.promptfoo/`, `.telemetry/`, `.surface/`, generated `.veritas/` output, or tool caches; intentionally tracked `.veritas/` governance/config remains durable source.
13
+ - Do not commit local runtime state from `.kontourai/flow-agents/<slug>/`, `.codex/`, `.claude/`, `.omx/`, `.promptfoo/`, `.telemetry/`, `.surface/`, generated `.veritas/` output, or tool caches; intentionally tracked `.veritas/` governance/config remains durable source.
14
14
  - Runtime workflow artifacts stay local and ignored; promote reviewable or durable outcomes to docs, source, schemas, or provider records before merging to `main`.
15
15
  - Treat generated exports and installed runtime config as products of `packaging/manifest.json`, `src/tools/build-universal-bundles.ts`, `scripts/install-*.sh`, and the source directories they copy.
16
16
  - Use `.kontourai/` for non-durable local or generated Kontour workspace state. Keep durable tracked files in intuitive product-owned paths such as `.veritas/`, `.flow/`, `.agents/`, `.claude/commands`, and `docs/`; existing transition ignores remain during migration.
@@ -33,15 +33,15 @@ This is the canonical developer-facing map for the Flow Agents repository. Use i
33
33
  docs/ # durable docs and GitHub Pages source
34
34
  integrations/ # optional external integration config
35
35
  dist/ build/ _site/ # generated output; ignored
36
- .flow-agents/ .kontourai/ .codex/ .claude/ ... # local runtime state; ignored by default
36
+ .kontourai/ .flow-agents/ .codex/ .claude/ ... # local/generated or installed state; ignored by default
37
37
  ```
38
38
 
39
39
  ## Top-Level Inventory
40
40
 
41
41
  | Path | Classification | Source of truth | Generated or runtime policy | Safe cleanup rule |
42
42
  | --- | --- | --- | --- | --- |
43
- | `.flow-agents/` | runtime state | Workflow tools write local session artifacts. | Ignored. | Do not commit task runtime roots; promote durable decisions to docs, source, schemas, or providers before merge. |
44
- | `.kontourai/` | local/generated workspace state | Local Kontour tools and developer workflows. | Ignored. | Safe local cleanup when no active workflow needs it; durable source and decisions stay in product-owned tracked paths. |
43
+ | `.kontourai/` | local/generated workspace state | Local Kontour tools and developer workflows, including `.kontourai/flow-agents/<slug>/` runtime sessions. | Ignored. | Safe local cleanup when no active workflow needs it; durable source and decisions stay in product-owned tracked paths. |
44
+ | `.flow-agents/` | durable local Flow Agents state | Explicit Flow Agents config/install records when documented. | Ignored unless a repo-specific contract intentionally tracks a durable file. | Do not use for non-durable workflow sessions; migrate old runtime artifacts into `.kontourai/flow-agents/`. |
45
45
  | `.claude/` | installed runtime config | Generated bundle or local runtime install. | Ignored. | Reinstall from `dist/claude-code/` instead of editing as source. |
46
46
  | `.codex/` | installed runtime config | Generated bundle or local runtime install. | Ignored. | Reinstall from `dist/codex/` or `scripts/install-codex-home.sh`; do not treat local hooks as canonical. |
47
47
  | `.githooks/` | canonical repo tooling | Tracked repository hook scripts. | Source, not runtime agent hooks. | Keep compatible with `npm run setup:repo-hooks` and `npm run validate:repo-hooks --`. |
@@ -115,7 +115,7 @@ The package requires Node `>=22`, and GitHub Actions runs CI on Node 22. Keep `@
115
115
 
116
116
  `.codex/` and `.claude/` at the repo root are installed runtime configuration surfaces. They can be useful for local testing, but canonical hook scripts and runtime config live in `scripts/hooks/`, `context/`, `packaging/`, and generated bundle output. The stale local `.codex/hooks.json` incident came from treating an installed runtime file as if it were canonical source. The fix is to regenerate or reinstall runtime config and update the canonical builder/install sources when behavior must change.
117
117
 
118
- `.flow-agents/<slug>/` is workflow working memory. Keep plans, sidecars, evidence, and handoffs there while work is active. Promote stable outcomes into `docs/`, schemas, source, or provider records before final acceptance.
118
+ `.kontourai/flow-agents/<slug>/` is workflow working memory. Keep plans, sidecars, evidence, and handoffs there while work is active. `.flow-agents/` is reserved for Flow Agents-owned durable config/install state when explicitly documented; do not use it for non-durable sessions. Promote stable outcomes into `docs/`, schemas, source, or provider records before final acceptance.
119
119
 
120
120
  Across Kontour repos, `.kontourai/` is the simple ignored home for non-durable local/generated workspace state. It is not a durable source root. Keep durable governance, Flow config, agent source, command source, and documentation in the product-owned tracked paths where developers expect them, including `.veritas/`, `.flow/`, `.agents/`, `.claude/commands`, and `docs/`. Existing transition ignores such as `.flow-agents/`, `.kontour/`, `.surface/`, `.veritas/evidence/`, `.flow/runs/`, and `.telemetry/` remain in place during migration.
121
121
 
@@ -82,7 +82,7 @@ This view shows how each phase is composed. The left rail is the durable phase s
82
82
  <section class="phase-lane phase-lane--primary"><h3>Primary</h3><p><code>builder-shape</code> <code>idea-to-backlog</code></p></section>
83
83
  <section class="phase-lane"><h3>Support</h3><p><code>search-first</code> <code>explore</code> <code>frontend-design</code> <code>github-cli</code> <code>knowledge-capture</code></p></section>
84
84
  <section class="phase-lane"><h3>Nested sections / future primitives</h3><p>intake/dedupe, separate ideas, thinnest meaningful slice, opportunity review, explore options, <code>shape-work</code>, prioritize work, sync executable backlog</p></section>
85
- <section class="phase-lane phase-lane--gate"><h3>Gate & artifact</h3><p>Idea, slice, shape, and backlog gates. Writes shaped briefs and GitHub issue links in <code>.flow-agents/&lt;slug&gt;/</code>.</p></section>
85
+ <section class="phase-lane phase-lane--gate"><h3>Gate & artifact</h3><p>Idea, slice, shape, and backlog gates. Writes shaped briefs and GitHub issue links in <code>.kontourai/flow-agents/&lt;slug&gt;/</code>.</p></section>
86
86
  </div>
87
87
  </article>
88
88
  <article class="phase-row">
@@ -137,15 +137,15 @@ The highest-leverage future extractions are likely `shape-work`, `test-map`, `sc
137
137
 
138
138
  Each workflow phase ends with an explicit gate and durable artifact:
139
139
 
140
- - `builder-shape` invokes Builder Kit shape, delegates to `idea-to-backlog`, links `kits/builder/flows/shape.flow.json`, and writes the standard `.flow-agents/<slug>/<slug>--idea-to-backlog.md` artifact.
141
- - `idea-to-backlog` writes `.flow-agents/<slug>/<slug>--idea-to-backlog.md` and produces shaped briefs plus GitHub issue links.
142
- - `pull-work` writes `.flow-agents/<slug>/<slug>--pull-work.md` with selected issues, WIP notes, blockers, pickup Probe decisions or accepted gaps, worktree decision, expected modified files, conflict risks, and a `plan-work` handoff.
143
- - `plan-work` and `deliver` write `.flow-agents/<slug>/<slug>--*.md` artifacts with `Definition Of Done`, `Goal Fit Gate`, and `Final Acceptance` sections.
140
+ - `builder-shape` invokes Builder Kit shape, delegates to `idea-to-backlog`, links `kits/builder/flows/shape.flow.json`, and writes the standard `.kontourai/flow-agents/<slug>/<slug>--idea-to-backlog.md` artifact.
141
+ - `idea-to-backlog` writes `.kontourai/flow-agents/<slug>/<slug>--idea-to-backlog.md` and produces shaped briefs plus GitHub issue links.
142
+ - `pull-work` writes `.kontourai/flow-agents/<slug>/<slug>--pull-work.md` with selected issues, WIP notes, blockers, pickup Probe decisions or accepted gaps, worktree decision, expected modified files, conflict risks, and a `plan-work` handoff.
143
+ - `plan-work` and `deliver` write `.kontourai/flow-agents/<slug>/<slug>--*.md` artifacts with `Definition Of Done`, `Goal Fit Gate`, and `Final Acceptance` sections.
144
144
  - `review-work` writes reviewer artifacts when available and updates `critique.json` with quality, security, architecture, standards, and resolution state.
145
145
  - `verify-work` writes verification artifacts and updates `evidence.json` with behavior evidence mapped to acceptance criteria.
146
- - `evidence-gate` writes `.flow-agents/<slug>/<slug>--evidence-gate.md` with acceptance evidence, CI summary, integrity report, verdict, and next step.
147
- - `release-readiness` writes `.flow-agents/<slug>/<slug>--release-readiness.md` with release scope, evidence reference, risk review, operational plan, rollback plan, observability plan, post-deploy checks, and decision.
148
- - `learning-review` writes `.flow-agents/<slug>/<slug>--learning-review.md` with outcomes, evidence, decisions, gaps, follow-ups, knowledge updates, and verdict.
146
+ - `evidence-gate` writes `.kontourai/flow-agents/<slug>/<slug>--evidence-gate.md` with acceptance evidence, CI summary, integrity report, verdict, and next step.
147
+ - `release-readiness` writes `.kontourai/flow-agents/<slug>/<slug>--release-readiness.md` with release scope, evidence reference, risk review, operational plan, rollback plan, observability plan, post-deploy checks, and decision.
148
+ - `learning-review` writes `.kontourai/flow-agents/<slug>/<slug>--learning-review.md` with outcomes, evidence, decisions, gaps, follow-ups, knowledge updates, and verdict.
149
149
 
150
150
  Core gates:
151
151
 
@@ -86,8 +86,8 @@ Flow Agents currently ships five canonical policy classes. Each policy class has
86
86
  **Canonical trigger event**: `userPromptSubmit` and `agentSpawn`/`SessionStart` (active-goal re-grounding), `postToolUse` (after `InvokeSubagents` tool calls)
87
87
 
88
88
  **Inputs consumed**:
89
- - `.flow-agents/<slug>/state.json` — current workflow phase and status
90
- - `.flow-agents/<slug>/critique.json` — open critique findings
89
+ - `.kontourai/flow-agents/<slug>/state.json` — current workflow phase and status
90
+ - `.kontourai/flow-agents/<slug>/critique.json` — open critique findings
91
91
  - `docs/context-map.md` — structure hint for repo navigation
92
92
 
93
93
  **Decision contract**: Non-blocking. Always exits 0. Appends steering text to the agent's context via `additionalContext` in the hook response. Does not block any action. It re-grounds the active workflow goal (status, phase, recorded next step) at the start of every user turn — not only for flagged/blocked states — and on `SessionStart`, which fires after context compaction and on resume. This is the mechanism that keeps an in-flight goal alive across context loss instead of relying on the model voluntarily re-reading the sidecar.
@@ -125,12 +125,14 @@ Flow Agents currently ships five canonical policy classes. Each policy class has
125
125
  **Canonical trigger event**: `stop`
126
126
 
127
127
  **Inputs consumed**:
128
- - `.flow-agents/<slug>/*.md` — workflow artifact files (scanned for active status, DOD, Goal Fit Gate sections)
129
- - `.flow-agents/<slug>/state.json` — workflow phase and next action
130
- - `.flow-agents/<slug>/evidence.json` — verification verdict and NOT_VERIFIED gaps
131
- - `.flow-agents/<slug>/critique.json` — critique status and open findings
132
- - `.flow-agents/<slug>/command-log.jsonl` — the deterministic capture log written by the Evidence Capture policy (see §2.5); cross-referenced against `evidence.json` claimed-pass command checks
133
- - `.flow-agents/<slug>/acceptance.json` — acceptance criteria; a criterion's `command`-kind `evidence_ref` (`excerpt`) is the most-trusted backstop command
128
+ - `.kontourai/flow-agents/<slug>/*.md` — workflow artifact files (scanned for active status, DOD, Goal Fit Gate sections)
129
+ - `.kontourai/flow-agents/<slug>/state.json` — workflow phase and next action
130
+ - `.kontourai/flow-agents/<slug>/evidence.json` — verification verdict and NOT_VERIFIED gaps
131
+ - `.kontourai/flow-agents/<slug>/critique.json` — critique status and open findings
132
+ - `.kontourai/flow-agents/<slug>/command-log.jsonl` — the deterministic capture log written by the Evidence Capture policy (see §2.5); cross-referenced against `evidence.json` claimed-pass command checks
133
+ - `.kontourai/flow-agents/<slug>/acceptance.json` — acceptance criteria; a criterion's `command`-kind `evidence_ref` (`excerpt`) is the most-trusted backstop command
134
+ - `.kontourai/flow-agents/current.json` (`active_flow_id`/`active_step_id`) — when present, resolves the active kit FlowDefinition's gate `expects[]` via the compiled `build/src/lib/flow-resolver.js` (`loadActiveFlowStep`, ADR 0016 Abstraction A P-c); requires `build/` to exist and fails open to the legacy `workflow.*`-only behavior when it does not (the `hasBuild` guard — the same fail-open pattern already used for the trust-bundle validator)
135
+ - The active kit's `kits/<kit>/flows/<flow>.flow.json` — the FlowDefinition file `current.json` resolves against; the matching gate's `expects[].bundle_claim.claimType` values become the declared claim types enforced for the active step (see FlowDefinition-driven claim selection below)
134
136
  - `FLOW_AGENTS_GOAL_FIT_MODE` env var — `block` | `warn` | `off` (the legacy `FLOW_AGENTS_GOAL_FIT_STRICT=true` is an alias for `block`)
135
137
  - `FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS` env var — consecutive-identical-block cap before the escape hatch releases (default 3)
136
138
  - `FLOW_AGENTS_GOAL_FIT_BACKSTOP` env var — `block` (default) | `off`/`warn` | `skip`; controls the capture backstop re-run (see Capture cross-reference below)
@@ -143,6 +145,8 @@ Flow Agents currently ships five canonical policy classes. Each policy class has
143
145
  - `off`: silent (exits 0, no stderr).
144
146
  - Escape hatch: in `block` mode the same goal-fit gap is refused up to `FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS` (default 3) consecutive times, then released (exit 0 with a loud notice) so a genuinely-unsatisfiable goal cannot trap the agent. A changing gap resets the streak.
145
147
 
148
+ **FlowDefinition-driven claim selection (ADR 0016 Abstraction A)**: When `current.json` resolves an active flow/step, `bundleEnforcement`'s claim-selection predicate (`isSelectedClaim`) is a **union**: `workflow.*`-prefixed claims are always selected as a baseline floor, and the active gate's declared `claimType` set (from `expects[].bundle_claim.claimType`, e.g. `builder.verify.tests`) is selected *in addition to* that floor — never instead of it. An earlier design used a pure if/else (declared types selected only when a FlowDefinition was active, with no `workflow.*` fallback) and was found in PR #215 to compose into a HIGH-severity gate-bypass chain: a forged `current.json` pointing at an `expects: []` flow made the if/else select zero claims, silently skipping all re-derivation, tamper-detection, and high/critical enforcement. The union floor closed that chain and is a **permanent** design decision, not a transitional step toward the if/else — see [ADR 0016](../adr/0016-three-hard-boundary-model.md) and the PR #215 post-mortem in [ADR 0015](../adr/0015-flow-flow-agents-boundary-reconciliation.md). Consequently, an active FlowDefinition whose gate resolves to an **empty** `expects[]` is always a `HARD_BLOCK` (`gate misconfiguration: active FlowDefinition has empty expects[]...`) — an empty declared set is treated as a possible tampered flow definition, never as a legitimately-empty gate that quietly enforces nothing beyond the floor.
149
+
146
150
  **Capture cross-reference (capture-first determinism)**: For each `evidence.checks[]` of `kind:"command"` claiming `status:"pass"` that carries a `command`, the gate cross-references the deterministic capture log (`command-log.jsonl`, §2.5) *before* trusting the model's claim:
147
151
 
148
152
  1. **Log shows the command ran and FAILED** → this is a caught false-completion → a blocking goal-fit gap (feeds the existing block/`MAX_BLOCKS` machinery).
@@ -186,9 +190,9 @@ Flow Agents currently ships five canonical policy classes. Each policy class has
186
190
  **Inputs consumed**:
187
191
  - `tool_name` + `tool_input.command` — identifies a command/shell execution (a command string present, with a command-shaped tool name; when no tool name is present but a command string is, it is still captured).
188
192
  - `tool_response` / `tool_output` / `error` — the host tool result (per §1, `postToolUse`); the source of the deterministically-observed outcome.
189
- - `.flow-agents/current.json` (`active_slug` / `artifact_dir`) then newest-mtime `state.json` — resolves the active artifact dir, the same way Workflow Steering and Stop-Goal-Fit do.
193
+ - `.kontourai/flow-agents/current.json` (`active_slug` / `artifact_dir`) then newest-mtime `state.json` — resolves the active artifact dir, the same way Workflow Steering and Stop-Goal-Fit do.
190
194
 
191
- **Output**: appends one JSON object per line to `.flow-agents/<slug>/command-log.jsonl`:
195
+ **Output**: appends one JSON object per line to `.kontourai/flow-agents/<slug>/command-log.jsonl`:
192
196
 
193
197
  ```json
194
198
  { "command": "npm test", "observedResult": "pass", "exitCode": 0, "capturedAt": "2026-06-23T00:00:00Z", "source": "postToolUse-capture" }
@@ -561,7 +565,7 @@ The CLI command is:
561
565
  flow-agents kit activate --adapter strands-local [--dest DIR] [--source-root DIR]
562
566
  ```
563
567
 
564
- This writes activated flow files to `.flow-agents/runtime/strands/flows/<kit-id>/<asset-id>.flow.json` and produces a parity-diagnostic `activation.json` (same schema as codex-local: `schema_version`, `adapter`, `supported_asset_classes`, `generated_runtime_files`, `skipped_assets`, `warnings`, `errors`).
568
+ This writes activated flow files to `.kontourai/flow-agents/projections/strands/flows/<kit-id>/<asset-id>.flow.json` and produces a parity-diagnostic `activation.json` (same schema as codex-local: `schema_version`, `adapter`, `supported_asset_classes`, `generated_runtime_files`, `skipped_assets`, `warnings`, `errors`).
565
569
 
566
570
  ### 9.2 Steering context surfacing (AC2)
567
571
 
@@ -572,7 +576,7 @@ This writes activated flow files to `.flow-agents/runtime/strands/flows/<kit-id>
572
576
  ```
573
577
  hooks = FlowAgentsHooks(workspace=".")
574
578
  system_prompt = base_prompt + hooks.steering_context()
575
- # steering_context() includes KIT FLOWS section if .flow-agents/runtime/strands/flows/ is populated
579
+ # steering_context() includes KIT FLOWS section if .kontourai/flow-agents/projections/strands/flows/ is populated
576
580
  ```
577
581
 
578
582
  **TypeScript usage**:
@@ -580,14 +584,14 @@ system_prompt = base_prompt + hooks.steering_context()
580
584
  ```typescript
581
585
  const hooks = new FlowAgentsHooks({ workspace: "." });
582
586
  const systemPrompt = basePrompt + hooks.steeringContext();
583
- // steeringContext() includes KIT FLOWS section if .flow-agents/runtime/strands/flows/ is populated
587
+ // steeringContext() includes KIT FLOWS section if .kontourai/flow-agents/projections/strands/flows/ is populated
584
588
  ```
585
589
 
586
590
  ### 9.3 Co-existence with codex-local
587
591
 
588
592
  The `codex-local` and `strands-local` runtime directories are independent:
589
593
 
590
- - `codex-local` writes to `.flow-agents/runtime/codex/`
591
- - `strands-local` writes to `.flow-agents/runtime/strands/`
594
+ - `codex-local` writes to `.kontourai/flow-agents/projections/codex/`
595
+ - `strands-local` writes to `.kontourai/flow-agents/projections/strands/`
592
596
 
593
597
  Running either adapter does not affect the other's runtime directory. Both adapters skip non-flow asset classes (skills, docs, adapters, evals, assets) with `reason: "asset class is diagnostic-only for <adapter>"`.
@@ -0,0 +1,155 @@
1
+ # SPIKE findings — graph database provider experience: Neo4j Community vs Kuzu (embedded)
2
+
3
+ - Issue: kontourai/flow-agents#318
4
+ - Executed: 2026-07-03 (agent session)
5
+ - **Graph snapshot timestamp: `2026-07-03T05:14:42Z`** (point-in-time; two builds in flight during the spike — #312 flow-agents, #314 traverse — so backlog edges may have moved since)
6
+ - Provider interface (#317) had NOT landed → used a throwaway extractor (`build-graph.js`) over the real stores, per scope.
7
+ - Engines exercised: **BOTH** — Neo4j Community 5 (Docker) AND Kuzu 0.11.3 (embedded, in-process via npm). All 5 canonical queries ran on both.
8
+
9
+ ---
10
+
11
+ ## 1. Node / edge counts (identical on both engines)
12
+
13
+ **Nodes: 200**
14
+
15
+ | Label | Count | Source |
16
+ |---|---|---|
17
+ | Issue | 116 | flow-agents (112) + traverse (4), via `gh issue list --json` |
18
+ | Session | 40 | `.kontourai/flow-agents/archive/sweep-2026-07-02.json` (`archived[]`) |
19
+ | Decision | 23 | `docs/adr/*.md` (the *living* `docs/decisions/` registry from #310 does not exist yet — ADRs are the current decision records) |
20
+ | PR | 13 | flow-agents PRs that carry `closingIssuesReferences` |
21
+ | Learning | 8 | numbered sections of `docs/learnings/2026-07-improvement-program.md` |
22
+
23
+ **Edges: 227**
24
+
25
+ | Type | Count | Derivation |
26
+ |---|---|---|
27
+ | RELATES | 141 | prose `#NNN` cross-references (+ cross-repo `traverse#NN`, + ADR-0007 number collision) |
28
+ | MENTIONS | 35 | Decision→Issue and Learning→Issue `#NNN` references in doc bodies |
29
+ | BLOCKED_BY | 27 | metadata markers (`work-item-metadata.blockers[]`) AND prose ("blocked by/depends on #N") |
30
+ | CLOSES | 14 | PR→Issue from `closingIssuesReferences` |
31
+ | EVIDENCE_OF | 10 | Session→Decision/Issue — **heuristic** slug/title token overlap (≥2 shared ≥5-char tokens), flagged `heuristic:true` |
32
+
33
+ AC1 satisfied: both engines loaded the real graph; counts reported.
34
+
35
+ ---
36
+
37
+ ## 2. Engine setup friction
38
+
39
+ ### Neo4j Community (Docker)
40
+ - `docker run -d -p 7474:7474 -p 7687:7687 -e NEO4J_AUTH=neo4j/… neo4j:5-community` — image pull + boot to "Started" in ~30s. Zero config.
41
+ - **Schema-free load**: no DDL. `UNWIND $rows AS r CREATE (n:Label) SET n=r` for nodes; `UNWIND … MATCH (a{id}),(b{id}) CREATE (a)-[x:TYPE]->(b) SET x=r.props` for edges. Endpoints matched by `id` regardless of label — polyglot property bags "just work."
42
+ - Bulk load of 200 nodes + 227 edges via batched UNWIND: **~1.8s**.
43
+ - Ops cost: a running server + two ports + auth. Fine locally; a real dependency in CI/prod.
44
+
45
+ ### Kuzu (embedded, npm)
46
+ - `npm install kuzu` → `new kuzu.Database(path)` + `new kuzu.Connection(db)`. In-process, no server, no ports. SQLite-for-graphs as advertised.
47
+ - **Typed schema REQUIRED up front**: `CREATE NODE TABLE Issue(id STRING PRIMARY KEY, …)` and `CREATE REL TABLE BLOCKED_BY(FROM Issue TO Issue, …)`. Multi-pair rel tables (`FROM Decision TO Issue, FROM Learning TO Issue`) are supported and needed here. This is more rigor than Neo4j but also more friction for an evolving/heterogeneous graph.
48
+ - **Escaping gotcha**: string literals with `'` fail the Cypher parser even with SQL-style `''` doubling — had to switch to parameterized `conn.prepare()`/`conn.execute()`. (Real backlog titles contain apostrophes, em-dashes, emoji — this bit immediately.)
49
+ - **Cleanup gotcha**: the DB is a file *plus* a `.wal` sidecar. Deleting only the file leaves a stale catalog → "Issue already exists in catalog" on reload. Must remove `<db>` and `<db>.wal`.
50
+ - Load of the same graph via per-row prepared statements: **~3.3s** (Kuzu's real strength is bulk `COPY FROM`, which I didn't use for 200 rows).
51
+
52
+ ### ⚠️ Material viability finding (dominates the recommendation)
53
+ **Kuzu is abandoned upstream.** The npm package (`kuzu@0.11.3`) prints *"Package no longer supported"* on install. In October 2025 Kùzu Inc. was acquired (reporting: by Apple), the GitHub repo was **archived**, and active development/support ended. It remains MIT-licensed and usable; community forks exist (Kineviz **"bighorn"**, **"Ladybug"**) but are early. Adopting Kuzu today means betting on a fork or freezing on an unmaintained pin. Sources: The Register 2025-10-14 "KuzuDB graph database abandoned"; npm deprecation notice on `kuzu`.
54
+
55
+ ---
56
+
57
+ ## 3. Query ergonomics — side-by-side Cypher (where they differ)
58
+
59
+ Q1–Q3 were **byte-identical Cypher** across engines. Q3, Q4, Q5 differed:
60
+
61
+ **Q1 — transitive blocker closure (identical):**
62
+ ```cypher
63
+ MATCH (i:Issue {id:'FA#313'})-[:BLOCKED_BY*1..10]->(b:Issue)
64
+ RETURN DISTINCT b.id, b.state ORDER BY b.id
65
+ ```
66
+ Both engines accept the `*1..10` variable-length syntax verbatim.
67
+
68
+ **Q3 — orphans (no inbound). DIFFERS:**
69
+ ```cypher
70
+ -- Neo4j: pattern-predicate + labels()[0]
71
+ MATCH (n) WHERE NOT ( ()-->(n) ) RETURN labels(n)[0] AS label, count(*) ...
72
+ -- Kuzu: EXISTS-subquery + label() (singular)
73
+ MATCH (n) WHERE NOT EXISTS { MATCH ()-[]->(n) } RETURN label(n) AS label, count(*) ...
74
+ ```
75
+
76
+ **Q4 — duplicate candidates (string/list functions DIFFER):**
77
+ ```cypher
78
+ -- Neo4j: split() + list comprehension + substring()
79
+ [w IN split(toLower(t),' ') WHERE size(w)>=5 | substring(w,0,5)]
80
+ -- Kuzu: string_split() + list_transform()/list_filter() + list_contains()
81
+ list_transform(list_filter(string_split(lower(t),' '), x->size(x)>=5), x->substring(x,1,5))
82
+ ```
83
+ Note `substring` is **0-indexed in Neo4j, 1-indexed in Kuzu**.
84
+
85
+ **Q5 — shortest path between two decisions. DIFFERS most:**
86
+ ```cypher
87
+ -- Neo4j: shortestPath() function + list comprehension over path nodes
88
+ MATCH p=shortestPath((a:Decision {id:'ADR-0011'})-[*..8]-(b:Decision {id:'ADR-0021'}))
89
+ RETURN [n IN nodes(p) | n.id] AS path, length(p)
90
+ -- Kuzu: SHORTEST keyword in the pattern + list_transform for projection
91
+ MATCH p=(a:Decision {id:'ADR-0011'})-[* SHORTEST 1..8]-(b:Decision {id:'ADR-0021'})
92
+ RETURN list_transform(nodes(p), x->x.id) AS path, length(p)
93
+ ```
94
+ Kuzu rejected the Neo4j-style `[n IN nodes(p) | n.id]` projection ("Variable n is not in scope") — `list_transform` is the Kuzu idiom. Both returned the same path.
95
+
96
+ **Takeaway:** ~80% of Cypher is portable; the divergence is entirely in (a) existence predicates, (b) string/list stdlib, (c) path projection + shortest-path spelling. A provider abstraction would need a thin dialect shim for exactly those three areas.
97
+
98
+ ---
99
+
100
+ ## 4. What the queries REVEALED (surprises > confirmations)
101
+
102
+ **Q1 — SURPRISE / the headline.** #313's transitive blockers = **{#312 (OPEN), #310 (CLOSED)}** — and *nothing else*. The orchestrator's stated ground truth ("#313's transitive blockers now include #317") **does NOT hold in this snapshot.** No edge from #313 (or its blockers #312/#310) to #317 exists in metadata OR prose; #317 is referenced only by this spike (#318, soft blocker). Verified with a fresh individual `gh issue view` on #313/#312/#310. Interpretation: the intended #313→(knowledge provider #317) dependency is **not yet encoded** — either the edit is still in flight (builds #312/#314 open) or the coupling lives only in humans' heads. *This is exactly the class of gap a graph pass surfaces mechanically: an expected transitive dependency that isn't in the data.* The #310–#314 chain itself is confirmed: #310→{#311,#312,#314}, #312→#313.
103
+
104
+ **Q2 — contradiction candidates: the ADR failure mode caught red-handed.** Top hit is **ADR-0007 vs ADR-0007b** — two files sharing decision number 0007 ("Flow/Skill/Kit/Tool Boundary"), one `Accepted`, one status-less, both citing #62. This is *literally* the numbering-collision + contradiction-accumulation failure that #310 was written to kill, sitting in the current ADR tree. Also surfaced: ADR-0014 (`Proposed`, superseded) contradicting ADR-0015/0016 (`Accepted`) over the same subject (#183, the core-vs-domain boundary), and ADR-0011/0012 (`Accepted`) vs ADR-0021 (`Draft`) over #137. These are real "divergent status over shared subject" pairs.
105
+
106
+ **Q3 — orphans: reveals a modeling lesson, not just data.** "No inbound edge" flags 43 issues, all 40 sessions, 21 decisions, all 13 PRs, all 8 learnings. But Sessions/PRs/Learnings are *source-only node types by construction* (EVIDENCE_OF/CLOSES/MENTIONS all originate from them), so flagging them wholesale is noise. **Finding: orphan detection needs node-type awareness** ("issues/decisions with no inbound" is the meaningful query; leaf-type nodes should be excluded). The genuinely interesting orphans are the 21 Decisions (ADRs) that *nothing* in the backlog references — candidate stale/undiscoverable decisions.
107
+
108
+ **Q4 — duplicate candidates: naive title-token overlap MISSES the known duplicate.** With exact ≥5-char token matching, the ground-truth **traverse#14 ~ traverse#8** duplicate did **not** appear (they share only `extraction`; `chunk` vs `chunking` don't match exactly). It surfaced only after switching to **5-char-prefix stemming** (`extra`,`chunk`), on *both* engines. Lesson: mechanical dup-detection needs stemming + shared-evidence (both issues cite the same 23-item listing-page truncation (downstream consumer pilot) in their *bodies*, which title-only matching can't see — full-text/evidence-ref overlap is required, exactly what #317's "shared evidence refs" clause calls for). Bonus real find: the **runtime-compatibility-canary trio #75/#93/#247** ranks top — recurring near-duplicate canary-failure issues.
109
+
110
+ **Q5 — shortest path.** ADR-0011 ↔ ADR-0021 resolves to `ADR-0011 → FA#137 ← ADR-0021` (length 2): two decisions connected through the backlog issue they both touch. Clean, and a genuinely useful "how are these two decisions related" primitive.
111
+
112
+ AC2 satisfied: all five queries executed on both engines, interpreted against ground truth.
113
+
114
+ ---
115
+
116
+ ## 5. Visualization notes
117
+
118
+ - **Neo4j Browser** (http://localhost:7474) is the real differentiator. Captured screenshot (`neo4j-graph.png`, via Playwright) shows the Browser **connected to the live instance** (`neo4j://localhost:7687`, Community 5.26) rendering `MATCH p=(a:Issue)-[:BLOCKED_BY]->(b:Issue) RETURN p LIMIT 60` as a **d3-force graph — 26 Issue nodes / 27 BLOCKED_BY relationships in several distinct clusters** (the backlog's blocker chains, visually separable at a glance). The left Database Information panel simultaneously confirms the full loaded graph: **Nodes (200)** color-coded by all five labels (Decision, Issue, Learning, PR, Session) and **Relationships (227)** across all five types (BLOCKED_BY, CLOSES, EVIDENCE_OF, MENTIONS, RELATES), plus the property-key catalog (id, state, status, superseded, heuristic, overlap, markerStatus, crossRepo, …). Interactive force-directed exploration, click-to-expand neighborhoods, and color-by-label are its standout value for *human* exploration of the blocker/decision subgraph — Kuzu has no equivalent.
119
+ - **Kuzu** ships **no built-in visualization** in the embedded npm path (Kuzu Explorer exists only as a separate Docker image — which defeats the "zero-ops embedded" pitch). For an embedded engine you bring your own viz (export to a JS graph lib).
120
+ - Screenshot path: `/Users/brian/.claude/jobs/90beb625/tmp/graph-spike/neo4j-graph.png`.
121
+
122
+ ---
123
+
124
+ ## 6. Recommendation: **DEFER adoption** (build the model now, pick the engine later)
125
+
126
+ The spike's own gate ("adoption stays gated on a real query going slow/awkward over file providers") did **not** trip: all five queries ran in milliseconds over 200 nodes / 227 edges. At portfolio scale (hundreds of issues, dozens of decisions, ~120 sessions) this graph is *tiny* — an in-memory JS object graph, or even the throwaway extractor + array scans, answers every canonical query without a database engine at all. **The value proven tonight is the MODEL and the QUERIES, not either engine.**
127
+
128
+ **What to build now (regardless of engine):** the #317 typed graph model (nodes/edges/provenance) + the read-side extractors validated here (metadata markers + prose blockers + ADR/tombstone status + archive index + PR closes). That model is what caught the ADR-0007 collision, the missing #313→#317 edge, and the traverse#14 dup.
129
+
130
+ **Trigger conditions to REVISIT an engine (adopt-when):**
131
+ 1. Graph exceeds ~10k nodes / ~50k edges, OR a canonical query (transitive closure, all-pairs shortest path, dup-scan) measurably lags in the naive JS implementation.
132
+ 2. Multi-hop/variable-length traversal or shortest-path becomes a *frequent, interactive* need (not batch) — this is where hand-rolled JS gets painful and Cypher pays off.
133
+ 3. Interactive human exploration of the knowledge graph becomes a workflow (not just automated health passes) — pulls toward Neo4j Browser specifically.
134
+
135
+ **If/when a trigger fires, prefer Neo4j Community over Kuzu**, primarily because **Kuzu is abandoned upstream (Oct 2025)** — the "zero-ops embedded" advantage is real but is now offset by no maintenance, no security updates, and a fork-or-freeze decision. Neo4j Community is heavier (server + ports) but actively maintained, has the browser, and its Cypher is the portable baseline. *Caveat:* re-evaluate the Kuzu forks (bighorn/Ladybug) at revisit time — if one is credibly maintained, embedded-Kuzu-fork reclaims the zero-ops win for the automated-health-pass use case.
136
+
137
+ **What a provider implementation (#317) would need:**
138
+ - Read-side extractors for each store (validated here): work-item adapter (issues + `work-item-metadata` markers + prose refs), git-repo-docs adapter (ADR/decision status + tombstones + evidence[] + CONTEXT.md vocabulary + learnings), archive-index adapter (sessions). **Robustness note:** 3 of 19 metadata markers failed to JSON-parse and several `blockers[].ref` were `undefined` — the extractor MUST tolerate malformed markers and fall back to prose.
139
+ - A typed node/edge schema (Kuzu proved you *can* enforce types; the model should own the contract independent of storage).
140
+ - Proposal-only writes where the store is human-curated (decision registry, CONTEXT.md).
141
+ - A **dialect shim** if any real engine is used, covering exactly the three divergences found: existence predicates, string/list stdlib (incl. 0- vs 1-indexed substring), and shortest-path/path-projection syntax.
142
+ - Dup-detection needs **stemming + shared-evidence-ref overlap**, not exact title tokens (proven by the traverse#14~#8 miss).
143
+
144
+ AC3 satisfied: explicit adopt/defer recommendation with trigger conditions and provider requirements.
145
+
146
+ ---
147
+
148
+ ## Appendix — artifacts in this scratch dir (auto-cleaned with the job; nothing committed)
149
+ - `build-graph.js` — throwaway extractor → `graph.json` (200 nodes / 227 edges)
150
+ - `kuzu-load.js`, `kuzu-queries.js` — Kuzu embedded loader + 5 queries
151
+ - `neo4j-load.js`, `neo4j-queries.js`, `neo4j-q4-stem.js` — Neo4j loader + queries
152
+ - `graph.json`, `fa-issues.json`, `traverse-issues.json`, `fa-prs.json`, `adr.json` — snapshots
153
+ - `kuzu-db` (+`.wal`) — embedded DB file
154
+ - `neo4j-browser.png` — visualization screenshot
155
+ - Docker container `graph-spike-neo4j` — **torn down at end of session** (see cleanup)