@kontourai/flow-agents 3.3.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/.github/workflows/add-to-project.yml +15 -0
  2. package/.github/workflows/ci.yml +161 -0
  3. package/CHANGELOG.md +48 -0
  4. package/CONTEXT.md +5 -1
  5. package/README.md +19 -8
  6. package/build/src/builder-flow-run-adapter.d.ts +80 -0
  7. package/build/src/builder-flow-run-adapter.js +241 -0
  8. package/build/src/builder-flow-runtime.d.ts +16 -0
  9. package/build/src/builder-flow-runtime.js +290 -0
  10. package/build/src/cli/builder-run.d.ts +1 -0
  11. package/build/src/cli/builder-run.js +27 -0
  12. package/build/src/cli/effective-backlog-settings.js +70 -2
  13. package/build/src/cli/init.d.ts +34 -0
  14. package/build/src/cli/init.js +341 -61
  15. package/build/src/cli/kit.js +55 -12
  16. package/build/src/cli/pull-work-provider.js +346 -5
  17. package/build/src/cli/skill-drift-check.d.ts +1 -0
  18. package/build/src/cli/skill-drift-check.js +165 -0
  19. package/build/src/cli/telemetry-doctor.d.ts +37 -0
  20. package/build/src/cli/telemetry-doctor.js +53 -6
  21. package/build/src/cli/validate-hook-influence.js +37 -7
  22. package/build/src/cli/workflow-sidecar.d.ts +93 -8
  23. package/build/src/cli/workflow-sidecar.js +1175 -158
  24. package/build/src/cli.js +5 -0
  25. package/build/src/flow-kit/validate.d.ts +54 -34
  26. package/build/src/flow-kit/validate.js +237 -26
  27. package/build/src/index.d.ts +2 -0
  28. package/build/src/index.js +1 -0
  29. package/build/src/lib/console-connect-options.d.ts +97 -0
  30. package/build/src/lib/console-connect-options.js +199 -0
  31. package/build/src/lib/console-telemetry-validate.d.ts +49 -0
  32. package/build/src/lib/console-telemetry-validate.js +91 -0
  33. package/build/src/lib/flow-resolver.d.ts +56 -3
  34. package/build/src/lib/flow-resolver.js +151 -11
  35. package/build/src/lib/fs.d.ts +17 -0
  36. package/build/src/lib/fs.js +172 -0
  37. package/build/src/lib/local-artifact-root.d.ts +44 -1
  38. package/build/src/lib/local-artifact-root.js +131 -3
  39. package/build/src/runtime-adapters.d.ts +39 -3
  40. package/build/src/runtime-adapters.js +77 -31
  41. package/build/src/tools/build-universal-bundles.js +40 -2
  42. package/build/src/tools/codex-agent-routing.d.ts +2 -0
  43. package/build/src/tools/codex-agent-routing.js +49 -0
  44. package/build/src/tools/generate-context-map.js +1 -0
  45. package/build/src/tools/validate-source-tree.js +27 -1
  46. package/context/scripts/hooks/lib/kit-catalog.js +235 -0
  47. package/context/scripts/hooks/lib/runnable-command.js +177 -0
  48. package/context/scripts/hooks/stop-goal-fit.js +278 -48
  49. package/context/scripts/hooks/workflow-steering.js +121 -21
  50. package/context/scripts/package.json +3 -0
  51. package/context/scripts/telemetry/install-console-config.sh +25 -4
  52. package/context/scripts/telemetry/lib/config.sh +102 -12
  53. package/context/scripts/telemetry/lib/pricing.sh +50 -0
  54. package/context/scripts/telemetry/lib/session.sh +3 -0
  55. package/context/scripts/telemetry/lib/transport.sh +87 -0
  56. package/context/scripts/telemetry/lib/usage.sh +205 -4
  57. package/context/scripts/telemetry/telemetry.conf +6 -0
  58. package/context/scripts/telemetry/telemetry.sh +48 -0
  59. package/context/settings/workspace-backlog-provider-settings.example.json +48 -0
  60. package/docs/agent-usage-feedback-loop.md +35 -0
  61. package/docs/architecture-engine-and-kits.md +110 -0
  62. package/docs/context-map.md +2 -0
  63. package/docs/decisions/embeddable-engine.md +152 -0
  64. package/docs/decisions/index.md +3 -1
  65. package/docs/decisions/trust-ledger-retention.md +88 -0
  66. package/docs/decisions/workflow-enforcement.md +31 -9
  67. package/docs/fixture-ownership.md +3 -0
  68. package/docs/implementing-trust-reconciliation.md +129 -0
  69. package/docs/index.md +19 -9
  70. package/docs/integrations/flow-agents-console.md +167 -0
  71. package/docs/kit-authoring-guide.md +52 -21
  72. package/docs/spec/builder-flow-runtime.md +80 -0
  73. package/docs/spec/runtime-hook-surface.md +45 -1
  74. package/docs/specs/economics-record-contract.md +270 -0
  75. package/docs/specs/harness-capability-matrix.md +74 -0
  76. package/docs/specs/learning-review-proposals-contract.md +340 -0
  77. package/docs/specs/routing-efficiency-review.md +59 -0
  78. package/docs/verifiable-trust.md +74 -25
  79. package/docs/workflow-usage-guide.md +10 -0
  80. package/evals/acceptance/prove-capture-teeth.sh +132 -0
  81. package/evals/ci/antigaming-suite.sh +1 -0
  82. package/evals/ci/run-baseline.sh +72 -4
  83. package/evals/fixtures/economics/acceptance.json +12 -0
  84. package/evals/fixtures/economics/agents/tool-worker-1/events.jsonl +2 -0
  85. package/evals/fixtures/economics/agents/tool-worker-2/events.jsonl +2 -0
  86. package/evals/fixtures/economics/agents/tool-worker-3/events.jsonl +2 -0
  87. package/evals/fixtures/economics/agents/tool-worker-4/events.jsonl +1 -0
  88. package/evals/fixtures/economics/agents/tool-worker-5/events.jsonl +2 -0
  89. package/evals/fixtures/economics/critique.json +22 -0
  90. package/evals/fixtures/economics/expected-record.json +71 -0
  91. package/evals/fixtures/economics/session-usage-event.json +1 -0
  92. package/evals/fixtures/economics/state.json +11 -0
  93. package/evals/fixtures/economics/transcript.jsonl +3 -0
  94. package/evals/fixtures/hook-influence/cases.json +7 -7
  95. package/evals/fixtures/learning-review-proposals/balanced/economics.jsonl +6 -0
  96. package/evals/fixtures/learning-review-proposals/effect-follow-up/economics.jsonl +5 -0
  97. package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-1/trust.bundle +21 -0
  98. package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-2/trust.bundle +21 -0
  99. package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-3/trust.bundle +21 -0
  100. package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-4/trust.bundle +21 -0
  101. package/evals/fixtures/learning-review-proposals/effect-follow-up/sessions/task-lr-ef-5/trust.bundle +21 -0
  102. package/evals/fixtures/learning-review-proposals/pattern-present/economics.jsonl +6 -0
  103. package/evals/fixtures/learning-review-proposals/pattern-present/expected-aggregates.json +30 -0
  104. package/evals/fixtures/learning-review-proposals/pattern-present/expected-aggregates.md +66 -0
  105. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-1/gate-review.inquiries.json +26 -0
  106. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-1/trust.bundle +21 -0
  107. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-2/gate-review.inquiries.json +26 -0
  108. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-2/trust.bundle +21 -0
  109. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-3/gate-review.inquiries.json +26 -0
  110. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-3/trust.bundle +21 -0
  111. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-4/gate-review.inquiries.json +26 -0
  112. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-4/trust.bundle +21 -0
  113. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-5/trust.bundle +21 -0
  114. package/evals/fixtures/learning-review-proposals/pattern-present/sessions/task-lr-pp-6/trust.bundle +21 -0
  115. package/evals/fixtures/learning-review-proposals/repeat-window/economics.jsonl +6 -0
  116. package/evals/fixtures/learning-review-proposals/under-threshold/economics.jsonl +3 -0
  117. package/evals/fixtures/telemetry/usage-transcript-sample.jsonl +4 -0
  118. package/evals/fixtures/trust-reconcile-exploits/mcp-degrade.json +42 -0
  119. package/evals/integration/test_builder_entry_enforcement.sh +241 -0
  120. package/evals/integration/test_builder_step_producers.sh +18 -10
  121. package/evals/integration/test_bundle_install.sh +172 -0
  122. package/evals/integration/test_console_tenant_isolation.sh +167 -0
  123. package/evals/integration/test_critique_supersession_roundtrip.sh +4 -1
  124. package/evals/integration/test_dual_emit_flow_step.sh +10 -4
  125. package/evals/integration/test_economics_record.sh +674 -0
  126. package/evals/integration/test_effective_backlog_settings.sh +1 -1
  127. package/evals/integration/test_evidence_capture_hook.sh +17 -2
  128. package/evals/integration/test_exemption_usage_review.sh +198 -0
  129. package/evals/integration/test_fixture_retirement_audit.sh +2 -2
  130. package/evals/integration/test_flow_kit_install_git.sh +83 -0
  131. package/evals/integration/test_flowdef_session_activation.sh +0 -1
  132. package/evals/integration/test_flowdef_session_history_preservation.sh +13 -3
  133. package/evals/integration/test_gate_lockdown.sh +7 -0
  134. package/evals/integration/test_gate_review_inquiry_records.sh +9 -1
  135. package/evals/integration/test_goal_fit_hook.sh +2031 -0
  136. package/evals/integration/test_hook_category_behaviors.sh +8 -1
  137. package/evals/integration/test_hook_influence_cases.sh +25 -1
  138. package/evals/integration/test_install_merge.sh +227 -2
  139. package/evals/integration/test_kit_conformance_levels.sh +6 -6
  140. package/evals/integration/test_learning_review_proposals.sh +329 -0
  141. package/evals/integration/test_liveness_conflict_injection.sh +26 -22
  142. package/evals/integration/test_liveness_console_relay.sh +166 -0
  143. package/evals/integration/test_liveness_heartbeat.sh +17 -17
  144. package/evals/integration/test_liveness_worktree_root.sh +575 -0
  145. package/evals/integration/test_phase_map_and_gate_claim.sh +6 -1
  146. package/evals/integration/test_publish_delivery.sh +331 -1
  147. package/evals/integration/test_pull_work_board.sh +200 -0
  148. package/evals/integration/test_pull_work_provider.sh +1 -1
  149. package/evals/integration/test_record_check.sh +378 -0
  150. package/evals/integration/test_routing_efficiency.sh +71 -0
  151. package/evals/integration/test_runtime_adapter_activation.sh +28 -0
  152. package/evals/integration/test_session_resume_roundtrip.sh +16 -19
  153. package/evals/integration/test_skill_drift_check.sh +870 -0
  154. package/evals/integration/test_telemetry.sh +445 -0
  155. package/evals/integration/test_telemetry_doctor.sh +66 -0
  156. package/evals/integration/test_telemetry_usage_pipeline.sh +228 -0
  157. package/evals/integration/test_trust_reconcile_negatives.sh +30 -13
  158. package/evals/integration/test_trust_reconcile_trailer_diagnostic.sh +247 -0
  159. package/evals/integration/test_usage_cost.sh +61 -0
  160. package/evals/integration/test_workflow_sidecar_writer.sh +1395 -0
  161. package/evals/integration/test_workflow_steering_hook.sh +157 -16
  162. package/evals/integration/test_workspace_settings.sh +176 -0
  163. package/evals/lib/env.sh +26 -0
  164. package/evals/lib/node.sh +8 -0
  165. package/evals/run.sh +29 -0
  166. package/evals/static/test_ci_integration_coverage.sh +115 -0
  167. package/evals/static/test_declared_scope_forms_documented.sh +114 -0
  168. package/evals/static/test_universal_bundles.sh +34 -0
  169. package/evals/static/test_validate_source_kit_asset_scope.sh +259 -0
  170. package/evals/static/test_workflow_skills.sh +1 -1
  171. package/kits/builder/flows/build.flow.json +9 -18
  172. package/kits/builder/flows/publish-learn.flow.json +5 -1
  173. package/kits/builder/kit.json +120 -0
  174. package/kits/builder/skills/deliver/SKILL.md +42 -0
  175. package/kits/builder/skills/evidence-gate/SKILL.md +12 -0
  176. package/kits/builder/skills/execute-plan/SKILL.md +9 -0
  177. package/kits/builder/skills/learning-review/SKILL.md +51 -0
  178. package/kits/builder/skills/plan-work/SKILL.md +17 -20
  179. package/kits/builder/skills/pull-work/SKILL.md +21 -0
  180. package/kits/builder/skills/release-readiness/SKILL.md +12 -0
  181. package/kits/knowledge/kit.json +9 -0
  182. package/kits/veritas-governance/docs/README.md +35 -7
  183. package/kits/veritas-governance/fixtures/exemption-review/mixed-fresh-stale.DECLARED.json +14 -0
  184. package/kits/veritas-governance/kit.json +14 -0
  185. package/kits/veritas-governance/skills/exemption-usage-review/SKILL.md +128 -0
  186. package/kits/veritas-governance/skills/exemption-usage-review/review-exemptions.mjs +231 -0
  187. package/package.json +2 -2
  188. package/packaging/manifest.json +29 -0
  189. package/schemas/backlog-provider-settings.schema.json +13 -0
  190. package/schemas/workflow-state.schema.json +44 -0
  191. package/scripts/README.md +4 -0
  192. package/scripts/check-content-boundary.cjs +8 -1
  193. package/scripts/ci/trust-reconcile.js +136 -0
  194. package/scripts/hooks/codex-hook-adapter.js +77 -2
  195. package/scripts/hooks/evidence-capture.js +38 -5
  196. package/scripts/hooks/lib/codex-exit-code.js +316 -0
  197. package/scripts/hooks/lib/kit-catalog.js +235 -0
  198. package/scripts/hooks/lib/liveness-write.js +28 -1
  199. package/scripts/hooks/lib/local-artifact-paths.js +97 -1
  200. package/scripts/hooks/lib/runnable-command.js +177 -0
  201. package/scripts/hooks/lib/skill-drift.js +350 -0
  202. package/scripts/hooks/stop-goal-fit.js +278 -48
  203. package/scripts/hooks/workflow-steering.js +121 -21
  204. package/scripts/install-codex-home.sh +97 -47
  205. package/scripts/install-merge.js +72 -14
  206. package/scripts/install-owned-files.js +178 -0
  207. package/scripts/liveness/relay.sh +84 -0
  208. package/scripts/telemetry/economics-record.schema.json +145 -0
  209. package/scripts/telemetry/economics-record.sh +331 -0
  210. package/scripts/telemetry/install-console-config.sh +25 -4
  211. package/scripts/telemetry/learning-review-decide.sh +124 -0
  212. package/scripts/telemetry/learning-review-proposals.schema.json +161 -0
  213. package/scripts/telemetry/learning-review-proposals.sh +484 -0
  214. package/scripts/telemetry/lib/config.sh +102 -12
  215. package/scripts/telemetry/lib/pricing.sh +14 -6
  216. package/scripts/telemetry/lib/session.sh +3 -0
  217. package/scripts/telemetry/lib/transport.sh +133 -15
  218. package/scripts/telemetry/lib/usage.sh +121 -28
  219. package/scripts/telemetry/routing-efficiency.sh +0 -0
  220. package/scripts/telemetry/telemetry.conf +6 -0
  221. package/scripts/telemetry/telemetry.sh +48 -0
  222. package/src/builder-flow-run-adapter.ts +357 -0
  223. package/src/builder-flow-runtime.ts +348 -0
  224. package/src/cli/builder-flow-run-adapter.test.mjs +495 -0
  225. package/src/cli/builder-flow-runtime.test.mjs +213 -0
  226. package/src/cli/builder-run.ts +28 -0
  227. package/src/cli/codex-agent-routing.test.mjs +44 -0
  228. package/src/cli/codex-exit-code.test.mjs +207 -0
  229. package/src/cli/console-connect-options.test.mjs +329 -0
  230. package/src/cli/console-telemetry-validate.test.mjs +157 -0
  231. package/src/cli/effective-backlog-settings.ts +68 -2
  232. package/src/cli/flow-resolver-composition.test.mjs +101 -0
  233. package/src/cli/init.test.mjs +161 -0
  234. package/src/cli/init.ts +407 -62
  235. package/src/cli/kit-metadata-security.test.mjs +443 -0
  236. package/src/cli/kit.ts +50 -12
  237. package/src/cli/pull-work-provider.ts +377 -3
  238. package/src/cli/sidecar-pure-helpers.test.mjs +64 -0
  239. package/src/cli/skill-drift-check.ts +196 -0
  240. package/src/cli/telemetry-doctor.test.mjs +53 -0
  241. package/src/cli/telemetry-doctor.ts +50 -7
  242. package/src/cli/validate-hook-influence.ts +37 -6
  243. package/src/cli/workflow-sidecar.ts +1150 -151
  244. package/src/cli.ts +5 -0
  245. package/src/flow-kit/validate.ts +277 -38
  246. package/src/index.ts +19 -0
  247. package/src/lib/console-connect-options.ts +261 -0
  248. package/src/lib/console-telemetry-validate.ts +88 -0
  249. package/src/lib/flow-resolver.ts +153 -10
  250. package/src/lib/fs.ts +160 -0
  251. package/src/lib/local-artifact-root.ts +129 -3
  252. package/src/runtime-adapters.ts +113 -33
  253. package/src/tools/build-universal-bundles.ts +36 -2
  254. package/src/tools/codex-agent-routing.ts +48 -0
  255. package/src/tools/generate-context-map.ts +1 -0
  256. package/src/tools/validate-source-tree.ts +26 -1
