@kontourai/flow-agents 3.9.0 → 3.10.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 (106) hide show
  1. package/.github/workflows/ci.yml +8 -0
  2. package/CHANGELOG.md +17 -0
  3. package/README.md +1 -1
  4. package/build/src/cli/assignment-provider.js +4 -18
  5. package/build/src/cli/continuation-adapter.d.ts +10 -8
  6. package/build/src/cli/continuation-adapter.js +22 -4
  7. package/build/src/cli/validate-workflow-artifacts.js +21 -1
  8. package/build/src/cli/workflow-sidecar.js +15 -20
  9. package/build/src/cli/workflow.js +58 -11
  10. package/build/src/continuation-driver.d.ts +27 -3
  11. package/build/src/continuation-driver.js +97 -14
  12. package/build/src/index.d.ts +2 -2
  13. package/build/src/index.js +1 -1
  14. package/build/src/tools/build-universal-bundles.js +52 -25
  15. package/build/src/tools/validate-source-tree.js +5 -2
  16. package/context/scripts/hooks/lib/continuation-turn-authority.js +386 -0
  17. package/context/scripts/hooks/stop-goal-fit.js +244 -73
  18. package/context/scripts/hooks/workflow-steering.js +24 -15
  19. package/context/scripts/telemetry/lib/pricing.sh +18 -6
  20. package/context/scripts/telemetry/lib/transport.sh +139 -37
  21. package/context/scripts/telemetry/lib/usage.sh +282 -32
  22. package/context/scripts/telemetry/lib/usage_model_guard.sh +42 -0
  23. package/context/scripts/telemetry/telemetry.sh +76 -1
  24. package/docs/coordination-guide.md +21 -5
  25. package/docs/fixture-ownership.md +2 -1
  26. package/docs/public-workflow-cli.md +44 -0
  27. package/docs/spec/runtime-hook-surface.md +8 -4
  28. package/evals/acceptance/prove-capture-teeth-declared.sh +13 -0
  29. package/evals/acceptance/prove-capture-teeth.sh +13 -0
  30. package/evals/ci/run-baseline.sh +2 -0
  31. package/evals/fixtures/codex-legacy-agents/5273878130bdafc8a024a650bb5b66c9b003f1f859b5dc6e5b588cbf4ab23228.md +25 -0
  32. package/evals/fixtures/telemetry/usage-transcript-adversarial.jsonl +2 -0
  33. package/evals/fixtures/telemetry/usage-transcript-malformed-sandwich.jsonl +3 -0
  34. package/evals/fixtures/telemetry/usage-transcript-negative-tokens.jsonl +1 -0
  35. package/evals/fixtures/telemetry/usage-transcript-oversized-prefix.jsonl +201 -0
  36. package/evals/fixtures/telemetry/usage-transcript-oversized-tokens.jsonl +1 -0
  37. package/evals/fixtures/telemetry/usage-transcript-prefixed-secret-lower.jsonl +1 -0
  38. package/evals/fixtures/telemetry/usage-transcript-prefixed-secret-upper.jsonl +1 -0
  39. package/evals/fixtures/telemetry/usage-transcript-secret-model-jwt.jsonl +1 -0
  40. package/evals/fixtures/telemetry/usage-transcript-secret-model.jsonl +1 -0
  41. package/evals/fixtures/telemetry/usage-transcript-torn-trailing.jsonl +2 -0
  42. package/evals/integration/test_actor_identity.sh +63 -0
  43. package/evals/integration/test_assignment_provider_local_file.sh +34 -0
  44. package/evals/integration/test_builder_entry_enforcement.sh +5 -1
  45. package/evals/integration/test_bundle_install.sh +106 -17
  46. package/evals/integration/test_bundle_lifecycle.sh +17 -3
  47. package/evals/integration/test_captured_fail_reconciliation.sh +11 -0
  48. package/evals/integration/test_ci_actor_identity.sh +2 -2
  49. package/evals/integration/test_command_log_concurrency.sh +11 -0
  50. package/evals/integration/test_command_log_fork_classification.sh +11 -0
  51. package/evals/integration/test_command_log_integrity.sh +11 -0
  52. package/evals/integration/test_current_json_per_actor.sh +416 -21
  53. package/evals/integration/test_enforcer_expects_driven.sh +11 -0
  54. package/evals/integration/test_ensure_session_ownership_guard.sh +39 -0
  55. package/evals/integration/test_evidence_capture_hook.sh +25 -6
  56. package/evals/integration/test_fixture_retirement_audit.sh +2 -2
  57. package/evals/integration/test_flowdef_union_floor_regression.sh +11 -0
  58. package/evals/integration/test_gate_bypass_chain.sh +11 -0
  59. package/evals/integration/test_gate_lockdown.sh +10 -0
  60. package/evals/integration/test_goal_fit_ghost_session.sh +11 -0
  61. package/evals/integration/test_goal_fit_hook.sh +257 -9
  62. package/evals/integration/test_goal_fit_rederive.sh +11 -0
  63. package/evals/integration/test_install_merge.sh +141 -3
  64. package/evals/integration/test_liveness_conflict_injection.sh +39 -3
  65. package/evals/integration/test_liveness_heartbeat.sh +46 -9
  66. package/evals/integration/test_phase_map_and_gate_claim.sh +10 -1
  67. package/evals/integration/test_public_workflow_cli.sh +6 -6
  68. package/evals/integration/test_session_resume_roundtrip.sh +30 -0
  69. package/evals/integration/test_stop_hook_release.sh +111 -11
  70. package/evals/integration/test_telemetry_tool_usage.sh +394 -0
  71. package/evals/integration/test_verify_hold.sh +64 -1
  72. package/evals/integration/test_workflow_sidecar_writer.sh +10 -1
  73. package/evals/integration/test_workflow_steering_hook.sh +20 -4
  74. package/evals/run.sh +2 -0
  75. package/evals/static/test_universal_bundles.sh +123 -0
  76. package/package.json +1 -1
  77. package/packaging/README.md +21 -0
  78. package/packaging/codex-legacy-agents-fingerprints.json +33 -0
  79. package/scripts/README.md +2 -1
  80. package/scripts/audit-codex-legacy-agents.js +43 -0
  81. package/scripts/classify-codex-legacy-agents.js +71 -0
  82. package/scripts/hooks/evidence-capture.js +18 -6
  83. package/scripts/hooks/lib/actor-identity.js +62 -29
  84. package/scripts/hooks/lib/continuation-turn-authority.js +386 -0
  85. package/scripts/hooks/lib/current-pointer.js +114 -12
  86. package/scripts/hooks/lib/liveness-heartbeat.js +15 -12
  87. package/scripts/hooks/stop-goal-fit.js +244 -73
  88. package/scripts/hooks/workflow-steering.js +24 -15
  89. package/scripts/install-codex-home.sh +8 -7
  90. package/scripts/telemetry/lib/pricing.sh +18 -6
  91. package/scripts/telemetry/lib/transport.sh +71 -0
  92. package/scripts/telemetry/lib/usage.sh +282 -32
  93. package/scripts/telemetry/lib/usage_model_guard.sh +42 -0
  94. package/scripts/telemetry/telemetry.sh +76 -1
  95. package/src/cli/assignment-provider.ts +5 -26
  96. package/src/cli/builder-flow-runtime.test.mjs +93 -6
  97. package/src/cli/continuation-adapter.ts +33 -7
  98. package/src/cli/continuation-driver.test.mjs +741 -2
  99. package/src/cli/public-api.test.mjs +1 -0
  100. package/src/cli/validate-workflow-artifacts.ts +19 -1
  101. package/src/cli/workflow-sidecar.ts +18 -23
  102. package/src/cli/workflow.ts +71 -11
  103. package/src/continuation-driver.ts +125 -19
  104. package/src/index.ts +4 -0
  105. package/src/tools/build-universal-bundles.ts +61 -25
  106. package/src/tools/validate-source-tree.ts +5 -2
