@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
@@ -18,10 +18,10 @@ _pass() { echo " ✓ $1"; }
18
18
  _fail() { echo " ✗ $1"; errors=$((errors + 1)); }
19
19
 
20
20
  REPO="$TMPDIR_EVAL/repo"
21
- mkdir -p "$REPO/.flow-agents/feedback-loop"
21
+ mkdir -p "$REPO/.kontourai/flow-agents/feedback-loop"
22
22
  printf '# Test Repo\n' > "$REPO/AGENTS.md"
23
23
 
24
- cat > "$REPO/.flow-agents/feedback-loop/feedback-loop--deliver.md" <<'MARKDOWN'
24
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/feedback-loop--deliver.md" <<'MARKDOWN'
25
25
  # Build feedback loop
26
26
 
27
27
  branch: main
@@ -66,7 +66,7 @@ else
66
66
  fi
67
67
  fi
68
68
 
69
- cat > "$REPO/.flow-agents/feedback-loop/feedback-loop--deliver.md" <<'MARKDOWN'
69
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/feedback-loop--deliver.md" <<'MARKDOWN'
70
70
  # Build feedback loop
71
71
 
72
72
  branch: main
@@ -108,7 +108,7 @@ MARKDOWN
108
108
  # pending criteria so the sidecar-driven Final Acceptance hygiene check fires.
109
109
  # The markdown-based uncheckedInSection(Final Acceptance) check was removed; the
110
110
  # acceptance.json pending-criteria check in missingBundleOrStateSignal is its replacement.
111
- cat > "$REPO/.flow-agents/feedback-loop/state.json" <<'JSON'
111
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/state.json" <<'JSON'
112
112
  {
113
113
  "schema_version": "1.0",
114
114
  "task_slug": "feedback-loop",
@@ -119,7 +119,7 @@ cat > "$REPO/.flow-agents/feedback-loop/state.json" <<'JSON'
119
119
  }
120
120
  JSON
121
121
 