@@ -154,7 +154,14 @@ mkdir -p "$audit_dir/sessions"
154
154
  printf '{"session_id":"session-1"}\n' > "$audit_dir/sessions/one.session"
155
155
  if printf '%s\n' '{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"echo AKIA1234567890ABCDEF && rm -rf /tmp/example"}}' \
156
156
  | TELEMETRY_GOVERNANCE=true TELEMETRY_DATA_DIR="$audit_dir" TELEMETRY_SESSION_DIR="$audit_dir/sessions" bash "$ROOT/scripts/hooks/governance-audit.sh" preToolUse dev >"$TMPDIR_EVAL/governance.out" 2>"$TMPDIR_EVAL/governance.err"; then
157
- sleep 0.2
157
+ for _audit_wait in $(seq 1 50); do
158
+ if [[ -s "$audit_dir/audit.jsonl" ]] \
159
+ && grep -q '"event_type":"governance.secret_detected"' "$audit_dir/audit.jsonl" \
160
+ && grep -q '"event_type":"governance.destructive_operation"' "$audit_dir/audit.jsonl"; then
161
+ break
162
+ fi
163
+ sleep 0.1
164
+ done
158
165
  if [[ -s "$audit_dir/audit.jsonl" ]] \
159
166
  && grep -q '"event_type":"governance.secret_detected"' "$audit_dir/audit.jsonl" \