@@ -11,6 +11,10 @@ set -uo pipefail
11
11
  ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
12
12
  CAPTURE="$ROOT/scripts/hooks/evidence-capture.js"
13
13
  GATE="$ROOT/scripts/hooks/stop-goal-fit.js"
14
+ CURRENT_POINTER_HELPER="$ROOT/scripts/hooks/lib/current-pointer.js"
15
+ # #440: every fixture this file builds is "owned" by this one constant actor, once a given
16
+ # invocation below applies FLOW_AGENTS_ACTOR="$EVIDENCE_ACTOR" to it (see seed_repo/capture()).
17
+ EVIDENCE_ACTOR="eval-evidence-capture-actor"
14
18
 
15
19
  # Disable the block escape hatch so repeated independent assertions never trip it.
16
20
  export FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=100000
@@ -41,10 +45,21 @@ type: deliver
41
45
 
42
46
  ### Verdict: PASS
43
47
  MD
48
+ # #440 FIXTURE-GAP: seed EVIDENCE_ACTOR's own per-actor current pointer for this repo/slug,
49
+ # unconditionally (harmless/unused for any invocation below that does NOT set
50
+ # FLOW_AGENTS_ACTOR="$EVIDENCE_ACTOR") -- mirroring workflow-sidecar.ts's real writeCurrent()
51
+ # dual-write via current-pointer.js's own writePerActorCurrent, so #440's ownership-scoped
52
+ # resolveArtifactDir/preferredArtifactDir find this fixture's session exactly like a real
53
+ # ensure-session'd one would.
54
+ CP_HELPER_ARG="$CURRENT_POINTER_HELPER" FLOW_AGENTS_DIR_ARG="$p/.kontourai/flow-agents" \
55
+ SLUG_ARG="$slug" ACTOR_ARG="$EVIDENCE_ACTOR" node - <<'NODE'
56
+ const { writePerActorCurrent } = require(process.env.CP_HELPER_ARG);
57
+ writePerActorCurrent(process.env.FLOW_AGENTS_DIR_ARG, process.env.ACTOR_ARG, { active_slug: process.env.SLUG_ARG });
58
+ NODE
44
59
  }
45
60
 
46
61
  capture() { # stdin = payload json
47
- node "$CAPTURE" >/dev/null 2>&1
62
+ FLOW_AGENTS_ACTOR="$EVIDENCE_ACTOR" node "$CAPTURE" >/dev/null 2>&1
48
63
  }
49
64
 
50
65
  # ============================================================================
@@ -103,7 +118,7 @@ B="$TMP/contradict"; seed_repo "$B" t1
103
118
  printf '%s' '{"schema_version":"1.0","task_slug":"t1","verdict":"pass","checks":[{"id":"unit-tests","kind":"command","status":"pass","command":"npm test","summary":"tests passed"}]}' > "$B/.kontourai/flow-agents/t1/evidence.json"
104
119
  printf '%s\n' '{"command":"npm test","observedResult":"fail","exitCode":1,"capturedAt":"2026-06-23T00:00:00Z","source":"postToolUse-capture"}' > "$B/.kontourai/flow-agents/t1/command-log.jsonl"
105
120
 
106
- if FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_BACKSTOP=skip node "$GATE" >/dev/null 2>"$TMP/b1.err" <<JSON
121
+ if FLOW_AGENTS_ACTOR="$EVIDENCE_ACTOR" FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_BACKSTOP=skip node "$GATE" >/dev/null 2>"$TMP/b1.err" <<JSON
107
122
  {"hook_event_name":"Stop","cwd":"$B"}
108
123
  JSON
109
124
  then _fail "gate should BLOCK when capture log contradicts claimed pass"
@@ -124,7 +139,11 @@ printf '%s\n' '{"command":"npm test","observedResult":"pass","exitCode":0,"captu
124
139
  # A poisoned npm on PATH proves the gate does NOT re-run when the log confirms.
125
140
  POISON="$TMP/poison"; mkdir -p "$POISON"
126
141
  printf '#!/usr/bin/env bash\necho "npm should not run" >&2\nexit 99\n' > "$POISON/npm"; chmod +x "$POISON/npm"
127
- PATH="$POISON:$PATH" FLOW_AGENTS_GOAL_FIT_MODE=block node "$GATE" >/dev/null 2>"$TMP/b2.err" <<JSON
142
+ # #440 FIX 2 (de-vacuate, independent review): apply EVIDENCE_ACTOR so the gate actually resolves
143
+ # repo C's session (seed_repo already seeded EVIDENCE_ACTOR's own pointer for it) and reaches the
144
+ # capture cross-reference / confirmed-pass-trusts-the-log logic, not the outer "no artifactDir at
145
+ # all" early-return (which would also never re-run npm, for an unrelated reason).
146
+ PATH="$POISON:$PATH" FLOW_AGENTS_ACTOR="$EVIDENCE_ACTOR" FLOW_AGENTS_GOAL_FIT_MODE=block node "$GATE" >/dev/null 2>"$TMP/b2.err" <<JSON
128
147
  {"hook_event_name":"Stop","cwd":"$C"}
129
148
  JSON
130
149
  if rg -q 'CONTRADICTS|backstop|npm should not run' "$TMP/b2.err"; then
@@ -140,7 +159,7 @@ printf '%s' '{"name":"x","scripts":{"test":"exit 7"}}' > "$D/package.json"
140
159
  printf '%s' '{"schema_version":"1.0","task_slug":"t1","verdict":"pass","checks":[{"id":"unit-tests","kind":"command","status":"pass","command":"npm test","summary":"tests passed"}]}' > "$D/.kontourai/flow-agents/t1/evidence.json"