122
- cat > "$REPO/.flow-agents/feedback-loop/acceptance.json" <<'JSON'
122
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/acceptance.json" <<'JSON'
123
123
  {
124
124
  "schema_version": "1.0",
125
125
  "task_slug": "feedback-loop",
@@ -155,9 +155,9 @@ else
155
155
  fi
156
156
 
157
157
  BACKLOG_REPO="$TMPDIR_EVAL/backlog-repo"
158
- mkdir -p "$BACKLOG_REPO/.flow-agents/configurable-workflow-routing"
158
+ mkdir -p "$BACKLOG_REPO/.kontourai/flow-agents/configurable-workflow-routing"
159
159
  printf '# Test Repo\n' > "$BACKLOG_REPO/AGENTS.md"
160
- cat > "$BACKLOG_REPO/.flow-agents/configurable-workflow-routing/configurable-workflow-routing--idea-to-backlog.md" <<'MARKDOWN'
160
+ cat > "$BACKLOG_REPO/.kontourai/flow-agents/configurable-workflow-routing/configurable-workflow-routing--idea-to-backlog.md" <<'MARKDOWN'
161
161
  # Configurable Workflow Routing
162
162
 
163
163
  status: complete
@@ -191,7 +191,7 @@ else
191
191
  fi
192
192
  fi
193
193
 
194
- cat > "$REPO/.flow-agents/feedback-loop/state.json" <<'JSON'
194
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/state.json" <<'JSON'
195
195
  {
196
196
  "schema_version": "1.0",
197
197
  "task_slug": "feedback-loop",
@@ -205,7 +205,7 @@ cat > "$REPO/.flow-agents/feedback-loop/state.json" <<'JSON'
205
205
  }
206
206
  JSON
207
207
 
208
- cat > "$REPO/.flow-agents/feedback-loop/acceptance.json" <<'JSON'
208
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/acceptance.json" <<'JSON'
209
209
  {
210
210
  "schema_version": "1.0",
211
211
  "task_slug": "feedback-loop",
@@ -230,7 +230,7 @@ cat > "$REPO/.flow-agents/feedback-loop/acceptance.json" <<'JSON'
230
230
  }
231
231
  JSON
232
232
 
233
- cat > "$REPO/.flow-agents/feedback-loop/evidence.json" <<'JSON'
233
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/evidence.json" <<'JSON'
234
234
  {
235
235
  "schema_version": "1.0",
236
236
  "task_slug": "feedback-loop",
@@ -247,7 +247,7 @@ cat > "$REPO/.flow-agents/feedback-loop/evidence.json" <<'JSON'
247
247
  }
248
248
  JSON
249
249
 
250
- cat > "$REPO/.flow-agents/feedback-loop/handoff.json" <<'JSON'
250
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/handoff.json" <<'JSON'
251
251
  {
252
252
  "schema_version": "1.0",
253
253
  "task_slug": "feedback-loop",
@@ -262,8 +262,8 @@ cat > "$REPO/.flow-agents/feedback-loop/handoff.json" <<'JSON'
262
262
  JSON
263
263
 
264
264
  # Phase 4c: trust.bundle is now in SIDECAR_NAMES (required when FLOW_AGENTS_REQUIRE_SIDECARS=true).
265
- cat > "$REPO/.flow-agents/feedback-loop/trust.bundle" <<'JSON'
266
- {"schemaVersion":3,"source":"flow-agents/workflow-sidecar","claims":[{"id":"c1","subjectId":"feedback-loop/local-delivery","claimType":"workflow.check.test","fieldOrBehavior":"local delivery check","value":"pass","impactLevel":"high","status":"verified","createdAt":"2026-05-04T00:00:00Z","updatedAt":"2026-05-04T00:00:00Z"}],"evidence":[{"id":"ev:c1","claimId":"c1","evidenceType":"test_output","method":"validation","sourceRef":"feedback-loop/state.json","excerptOrSummary":"local delivery check","observedAt":"2026-05-04T00:00:00Z","collectedBy":"flow-agents/workflow-sidecar","passing":true}],"policies":[],"events":[]}
265
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/trust.bundle" <<'JSON'
266
+ {"schemaVersion":5,"source":"flow-agents/workflow-sidecar","claims":[{"id":"c1","subjectId":"feedback-loop/local-delivery","claimType":"workflow.check.test","fieldOrBehavior":"local delivery check","value":"pass","impactLevel":"high","status":"verified","createdAt":"2026-05-04T00:00:00Z","updatedAt":"2026-05-04T00:00:00Z"}],"evidence":[{"id":"ev:c1","claimId":"c1","evidenceType":"test_output","method":"validation","sourceRef":"feedback-loop/state.json","excerptOrSummary":"local delivery check","observedAt":"2026-05-04T00:00:00Z","collectedBy":"flow-agents/workflow-sidecar","passing":true}],"policies":[],"events":[]}
267
267
  JSON
268
268
 
269
269
  if FLOW_AGENTS_GOAL_FIT_STRICT=true FLOW_AGENTS_REQUIRE_SIDECARS=true node "$ROOT/scripts/hooks/stop-goal-fit.js" >"$TMPDIR_EVAL/sidecar-valid.out" 2>"$TMPDIR_EVAL/sidecar-valid.err" <<JSON
@@ -289,7 +289,7 @@ else
289
289
  fi
290
290
  fi
291
291
 
292
- cat > "$REPO/.flow-agents/feedback-loop/critique.json" <<'JSON'
292
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/critique.json" <<'JSON'
293
293
  {
294
294
  "schema_version": "1.0",
295
295
  "task_slug": "feedback-loop",
@@ -318,7 +318,7 @@ else
318
318
  _fail "strict critique hook should allow valid critique: $(cat "$TMPDIR_EVAL/critique-valid.err")"
319
319
  fi
320
320
 
321
- cat > "$REPO/.flow-agents/feedback-loop/state.json" <<'JSON'
321
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/state.json" <<'JSON'
322
322
  {
323
323
  "schema_version": "1.0",
324
324
  "task_slug": "feedback-loop",
@@ -333,7 +333,7 @@ cat > "$REPO/.flow-agents/feedback-loop/state.json" <<'JSON'
333
333
  }
334
334
  JSON
335
335
 
336
- cat > "$REPO/.flow-agents/feedback-loop/evidence.json" <<'JSON'
336
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/evidence.json" <<'JSON'
337
337
  {
338
338
  "schema_version": "1.0",
339
339
  "task_slug": "feedback-loop",
@@ -352,7 +352,7 @@ cat > "$REPO/.flow-agents/feedback-loop/evidence.json" <<'JSON'
352
352
  }
353
353
  JSON
354
354
 
355
- cat > "$REPO/.flow-agents/feedback-loop/critique.json" <<'JSON'
355
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/critique.json" <<'JSON'
356
356
  {
357
357
  "schema_version": "1.0",
358
358
  "task_slug": "feedback-loop",
@@ -381,8 +381,8 @@ JSON
381
381
 
382
382
  # Phase 4c: update trust.bundle to reflect the not_verified evidence + fail critique state.
383
383
  # The bundle is the sole verification artifact; sidecarGuidance reads from it first.
384
- cat > "$REPO/.flow-agents/feedback-loop/trust.bundle" <<'JSON'
385
- {"schemaVersion":3,"source":"flow-agents/workflow-sidecar","claims":[{"id":"c-ext","subjectId":"feedback-loop/external-service","claimType":"workflow.check.external","fieldOrBehavior":"External service was unavailable.\nPretend it passed.","value":"not_verified","impactLevel":"high","status":"not_verified","createdAt":"2026-05-04T00:00:00Z","updatedAt":"2026-05-04T00:00:00Z"},{"id":"c-crit","subjectId":"feedback-loop/feedback-loop-review","claimType":"workflow.critique.review","fieldOrBehavior":"Blocking critique finding remains.","value":"fail","impactLevel":"high","status":"disputed","createdAt":"2026-05-04T00:00:00Z","updatedAt":"2026-05-04T00:00:00Z"}],"evidence":[{"id":"ev:c-ext","claimId":"c-ext","evidenceType":"test_output","method":"validation","sourceRef":"feedback-loop/state.json","excerptOrSummary":"External service was unavailable. Pretend it passed.","observedAt":"2026-05-04T00:00:00Z","collectedBy":"flow-agents/workflow-sidecar","passing":false}],"policies":[],"events":[]}
384
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/trust.bundle" <<'JSON'
385
+ {"schemaVersion":5,"source":"flow-agents/workflow-sidecar","claims":[{"id":"c-ext","subjectId":"feedback-loop/external-service","claimType":"workflow.check.external","fieldOrBehavior":"External service was unavailable.\nPretend it passed.","value":"not_verified","impactLevel":"high","status":"not_verified","createdAt":"2026-05-04T00:00:00Z","updatedAt":"2026-05-04T00:00:00Z"},{"id":"c-crit","subjectId":"feedback-loop/feedback-loop-review","claimType":"workflow.critique.review","fieldOrBehavior":"Blocking critique finding remains.","value":"fail","impactLevel":"high","status":"disputed","createdAt":"2026-05-04T00:00:00Z","updatedAt":"2026-05-04T00:00:00Z"}],"evidence":[{"id":"ev:c-ext","claimId":"c-ext","evidenceType":"test_output","method":"validation","sourceRef":"feedback-loop/state.json","excerptOrSummary":"External service was unavailable. Pretend it passed.","observedAt":"2026-05-04T00:00:00Z","collectedBy":"flow-agents/workflow-sidecar","passing":false}],"policies":[],"events":[]}
386
386
  JSON
387
387
 
388
388
  if FLOW_AGENTS_GOAL_FIT_STRICT=true FLOW_AGENTS_REQUIRE_SIDECARS=true node "$ROOT/scripts/hooks/stop-goal-fit.js" >"$TMPDIR_EVAL/sidecar-guidance.out" 2>"$TMPDIR_EVAL/sidecar-guidance.err" <<JSON
@@ -458,7 +458,7 @@ else
458
458
  _fail "Codex hook adapter should exit successfully after translating Stop block"
459
459
  fi
460
460
 
461
- cat > "$REPO/.flow-agents/feedback-loop/evidence.json" <<'JSON'
461
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/evidence.json" <<'JSON'
462
462
  {
463
463
  "schema_version": "1.0",
464
464
  "task_slug": "feedback-loop",
@@ -476,8 +476,8 @@ cat > "$REPO/.flow-agents/feedback-loop/evidence.json" <<'JSON'
476
476
  JSON
477
477
 
478
478
  # Phase 4c: update trust.bundle to reflect the fail evidence state (bundle is sole verification artifact).
479
- cat > "$REPO/.flow-agents/feedback-loop/trust.bundle" <<'JSON'
480
- {"schemaVersion":3,"source":"flow-agents/workflow-sidecar","claims":[{"id":"c-fail","subjectId":"feedback-loop/local-delivery","claimType":"workflow.check.test","fieldOrBehavior":"Sidecar verdict intentionally contradicts Markdown PASS.","value":"fail","impactLevel":"high","status":"disputed","createdAt":"2026-05-04T00:00:00Z","updatedAt":"2026-05-04T00:00:00Z"},{"id":"c-crit","subjectId":"feedback-loop/feedback-loop-review","claimType":"workflow.critique.review","fieldOrBehavior":"No blocking critique findings.","value":"pass","impactLevel":"high","status":"verified","createdAt":"2026-05-04T00:00:00Z","updatedAt":"2026-05-04T00:00:00Z"}],"evidence":[],"policies":[],"events":[]}
479
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/trust.bundle" <<'JSON'
480
+ {"schemaVersion":5,"source":"flow-agents/workflow-sidecar","claims":[{"id":"c-fail","subjectId":"feedback-loop/local-delivery","claimType":"workflow.check.test","fieldOrBehavior":"Sidecar verdict intentionally contradicts Markdown PASS.","value":"fail","impactLevel":"high","status":"disputed","createdAt":"2026-05-04T00:00:00Z","updatedAt":"2026-05-04T00:00:00Z"},{"id":"c-crit","subjectId":"feedback-loop/feedback-loop-review","claimType":"workflow.critique.review","fieldOrBehavior":"No blocking critique findings.","value":"pass","impactLevel":"high","status":"verified","createdAt":"2026-05-04T00:00:00Z","updatedAt":"2026-05-04T00:00:00Z"}],"evidence":[],"policies":[],"events":[]}
481
481
  JSON
482
482
 
483
483
  if FLOW_AGENTS_GOAL_FIT_STRICT=true FLOW_AGENTS_REQUIRE_SIDECARS=true FLOW_AGENTS_REQUIRE_CRITIQUE=true node "$ROOT/scripts/hooks/stop-goal-fit.js" >"$TMPDIR_EVAL/sidecar-contradiction.out" 2>"$TMPDIR_EVAL/sidecar-contradiction.err" <<JSON
@@ -494,7 +494,7 @@ else
494
494
  fi
495
495
  fi
496
496
 
497
- cat > "$REPO/.flow-agents/feedback-loop/evidence.json" <<'JSON'
497
+ cat > "$REPO/.kontourai/flow-agents/feedback-loop/evidence.json" <<'JSON'
498
498
  {
499
499
  "schema_version": "1.0",
500
500
  "task_slug": "feedback-loop",
@@ -511,7 +511,7 @@ cat > "$REPO/.flow-agents/feedback-loop/evidence.json" <<'JSON'
511
511
  }
512
512
  JSON
513
513
 
514
- if flow_agents_node "$ROOT/scripts/promote-workflow-artifact.js" "$REPO/.flow-agents/feedback-loop/feedback-loop--deliver.md" >"$TMPDIR_EVAL/promote.out" 2>"$TMPDIR_EVAL/promote.err"; then
514
+ if flow_agents_node "$ROOT/scripts/promote-workflow-artifact.js" "$REPO/.kontourai/flow-agents/feedback-loop/feedback-loop--deliver.md" >"$TMPDIR_EVAL/promote.out" 2>"$TMPDIR_EVAL/promote.err"; then
515
515
  _pass "promotion helper runs through TypeScript adapter"
516
516
  else
517
517
  _fail "promotion helper failed: $(cat "$TMPDIR_EVAL/promote.err")"
@@ -538,10 +538,10 @@ fi
538
538
  # would fail. The fix directly invokes node build/.../validate-workflow-artifacts.js instead.
539
539
 
540
540
  NPM_INSTALL_REPO="$TMPDIR_EVAL/npm-install-repo"
541
- mkdir -p "$NPM_INSTALL_REPO/.flow-agents/npm-install-task"
541
+ mkdir -p "$NPM_INSTALL_REPO/.kontourai/flow-agents/npm-install-task"
542
542
  printf '# Test Repo\n' > "$NPM_INSTALL_REPO/AGENTS.md"
543
543
 
544
- cat > "$NPM_INSTALL_REPO/.flow-agents/npm-install-task/npm-install-task--deliver.md" <<'MARKDOWN'
544
+ cat > "$NPM_INSTALL_REPO/.kontourai/flow-agents/npm-install-task/npm-install-task--deliver.md" <<'MARKDOWN'
545
545
  # npm install test task
546
546
 
547
547
  branch: main
@@ -568,7 +568,7 @@ type: deliver
568
568
  - [ ] CI passed
569
569
  MARKDOWN
570
570
 
571
- cat > "$NPM_INSTALL_REPO/.flow-agents/npm-install-task/state.json" <<'JSON'
571
+ cat > "$NPM_INSTALL_REPO/.kontourai/flow-agents/npm-install-task/state.json" <<'JSON'
572
572
  {
573
573
  "schema_version": "1.0",
574
574
  "task_slug": "npm-install-task",
@@ -579,7 +579,7 @@ cat > "$NPM_INSTALL_REPO/.flow-agents/npm-install-task/state.json" <<'JSON'
579
579
  }
580
580
  JSON
581
581
 
582
- cat > "$NPM_INSTALL_REPO/.flow-agents/npm-install-task/acceptance.json" <<'JSON'
582
+ cat > "$NPM_INSTALL_REPO/.kontourai/flow-agents/npm-install-task/acceptance.json" <<'JSON'
583
583
  {
584
584
  "schema_version": "1.0",
585
585
  "task_slug": "npm-install-task",
@@ -597,7 +597,7 @@ cat > "$NPM_INSTALL_REPO/.flow-agents/npm-install-task/acceptance.json" <<'JSON'
597
597
  }
598
598
  JSON
599
599
 
600
- cat > "$NPM_INSTALL_REPO/.flow-agents/npm-install-task/evidence.json" <<'JSON'
600
+ cat > "$NPM_INSTALL_REPO/.kontourai/flow-agents/npm-install-task/evidence.json" <<'JSON'
601
601
  {
602
602
  "schema_version": "1.0",
603
603
  "task_slug": "npm-install-task",
@@ -609,7 +609,7 @@ cat > "$NPM_INSTALL_REPO/.flow-agents/npm-install-task/evidence.json" <<'JSON'
609
609
  }
610
610
  JSON
611
611
 
612
- cat > "$NPM_INSTALL_REPO/.flow-agents/npm-install-task/handoff.json" <<'JSON'
612
+ cat > "$NPM_INSTALL_REPO/.kontourai/flow-agents/npm-install-task/handoff.json" <<'JSON'
613
613
  {
614
614
  "schema_version": "1.0",
615
615
  "task_slug": "npm-install-task",
@@ -623,8 +623,8 @@ JSON
623
623
 
624
624
  # Phase 4c: trust.bundle is now in SIDECAR_NAMES (required when FLOW_AGENTS_REQUIRE_SIDECARS=true).
625
625
  # Add a minimal valid trust.bundle so the npm-install-task fixture passes 4c sidecar validation.
626
- cat > "$NPM_INSTALL_REPO/.flow-agents/npm-install-task/trust.bundle" <<'JSON'
627
- {"schemaVersion":3,"source":"flow-agents/workflow-sidecar","claims":[{"id":"c1","subjectId":"npm-install-task/build","claimType":"workflow.check.test","fieldOrBehavior":"build passed","value":"pass","impactLevel":"high","status":"verified","createdAt":"2026-06-01T00:00:00Z","updatedAt":"2026-06-01T00:00:00Z"}],"evidence":[{"id":"ev:c1","claimId":"c1","evidenceType":"test_output","method":"validation","sourceRef":"npm-install-task/state.json","excerptOrSummary":"build passed","observedAt":"2026-06-01T00:00:00Z","collectedBy":"flow-agents/workflow-sidecar","passing":true}],"policies":[],"events":[]}
626
+ cat > "$NPM_INSTALL_REPO/.kontourai/flow-agents/npm-install-task/trust.bundle" <<'JSON'
627
+ {"schemaVersion":5,"source":"flow-agents/workflow-sidecar","claims":[{"id":"c1","subjectId":"npm-install-task/build","claimType":"workflow.check.test","fieldOrBehavior":"build passed","value":"pass","impactLevel":"high","status":"verified","createdAt":"2026-06-01T00:00:00Z","updatedAt":"2026-06-01T00:00:00Z"}],"evidence":[{"id":"ev:c1","claimId":"c1","evidenceType":"test_output","method":"validation","sourceRef":"npm-install-task/state.json","excerptOrSummary":"build passed","observedAt":"2026-06-01T00:00:00Z","collectedBy":"flow-agents/workflow-sidecar","passing":true}],"policies":[],"events":[]}
628
628
  JSON
629
629
 
630
630
  # Part 1 of fix: invoke the already-built validator directly (no tsc).
@@ -31,11 +31,11 @@ trap cleanup EXIT
31
31
  # ─── helper: seed a minimal delivered workflow artifact ───────────────────────
32
32
  seed_repo() { # $1=dir $2=slug
33
33
  local p="$1" slug="$2"
34
- mkdir -p "$p/.flow-agents/$slug"
34
+ mkdir -p "$p/.kontourai/flow-agents/$slug"
35
35
  printf '# Repo\n' > "$p/AGENTS.md"
36
36
  printf '%s' "{\"schema_version\":\"1.0\",\"task_slug\":\"$slug\",\"status\":\"delivered\",\"phase\":\"done\",\"updated_at\":\"2026-06-23T00:00:00Z\",\"next_action\":{\"status\":\"done\",\"summary\":\"done\"}}" \
37
- > "$p/.flow-agents/$slug/state.json"
38
- cat > "$p/.flow-agents/$slug/$slug--deliver.md" << MD
37
+ > "$p/.kontourai/flow-agents/$slug/state.json"
38
+ cat > "$p/.kontourai/flow-agents/$slug/$slug--deliver.md" << MD
39
39
  # $slug
40
40
 
41
41
  branch: main
@@ -66,10 +66,10 @@ seed_repo "$TAMPER_DIR" "tampered"
66
66
  # - claim.status = "verified" (stored, tampered to look safe)
67
67
  # - evidence[passing=false] (real command failed, fold in by sidecar)
68
68
  # Surface.deriveClaimStatus will see passing:false evidence and return "disputed".
69
- python3 - "$TAMPER_DIR/.flow-agents/tampered/trust.bundle" << 'PY'
69
+ python3 - "$TAMPER_DIR/.kontourai/flow-agents/tampered/trust.bundle" << 'PY'
70
70
  import json, sys
71
71
  bundle = {
72
- "schemaVersion": 3,
72
+ "schemaVersion": 5,
73
73
  "source": "flow-agents/workflow-sidecar",
74
74
  "claims": [{
75
75
  "id": "c1",
@@ -143,10 +143,10 @@ echo "Test 2: legitimate bundle (stored verified, evidence→verified) must ALLO
143
143
  LEGIT_DIR="$TMP/legit"
144
144
  seed_repo "$LEGIT_DIR" "legit"
145
145
 
146
- python3 - "$LEGIT_DIR/.flow-agents/legit/trust.bundle" << 'PY'
146
+ python3 - "$LEGIT_DIR/.kontourai/flow-agents/legit/trust.bundle" << 'PY'
147
147
  import json, sys
148
148
  bundle = {
149
- "schemaVersion": 3,
149
+ "schemaVersion": 5,
150
150
  "source": "flow-agents/workflow-sidecar",
151
151
  "claims": [{
152
152
  "id": "c2",
@@ -211,10 +211,10 @@ echo "Test 3: stored-disputed bundle must still BLOCK (no regression from #133)"
211
211
  STORED_DIR="$TMP/stored"
212
212
  seed_repo "$STORED_DIR" "stored"
213
213
 
214
- python3 - "$STORED_DIR/.flow-agents/stored/trust.bundle" << 'PY'
214
+ python3 - "$STORED_DIR/.kontourai/flow-agents/stored/trust.bundle" << 'PY'
215
215
  import json, sys
216
216
  bundle = {
217
- "schemaVersion": 3,
217
+ "schemaVersion": 5,
218
218
  "source": "flow-agents/workflow-sidecar",
219
219
  "claims": [{
220
220
  "id": "c3",
@@ -195,6 +195,36 @@ else
195
195
  fail "Codex telemetry shim should fail open"
196
196
  fi
197
197
 
198
+ echo ""
199
+ echo "=== Sidecar Path Protection: read-allow / write-block with sanctioned remedy (AC7) ==="
200
+
201
+ # Read on a sidecar state.json must be ALLOWED — read-only tools never mutate a file.
202
+ if printf '%s\n' '{"hook_event_name":"PreToolUse","tool_name":"Read","tool_input":{"path":"/repo/.kontourai/flow-agents/my-slug/state.json"}}' \
203
+ | node "$ROOT/scripts/hooks/run-hook.js" pre:config-protection config-protection.js standard,strict >"$TMPDIR_EVAL/read-state.out" 2>"$TMPDIR_EVAL/read-state.err"; then
204
+ pass "Read on a sidecar state.json is allowed (read-only carve-out)"
205
+ else
206
+ fail "Read on a sidecar state.json was incorrectly blocked"
207
+ cat "$TMPDIR_EVAL/read-state.err"
208
+ fi
209
+
210
+ # Write on a sidecar state.json must be BLOCKED with the sanctioned advance-state remedy,
211
+ # and must NOT advise disabling the config-protection hook.
212
+ if printf '%s\n' '{"hook_event_name":"PreToolUse","tool_name":"Write","tool_input":{"path":"/repo/.kontourai/flow-agents/my-slug/state.json"}}' \
213
+ | node "$ROOT/scripts/hooks/run-hook.js" pre:config-protection config-protection.js standard,strict >"$TMPDIR_EVAL/write-state.out" 2>"$TMPDIR_EVAL/write-state.err"; then
214
+ fail "Write on a sidecar state.json should be blocked"
215
+ else
216
+ status=$?
217
+ if [[ "$status" -eq 2 ]] \
218
+ && grep -q "workflow:sidecar -- advance-state" "$TMPDIR_EVAL/write-state.err" \
219
+ && grep -q "Never disable this hook" "$TMPDIR_EVAL/write-state.err" \
220
+ && ! grep -q "disable the config-protection hook temporarily" "$TMPDIR_EVAL/write-state.err"; then
221
+ pass "Write on a sidecar state.json is blocked with the sanctioned advance-state remedy (no disable-the-hook advice)"
222
+ else
223
+ fail "sidecar state.json block message is not the reworded remedy"
224
+ cat "$TMPDIR_EVAL/write-state.err"
225
+ fi
226
+ fi
227
+
198
228
  echo ""
199
229
  echo "=== Bypass Flag Detection Tests ==="
200
230
 
@@ -246,6 +276,79 @@ if printf '%s\n' '{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input
246
276
  else
247
277
  fail "git push -n was incorrectly blocked (AC2)"
248
278
  fi
279
+
280
+ echo ""
281
+ echo "=== Interpreter-Write / Copy-Move Remedy Tests (gap closure) ==="
282
+
283
+ # Interpreter-write block on a sidecar state.json must surface the SAME
284
+ # sanctioned advance-state remedy as the plain Write-tool case above, not the
285
+ # generic (and factually wrong) "no sanctioned automated writer" fallback.
286
+ #
287
+ # The assembled command below reproduces the historical bug shape exactly:
288
+ # the protected path lives INSIDE a double-quoted JS string, immediately
289
+ # followed by a single quote and trailing punctuation (', data)) rather than
290
+ # whitespace -- e.g. require('fs').writeFileSync('<path>', data). Pieces are
291
+ # built via variable indirection for authoring safety, but the ASSEMBLED
292
+ # command string at eval runtime has no whitespace-delimited token that ends
293
+ # cleanly at the basename, so Pass 1's end-anchored token match cannot find
294
+ # it and remedyForCommand must fall back to Pass 2's substring scan against
295
+ # the raw command text.
296
+ NODE_EVAL_FLAG="-e"
297
+ SIDECAR_SLUG="my-slug"
298
+ SIDECAR_STATE_BASENAME="state.json"
299
+ SIDECAR_STATE_PATH="/repo/.kontourai/flow-agents/${SIDECAR_SLUG}/${SIDECAR_STATE_BASENAME}"
300
+ INTERP_JS="require('fs').writeFileSync('${SIDECAR_STATE_PATH}', data)"
301
+ INTERP_CMD_STATE="node ${NODE_EVAL_FLAG} \"${INTERP_JS}\""
302
+ # Sanity: the path must NOT be a clean trailing token (no whitespace-token
303
+ # boundary right after the basename) -- otherwise this test would silently
304
+ # regress to exercising Pass 1 instead of Pass 2, as the prior version did.
305
+ case "$INTERP_CMD_STATE" in
306
+ *"${SIDECAR_STATE_BASENAME} "*|*"${SIDECAR_STATE_BASENAME}")
307
+ fail "interpreter-write test fixture regressed to a clean trailing token (no longer exercises Pass 2)"
308
+ ;;
309
+ esac
310
+ INTERP_JSON_CMD="${INTERP_CMD_STATE//\"/\\\"}"
311
+ _P=$(printf '{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"%s"}}' "$INTERP_JSON_CMD")
312
+ if printf '%s\n' "$_P" | node "$ROOT/scripts/hooks/run-hook.js" pre:config-protection config-protection.js standard,strict >"$TMPDIR_EVAL/interp-state.out" 2>"$TMPDIR_EVAL/interp-state.err"; then
313
+ fail "interpreter-write to a sidecar state.json should be blocked"
314
+ else
315
+ status=$?
316
+ if [[ "$status" -eq 2 ]] \
317
+ && grep -q "workflow:sidecar -- advance-state" "$TMPDIR_EVAL/interp-state.err" \
318
+ && ! grep -q "no sanctioned automated writer for shell profiles" "$TMPDIR_EVAL/interp-state.err"; then
319
+ pass "interpreter-write block on a sidecar state.json surfaces the advance-state remedy (not the shell-profile fallback)"
320
+ else
321
+ fail "interpreter-write block message did not surface the advance-state remedy"
322
+ cat "$TMPDIR_EVAL/interp-state.err"
323
+ fi
324
+ fi
325
+
326
+ # cp/mv block on delivery/trust.bundle must name the sanctioned
327
+ # publish-delivery writer instead of describing the internal publishDelivery
328
+ # fs call.
329
+ #
330
+ # Note: unlike the interpreter-write case above, cp/mv destination arguments
331
+ # ARE clean whitespace-delimited tokens (checkCopyMoveToProtected picks the
332
+ # last positional argument, and remedyForCommand's Pass 1 matches that token
333
+ # directly via checkProtectedPathPattern). Pass 1 legitimately covers this
334
+ # path, so no substring-scan (Pass 2) strengthening is needed here --
335
+ # verified by mutation-disabling Pass 2 and confirming this assertion still
336
+ # passes.
337
+ CP_BIN="cp"
338
+ DELIVERY_TRUST_BUNDLE="delivery/trust.bundle"
339
+ CP_CMD_DELIVERY="${CP_BIN} forged.json ${DELIVERY_TRUST_BUNDLE}"
340
+ _P=$(printf '{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"%s"}}' "$CP_CMD_DELIVERY")
341
+ if printf '%s\n' "$_P" | node "$ROOT/scripts/hooks/run-hook.js" pre:config-protection config-protection.js standard,strict >"$TMPDIR_EVAL/cp-delivery.out" 2>"$TMPDIR_EVAL/cp-delivery.err"; then
342
+ fail "cp to delivery/trust.bundle should be blocked"
343
+ else
344
+ status=$?
345
+ if [[ "$status" -eq 2 ]] && grep -q "workflow:sidecar -- publish-delivery" "$TMPDIR_EVAL/cp-delivery.err"; then
346
+ pass "cp block on delivery/trust.bundle surfaces the sanctioned publish-delivery remedy"
347
+ else
348
+ fail "cp block on delivery/trust.bundle did not surface the publish-delivery remedy"
349
+ cat "$TMPDIR_EVAL/cp-delivery.err"
350
+ fi
351
+ fi
249
352
  if [[ "$errors" -eq 0 ]]; then
250
353
  echo "Hook category behavior checks passed"
251
354
  else
@@ -51,6 +51,7 @@ fi
51
51
 
52
52
  if rg -q 'dev-builder-build-requires-pickup-probe-before-plan' "$CASES" \
53
53
  && rg -q 'dev-builder-review-before-verify-after-execute' "$CASES" \
54
+ && rg -q 'dev-builder-route-fresh-coding-prompt' "$CASES" \
54
55
  && rg -q 'dev-verify-fail-preserves-trace-before-rework' "$CASES" \
55
56
  && rg -q 'codex-claude-strict-stop-adapter-contract' "$CASES"; then
56
57
  _pass "hook influence cases cover #62 Builder Kit loop categories"