160
167
  && grep -q '"event_type":"governance.destructive_operation"' "$audit_dir/audit.jsonl"; then
@@ -31,6 +31,30 @@ else
31
31
  _fail "hook influence behavioral cases failed validation: $(cat /tmp/flow-agents-hook-influence.out /tmp/flow-agents-hook-influence.err)"
32
32
  fi
33
33
 
34
+ TMP_HOOK_INFLUENCE="$(mktemp -d)"
35
+ mkdir -p "$TMP_HOOK_INFLUENCE/source/kits/release-evidence" "$TMP_HOOK_INFLUENCE/dest"
36
+ cat > "$TMP_HOOK_INFLUENCE/source/kits/catalog.json" <<'JSON'
37
+ {"schema_version":"1.0","kits":[{"id":"release-evidence","name":"Release Evidence Kit","path":"kits/release-evidence","description":"Builder-less fixture"}]}
38
+ JSON
39
+ cat > "$TMP_HOOK_INFLUENCE/source/kits/release-evidence/kit.json" <<'JSON'
40
+ {"schema_version":"1.0","id":"release-evidence","name":"Release Evidence Kit","flows":[{"id":"release-evidence.review","path":"flows/review.flow.json"}]}
41
+ JSON
42
+ node - "$CASES" "$TMP_HOOK_INFLUENCE/cases-without-builder.json" <<'NODE'
43
+ const fs = require("node:fs");
44
+ const input = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
45
+ input.cases = input.cases.filter((item) => !/^(kit:builder:)?dev-builder-/.test(String(item.id || "")));
46
+ fs.writeFileSync(process.argv[3], JSON.stringify(input, null, 2) + "\n");
47
+ NODE
48
+
49
+ if FLOW_AGENTS_HOOK_INFLUENCE_SOURCE_ROOT="$TMP_HOOK_INFLUENCE/source" \
50
+ FLOW_AGENTS_HOOK_INFLUENCE_DEST="$TMP_HOOK_INFLUENCE/dest" \
51
+ flow_agents_node "$VALIDATOR" "$TMP_HOOK_INFLUENCE/cases-without-builder.json" > /tmp/flow-agents-hook-influence-builderless.out 2> /tmp/flow-agents-hook-influence-builderless.err; then
52
+ _pass "hook influence validator drops Builder-required cases when Builder is absent from catalog"
53
+ else
54
+ _fail "hook influence validator still required Builder cases for a Builder-less catalog: $(cat /tmp/flow-agents-hook-influence-builderless.out /tmp/flow-agents-hook-influence-builderless.err)"
55
+ fi
56
+ rm -rf "$TMP_HOOK_INFLUENCE"
57
+
34
58
  if rg -q '"tier": "adapter"' "$CASES" \