141
160
  # command-log.jsonl intentionally absent — the command was never actually run.
142
161
 
143
- if FLOW_AGENTS_GOAL_FIT_MODE=block node "$GATE" >/dev/null 2>"$TMP/b3.err" <<JSON
162
+ if FLOW_AGENTS_ACTOR="$EVIDENCE_ACTOR" FLOW_AGENTS_GOAL_FIT_MODE=block node "$GATE" >/dev/null 2>"$TMP/b3.err" <<JSON
144
163
  {"hook_event_name":"Stop","cwd":"$D"}
145
164
  JSON
146
165
  then _fail "gate should BLOCK when trusted backstop re-run of declared manifest target fails"
@@ -159,7 +178,7 @@ E="$TMP/notverified"; seed_repo "$E" t1
159
178
  printf '%s' '{"schema_version":"1.0","task_slug":"t1","status":"in_progress","phase":"verification","updated_at":"2026-06-23T00:00:00Z","next_action":{"status":"continue","summary":"verify command evidence"}}' > "$E/.kontourai/flow-agents/t1/state.json"
160
179
  printf '%s' '{"schema_version":"1.0","task_slug":"t1","verdict":"pass","checks":[{"id":"custom","kind":"command","status":"pass","command":"./my-thing.sh","summary":"ran custom"}]}' > "$E/.kontourai/flow-agents/t1/evidence.json"
161
180
 
162
- if FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_RECHECK=false node "$GATE" >/dev/null 2>"$TMP/b4.err" <<JSON
181
+ if FLOW_AGENTS_ACTOR="$EVIDENCE_ACTOR" FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_RECHECK=false node "$GATE" >/dev/null 2>"$TMP/b4.err" <<JSON
163
182
  {"hook_event_name":"Stop","cwd":"$E"}
164
183
  JSON
165
184
  then _fail "gate should not silently pass an un-captured, un-verifiable claimed-pass command"
@@ -182,7 +201,7 @@ F="$TMP/recheck"; seed_repo "$F" t1
182
201
  printf '%s' '{"schema_version":"1.0","task_slug":"t1","status":"in_progress","phase":"verification","updated_at":"2026-06-23T00:00:00Z","next_action":{"status":"continue","summary":"verify command evidence"}}' > "$F/.kontourai/flow-agents/t1/state.json"
183
202
  printf '%s' '{"schema_version":"1.0","task_slug":"t1","verdict":"pass","checks":[{"id":"custom","kind":"command","status":"pass","command":"exit 5","summary":"ran custom"}]}' > "$F/.kontourai/flow-agents/t1/evidence.json"
184
203
  # Opt-in ON (in-flight): the model's free-form "exit 5" is re-run and fails → block.
185
- if FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_RECHECK=true node "$GATE" >/dev/null 2>"$TMP/b5.err" <<JSON
204
+ if FLOW_AGENTS_ACTOR="$EVIDENCE_ACTOR" FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_RECHECK=true node "$GATE" >/dev/null 2>"$TMP/b5.err" <<JSON
186
205
  {"hook_event_name":"Stop","cwd":"$F"}
187
206
  JSON
188
207
  then _fail "with RECHECK=true the failing model command should block"
@@ -21,9 +21,9 @@ json_query() {
21
21
  node -e 'const fs=require("fs"); let cur=JSON.parse(fs.readFileSync(process.argv[1],"utf8")); for (const part of process.argv[2].split(".")) cur=Array.isArray(cur) ? cur[Number(part)] : cur[part]; console.log(cur);' "$1" "$2"
22
22
  }
23
23
 
24
- [[ "$(json_query "$TMPDIR_EVAL/audit.json" "totals.scanned")" == "19" ]] && pass "audit scans all fixture groups" || fail "audit scans all fixture groups"
24
+ [[ "$(json_query "$TMPDIR_EVAL/audit.json" "totals.scanned")" == "20" ]] && pass "audit scans all fixture groups" || fail "audit scans all fixture groups"
25
25
  [[ "$(json_query "$TMPDIR_EVAL/audit.json" "totals.retire_candidates")" == "0" ]] && pass "audit finds no unowned retire candidates" || fail "audit finds no unowned retire candidates"
26
- [[ "$(json_query "$TMPDIR_EVAL/audit.json" "totals.kept")" == "19" ]] && pass "audit keeps all owned fixture groups" || fail "audit keeps all owned fixture groups"
26
+ [[ "$(json_query "$TMPDIR_EVAL/audit.json" "totals.kept")" == "20" ]] && pass "audit keeps all owned fixture groups" || fail "audit keeps all owned fixture groups"
27
27
 
28
28
  node - "$TMPDIR_EVAL/audit.json" <<'NODE'
29
29
  const fs = require("node:fs");
@@ -59,6 +59,17 @@ set -uo pipefail
59
59
 
60
60
  ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
61
61
  GATE="$ROOT/scripts/hooks/stop-goal-fit.js"
62
+
63
+ # #440 FIXTURE-GAP: this suite's fixtures were written before #440's per-actor ownership scoping
64
+ # and never establish a per-actor current pointer for the invoking actor -- under a RESOLVED
65
+ # ambient actor (ancestry-derived locally, GITHUB_RUN_ID-derived CI-runtime in CI), stop-goal-fit.js's
66
+ # analyze() now scopes to that actor's own (nonexistent) pointer and never reaches the
67
+ # fixture-under-test at all. This suite is about anti-gaming/gate mechanics, not #440's ownership
68
+ # scoping, so forcing the documented test-only unresolved-actor escape hatch restores EXACTLY this
69
+ # suite's pre-#440 behavior (D3 compat: an unresolved actor keeps the unchanged legacy-fallback/
70
+ # global-scan discovery every assertion below was written against).
71
+ export FLOW_AGENTS_ACTOR_TEST_FORCE_UNRESOLVED=1
72
+ export NODE_ENV=test
62
73
  GATE_SRC="$ROOT/scripts/hooks/stop-goal-fit.js"
63
74
 
64
75
  export FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=100000
@@ -33,6 +33,17 @@ set -uo pipefail
33
33
 
34
34
  ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
35
35
  GATE="$ROOT/scripts/hooks/stop-goal-fit.js"
