@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
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
#
|
|
10
10
|
# Covers:
|
|
11
11
|
# AC1 — config-protection.js: blocked Write/Edit to kill-switch / routing files
|
|
12
|
-
# (.claude/settings.json, shell profiles, .flow-agents/current.json) and
|
|
12
|
+
# (.claude/settings.json, shell profiles, .kontourai/flow-agents/current.json) and
|
|
13
13
|
# shell-redirect detection (best-effort, incomplete coverage).
|
|
14
14
|
# AC2 — stop-goal-fit.js: MAX_BLOCKS cannot release a HARD block (false-completion
|
|
15
15
|
# / integrity failure); only soft/advisory streaks may auto-release.
|
|
@@ -40,11 +40,11 @@ trap cleanup EXIT
|
|
|
40
40
|
|
|
41
41
|
seed_repo_inprogress() { # $1=dir $2=slug $3=phase(opt) $4=status(opt)
|
|
42
42
|
local dir="$1" slug="$2" phase="${3:-execution}" status="${4:-in_progress}"
|
|
43
|
-
mkdir -p "$dir/.flow-agents/$slug"
|
|
43
|
+
mkdir -p "$dir/.kontourai/flow-agents/$slug"
|
|
44
44
|
printf '# Repo\n' > "$dir/AGENTS.md"
|
|
45
45
|
printf '%s' "{\"schema_version\":\"1.0\",\"task_slug\":\"$slug\",\"status\":\"$status\",\"phase\":\"$phase\",\"updated_at\":\"2026-06-27T00:00:00Z\",\"next_action\":{\"status\":\"in_progress\",\"summary\":\"Testing\"}}" \
|
|
46
|
-
> "$dir/.flow-agents/$slug/state.json"
|
|
47
|
-
cat > "$dir/.flow-agents/$slug/$slug--deliver.md" << MD
|
|
46
|
+
> "$dir/.kontourai/flow-agents/$slug/state.json"
|
|
47
|
+
cat > "$dir/.kontourai/flow-agents/$slug/$slug--deliver.md" << MD
|
|
48
48
|
# $slug
|
|
49
49
|
|
|
50
50
|
branch: main
|
|
@@ -58,11 +58,11 @@ MD
|
|
|
58
58
|
|
|
59
59
|
seed_repo_preexec() { # $1=dir $2=slug
|
|
60
60
|
local dir="$1" slug="$2"
|
|
61
|
-
mkdir -p "$dir/.flow-agents/$slug"
|
|
61
|
+
mkdir -p "$dir/.kontourai/flow-agents/$slug"
|
|
62
62
|
printf '# Repo\n' > "$dir/AGENTS.md"
|
|
63
63
|
printf '%s' "{\"schema_version\":\"1.0\",\"task_slug\":\"$slug\",\"status\":\"planned\",\"phase\":\"planning\",\"updated_at\":\"2026-06-27T00:00:00Z\",\"next_action\":{\"status\":\"planned\",\"summary\":\"Planning\"}}" \
|
|
64
|
-
> "$dir/.flow-agents/$slug/state.json"
|
|
65
|
-
cat > "$dir/.flow-agents/$slug/$slug--deliver.md" << MD
|
|
64
|
+
> "$dir/.kontourai/flow-agents/$slug/state.json"
|
|
65
|
+
cat > "$dir/.kontourai/flow-agents/$slug/$slug--deliver.md" << MD
|
|
66
66
|
# $slug
|
|
67
67
|
|
|
68
68
|
branch: main
|
|
@@ -78,7 +78,7 @@ write_clean_bundle() { # $1=path
|
|
|
78
78
|
python3 - "$1" << 'PY'
|
|
79
79
|
import json, sys
|
|
80
80
|
bundle = {
|
|
81
|
-
"schemaVersion":
|
|
81
|
+
"schemaVersion": 5, "source": "test",
|
|
82
82
|
"claims": [], "evidence": [], "policies": [], "events": []
|
|
83
83
|
}
|
|
84
84
|
json.dump(bundle, open(sys.argv[1], 'w'))
|
|
@@ -90,7 +90,7 @@ write_high_impact_bundle() { # $1=path $2=slug $3=status(verified|disputed)
|
|
|
90
90
|
import json, sys
|
|
91
91
|
bp, slug, status = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
92
92
|
bundle = {
|
|
93
|
-
"schemaVersion":
|
|
93
|
+
"schemaVersion": 5, "source": "test",
|
|
94
94
|
"claims": [{
|
|
95
95
|
"id": "c-high",
|
|
96
96
|
"subjectId": slug + "/tests",
|
|
@@ -189,15 +189,15 @@ for profile in ".bash_profile" ".bashrc" ".profile" ".zprofile" ".zshrc"; do
|
|
|
189
189
|
done
|
|
190
190
|
|
|
191
191
|
echo ""
|
|
192
|
-
echo "--- AC1.3: Write/Edit to .flow-agents/current.json BLOCKED ---"
|
|
192
|
+
echo "--- AC1.3: Write/Edit to .kontourai/flow-agents/current.json BLOCKED ---"
|
|
193
193
|
set +e
|
|
194
|
-
prot_out=$(echo '{"tool_name":"Write","tool_input":{"path":"/repo/.flow-agents/current.json"}}' | node "$PROT" 2>&1)
|
|
194
|
+
prot_out=$(echo '{"tool_name":"Write","tool_input":{"path":"/repo/.kontourai/flow-agents/current.json"}}' | node "$PROT" 2>&1)
|
|
195
195
|
prot_exit=$?
|
|
196
196
|
set -e
|
|
197
197
|
if [ "$prot_exit" -eq 2 ] && echo "$prot_out" | grep -q "BLOCKED"; then
|
|
198
|
-
_pass "Write to .flow-agents/current.json blocked (exit 2)"
|
|
198
|
+
_pass "Write to .kontourai/flow-agents/current.json blocked (exit 2)"
|
|
199
199
|
else
|
|
200
|
-
_fail "Write to .flow-agents/current.json NOT blocked (exit=$prot_exit)"
|
|
200
|
+
_fail "Write to .kontourai/flow-agents/current.json NOT blocked (exit=$prot_exit)"
|
|
201
201
|
fi
|
|
202
202
|
|
|
203
203
|
echo ""
|
|
@@ -238,15 +238,15 @@ else
|
|
|
238
238
|
fi
|
|
239
239
|
|
|
240
240
|
echo ""
|
|
241
|
-
echo "--- AC1.7: tee .flow-agents/current.json BLOCKED ---"
|
|
241
|
+
echo "--- AC1.7: tee .kontourai/flow-agents/current.json BLOCKED ---"
|
|
242
242
|
set +e
|
|
243
|
-
prot_out=$(echo '{"tool_name":"Bash","tool_input":{"command":"echo {} | tee .flow-agents/current.json"}}' | node "$PROT" 2>&1)
|
|
243
|
+
prot_out=$(echo '{"tool_name":"Bash","tool_input":{"command":"echo {} | tee .kontourai/flow-agents/current.json"}}' | node "$PROT" 2>&1)
|
|
244
244
|
prot_exit=$?
|
|
245
245
|
set -e
|
|
246
246
|
if [ "$prot_exit" -eq 2 ]; then
|
|
247
|
-
_pass "tee to .flow-agents/current.json blocked (exit 2)"
|
|
247
|
+
_pass "tee to .kontourai/flow-agents/current.json blocked (exit 2)"
|
|
248
248
|
else
|
|
249
|
-
_fail "tee to .flow-agents/current.json NOT blocked (exit=$prot_exit)"
|
|
249
|
+
_fail "tee to .kontourai/flow-agents/current.json NOT blocked (exit=$prot_exit)"
|
|
250
250
|
fi
|
|
251
251
|
|
|
252
252
|
echo ""
|
|
@@ -276,15 +276,15 @@ else
|
|
|
276
276
|
fi
|
|
277
277
|
|
|
278
278
|
echo ""
|
|
279
|
-
echo "--- AC1.11: tee multi-file — tee /tmp/x .flow-agents/current.json BLOCKED ---"
|
|
279
|
+
echo "--- AC1.11: tee multi-file — tee /tmp/x .kontourai/flow-agents/current.json BLOCKED ---"
|
|
280
280
|
set +e
|
|
281
|
-
prot_out=$(echo '{"tool_name":"Bash","tool_input":{"command":"echo {} | tee /tmp/x .flow-agents/current.json"}}' | node "$PROT" 2>&1)
|
|
281
|
+
prot_out=$(echo '{"tool_name":"Bash","tool_input":{"command":"echo {} | tee /tmp/x .kontourai/flow-agents/current.json"}}' | node "$PROT" 2>&1)
|
|
282
282
|
prot_exit=$?
|
|
283
283
|
set -e
|
|
284
284
|
if [ "$prot_exit" -eq 2 ] && echo "$prot_out" | grep -q "BLOCKED"; then
|
|
285
|
-
_pass "tee /tmp/x .flow-agents/current.json blocked (protected 2nd arg checked) (exit 2)"
|
|
285
|
+
_pass "tee /tmp/x .kontourai/flow-agents/current.json blocked (protected 2nd arg checked) (exit 2)"
|
|
286
286
|
else
|
|
287
|
-
_fail "tee /tmp/x .flow-agents/current.json NOT blocked (exit=$prot_exit, out=$prot_out)"
|
|
287
|
+
_fail "tee /tmp/x .kontourai/flow-agents/current.json NOT blocked (exit=$prot_exit, out=$prot_out)"
|
|
288
288
|
fi
|
|
289
289
|
|
|
290
290
|
echo ""
|
|
@@ -325,27 +325,27 @@ echo ""
|
|
|
325
325
|
echo "=== AC1 R5a: state.json/trust.bundle protection + interpreter-write detection ==="
|
|
326
326
|
|
|
327
327
|
echo ""
|
|
328
|
-
echo "--- AC1.13: Write to .flow-agents/slug/state.json BLOCKED (R5a) ---"
|
|
328
|
+
echo "--- AC1.13: Write to .kontourai/flow-agents/slug/state.json BLOCKED (R5a) ---"
|
|
329
329
|
set +e
|
|
330
|
-
prot_out=$(echo '{"tool_name":"Write","tool_input":{"path":"/repo/.flow-agents/my-slug/state.json"}}' | node "$PROT" 2>&1)
|
|
330
|
+
prot_out=$(echo '{"tool_name":"Write","tool_input":{"path":"/repo/.kontourai/flow-agents/my-slug/state.json"}}' | node "$PROT" 2>&1)
|
|
331
331
|
prot_exit=$?
|
|
332
332
|
set -e
|
|
333
333
|
if [ "$prot_exit" -eq 2 ] && echo "$prot_out" | grep -q "BLOCKED"; then
|
|
334
|
-
_pass "Write to .flow-agents/slug/state.json blocked (exit 2)"
|
|
334
|
+
_pass "Write to .kontourai/flow-agents/slug/state.json blocked (exit 2)"
|
|
335
335
|
else
|
|
336
|
-
_fail "Write to .flow-agents/slug/state.json NOT blocked (exit=$prot_exit)"
|
|
336
|
+
_fail "Write to .kontourai/flow-agents/slug/state.json NOT blocked (exit=$prot_exit)"
|
|
337
337
|
fi
|
|
338
338
|
|
|
339
339
|
echo ""
|
|
340
|
-
echo "--- AC1.14: Edit to .flow-agents/slug/trust.bundle BLOCKED (R5a) ---"
|
|
340
|
+
echo "--- AC1.14: Edit to .kontourai/flow-agents/slug/trust.bundle BLOCKED (R5a) ---"
|
|
341
341
|
set +e
|
|
342
|
-
prot_out=$(echo '{"tool_name":"Edit","tool_input":{"path":"/repo/.flow-agents/my-slug/trust.bundle"}}' | node "$PROT" 2>&1)
|
|
342
|
+
prot_out=$(echo '{"tool_name":"Edit","tool_input":{"path":"/repo/.kontourai/flow-agents/my-slug/trust.bundle"}}' | node "$PROT" 2>&1)
|
|
343
343
|
prot_exit=$?
|
|
344
344
|
set -e
|
|
345
345
|
if [ "$prot_exit" -eq 2 ] && echo "$prot_out" | grep -q "BLOCKED"; then
|
|
346
|
-
_pass "Edit to .flow-agents/slug/trust.bundle blocked (exit 2)"
|
|
346
|
+
_pass "Edit to .kontourai/flow-agents/slug/trust.bundle blocked (exit 2)"
|
|
347
347
|
else
|
|
348
|
-
_fail "Edit to .flow-agents/slug/trust.bundle NOT blocked (exit=$prot_exit)"
|
|
348
|
+
_fail "Edit to .kontourai/flow-agents/slug/trust.bundle NOT blocked (exit=$prot_exit)"
|
|
349
349
|
fi
|
|
350
350
|
|
|
351
351
|
echo ""
|
|
@@ -363,25 +363,49 @@ fi
|
|
|
363
363
|
echo ""
|
|
364
364
|
echo "--- AC1.16: Bash redirect > to state.json BLOCKED (R5a: REDIRECT_PROTECTED_RE extended) ---"
|
|
365
365
|
set +e
|
|
366
|
-
prot_out=$(echo '{"tool_name":"Bash","tool_input":{"command":"echo {} > .flow-agents/slug/state.json"}}' | node "$PROT" 2>&1)
|
|
366
|
+
prot_out=$(echo '{"tool_name":"Bash","tool_input":{"command":"echo {} > .kontourai/flow-agents/slug/state.json"}}' | node "$PROT" 2>&1)
|
|
367
367
|
prot_exit=$?
|
|
368
368
|
set -e
|
|
369
369
|
if [ "$prot_exit" -eq 2 ] && echo "$prot_out" | grep -q "BLOCKED"; then
|
|
370
|
-
_pass "Bash redirect > .flow-agents/slug/state.json blocked (exit 2)"
|
|
370
|
+
_pass "Bash redirect > .kontourai/flow-agents/slug/state.json blocked (exit 2)"
|
|
371
371
|
else
|
|
372
|
-
_fail "Bash redirect > .flow-agents/slug/state.json NOT blocked (exit=$prot_exit)"
|
|
372
|
+
_fail "Bash redirect > .kontourai/flow-agents/slug/state.json NOT blocked (exit=$prot_exit)"
|
|
373
373
|
fi
|
|
374
374
|
|
|
375
375
|
echo ""
|
|
376
376
|
echo "--- AC1.17: tee to trust.bundle BLOCKED (R5a: REDIRECT_PROTECTED_RE extended) ---"
|
|
377
377
|
set +e
|
|
378
|
-
prot_out=$(echo '{"tool_name":"Bash","tool_input":{"command":"echo {} | tee .flow-agents/slug/trust.bundle"}}' | node "$PROT" 2>&1)
|
|
378
|
+
prot_out=$(echo '{"tool_name":"Bash","tool_input":{"command":"echo {} | tee .kontourai/flow-agents/slug/trust.bundle"}}' | node "$PROT" 2>&1)
|
|
379
379
|
prot_exit=$?
|
|
380
380
|
set -e
|
|
381
381
|
if [ "$prot_exit" -eq 2 ] && echo "$prot_out" | grep -q "BLOCKED"; then
|
|
382
|
-
_pass "tee to .flow-agents/slug/trust.bundle blocked (exit 2)"
|
|
382
|
+
_pass "tee to .kontourai/flow-agents/slug/trust.bundle blocked (exit 2)"
|
|
383
383
|
else
|
|
384
|
-
_fail "tee to .flow-agents/slug/trust.bundle NOT blocked (exit=$prot_exit)"
|
|
384
|
+
_fail "tee to .kontourai/flow-agents/slug/trust.bundle NOT blocked (exit=$prot_exit)"
|
|
385
|
+
fi
|
|
386
|
+
|
|
387
|
+
echo ""
|
|
388
|
+
echo "--- AC1.17b: Write to goal-fit block streak BLOCKED ---"
|
|
389
|
+
set +e
|
|
390
|
+
prot_out=$(echo '{"tool_name":"Write","tool_input":{"path":"/repo/.kontourai/flow-agents/.goal-fit-block-streak.json"}}' | node "$PROT" 2>&1)
|
|
391
|
+
prot_exit=$?
|
|
392
|
+
set -e
|
|
393
|
+
if [ "$prot_exit" -eq 2 ] && echo "$prot_out" | grep -q "BLOCKED"; then
|
|
394
|
+
_pass "Write to .kontourai/flow-agents/.goal-fit-block-streak.json blocked (exit 2)"
|
|
395
|
+
else
|
|
396
|
+
_fail "Write to .kontourai/flow-agents/.goal-fit-block-streak.json NOT blocked (exit=$prot_exit)"
|
|
397
|
+
fi
|
|
398
|
+
|
|
399
|
+
echo ""
|
|
400
|
+
echo "--- AC1.17c: tee to goal-fit block streak BLOCKED ---"
|
|
401
|
+
set +e
|
|
402
|
+
prot_out=$(echo '{"tool_name":"Bash","tool_input":{"command":"echo {} | tee .kontourai/flow-agents/.goal-fit-block-streak.json"}}' | node "$PROT" 2>&1)
|
|
403
|
+
prot_exit=$?
|
|
404
|
+
set -e
|
|
405
|
+
if [ "$prot_exit" -eq 2 ] && echo "$prot_out" | grep -q "BLOCKED"; then
|
|
406
|
+
_pass "tee to .kontourai/flow-agents/.goal-fit-block-streak.json blocked (exit 2)"
|
|
407
|
+
else
|
|
408
|
+
_fail "tee to .kontourai/flow-agents/.goal-fit-block-streak.json NOT blocked (exit=$prot_exit)"
|
|
385
409
|
fi
|
|
386
410
|
|
|
387
411
|
echo ""
|
|
@@ -487,11 +511,11 @@ echo ""
|
|
|
487
511
|
echo "--- AC1.R6a.2: Gate blocks npm test || exit 0 (claimed pass via laundered command) ---"
|
|
488
512
|
R6LA="$TMP/r6la-laundering"
|
|
489
513
|
seed_repo_inprogress "$R6LA" "launder-r6"
|
|
490
|
-
python3 - "$R6LA/.flow-agents/launder-r6/trust.bundle" "launder-r6" "npm test || exit 0" << 'PY'
|
|
514
|
+
python3 - "$R6LA/.kontourai/flow-agents/launder-r6/trust.bundle" "launder-r6" "npm test || exit 0" << 'PY'
|
|
491
515
|
import json, sys
|
|
492
516
|
bp, slug, cmd = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
493
517
|
bundle = {
|
|
494
|
-
"schemaVersion":
|
|
518
|
+
"schemaVersion": 5, "source": "flow-agents/workflow-sidecar",
|
|
495
519
|
"claims": [{"id":"c1","subjectId":slug+"/tests","subjectType":"flow-step",
|
|
496
520
|
"claimType":"builder.verify.tests","fieldOrBehavior":cmd,
|
|
497
521
|
"value":"pass","impactLevel":"high","status":"verified",
|
|
@@ -505,7 +529,7 @@ bundle = {
|
|
|
505
529
|
json.dump(bundle, open(bp, 'w'))
|
|
506
530
|
PY
|
|
507
531
|
printf '%s\n' '{"command":"npm test || exit 0","observedResult":"pass","exitCode":0,"capturedAt":"2026-06-27T00:00:00Z","source":"postToolUse-capture"}' \
|
|
508
|
-
> "$R6LA/.flow-agents/launder-r6/command-log.jsonl"
|
|
532
|
+
> "$R6LA/.kontourai/flow-agents/launder-r6/command-log.jsonl"
|
|
509
533
|
|
|
510
534
|
set +e
|
|
511
535
|
r6la_out=$(run_gate "$R6LA")
|
|
@@ -526,11 +550,11 @@ echo ""
|
|
|
526
550
|
echo "--- AC1.R6a.3: Gate blocks npm test || echo ok (claimed pass via laundered command) ---"
|
|
527
551
|
R6LB="$TMP/r6lb-laundering"
|
|
528
552
|
seed_repo_inprogress "$R6LB" "launder-r6b"
|
|
529
|
-
python3 - "$R6LB/.flow-agents/launder-r6b/trust.bundle" "launder-r6b" "npm test || echo ok" << 'PY'
|
|
553
|
+
python3 - "$R6LB/.kontourai/flow-agents/launder-r6b/trust.bundle" "launder-r6b" "npm test || echo ok" << 'PY'
|
|
530
554
|
import json, sys
|
|
531
555
|
bp, slug, cmd = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
532
556
|
bundle = {
|
|
533
|
-
"schemaVersion":
|
|
557
|
+
"schemaVersion": 5, "source": "test",
|
|
534
558
|
"claims": [{"id":"c1","subjectId":slug+"/tests","subjectType":"flow-step",
|
|
535
559
|
"claimType":"builder.verify.tests","fieldOrBehavior":cmd,
|
|
536
560
|
"value":"pass","impactLevel":"high","status":"verified",
|
|
@@ -544,7 +568,7 @@ bundle = {
|
|
|
544
568
|
json.dump(bundle, open(bp, 'w'))
|
|
545
569
|
PY
|
|
546
570
|
printf '%s\n' '{"command":"npm test || echo ok","observedResult":"pass","exitCode":0,"capturedAt":"2026-06-27T00:00:00Z","source":"postToolUse-capture"}' \
|
|
547
|
-
> "$R6LB/.flow-agents/launder-r6b/command-log.jsonl"
|
|
571
|
+
> "$R6LB/.kontourai/flow-agents/launder-r6b/command-log.jsonl"
|
|
548
572
|
|
|
549
573
|
set +e
|
|
550
574
|
r6lb_out=$(run_gate "$R6LB")
|
|
@@ -560,11 +584,11 @@ echo ""
|
|
|
560
584
|
echo "--- AC1.R6a.4: Gate blocks npm test || /bin/true (claimed pass via laundered command) ---"
|
|
561
585
|
R6LC="$TMP/r6lc-laundering"
|
|
562
586
|
seed_repo_inprogress "$R6LC" "launder-r6c"
|
|
563
|
-
python3 - "$R6LC/.flow-agents/launder-r6c/trust.bundle" "launder-r6c" "npm test || /bin/true" << 'PY'
|
|
587
|
+
python3 - "$R6LC/.kontourai/flow-agents/launder-r6c/trust.bundle" "launder-r6c" "npm test || /bin/true" << 'PY'
|
|
564
588
|
import json, sys
|
|
565
589
|
bp, slug, cmd = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
566
590
|
bundle = {
|
|
567
|
-
"schemaVersion":
|
|
591
|
+
"schemaVersion": 5, "source": "test",
|
|
568
592
|
"claims": [{"id":"c1","subjectId":slug+"/tests","subjectType":"flow-step",
|
|
569
593
|
"claimType":"builder.verify.tests","fieldOrBehavior":cmd,
|
|
570
594
|
"value":"pass","impactLevel":"high","status":"verified",
|
|
@@ -578,7 +602,7 @@ bundle = {
|
|
|
578
602
|
json.dump(bundle, open(bp, 'w'))
|
|
579
603
|
PY
|
|
580
604
|
printf '%s\n' '{"command":"npm test || /bin/true","observedResult":"pass","exitCode":0,"capturedAt":"2026-06-27T00:00:00Z","source":"postToolUse-capture"}' \
|
|
581
|
-
> "$R6LC/.flow-agents/launder-r6c/command-log.jsonl"
|
|
605
|
+
> "$R6LC/.kontourai/flow-agents/launder-r6c/command-log.jsonl"
|
|
582
606
|
|
|
583
607
|
set +e
|
|
584
608
|
r6lc_out=$(run_gate "$R6LC")
|
|
@@ -594,11 +618,11 @@ echo ""
|
|
|
594
618
|
echo "--- AC1.R6a.5: Bare 'npm test' with PASS log NOT blocked (no over-flag) ---"
|
|
595
619
|
R6LD="$TMP/r6ld-legit"
|
|
596
620
|
seed_repo_inprogress "$R6LD" "legit-r6"
|
|
597
|
-
python3 - "$R6LD/.flow-agents/legit-r6/trust.bundle" "legit-r6" << 'PY'
|
|
621
|
+
python3 - "$R6LD/.kontourai/flow-agents/legit-r6/trust.bundle" "legit-r6" << 'PY'
|
|
598
622
|
import json, sys
|
|
599
623
|
bp, slug = sys.argv[1], sys.argv[2]
|
|
600
624
|
bundle = {
|
|
601
|
-
"schemaVersion":
|
|
625
|
+
"schemaVersion": 5, "source": "test",
|
|
602
626
|
"claims": [{"id":"c1","subjectId":slug+"/tests","subjectType":"flow-step",
|
|
603
627
|
"claimType":"builder.verify.tests","fieldOrBehavior":"npm test",
|
|
604
628
|
"value":"pass","impactLevel":"high","status":"verified",
|
|
@@ -612,7 +636,7 @@ bundle = {
|
|
|
612
636
|
json.dump(bundle, open(bp, 'w'))
|
|
613
637
|
PY
|
|
614
638
|
printf '%s\n' '{"command":"npm test","observedResult":"pass","exitCode":0,"capturedAt":"2026-06-27T00:00:00Z","source":"postToolUse-capture"}' \
|
|
615
|
-
> "$R6LD/.flow-agents/legit-r6/command-log.jsonl"
|
|
639
|
+
> "$R6LD/.kontourai/flow-agents/legit-r6/command-log.jsonl"
|
|
616
640
|
|
|
617
641
|
set +e
|
|
618
642
|
r6ld_out=$(run_gate "$R6LD")
|
|
@@ -726,8 +750,8 @@ AC2D="$TMP/ac2-hard"
|
|
|
726
750
|
seed_repo_inprogress "$AC2D" "ac2hard"
|
|
727
751
|
# Evidence claims npm test passed, but log shows it failed → caught false-completion
|
|
728
752
|
printf '%s' '{"schema_version":"1.0","task_slug":"ac2hard","verdict":"pass","checks":[{"id":"unit-tests","kind":"command","status":"pass","command":"npm test","summary":"passed"}]}' \
|
|
729
|
-
> "$AC2D/.flow-agents/ac2hard/evidence.json"
|
|
730
|
-
write_chained_fail_log "$AC2D/.flow-agents/ac2hard/command-log.jsonl" "npm test"
|
|
753
|
+
> "$AC2D/.kontourai/flow-agents/ac2hard/evidence.json"
|
|
754
|
+
write_chained_fail_log "$AC2D/.kontourai/flow-agents/ac2hard/command-log.jsonl" "npm test"
|
|
731
755
|
|
|
732
756
|
set +e
|
|
733
757
|
ac2h_1=$(FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=1 FLOW_AGENTS_GOAL_FIT_BACKSTOP=skip \
|
|
@@ -758,9 +782,9 @@ echo "--- AC2.2: MAX_BLOCKS=1 with soft/advisory-only streak → may release (ex
|
|
|
758
782
|
AC2S="$TMP/ac2-soft"
|
|
759
783
|
seed_repo_inprogress "$AC2S" "ac2soft" "execution" "executing"
|
|
760
784
|
# Write a clean bundle with no disputed claims (just a workflow-state warning from status)
|
|
761
|
-
write_clean_bundle "$AC2S/.flow-agents/ac2soft/trust.bundle"
|
|
785
|
+
write_clean_bundle "$AC2S/.kontourai/flow-agents/ac2soft/trust.bundle"
|
|
762
786
|
# Write empty command-log so missing-log doesn't fire
|
|
763
|
-
printf '' > "$AC2S/.flow-agents/ac2soft/command-log.jsonl"
|
|
787
|
+
printf '' > "$AC2S/.kontourai/flow-agents/ac2soft/command-log.jsonl"
|
|
764
788
|
|
|
765
789
|
set +e
|
|
766
790
|
# First call: blocks (streak=1, max=1 → already at max → soft: release)
|
|
@@ -769,8 +793,8 @@ ac2s_1=$(FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=1 FLOW_
|
|
|
769
793
|
ac2s_1_exit=$?
|
|
770
794
|
set -e
|
|
771
795
|
|
|
772
|
-
if [ "$ac2s_1_exit" -eq 0 ] && echo "$ac2s_1" | grep -q "
|
|
773
|
-
_pass "AC2: soft/advisory-only streak releases at MAX_BLOCKS=1 (exit 0,
|
|
796
|
+
if [ "$ac2s_1_exit" -eq 0 ] && echo "$ac2s_1" | grep -q "released — the same gap(s) blocked"; then
|
|
797
|
+
_pass "AC2: soft/advisory-only streak releases at MAX_BLOCKS=1 (exit 0, released notice)"
|
|
774
798
|
else
|
|
775
799
|
_fail "AC2: soft streak should release at MAX_BLOCKS=1. exit=$ac2s_1_exit out=${ac2s_1:0:300}"
|
|
776
800
|
fi
|
|
@@ -801,15 +825,15 @@ cp "$ROOT/scripts/lib/command-log-chain.js" "$ISO_LIBDIR/"
|
|
|
801
825
|
|
|
802
826
|
# Create isolated node context that can't find @kontourai/surface
|
|
803
827
|
ISO_DIR="$TMP/surface-iso"
|
|
804
|
-
mkdir -p "$ISO_DIR/repo/.flow-agents/surftest"
|
|
828
|
+
mkdir -p "$ISO_DIR/repo/.kontourai/flow-agents/surftest"
|
|
805
829
|
mkdir -p "$ISO_DIR/lib"
|
|
806
830
|
cp "$GATE" "$ISO_DIR/stop-goal-fit.js"
|
|
807
831
|
cp "$ROOT/scripts/hooks/lib/local-artifact-paths.js" "$ISO_DIR/lib/"
|
|
808
832
|
printf '# Repo\n' > "$ISO_DIR/repo/AGENTS.md"
|
|
809
833
|
# Non-terminal session (execution phase, in_progress status)
|
|
810
834
|
printf '%s' '{"schema_version":"1.0","task_slug":"surftest","status":"in_progress","phase":"execution","updated_at":"2026-06-27T00:00:00Z","next_action":{"status":"in_progress","summary":"running"}}' \
|
|
811
|
-
> "$ISO_DIR/repo/.flow-agents/surftest/state.json"
|
|
812
|
-
cat > "$ISO_DIR/repo/.flow-agents/surftest/surftest--deliver.md" << 'MD'
|
|
835
|
+
> "$ISO_DIR/repo/.kontourai/flow-agents/surftest/state.json"
|
|
836
|
+
cat > "$ISO_DIR/repo/.kontourai/flow-agents/surftest/surftest--deliver.md" << 'MD'
|
|
813
837
|
# surftest
|
|
814
838
|
|
|
815
839
|
branch: main
|
|
@@ -819,9 +843,9 @@ type: deliver
|
|
|
819
843
|
## Definition Of Done
|
|
820
844
|
- [ ] tests pass
|
|
821
845
|
MD
|
|
822
|
-
write_high_impact_bundle "$ISO_DIR/repo/.flow-agents/surftest/trust.bundle" "surftest" "verified"
|
|
846
|
+
write_high_impact_bundle "$ISO_DIR/repo/.kontourai/flow-agents/surftest/trust.bundle" "surftest" "verified"
|
|
823
847
|
# Empty log (non-missing)
|
|
824
|
-
printf '' > "$ISO_DIR/repo/.flow-agents/surftest/command-log.jsonl"
|
|
848
|
+
printf '' > "$ISO_DIR/repo/.kontourai/flow-agents/surftest/command-log.jsonl"
|
|
825
849
|
|
|
826
850
|
set +e
|
|
827
851
|
# Run in isolated dir with NODE_PATH=$ISO_DIR so @kontourai/surface cannot be found
|
|
@@ -847,14 +871,14 @@ echo ""
|
|
|
847
871
|
echo "--- AC3.1b: Low-impact-only bundle with unavailable surface → NOT blocked ---"
|
|
848
872
|
|
|
849
873
|
ISO2_DIR="$TMP/surface-iso2"
|
|
850
|
-
mkdir -p "$ISO2_DIR/repo/.flow-agents/lowtest"
|
|
874
|
+
mkdir -p "$ISO2_DIR/repo/.kontourai/flow-agents/lowtest"
|
|
851
875
|
mkdir -p "$ISO2_DIR/lib"
|
|
852
876
|
cp "$GATE" "$ISO2_DIR/stop-goal-fit.js"
|
|
853
877
|
cp "$ROOT/scripts/hooks/lib/local-artifact-paths.js" "$ISO2_DIR/lib/"
|
|
854
878
|
printf '# Repo\n' > "$ISO2_DIR/repo/AGENTS.md"
|
|
855
879
|
printf '%s' '{"schema_version":"1.0","task_slug":"lowtest","status":"in_progress","phase":"execution","updated_at":"2026-06-27T00:00:00Z","next_action":{"status":"in_progress","summary":"running"}}' \
|
|
856
|
-
> "$ISO2_DIR/repo/.flow-agents/lowtest/state.json"
|
|
857
|
-
cat > "$ISO2_DIR/repo/.flow-agents/lowtest/lowtest--deliver.md" << 'MD'
|
|
880
|
+
> "$ISO2_DIR/repo/.kontourai/flow-agents/lowtest/state.json"
|
|
881
|
+
cat > "$ISO2_DIR/repo/.kontourai/flow-agents/lowtest/lowtest--deliver.md" << 'MD'
|
|
858
882
|
# lowtest
|
|
859
883
|
|
|
860
884
|
branch: main
|
|
@@ -865,11 +889,11 @@ type: deliver
|
|
|
865
889
|
- [ ] tests pass
|
|
866
890
|
MD
|
|
867
891
|
# Low-impact claim only
|
|
868
|
-
python3 - "$ISO2_DIR/repo/.flow-agents/lowtest/trust.bundle" "lowtest" << 'PY'
|
|
892
|
+
python3 - "$ISO2_DIR/repo/.kontourai/flow-agents/lowtest/trust.bundle" "lowtest" << 'PY'
|
|
869
893
|
import json, sys
|
|
870
894
|
bp, slug = sys.argv[1], sys.argv[2]
|
|
871
895
|
bundle = {
|
|
872
|
-
"schemaVersion":
|
|
896
|
+
"schemaVersion": 5, "source": "test",
|
|
873
897
|
"claims": [{
|
|
874
898
|
"id": "c-low",
|
|
875
899
|
"subjectId": slug + "/docs",
|
|
@@ -886,7 +910,7 @@ bundle = {
|
|
|
886
910
|
}
|
|
887
911
|
json.dump(bundle, open(bp, 'w'))
|
|
888
912
|
PY
|
|
889
|
-
printf '' > "$ISO2_DIR/repo/.flow-agents/lowtest/command-log.jsonl"
|
|
913
|
+
printf '' > "$ISO2_DIR/repo/.kontourai/flow-agents/lowtest/command-log.jsonl"
|
|
890
914
|
|
|
891
915
|
set +e
|
|
892
916
|
surf2_out=$(NODE_PATH="$ISO2_DIR" FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=100000 \
|
|
@@ -919,10 +943,10 @@ seed_repo_inprogress "$AC3D" "postex" "execution" "in_progress"
|
|
|
919
943
|
# This simulates a session where the agent ran commands (evidence.execution.label present)
|
|
920
944
|
# but deleted command-log.jsonl. The #216 guard uses execution.label to distinguish this
|
|
921
945
|
# from a legitimate no-command session (no execution.label → no missing-log warning).
|
|
922
|
-
python3 - "$AC3D/.flow-agents/postex/trust.bundle" << 'PY'
|
|
946
|
+
python3 - "$AC3D/.kontourai/flow-agents/postex/trust.bundle" << 'PY'
|
|
923
947
|
import json, sys
|
|
924
948
|
bundle = {
|
|
925
|
-
"schemaVersion":
|
|
949
|
+
"schemaVersion": 5, "source": "test",
|
|
926
950
|
"claims": [],
|
|
927
951
|
"evidence": [{
|
|
928
952
|
"id": "ev-captured", "claimId": None,
|
|
@@ -962,7 +986,7 @@ echo "--- AC3.2b: Pre-execution session (planning/planned) with no log → NOT b
|
|
|
962
986
|
|
|
963
987
|
AC3P="$TMP/ac3-preexec"
|
|
964
988
|
seed_repo_preexec "$AC3P" "preex"
|
|
965
|
-
write_clean_bundle "$AC3P/.flow-agents/preex/trust.bundle"
|
|
989
|
+
write_clean_bundle "$AC3P/.kontourai/flow-agents/preex/trust.bundle"
|
|
966
990
|
# No command-log.jsonl — pre-execution sessions have no commands yet
|
|
967
991
|
|
|
968
992
|
set +e
|
|
@@ -984,11 +1008,11 @@ echo "--- AC3.2c: Post-execution session WITH command log present → NOT falsel
|
|
|
984
1008
|
|
|
985
1009
|
AC3C="$TMP/ac3-cleanlog"
|
|
986
1010
|
seed_repo_inprogress "$AC3C" "cleanlog" "execution" "in_progress"
|
|
987
|
-
write_clean_bundle "$AC3C/.flow-agents/cleanlog/trust.bundle"
|
|
988
|
-
write_chained_fail_log "$AC3C/.flow-agents/cleanlog/command-log.jsonl" "echo hello"
|
|
1011
|
+
write_clean_bundle "$AC3C/.kontourai/flow-agents/cleanlog/trust.bundle"
|
|
1012
|
+
write_chained_fail_log "$AC3C/.kontourai/flow-agents/cleanlog/command-log.jsonl" "echo hello"
|
|
989
1013
|
# Override: mark the command as pass in evidence to avoid false-completion blocking
|
|
990
1014
|
printf '%s' '{"schema_version":"1.0","task_slug":"cleanlog","verdict":"pass","checks":[]}' \
|
|
991
|
-
> "$AC3C/.flow-agents/cleanlog/evidence.json"
|
|
1015
|
+
> "$AC3C/.kontourai/flow-agents/cleanlog/evidence.json"
|
|
992
1016
|
|
|
993
1017
|
set +e
|
|
994
1018
|
ac3c_out=$(FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=100000 \
|
|
@@ -1051,9 +1075,9 @@ echo "=== Over-block check: normal session NOT falsely blocked ==="
|
|
|
1051
1075
|
|
|
1052
1076
|
OVR="$TMP/overblock"
|
|
1053
1077
|
seed_repo_inprogress "$OVR" "normal" "execution" "in_progress"
|
|
1054
|
-
write_clean_bundle "$OVR/.flow-agents/normal/trust.bundle"
|
|
1078
|
+
write_clean_bundle "$OVR/.kontourai/flow-agents/normal/trust.bundle"
|
|
1055
1079
|
# Write a valid command log (empty — no claims to cross-reference)
|
|
1056
|
-
printf '' > "$OVR/.flow-agents/normal/command-log.jsonl"
|
|
1080
|
+
printf '' > "$OVR/.kontourai/flow-agents/normal/command-log.jsonl"
|
|
1057
1081
|
|
|
1058
1082
|
set +e
|
|
1059
1083
|
ovr_out=$(FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=100000 \
|
|
@@ -1143,7 +1167,7 @@ if [ "$errors" -eq 0 ]; then
|
|
|
1143
1167
|
echo " R6b: delivery/trust.bundle + delivery/trust.checkpoint.json protected (Write/Edit + > + cp/mv blocked)"
|
|
1144
1168
|
echo " INCOMPLETE: process substitution, runtime path construction, rsync/scp/dd evade"
|
|
1145
1169
|
echo " AC2: Hard blocks (false-completion, integrity failure) NOT auto-released by MAX_BLOCKS"
|
|
1146
|
-
echo " INCOMPLETE: agent can reset streak
|
|
1170
|
+
echo " INCOMPLETE: agent can reset streak with runtime-constructed paths"
|
|
1147
1171
|
echo " AC3.1: surface-unavailable + high-impact → FULL_BLOCK warning; low-impact non-blocking"
|
|
1148
1172
|
echo " INCOMPLETE: agent could delete @kontourai/surface to force this path"
|
|
1149
1173
|
echo " AC3.2: missing log in post-execution → FULL_BLOCK; pre-execution → not blocked"
|
|
@@ -62,14 +62,14 @@ seed_trust_bundle() {
|
|
|
62
62
|
|
|
63
63
|
cat > "$dir/trust.bundle" <<JSON
|
|
64
64
|
{
|
|
65
|
-
"schemaVersion":
|
|
65
|
+
"schemaVersion": 5,
|
|
66
66
|
"source": "gate-review-test;statusFunctionVersion=1",
|
|
67
67
|
"claims": [
|
|
68
68
|
{
|
|
69
69
|
"id": "$claimId",
|
|
70
70
|
"subjectType": "workflow-check",
|
|
71
71
|
"subjectId": "$slug/unit-tests",
|
|
72
|
-
"
|
|
72
|
+
"facet": "flow-agents.workflow",
|
|
73
73
|
"claimType": "workflow.check.test",
|
|
74
74
|
"fieldOrBehavior": "unit tests pass",
|
|
75
75
|
"value": "pass",
|
|
@@ -256,7 +256,7 @@ mkdir -p "$AC2MB_DIR"
|
|
|
256
256
|
# Seed: empty bundle (no claims) + no block + expected criterion absent → missed_block
|
|
257
257
|
cat > "$AC2MB_DIR/trust.bundle" <<JSON
|
|
258
258
|
{
|
|
259
|
-
"schemaVersion":
|
|
259
|
+
"schemaVersion": 5,
|
|
260
260
|
"source": "gate-review-test;statusFunctionVersion=1",
|
|
261
261
|
"claims": [],
|
|
262
262
|
"evidence": [],
|
|
@@ -34,21 +34,21 @@ c2=$(run_block "$TMPDIR_EVAL/b2.err")
|
|
|
34
34
|
c3=$(run_block "$TMPDIR_EVAL/b3.err")
|
|
35
35
|
c4=$(run_block "$TMPDIR_EVAL/b4.err")
|
|
36
36
|
|
|
37
|
-
[[ "$c1" -eq 2 ]] && rg -q '
|
|
38
|
-
&& _pass "first identical block exits 2 (
|
|
39
|
-
|| _fail "first block should exit 2
|
|
37
|
+
[[ "$c1" -eq 2 ]] && rg -q 'Stop blocked .* \(block 1; after 3 identical blocks' "$TMPDIR_EVAL/b1.err" \
|
|
38
|
+
&& _pass "first identical block exits 2 (block 1; after 3 identical blocks)" \
|
|
39
|
+
|| _fail "first block should exit 2, block 1/3 shape (got $c1: $(cat "$TMPDIR_EVAL/b1.err"))"
|
|
40
40
|
|
|
41
|
-
[[ "$c2" -eq 2 ]] && rg -q '
|
|
42
|
-
&& _pass "second identical block exits 2 (
|
|
43
|
-
|| _fail "second block should exit 2
|
|
41
|
+
[[ "$c2" -eq 2 ]] && rg -q 'Stop blocked .* \(block 2; after 3 identical blocks' "$TMPDIR_EVAL/b2.err" \
|
|
42
|
+
&& _pass "second identical block exits 2 (block 2; after 3 identical blocks)" \
|
|
43
|
+
|| _fail "second block should exit 2, block 2/3 shape (got $c2)"
|
|
44
44
|
|
|
45
|
-
[[ "$c3" -eq 0 ]] && rg -q '
|
|
45
|
+
[[ "$c3" -eq 0 ]] && rg -q 'released — the same gap\(s\) blocked 3x without progress' "$TMPDIR_EVAL/b3.err" \
|
|
46
46
|
&& _pass "third identical block RELEASES (exit 0, loud notice)" \
|
|
47
47
|
|| _fail "third block should release exit 0 (got $c3: $(cat "$TMPDIR_EVAL/b3.err"))"
|
|
48
48
|
|
|
49
|
-
[[ "$c4" -eq 2 ]] && rg -q '
|
|
49
|
+
[[ "$c4" -eq 2 ]] && rg -q 'Stop blocked .* \(block 1; after 3 identical blocks' "$TMPDIR_EVAL/b4.err" \
|
|
50
50
|
&& _pass "streak resets after release (next block is 1/3 again)" \
|
|
51
|
-
|| _fail "post-release block should reset to
|
|
51
|
+
|| _fail "post-release block should reset to block 1/3 shape (got $c4)"
|
|
52
52
|
|
|
53
53
|
# A changing goal-fit gap must reset the streak (progress, not a stuck loop).
|
|
54
54
|
printf '%s' "$PAYLOAD" | FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=3 node "$ROOT/scripts/hooks/stop-goal-fit.js" >/dev/null 2>/dev/null
|
|
@@ -56,7 +56,7 @@ printf '%s' "$PAYLOAD" | FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_MA
|
|
|
56
56
|
printf '# Stuck\n\nbranch: main\nstatus: verifying\ntype: deliver\n\n## Plan\n\nDifferent.\n' \
|
|
57
57
|
> "$REPO/.flow-agents/stuck/stuck--deliver.md"
|
|
58
58
|
cd=$(run_block "$TMPDIR_EVAL/bd.err")
|
|
59
|
-
[[ "$cd" -eq 2 ]] && rg -q '
|
|
59
|
+
[[ "$cd" -eq 2 ]] && rg -q 'Stop blocked .* \(block 1; after 3 identical blocks' "$TMPDIR_EVAL/bd.err" \
|
|
60
60
|
&& _pass "changed goal-fit gap resets the streak to 1/3" \
|
|
61
61
|
|| _fail "changed gap should reset streak (got $cd: $(cat "$TMPDIR_EVAL/bd.err"))"
|
|
62
62
|
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# test_goal_fit_ghost_session.sh — WS8 (AC10) stop-goal-fit hardening.
|
|
3
|
+
#
|
|
4
|
+
# (a) GHOST-SESSION: when current.json names a slug whose session directory does not exist,
|
|
5
|
+
# the hook LOGS the staleness and does NOT resurface an abandoned, markdown-only
|
|
6
|
+
# directory (no state.json / trust.bundle) as "the active session" via a global mtime
|
|
7
|
+
# scan. A directory is eligible as active only with real sidecar presence.
|
|
8
|
+
# (b) MALFORMED-EVIDENCE: a kind:"command" acceptance evidence ref whose excerpt is prose
|
|
9
|
+
# (a sentence, not a runnable command) is classified `malformed-evidence` — it is NOT
|
|
10
|
+
# spawned via `bash -lc "<a sentence>"` and NOT conflated with a caught false-completion.
|
|
11
|
+
#
|
|
12
|
+
# Deterministic, no model spend, self-cleaning.
|
|
13
|
+
# Usage: bash evals/integration/test_goal_fit_ghost_session.sh
|
|
14
|
+
|
|
15
|
+
set -uo pipefail
|
|
16
|
+
|
|
17
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
18
|
+
HOOK="$ROOT/scripts/hooks/stop-goal-fit.js"
|
|
19
|
+
|
|
20
|
+
TMP="$(mktemp -d)"
|
|
21
|
+
errors=0
|
|
22
|
+
_pass() { echo " PASS: $1"; }
|
|
23
|
+
_fail() { echo " FAIL: $1"; errors=$((errors + 1)); }
|
|
24
|
+
cleanup() { rm -rf "$TMP"; }
|
|
25
|
+
trap cleanup EXIT
|
|
26
|
+
|
|
27
|
+
# ─── (a) GHOST-SESSION ─────────────────────────────────────────────────────────
|
|
28
|
+
echo "=== AC10a: stale current.json slug does not resurface an abandoned markdown-only session ==="
|
|
29
|
+
REPO="$TMP/repo"
|
|
30
|
+
FA="$REPO/.kontourai/flow-agents"
|
|
31
|
+
mkdir -p "$FA/old-abandoned"
|
|
32
|
+
printf '# Test Repo\n' > "$REPO/AGENTS.md"
|
|
33
|
+
|
|
34
|
+
# An abandoned session: ACTIVE status, but only a markdown artifact (no state.json / trust.bundle).
|
|
35
|
+
cat > "$FA/old-abandoned/old-abandoned--deliver.md" <<'MD'
|
|
36
|
+
# Old abandoned session
|
|
37
|
+
|
|
38
|
+
branch: main
|
|
39
|
+
worktree: main
|
|
40
|
+
created: 2026-01-01
|
|
41
|
+
status: executing
|
|
42
|
+
type: deliver
|
|
43
|
+
|
|
44
|
+
## Plan
|
|
45
|
+
|
|
46
|
+
Abandoned long ago; never had sidecars.
|
|
47
|
+
MD
|
|
48
|
+
|
|
49
|
+
# current.json points at a slug whose directory does NOT exist (stale pointer).
|
|
50
|
+
cat > "$FA/current.json" <<'JSON'
|
|
51
|
+
{ "schema_version": "1.0", "active_slug": "ghost-slug", "artifact_dir": "ghost-slug", "updated_at": "2026-07-02T00:00:00Z", "owner": "workflow-sidecar", "source": "ensure-session", "active_agents": [] }
|
|
52
|
+
JSON
|
|
53
|
+
|
|
54
|
+
out_a="$(echo '{"hook_event_name":"Stop","cwd":"'"$REPO"'"}' | node "$HOOK" 2>"$TMP/a.err")"
|
|
55
|
+
exit_a=$?
|
|
56
|
+
err_a="$(cat "$TMP/a.err")"
|
|
57
|
+
|
|
58
|
+
if echo "$err_a" | grep -q 'no such session directory exists'; then
|
|
59
|
+
_pass "staleness is LOGGED (stale current.json slug is visible, not silently swallowed)"
|
|
60
|
+
else
|
|
61
|
+
_fail "expected a staleness log for the stale current.json slug; stderr: $err_a"
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
if echo "$err_a" | grep -q 'old-abandoned'; then
|
|
65
|
+
_fail "abandoned markdown-only session was resurfaced as active (should be filtered — no sidecar): $err_a"
|
|
66
|
+
else
|
|
67
|
+
_pass "abandoned markdown-only session (no state.json/trust.bundle) was NOT resurfaced as active"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
if [[ $exit_a -eq 0 ]]; then
|
|
71
|
+
_pass "no block from a stale pointer + abandoned session (exit 0)"
|
|
72
|
+
else
|
|
73
|
+
_fail "expected exit 0 (nothing genuinely active), got $exit_a"
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# ─── (b) MALFORMED-EVIDENCE ─────────────────────────────────────────────────────
|
|
77
|
+
echo ""
|
|
78
|
+
echo "=== AC10b: prose kind:command evidence ref is classified malformed, never spawned as bash ==="
|
|
79
|
+
if node - "$ROOT" << 'NODE'
|
|
80
|
+
const path = require('path');
|
|
81
|
+
const mod = require(path.join(process.argv[2], 'scripts/hooks/stop-goal-fit.js'));
|
|
82
|
+
const check = { id: 'unit', command: '', kind: 'test', status: 'not_verified' };
|
|
83
|
+
const prose = { criteria: [ { id: 'unit', evidence_refs: [ { kind: 'command', excerpt: 'Manually verify the dashboard renders the export button and click it.' } ] } ] };
|
|
84
|
+
const runnable = { criteria: [ { id: 'unit', evidence_refs: [ { kind: 'command', excerpt: 'npm test' } ] } ] };
|
|
85
|
+
const r1 = mod.resolveTrustedCommand('/repo', '/repo/.kontourai/flow-agents/x', check, prose);
|
|
86
|
+
const r2 = mod.resolveTrustedCommand('/repo', '/repo/.kontourai/flow-agents/x', check, runnable);
|
|
87
|
+
if (!(r1 && r1.malformed && !r1.argv)) { console.error('prose ref NOT classified malformed: ' + JSON.stringify(r1)); process.exit(1); }
|
|
88
|
+
if (!(r2 && Array.isArray(r2.argv) && r2.argv[0] === 'bash' && r2.argv[2] === 'npm test')) { console.error('runnable ref did not resolve to an argv: ' + JSON.stringify(r2)); process.exit(1); }
|
|
89
|
+
process.exit(0);
|
|
90
|
+
NODE
|
|
91
|
+
then
|
|
92
|
+
_pass "prose acceptance command ref → {malformed} (no argv); runnable ref → executable argv"
|
|
93
|
+
else
|
|
94
|
+
_fail "resolveTrustedCommand mishandled prose vs runnable command refs"
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
echo ""
|
|
98
|
+
if [[ $errors -eq 0 ]]; then
|
|
99
|
+
echo "test_goal_fit_ghost_session: all checks passed."
|
|
100
|
+
exit 0
|
|
101
|
+
else
|
|
102
|
+
echo "test_goal_fit_ghost_session: $errors check(s) failed."
|
|
103
|
+
exit 1
|
|
104
|
+
fi
|