35
59
  && rg -q '"tier": "live-acceptance"' "$CASES" \
36
60
  && rg -q '"tier": "installed-command"' "$CASES" \
@@ -59,7 +83,7 @@ else
59
83
  _fail "hook influence cases miss a required #62 Builder Kit loop category"
60
84
  fi
61
85
 
62
- rm -f /tmp/flow-agents-hook-influence.out /tmp/flow-agents-hook-influence.err
86
+ rm -f /tmp/flow-agents-hook-influence.out /tmp/flow-agents-hook-influence.err /tmp/flow-agents-hook-influence-builderless.out /tmp/flow-agents-hook-influence-builderless.err
63
87
 
64
88
  if [[ "$errors" -eq 0 ]]; then
65
89
  echo "Hook influence case integration passed."
@@ -58,8 +58,14 @@ cat > "$SEEDED_DEST/.claude/settings.json" << 'JSON'
58
58
  {
59
59
  "permissions": {
60
60
  "allow": ["Bash(usertool:*)"],
61
+ "defaultMode": "ask",
61
62
  "customPermission": true
62
63
  },
64
+ "statusLine": {
65
+ "type": "command",
66
+ "command": "echo user-statusline"
67
+ },
68
+ "skipDangerousModePermissionPrompt": false,
63
69
  "myUserKey": "preserved-value",
64
70
  "hooks": {
65
71
  "Stop": [
@@ -78,7 +84,8 @@ cat > "$SEEDED_DEST/.claude/settings.json" << 'JSON'
78
84
  JSON
79
85
 
80
86
  # Run install
81
- (cd "$ROOT_DIR/dist/claude-code" && bash install.sh "$SEEDED_DEST" >/dev/null 2>&1)
87
+ SEEDED_INSTALL_OUT="$TMPDIR_EVAL/seeded-claude-install.out"
88
+ (cd "$ROOT_DIR/dist/claude-code" && bash install.sh "$SEEDED_DEST" >"$SEEDED_INSTALL_OUT" 2>&1)
82
89
 
83
90
  # Assert: FA hooks present
84
91
  if node - "$SEEDED_DEST/.claude/settings.json" << 'NODE'
@@ -135,15 +142,39 @@ const fs = require("node:fs");
135
142
  const s = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
136
143
  const p = s.permissions || {};
137
144
  if (p.customPermission !== true) throw new Error("user permissions.customPermission was clobbered: " + JSON.stringify(p));
145
+ if (p.defaultMode !== "ask") throw new Error("user permissions.defaultMode conflict was not preserved: " + JSON.stringify(p));
138
146
  if (!JSON.stringify(p.allow || []).includes("usertool")) throw new Error("user permissions.allow entry not preserved by union: " + JSON.stringify(p.allow));
139
147
  console.log("ok");
140
148
  NODE
141
149
  then
142
- _pass "seeded: user custom permissions preserved (deep-merge union, not clobbered)"
150
+ _pass "seeded: user custom permissions preserved (deep-merge union, scalar conflicts preserved)"
143
151
  else
144
152
  _fail "seeded: user custom permissions were clobbered"
145
153
  fi
146
154
 
155
+ # Assert: user-owned scalar/object settings are preserved and surfaced as conflicts.
156
+ if node - "$SEEDED_DEST/.claude/settings.json" << 'NODE'
157
+ const fs = require("node:fs");
158
+ const s = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
159
+ if (s.statusLine?.command !== "echo user-statusline") throw new Error("statusLine conflict was not preserved: " + JSON.stringify(s.statusLine));
160
+ if (s.skipDangerousModePermissionPrompt !== false) throw new Error("skipDangerousModePermissionPrompt conflict was not preserved: " + JSON.stringify(s.skipDangerousModePermissionPrompt));
161
+ console.log("ok");
162
+ NODE
163
+ then
164
+ _pass "seeded: user-owned statusLine and skipDangerousModePermissionPrompt preserved"
165
+ else
166
+ _fail "seeded: user-owned scalar/object settings were clobbered"
167
+ fi
168
+
169
+ if rg -q "install-merge: conflict: preserving existing setting 'statusLine'" "$SEEDED_INSTALL_OUT" \
170
+ && rg -q "install-merge: conflict: preserving existing setting 'permissions.defaultMode'" "$SEEDED_INSTALL_OUT" \
171
+ && rg -q "install-merge: conflict: preserving existing setting 'skipDangerousModePermissionPrompt'" "$SEEDED_INSTALL_OUT"; then
172
+ _pass "seeded: install reports preserved setting conflicts to the user"
173
+ else
174
+ _fail "seeded: install did not report expected setting conflicts"
175
+ sed -n '1,120p' "$SEEDED_INSTALL_OUT"
176
+ fi
177
+
147
178
  echo ""
148
179
 
149
180
  # ─── Scenario 2: Version-stamped first install ───────────────────────────────
@@ -403,6 +434,36 @@ else
403
434
  _fail "--global: agents were not synced into global destination"
404
435
  fi
405
436
 
437
+ # Regression guard (#439): --global must also write a per-skill-file sha256 content-hash
438
+ # manifest, a sibling of install.json, so `flow-agents skill-drift-check` and the SessionStart
439
+ # advisory have a baseline to classify installed skill files against.
440
+ if node - "$GLOBAL_SETTINGS_DIR/.flow-agents/skills-manifest.json" << 'NODE'
441
+ const fs = require("node:fs");
442
+ const manifest = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
443
+ if (!manifest.files || typeof manifest.files !== "object" || Object.keys(manifest.files).length === 0) throw new Error("skills-manifest.json files is empty: " + JSON.stringify(manifest.files));
444
+ if (!manifest.generatedAt) throw new Error("skills-manifest.json missing generatedAt");
445
+ if (manifest.runtime !== "claude-code") throw new Error("skills-manifest.json wrong runtime: " + manifest.runtime);
446
+ console.log("ok: " + Object.keys(manifest.files).length + " files");
447
+ NODE
448
+ then
449
+ _pass "--global: skills-manifest.json written with non-empty files after install"
450
+ else
451
+ _fail "--global: skills-manifest.json missing, empty, or invalid after install"
452
+ fi
453
+
454
+ # Re-run init --global: the manifest must regenerate (fresh generatedAt) without disturbing any
455
+ # of the settings-merge, skill-sync, and agent-sync assertions already proven above in this scenario.
456
+ FIRST_MANIFEST_GENERATED_AT=$(node -e "console.log(JSON.parse(require('fs').readFileSync('$GLOBAL_SETTINGS_DIR/.flow-agents/skills-manifest.json','utf8')).generatedAt)" 2>/dev/null || echo "")
457
+ FLOW_AGENTS_USER_CLAUDE_SETTINGS="$GLOBAL_SETTINGS_DIR/settings.json" \
458
+ node "$ROOT_DIR/build/src/cli.js" init --runtime claude-code --global --yes >/dev/null 2>&1 || true
459
+ SECOND_MANIFEST_GENERATED_AT=$(node -e "console.log(JSON.parse(require('fs').readFileSync('$GLOBAL_SETTINGS_DIR/.flow-agents/skills-manifest.json','utf8')).generatedAt)" 2>/dev/null || echo "")
460
+
461
+ if [[ -n "$FIRST_MANIFEST_GENERATED_AT" && -n "$SECOND_MANIFEST_GENERATED_AT" && "$FIRST_MANIFEST_GENERATED_AT" != "$SECOND_MANIFEST_GENERATED_AT" ]]; then
462
+ _pass "--global: re-running init regenerates skills-manifest.json (generatedAt changed)"
463
+ else
464
+ _fail "--global: skills-manifest.json generatedAt did not change on re-run (first=$FIRST_MANIFEST_GENERATED_AT second=$SECOND_MANIFEST_GENERATED_AT)"
465
+ fi
466
+
406
467
  echo ""
407
468
 
408
469
  # ─── Scenario 6: Manual proof (user-visible) ─────────────────────────────────
@@ -1055,6 +1116,12 @@ echo "--- CH4: codex-home preserves user config, profiles, hooks, local kit stat
1055
1116
  CH4_DEST="$TMPDIR_EVAL/codex-home-ch4"
1056
1117
  mkdir -p "$CH4_DEST/kits/local/repositories/user-kit" "$CH4_DEST/sk""ills/user-owned-skill" "$CH4_DEST/ag""ents"
1057
1118
 
1119
+ CH4_GENERIC_DIRS=(agent-cards build context docs evals integrations packaging powers prompts schemas scripts kits)
1120
+ for CH4_DIR in "${CH4_GENERIC_DIRS[@]}"; do
1121
+ mkdir -p "$CH4_DEST/$CH4_DIR"
1122
+ printf 'user-owned-%s\n' "$CH4_DIR" > "$CH4_DEST/$CH4_DIR/user-owned.txt"
1123
+ done
1124
+
1058
1125
  cat > "$CH4_DEST/config.toml" << 'EOF_CFG'
1059
1126
  model = "user-model"
1060
1127
  EOF_CFG
@@ -1181,6 +1248,17 @@ else
1181
1248
  _fail "CH4: installed scripts/kit.js could not run with installed build bundle"
1182
1249
  fi
1183
1250
 
1251
+ CODEX_REAL_HOME="$TMPDIR_EVAL/fake-real-codex" bash "$ROOT_DIR/scripts/install-codex-home.sh" "$CH4_DEST" >/dev/null 2>&1
1252
+ CH4_GENERIC_PRESERVED=1
1253
+ for CH4_DIR in "${CH4_GENERIC_DIRS[@]}"; do
1254
+ [[ "$(cat "$CH4_DEST/$CH4_DIR/user-owned.txt" 2>/dev/null)" == "user-owned-$CH4_DIR" ]] || CH4_GENERIC_PRESERVED=0
1255
+ done
1256
+ if [[ "$CH4_GENERIC_PRESERVED" -eq 1 && -f "$CH4_DEST/.flow-agents/codex-install-manifest.json" ]]; then
1257
+ _pass "CH4: unrelated files in every shared bundle directory survive install and reinstall"
1258
+ else
1259
+ _fail "CH4: install or reinstall removed unrelated files from a shared bundle directory"
1260
+ fi
1261
+
1184
1262
  echo ""
1185
1263
 
1186
1264
  # ─── codex-home: CH5: destination symlink containment ───────────────────────
@@ -1201,6 +1279,153 @@ for CH5_REL in scripts kits sk""ills hooks.json; do
1201
1279
  fi
1202
1280
  done
1203
1281
 
1282
+ echo ""
1283
+ echo "--- CH6: codex-home rejects canonical source/destination overlap before writes ---"
1284
+ CH6_ROOT="$TMPDIR_EVAL/ch6-fixture-root"
1285
+ CH6_FAKE_BIN="$TMPDIR_EVAL/ch6-bin"
1286
+ CH_FIXTURE_SCRIPTS="scr""ipts"
1287
+ CH_FIXTURE_SKILLS="sk""ills"
1288
+ CH_FIXTURE_AGENTS="ag""ents"
1289
+ mkdir -p "$CH6_ROOT/$CH_FIXTURE_SCRIPTS" "$CH6_ROOT/dist/codex/$CH_FIXTURE_SCRIPTS" "$CH6_FAKE_BIN"
1290
+ cp "$ROOT_DIR/scripts/install-codex-home.sh" "$ROOT_DIR/scripts/install-owned-files.js" "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/"
1291
+ printf '#!/usr/bin/env bash\nexit 0\n' > "$CH6_FAKE_BIN/npm"
1292
+ chmod +x "$CH6_FAKE_BIN/npm"
1293
+ printf 'fixture\n' > "$CH6_ROOT/dist/codex/$CH_FIXTURE_SCRIPTS/fixture.txt"
1294
+ mkdir -p "$CH6_ROOT/dist/codex/.codex/$CH_FIXTURE_SKILLS/legacy-collision" "$CH6_ROOT/dist/codex/.codex/$CH_FIXTURE_AGENTS"
1295
+ printf 'flow-agents-new-skill\n' > "$CH6_ROOT/dist/codex/.codex/$CH_FIXTURE_SKILLS/legacy-collision/SKILL.md"
1296
+ printf 'name = "flow-agents-new-agent"\n' > "$CH6_ROOT/dist/codex/.codex/$CH_FIXTURE_AGENTS/legacy-collision.toml"
1297
+
1298
+ for CH6_CASE in equal descendant ancestor; do
1299
+ case "$CH6_CASE" in
1300
+ equal) CH6_DEST="$CH6_ROOT" ;;
1301
+ descendant) CH6_DEST="$CH6_ROOT/nested-destination" ;;
1302
+ ancestor) CH6_DEST="$TMPDIR_EVAL" ;;
1303
+ esac
1304
+ if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch6-home" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH6_DEST" >"$TMPDIR_EVAL/ch6-$CH6_CASE.out" 2>&1; then
1305
+ _fail "CH6: installer accepted $CH6_CASE source/destination overlap"
1306
+ elif grep -q 'overlaps' "$TMPDIR_EVAL/ch6-$CH6_CASE.out" && [[ -f "$CH6_ROOT/dist/codex/$CH_FIXTURE_SCRIPTS/fixture.txt" ]]; then
1307
+ _pass "CH6: installer rejects $CH6_CASE canonical overlap before source mutation"
1308
+ else
1309
+ _fail "CH6: installer did not safely reject $CH6_CASE overlap"
1310
+ fi
1311
+ done
1312
+
1313
+ CH6_AUTH_DEST="$TMPDIR_EVAL/ch6-auth-dest"
1314
+ CH6_AUTH_ALIAS="$TMPDIR_EVAL/ch6-auth-alias"
1315
+ mkdir -p "$CH6_AUTH_DEST"
1316
+ printf '{"user":"preserved"}\n' > "$CH6_AUTH_DEST/auth.json"
1317
+ ln -s "$CH6_AUTH_DEST" "$CH6_AUTH_ALIAS"
1318
+ if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch6-home" CODEX_REAL_HOME="$CH6_AUTH_ALIAS" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH6_AUTH_DEST" >"$TMPDIR_EVAL/ch6-auth.out" 2>&1 \
1319
+ && grep -q '"user":"preserved"' "$CH6_AUTH_DEST/auth.json"; then
1320
+ _pass "CH6: canonical auth-home alias is treated as self-copy and preserved"
1321
+ else
1322
+ _fail "CH6: canonical auth-home alias caused a self-copy failure or mutation"
1323
+ fi
1324
+
1325
+ echo ""
1326
+ echo "--- CH7: pre-manifest ownership bootstrap is evidence-bound ---"
1327
+ seed_ch7_legacy() {
1328
+ local destination="$1"
1329
+ local installed_at="$2"
1330
+ mkdir -p "$destination/.flow-agents" "$destination/$CH_FIXTURE_SCRIPTS"
1331
+ printf 'old-release\n' > "$destination/$CH_FIXTURE_SCRIPTS/fixture.txt"
1332
+ cat > "$destination/.flow-agents/install.json" <<JSON
1333
+ {"version":"3.2.0","installedAt":"$installed_at","runtime":"codex"}
1334
+ JSON
1335
+ cat > "$destination/hooks.json" <<'JSON'
1336
+ {"hooks":{"Stop":[{"hooks":[{"statusMessage":"Recording Flow Agents telemetry"}]}]}}
1337
+ JSON
1338
+ }
1339
+
1340
+ CH7_LEGACY="$TMPDIR_EVAL/ch7-genuine-legacy"
1341
+ seed_ch7_legacy "$CH7_LEGACY" "2099-01-01T00:00:00.000Z"
1342
+ if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_LEGACY" >"$TMPDIR_EVAL/ch7-legacy.out" 2>&1 \
1343
+ && [[ "$(cat "$CH7_LEGACY/$CH_FIXTURE_SCRIPTS/fixture.txt")" == "fixture" ]] \
1344
+ && [[ -f "$CH7_LEGACY/.flow-agents/codex-install-manifest.json" ]]; then
1345
+ _pass "CH7: corroborated pre-manifest legacy owned file upgrades and gains a manifest"
1346
+ else
1347
+ _fail "CH7: genuine pre-manifest legacy install did not upgrade"
1348
+ fi
1349
+
1350
+ CH7_ARBITRARY="$TMPDIR_EVAL/ch7-arbitrary-collision"
1351
+ mkdir -p "$CH7_ARBITRARY/$CH_FIXTURE_SCRIPTS"
1352
+ printf 'user-arbitrary\n' > "$CH7_ARBITRARY/$CH_FIXTURE_SCRIPTS/fixture.txt"
1353
+ if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_ARBITRARY" >"$TMPDIR_EVAL/ch7-arbitrary.out" 2>&1; then
1354
+ _fail "CH7: first install overwrote an arbitrary unowned collision"
1355
+ elif [[ "$(cat "$CH7_ARBITRARY/$CH_FIXTURE_SCRIPTS/fixture.txt")" == "user-arbitrary" ]] && grep -q 'unowned or ambiguous' "$TMPDIR_EVAL/ch7-arbitrary.out"; then
1356
+ _pass "CH7: arbitrary unowned collision fails before mutation and survives"
1357
+ else
1358
+ _fail "CH7: arbitrary collision was not preserved cleanly"
1359
+ fi
1360
+
1361
+ CH7_MODIFIED="$TMPDIR_EVAL/ch7-modified-ambiguous"
1362
+ seed_ch7_legacy "$CH7_MODIFIED" "2000-01-01T00:00:00.000Z"
1363
+ printf 'user-modified-after-install\n' > "$CH7_MODIFIED/$CH_FIXTURE_SCRIPTS/fixture.txt"
1364
+ if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_MODIFIED" >"$TMPDIR_EVAL/ch7-modified.out" 2>&1; then
1365
+ _fail "CH7: ambiguous post-install modification was overwritten"
1366
+ elif [[ "$(cat "$CH7_MODIFIED/$CH_FIXTURE_SCRIPTS/fixture.txt")" == "user-modified-after-install" ]] && grep -q 'unowned or ambiguous' "$TMPDIR_EVAL/ch7-modified.out"; then
1367
+ _pass "CH7: modified ambiguous legacy-path file fails before mutation and survives"
1368
+ else
1369
+ _fail "CH7: modified ambiguous file was not preserved cleanly"
1370
+ fi
1371
+
1372
+ CH7_EXTENSIBLE="$TMPDIR_EVAL/ch7-user-extensible"
1373
+ seed_ch7_legacy "$CH7_EXTENSIBLE" "2099-01-01T00:00:00.000Z"
1374
+ mkdir -p "$CH7_EXTENSIBLE/$CH_FIXTURE_SKILLS/legacy-collision" "$CH7_EXTENSIBLE/$CH_FIXTURE_AGENTS"
1375
+ printf 'older-user-skill\n' > "$CH7_EXTENSIBLE/$CH_FIXTURE_SKILLS/legacy-collision/SKILL.md"
1376
+ printf 'name = "older-user-agent"\n' > "$CH7_EXTENSIBLE/$CH_FIXTURE_AGENTS/legacy-collision.toml"
1377
+ if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_EXTENSIBLE" >"$TMPDIR_EVAL/ch7-extensible.out" 2>&1; then
1378
+ _fail "CH7: legacy inference claimed a pre-existing user skill or agent"
1379
+ elif [[ "$(cat "$CH7_EXTENSIBLE/$CH_FIXTURE_SKILLS/legacy-collision/SKILL.md")" == "older-user-skill" ]] \
1380
+ && grep -q 'older-user-agent' "$CH7_EXTENSIBLE/$CH_FIXTURE_AGENTS/legacy-collision.toml" \
1381
+ && grep -q 'unowned or ambiguous' "$TMPDIR_EVAL/ch7-extensible.out"; then
1382
+ _pass "CH7: older user skill and agent collisions remain ambiguous and preserved"
1383
+ else
1384
+ _fail "CH7: user-extensible skill or agent collision was not preserved cleanly"
1385
+ fi
1386
+
1387
+ CH7_RETRY="$TMPDIR_EVAL/ch7-interrupted-retry"
1388
+ mkdir -p "$CH7_RETRY/.flow-agents" "$CH7_RETRY/$CH_FIXTURE_SCRIPTS"
1389
+ printf 'fixture\n' > "$CH7_RETRY/$CH_FIXTURE_SCRIPTS/fixture.txt"
1390
+ printf 'stale-old\n' > "$CH7_RETRY/$CH_FIXTURE_SCRIPTS/stale.txt"
1391
+ CH7_OLD_HASH="$(printf 'old-release\n' | shasum -a 256 | awk '{print $1}')"
1392
+ CH7_STALE_HASH="$(shasum -a 256 "$CH7_RETRY/$CH_FIXTURE_SCRIPTS/stale.txt" | awk '{print $1}')"
1393
+ cat > "$CH7_RETRY/.flow-agents/codex-install-manifest.json" <<JSON
1394
+ {"schema_version":"1.0","files":[{"path":"$CH_FIXTURE_SCRIPTS/fixture.txt","sha256":"$CH7_OLD_HASH"},{"path":"$CH_FIXTURE_SCRIPTS/stale.txt","sha256":"$CH7_STALE_HASH"}]}
1395
+ JSON
1396
+ if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_RETRY" >"$TMPDIR_EVAL/ch7-retry.out" 2>&1 \
1397
+ && [[ "$(cat "$CH7_RETRY/$CH_FIXTURE_SCRIPTS/fixture.txt")" == "fixture" ]] \
1398
+ && [[ ! -e "$CH7_RETRY/$CH_FIXTURE_SCRIPTS/stale.txt" ]]; then
1399
+ _pass "CH7: interrupted apply retries when current content already matches incoming and removes stale owned files"
1400
+ else
1401
+ _fail "CH7: interrupted apply state was not retry-safe"
1402
+ fi
1403
+
1404
+ CH7_THIRD="$TMPDIR_EVAL/ch7-interrupted-third-content"
1405
+ mkdir -p "$CH7_THIRD/.flow-agents" "$CH7_THIRD/$CH_FIXTURE_SCRIPTS"
1406
+ printf 'third-party-change\n' > "$CH7_THIRD/$CH_FIXTURE_SCRIPTS/fixture.txt"
1407
+ cat > "$CH7_THIRD/.flow-agents/codex-install-manifest.json" <<JSON
1408
+ {"schema_version":"1.0","files":[{"path":"$CH_FIXTURE_SCRIPTS/fixture.txt","sha256":"$CH7_OLD_HASH"}]}
1409
+ JSON
1410
+ if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_THIRD" >"$TMPDIR_EVAL/ch7-third.out" 2>&1; then
1411
+ _fail "CH7: retry safety accepted arbitrary third content"
1412
+ elif [[ "$(cat "$CH7_THIRD/$CH_FIXTURE_SCRIPTS/fixture.txt")" == "third-party-change" ]] && grep -q 'modified Flow Agents file' "$TMPDIR_EVAL/ch7-third.out"; then
1413
+ _pass "CH7: retry safety still rejects and preserves arbitrary third content"
1414
+ else
1415
+ _fail "CH7: arbitrary third content was not rejected cleanly"
1416
+ fi
1417
+
1418
+ CH7_FRESH="$TMPDIR_EVAL/ch7-fresh"
1419
+ mkdir -p "$CH7_FRESH/$CH_FIXTURE_SCRIPTS"
1420
+ printf 'user-unrelated\n' > "$CH7_FRESH/$CH_FIXTURE_SCRIPTS/user-owned.txt"
1421
+ if PATH="$CH6_FAKE_BIN:$PATH" HOME="$TMPDIR_EVAL/ch7-home" CODEX_REAL_HOME="$TMPDIR_EVAL/ch7-real" bash "$CH6_ROOT/$CH_FIXTURE_SCRIPTS/install-codex-home.sh" "$CH7_FRESH" >"$TMPDIR_EVAL/ch7-fresh.out" 2>&1 \
1422
+ && [[ "$(cat "$CH7_FRESH/$CH_FIXTURE_SCRIPTS/fixture.txt")" == "fixture" ]] \
1423
+ && [[ "$(cat "$CH7_FRESH/$CH_FIXTURE_SCRIPTS/user-owned.txt")" == "user-unrelated" ]]; then
1424
+ _pass "CH7: safe first install writes owned files and preserves unrelated files"
1425
+ else
1426
+ _fail "CH7: safe first install or unrelated-file preservation regressed"
1427
+ fi
1428
+
1204
1429
  echo ""