36
+
37
+ # #440 FIXTURE-GAP: this suite's fixtures were written before #440's per-actor ownership scoping
38
+ # and never establish a per-actor current pointer for the invoking actor -- under a RESOLVED
39
+ # ambient actor (ancestry-derived locally, GITHUB_RUN_ID-derived CI-runtime in CI), stop-goal-fit.js's
40
+ # analyze() now scopes to that actor's own (nonexistent) pointer and never reaches the
41
+ # fixture-under-test at all. This suite is about anti-gaming/gate mechanics, not #440's ownership
42
+ # scoping, so forcing the documented test-only unresolved-actor escape hatch restores EXACTLY this
43
+ # suite's pre-#440 behavior (D3 compat: an unresolved actor keeps the unchanged legacy-fallback/
44
+ # global-scan discovery every assertion below was written against).
45
+ export FLOW_AGENTS_ACTOR_TEST_FORCE_UNRESOLVED=1
46
+ export NODE_ENV=test
36
47
  RESOLVER="$ROOT/build/src/li""b/flow-resolver.js"
37
48
 
38
49
  export FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=100000
@@ -26,6 +26,16 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
26
26
  GATE="$ROOT/scripts/hooks/stop-goal-fit.js"
27
27
  PROT="$ROOT/scripts/hooks/config-protection.js"
28
28
 
29
+ # #440 FIXTURE-GAP: this suite's fixtures were written before #440's per-actor ownership scoping
30
+ # and never establish a per-actor current pointer for the invoking actor -- under a RESOLVED
31
+ # ambient actor (ancestry-derived locally, GITHUB_RUN_ID-derived CI-runtime in CI), stop-goal-fit.js's
32
+ # analyze() now scopes to that actor's own (nonexistent) pointer and never reaches the
33
+ # fixture-under-test at all. This suite is about anti-gaming/gate-lockdown mechanics, not #440's
34
+ # ownership scoping, so forcing the documented test-only unresolved-actor escape hatch restores
35
+ # EXACTLY this suite's pre-#440 behavior (D3 compat: an unresolved actor keeps the unchanged
36
+ # legacy-fallback/global-scan discovery every assertion below was written against).
37
+ export FLOW_AGENTS_ACTOR_TEST_FORCE_UNRESOLVED=1
38
+ export NODE_ENV=test
29
39
  export FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=100000
30
40
 
31
41
  TMP="$(mktemp -d)"
@@ -17,6 +17,17 @@ set -uo pipefail
17
17
  ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
18
18
  HOOK="$ROOT/scripts/hooks/stop-goal-fit.js"
19
19
 
20
+ # #440 FIXTURE-GAP: this suite's fixtures were written before #440's per-actor ownership scoping
21
+ # and never establish a per-actor current pointer for the invoking actor -- under a RESOLVED
22
+ # ambient actor (ancestry-derived locally, GITHUB_RUN_ID-derived CI-runtime in CI), stop-goal-fit.js's
23
+ # analyze() now scopes to that actor's own (nonexistent) pointer and never reaches the
24
+ # fixture-under-test at all. This suite is about anti-gaming/gate mechanics, not #440's ownership
25
+ # scoping, so forcing the documented test-only unresolved-actor escape hatch restores EXACTLY this
26
+ # suite's pre-#440 behavior (D3 compat: an unresolved actor keeps the unchanged legacy-fallback/
27
+ # global-scan discovery every assertion below was written against).
28
+ export FLOW_AGENTS_ACTOR_TEST_FORCE_UNRESOLVED=1
29
+ export NODE_ENV=test
30
+
20
31
  TMP="$(mktemp -d)"
21
32
  errors=0
22
33
  _pass() { echo " PASS: $1"; }
@@ -3,6 +3,18 @@
3
3
  set -uo pipefail
4
4
 
5
5
  ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
6
+ # #440 FIXTURE-GAP: this suite's fixtures were written before #440's per-actor ownership scoping
7
+ # and never establish a per-actor current pointer for the invoking actor (no ensure-session/
8
+ # workflow-start call anywhere in this file) -- under a RESOLVED ambient actor (ancestry-derived
9
+ # locally, GITHUB_RUN_ID-derived CI-runtime in CI), stop-goal-fit.js's analyze() now scopes to
10
+ # that actor's own (nonexistent) pointer and never reaches the fixture-under-test at all. This
11
+ # suite is about goal-fit gate mechanics, not #440's ownership scoping, so forcing the documented
12
+ # test-only unresolved-actor escape hatch restores EXACTLY this suite's pre-#440 behavior (D3
13
+ # compat: an unresolved actor keeps the unchanged legacy-fallback/global-scan discovery every
14
+ # assertion below was written against).
15
+ export FLOW_AGENTS_ACTOR_TEST_FORCE_UNRESOLVED=1
16
+ export NODE_ENV=test
17
+
6
18
  source "$ROOT/evals/lib/node.sh"
7
19
 
8
20
  # These checks exercise the block mechanism repeatedly against the same workspace
@@ -977,30 +989,31 @@ else
977
989
  _fail "hook leaked tsc error into goal-fit output"
978
990
  fi
979
991
 
980
- # Part 2 of fix: when the validator cannot run at all (build/ absent and npm fails),
981
- # the hook must skip cleanly never block in strict mode due to an env error.
992
+ # Part 2 of fix: when the hook-owned build is absent, the hook must skip cleanly
993
+ # without executing npm or any other PATH-discovered fallback.
982
994
  mv "$ROOT/build" "$ROOT/build-absent"
983
995
 
984
996
  SPAWN_FAIL_DIR="$TMPDIR_EVAL/spawn-fail"
997
+ SPAWN_FAIL_MARKER="$TMPDIR_EVAL/path-npm-was-executed"
985
998
  mkdir -p "$SPAWN_FAIL_DIR"
986
- printf '#!/usr/bin/env bash\necho "npm ERR! tsc: command not found" >&2\nexit 127\n' > "$SPAWN_FAIL_DIR/npm"
999
+ printf '#!/usr/bin/env bash\nprintf "ran\\n" > "$SPAWN_FAIL_MARKER"\nexit 127\n' > "$SPAWN_FAIL_DIR/npm"
987
1000
  chmod +x "$SPAWN_FAIL_DIR/npm"
988
1001
 
989
- if PATH="$SPAWN_FAIL_DIR:$PATH" FLOW_AGENTS_GOAL_FIT_STRICT=true FLOW_AGENTS_REQUIRE_SIDECARS=true \
1002
+ if PATH="$SPAWN_FAIL_DIR:$PATH" SPAWN_FAIL_MARKER="$SPAWN_FAIL_MARKER" FLOW_AGENTS_GOAL_FIT_STRICT=true FLOW_AGENTS_REQUIRE_SIDECARS=true \
990
1003
  node "$ROOT/scripts/hooks/stop-goal-fit.js" \
991
1004
  >"$TMPDIR_EVAL/npm-install-env-err.out" 2>"$TMPDIR_EVAL/npm-install-env-err.err" <<JSON
992
1005
  {"hook_event_name":"Stop","cwd":"$NPM_INSTALL_REPO"}
993
1006
  JSON
994
1007
  then
