@kontourai/flow-agents 2.3.0 → 2.4.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.
- package/.github/CODEOWNERS +8 -0
- package/.github/workflows/ci.yml +32 -0
- package/AGENTS.md +4 -4
- package/CHANGELOG.md +39 -0
- package/CONTEXT.md +14 -0
- package/README.md +9 -3
- package/agents/dev.json +1 -1
- package/agents/tool-code-reviewer.json +1 -1
- package/agents/tool-planner.json +3 -3
- package/agents/tool-verifier.json +3 -3
- package/build/src/cli/console-learning-projection.js +3 -2
- package/build/src/cli/init.js +104 -21
- package/build/src/cli/kit.js +37 -6
- package/build/src/cli/pull-work-provider.js +1 -1
- package/build/src/cli/usage-feedback.js +3 -3
- package/build/src/cli/validate-hook-influence.js +1 -0
- package/build/src/cli/validate-workflow-artifacts.js +22 -6
- package/build/src/cli/workflow-artifact-cleanup-audit.js +36 -2
- package/build/src/cli/workflow-sidecar.d.ts +14 -7
- package/build/src/cli/workflow-sidecar.js +792 -69
- package/build/src/flow-kit/validate.d.ts +23 -0
- package/build/src/flow-kit/validate.js +67 -1
- package/build/src/index.d.ts +1 -1
- package/build/src/index.js +1 -1
- package/build/src/lib/flow-resolver.d.ts +6 -4
- package/build/src/lib/flow-resolver.js +125 -58
- package/build/src/lib/local-artifact-root.d.ts +14 -2
- package/build/src/lib/local-artifact-root.js +22 -5
- package/build/src/lib/workflow-learning-projection.js +2 -2
- package/build/src/runtime-adapters.d.ts +12 -0
- package/build/src/runtime-adapters.js +56 -16
- package/build/src/tools/build-universal-bundles.js +49 -16
- package/build/src/tools/generate-context-map.js +10 -8
- package/build/src/tools/validate-source-tree.js +23 -1
- package/console.telemetry.json +22 -0
- package/context/contracts/artifact-contract.md +38 -7
- package/context/contracts/builder-kit-workflow-state-contract.md +3 -2
- package/context/contracts/decision-registry-contract.md +263 -0
- package/context/contracts/delivery-contract.md +1 -1
- package/context/contracts/planning-contract.md +2 -1
- package/context/contracts/review-contract.md +5 -3
- package/context/contracts/verification-contract.md +9 -1
- package/context/contracts/work-item-contract.md +1 -1
- package/context/deferred/parallelization.md +1 -1
- package/context/gate-awareness.md +4 -4
- package/context/scripts/git-status.sh +2 -2
- package/context/scripts/hooks/config-protection.js +502 -2
- package/context/scripts/hooks/lib/config-protection-remedies.js +69 -0
- package/context/scripts/hooks/run-hook.js +14 -1
- package/context/scripts/hooks/stop-goal-fit.js +1140 -99
- package/context/scripts/hooks/workflow-steering.js +212 -6
- package/docs/adr/0007-flow-skill-kit-tool-boundary.md +2 -0
- package/docs/adr/0015-flow-flow-agents-boundary-reconciliation.md +35 -0
- package/docs/adr/0019-kit-dependency-ownership.md +62 -0
- package/docs/adr/0020-trust-reconcile-manifest-and-claim-classification.md +290 -0
- package/docs/adr/0021-assignment-leases-and-stale-claim-takeover.md +221 -0
- package/docs/adr/0022-fail-closed-delivery-reconciliation-with-governed-exemptions.md +283 -0
- package/docs/agent-system-guidebook.md +3 -3
- package/docs/agent-usage-feedback-loop.md +6 -6
- package/docs/context-map.md +9 -7
- package/docs/decisions/decision-records.md +57 -0
- package/docs/decisions/index.md +14 -0
- package/docs/decisions/promotion-gate.md +52 -0
- package/docs/developer-architecture.md +1 -1
- package/docs/fixture-ownership.md +3 -0
- package/docs/flow-kit-repository-contract.md +5 -5
- package/docs/getting-started.md +12 -2
- package/docs/integrations/harness-install.md +2 -1
- package/docs/kit-authoring-guide.md +64 -5
- package/docs/knowledge-kit.md +5 -1
- package/docs/learnings/2026-07-improvement-program.md +203 -0
- package/docs/migrations.md +6 -5
- package/docs/north-star.md +2 -2
- package/docs/operating-layers.md +4 -3
- package/docs/repository-structure.md +5 -5
- package/docs/skills-map.md +8 -8
- package/docs/spec/runtime-hook-surface.md +19 -15
- package/docs/spikes/graph-provider-2026-07.md +155 -0
- package/docs/standards-register.md +7 -7
- package/docs/trust-anchor-adoption.md +105 -4
- package/docs/work-item-adapters.md +1 -1
- package/docs/workflow-artifact-lifecycle.md +72 -9
- package/docs/workflow-eval-strategy.md +3 -3
- package/docs/workflow-shared-contracts.md +1 -1
- package/docs/workflow-usage-guide.md +254 -21
- package/evals/acceptance/DEMO-false-completion.md +20 -11
- package/evals/acceptance/prove-capture-teeth-declared.sh +15 -15
- package/evals/acceptance/prove-capture-teeth.sh +11 -11
- package/evals/acceptance/test_kiro_harness.sh +1 -1
- package/evals/ci/antigaming-suite.sh +5 -0
- package/evals/ci/run-baseline.sh +65 -1
- package/evals/fixtures/flow-kit-repository/invalid-bad-dependency/flows/review.flow.json +26 -0
- package/evals/fixtures/flow-kit-repository/invalid-bad-dependency/kit.json +13 -0
- package/evals/fixtures/flow-kit-repository/valid-with-dependency/flows/review.flow.json +26 -0
- package/evals/fixtures/flow-kit-repository/valid-with-dependency/kit.json +13 -0
- package/evals/fixtures/hook-influence/cases.json +32 -0
- package/evals/fixtures/pull-work-provider/github-issues.json +6 -6
- package/evals/fixtures/trust-reconcile-exploits/fabricated-attestation.json +59 -0
- package/evals/fixtures/trust-reconcile-exploits/no-label-bypass.json +36 -0
- package/evals/fixtures/trust-reconcile-exploits/skip-assumed-bypass.json +59 -0
- package/evals/fixtures/trust-reconcile-exploits/status-misassertion.json +48 -0
- package/evals/fixtures/trust-reconcile-exploits/waived-command-check.json +44 -0
- package/evals/fixtures/trust-reconcile-mixed-bundle/mixed-bundle.json +159 -0
- package/evals/fixtures/trust-reconcile-ws3/ws3-bundle.json +920 -0
- package/evals/integration/test_actor_identity.sh +254 -0
- package/evals/integration/test_builder_step_producers.sh +33 -23
- package/evals/integration/test_bundle_install.sh +22 -16
- package/evals/integration/test_bundle_lifecycle.sh +11 -11
- package/evals/integration/test_captured_fail_reconciliation.sh +50 -50
- package/evals/integration/test_checkpoint_signing.sh +43 -0
- package/evals/integration/test_claim_lookup.sh +4 -4
- package/evals/integration/test_codex_hook_resolution.sh +114 -0
- package/evals/integration/test_command_log_concurrency.sh +8 -8
- package/evals/integration/test_command_log_fork_classification.sh +3 -3
- package/evals/integration/test_command_log_integrity.sh +16 -16
- package/evals/integration/test_console_learning_projection.sh +1 -1
- package/evals/integration/test_dual_emit_flow_step.sh +145 -0
- package/evals/integration/test_enforcer_expects_driven.sh +12 -12
- package/evals/integration/test_evidence_capture_hook.sh +14 -13
- package/evals/integration/test_fixture_retirement_audit.sh +2 -2
- package/evals/integration/test_flow_agents_statusline.sh +2 -2
- package/evals/integration/test_flow_kit_install_git.sh +52 -0
- package/evals/integration/test_flow_kit_repository.sh +2 -0
- package/evals/integration/test_flowdef_session_activation.sh +6 -6
- package/evals/integration/test_flowdef_union_floor_regression.sh +429 -0
- package/evals/integration/test_gate_bypass_chain.sh +52 -40
- package/evals/integration/test_gate_lockdown.sh +97 -73
- package/evals/integration/test_gate_review_inquiry_records.sh +3 -3
- package/evals/integration/test_goal_fit_escape_hatch.sh +10 -10
- package/evals/integration/test_goal_fit_ghost_session.sh +104 -0
- package/evals/integration/test_goal_fit_hook.sh +32 -32
- package/evals/integration/test_goal_fit_rederive.sh +9 -9
- package/evals/integration/test_hook_category_behaviors.sh +103 -0
- package/evals/integration/test_hook_influence_cases.sh +1 -0
- package/evals/integration/test_install_merge.sh +262 -1
- package/evals/integration/test_kit_identity_trust.sh +6 -6
- package/evals/integration/test_liveness_conflict_injection.sh +587 -0
- package/evals/integration/test_liveness_heartbeat.sh +677 -0
- package/evals/integration/test_liveness_verdict.sh +394 -0
- package/evals/integration/test_local_flow_kit_install.sh +15 -0
- package/evals/integration/test_phase_map_and_gate_claim.sh +63 -11
- package/evals/integration/test_promote_gate.sh +178 -0
- package/evals/integration/test_publish_delivery.sh +2 -2
- package/evals/integration/test_pull_work_liveness_preflight.sh +386 -0
- package/evals/integration/test_pull_work_provider.sh +2 -2
- package/evals/integration/test_reconcile_soundness.sh +4 -4
- package/evals/integration/test_resolvefirststep_security.sh +22 -0
- package/evals/integration/test_runtime_adapter_activation.sh +87 -18
- package/evals/integration/test_session_resume_roundtrip.sh +147 -0
- package/evals/integration/test_sidecar_field_preservation.sh +249 -0
- package/evals/integration/test_trust_reconcile.sh +2 -2
- package/evals/integration/test_trust_reconcile_manifest.sh +79 -0
- package/evals/integration/test_trust_reconcile_mixed_bundle.sh +96 -0
- package/evals/integration/test_trust_reconcile_negatives.sh +151 -0
- package/evals/integration/test_usage_feedback_global.sh +5 -5
- package/evals/integration/test_validate_artifacts_portability.sh +60 -0
- package/evals/integration/test_verify_cli.sh +2 -2
- package/evals/integration/test_veritas_governance_kit.sh +117 -0
- package/evals/integration/test_workflow_artifact_cleanup_audit.sh +26 -1
- package/evals/integration/test_workflow_artifacts.sh +33 -0
- package/evals/integration/test_workflow_sidecar_writer.sh +723 -74
- package/evals/integration/test_workflow_steering_hook.sh +175 -5
- package/evals/lib/codex-provider.sh +1 -1
- package/evals/lib/node.sh +19 -1
- package/evals/run.sh +22 -0
- package/evals/static/test_decisions.sh +150 -0
- package/evals/static/test_flowdef_codeowners_coverage.sh +56 -0
- package/evals/static/test_package.sh +19 -10
- package/evals/static/test_universal_bundles.sh +48 -3
- package/evals/static/test_workflow_skills.sh +41 -8
- package/kits/builder/flows/build.flow.json +3 -74
- package/kits/builder/flows/publish-learn.flow.json +90 -0
- package/kits/builder/kit.json +11 -0
- package/kits/builder/skills/builder-shape/SKILL.md +1 -1
- package/kits/builder/skills/deliver/SKILL.md +13 -11
- package/kits/builder/skills/design-probe/SKILL.md +4 -4
- package/kits/builder/skills/evidence-gate/SKILL.md +26 -1
- package/kits/builder/skills/execute-plan/SKILL.md +2 -2
- package/kits/builder/skills/fix-bug/SKILL.md +2 -0
- package/kits/builder/skills/gate-review/SKILL.md +6 -6
- package/kits/builder/skills/idea-to-backlog/SKILL.md +1 -1
- package/kits/builder/skills/learning-review/SKILL.md +7 -7
- package/kits/builder/skills/pickup-probe/SKILL.md +5 -4
- package/kits/builder/skills/plan-work/SKILL.md +27 -5
- package/kits/builder/skills/pull-work/SKILL.md +80 -5
- package/kits/builder/skills/release-readiness/SKILL.md +4 -4
- package/kits/builder/skills/review-work/SKILL.md +24 -1
- package/kits/builder/skills/tdd-workflow/SKILL.md +2 -0
- package/kits/builder/skills/verify-work/SKILL.md +8 -1
- package/kits/catalog.json +6 -0
- package/kits/veritas-governance/adapter/readiness-to-trust-bundle.mjs +178 -0
- package/kits/veritas-governance/docs/README.md +75 -0
- package/kits/veritas-governance/fixtures/readiness/not-ready.readiness-report.json +4645 -0
- package/kits/veritas-governance/fixtures/readiness/ready.readiness-report.json +4403 -0
- package/kits/veritas-governance/flows/readiness-check.flow.json +35 -0
- package/kits/veritas-governance/kit.json +16 -0
- package/package.json +8 -4
- package/packaging/README.md +2 -2
- package/packaging/conformance/fixtures/config-protection--allow-read-state-json.json +20 -0
- package/packaging/conformance/fixtures/config-protection--block-write-state-json.json +20 -0
- package/packaging/conformance/fixtures/stop-goal-fit--block-bundle-disputed-claim.json +1 -1
- package/packaging/conformance/fixtures/stop-goal-fit--block-capture-contradicts-claimed-pass.json +1 -1
- package/packaging/manifest.json +9 -10
- package/schemas/decision-record.schema.json +109 -0
- package/schemas/workflow-evidence.schema.json +1 -1
- package/schemas/workflow-state.schema.json +5 -0
- package/scripts/README.md +8 -3
- package/scripts/check-content-boundary.cjs +1 -1
- package/scripts/check-decisions.cjs +356 -0
- package/scripts/ci/derive-claim-status.mjs +74 -0
- package/scripts/ci/trust-reconcile.js +436 -79
- package/scripts/git-status.sh +2 -2
- package/scripts/hooks/claude-telemetry-hook.js +37 -3
- package/scripts/hooks/codex-telemetry-hook.js +36 -2
- package/scripts/hooks/config-protection.js +102 -30
- package/scripts/hooks/evidence-capture.js +3 -3
- package/scripts/hooks/lib/actor-identity.js +368 -0
- package/scripts/hooks/lib/config-protection-remedies.js +69 -0
- package/scripts/hooks/lib/liveness-heartbeat.js +361 -0
- package/scripts/hooks/lib/liveness-policy.js +127 -0
- package/scripts/hooks/lib/liveness-read.js +105 -12
- package/scripts/hooks/lib/liveness-write.js +46 -0
- package/scripts/hooks/lib/local-artifact-paths.js +12 -6
- package/scripts/hooks/opencode-telemetry-hook.js +27 -1
- package/scripts/hooks/pi-telemetry-hook.js +27 -1
- package/scripts/hooks/stop-goal-fit.js +157 -26
- package/scripts/hooks/workflow-steering.js +77 -3
- package/scripts/install-codex-home.sh +138 -38
- package/scripts/statusline/flow-agents-statusline.js +2 -2
- package/src/cli/console-learning-projection.ts +3 -2
- package/src/cli/init.ts +101 -21
- package/src/cli/kit.ts +37 -6
- package/src/cli/public-api.test.mjs +58 -6
- package/src/cli/pull-work-provider.ts +1 -1
- package/src/cli/trust-bundle-policy-order.test.mjs +87 -0
- package/src/cli/usage-feedback.ts +3 -3
- package/src/cli/validate-hook-influence.ts +1 -0
- package/src/cli/validate-workflow-artifacts.ts +22 -6
- package/src/cli/veritas-readiness-adapter.test.mjs +267 -0
- package/src/cli/workflow-artifact-cleanup-audit.ts +35 -2
- package/src/cli/workflow-sidecar.ts +795 -71
- package/src/flow-kit/validate.ts +74 -1
- package/src/index.ts +6 -2
- package/src/lib/flow-resolver.ts +123 -55
- package/src/lib/local-artifact-root.ts +24 -5
- package/src/lib/workflow-learning-projection.ts +2 -2
- package/src/runtime-adapters.ts +61 -15
- package/src/tools/build-universal-bundles.ts +49 -16
- package/src/tools/generate-context-map.ts +10 -8
- package/src/tools/validate-source-tree.ts +23 -1
|
@@ -42,11 +42,11 @@ trap cleanup EXIT
|
|
|
42
42
|
# ─── Helper: seed a delivered (terminal) workflow artifact ────────────────────
|
|
43
43
|
seed_delivered() { # $1=dir $2=slug
|
|
44
44
|
local p="$1" slug="$2"
|
|
45
|
-
mkdir -p "$p/.flow-agents/$slug"
|
|
45
|
+
mkdir -p "$p/.kontourai/flow-agents/$slug"
|
|
46
46
|
printf '# Repo\n' > "$p/AGENTS.md"
|
|
47
47
|
printf '%s' "{\"schema_version\":\"1.0\",\"task_slug\":\"$slug\",\"status\":\"delivered\",\"phase\":\"done\",\"updated_at\":\"2026-06-27T00:00:00Z\",\"next_action\":{\"status\":\"done\",\"summary\":\"done\"}}" \
|
|
48
|
-
> "$p/.flow-agents/$slug/state.json"
|
|
49
|
-
cat > "$p/.flow-agents/$slug/$slug--deliver.md" << MD
|
|
48
|
+
> "$p/.kontourai/flow-agents/$slug/state.json"
|
|
49
|
+
cat > "$p/.kontourai/flow-agents/$slug/$slug--deliver.md" << MD
|
|
50
50
|
# $slug
|
|
51
51
|
|
|
52
52
|
branch: main
|
|
@@ -71,7 +71,7 @@ write_kit_pass_bundle() { # $1=bundle_path $2=slug $3=claim_value(opt)
|
|
|
71
71
|
import json, sys
|
|
72
72
|
bundle_path, slug, claim_val = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
73
73
|
bundle = {
|
|
74
|
-
"schemaVersion":
|
|
74
|
+
"schemaVersion": 5, "source": "flow-agents/workflow-sidecar",
|
|
75
75
|
"claims": [{
|
|
76
76
|
"id": "c1", "subjectId": slug + "/tests", "subjectType": "flow-step",
|
|
77
77
|
"claimType": "builder.verify.tests",
|
|
@@ -131,10 +131,10 @@ T1="$TMP/t1-bypass"
|
|
|
131
131
|
seed_delivered "$T1" "bypass-kit"
|
|
132
132
|
|
|
133
133
|
# NO active_flow_id in current.json
|
|
134
|
-
printf '%s' '{"artifact_dir":"bypass-kit"}' > "$T1/.flow-agents/current.json"
|
|
134
|
+
printf '%s' '{"artifact_dir":"bypass-kit"}' > "$T1/.kontourai/flow-agents/current.json"
|
|
135
135
|
|
|
136
|
-
write_kit_pass_bundle "$T1/.flow-agents/bypass-kit/trust.bundle" "bypass-kit"
|
|
137
|
-
write_fail_log "$T1/.flow-agents/bypass-kit/command-log.jsonl"
|
|
136
|
+
write_kit_pass_bundle "$T1/.kontourai/flow-agents/bypass-kit/trust.bundle" "bypass-kit"
|
|
137
|
+
write_fail_log "$T1/.kontourai/flow-agents/bypass-kit/command-log.jsonl"
|
|
138
138
|
|
|
139
139
|
echo ""
|
|
140
140
|
echo "--- 1a. PRE-FIX simulation: show the gate was blind ---"
|
|
@@ -208,7 +208,7 @@ seed_delivered "$T2" "nondeclared"
|
|
|
208
208
|
|
|
209
209
|
# current.json: active flow (builder.build/verify)
|
|
210
210
|
printf '%s' '{"artifact_dir":"nondeclared","active_flow_id":"builder.build","active_step_id":"verify"}' \
|
|
211
|
-
> "$T2/.flow-agents/current.json"
|
|
211
|
+
> "$T2/.kontourai/flow-agents/current.json"
|
|
212
212
|
|
|
213
213
|
# Fake flow defs dir (safe, not agent-writable)
|
|
214
214
|
FLOW_DEFS_DIR="$TMP/flows"
|
|
@@ -238,11 +238,11 @@ cat > "$FLOW_DEFS_DIR/builder.build.flow.json" << 'FLOWJSON'
|
|
|
238
238
|
FLOWJSON
|
|
239
239
|
|
|
240
240
|
# Bundle: agent-chosen NON-declared claimType (e.g. "acme.custom.verify") claiming npm test passed
|
|
241
|
-
python3 - "$T2/.flow-agents/nondeclared/trust.bundle" "nondeclared" << 'PY'
|
|
241
|
+
python3 - "$T2/.kontourai/flow-agents/nondeclared/trust.bundle" "nondeclared" << 'PY'
|
|
242
242
|
import json, sys
|
|
243
243
|
bundle_path, slug = sys.argv[1], sys.argv[2]
|
|
244
244
|
bundle = {
|
|
245
|
-
"schemaVersion":
|
|
245
|
+
"schemaVersion": 5, "source": "flow-agents/workflow-sidecar",
|
|
246
246
|
"claims": [{
|
|
247
247
|
"id": "c1", "subjectId": slug + "/tests", "subjectType": "custom",
|
|
248
248
|
"claimType": "acme.custom.verify", # neither workflow.* NOR declared by the flow
|
|
@@ -263,7 +263,7 @@ bundle = {
|
|
|
263
263
|
}
|
|
264
264
|
json.dump(bundle, open(bundle_path, 'w'))
|
|
265
265
|
PY
|
|
266
|
-
write_fail_log "$T2/.flow-agents/nondeclared/command-log.jsonl"
|
|
266
|
+
write_fail_log "$T2/.kontourai/flow-agents/nondeclared/command-log.jsonl"
|
|
267
267
|
|
|
268
268
|
set +e
|
|
269
269
|
t2_out="$(FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_BACKSTOP=skip \
|
|
@@ -293,9 +293,9 @@ echo "=== 3. NO OVER-BLOCK (a): clean session, no captured fails ==="
|
|
|
293
293
|
|
|
294
294
|
T3="$TMP/t3-clean"
|
|
295
295
|
seed_delivered "$T3" "clean-sess"
|
|
296
|
-
printf '%s' '{"artifact_dir":"clean-sess"}' > "$T3/.flow-agents/current.json"
|
|
297
|
-
write_kit_pass_bundle "$T3/.flow-agents/clean-sess/trust.bundle" "clean-sess"
|
|
298
|
-
write_pass_log "$T3/.flow-agents/clean-sess/command-log.jsonl"
|
|
296
|
+
printf '%s' '{"artifact_dir":"clean-sess"}' > "$T3/.kontourai/flow-agents/current.json"
|
|
297
|
+
write_kit_pass_bundle "$T3/.kontourai/flow-agents/clean-sess/trust.bundle" "clean-sess"
|
|
298
|
+
write_pass_log "$T3/.kontourai/flow-agents/clean-sess/command-log.jsonl"
|
|
299
299
|
|
|
300
300
|
set +e
|
|
301
301
|
t3_out="$(run_gate "$T3")"
|
|
@@ -319,13 +319,13 @@ echo "=== 4. NO OVER-BLOCK (b): fail-then-re-run-to-pass (latest capture PASS) =
|
|
|
319
319
|
|
|
320
320
|
T4="$TMP/t4-rerun"
|
|
321
321
|
seed_delivered "$T4" "rerun-pass"
|
|
322
|
-
printf '%s' '{"artifact_dir":"rerun-pass"}' > "$T4/.flow-agents/current.json"
|
|
323
|
-
write_kit_pass_bundle "$T4/.flow-agents/rerun-pass/trust.bundle" "rerun-pass"
|
|
322
|
+
printf '%s' '{"artifact_dir":"rerun-pass"}' > "$T4/.kontourai/flow-agents/current.json"
|
|
323
|
+
write_kit_pass_bundle "$T4/.kontourai/flow-agents/rerun-pass/trust.bundle" "rerun-pass"
|
|
324
324
|
# FAIL first, then PASS (re-run fixed it — latest is PASS)
|
|
325
325
|
{
|
|
326
326
|
printf '%s\n' '{"command":"npm test","observedResult":"fail","exitCode":1,"capturedAt":"2026-06-27T00:00:00Z","source":"test"}'
|
|
327
327
|
printf '%s\n' '{"command":"npm test","observedResult":"pass","exitCode":0,"capturedAt":"2026-06-27T00:00:01Z","source":"test"}'
|
|
328
|
-
} > "$T4/.flow-agents/rerun-pass/command-log.jsonl"
|
|
328
|
+
} > "$T4/.kontourai/flow-agents/rerun-pass/command-log.jsonl"
|
|
329
329
|
|
|
330
330
|
set +e
|
|
331
331
|
t4_out="$(run_gate "$T4")"
|
|
@@ -349,14 +349,14 @@ echo "=== 5. NO OVER-BLOCK (c): acknowledged failure (evidence marks command dis
|
|
|
349
349
|
|
|
350
350
|
T5="$TMP/t5-ack"
|
|
351
351
|
seed_delivered "$T5" "ack-fail"
|
|
352
|
-
printf '%s' '{"artifact_dir":"ack-fail"}' > "$T5/.flow-agents/current.json"
|
|
352
|
+
printf '%s' '{"artifact_dir":"ack-fail"}' > "$T5/.kontourai/flow-agents/current.json"
|
|
353
353
|
|
|
354
354
|
# Bundle: claim acknowledges failure (status=disputed, value=fail)
|
|
355
|
-
python3 - "$T5/.flow-agents/ack-fail/trust.bundle" "ack-fail" << 'PY'
|
|
355
|
+
python3 - "$T5/.kontourai/flow-agents/ack-fail/trust.bundle" "ack-fail" << 'PY'
|
|
356
356
|
import json, sys
|
|
357
357
|
bundle_path, slug = sys.argv[1], sys.argv[2]
|
|
358
358
|
bundle = {
|
|
359
|
-
"schemaVersion":
|
|
359
|
+
"schemaVersion": 5, "source": "flow-agents/workflow-sidecar",
|
|
360
360
|
"claims": [{
|
|
361
361
|
"id": "c1", "subjectId": slug + "/tests", "subjectType": "flow-step",
|
|
362
362
|
"claimType": "builder.verify.tests",
|
|
@@ -379,7 +379,7 @@ bundle = {
|
|
|
379
379
|
}
|
|
380
380
|
json.dump(bundle, open(bundle_path, 'w'))
|
|
381
381
|
PY
|
|
382
|
-
write_fail_log "$T5/.flow-agents/ack-fail/command-log.jsonl"
|
|
382
|
+
write_fail_log "$T5/.kontourai/flow-agents/ack-fail/command-log.jsonl"
|
|
383
383
|
|
|
384
384
|
set +e
|
|
385
385
|
t5_out="$(run_gate "$T5")"
|
|
@@ -403,12 +403,12 @@ echo "=== 6. NO OVER-BLOCK (d): no-command doc/policy session (verified, no exec
|
|
|
403
403
|
echo " (#216 fix: missing-log check must NOT fire when no command was expected)"
|
|
404
404
|
|
|
405
405
|
T6="$TMP/t6-nocommand"
|
|
406
|
-
mkdir -p "$T6/.flow-agents/nocommand"
|
|
406
|
+
mkdir -p "$T6/.kontourai/flow-agents/nocommand"
|
|
407
407
|
printf '# Repo\n' > "$T6/AGENTS.md"
|
|
408
408
|
# State is verified (completing) but no commands were run
|
|
409
409
|
printf '%s' '{"schema_version":"1.0","task_slug":"nocommand","status":"verified","phase":"verification","updated_at":"2026-06-27T00:00:00Z","next_action":{"status":"done","summary":"done"}}' \
|
|
410
|
-
> "$T6/.flow-agents/nocommand/state.json"
|
|
411
|
-
cat > "$T6/.flow-agents/nocommand/nocommand--deliver.md" << 'MD'
|
|
410
|
+
> "$T6/.kontourai/flow-agents/nocommand/state.json"
|
|
411
|
+
cat > "$T6/.kontourai/flow-agents/nocommand/nocommand--deliver.md" << 'MD'
|
|
412
412
|
# nocommand
|
|
413
413
|
|
|
414
414
|
branch: main
|
|
@@ -423,13 +423,13 @@ type: deliver
|
|
|
423
423
|
|
|
424
424
|
### Verdict: PASS
|
|
425
425
|
MD
|
|
426
|
-
printf '%s' '{"artifact_dir":"nocommand"}' > "$T6/.flow-agents/current.json"
|
|
426
|
+
printf '%s' '{"artifact_dir":"nocommand"}' > "$T6/.kontourai/flow-agents/current.json"
|
|
427
427
|
|
|
428
428
|
# Bundle with NO execution.label (doc/policy session — no commands run)
|
|
429
|
-
python3 - "$T6/.flow-agents/nocommand/trust.bundle" << 'PY'
|
|
429
|
+
python3 - "$T6/.kontourai/flow-agents/nocommand/trust.bundle" << 'PY'
|
|
430
430
|
import json, sys
|
|
431
431
|
bundle = {
|
|
432
|
-
"schemaVersion":
|
|
432
|
+
"schemaVersion": 5, "source": "flow-agents/workflow-sidecar",
|
|
433
433
|
"claims": [{
|
|
434
434
|
"id": "c1", "subjectId": "nocommand/review", "subjectType": "workflow-check",
|
|
435
435
|
"claimType": "workflow.check.review", "fieldOrBehavior": "policy doc reviewed",
|
|
@@ -476,11 +476,11 @@ echo " (Two-part dependency: union form ALWAYS enforces workflow.* + empty-ex
|
|
|
476
476
|
echo " emits gate-misconfiguration HARD_BLOCK for empty expects[])"
|
|
477
477
|
|
|
478
478
|
T7="$TMP/t7-empty-expects"
|
|
479
|
-
mkdir -p "$T7/.flow-agents/empty-expects"
|
|
479
|
+
mkdir -p "$T7/.kontourai/flow-agents/empty-expects"
|
|
480
480
|
printf '# Repo\n' > "$T7/AGENTS.md"
|
|
481
481
|
printf '%s' '{"schema_version":"1.0","task_slug":"empty-expects","status":"in_progress","phase":"execution","updated_at":"2026-06-27T00:00:00Z","next_action":{"status":"in_progress","summary":"Testing"}}' \
|
|
482
|
-
> "$T7/.flow-agents/empty-expects/state.json"
|
|
483
|
-
cat > "$T7/.flow-agents/empty-expects/empty-expects--deliver.md" << 'MD'
|
|
482
|
+
> "$T7/.kontourai/flow-agents/empty-expects/state.json"
|
|
483
|
+
cat > "$T7/.kontourai/flow-agents/empty-expects/empty-expects--deliver.md" << 'MD'
|
|
484
484
|
# empty-expects
|
|
485
485
|
|
|
486
486
|
branch: main
|
|
@@ -491,14 +491,14 @@ type: deliver
|
|
|
491
491
|
- [ ] tests pass
|
|
492
492
|
MD
|
|
493
493
|
printf '%s' '{"artifact_dir":"empty-expects","active_flow_id":"builder.build","active_step_id":"verify"}' \
|
|
494
|
-
> "$T7/.flow-agents/current.json"
|
|
494
|
+
> "$T7/.kontourai/flow-agents/current.json"
|
|
495
495
|
|
|
496
496
|
# Bundle with ONLY kit-typed claims (no workflow.*)
|
|
497
|
-
python3 - "$T7/.flow-agents/empty-expects/trust.bundle" "empty-expects" << 'PY'
|
|
497
|
+
python3 - "$T7/.kontourai/flow-agents/empty-expects/trust.bundle" "empty-expects" << 'PY'
|
|
498
498
|
import json, sys
|
|
499
499
|
bundle_path, slug = sys.argv[1], sys.argv[2]
|
|
500
500
|
bundle = {
|
|
501
|
-
"schemaVersion":
|
|
501
|
+
"schemaVersion": 5, "source": "flow-agents/workflow-sidecar",
|
|
502
502
|
"claims": [{
|
|
503
503
|
"id": "c1", "subjectId": slug + "/tests", "subjectType": "flow-step",
|
|
504
504
|
"claimType": "builder.verify.tests",
|
|
@@ -510,7 +510,7 @@ bundle = {
|
|
|
510
510
|
}
|
|
511
511
|
json.dump(bundle, open(bundle_path, 'w'))
|
|
512
512
|
PY
|
|
513
|
-
printf '' > "$T7/.flow-agents/empty-expects/command-log.jsonl"
|
|
513
|
+
printf '' > "$T7/.kontourai/flow-agents/empty-expects/command-log.jsonl"
|
|
514
514
|
|
|
515
515
|
# Fake flow with expects:[] (safe dir, not agent-writable)
|
|
516
516
|
FAKE_FLOWS="$TMP/fake-flows-ac3"
|
|
@@ -566,12 +566,12 @@ echo " PRE-FIX: completing guard skipped reconciliation for non-terminal stat
|
|
|
566
566
|
echo " POST-FIX: guard removed → check runs on every stop (status-independent)"
|
|
567
567
|
|
|
568
568
|
T8="$TMP/t8-status-dodge"
|
|
569
|
-
mkdir -p "$T8/.flow-agents/status-dodge"
|
|
569
|
+
mkdir -p "$T8/.kontourai/flow-agents/status-dodge"
|
|
570
570
|
printf '# Repo\n' > "$T8/AGENTS.md"
|
|
571
571
|
# CRITICAL: status = 'blocked' (non-terminal — pre-fix would have returned [] here)
|
|
572
572
|
printf '%s' '{"schema_version":"1.0","task_slug":"status-dodge","status":"blocked","phase":"executing","updated_at":"2026-06-27T00:00:00Z","next_action":{"status":"in_progress","summary":"running"}}' \
|
|
573
|
-
> "$T8/.flow-agents/status-dodge/state.json"
|
|
574
|
-
cat > "$T8/.flow-agents/status-dodge/status-dodge--deliver.md" << 'MD'
|
|
573
|
+
> "$T8/.kontourai/flow-agents/status-dodge/state.json"
|
|
574
|
+
cat > "$T8/.kontourai/flow-agents/status-dodge/status-dodge--deliver.md" << 'MD'
|
|
575
575
|
# status-dodge
|
|
576
576
|
|
|
577
577
|
branch: main
|
|
@@ -588,11 +588,11 @@ type: deliver
|
|
|
588
588
|
MD
|
|
589
589
|
|
|
590
590
|
# Bundle: kit-typed claim asserting pass for "npm test"
|
|
591
|
-
python3 - "$T8/.flow-agents/status-dodge/trust.bundle" "status-dodge" << 'PY'
|
|
591
|
+
python3 - "$T8/.kontourai/flow-agents/status-dodge/trust.bundle" "status-dodge" << 'PY'
|
|
592
592
|
import json, sys
|
|
593
593
|
bundle_path, slug = sys.argv[1], sys.argv[2]
|
|
594
594
|
bundle = {
|
|
595
|
-
"schemaVersion":
|
|
595
|
+
"schemaVersion": 5, "source": "flow-agents/workflow-sidecar",
|
|
596
596
|
"claims": [{
|
|
597
597
|
"id": "c1", "subjectId": slug + "/tests", "subjectType": "flow-step",
|
|
598
598
|
"claimType": "builder.verify.tests",
|
|
@@ -614,7 +614,7 @@ bundle = {
|
|
|
614
614
|
json.dump(bundle, open(bundle_path, 'w'))
|
|
615
615
|
PY
|
|
616
616
|
# command-log: "npm test" FAIL (latest capture is FAIL — the agent lied)
|
|
617
|
-
write_fail_log "$T8/.flow-agents/status-dodge/command-log.jsonl"
|
|
617
|
+
write_fail_log "$T8/.kontourai/flow-agents/status-dodge/command-log.jsonl"
|
|
618
618
|
|
|
619
619
|
echo ""
|
|
620
620
|
echo "--- 8a. PRE-FIX simulation (completing guard) ---"
|
|
@@ -663,14 +663,14 @@ echo " POST-FIX: Case B removed → incidental fails with no claim NOT blocke
|
|
|
663
663
|
|
|
664
664
|
T9="$TMP/t9-overblock"
|
|
665
665
|
seed_delivered "$T9" "overblock-sess"
|
|
666
|
-
printf '%s' '{"artifact_dir":"overblock-sess"}' > "$T9/.flow-agents/current.json"
|
|
666
|
+
printf '%s' '{"artifact_dir":"overblock-sess"}' > "$T9/.kontourai/flow-agents/current.json"
|
|
667
667
|
# Bundle: only "npm test" claim asserting pass (no claim about the grep incidental fail)
|
|
668
|
-
write_kit_pass_bundle "$T9/.flow-agents/overblock-sess/trust.bundle" "overblock-sess"
|
|
668
|
+
write_kit_pass_bundle "$T9/.kontourai/flow-agents/overblock-sess/trust.bundle" "overblock-sess"
|
|
669
669
|
# Log: "npm test" PASS + incidental "grep --quiet somepattern AGENTS.md" FAIL (exit 1)
|
|
670
670
|
printf '%s\n%s\n' \
|
|
671
671
|
'{"command":"npm test","observedResult":"pass","exitCode":0,"capturedAt":"2026-06-27T00:00:00Z","source":"postToolUse-capture"}' \
|
|
672
672
|
'{"command":"grep --quiet somepattern AGENTS.md","observedResult":"fail","exitCode":1,"capturedAt":"2026-06-27T00:00:01Z","source":"postToolUse-capture"}' \
|
|
673
|
-
> "$T9/.flow-agents/overblock-sess/command-log.jsonl"
|
|
673
|
+
> "$T9/.kontourai/flow-agents/overblock-sess/command-log.jsonl"
|
|
674
674
|
|
|
675
675
|
set +e
|
|
676
676
|
t9_out="$(run_gate "$T9")"
|
|
@@ -708,13 +708,13 @@ echo " POST-FIX: latest-wins → re-run to PASS clears the block"
|
|
|
708
708
|
|
|
709
709
|
T10="$TMP/t10-fixpass"
|
|
710
710
|
seed_delivered "$T10" "fixpass-sess"
|
|
711
|
-
printf '%s' '{"artifact_dir":"fixpass-sess"}' > "$T10/.flow-agents/current.json"
|
|
712
|
-
write_kit_pass_bundle "$T10/.flow-agents/fixpass-sess/trust.bundle" "fixpass-sess"
|
|
711
|
+
printf '%s' '{"artifact_dir":"fixpass-sess"}' > "$T10/.kontourai/flow-agents/current.json"
|
|
712
|
+
write_kit_pass_bundle "$T10/.kontourai/flow-agents/fixpass-sess/trust.bundle" "fixpass-sess"
|
|
713
713
|
# Log: FAIL first, then PASS (genuine fix-then-re-run)
|
|
714
714
|
printf '%s\n%s\n' \
|
|
715
715
|
'{"command":"npm test","observedResult":"fail","exitCode":1,"capturedAt":"2026-06-27T00:00:00Z","source":"postToolUse-capture"}' \
|
|
716
716
|
'{"command":"npm test","observedResult":"pass","exitCode":0,"capturedAt":"2026-06-27T00:00:01Z","source":"postToolUse-capture"}' \
|
|
717
|
-
> "$T10/.flow-agents/fixpass-sess/command-log.jsonl"
|
|
717
|
+
> "$T10/.kontourai/flow-agents/fixpass-sess/command-log.jsonl"
|
|
718
718
|
|
|
719
719
|
set +e
|
|
720
720
|
t10_out="$(run_gate "$T10")"
|
|
@@ -747,13 +747,13 @@ echo " POST-FIX: hasLaunderingOperator detects || true → 'exit-code-launder
|
|
|
747
747
|
|
|
748
748
|
T11="$TMP/t11-laundering"
|
|
749
749
|
seed_delivered "$T11" "laundering-sess"
|
|
750
|
-
printf '%s' '{"artifact_dir":"laundering-sess"}' > "$T11/.flow-agents/current.json"
|
|
750
|
+
printf '%s' '{"artifact_dir":"laundering-sess"}' > "$T11/.kontourai/flow-agents/current.json"
|
|
751
751
|
# Bundle: claim asserting pass for "npm test || true" — command string has laundering operator
|
|
752
|
-
python3 - "$T11/.flow-agents/laundering-sess/trust.bundle" "laundering-sess" << 'PY'
|
|
752
|
+
python3 - "$T11/.kontourai/flow-agents/laundering-sess/trust.bundle" "laundering-sess" << 'PY'
|
|
753
753
|
import json, sys
|
|
754
754
|
bundle_path, slug = sys.argv[1], sys.argv[2]
|
|
755
755
|
bundle = {
|
|
756
|
-
"schemaVersion":
|
|
756
|
+
"schemaVersion": 5, "source": "flow-agents/workflow-sidecar",
|
|
757
757
|
"claims": [{
|
|
758
758
|
"id": "c1", "subjectId": slug + "/tests", "subjectType": "flow-step",
|
|
759
759
|
"claimType": "builder.verify.tests",
|
|
@@ -777,7 +777,7 @@ PY
|
|
|
777
777
|
# Log: "npm test || true" captured as PASS (exit 0) — the laundering worked
|
|
778
778
|
printf '%s\n' \
|
|
779
779
|
'{"command":"npm test || true","observedResult":"pass","exitCode":0,"capturedAt":"2026-06-27T00:00:00Z","source":"postToolUse-capture"}' \
|
|
780
|
-
> "$T11/.flow-agents/laundering-sess/command-log.jsonl"
|
|
780
|
+
> "$T11/.kontourai/flow-agents/laundering-sess/command-log.jsonl"
|
|
781
781
|
|
|
782
782
|
set +e
|
|
783
783
|
t11_out="$(run_gate "$T11")"
|
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
# This proves the signing PATH is structurally correct without needing real OIDC.
|
|
16
16
|
# 4. ADDITIVE: all existing gating tests still pass (record-release, advance-state-delivered,
|
|
17
17
|
# seal-checkpoint, record-evidence, record-critique all unaffected).
|
|
18
|
+
# 5. NO-CLOBBER (WS5 iteration-2 part 2 regression guard): this eval's scratch sessions
|
|
19
|
+
# (mktemp -d, no kits/ ancestor) never publish into this real repo's delivery/trust.bundle,
|
|
20
|
+
# even when the eval is run from a checkout of this repo — publish-delivery's repo-root
|
|
21
|
+
# resolution is fail-closed and TEST 2 passes an explicit scratch --repo-root.
|
|
18
22
|
#
|
|
19
23
|
# Deterministic, no model spend, no network, self-cleaning.
|
|
20
24
|
# Usage: bash evals/integration/test_checkpoint_signing.sh
|
|
@@ -34,6 +38,19 @@ _fail() { echo " ✗ $1"; errors=$((errors + 1)); }
|
|
|
34
38
|
cleanup() { rm -rf "$TMP"; }
|
|
35
39
|
trap cleanup EXIT
|
|
36
40
|
|
|
41
|
+
# REGRESSION GUARD (WS5 iteration-2 part 2): this eval's scratch sessions live under a
|
|
42
|
+
# mktemp -d tree with no kits/ ancestor. Before the fail-closed fix to
|
|
43
|
+
# findRepoRootFromDir/publishDelivery in src/cli/workflow-sidecar.ts, a scratch session's
|
|
44
|
+
# record-release / advance-state --status delivered call would silently fall back to
|
|
45
|
+
# process.cwd() for its delivery/ repo-root — and when this eval runs from a checkout of
|
|
46
|
+
# THIS repo (as it does under npm run eval:static / the integration suite), that clobbered
|
|
47
|
+
# the real repo's own delivery/trust.bundle with scratch fixture content. Capture this real
|
|
48
|
+
# repo's delivery/trust.bundle content hash now (before any scratch session in this eval
|
|
49
|
+
# runs) and re-check it is byte-identical after every test below.
|
|
50
|
+
REAL_DELIVERY_BUNDLE="$ROOT/delivery/trust.bundle"
|
|
51
|
+
_bundle_hash() { if [[ -f "$1" ]]; then shasum -a 256 "$1" | awk '{print $1}'; else echo "absent"; fi; }
|
|
52
|
+
REAL_DELIVERY_HASH_BEFORE="$(_bundle_hash "$REAL_DELIVERY_BUNDLE")"
|
|
53
|
+
|
|
37
54
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
38
55
|
echo ""
|
|
39
56
|
echo "=== TEST 1: Statement produced with correct subject (sha256 of checkpoint) ==="
|
|
@@ -242,6 +259,14 @@ SLUG2="sign-test-failopen"
|
|
|
242
259
|
SESSION_DIR2="$AROOT2/$SLUG2"
|
|
243
260
|
mkdir -p "$AROOT2"
|
|
244
261
|
|
|
262
|
+
# REGRESSION FIX (WS5 iteration-2 part 2): this session dir has no kits/ ancestor of its
|
|
263
|
+
# own (it lives under $TMP). Pass an explicit --repo-root pointing at a scratch repo-root
|
|
264
|
+
# under $TMP so advance-state --status delivered's auto-publish never has to fall back to
|
|
265
|
+
# (or, pre-fix, silently trust) process.cwd() — matching test_publish_delivery.sh's pattern
|
|
266
|
+
# of always giving its scratch sessions an explicit repo-root.
|
|
267
|
+
REPO_ROOT2="$TMP/test2/scratch-repo"
|
|
268
|
+
mkdir -p "$REPO_ROOT2"
|
|
269
|
+
|
|
245
270
|
flow_agents_node "$WRITER" ensure-session \
|
|
246
271
|
--artifact-root "$AROOT2" \
|
|
247
272
|
--task-slug "$SLUG2" \
|
|
@@ -264,6 +289,7 @@ flow_agents_node "$WRITER" advance-state "$SESSION_DIR2" \
|
|
|
264
289
|
--status delivered \
|
|
265
290
|
--phase release \
|
|
266
291
|
--summary "Delivered." \
|
|
292
|
+
--repo-root "$REPO_ROOT2" \
|
|
267
293
|
--timestamp "2026-06-26T11:03:00Z" >/dev/null 2>&1 || SEAL_EXIT=$?
|
|
268
294
|
|
|
269
295
|
if [[ "$SEAL_EXIT" -eq 0 ]]; then
|
|
@@ -272,6 +298,12 @@ else
|
|
|
272
298
|
_fail "advance-state --status delivered exited $SEAL_EXIT (signing must not break the seal)"
|
|
273
299
|
fi
|
|
274
300
|
|
|
301
|
+
if [[ -f "$REPO_ROOT2/delivery/trust.bundle" ]]; then
|
|
302
|
+
_pass "publish-delivery published into the explicit scratch --repo-root ($REPO_ROOT2/delivery/trust.bundle), not process.cwd()"
|
|
303
|
+
else
|
|
304
|
+
_fail "publish-delivery did not write to the explicit scratch --repo-root ($REPO_ROOT2/delivery/trust.bundle) — check the --repo-root plumbing in advanceState"
|
|
305
|
+
fi
|
|
306
|
+
|
|
275
307
|
if [[ -f "$SESSION_DIR2/trust.checkpoint.json" ]]; then
|
|
276
308
|
_pass "trust.checkpoint.json written even when signing is fail-open"
|
|
277
309
|
else
|
|
@@ -477,6 +509,17 @@ else
|
|
|
477
509
|
_fail "Increment A checkpoint envelope shape broken (regression)"
|
|
478
510
|
fi
|
|
479
511
|
|
|
512
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
513
|
+
echo ""
|
|
514
|
+
echo "=== TEST 5: Regression — this eval's scratch sessions never touch the real repo's delivery/trust.bundle ==="
|
|
515
|
+
|
|
516
|
+
REAL_DELIVERY_HASH_AFTER="$(_bundle_hash "$REAL_DELIVERY_BUNDLE")"
|
|
517
|
+
if [[ "$REAL_DELIVERY_HASH_AFTER" == "$REAL_DELIVERY_HASH_BEFORE" ]]; then
|
|
518
|
+
_pass "real repo delivery/trust.bundle unchanged by this eval's scratch sessions (before=$REAL_DELIVERY_HASH_BEFORE after=$REAL_DELIVERY_HASH_AFTER)"
|
|
519
|
+
else
|
|
520
|
+
_fail "real repo delivery/trust.bundle CHANGED during this eval (before=$REAL_DELIVERY_HASH_BEFORE after=$REAL_DELIVERY_HASH_AFTER) — a scratch session's publish-delivery clobbered $REAL_DELIVERY_BUNDLE"
|
|
521
|
+
fi
|
|
522
|
+
|
|
480
523
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
481
524
|
echo ""
|
|
482
525
|
echo "────────────────────────────────────────────"
|
|
@@ -46,14 +46,14 @@ seed_disputed_bundle() {
|
|
|
46
46
|
mkdir -p "$dir"
|
|
47
47
|
cat > "$dir/trust.bundle" <<JSON
|
|
48
48
|
{
|
|
49
|
-
"schemaVersion":
|
|
49
|
+
"schemaVersion": 5,
|
|
50
50
|
"source": "claim-lookup-test;statusFunctionVersion=1",
|
|
51
51
|
"claims": [
|
|
52
52
|
{
|
|
53
53
|
"id": "$claimId",
|
|
54
54
|
"subjectType": "workflow-check",
|
|
55
55
|
"subjectId": "${slug}/unit-tests",
|
|
56
|
-
"
|
|
56
|
+
"facet": "flow-agents.workflow",
|
|
57
57
|
"claimType": "workflow.check.test",
|
|
58
58
|
"fieldOrBehavior": "unit tests pass",
|
|
59
59
|
"value": "fail",
|
|
@@ -255,14 +255,14 @@ mkdir -p "$AC5_DIR"
|
|
|
255
255
|
# won't match any evidence check id and bundleEnforcement won't be deduped.
|
|
256
256
|
cat > "$AC5_DIR/trust.bundle" <<'BUNDLE'
|
|
257
257
|
{
|
|
258
|
-
"schemaVersion":
|
|
258
|
+
"schemaVersion": 5,
|
|
259
259
|
"source": "claim-lookup-test",
|
|
260
260
|
"claims": [
|
|
261
261
|
{
|
|
262
262
|
"id": "gate-hint-test/AC1.flow-agents.workflow.acceptance criterion verified",
|
|
263
263
|
"subjectType": "workflow-criterion",
|
|
264
264
|
"subjectId": "gate-hint-test/AC1",
|
|
265
|
-
"
|
|
265
|
+
"facet": "flow-agents.workflow",
|
|
266
266
|
"claimType": "workflow.acceptance.criterion",
|
|
267
267
|
"fieldOrBehavior": "acceptance criterion verified",
|
|
268
268
|
"value": "fail",
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# test_codex_hook_resolution.sh - exercises the literal hooks.json command
|
|
3
|
+
# strings emitted by build-universal-bundles.ts against the CODEX_HOME
|
|
4
|
+
# resolution edge cases that a live Codex session actually hits: CODEX_HOME
|
|
5
|
+
# unset/stale, and cwd being an unrelated project rather than this repo.
|
|
6
|
+
#
|
|
7
|
+
# Coverage gap this closes: test_codex_harness.sh only runs when a `codex`
|
|
8
|
+
# binary is on PATH (it skips-as-pass otherwise, and no CI workflow installs
|
|
9
|
+
# one), and every other hook eval calls the underlying script directly
|
|
10
|
+
# (e.g. `node scripts/hooks/stop-goal-fit.js`), bypassing the bash -lc
|
|
11
|
+
# CODEX_HOME resolver in hooks.json entirely. Neither ever caught a resolver
|
|
12
|
+
# bug, which is exactly what shipped: every hook exited 1 in real usage
|
|
13
|
+
# whenever CODEX_HOME wasn't exported into the hook's process and the
|
|
14
|
+
# project cwd didn't happen to vendor scripts/hooks itself.
|
|
15
|
+
set -uo pipefail
|
|
16
|
+
|
|
17
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
18
|
+
source "$ROOT/evals/lib/node.sh"
|
|
19
|
+
|
|
20
|
+
errors=0
|
|
21
|
+
TMPDIR_EVAL="$(mktemp -d)"
|
|
22
|
+
trap 'rm -rf "$TMPDIR_EVAL"' EXIT
|
|
23
|
+
|
|
24
|
+
_pass() { echo " ✓ $1"; }
|
|
25
|
+
_fail() { echo " ✗ $1"; errors=$((errors + 1)); }
|
|
26
|
+
|
|
27
|
+
echo "=== Codex Hook Resolution ==="
|
|
28
|
+
echo ""
|
|
29
|
+
|
|
30
|
+
if flow_agents_node scripts/build-universal-bundles.js >/dev/null; then
|
|
31
|
+
_pass "bundle build completed"
|
|
32
|
+
else
|
|
33
|
+
_fail "bundle build failed"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
HOOKS_JSON="$ROOT/dist/codex/.codex/hooks.json"
|
|
37
|
+
if [[ -f "$HOOKS_JSON" ]]; then
|
|
38
|
+
_pass "dist/codex/.codex/hooks.json exists"
|
|
39
|
+
else
|
|
40
|
+
_fail "dist/codex/.codex/hooks.json missing"
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Pull the exact SessionStart workflow-steering command string Codex would run.
|
|
44
|
+
SESSION_START_CMD="$(node -e '
|
|
45
|
+
const hooks = require(process.argv[1]).hooks.SessionStart;
|
|
46
|
+
const entry = hooks.find(group => group.hooks[0].command.includes("codex-hook-adapter.js"));
|
|
47
|
+
process.stdout.write(entry.hooks[0].command);
|
|
48
|
+
' "$HOOKS_JSON")"
|
|
49
|
+
|
|
50
|
+
if [[ "$SESSION_START_CMD" == *"codex-hook-adapter.js"* ]]; then
|
|
51
|
+
_pass "extracted SessionStart hook command"
|
|
52
|
+
else
|
|
53
|
+
_fail "could not extract SessionStart hook command"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# An unrelated project: a real git repo that does NOT vendor scripts/hooks,
|
|
57
|
+
# which is what every real installation target looks like (this repo is the
|
|
58
|
+
# one exception, since it dogfoods itself from its own repo root).
|
|
59
|
+
PROJECT="$TMPDIR_EVAL/unrelated-project"
|
|
60
|
+
mkdir -p "$PROJECT"
|
|
61
|
+
git init -q "$PROJECT"
|
|
62
|
+
|
|
63
|
+
HOME_WITH_INSTALL="$TMPDIR_EVAL/home-with-install"
|
|
64
|
+
mkdir -p "$HOME_WITH_INSTALL"
|
|
65
|
+
bash "$ROOT/dist/codex/install.sh" "$HOME_WITH_INSTALL/.codex" >/dev/null
|
|
66
|
+
|
|
67
|
+
HOME_EMPTY="$TMPDIR_EVAL/home-empty"
|
|
68
|
+
mkdir -p "$HOME_EMPTY"
|
|
69
|
+
|
|
70
|
+
echo ""
|
|
71
|
+
echo "--- CODEX_HOME set correctly (baseline) ---"
|
|
72
|
+
OUT="$(cd "$PROJECT" && CODEX_HOME="$HOME_WITH_INSTALL/.codex" bash -lc "$SESSION_START_CMD" <<<'{"hook_event_name":"SessionStart"}' 2>"$TMPDIR_EVAL/stderr.baseline")"
|
|
73
|
+
STATUS=$?
|
|
74
|
+
if [[ $STATUS -eq 0 ]] && [[ "$OUT" == *'"continue":true'* ]]; then
|
|
75
|
+
_pass "hook succeeds when CODEX_HOME is set and correct"
|
|
76
|
+
else
|
|
77
|
+
_fail "hook should succeed when CODEX_HOME is set and correct (exit $STATUS): $OUT"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
echo ""
|
|
81
|
+
echo "--- CODEX_HOME unset, unrelated cwd, install lives under \$HOME/.codex ---"
|
|
82
|
+
OUT="$(cd "$PROJECT" && unset CODEX_HOME && HOME="$HOME_WITH_INSTALL" bash -lc "$SESSION_START_CMD" <<<'{"hook_event_name":"SessionStart"}' 2>"$TMPDIR_EVAL/stderr.fallback")"
|
|
83
|
+
STATUS=$?
|
|
84
|
+
if [[ $STATUS -eq 0 ]] && [[ "$OUT" == *'"continue":true'* ]]; then
|
|
85
|
+
_pass "hook falls back to \$HOME/.codex and succeeds when CODEX_HOME is unset"
|
|
86
|
+
else
|
|
87
|
+
_fail "hook should fall back to \$HOME/.codex when CODEX_HOME is unset (exit $STATUS): $OUT"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
echo ""
|
|
91
|
+
echo "--- CODEX_HOME unset, unrelated cwd, no install anywhere (fail open) ---"
|
|
92
|
+
set +e
|
|
93
|
+
OUT="$(cd "$PROJECT" && unset CODEX_HOME && HOME="$HOME_EMPTY" bash -lc "$SESSION_START_CMD" <<<'{"hook_event_name":"SessionStart"}' 2>"$TMPDIR_EVAL/stderr.missing")"
|
|
94
|
+
STATUS=$?
|
|
95
|
+
set -e
|
|
96
|
+
if [[ $STATUS -eq 0 ]]; then
|
|
97
|
+
_pass "hook exits 0 (fails open) instead of crashing when the script cannot be found anywhere"
|
|
98
|
+
else
|
|
99
|
+
_fail "hook should fail open with exit 0 when unresolvable, got exit $STATUS"
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
if grep -q "hook script not found" "$TMPDIR_EVAL/stderr.missing"; then
|
|
103
|
+
_pass "hook reports a clear diagnostic instead of a bare module-not-found crash"
|
|
104
|
+
else
|
|
105
|
+
_fail "hook did not report a diagnostic when the script was unresolvable"
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
echo ""
|
|
109
|
+
if [[ $errors -gt 0 ]]; then
|
|
110
|
+
echo "FAILED: $errors error(s)"
|
|
111
|
+
exit 1
|
|
112
|
+
fi
|
|
113
|
+
echo "PASSED"
|
|
114
|
+
exit 0
|
|
@@ -30,15 +30,15 @@ trap cleanup EXIT
|
|
|
30
30
|
|
|
31
31
|
REPO="$TMP/repo"
|
|
32
32
|
SLUG="conc"
|
|
33
|
-
mkdir -p "$REPO/.flow-agents/$SLUG"
|
|
33
|
+
mkdir -p "$REPO/.kontourai/flow-agents/$SLUG"
|
|
34
34
|
printf '# Repo\n' > "$REPO/AGENTS.md"
|
|
35
35
|
# Anchor the capture log to this slug. evidence-capture.js resolves the artifact
|
|
36
|
-
# dir via .flow-agents/current.json (active_slug) or the newest state.json; seed
|
|
37
|
-
# both so resolveArtifactDir() points at .flow-agents/<slug>/.
|
|
38
|
-
printf '{"active_slug":"%s","artifact_dir":".flow-agents/%s"}' "$SLUG" "$SLUG" \
|
|
39
|
-
> "$REPO/.flow-agents/current.json"
|
|
36
|
+
# dir via .kontourai/flow-agents/current.json (active_slug) or the newest state.json; seed
|
|
37
|
+
# both so resolveArtifactDir() points at .kontourai/flow-agents/<slug>/.
|
|
38
|
+
printf '{"active_slug":"%s","artifact_dir":".kontourai/flow-agents/%s"}' "$SLUG" "$SLUG" \
|
|
39
|
+
> "$REPO/.kontourai/flow-agents/current.json"
|
|
40
40
|
printf '%s' "{\"schema_version\":\"1.0\",\"task_slug\":\"$SLUG\",\"status\":\"in_progress\",\"phase\":\"build\",\"updated_at\":\"2026-06-23T00:00:00Z\",\"next_action\":{\"status\":\"in_progress\",\"summary\":\"work\"}}" \
|
|
41
|
-
> "$REPO/.flow-agents/$SLUG/state.json"
|
|
41
|
+
> "$REPO/.kontourai/flow-agents/$SLUG/state.json"
|
|
42
42
|
|
|
43
43
|
N=24
|
|
44
44
|
echo "Test: $N concurrent captures into one command-log must not fork the chain"
|
|
@@ -51,7 +51,7 @@ for i in $(seq 1 "$N"); do
|
|
|
51
51
|
done
|
|
52
52
|
wait
|
|
53
53
|
|
|
54
|
-
LOG="$REPO/.flow-agents/$SLUG/command-log.jsonl"
|
|
54
|
+
LOG="$REPO/.kontourai/flow-agents/$SLUG/command-log.jsonl"
|
|
55
55
|
|
|
56
56
|
# 1. All N records present.
|
|
57
57
|
count=$(grep -c '' "$LOG" 2>/dev/null || echo 0)
|
|
@@ -91,7 +91,7 @@ else
|
|
|
91
91
|
fi
|
|
92
92
|
|
|
93
93
|
# 3. The verifier confirms an intact chain.
|
|
94
|
-
chain_status=$(node -e "const g = require('$GATE'); console.log(g.verifyCommandLogChain('$REPO/.flow-agents/$SLUG').status);")
|
|
94
|
+
chain_status=$(node -e "const g = require('$GATE'); console.log(g.verifyCommandLogChain('$REPO/.kontourai/flow-agents/$SLUG').status);")
|
|
95
95
|
if [[ "$chain_status" == "ok" ]]; then
|
|
96
96
|
_pass "verifyCommandLogChain → ok under concurrency"
|
|
97
97
|
else
|
|
@@ -22,7 +22,7 @@ errors=0
|
|
|
22
22
|
_pass() { echo " ✓ $1"; }
|
|
23
23
|
_fail() { echo " ✗ $1"; errors=$((errors + 1)); }
|
|
24
24
|
|
|
25
|
-
SD=".flow-agents/s"
|
|
25
|
+
SD=".kontourai/flow-agents/s"
|
|
26
26
|
|
|
27
27
|
# Build a command-log from a spec: JSON array of {cmd,exit,src,parent} where
|
|
28
28
|
# parent is the 0-based index of the entry whose hash is this entry's prevHash
|
|
@@ -41,10 +41,10 @@ build() { # $1=dir $2=spec-json
|
|
|
41
41
|
const prev=s.parent===-1?GEN:hashes[s.parent]; const h=H(prev,rec);
|
|
42
42
|
hashes.push(h); lines.push(JSON.stringify({...rec,_chain:{seq:i,prevHash:prev,hash:h}}));
|
|
43
43
|
});
|
|
44
|
-
fs.writeFileSync(path.join(process.env.DIR,".flow-agents/s/command-log.jsonl"),lines.join("\n")+"\n");
|
|
44
|
+
fs.writeFileSync(path.join(process.env.DIR,".kontourai/flow-agents/s/command-log.jsonl"),lines.join("\n")+"\n");
|
|
45
45
|
' "$2"
|
|
46
46
|
}
|
|
47
|
-
status() { DIR="$1" node -e 'const g=require(process.env.GATE);console.log(g.verifyCommandLogChain(process.env.DIR+"/.flow-agents/s").status)' ; }
|
|
47
|
+
status() { DIR="$1" node -e 'const g=require(process.env.GATE);console.log(g.verifyCommandLogChain(process.env.DIR+"/.kontourai/flow-agents/s").status)' ; }
|
|
48
48
|
|
|
49
49
|
# ── 1. linear → ok ────────────────────────────────────────────────────────────
|
|
50
50
|
D="$TMP/linear"; build "$D" '[{"cmd":"a","exit":0,"parent":-1},{"cmd":"b","exit":0,"parent":0}]'
|