1205
1430
 
1206
1431
  # ─── opencode --global: OG1: seed user key → install --global → key survives + $schema + stamp ─
@@ -201,17 +201,17 @@ fi
201
201
 
202
202
  # ===================================================================
203
203
  echo ""
204
- echo "=== 8. Trust axis: first-party allowlist (builder and knowledge) ==="
204
+ echo "=== 8. Trust axis: built-in kits are unverified without runtime privilege ==="
205
205
  # ===================================================================
206
206
 
207
207
  for kit_name in builder knowledge; do
208
208
  out="$TMP_DIR/trust-${kit_name}.out"
209
209
  run_inspect "$ROOT/kits/$kit_name" "$out" || true
210
210
  trust=$(node -e "const d=require('fs').readFileSync('$out','utf8'); console.log(JSON.parse(d).trust)" 2>/dev/null)
211
- if [[ "$trust" == "first-party" ]]; then
212
- pass "$kit_name kit trust: first-party (in Kontour allowlist)"
211
+ if [[ "$trust" == "unverified" ]]; then
212
+ pass "$kit_name kit trust: unverified (official catalog metadata grants no runtime privilege)"
213
213
  else
214
- fail "$kit_name kit trust: expected first-party, got '$trust'"
214
+ fail "$kit_name kit trust: expected unverified, got '$trust'"
215
215
  cat "$out"