995
- _pass "strict hook does not block when validator environment fails (build/ absent, tsc missing)"
1008
+ _pass "strict hook does not block when its hook-owned validator build is unavailable"
996
1009
  else
997
- _fail "strict hook must not block when validator env fails: $(cat "$TMPDIR_EVAL/npm-install-env-err.err")"
1010
+ _fail "strict hook must not block when its validator build is unavailable: $(cat "$TMPDIR_EVAL/npm-install-env-err.err")"
998
1011
  fi
999
1012
 
1000
- if rg -q 'sidecar validation skipped' "$TMPDIR_EVAL/npm-install-env-err.err"; then
1001
- _pass "hook emits sidecar validation skipped warning for environment errors"
1013
+ if [ ! -e "$SPAWN_FAIL_MARKER" ] && rg -q 'sidecar validation skipped' "$TMPDIR_EVAL/npm-install-env-err.err"; then
1014
+ _pass "unavailable validator is disclosed without executing a PATH-provided npm fallback"
1002
1015
  else
1003
- _fail "hook did not emit 'sidecar validation skipped' for environment errors"
1016
+ _fail "hook executed PATH npm or hid the unavailable-validator warning"
1004
1017
  fi
1005
1018
 
1006
1019
  # Restore build/ so subsequent evals are unaffected.
@@ -2764,6 +2777,241 @@ else
2764
2777
  _fail "strict goal-fit hook did not report malformed canonical Flow state: $(cat "$TMPDIR_EVAL/canonical-malformed.err")"
2765
2778
  fi
2766
2779
 
2780
+ # A live driver turn may return from one ordinary active Flow gate, but the
2781
+ # exception is strictly record-bound. It must not release assignment/liveness
2782
+ # (releaseOnNonTerminalStop sees the active canonical run) or hide a hard
2783
+ # evidence failure.
2784
+ AUTHORITY_REPO="$TMPDIR_EVAL/continuation-authority-repo"
2785
+ AUTHORITY_SESSION="$AUTHORITY_REPO/.kontourai/flow-agents/continuation-authority"
2786
+ mkdir -p "$AUTHORITY_SESSION/continuation-driver/locks" "$AUTHORITY_REPO/.kontourai/flow/runs/continuation-authority"
2787
+ printf '# Test Repo\n' > "$AUTHORITY_REPO/AGENTS.md"
2788
+ cat > "$AUTHORITY_SESSION/continuation-authority--deliver.md" <<'MARKDOWN'
2789
+ # Continuation authority fixture
2790
+
2791
+ status: planned
2792
+ type: deliver
2793
+ MARKDOWN
2794
+ cat > "$AUTHORITY_SESSION/state.json" <<'JSON'
2795
+ {
2796
+ "schema_version": "1.0",
2797
+ "task_slug": "continuation-authority",
2798
+ "status": "planned",
2799
+ "phase": "planning",
2800
+ "updated_at": "2026-07-13T00:00:00.000Z",
2801
+ "flow_run": { "status": "active", "run_id": "continuation-authority", "definition_id": "builder.build", "definition_version": "1.0", "current_step": "pull-work", "run_ref": ".kontourai/flow/runs/continuation-authority", "open_gate_ids": ["pull-work-gate"] },
2802
+ "next_action": { "status": "continue", "summary": "Continue the canonical gate." }
2803
+ }
2804
+ JSON
2805
+ cat > "$AUTHORITY_REPO/.kontourai/flow-agents/current.json" <<'JSON'
2806
+ { "active_slug": "continuation-authority" }
2807
+ JSON
2808
+ cat > "$AUTHORITY_REPO/.kontourai/flow/runs/continuation-authority/state.json" <<'JSON'
2809
+ { "run_id": "continuation-authority", "definition_id": "builder.build", "definition_version": "1.0", "status": "active", "current_step": "pull-work" }
2810
+ JSON
2811
+ cat > "$AUTHORITY_REPO/.kontourai/flow/runs/continuation-authority/definition.json" <<'JSON'
2812
+ { "id": "builder.build", "version": "1.0", "steps": [{ "id": "pull-work" }, { "id": "design-probe" }] }
2813
+ JSON
2814
+ AUTHORITY_PID="$$"
2815
+ AUTHORITY_TOKEN="authority-lock"
2816
+ AUTHORITY_ENV="$TMPDIR_EVAL/continuation-authority-env.json"
2817
+ AUTHORITY_REPO="$AUTHORITY_REPO" AUTHORITY_SESSION="$AUTHORITY_SESSION" AUTHORITY_PID="$AUTHORITY_PID" AUTHORITY_TOKEN="$AUTHORITY_TOKEN" AUTHORITY_ENV="$AUTHORITY_ENV" AUTHORITY_ROOT="$ROOT" node - <<'NODE'
2818
+ const fs = require('fs');
2819
+ const path = require('path');
2820
+ const issued = new Date();
2821
+ const lock = { schema_version: '1.0', pid: Number(process.env.AUTHORITY_PID), token: process.env.AUTHORITY_TOKEN, created_at: issued.toISOString() };
2822
+ fs.writeFileSync(path.join(process.env.AUTHORITY_SESSION, 'continuation-driver', 'locks', `${lock.pid}-${lock.token}.lock`), `${JSON.stringify(lock)}\n`);
2823
+ fs.writeFileSync(path.join(process.env.AUTHORITY_SESSION, 'continuation-driver', 'state.json'), JSON.stringify({
2824
+ schema_version: '1.0', run_id: 'continuation-authority', definition_id: 'builder.build', max_turns: 2,
2825
+ adapter_command_identity: 'adapter-identity', status: 'active', turns_started: 1, active_turn_step: 'pull-work', pending_barrier: null,
2826
+ }));
2827
+ const actor = { runtime: 'explicit-override', session_id: 'driver-actor', host: 'fixture-host', human: null };
2828
+ const assignment = path.join(process.env.AUTHORITY_REPO, '.kontourai', 'flow-agents', 'assignment', 'continuation-authority.json');
2829
+ fs.mkdirSync(path.dirname(assignment), { recursive: true });
2830
+ fs.writeFileSync(assignment, JSON.stringify({ schema_version: '1.0', role: 'AssignmentClaimRecord', subject_id: 'continuation-authority', actor, actor_key: 'driver-actor', artifact_dir: 'continuation-authority', status: 'claimed' }));
2831
+ const authority = require(path.join(process.env.AUTHORITY_ROOT, 'scripts', 'hooks', 'lib', 'continuation-turn-authority.js'));
2832
+ const turn = authority.issueActiveTurnAuthority({ sessionDir: process.env.AUTHORITY_SESSION, runId: 'continuation-authority', definitionId: 'builder.build', currentStep: 'pull-work', iteration: 1, maxTurns: 2, adapterCommandIdentity: 'adapter-identity', assignmentActor: 'driver-actor', assignmentActorStruct: actor, lock, timeoutMs: 60_000 });
2833
+ const missionFile = path.join(process.env.AUTHORITY_SESSION, 'continuation-driver', 'state.json');
2834
+ const mission = JSON.parse(fs.readFileSync(missionFile, 'utf8'));
2835
+ fs.writeFileSync(missionFile, JSON.stringify({ ...mission, active_turn_public_key_digest: turn.publicKeyDigest }));
2836
+ fs.writeFileSync(process.env.AUTHORITY_ENV, JSON.stringify({ runId: turn.runId, turnSecret: turn.turnSecret }));
2837
+ NODE
2838
+ AUTHORITY_TURN_SECRET="$(node -p "require(process.argv[1]).turnSecret" "$AUTHORITY_ENV")"
2839
+ AUTHORITY_RUN_ID="$(node -p "require(process.argv[1]).runId" "$AUTHORITY_ENV")"
2840
+ cat > "$AUTHORITY_REPO/.kontourai/flow/runs/continuation-authority/state.json" <<'JSON'
2841
+ { "run_id": "continuation-authority", "definition_id": "builder.build", "definition_version": "1.0", "status": "active", "current_step": "design-probe" }
2842
+ JSON
2843
+ if FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_CONTINUATION_TURN_SECRET="$AUTHORITY_TURN_SECRET" FLOW_AGENTS_CONTINUATION_RUN_ID="$AUTHORITY_RUN_ID" node "$ROOT/scripts/hooks/stop-goal-fit.js" >"$TMPDIR_EVAL/authority-valid.out" 2>"$TMPDIR_EVAL/authority-valid.err" <<JSON
2844
+ {"hook_event_name":"Stop","cwd":"$AUTHORITY_REPO"}
2845
+ JSON
2846
+ then
2847
+ _pass "a matching live continuation authority makes only the ordinary active Flow gate advisory"
2848
+ else
2849
+ _fail "matching continuation authority did not return control to the driver: $(cat "$TMPDIR_EVAL/authority-valid.err")"
2850
+ fi
2851
+ if grep -q 'continuation driver active turn is authorized' "$TMPDIR_EVAL/authority-valid.err"; then
2852
+ _pass "authorized continuation turn remains observable in Goal Fit output"
2853
+ else
2854
+ _fail "authorized continuation turn was not disclosed: $(cat "$TMPDIR_EVAL/authority-valid.err")"
2855
+ fi
2856
+ AUTHORITY_CONSUMER_MARKER="$TMPDIR_EVAL/authority-consumer-validator-ran"
2857
+ mkdir -p "$AUTHORITY_REPO/build/src/cli"
2858
+ cat > "$AUTHORITY_REPO/package.json" <<'JSON'
2859
+ {
2860
+ "name": "@kontourai/flow-agents",
2861
+ "private": true,
2862
+ "scripts": {
2863
+ "test": "node --test",
2864
+ "workflow:validate-artifacts": "node -e \"require('fs').writeFileSync(process.env.AUTHORITY_CONSUMER_MARKER, 'ran')\""
2865
+ }
2866
+ }
2867
+ JSON
2868
+ cat > "$AUTHORITY_REPO/build/src/cli/validate-workflow-artifacts.js" <<'JS'
2869
+ require('fs').writeFileSync(process.env.AUTHORITY_CONSUMER_MARKER, 'ran');
2870
+ process.exit(0);
2871
+ JS
2872
+ if AUTHORITY_CONSUMER_MARKER="$AUTHORITY_CONSUMER_MARKER" FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_CONTINUATION_TURN_SECRET="$AUTHORITY_TURN_SECRET" FLOW_AGENTS_CONTINUATION_RUN_ID="$AUTHORITY_RUN_ID" node "$ROOT/scripts/hooks/stop-goal-fit.js" >"$TMPDIR_EVAL/authority-consumer-package.out" 2>"$TMPDIR_EVAL/authority-consumer-package.err" <<JSON
2873
+ {"hook_event_name":"Stop","cwd":"$AUTHORITY_REPO"}
2874
+ JSON
2875
+ then
2876
+ if [ ! -e "$AUTHORITY_CONSUMER_MARKER" ]; then
2877
+ _pass "authorized continuation uses only the hook-owned validator, never a same-name consumer package"
2878
+ else
2879
+ _fail "hook executed a consumer-controlled same-name validator"
2880
+ fi
2881
+ else
2882
+ _fail "consumer package.json trapped an authorized continuation turn: $(cat "$TMPDIR_EVAL/authority-consumer-package.err")"
2883
+ fi
2884
+ printf '{}\n' > "$AUTHORITY_SESSION/handoff.json"
2885
+ if FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_CONTINUATION_TURN_SECRET="$AUTHORITY_TURN_SECRET" FLOW_AGENTS_CONTINUATION_RUN_ID="$AUTHORITY_RUN_ID" node "$ROOT/scripts/hooks/stop-goal-fit.js" >"$TMPDIR_EVAL/authority-validator-finding.out" 2>"$TMPDIR_EVAL/authority-validator-finding.err" <<JSON
2886
+ {"hook_event_name":"Stop","cwd":"$AUTHORITY_REPO"}
2887
+ JSON
2888
+ then
2889
+ _fail "authorized continuation bypassed a real hook-owned validator finding"
2890
+ elif [[ "$?" -eq 2 ]] && grep -q 'sidecar validation:' "$TMPDIR_EVAL/authority-validator-finding.err"; then
2891
+ _pass "authorized continuation preserves real hook-owned validator findings as hard blocks"
2892
+ else
2893
+ _fail "hook-owned validator finding returned an unexpected result: $(cat "$TMPDIR_EVAL/authority-validator-finding.err")"
2894
+ fi
2895
+ rm -f "$AUTHORITY_SESSION/handoff.json"
2896
+ AUTHORITY_BUNDLE_DIST="$TMPDIR_EVAL/continuation-authority-bundles"
2897
+ if (cd "$ROOT" && FLOW_AGENTS_DIST_DIR="$AUTHORITY_BUNDLE_DIST" node build/src/cli.js build-bundles) >"$TMPDIR_EVAL/authority-bundle-build.out" 2>"$TMPDIR_EVAL/authority-bundle-build.err"; then
2898
+ _pass "continuation authority fixture builds the shipped Codex bundle layout"
2899
+ else
2900
+ _fail "continuation authority fixture could not build a Codex bundle: $(cat "$TMPDIR_EVAL/authority-bundle-build.err")"
2901
+ fi
2902
+ AUTHORITY_INSTALLED_HOME="$AUTHORITY_BUNDLE_DIST/codex"
2903
+ AUTHORITY_FAKE_PATH="$TMPDIR_EVAL/authority-hostile-path"
2904
+ AUTHORITY_PATH_MARKER="$TMPDIR_EVAL/authority-path-validator-ran"
2905
+ mkdir -p "$AUTHORITY_FAKE_PATH"
2906
+ cat > "$AUTHORITY_FAKE_PATH/flow-agents" <<'SH'
2907
+ #!/usr/bin/env bash
2908
+ printf 'ran\n' > "$AUTHORITY_PATH_MARKER"
2909
+ SH
2910
+ chmod +x "$AUTHORITY_FAKE_PATH/flow-agents"
2911
+ if PATH="$AUTHORITY_FAKE_PATH:$PATH" AUTHORITY_PATH_MARKER="$AUTHORITY_PATH_MARKER" FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_CONTINUATION_TURN_SECRET="$AUTHORITY_TURN_SECRET" FLOW_AGENTS_CONTINUATION_RUN_ID="$AUTHORITY_RUN_ID" node "$AUTHORITY_INSTALLED_HOME/scripts/hooks/stop-goal-fit.js" >"$TMPDIR_EVAL/authority-installed-hook.out" 2>"$TMPDIR_EVAL/authority-installed-hook.err" <<JSON
2912
+ {"hook_event_name":"Stop","cwd":"$AUTHORITY_REPO"}
2913
+ JSON
2914
+ then
2915
+ if [ ! -e "$AUTHORITY_PATH_MARKER" ] && [ ! -e "$AUTHORITY_CONSUMER_MARKER" ] && ! grep -q 'Flow Agents validator is unavailable' "$TMPDIR_EVAL/authority-installed-hook.err"; then
2916
+ _pass "bundle-installed continuation hook uses its own compiled validator and ignores PATH code"
2917
+ else
2918
+ _fail "bundle-installed hook used untrusted code or failed to recognize its compiled validator"
2919
+ fi
2920
+ else
2921
+ _fail "installed continuation hook trapped a signed driver handback: $(cat "$TMPDIR_EVAL/authority-installed-hook.err")"
2922
+ fi
2923
+ rm -f "$AUTHORITY_REPO/package.json"
2924
+ rm -rf "$AUTHORITY_REPO/build"
2925
+ mv "$AUTHORITY_SESSION/continuation-authority--deliver.md" "$AUTHORITY_SESSION/continuation-authority--deliver.md.saved"
2926
+ if FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_CONTINUATION_TURN_SECRET="$AUTHORITY_TURN_SECRET" FLOW_AGENTS_CONTINUATION_RUN_ID="$AUTHORITY_RUN_ID" node "$ROOT/scripts/hooks/stop-goal-fit.js" >"$TMPDIR_EVAL/authority-no-markdown.out" 2>"$TMPDIR_EVAL/authority-no-markdown.err" <<JSON
2927
+ {"hook_event_name":"Stop","cwd":"$AUTHORITY_REPO"}
2928
+ JSON
2929
+ then
2930
+ _pass "a matching continuation authority returns control before any workflow markdown exists"
2931
+ else
2932
+ _fail "matching continuation authority still required workflow markdown before returning control: $(cat "$TMPDIR_EVAL/authority-no-markdown.err")"
2933
+ fi
2934
+ printf '{"verdict":"fail","checks":[]}\n' > "$AUTHORITY_SESSION/evidence.json"
2935
+ if FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_CONTINUATION_TURN_SECRET="$AUTHORITY_TURN_SECRET" FLOW_AGENTS_CONTINUATION_RUN_ID="$AUTHORITY_RUN_ID" node "$ROOT/scripts/hooks/stop-goal-fit.js" >"$TMPDIR_EVAL/authority-no-markdown-hard.out" 2>"$TMPDIR_EVAL/authority-no-markdown-hard.err" <<JSON
2936
+ {"hook_event_name":"Stop","cwd":"$AUTHORITY_REPO"}
2937
+ JSON
2938
+ then
2939
+ _fail "a no-markdown continuation session bypassed a non-markdown evidence hard block"
2940
+ elif [[ "$?" -eq 2 ]] && grep -q 'evidence verdict:fail' "$TMPDIR_EVAL/authority-no-markdown-hard.err"; then
2941
+ _pass "a no-markdown continuation session still enforces non-markdown evidence hard blocks"
2942
+ else
2943
+ _fail "no-markdown evidence hard block returned an unexpected result: $(cat "$TMPDIR_EVAL/authority-no-markdown-hard.err")"
2944
+ fi
2945
+ rm -f "$AUTHORITY_SESSION/evidence.json"
2946
+ mv "$AUTHORITY_SESSION/continuation-authority--deliver.md.saved" "$AUTHORITY_SESSION/continuation-authority--deliver.md"
2947
+ AUTHORITY_SESSION="$AUTHORITY_SESSION" node - <<'NODE' >/dev/null 2>"$TMPDIR_EVAL/authority-terminal-sidecar-setup.err"
2948
+ const fs = require('fs');
2949
+ const path = require('path');
2950
+ const session = process.env.AUTHORITY_SESSION;
2951
+ const state = JSON.parse(fs.readFileSync(path.join(session, 'state.json'), 'utf8'));
2952
+ fs.writeFileSync(path.join(session, 'state.json'), JSON.stringify({ ...state, status: 'delivered', phase: 'release' }));
2953
+ fs.writeFileSync(path.join(session, 'evidence.json'), JSON.stringify({ verdict: 'pass', checks: [], not_verified_gaps: ['terminal authority FULL_BLOCK-only regression'] }));
2954
+ NODE
2955
+ if AUTHORITY_SESSION="$AUTHORITY_SESSION" AUTHORITY_REPO="$AUTHORITY_REPO" AUTHORITY_TURN_SECRET="$AUTHORITY_TURN_SECRET" AUTHORITY_RUN_ID="$AUTHORITY_RUN_ID" AUTHORITY_ROOT="$ROOT" FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=10 FLOW_AGENTS_CONTINUATION_TURN_SECRET="$AUTHORITY_TURN_SECRET" FLOW_AGENTS_CONTINUATION_RUN_ID="$AUTHORITY_RUN_ID" node - <<'NODE' >"$TMPDIR_EVAL/authority-terminal-sidecar.out" 2>"$TMPDIR_EVAL/authority-terminal-sidecar.err"
2956
+ const assert = require('assert/strict');
2957
+ const hook = require(`${process.env.AUTHORITY_ROOT}/scripts/hooks/stop-goal-fit.js`);
2958
+ (async () => {
2959
+ const analyzed = await hook.analyze(process.env.AUTHORITY_REPO);
2960
+ assert.equal(analyzed.activeTurnAuthority, true, 'fixture authority remains valid');
2961
+ assert.equal(analyzed.blocking, true, 'authorized terminal sidecar evaluates FULL_BLOCK-only gaps');
2962
+ assert.ok(analyzed.warnings.some((warning) => warning.includes('NOT_VERIFIED gap')), 'fixture produced a FULL_BLOCK-only warning');
2963
+ const result = await hook.run(JSON.stringify({ hook_event_name: 'Stop', cwd: process.env.AUTHORITY_REPO }));
2964
+ assert.equal(result.exitCode, 2, 'run preserves the terminal FULL_BLOCK-only block');
2965
+ assert.match(result.stderr, /NOT_VERIFIED gap/);
2966
+ })().catch((error) => { console.error(error.stack || error); process.exitCode = 1; });
2967
+ NODE
2968
+ then
2969
+ _pass "valid continuation authority still blocks a terminal sidecar FULL_BLOCK-only warning through analyze and run"
2970
+ else
2971
+ _fail "authorized terminal sidecar did not preserve the FULL_BLOCK-only warning: $(cat "$TMPDIR_EVAL/authority-terminal-sidecar.out" "$TMPDIR_EVAL/authority-terminal-sidecar.err" "$TMPDIR_EVAL/authority-terminal-sidecar-setup.err")"
2972
+ fi
2973
+ rm -f "$AUTHORITY_SESSION/evidence.json"
2974
+ AUTHORITY_SESSION="$AUTHORITY_SESSION" node - <<'NODE' >/dev/null 2>"$TMPDIR_EVAL/authority-terminal-sidecar-restore.err"
2975
+ const fs = require('fs');
2976
+ const path = require('path');
2977
+ const session = process.env.AUTHORITY_SESSION;
2978
+ const state = JSON.parse(fs.readFileSync(path.join(session, 'state.json'), 'utf8'));
2979
+ fs.writeFileSync(path.join(session, 'state.json'), JSON.stringify({ ...state, status: 'planned', phase: 'planning' }));
2980
+ NODE
2981
+ if FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_ACTOR=driver-actor FLOW_AGENTS_CONTINUATION_TURN_SECRET="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" FLOW_AGENTS_CONTINUATION_RUN_ID="$AUTHORITY_RUN_ID" node "$ROOT/scripts/hooks/stop-goal-fit.js" >"$TMPDIR_EVAL/authority-wrong-secret.out" 2>"$TMPDIR_EVAL/authority-wrong-secret.err" <<JSON
2982
+ {"hook_event_name":"Stop","cwd":"$AUTHORITY_REPO"}
2983
+ JSON
2984
+ then
2985
+ _fail "wrong continuation secret bypassed active Flow Stop blocking"
2986
+ elif [[ "$?" -eq 2 ]]; then
2987
+ _pass "wrong continuation secret preserves active Flow Stop blocking"
2988
+ else
2989
+ _fail "wrong continuation secret returned an unexpected Stop exit code"
2990
+ fi
2991
+ cat > "$AUTHORITY_SESSION/evidence.json" <<'JSON'
2992
+ { "verdict": "fail", "checks": [] }
2993
+ JSON
2994
+ if FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=1 FLOW_AGENTS_CONTINUATION_TURN_SECRET="$AUTHORITY_TURN_SECRET" FLOW_AGENTS_CONTINUATION_RUN_ID="$AUTHORITY_RUN_ID" node "$ROOT/scripts/hooks/stop-goal-fit.js" >"$TMPDIR_EVAL/authority-hard-block.out" 2>"$TMPDIR_EVAL/authority-hard-block.err" <<JSON
2995
+ {"hook_event_name":"Stop","cwd":"$AUTHORITY_REPO"}
2996
+ JSON
2997
+ then
2998
+ _fail "active continuation authority bypassed an evidence hard block"
2999
+ elif [[ "$?" -eq 2 ]] && grep -q 'evidence verdict:fail' "$TMPDIR_EVAL/authority-hard-block.err"; then
3000
+ _pass "active continuation authority preserves evidence hard blocking"
3001
+ else
3002
+ _fail "active continuation authority did not preserve the evidence hard block: $(cat "$TMPDIR_EVAL/authority-hard-block.err")"
3003
+ fi
3004
+ if FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=1 FLOW_AGENTS_CONTINUATION_TURN_SECRET="$AUTHORITY_TURN_SECRET" FLOW_AGENTS_CONTINUATION_RUN_ID="$AUTHORITY_RUN_ID" node "$ROOT/scripts/hooks/stop-goal-fit.js" >"$TMPDIR_EVAL/authority-hard-block-repeat.out" 2>"$TMPDIR_EVAL/authority-hard-block-repeat.err" <<JSON
3005
+ {"hook_event_name":"Stop","cwd":"$AUTHORITY_REPO"}
3006
+ JSON
3007
+ then
3008
+ _fail "nonordinary FULL_BLOCK escaped through max-block release"
3009
+ elif [[ "$?" -eq 2 ]] && grep -q 'max-blocks reached but the block' "$TMPDIR_EVAL/authority-hard-block-repeat.err"; then
3010
+ _pass "nonordinary FULL_BLOCK cannot burn through max-block release"
3011
+ else
3012
+ _fail "nonordinary FULL_BLOCK did not remain hard after max blocks: $(cat "$TMPDIR_EVAL/authority-hard-block-repeat.err")"
3013
+ fi
3014
+
2767
3015
  if cmp -s "$ROOT/scripts/hooks/stop-goal-fit.js" "$ROOT/context/scripts/hooks/stop-goal-fit.js"; then