216
216
  fi
217
217
  done
@@ -226,7 +226,7 @@ for fixture in k0-flows-only k1-agent-extension k2-with-evals third-party-extens
226
226
  run_inspect "$ROOT/evals/fixtures/kit-conformance-levels/$fixture" "$out" || true
227
227
  trust=$(node -e "const d=require('fs').readFileSync('$out','utf8'); console.log(JSON.parse(d).trust)" 2>/dev/null)
228
228
  if [[ "$trust" == "unverified" ]]; then
229
- pass "$fixture fixture trust: unverified (not in first-party allowlist)"
229
+ pass "$fixture fixture trust: unverified"
230
230
  else
231
231
  fail "$fixture fixture trust: expected unverified, got '$trust'"
232
232
  cat "$out"
@@ -244,7 +244,7 @@ if node -e "
244
244
  const d = require('fs').readFileSync('$out', 'utf8');
245
245
  const r = JSON.parse(d);
246
246
  if (!('trust' in r)) throw new Error('missing key: trust');
247
- const valid = ['first-party', 'verified', 'unverified'];
247
+ const valid = ['verified', 'unverified'];
248
248
  if (!valid.includes(r.trust)) throw new Error('trust must be one of: ' + valid.join(', ') + '; got: ' + r.trust);
249
249
  " 2>/dev/null; then
250
250
  pass "inspect JSON output includes trust field with valid value"