2768
3016
  _pass "canonical Stop hook source and shipped context mirror remain byte-identical"
2769
3017
  else
@@ -16,6 +16,17 @@
16
16
  set -uo pipefail
17
17
 
18
18
  ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
19
+
20
+ # #440 FIXTURE-GAP: this suite's fixtures were written before #440's per-actor ownership scoping
21
+ # and never establish a per-actor current pointer for the invoking actor -- under a RESOLVED
22
+ # ambient actor (ancestry-derived locally, GITHUB_RUN_ID-derived CI-runtime in CI), stop-goal-fit.js's
23
+ # analyze() now scopes to that actor's own (nonexistent) pointer and never reaches the
24
+ # fixture-under-test at all. This suite is about anti-gaming/gate mechanics, not #440's ownership
25
+ # scoping, so forcing the documented test-only unresolved-actor escape hatch restores EXACTLY this
26
+ # suite's pre-#440 behavior (D3 compat: an unresolved actor keeps the unchanged legacy-fallback/
27
+ # global-scan discovery every assertion below was written against).
28
+ export FLOW_AGENTS_ACTOR_TEST_FORCE_UNRESOLVED=1
29
+ export NODE_ENV=test
19
30
  GATE="$ROOT/scripts/hooks/stop-goal-fit.js"
20
31
 
21
32
  export FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=100000