@kontourai/flow-agents 2.3.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/CODEOWNERS +16 -0
- package/.github/workflows/ci.yml +44 -0
- package/.github/workflows/trust-reconcile.yml +62 -4
- package/AGENTS.md +4 -4
- package/CHANGELOG.md +62 -0
- package/CONTEXT.md +35 -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/assignment-provider.d.ts +1 -0
- package/build/src/cli/assignment-provider.js +748 -0
- package/build/src/cli/console-learning-projection.js +3 -2
- package/build/src/cli/effective-assignment-provider-settings.d.ts +1 -0
- package/build/src/cli/effective-assignment-provider-settings.js +125 -0
- 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 +27 -7
- 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 +938 -168
- package/build/src/cli.js +6 -0
- 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 +24 -1
- package/console.telemetry.json +22 -0
- package/context/contracts/artifact-contract.md +40 -7
- package/context/contracts/assignment-provider-contract.md +239 -0
- package/context/contracts/builder-kit-workflow-state-contract.md +5 -2
- package/context/contracts/decision-registry-contract.md +265 -0
- package/context/contracts/delivery-contract.md +3 -1
- package/context/contracts/execution-contract.md +25 -0
- package/context/contracts/governance-adapter-contract.md +2 -0
- package/context/contracts/knowledge-store-contract.md +197 -0
- package/context/contracts/planning-contract.md +4 -1
- package/context/contracts/review-contract.md +7 -3
- package/context/contracts/sandbox-policy.md +2 -0
- package/context/contracts/standing-directives.md +13 -0
- package/context/contracts/verification-contract.md +11 -1
- package/context/contracts/work-item-contract.md +3 -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/context/settings/assignment-provider-settings.json +33 -0
- 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 +463 -0
- package/docs/agent-system-guidebook.md +3 -3
- package/docs/agent-usage-feedback-loop.md +6 -6
- package/docs/context-map.md +10 -7
- package/docs/decisions/decision-records.md +57 -0
- package/docs/decisions/index.md +17 -0
- package/docs/decisions/knowledge-store-provider.md +51 -0
- package/docs/decisions/model-routing.md +63 -0
- package/docs/decisions/promotion-gate.md +52 -0
- package/docs/decisions/standing-directives.md +66 -0
- package/docs/developer-architecture.md +1 -1
- package/docs/fixture-ownership.md +4 -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 +3 -2
- package/docs/workflow-usage-guide.md +260 -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 +71 -1
- package/evals/fixtures/assignment-provider/actor-a.json +6 -0
- package/evals/fixtures/assignment-provider/actor-b.json +6 -0
- package/evals/fixtures/assignment-provider/github-issue-claimed.json +27 -0
- package/evals/fixtures/assignment-provider/github-issue-unassigned.json +7 -0
- package/evals/fixtures/assignment-provider/liveness-fresh.json +9 -0
- package/evals/fixtures/assignment-provider/liveness-stale.json +9 -0
- 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_assignment_provider_github.sh +318 -0
- package/evals/integration/test_assignment_provider_local_file.sh +222 -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_critique_supersession_roundtrip.sh +182 -0
- 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 +23 -6
- package/evals/integration/test_pull_work_assignment_join.sh +132 -0
- package/evals/integration/test_pull_work_liveness_preflight.sh +394 -0
- package/evals/integration/test_pull_work_provider.sh +2 -2
- package/evals/integration/test_reconcile_soundness.sh +37 -13
- 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 +11 -10
- 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 +759 -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 +802 -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 +32 -0
- package/evals/static/test_decisions.sh +150 -0
- package/evals/static/test_flowdef_codeowners_coverage.sh +62 -0
- package/evals/static/test_knowledge_providers.sh +23 -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 +32 -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 +148 -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/knowledge/kit.json +35 -0
- package/kits/knowledge/providers/conformance/fixtures/git-repo/CONTEXT.md +12 -0
- package/kits/knowledge/providers/conformance/fixtures/git-repo/docs/decisions/old-sprocket-shape.md +13 -0
- package/kits/knowledge/providers/conformance/fixtures/git-repo/docs/decisions/sprocket-shape.md +14 -0
- package/kits/knowledge/providers/conformance/fixtures/git-repo/docs/decisions/widget-format.md +14 -0
- package/kits/knowledge/providers/conformance/fixtures/git-repo/docs/learnings/fixture-learning.md +7 -0
- package/kits/knowledge/providers/conformance/fixtures/work-item/issues.json +30 -0
- package/kits/knowledge/providers/conformance/suite.test.js +125 -0
- package/kits/knowledge/providers/git-repo/index.js +236 -0
- package/kits/knowledge/providers/health/health-pass.test.js +99 -0
- package/kits/knowledge/providers/health/index.js +153 -0
- package/kits/knowledge/providers/index.js +24 -0
- package/kits/knowledge/providers/lib/model.js +91 -0
- package/kits/knowledge/providers/lib/schema-validate.js +119 -0
- package/kits/knowledge/providers/markdown-vault/index.js +169 -0
- package/kits/knowledge/providers/work-item/index.js +204 -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 +11 -5
- 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/assignment-provider-settings.schema.json +125 -0
- package/schemas/decision-record.schema.json +109 -0
- package/schemas/knowledge/edge.schema.json +54 -0
- package/schemas/knowledge/health-report.schema.json +45 -0
- package/schemas/knowledge/node.schema.json +49 -0
- package/schemas/knowledge/proposal.schema.json +53 -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 +957 -103
- 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/assignment-provider.ts +845 -0
- package/src/cli/console-learning-projection.ts +3 -2
- package/src/cli/effective-assignment-provider-settings.ts +112 -0
- 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 +27 -7
- 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 +933 -168
- package/src/cli.ts +6 -0
- 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 +24 -1
|
@@ -34,7 +34,7 @@ run_bounded() {
|
|
|
34
34
|
|
|
35
35
|
WRITER="workflow-sidecar"
|
|
36
36
|
VALIDATOR="validate-workflow-artifacts"
|
|
37
|
-
ARTIFACT_DIR="$TMPDIR_EVAL/repo/.flow-agents/auto-sidecars"
|
|
37
|
+
ARTIFACT_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/auto-sidecars"
|
|
38
38
|
mkdir -p "$ARTIFACT_DIR"
|
|
39
39
|
|
|
40
40
|
DEFAULT_ROOT_REPO="$TMPDIR_EVAL/default-root-repo"
|
|
@@ -56,22 +56,57 @@ else
|
|
|
56
56
|
_fail "sidecar writer default-root ensure-session failed: $(cat "$TMPDIR_EVAL/default-root.out" "$TMPDIR_EVAL/default-root.err")"
|
|
57
57
|
fi
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
mkdir -p "$
|
|
61
|
-
cat > "$
|
|
62
|
-
{"schema_version":"1.0","active_slug":"
|
|
59
|
+
PREVIOUS_ROOT_REPO="$TMPDIR_EVAL/previous-root-repo"
|
|
60
|
+
mkdir -p "$PREVIOUS_ROOT_REPO/.flow-agents/previous-session"
|
|
61
|
+
cat > "$PREVIOUS_ROOT_REPO/.flow-agents/current.json" <<'JSON'
|
|
62
|
+
{"schema_version":"1.0","active_slug":"previous-session","artifact_dir":"previous-session"}
|
|
63
63
|
JSON
|
|
64
|
-
cat > "$
|
|
65
|
-
{"schema_version":"1.0","task_slug":"
|
|
64
|
+
cat > "$PREVIOUS_ROOT_REPO/.flow-agents/previous-session/state.json" <<'JSON'
|
|
65
|
+
{"schema_version":"1.0","task_slug":"previous-session","status":"planned","phase":"planning","next_action":{"status":"continue","summary":"continue"}}
|
|
66
66
|
JSON
|
|
67
|
-
if (cd "$
|
|
68
|
-
|
|
69
|
-
_pass "sidecar writer reads legacy .flow-agents current session when no new root exists"
|
|
67
|
+
if (cd "$PREVIOUS_ROOT_REPO" && flow_agents_node "$WRITER" current --format slug >"$TMPDIR_EVAL/previous-current.out" 2>"$TMPDIR_EVAL/previous-current.err"); then
|
|
68
|
+
_fail "sidecar writer default current unexpectedly read previous .flow-agents runtime root: $(cat "$TMPDIR_EVAL/previous-current.out")"
|
|
70
69
|
else
|
|
71
|
-
|
|
70
|
+
_pass "sidecar writer does not fall back to previous .flow-agents runtime root"
|
|
72
71
|
fi
|
|
73
72
|
|
|
74
|
-
|
|
73
|
+
if (cd "$PREVIOUS_ROOT_REPO" && flow_agents_node "$WRITER" current --artifact-root "$PREVIOUS_ROOT_REPO/.flow-agents" --format slug >"$TMPDIR_EVAL/previous-current-explicit.out" 2>"$TMPDIR_EVAL/previous-current-explicit.err") \
|
|
74
|
+
&& [[ "$(cat "$TMPDIR_EVAL/previous-current-explicit.out")" == "previous-session" ]]; then
|
|
75
|
+
_pass "sidecar writer reads explicitly supplied artifact root"
|
|
76
|
+
else
|
|
77
|
+
_fail "sidecar writer did not read explicit artifact root: $(cat "$TMPDIR_EVAL/previous-current-explicit.out" "$TMPDIR_EVAL/previous-current-explicit.err")"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
TRAVERSAL_ROOT="$TMPDIR_EVAL/traversal-repo/.kontourai/flow-agents"
|
|
81
|
+
TRAVERSAL_OUTSIDE="$TMPDIR_EVAL/traversal-outside-existing"
|
|
82
|
+
mkdir -p "$TRAVERSAL_ROOT" "$TRAVERSAL_OUTSIDE"
|
|
83
|
+
node - "$TRAVERSAL_ROOT" "$TRAVERSAL_OUTSIDE" <<'NODE'
|
|
84
|
+
const fs = require("node:fs");
|
|
85
|
+
const path = require("node:path");
|
|
86
|
+
const root = process.argv[2];
|
|
87
|
+
const outside = process.argv[3];
|
|
88
|
+
fs.writeFileSync(path.join(root, "current.json"), JSON.stringify({
|
|
89
|
+
schema_version: "1.0",
|
|
90
|
+
active_slug: "escape",
|
|
91
|
+
artifact_dir: path.relative(root, outside),
|
|
92
|
+
updated_at: "2026-05-09T00:00:00Z",
|
|
93
|
+
}) + "\n");
|
|
94
|
+
NODE
|
|
95
|
+
if run_bounded 20 flow_agents_node "$WRITER" record-agent-event \
|
|
96
|
+
--artifact-root "$TRAVERSAL_ROOT" \
|
|
97
|
+
--agent-id tool-worker \
|
|
98
|
+
--kind note \
|
|
99
|
+
--status active \
|
|
100
|
+
--summary "must not write outside" \
|
|
101
|
+
>"$TMPDIR_EVAL/current-traversal.out" 2>"$TMPDIR_EVAL/current-traversal.err"; then
|
|
102
|
+
_fail "sidecar writer accepted current.json artifact_dir outside artifact root"
|
|
103
|
+
elif [[ ! -e "$TRAVERSAL_OUTSIDE/agents" ]]; then
|
|
104
|
+
_pass "sidecar writer rejects current.json artifact_dir outside artifact root"
|
|
105
|
+
else
|
|
106
|
+
_fail "sidecar writer wrote agent events outside artifact root"
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
SESSION_ROOT="$TMPDIR_EVAL/repo/.kontourai/flow-agents"
|
|
75
110
|
if flow_agents_node "$WRITER" ensure-session \
|
|
76
111
|
--artifact-root "$SESSION_ROOT" \
|
|
77
112
|
--task-slug ensured-session \
|
|
@@ -118,12 +153,12 @@ if (cd "$UNSAFE_REPO_ROOT" \
|
|
|
118
153
|
&& git init -q \
|
|
119
154
|
&& git remote add origin "file:///Users/alice/customer-secret.git" \
|
|
120
155
|
&& FLOW_AGENTS_REPO="/Users/alice/customer-secret" flow_agents_node "$WRITER" ensure-session \
|
|
121
|
-
--artifact-root ".flow-agents" \
|
|
156
|
+
--artifact-root ".kontourai/flow-agents" \
|
|
122
157
|
--task-slug unsafe-repo \
|
|
123
158
|
--title "Unsafe repo" \
|
|
124
159
|
--summary "Unsafe repo fallback." \
|
|
125
160
|
--timestamp "2026-05-09T00:00:00Z" >/dev/null 2>"$TMPDIR_EVAL/unsafe-repo.err" \
|
|
126
|
-
&& node - ".flow-agents/unsafe-repo/state.json" <<'NODE'
|
|
161
|
+
&& node - ".kontourai/flow-agents/unsafe-repo/state.json" <<'NODE'
|
|
127
162
|
const fs = require("node:fs");
|
|
128
163
|
const repo = JSON.parse(fs.readFileSync(process.argv[2], "utf8")).repo;
|
|
129
164
|
if (repo !== "unsafe-repo") throw new Error(`unsafe repo fallback was ${JSON.stringify(repo)}`);
|
|
@@ -162,8 +197,8 @@ else
|
|
|
162
197
|
fi
|
|
163
198
|
|
|
164
199
|
cp "$SESSION_ROOT/current.json" "$TMPDIR_EVAL/current-before-traversal-agent.json"
|
|
165
|
-
TRAVERSAL_AGENT_OUTSIDE="$TMPDIR_EVAL/repo/.flow-agents/evil-agent-outside.jsonl"
|
|
166
|
-
if run_bounded
|
|
200
|
+
TRAVERSAL_AGENT_OUTSIDE="$TMPDIR_EVAL/repo/.kontourai/flow-agents/evil-agent-outside.jsonl"
|
|
201
|
+
if run_bounded 20 flow_agents_node "$WRITER" record-agent-event \
|
|
167
202
|
--artifact-root "$SESSION_ROOT" \
|
|
168
203
|
--agent-id ../evil-agent-outside \
|
|
169
204
|
--kind evidence \
|
|
@@ -219,7 +254,7 @@ if flow_agents_node "$WRITER" ensure-session \
|
|
|
219
254
|
--timestamp "2026-05-09T00:00:50Z" >"$TMPDIR_EVAL/ensure-traversal.out" 2>&1; then
|
|
220
255
|
_fail "sidecar writer should reject traversal task slugs"
|
|
221
256
|
elif rg -q -- '--task-slug must not contain' "$TMPDIR_EVAL/ensure-traversal.out" \
|
|
222
|
-
&& [[ ! -d "$TMPDIR_EVAL/repo/.flow-agents/outside" ]]; then
|
|
257
|
+
&& [[ ! -d "$TMPDIR_EVAL/repo/.kontourai/flow-agents/outside" ]]; then
|
|
223
258
|
_pass "sidecar writer rejects traversal task slugs without creating outside dirs"
|
|
224
259
|
else
|
|
225
260
|
_fail "sidecar writer traversal rejection was not fail-closed: $(cat "$TMPDIR_EVAL/ensure-traversal.out")"
|
|
@@ -249,7 +284,7 @@ mkdir -p "$COPIED_ROOT"
|
|
|
249
284
|
cp -R "$ENSURED_DIR" "$COPIED_DIR"
|
|
250
285
|
cp "$SESSION_ROOT/current.json" "$TMPDIR_EVAL/current-before-copied-agent.json"
|
|
251
286
|
COPIED_AGENT_EVENT_PATH="$COPIED_DIR/ag""ents/copied-worker/events.jsonl"
|
|
252
|
-
if run_bounded
|
|
287
|
+
if run_bounded 20 flow_agents_node "$WRITER" record-agent-event \
|
|
253
288
|
--artifact-dir "$COPIED_DIR" \
|
|
254
289
|
--agent-id copied-worker \
|
|
255
290
|
--kind evidence \
|
|
@@ -269,7 +304,7 @@ fi
|
|
|
269
304
|
|
|
270
305
|
cp "$SESSION_ROOT/current.json" "$TMPDIR_EVAL/current-before-mismatch-agent.json"
|
|
271
306
|
MISMATCH_AGENT_EVENT_PATH="$COPIED_DIR/ag""ents/mismatch-worker/events.jsonl"
|
|
272
|
-
if run_bounded
|
|
307
|
+
if run_bounded 20 flow_agents_node "$WRITER" record-agent-event \
|
|
273
308
|
--artifact-root "$SESSION_ROOT" \
|
|
274
309
|
--artifact-dir "$COPIED_DIR" \
|
|
275
310
|
--agent-id mismatch-worker \
|
|
@@ -293,7 +328,7 @@ SYMLINK_DIR="$SESSION_ROOT/symlink-session"
|
|
|
293
328
|
mkdir -p "$SYMLINK_TARGET"
|
|
294
329
|
if ln -s "$SYMLINK_TARGET" "$SYMLINK_DIR" 2>"$TMPDIR_EVAL/symlink-create.err"; then
|
|
295
330
|
cp "$SESSION_ROOT/current.json" "$TMPDIR_EVAL/current-before-symlink-agent.json"
|
|
296
|
-
if run_bounded
|
|
331
|
+
if run_bounded 20 flow_agents_node "$WRITER" record-agent-event \
|
|
297
332
|
--artifact-root "$SESSION_ROOT" \
|
|
298
333
|
--artifact-dir "$SYMLINK_DIR" \
|
|
299
334
|
--agent-id symlink-worker \
|
|
@@ -422,12 +457,405 @@ if flow_agents_node "$WRITER" ensure-session \
|
|
|
422
457
|
--criterion "Different CLI criterion" \
|
|
423
458
|
--timestamp "2026-05-09T00:02:00Z" >"$TMPDIR_EVAL/ensure-existing.out" 2>"$TMPDIR_EVAL/ensure-existing.err" \
|
|
424
459
|
&& rg -q '"description": "Existing artifact criterion"' "$EXISTING_ONLY_DIR/acceptance.json" \
|
|
425
|
-
&& ! rg -q 'Different CLI criterion' "$EXISTING_ONLY_DIR/acceptance.json"
|
|
426
|
-
|
|
460
|
+
&& ! rg -q 'Different CLI criterion' "$EXISTING_ONLY_DIR/acceptance.json" \
|
|
461
|
+
&& rg -q '"branch": "main"' "$EXISTING_ONLY_DIR/state.json"; then
|
|
462
|
+
_pass "sidecar writer derives missing sidecars from existing session Markdown and preserves its own pre-#289 branch: main line (legacy, not re-derived)"
|
|
427
463
|
else
|
|
428
464
|
_fail "sidecar writer drifted sidecars from existing session Markdown: $(cat "$TMPDIR_EVAL/ensure-existing.out" "$TMPDIR_EVAL/ensure-existing.err")"
|
|
429
465
|
fi
|
|
430
466
|
|
|
467
|
+
# ─── #289: branch as first-class routing state (agent/<actor>/<slug>) ─────────
|
|
468
|
+
# AC2/AC7 (derivation + current.json mirror): a freshly created session with no explicit
|
|
469
|
+
# --actor derives its branch from the ambient runtime session id. CLAUDE_CODE_SESSION_ID is
|
|
470
|
+
# injected here to exercise the real Claude Code runtime-session-id path in
|
|
471
|
+
# actor-identity.js's resolveActor (rather than the --actor override seam) — state.json, the
|
|
472
|
+
# freshly seeded session Markdown, and current.json must all carry the same derived
|
|
473
|
+
# agent/<actor>/<slug> value.
|
|
474
|
+
BRANCH_ENV_DIR="$SESSION_ROOT/branch-session-env"
|
|
475
|
+
if CLAUDE_CODE_SESSION_ID="claude-session-alpha-001" flow_agents_node "$WRITER" ensure-session \
|
|
476
|
+
--artifact-root "$SESSION_ROOT" \
|
|
477
|
+
--task-slug branch-session-env \
|
|
478
|
+
--source-request "Derive a routing branch from an injected runtime session id." \
|
|
479
|
+
--summary "A fresh session with no explicit --actor should derive its branch from the injected runtime session id." \
|
|
480
|
+
--timestamp "2026-05-09T00:03:00Z" >"$TMPDIR_EVAL/branch-session-env.out" 2>"$TMPDIR_EVAL/branch-session-env.err" \
|
|
481
|
+
&& rg -q '"branch": "agent/claude-code-claude-session-alpha-001-[A-Za-z0-9_.-]+/branch-session-env"' "$BRANCH_ENV_DIR/state.json" \
|
|
482
|
+
&& grep -Eq '^branch: agent/claude-code-claude-session-alpha-001-[A-Za-z0-9_.-]+/branch-session-env$' "$BRANCH_ENV_DIR/branch-session-env--deliver.md" \
|
|
483
|
+
&& rg -q '"branch": "agent/claude-code-claude-session-alpha-001-[A-Za-z0-9_.-]+/branch-session-env"' "$SESSION_ROOT/current.json"; then
|
|
484
|
+
_pass "sidecar writer derives agent/<actor>/<slug> branch from an injected runtime session id into state.json, markdown, and current.json (AC2, AC7)"
|
|
485
|
+
else
|
|
486
|
+
_fail "sidecar writer did not derive a consistent injected-session-id branch across state.json/markdown/current.json: $(cat "$TMPDIR_EVAL/branch-session-env.out" "$TMPDIR_EVAL/branch-session-env.err")"
|
|
487
|
+
fi
|
|
488
|
+
|
|
489
|
+
# AC3 (explicit override): --branch on a brand-new session records the value verbatim,
|
|
490
|
+
# not a derived agent/<actor>/<slug> name.
|
|
491
|
+
BRANCH_OVERRIDE_DIR="$SESSION_ROOT/branch-override-a"
|
|
492
|
+
if flow_agents_node "$WRITER" ensure-session \
|
|
493
|
+
--artifact-root "$SESSION_ROOT" \
|
|
494
|
+
--task-slug branch-override-a \
|
|
495
|
+
--branch "custom/my-branch" \
|
|
496
|
+
--source-request "An explicit --branch overrides derivation." \
|
|
497
|
+
--summary "A brand-new session with --branch should record the value verbatim." \
|
|
498
|
+
--timestamp "2026-05-09T00:03:05Z" >"$TMPDIR_EVAL/branch-override.out" 2>"$TMPDIR_EVAL/branch-override.err" \
|
|
499
|
+
&& rg -q '"branch": "custom/my-branch"' "$BRANCH_OVERRIDE_DIR/state.json" \
|
|
500
|
+
&& grep -Eq '^branch: custom/my-branch$' "$BRANCH_OVERRIDE_DIR/branch-override-a--deliver.md"; then
|
|
501
|
+
_pass "sidecar writer records an explicit --branch value verbatim, not a derived name (AC3)"
|
|
502
|
+
else
|
|
503
|
+
_fail "sidecar writer did not honor an explicit --branch override: $(cat "$TMPDIR_EVAL/branch-override.out" "$TMPDIR_EVAL/branch-override.err")"
|
|
504
|
+
fi
|
|
505
|
+
|
|
506
|
+
# AC4 (distinct actors): two fresh sessions with distinct explicit --actor values produce
|
|
507
|
+
# distinct branch values, differing only in the actor segment.
|
|
508
|
+
BRANCH_DERIVE_A_DIR="$SESSION_ROOT/branch-derive-a"
|
|
509
|
+
BRANCH_DERIVE_B_DIR="$SESSION_ROOT/branch-derive-b"
|
|
510
|
+
if flow_agents_node "$WRITER" ensure-session \
|
|
511
|
+
--artifact-root "$SESSION_ROOT" \
|
|
512
|
+
--task-slug branch-derive-a \
|
|
513
|
+
--actor test-actor-alpha \
|
|
514
|
+
--source-request "Derive a branch for actor alpha." \
|
|
515
|
+
--summary "Distinct actor alpha." \
|
|
516
|
+
--timestamp "2026-05-09T00:03:10Z" >"$TMPDIR_EVAL/branch-derive-a.out" 2>"$TMPDIR_EVAL/branch-derive-a.err" \
|
|
517
|
+
&& flow_agents_node "$WRITER" ensure-session \
|
|
518
|
+
--artifact-root "$SESSION_ROOT" \
|
|
519
|
+
--task-slug branch-derive-b \
|
|
520
|
+
--actor test-actor-beta \
|
|
521
|
+
--source-request "Derive a branch for actor beta." \
|
|
522
|
+
--summary "Distinct actor beta." \
|
|
523
|
+
--timestamp "2026-05-09T00:03:11Z" >"$TMPDIR_EVAL/branch-derive-b.out" 2>"$TMPDIR_EVAL/branch-derive-b.err" \
|
|
524
|
+
&& rg -q '"branch": "agent/test-actor-alpha/branch-derive-a"' "$BRANCH_DERIVE_A_DIR/state.json" \
|
|
525
|
+
&& rg -q '"branch": "agent/test-actor-beta/branch-derive-b"' "$BRANCH_DERIVE_B_DIR/state.json"; then
|
|
526
|
+
_pass "sidecar writer derives distinct branch values for distinct actors (AC4)"
|
|
527
|
+
else
|
|
528
|
+
_fail "sidecar writer did not derive distinct branches for distinct actors: $(cat "$TMPDIR_EVAL/branch-derive-a.out" "$TMPDIR_EVAL/branch-derive-a.err" "$TMPDIR_EVAL/branch-derive-b.out" "$TMPDIR_EVAL/branch-derive-b.err")"
|
|
529
|
+
fi
|
|
530
|
+
|
|
531
|
+
# AC5 (existing-session continuity): re-running ensure-session against the SAME slug from a
|
|
532
|
+
# DIFFERENT actor never re-derives or overwrites the already-recorded branch (ADR 0021 §5
|
|
533
|
+
# takeover continuity — resume the incumbent's branch, never a parallel one).
|
|
534
|
+
if flow_agents_node "$WRITER" ensure-session \
|
|
535
|
+
--artifact-root "$SESSION_ROOT" \
|
|
536
|
+
--task-slug branch-derive-a \
|
|
537
|
+
--actor test-actor-gamma \
|
|
538
|
+
--source-request "A takeover by a different actor must not refork the branch." \
|
|
539
|
+
--summary "Resuming actor gamma should inherit alpha's already-recorded branch." \
|
|
540
|
+
--timestamp "2026-05-09T00:03:12Z" >"$TMPDIR_EVAL/branch-no-rederive.out" 2>"$TMPDIR_EVAL/branch-no-rederive.err" \
|
|
541
|
+
&& rg -q '"branch": "agent/test-actor-alpha/branch-derive-a"' "$BRANCH_DERIVE_A_DIR/state.json" \
|
|
542
|
+
&& ! rg -q 'test-actor-gamma' "$BRANCH_DERIVE_A_DIR/state.json"; then
|
|
543
|
+
_pass "sidecar writer never re-derives an existing session's branch for a later actor (AC5, ADR 0021 §5)"
|
|
544
|
+
else
|
|
545
|
+
_fail "sidecar writer re-derived or overwrote an existing session's branch on takeover: $(cat "$TMPDIR_EVAL/branch-no-rederive.out" "$TMPDIR_EVAL/branch-no-rederive.err")"
|
|
546
|
+
fi
|
|
547
|
+
|
|
548
|
+
# ─── #309: init-plan (and advance-state) must never drop an already-recorded branch ────
|
|
549
|
+
# Regression cover for the full ensure-session -> init-plan -> advance-state lifecycle every
|
|
550
|
+
# real session goes through. init-plan is invoked (per plan-work/SKILL.md) against the
|
|
551
|
+
# PLAN artifact the tool-planner writes (e.g. "<slug>--plan-work.md"), a DIFFERENT file than
|
|
552
|
+
# the session "<slug>--deliver.md" that carries the "branch:" line ensure-session seeded — that
|
|
553
|
+
# plan artifact below deliberately carries NO "branch:" field, reproducing the exact shape of
|
|
554
|
+
# the live kontourai-flow-agents-166 regression. state.json (and current.json's mirror) must
|
|
555
|
+
# still carry the derived branch after init-plan, and again after a subsequent advance-state.
|
|
556
|
+
BRANCH_SEQ_DIR="$SESSION_ROOT/branch-full-sequence"
|
|
557
|
+
if flow_agents_node "$WRITER" ensure-session \
|
|
558
|
+
--artifact-root "$SESSION_ROOT" \
|
|
559
|
+
--task-slug branch-full-sequence \
|
|
560
|
+
--actor seq-actor \
|
|
561
|
+
--source-request "Establish a session whose branch must survive init-plan and advance-state." \
|
|
562
|
+
--summary "Fresh session for the full ensure-session -> init-plan -> advance-state sequence." \
|
|
563
|
+
--timestamp "2026-07-01T00:04:20Z" >"$TMPDIR_EVAL/branch-seq-ensure.out" 2>"$TMPDIR_EVAL/branch-seq-ensure.err" \
|
|
564
|
+
&& rg -q '"branch": "agent/seq-actor/branch-full-sequence"' "$BRANCH_SEQ_DIR/state.json"; then
|
|
565
|
+
_pass "sidecar writer (#309 setup) seeds branch-full-sequence with a derived branch via ensure-session"
|
|
566
|
+
else
|
|
567
|
+
_fail "sidecar writer (#309 setup) failed to seed branch-full-sequence: $(cat "$TMPDIR_EVAL/branch-seq-ensure.out" "$TMPDIR_EVAL/branch-seq-ensure.err")"
|
|
568
|
+
fi
|
|
569
|
+
|
|
570
|
+
BRANCH_SEQ_PLAN_ARTIFACT="$BRANCH_SEQ_DIR/branch-full-sequence--plan-work.md"
|
|
571
|
+
cat > "$BRANCH_SEQ_PLAN_ARTIFACT" <<'MARKDOWN'
|
|
572
|
+
---
|
|
573
|
+
role: plan
|
|
574
|
+
parent: branch-full-sequence--deliver
|
|
575
|
+
created: 2026-07-01
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
# Plan: #309 branch survival fixture
|
|
579
|
+
|
|
580
|
+
## Plan
|
|
581
|
+
|
|
582
|
+
A plan artifact deliberately carrying no `branch:` line (mirrors the real tool-planner output).
|
|
583
|
+
|
|
584
|
+
## Definition Of Done
|
|
585
|
+
|
|
586
|
+
- **Acceptance criteria:**
|
|
587
|
+
- [ ] init-plan preserves the already-recorded branch - Evidence: pending.
|
|
588
|
+
MARKDOWN
|
|
589
|
+
|
|
590
|
+
if flow_agents_node "$WRITER" init-plan "$BRANCH_SEQ_PLAN_ARTIFACT" \
|
|
591
|
+
--source-request "Plan artifact carries no branch: line." \
|
|
592
|
+
--summary "Planning sidecars initialized from a branch-less plan artifact." \
|
|
593
|
+
--next-action "Advance to execution." \
|
|
594
|
+
--timestamp "2026-07-01T00:04:21Z" >"$TMPDIR_EVAL/branch-seq-initplan.out" 2>"$TMPDIR_EVAL/branch-seq-initplan.err" \
|
|
595
|
+
&& rg -q '"branch": "agent/seq-actor/branch-full-sequence"' "$BRANCH_SEQ_DIR/state.json"; then
|
|
596
|
+
_pass "sidecar writer (#309) preserves the already-recorded branch across init-plan even when the plan artifact carries no branch: line"
|
|
597
|
+
else
|
|
598
|
+
_fail "sidecar writer (#309) DROPPED the branch on init-plan: $(cat "$TMPDIR_EVAL/branch-seq-initplan.out" "$TMPDIR_EVAL/branch-seq-initplan.err"); state.json=$(cat "$BRANCH_SEQ_DIR/state.json" 2>/dev/null)"
|
|
599
|
+
fi
|
|
600
|
+
|
|
601
|
+
if flow_agents_node "$WRITER" advance-state "$BRANCH_SEQ_DIR" \
|
|
602
|
+
--status in_progress \
|
|
603
|
+
--phase execution \
|
|
604
|
+
--summary "Execution started." \
|
|
605
|
+
--next-action "Run checks." \
|
|
606
|
+
--timestamp "2026-07-01T00:04:22Z" >"$TMPDIR_EVAL/branch-seq-advance.out" 2>"$TMPDIR_EVAL/branch-seq-advance.err" \
|
|
607
|
+
&& rg -q '"branch": "agent/seq-actor/branch-full-sequence"' "$BRANCH_SEQ_DIR/state.json" \
|
|
608
|
+
&& rg -q '"branch": "agent/seq-actor/branch-full-sequence"' "$SESSION_ROOT/current.json"; then
|
|
609
|
+
_pass "sidecar writer (#309) still carries the branch in state.json and its current.json mirror after advance-state"
|
|
610
|
+
else
|
|
611
|
+
_fail "sidecar writer (#309) lost the branch by advance-state, or current.json mirror drifted: $(cat "$TMPDIR_EVAL/branch-seq-advance.out" "$TMPDIR_EVAL/branch-seq-advance.err"); state.json=$(cat "$BRANCH_SEQ_DIR/state.json" 2>/dev/null)"
|
|
612
|
+
fi
|
|
613
|
+
|
|
614
|
+
# #309 backfill repro: an ALREADY-BROKEN pre-fix session (state.json has no branch key at all,
|
|
615
|
+
# matching kontourai-flow-agents-166/-290) can be repaired by re-running init-plan against the
|
|
616
|
+
# SAME branch-less plan artifact that dropped the branch in the first place -- WITHOUT any direct
|
|
617
|
+
# file edit -- because initSidecars falls back to reading the session's own canonical
|
|
618
|
+
# "<slug>--deliver.md" from disk when neither the existing state.json nor the passed-in markdown
|
|
619
|
+
# carries a branch.
|
|
620
|
+
BRANCH_BACKFILL_DIR="$SESSION_ROOT/branch-backfill-repro"
|
|
621
|
+
mkdir -p "$BRANCH_BACKFILL_DIR"
|
|
622
|
+
cat > "$BRANCH_BACKFILL_DIR/branch-backfill-repro--deliver.md" <<'MARKDOWN'
|
|
623
|
+
# branch-backfill-repro
|
|
624
|
+
|
|
625
|
+
branch: agent/seq-actor/branch-backfill-repro
|
|
626
|
+
worktree: main
|
|
627
|
+
created: 2026-07-01T00:04:23Z
|
|
628
|
+
status: planning
|
|
629
|
+
type: deliver
|
|
630
|
+
iteration: 1
|
|
631
|
+
|
|
632
|
+
## Plan
|
|
633
|
+
|
|
634
|
+
Pre-fix victim fixture: state.json below was written WITHOUT a branch key (simulating #309).
|
|
635
|
+
MARKDOWN
|
|
636
|
+
cat > "$BRANCH_BACKFILL_DIR/state.json" <<'JSON'
|
|
637
|
+
{
|
|
638
|
+
"schema_version": "1.0",
|
|
639
|
+
"task_slug": "branch-backfill-repro",
|
|
640
|
+
"repo": "kontourai/flow-agents",
|
|
641
|
+
"status": "planned",
|
|
642
|
+
"phase": "planning",
|
|
643
|
+
"created_at": "2026-07-01T00:04:23Z",
|
|
644
|
+
"updated_at": "2026-07-01T00:04:23Z",
|
|
645
|
+
"artifact_paths": ["state.json"],
|
|
646
|
+
"next_action": { "status": "continue", "summary": "pre-fix victim fixture" }
|
|
647
|
+
}
|
|
648
|
+
JSON
|
|
649
|
+
BRANCH_BACKFILL_PLAN_ARTIFACT="$BRANCH_BACKFILL_DIR/branch-backfill-repro--plan-work.md"
|
|
650
|
+
cat > "$BRANCH_BACKFILL_PLAN_ARTIFACT" <<'MARKDOWN'
|
|
651
|
+
---
|
|
652
|
+
role: plan
|
|
653
|
+
parent: branch-backfill-repro--deliver
|
|
654
|
+
created: 2026-07-01
|
|
655
|
+
---
|
|
656
|
+
|
|
657
|
+
# Plan: #309 backfill repro fixture
|
|
658
|
+
|
|
659
|
+
## Definition Of Done
|
|
660
|
+
|
|
661
|
+
- **Acceptance criteria:**
|
|
662
|
+
- [ ] backfill repairs the dropped branch - Evidence: pending.
|
|
663
|
+
MARKDOWN
|
|
664
|
+
|
|
665
|
+
if flow_agents_node "$WRITER" init-plan "$BRANCH_BACKFILL_PLAN_ARTIFACT" \
|
|
666
|
+
--source-request "Re-run init-plan against the same branch-less plan artifact to backfill." \
|
|
667
|
+
--summary "Backfill re-run." \
|
|
668
|
+
--next-action "n/a" \
|
|
669
|
+
--timestamp "2026-07-01T00:04:23Z" >"$TMPDIR_EVAL/branch-backfill.out" 2>"$TMPDIR_EVAL/branch-backfill.err" \
|
|
670
|
+
&& rg -q '"branch": "agent/seq-actor/branch-backfill-repro"' "$BRANCH_BACKFILL_DIR/state.json"; then
|
|
671
|
+
_pass "sidecar writer (#309) backfills a pre-fix-broken session's branch via a sanctioned init-plan re-run (no direct file edit)"
|
|
672
|
+
else
|
|
673
|
+
_fail "sidecar writer (#309) failed to backfill an already-broken session's branch: $(cat "$TMPDIR_EVAL/branch-backfill.out" "$TMPDIR_EVAL/branch-backfill.err"); state.json=$(cat "$BRANCH_BACKFILL_DIR/state.json" 2>/dev/null)"
|
|
674
|
+
fi
|
|
675
|
+
|
|
676
|
+
# Actor charset guard: an explicit --actor value that strips to empty under the allowed
|
|
677
|
+
# charset dies before any session artifact is written (mirrors the liveness write path's
|
|
678
|
+
# existing F7 test coverage).
|
|
679
|
+
BRANCH_BAD_ACTOR_DIR="$SESSION_ROOT/branch-bad-actor"
|
|
680
|
+
if flow_agents_node "$WRITER" ensure-session \
|
|
681
|
+
--artifact-root "$SESSION_ROOT" \
|
|
682
|
+
--task-slug branch-bad-actor \
|
|
683
|
+
--actor ":::" \
|
|
684
|
+
--source-request "Garbage --actor should die." \
|
|
685
|
+
--summary "Should not create a session." \
|
|
686
|
+
--timestamp "2026-05-09T00:03:13Z" >"$TMPDIR_EVAL/branch-bad-actor.out" 2>"$TMPDIR_EVAL/branch-bad-actor.err"; then
|
|
687
|
+
_fail "sidecar writer should reject a --actor value that strips to empty under the allowed charset"
|
|
688
|
+
elif rg -q -- '--actor value strips to empty' "$TMPDIR_EVAL/branch-bad-actor.out" "$TMPDIR_EVAL/branch-bad-actor.err" \
|
|
689
|
+
&& [[ ! -f "$BRANCH_BAD_ACTOR_DIR/state.json" ]]; then
|
|
690
|
+
_pass "sidecar writer dies on a garbage --actor value before writing any session artifact"
|
|
691
|
+
else
|
|
692
|
+
_fail "garbage --actor rejection was not fail-closed or lacked diagnostics: $(cat "$TMPDIR_EVAL/branch-bad-actor.out" "$TMPDIR_EVAL/branch-bad-actor.err")"
|
|
693
|
+
fi
|
|
694
|
+
|
|
695
|
+
# ─── #289 fix-plan iteration 1 (F1/F2/F4) ──────────────────────────────────────
|
|
696
|
+
# F1: a trailing-dot slug (git-check-ref-format forbids a ref component ending in ".") derives a
|
|
697
|
+
# branch that is a REAL, valid git ref — asserted against the actual `git check-ref-format`
|
|
698
|
+
# binary, not a hand-rolled regex re-implementation of its rules.
|
|
699
|
+
BRANCH_TRAILING_DOT_DIR="$SESSION_ROOT/branch-trailing-dot"
|
|
700
|
+
if flow_agents_node "$WRITER" ensure-session \
|
|
701
|
+
--artifact-root "$SESSION_ROOT" \
|
|
702
|
+
--task-slug branch-trailing-dot \
|
|
703
|
+
--actor "my-fix." \
|
|
704
|
+
--source-request "A trailing-dot actor segment must not leave an illegal git ref." \
|
|
705
|
+
--summary "Trailing dot should be stripped, not left dangling." \
|
|
706
|
+
--timestamp "2026-07-01T00:04:00Z" >"$TMPDIR_EVAL/branch-trailing-dot.out" 2>"$TMPDIR_EVAL/branch-trailing-dot.err"; then
|
|
707
|
+
TRAILING_DOT_BRANCH="$(jq -r '.branch // empty' "$BRANCH_TRAILING_DOT_DIR/state.json" 2>/dev/null)"
|
|
708
|
+
if [[ -n "$TRAILING_DOT_BRANCH" ]] && [[ "$TRAILING_DOT_BRANCH" != *"." ]] && git check-ref-format --branch "$TRAILING_DOT_BRANCH" >/dev/null 2>&1; then
|
|
709
|
+
_pass "sidecar writer strips a trailing dot from a derived branch segment and the result passes the real git check-ref-format binary (F1)"
|
|
710
|
+
else
|
|
711
|
+
_fail "sidecar writer derived a branch that git check-ref-format rejects (F1): branch=$TRAILING_DOT_BRANCH"
|
|
712
|
+
fi
|
|
713
|
+
else
|
|
714
|
+
_fail "sidecar writer ensure-session failed for trailing-dot actor fixture: $(cat "$TMPDIR_EVAL/branch-trailing-dot.out" "$TMPDIR_EVAL/branch-trailing-dot.err")"
|
|
715
|
+
fi
|
|
716
|
+
|
|
717
|
+
# F2: an explicit --branch is strictly validated, not trusted verbatim. Each hostile value below
|
|
718
|
+
# must die BEFORE any session artifact is written (no state.json / no session Markdown), with a
|
|
719
|
+
# diagnostic naming the actual problem.
|
|
720
|
+
assert_hostile_branch_dies() {
|
|
721
|
+
local label="$1" branch_value="$2" slug="$3" expect_pattern="$4"
|
|
722
|
+
local dir="$SESSION_ROOT/$slug"
|
|
723
|
+
local out="$TMPDIR_EVAL/hostile-branch-$slug.out"
|
|
724
|
+
if flow_agents_node "$WRITER" ensure-session \
|
|
725
|
+
--artifact-root "$SESSION_ROOT" \
|
|
726
|
+
--task-slug "$slug" \
|
|
727
|
+
--branch "$branch_value" \
|
|
728
|
+
--source-request "Hostile --branch should die before mutation." \
|
|
729
|
+
--summary "Should not create a session." \
|
|
730
|
+
--timestamp "2026-07-01T00:04:10Z" >"$out" 2>&1; then
|
|
731
|
+
_fail "sidecar writer should reject a hostile --branch value ($label)"
|
|
732
|
+
elif rg -q -- "$expect_pattern" "$out" && [[ ! -f "$dir/state.json" ]]; then
|
|
733
|
+
_pass "sidecar writer dies on a hostile --branch value before writing any session artifact ($label, F2)"
|
|
734
|
+
else
|
|
735
|
+
_fail "hostile --branch rejection ($label) was not fail-closed or lacked diagnostics: $(cat "$out")"
|
|
736
|
+
fi
|
|
737
|
+
}
|
|
738
|
+
assert_hostile_branch_dies "embedded newline" "$(printf 'main\nbad')" "branch-hostile-newline" "control character or newline"
|
|
739
|
+
assert_hostile_branch_dies '".." sequence' "foo..bar" "branch-hostile-dotdot" 'must not contain a "\.\." sequence'
|
|
740
|
+
assert_hostile_branch_dies "trailing .lock" "foo.lock" "branch-hostile-lock" '"\.lock"'
|
|
741
|
+
assert_hostile_branch_dies "embedded space" "foo bar" "branch-hostile-space" "contains a space"
|
|
742
|
+
|
|
743
|
+
# F4: two distinct all-garbage --task-slug values (each collapsing sanitizeBranchSegment's
|
|
744
|
+
# charset filter to empty) must derive DISTINCT branches, not silently collide on the bare
|
|
745
|
+
# literal "unknown". Actor is held fixed and valid so the slug segment is the only variable.
|
|
746
|
+
BRANCH_GARBAGE_A_DIR="$SESSION_ROOT/???"
|
|
747
|
+
BRANCH_GARBAGE_B_DIR="$SESSION_ROOT/!!!"
|
|
748
|
+
if flow_agents_node "$WRITER" ensure-session \
|
|
749
|
+
--artifact-root "$SESSION_ROOT" \
|
|
750
|
+
--task-slug '???' \
|
|
751
|
+
--actor test-actor-fix4 \
|
|
752
|
+
--source-request "All-garbage slug A." \
|
|
753
|
+
--summary "Garbage slug A." \
|
|
754
|
+
--timestamp "2026-07-01T00:04:20Z" >"$TMPDIR_EVAL/branch-garbage-a.out" 2>"$TMPDIR_EVAL/branch-garbage-a.err" \
|
|
755
|
+
&& flow_agents_node "$WRITER" ensure-session \
|
|
756
|
+
--artifact-root "$SESSION_ROOT" \
|
|
757
|
+
--task-slug '!!!' \
|
|
758
|
+
--actor test-actor-fix4 \
|
|
759
|
+
--source-request "All-garbage slug B." \
|
|
760
|
+
--summary "Garbage slug B." \
|
|
761
|
+
--timestamp "2026-07-01T00:04:21Z" >"$TMPDIR_EVAL/branch-garbage-b.out" 2>"$TMPDIR_EVAL/branch-garbage-b.err"; then
|
|
762
|
+
GARBAGE_A_BRANCH="$(jq -r '.branch // empty' "$BRANCH_GARBAGE_A_DIR/state.json" 2>/dev/null)"
|
|
763
|
+
GARBAGE_B_BRANCH="$(jq -r '.branch // empty' "$BRANCH_GARBAGE_B_DIR/state.json" 2>/dev/null)"
|
|
764
|
+
if [[ -n "$GARBAGE_A_BRANCH" ]] && [[ -n "$GARBAGE_B_BRANCH" ]] \
|
|
765
|
+
&& [[ "$GARBAGE_A_BRANCH" != "$GARBAGE_B_BRANCH" ]] \
|
|
766
|
+
&& [[ "$GARBAGE_A_BRANCH" == agent/test-actor-fix4/unknown-* ]] \
|
|
767
|
+
&& [[ "$GARBAGE_B_BRANCH" == agent/test-actor-fix4/unknown-* ]] \
|
|
768
|
+
&& git check-ref-format --branch "$GARBAGE_A_BRANCH" >/dev/null 2>&1 \
|
|
769
|
+
&& git check-ref-format --branch "$GARBAGE_B_BRANCH" >/dev/null 2>&1; then
|
|
770
|
+
_pass "sidecar writer derives distinct disambiguated branches for two all-garbage task slugs (F4): $GARBAGE_A_BRANCH vs $GARBAGE_B_BRANCH"
|
|
771
|
+
else
|
|
772
|
+
_fail "sidecar writer did not disambiguate two all-garbage task slugs (F4): a=$GARBAGE_A_BRANCH b=$GARBAGE_B_BRANCH"
|
|
773
|
+
fi
|
|
774
|
+
else
|
|
775
|
+
_fail "sidecar writer ensure-session failed for all-garbage slug fixtures: $(cat "$TMPDIR_EVAL/branch-garbage-a.out" "$TMPDIR_EVAL/branch-garbage-a.err" "$TMPDIR_EVAL/branch-garbage-b.out" "$TMPDIR_EVAL/branch-garbage-b.err")"
|
|
776
|
+
fi
|
|
777
|
+
|
|
778
|
+
# ─── #289 fix-plan iteration 2 (F2'/F4' residuals from code-review-289-iteration-1) ─────────────
|
|
779
|
+
# F2': the whole-string checks above (iteration 1) only look at the START/END of the full
|
|
780
|
+
# --branch value, so a fuzz of charset-valid values found hostile /-delimited PATH COMPONENTS
|
|
781
|
+
# that slip past them. Each of these four escape classes must still die pre-mutation.
|
|
782
|
+
assert_hostile_branch_dies "leading '-' (path component)" "-lead" "branch-hostile-lead" 'starting with "-"'
|
|
783
|
+
assert_hostile_branch_dies "non-first component starting with '.'" "a/.b" "branch-hostile-dotcomp" 'starting with "\."'
|
|
784
|
+
assert_hostile_branch_dies "non-last component ending in .lock" "foo.lock/bar" "branch-hostile-lockcomp" '"\.lock"'
|
|
785
|
+
assert_hostile_branch_dies "component that is exactly '.'" "a/./b" "branch-hostile-dotonly" '"\."'
|
|
786
|
+
|
|
787
|
+
# F2' belt-and-braces: every --branch value validateExplicitBranch ACCEPTS must also pass the
|
|
788
|
+
# real `git check-ref-format --branch` binary — not just this repo's earlier fixtures
|
|
789
|
+
# ("custom/my-branch", AC3 above), but a representative additional accepted value with a nested
|
|
790
|
+
# path and mixed charset.
|
|
791
|
+
BRANCH_ACCEPTED_GIT_DIR="$SESSION_ROOT/branch-accepted-git-valid"
|
|
792
|
+
if flow_agents_node "$WRITER" ensure-session \
|
|
793
|
+
--artifact-root "$SESSION_ROOT" \
|
|
794
|
+
--task-slug branch-accepted-git-valid \
|
|
795
|
+
--branch "release/2026.07_hotfix-1" \
|
|
796
|
+
--source-request "An accepted --branch value must also be a real, git-valid ref." \
|
|
797
|
+
--summary "Accepted --branch values are double-checked against the real git binary." \
|
|
798
|
+
--timestamp "2026-07-02T00:04:30Z" >"$TMPDIR_EVAL/branch-accepted-git.out" 2>"$TMPDIR_EVAL/branch-accepted-git.err"; then
|
|
799
|
+
ACCEPTED_GIT_BRANCH="$(jq -r '.branch // empty' "$BRANCH_ACCEPTED_GIT_DIR/state.json" 2>/dev/null)"
|
|
800
|
+
if [[ "$ACCEPTED_GIT_BRANCH" == "release/2026.07_hotfix-1" ]] && git check-ref-format --branch "$ACCEPTED_GIT_BRANCH" >/dev/null 2>&1; then
|
|
801
|
+
_pass "sidecar writer's accepted --branch value passes the real git check-ref-format binary (F2')"
|
|
802
|
+
else
|
|
803
|
+
_fail "sidecar writer accepted a --branch value that the real git binary rejects (F2'): branch=$ACCEPTED_GIT_BRANCH"
|
|
804
|
+
fi
|
|
805
|
+
else
|
|
806
|
+
_fail "sidecar writer ensure-session failed for the accepted git-valid --branch fixture: $(cat "$TMPDIR_EVAL/branch-accepted-git.out" "$TMPDIR_EVAL/branch-accepted-git.err")"
|
|
807
|
+
fi
|
|
808
|
+
|
|
809
|
+
# F4': the FINAL sanitized segment equaling the literal fallback token "unknown" must ALWAYS be
|
|
810
|
+
# disambiguated with the 6-hex sha256 suffix - including a literal --actor "unknown" (no
|
|
811
|
+
# literal-input carve-out), and including near-miss inputs ("unknown.", ".unknown") that only
|
|
812
|
+
# collapse to the literal "unknown" via this function's OWN leading/trailing-dot stripping.
|
|
813
|
+
# All three must derive DISTINCT branches (distinct raw input -> distinct hash) despite sharing
|
|
814
|
+
# the same effective actor "meaning".
|
|
815
|
+
BRANCH_UNKNOWN_LITERAL_DIR="$SESSION_ROOT/branch-unknown-literal"
|
|
816
|
+
BRANCH_UNKNOWN_TRAILING_DIR="$SESSION_ROOT/branch-unknown-trailing-dot"
|
|
817
|
+
BRANCH_UNKNOWN_LEADING_DIR="$SESSION_ROOT/branch-unknown-leading-dot"
|
|
818
|
+
if flow_agents_node "$WRITER" ensure-session \
|
|
819
|
+
--artifact-root "$SESSION_ROOT" \
|
|
820
|
+
--task-slug branch-unknown-literal \
|
|
821
|
+
--actor "unknown" \
|
|
822
|
+
--source-request "Literal --actor unknown must still be disambiguated." \
|
|
823
|
+
--summary "No literal-input carve-out." \
|
|
824
|
+
--timestamp "2026-07-02T00:04:40Z" >"$TMPDIR_EVAL/branch-unknown-literal.out" 2>"$TMPDIR_EVAL/branch-unknown-literal.err" \
|
|
825
|
+
&& flow_agents_node "$WRITER" ensure-session \
|
|
826
|
+
--artifact-root "$SESSION_ROOT" \
|
|
827
|
+
--task-slug branch-unknown-trailing-dot \
|
|
828
|
+
--actor "unknown." \
|
|
829
|
+
--source-request "Trailing-dot actor collapsing to literal unknown must still be disambiguated." \
|
|
830
|
+
--summary "Near-miss trailing dot." \
|
|
831
|
+
--timestamp "2026-07-02T00:04:41Z" >"$TMPDIR_EVAL/branch-unknown-trailing-dot.out" 2>"$TMPDIR_EVAL/branch-unknown-trailing-dot.err" \
|
|
832
|
+
&& flow_agents_node "$WRITER" ensure-session \
|
|
833
|
+
--artifact-root "$SESSION_ROOT" \
|
|
834
|
+
--task-slug branch-unknown-leading-dot \
|
|
835
|
+
--actor ".unknown" \
|
|
836
|
+
--source-request "Leading-dot actor collapsing to literal unknown must still be disambiguated." \
|
|
837
|
+
--summary "Near-miss leading dot." \
|
|
838
|
+
--timestamp "2026-07-02T00:04:42Z" >"$TMPDIR_EVAL/branch-unknown-leading-dot.out" 2>"$TMPDIR_EVAL/branch-unknown-leading-dot.err"; then
|
|
839
|
+
UNKNOWN_LITERAL_BRANCH="$(jq -r '.branch // empty' "$BRANCH_UNKNOWN_LITERAL_DIR/state.json" 2>/dev/null)"
|
|
840
|
+
UNKNOWN_TRAILING_BRANCH="$(jq -r '.branch // empty' "$BRANCH_UNKNOWN_TRAILING_DIR/state.json" 2>/dev/null)"
|
|
841
|
+
UNKNOWN_LEADING_BRANCH="$(jq -r '.branch // empty' "$BRANCH_UNKNOWN_LEADING_DIR/state.json" 2>/dev/null)"
|
|
842
|
+
if [[ "$UNKNOWN_LITERAL_BRANCH" == agent/unknown-*/branch-unknown-literal ]] \
|
|
843
|
+
&& [[ "$UNKNOWN_TRAILING_BRANCH" == agent/unknown-*/branch-unknown-trailing-dot ]] \
|
|
844
|
+
&& [[ "$UNKNOWN_LEADING_BRANCH" == agent/unknown-*/branch-unknown-leading-dot ]] \
|
|
845
|
+
&& [[ "${UNKNOWN_LITERAL_BRANCH#agent/}" != "${UNKNOWN_TRAILING_BRANCH#agent/}" ]] \
|
|
846
|
+
&& [[ "${UNKNOWN_LITERAL_BRANCH#agent/}" != "${UNKNOWN_LEADING_BRANCH#agent/}" ]] \
|
|
847
|
+
&& [[ "${UNKNOWN_TRAILING_BRANCH#agent/}" != "${UNKNOWN_LEADING_BRANCH#agent/}" ]] \
|
|
848
|
+
&& git check-ref-format --branch "$UNKNOWN_LITERAL_BRANCH" >/dev/null 2>&1 \
|
|
849
|
+
&& git check-ref-format --branch "$UNKNOWN_TRAILING_BRANCH" >/dev/null 2>&1 \
|
|
850
|
+
&& git check-ref-format --branch "$UNKNOWN_LEADING_BRANCH" >/dev/null 2>&1; then
|
|
851
|
+
_pass "sidecar writer derives three DISTINCT disambiguated branches for actors 'unknown', 'unknown.', '.unknown' (F4'): $UNKNOWN_LITERAL_BRANCH vs $UNKNOWN_TRAILING_BRANCH vs $UNKNOWN_LEADING_BRANCH"
|
|
852
|
+
else
|
|
853
|
+
_fail "sidecar writer did not disambiguate all three unknown-collapsing actor variants distinctly (F4'): literal=$UNKNOWN_LITERAL_BRANCH trailing=$UNKNOWN_TRAILING_BRANCH leading=$UNKNOWN_LEADING_BRANCH"
|
|
854
|
+
fi
|
|
855
|
+
else
|
|
856
|
+
_fail "sidecar writer ensure-session failed for one of the unknown-collapsing actor fixtures: $(cat "$TMPDIR_EVAL/branch-unknown-literal.out" "$TMPDIR_EVAL/branch-unknown-literal.err" "$TMPDIR_EVAL/branch-unknown-trailing-dot.out" "$TMPDIR_EVAL/branch-unknown-trailing-dot.err" "$TMPDIR_EVAL/branch-unknown-leading-dot.out" "$TMPDIR_EVAL/branch-unknown-leading-dot.err")"
|
|
857
|
+
fi
|
|
858
|
+
|
|
431
859
|
printf 'DO NOT OVERWRITE\n' >> "$ENSURED_DIR/ensured-session--deliver.md"
|
|
432
860
|
if flow_agents_node "$WRITER" ensure-session \
|
|
433
861
|
--artifact-root "$SESSION_ROOT" \
|
|
@@ -522,7 +950,46 @@ else
|
|
|
522
950
|
_fail "sidecar writer did not update state or bundle from evidence"
|
|
523
951
|
fi
|
|
524
952
|
|
|
525
|
-
|
|
953
|
+
# ─── WS8 (ADR 0020) AC1: producer evidence classification ─────────────────────
|
|
954
|
+
# buildTrustBundle derives evidence.evidenceType/method from check.kind instead of
|
|
955
|
+
# hardcoding test_output, and always stamps execution.label on command-backed checks.
|
|
956
|
+
CLASSIFY_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/evidence-classification"
|
|
957
|
+
mkdir -p "$CLASSIFY_DIR"
|
|
958
|
+
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$CLASSIFY_DIR/evidence-classification--deliver.md"
|
|
959
|
+
flow_agents_node "$WRITER" init-plan "$CLASSIFY_DIR/evidence-classification--deliver.md" \
|
|
960
|
+
--source-request "Classify evidence by kind." \
|
|
961
|
+
--summary "Evidence classification fixture." \
|
|
962
|
+
--next-action "Record mixed-kind evidence." \
|
|
963
|
+
--timestamp "2026-05-09T00:01:00Z" >"$TMPDIR_EVAL/classify-init.out" 2>"$TMPDIR_EVAL/classify-init.err"
|
|
964
|
+
|
|
965
|
+
if flow_agents_node "$WRITER" record-evidence "$CLASSIFY_DIR" \
|
|
966
|
+
--verdict pass \
|
|
967
|
+
--check-json '{"id":"unit-tests","kind":"test","status":"pass","summary":"Unit tests passed.","command":"npm test"}' \
|
|
968
|
+
--check-json '{"id":"dashboard-ui","kind":"browser","status":"pass","summary":"Visual check of dashboard."}' \
|
|
969
|
+
--timestamp "2026-05-09T00:01:05Z" >"$TMPDIR_EVAL/classify.out" 2>"$TMPDIR_EVAL/classify.err"; then
|
|
970
|
+
if node - "$CLASSIFY_DIR/trust.bundle" << 'NODE' 2>/dev/null
|
|
971
|
+
const fs = require("fs");
|
|
972
|
+
const b = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
|
|
973
|
+
const ev = b.evidence || [];
|
|
974
|
+
const testEv = ev.find((e) => /unit-tests/.test(String(e.claimId)) || /Unit tests/.test(String(e.excerptOrSummary)));
|
|
975
|
+
const browserEv = ev.find((e) => /dashboard-ui/.test(String(e.claimId)) || /dashboard/.test(String(e.excerptOrSummary)));
|
|
976
|
+
if (!testEv) throw new Error("no test-kind evidence item");
|
|
977
|
+
if (!browserEv) throw new Error("no browser-kind evidence item");
|
|
978
|
+
if (testEv.evidenceType !== "test_output") throw new Error("test-kind evidenceType expected test_output, got " + testEv.evidenceType);
|
|
979
|
+
if (!testEv.execution || testEv.execution.label !== "npm test") throw new Error("test-kind must stamp execution.label 'npm test', got " + JSON.stringify(testEv.execution));
|
|
980
|
+
if (browserEv.evidenceType === "test_output") throw new Error("browser-kind evidenceType must NOT be test_output (got test_output)");
|
|
981
|
+
if (browserEv.evidenceType !== "crawl_observation") throw new Error("browser-kind evidenceType expected crawl_observation, got " + browserEv.evidenceType);
|
|
982
|
+
NODE
|
|
983
|
+
then
|
|
984
|
+
_pass "AC1: producer classifies test-kind as test_output+label and browser-kind as crawl_observation"
|
|
985
|
+
else
|
|
986
|
+
_fail "AC1: evidence classification incorrect: $(cat "$TMPDIR_EVAL/classify.out" "$TMPDIR_EVAL/classify.err")"
|
|
987
|
+
fi
|
|
988
|
+
else
|
|
989
|
+
_fail "AC1: record-evidence for classification fixture failed: $(cat "$TMPDIR_EVAL/classify.out" "$TMPDIR_EVAL/classify.err")"
|
|
990
|
+
fi
|
|
991
|
+
|
|
992
|
+
INVALID_REF_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/invalid-evidence-ref"
|
|
526
993
|
mkdir -p "$INVALID_REF_DIR"
|
|
527
994
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$INVALID_REF_DIR/invalid-evidence-ref--deliver.md"
|
|
528
995
|
flow_agents_node "$WRITER" init-plan "$INVALID_REF_DIR/invalid-evidence-ref--deliver.md" \
|
|
@@ -557,7 +1024,7 @@ else
|
|
|
557
1024
|
_fail "incomplete structured artifact_refs rejection was not fail-closed: $(cat "$TMPDIR_EVAL/incomplete-ref.out" "$TMPDIR_EVAL/incomplete-ref.err")"
|
|
558
1025
|
fi
|
|
559
1026
|
|
|
560
|
-
INVALID_ACCEPTANCE_REF_DIR="$TMPDIR_EVAL/repo/.flow-agents/invalid-acceptance-ref"
|
|
1027
|
+
INVALID_ACCEPTANCE_REF_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/invalid-acceptance-ref"
|
|
561
1028
|
mkdir -p "$INVALID_ACCEPTANCE_REF_DIR"
|
|
562
1029
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$INVALID_ACCEPTANCE_REF_DIR/invalid-acceptance-ref--deliver.md"
|
|
563
1030
|
flow_agents_node "$WRITER" init-plan "$INVALID_ACCEPTANCE_REF_DIR/invalid-acceptance-ref--deliver.md" \
|
|
@@ -630,7 +1097,7 @@ check_surface_fixture() {
|
|
|
630
1097
|
local verdict="$3"
|
|
631
1098
|
local expected_status="$4"
|
|
632
1099
|
local expected_text="$5"
|
|
633
|
-
local dir="$TMPDIR_EVAL/repo/.flow-agents/surface-$name"
|
|
1100
|
+
local dir="$TMPDIR_EVAL/repo/.kontourai/flow-agents/surface-$name"
|
|
634
1101
|
mkdir -p "$dir"
|
|
635
1102
|
# Phase 4c: evidence.json no longer written; verify surface trust check status in trust.bundle.
|
|
636
1103
|
if flow_agents_node "$WRITER" record-evidence "$dir" \
|
|
@@ -657,7 +1124,7 @@ check_surface_fixture "integrity-mismatch" "integrity-mismatch-trust-report.json
|
|
|
657
1124
|
check_surface_fixture "provider-absent" "provider-absent.json" "not_verified" "not_verified" "No trust provider is configured"
|
|
658
1125
|
check_surface_fixture "artifact-absent" "artifact-absent.json" "not_verified" "not_verified" "not readable"
|
|
659
1126
|
|
|
660
|
-
PURE_SURFACE_DIR="$TMPDIR_EVAL/repo/.flow-agents/surface-trust-only"
|
|
1127
|
+
PURE_SURFACE_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/surface-trust-only"
|
|
661
1128
|
mkdir -p "$PURE_SURFACE_DIR"
|
|
662
1129
|
# Phase 4c: evidence.json no longer written; verify in trust.bundle.
|
|
663
1130
|
if flow_agents_node "$WRITER" record-evidence "$PURE_SURFACE_DIR" \
|
|
@@ -737,7 +1204,7 @@ else
|
|
|
737
1204
|
_fail "terminal jump rejection lacked diagnostics or mutated authoritative sidecars"
|
|
738
1205
|
fi
|
|
739
1206
|
|
|
740
|
-
BUILDER_TRANSITION_DIR="$TMPDIR_EVAL/repo/.flow-agents/builder-transition-guard"
|
|
1207
|
+
BUILDER_TRANSITION_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/builder-transition-guard"
|
|
741
1208
|
mkdir -p "$BUILDER_TRANSITION_DIR"
|
|
742
1209
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$BUILDER_TRANSITION_DIR/builder-transition-guard--deliver.md"
|
|
743
1210
|
flow_agents_node "$WRITER" init-plan "$BUILDER_TRANSITION_DIR/builder-transition-guard--deliver.md" \
|
|
@@ -835,7 +1302,7 @@ else
|
|
|
835
1302
|
_fail "Builder Kit max-attempt route-back behavior was not deterministic"
|
|
836
1303
|
fi
|
|
837
1304
|
|
|
838
|
-
LEGACY_TRANSITION_DIR="$TMPDIR_EVAL/repo/.flow-agents/legacy-transition-guard"
|
|
1305
|
+
LEGACY_TRANSITION_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/legacy-transition-guard"
|
|
839
1306
|
mkdir -p "$LEGACY_TRANSITION_DIR"
|
|
840
1307
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$LEGACY_TRANSITION_DIR/legacy-transition-guard--deliver.md"
|
|
841
1308
|
flow_agents_node "$WRITER" init-plan "$LEGACY_TRANSITION_DIR/legacy-transition-guard--deliver.md" \
|
|
@@ -864,7 +1331,7 @@ else
|
|
|
864
1331
|
_fail "legacy-compatible direct primitive route-back failed: $(cat "$TMPDIR_EVAL/legacy-route-back.out" "$TMPDIR_EVAL/legacy-route-back.err")"
|
|
865
1332
|
fi
|
|
866
1333
|
|
|
867
|
-
NV_DIR="$TMPDIR_EVAL/repo/.flow-agents/not-verified-sidecars"
|
|
1334
|
+
NV_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/not-verified-sidecars"
|
|
868
1335
|
mkdir -p "$NV_DIR"
|
|
869
1336
|
cat > "$NV_DIR/not-verified-sidecars--deliver.md" <<'MARKDOWN'
|
|
870
1337
|
# Route not verified evidence
|
|
@@ -937,7 +1404,7 @@ else
|
|
|
937
1404
|
_fail "sidecar writer did not preserve not-verified state"
|
|
938
1405
|
fi
|
|
939
1406
|
|
|
940
|
-
NEW_INVALID_DIR="$TMPDIR_EVAL/repo/.flow-agents/new-invalid-artifact"
|
|
1407
|
+
NEW_INVALID_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/new-invalid-artifact"
|
|
941
1408
|
if flow_agents_node "$WRITER" record-evidence "$NEW_INVALID_DIR" \
|
|
942
1409
|
--verdict banana \
|
|
943
1410
|
--check-json '{"id":"invalid-new","kind":"test","status":"pass","summary":"Should fail."}' >"$TMPDIR_EVAL/new-invalid.out" 2>&1; then
|
|
@@ -948,10 +1415,10 @@ else
|
|
|
948
1415
|
_fail "sidecar writer left lock file for invalid new artifact command"
|
|
949
1416
|
fi
|
|
950
1417
|
|
|
951
|
-
LOCK_DENIED_DIR="$TMPDIR_EVAL/repo/.flow-agents/lock-denied"
|
|
1418
|
+
LOCK_DENIED_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/lock-denied"
|
|
952
1419
|
mkdir -p "$LOCK_DENIED_DIR"
|
|
953
1420
|
if chmod 500 "$LOCK_DENIED_DIR" 2>"$TMPDIR_EVAL/lock-denied-chmod.err"; then
|
|
954
|
-
if run_bounded
|
|
1421
|
+
if run_bounded 20 flow_agents_node "$WRITER" record-critique "$LOCK_DENIED_DIR" \
|
|
955
1422
|
--id lock-denied-review \
|
|
956
1423
|
--reviewer tool-code-reviewer \
|
|
957
1424
|
--verdict pass \
|
|
@@ -992,7 +1459,7 @@ else
|
|
|
992
1459
|
_fail "sidecar writer critique failed: $(cat "$TMPDIR_EVAL/critique.out" "$TMPDIR_EVAL/critique.err")"
|
|
993
1460
|
fi
|
|
994
1461
|
|
|
995
|
-
CONCURRENT_DIR="$TMPDIR_EVAL/repo/.flow-agents/concurrent-critiques"
|
|
1462
|
+
CONCURRENT_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/concurrent-critiques"
|
|
996
1463
|
mkdir -p "$CONCURRENT_DIR"
|
|
997
1464
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$CONCURRENT_DIR/concurrent-critiques--deliver.md"
|
|
998
1465
|
flow_agents_node "$WRITER" init-plan "$CONCURRENT_DIR/concurrent-critiques--deliver.md" \
|
|
@@ -1056,7 +1523,7 @@ else
|
|
|
1056
1523
|
_fail "sidecar writer did not update release state"
|
|
1057
1524
|
fi
|
|
1058
1525
|
|
|
1059
|
-
NO_SUMMARY_RELEASE_DIR="$TMPDIR_EVAL/repo/.flow-agents/no-summary-release"
|
|
1526
|
+
NO_SUMMARY_RELEASE_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/no-summary-release"
|
|
1060
1527
|
mkdir -p "$NO_SUMMARY_RELEASE_DIR"
|
|
1061
1528
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$NO_SUMMARY_RELEASE_DIR/no-summary-release--deliver.md"
|
|
1062
1529
|
flow_agents_node "$WRITER" init-plan "$NO_SUMMARY_RELEASE_DIR/no-summary-release--deliver.md" \
|
|
@@ -1110,7 +1577,7 @@ else
|
|
|
1110
1577
|
_fail "no-correction learning closeout failed validation: $(cat "$TMPDIR_EVAL/learning-valid.out" "$TMPDIR_EVAL/learning-valid.err")"
|
|
1111
1578
|
fi
|
|
1112
1579
|
|
|
1113
|
-
CORRECTION_DIR="$TMPDIR_EVAL/repo/.flow-agents/correction-needed-learning"
|
|
1580
|
+
CORRECTION_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/correction-needed-learning"
|
|
1114
1581
|
mkdir -p "$CORRECTION_DIR"
|
|
1115
1582
|
if flow_agents_node "$WRITER" record-learning "$CORRECTION_DIR" \
|
|
1116
1583
|
--task-slug correction-needed-learning \
|
|
@@ -1124,7 +1591,7 @@ else
|
|
|
1124
1591
|
_fail "correction-needed learning closeout failed: $(cat "$TMPDIR_EVAL/correction-needed-learning.out" "$TMPDIR_EVAL/correction-needed-learning.err" "$TMPDIR_EVAL/correction-needed-valid.out" "$TMPDIR_EVAL/correction-needed-valid.err")"
|
|
1125
1592
|
fi
|
|
1126
1593
|
|
|
1127
|
-
DOGFOOD_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-pass"
|
|
1594
|
+
DOGFOOD_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-pass"
|
|
1128
1595
|
mkdir -p "$DOGFOOD_DIR"
|
|
1129
1596
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$DOGFOOD_DIR/dogfood-pass--deliver.md"
|
|
1130
1597
|
flow_agents_node "$WRITER" init-plan "$DOGFOOD_DIR/dogfood-pass--deliver.md" \
|
|
@@ -1145,7 +1612,7 @@ else
|
|
|
1145
1612
|
_fail "dogfood-pass missing actionable no-evidence error"
|
|
1146
1613
|
fi
|
|
1147
1614
|
|
|
1148
|
-
DIRTY_EVIDENCE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-dirty-evidence"
|
|
1615
|
+
DIRTY_EVIDENCE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-dirty-evidence"
|
|
1149
1616
|
mkdir -p "$DIRTY_EVIDENCE_DOGFOOD_DIR"
|
|
1150
1617
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$DIRTY_EVIDENCE_DOGFOOD_DIR/dogfood-dirty-evidence--deliver.md"
|
|
1151
1618
|
flow_agents_node "$WRITER" init-plan "$DIRTY_EVIDENCE_DOGFOOD_DIR/dogfood-dirty-evidence--deliver.md" \
|
|
@@ -1191,7 +1658,7 @@ else
|
|
|
1191
1658
|
_fail "dogfood-pass existing dirty evidence was not fail-closed"
|
|
1192
1659
|
fi
|
|
1193
1660
|
|
|
1194
|
-
INVALID_EXISTING_EVIDENCE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-existing-invalid-evidence"
|
|
1661
|
+
INVALID_EXISTING_EVIDENCE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-existing-invalid-evidence"
|
|
1195
1662
|
mkdir -p "$INVALID_EXISTING_EVIDENCE_DOGFOOD_DIR"
|
|
1196
1663
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$INVALID_EXISTING_EVIDENCE_DOGFOOD_DIR/dogfood-existing-invalid-evidence--deliver.md"
|
|
1197
1664
|
flow_agents_node "$WRITER" init-plan "$INVALID_EXISTING_EVIDENCE_DOGFOOD_DIR/dogfood-existing-invalid-evidence--deliver.md" \
|
|
@@ -1265,7 +1732,7 @@ else
|
|
|
1265
1732
|
_fail "dogfood-pass not_verified clean-pass check was not fail-closed"
|
|
1266
1733
|
fi
|
|
1267
1734
|
|
|
1268
|
-
INVALID_EVIDENCE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-invalid-evidence"
|
|
1735
|
+
INVALID_EVIDENCE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-invalid-evidence"
|
|
1269
1736
|
mkdir -p "$INVALID_EVIDENCE_DOGFOOD_DIR"
|
|
1270
1737
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$INVALID_EVIDENCE_DOGFOOD_DIR/dogfood-invalid-evidence--deliver.md"
|
|
1271
1738
|
flow_agents_node "$WRITER" init-plan "$INVALID_EVIDENCE_DOGFOOD_DIR/dogfood-invalid-evidence--deliver.md" \
|
|
@@ -1292,7 +1759,7 @@ else
|
|
|
1292
1759
|
_fail "dogfood-pass invalid evidence metadata was not fail-closed"
|
|
1293
1760
|
fi
|
|
1294
1761
|
|
|
1295
|
-
INVALID_LEARNING_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-invalid-learning"
|
|
1762
|
+
INVALID_LEARNING_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-invalid-learning"
|
|
1296
1763
|
mkdir -p "$INVALID_LEARNING_DOGFOOD_DIR"
|
|
1297
1764
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$INVALID_LEARNING_DOGFOOD_DIR/dogfood-invalid-learning--deliver.md"
|
|
1298
1765
|
flow_agents_node "$WRITER" init-plan "$INVALID_LEARNING_DOGFOOD_DIR/dogfood-invalid-learning--deliver.md" \
|
|
@@ -1318,7 +1785,7 @@ else
|
|
|
1318
1785
|
_fail "dogfood-pass invalid learning was not fail-closed"
|
|
1319
1786
|
fi
|
|
1320
1787
|
|
|
1321
|
-
INVALID_LEARNING_SHAPE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-invalid-learning-shape"
|
|
1788
|
+
INVALID_LEARNING_SHAPE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-invalid-learning-shape"
|
|
1322
1789
|
mkdir -p "$INVALID_LEARNING_SHAPE_DOGFOOD_DIR"
|
|
1323
1790
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$INVALID_LEARNING_SHAPE_DOGFOOD_DIR/dogfood-invalid-learning-shape--deliver.md"
|
|
1324
1791
|
flow_agents_node "$WRITER" init-plan "$INVALID_LEARNING_SHAPE_DOGFOOD_DIR/dogfood-invalid-learning-shape--deliver.md" \
|
|
@@ -1344,7 +1811,7 @@ else
|
|
|
1344
1811
|
_fail "dogfood-pass invalid learning shape was not fail-closed"
|
|
1345
1812
|
fi
|
|
1346
1813
|
|
|
1347
|
-
EXISTING_INVALID_LEARNING_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-existing-invalid-learning"
|
|
1814
|
+
EXISTING_INVALID_LEARNING_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-existing-invalid-learning"
|
|
1348
1815
|
mkdir -p "$EXISTING_INVALID_LEARNING_DOGFOOD_DIR"
|
|
1349
1816
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$EXISTING_INVALID_LEARNING_DOGFOOD_DIR/dogfood-existing-invalid-learning--deliver.md"
|
|
1350
1817
|
flow_agents_node "$WRITER" init-plan "$EXISTING_INVALID_LEARNING_DOGFOOD_DIR/dogfood-existing-invalid-learning--deliver.md" \
|
|
@@ -1397,7 +1864,7 @@ else
|
|
|
1397
1864
|
_fail "dogfood-pass existing invalid learning was not fail-closed"
|
|
1398
1865
|
fi
|
|
1399
1866
|
|
|
1400
|
-
EXISTING_LEARNED_NO_CORRECTION_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-learned-no-correction"
|
|
1867
|
+
EXISTING_LEARNED_NO_CORRECTION_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-learned-no-correction"
|
|
1401
1868
|
mkdir -p "$EXISTING_LEARNED_NO_CORRECTION_DIR"
|
|
1402
1869
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$EXISTING_LEARNED_NO_CORRECTION_DIR/dogfood-learned-no-correction--deliver.md"
|
|
1403
1870
|
flow_agents_node "$WRITER" init-plan "$EXISTING_LEARNED_NO_CORRECTION_DIR/dogfood-learned-no-correction--deliver.md" \
|
|
@@ -1452,7 +1919,7 @@ else
|
|
|
1452
1919
|
_fail "dogfood-pass existing learned learning missing correction was not fail-closed"
|
|
1453
1920
|
fi
|
|
1454
1921
|
|
|
1455
|
-
INVALID_CRITIQUE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-invalid-critique"
|
|
1922
|
+
INVALID_CRITIQUE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-invalid-critique"
|
|
1456
1923
|
mkdir -p "$INVALID_CRITIQUE_DOGFOOD_DIR"
|
|
1457
1924
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$INVALID_CRITIQUE_DOGFOOD_DIR/dogfood-invalid-critique--deliver.md"
|
|
1458
1925
|
flow_agents_node "$WRITER" init-plan "$INVALID_CRITIQUE_DOGFOOD_DIR/dogfood-invalid-critique--deliver.md" \
|
|
@@ -1484,7 +1951,7 @@ else
|
|
|
1484
1951
|
_fail "dogfood-pass invalid critique metadata was not fail-closed"
|
|
1485
1952
|
fi
|
|
1486
1953
|
|
|
1487
|
-
EXISTING_INVALID_CRITIQUE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-existing-invalid-critique"
|
|
1954
|
+
EXISTING_INVALID_CRITIQUE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-existing-invalid-critique"
|
|
1488
1955
|
mkdir -p "$EXISTING_INVALID_CRITIQUE_DOGFOOD_DIR"
|
|
1489
1956
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$EXISTING_INVALID_CRITIQUE_DOGFOOD_DIR/dogfood-existing-invalid-critique--deliver.md"
|
|
1490
1957
|
flow_agents_node "$WRITER" init-plan "$EXISTING_INVALID_CRITIQUE_DOGFOOD_DIR/dogfood-existing-invalid-critique--deliver.md" \
|
|
@@ -1650,7 +2117,7 @@ else
|
|
|
1650
2117
|
_fail "dogfood-pass failing critique was not fail-closed"
|
|
1651
2118
|
fi
|
|
1652
2119
|
|
|
1653
|
-
DIRTY_CRITIQUE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-dirty-critique"
|
|
2120
|
+
DIRTY_CRITIQUE_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-dirty-critique"
|
|
1654
2121
|
mkdir -p "$DIRTY_CRITIQUE_DOGFOOD_DIR"
|
|
1655
2122
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$DIRTY_CRITIQUE_DOGFOOD_DIR/dogfood-dirty-critique--deliver.md"
|
|
1656
2123
|
flow_agents_node "$WRITER" init-plan "$DIRTY_CRITIQUE_DOGFOOD_DIR/dogfood-dirty-critique--deliver.md" \
|
|
@@ -1701,7 +2168,7 @@ else
|
|
|
1701
2168
|
_fail "dogfood-pass existing dirty critique was not fail-closed"
|
|
1702
2169
|
fi
|
|
1703
2170
|
|
|
1704
|
-
FAILED_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-failed-pass"
|
|
2171
|
+
FAILED_DOGFOOD_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-failed-pass"
|
|
1705
2172
|
mkdir -p "$FAILED_DOGFOOD_DIR"
|
|
1706
2173
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$FAILED_DOGFOOD_DIR/dogfood-failed-pass--deliver.md"
|
|
1707
2174
|
flow_agents_node "$WRITER" init-plan "$FAILED_DOGFOOD_DIR/dogfood-failed-pass--deliver.md" \
|
|
@@ -1834,7 +2301,7 @@ else
|
|
|
1834
2301
|
_fail "dogfood-pass release readiness did not update expected sidecars"
|
|
1835
2302
|
fi
|
|
1836
2303
|
|
|
1837
|
-
DOGFOOD_NV_DIR="$TMPDIR_EVAL/repo/.flow-agents/dogfood-not-verified"
|
|
2304
|
+
DOGFOOD_NV_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/dogfood-not-verified"
|
|
1838
2305
|
mkdir -p "$DOGFOOD_NV_DIR"
|
|
1839
2306
|
cat > "$DOGFOOD_NV_DIR/dogfood-not-verified--deliver.md" <<'MARKDOWN'
|
|
1840
2307
|
# Dogfood not verified fixture
|
|
@@ -1914,7 +2381,7 @@ else
|
|
|
1914
2381
|
_fail "invalid release decision failure was not actionable"
|
|
1915
2382
|
fi
|
|
1916
2383
|
|
|
1917
|
-
SEMANTIC_RELEASE_DIR="$TMPDIR_EVAL/repo/.flow-agents/semantic-release"
|
|
2384
|
+
SEMANTIC_RELEASE_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/semantic-release"
|
|
1918
2385
|
mkdir -p "$SEMANTIC_RELEASE_DIR"
|
|
1919
2386
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$SEMANTIC_RELEASE_DIR/semantic-release--deliver.md"
|
|
1920
2387
|
flow_agents_node "$WRITER" init-plan "$SEMANTIC_RELEASE_DIR/semantic-release--deliver.md" \
|
|
@@ -1989,7 +2456,7 @@ else
|
|
|
1989
2456
|
_fail "incomplete correction prevention failure was not actionable: $(cat "$TMPDIR_EVAL/correction-incomplete-prevention.out")"
|
|
1990
2457
|
fi
|
|
1991
2458
|
|
|
1992
|
-
SEMANTIC_LEARNING_DIR="$TMPDIR_EVAL/repo/.flow-agents/semantic-learning"
|
|
2459
|
+
SEMANTIC_LEARNING_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/semantic-learning"
|
|
1993
2460
|
mkdir -p "$SEMANTIC_LEARNING_DIR"
|
|
1994
2461
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$SEMANTIC_LEARNING_DIR/semantic-learning--deliver.md"
|
|
1995
2462
|
flow_agents_node "$WRITER" init-plan "$SEMANTIC_LEARNING_DIR/semantic-learning--deliver.md" \
|
|
@@ -2023,7 +2490,7 @@ else
|
|
|
2023
2490
|
_fail "semantic learning failure advanced state or lacked actionable output"
|
|
2024
2491
|
fi
|
|
2025
2492
|
|
|
2026
|
-
REVIEW_DIR="$TMPDIR_EVAL/repo/.flow-agents/imported-critique"
|
|
2493
|
+
REVIEW_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/imported-critique"
|
|
2027
2494
|
mkdir -p "$REVIEW_DIR"
|
|
2028
2495
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$REVIEW_DIR/imported-critique--deliver.md"
|
|
2029
2496
|
flow_agents_node "$WRITER" init-plan "$REVIEW_DIR/imported-critique--deliver.md" \
|
|
@@ -2090,7 +2557,7 @@ else
|
|
|
2090
2557
|
_fail "writer output failed validation: $(cat "$TMPDIR_EVAL/valid.out" "$TMPDIR_EVAL/valid.err")"
|
|
2091
2558
|
fi
|
|
2092
2559
|
|
|
2093
|
-
BAD_DIR="$TMPDIR_EVAL/repo/.flow-agents/bad-critique"
|
|
2560
|
+
BAD_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/bad-critique"
|
|
2094
2561
|
mkdir -p "$BAD_DIR"
|
|
2095
2562
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$BAD_DIR/bad-critique--deliver.md"
|
|
2096
2563
|
|
|
@@ -2118,7 +2585,7 @@ else
|
|
|
2118
2585
|
_fail "open critique failure did not mention open findings"
|
|
2119
2586
|
fi
|
|
2120
2587
|
|
|
2121
|
-
IMPORT_BAD="$TMPDIR_EVAL/repo/.flow-agents/imported-bad-critique"
|
|
2588
|
+
IMPORT_BAD="$TMPDIR_EVAL/repo/.kontourai/flow-agents/imported-bad-critique"
|
|
2122
2589
|
mkdir -p "$IMPORT_BAD"
|
|
2123
2590
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$IMPORT_BAD/imported-bad-critique--deliver.md"
|
|
2124
2591
|
flow_agents_node "$WRITER" init-plan "$IMPORT_BAD/imported-bad-critique--deliver.md" \
|
|
@@ -2162,7 +2629,7 @@ fi
|
|
|
2162
2629
|
|
|
2163
2630
|
|
|
2164
2631
|
# ─── AC1: trust.bundle dual-write file existence and schema validity ──────────
|
|
2165
|
-
TB_SCHEMA_DIR="$TMPDIR_EVAL/repo/.flow-agents/trust-bundle-schema"
|
|
2632
|
+
TB_SCHEMA_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/trust-bundle-schema"
|
|
2166
2633
|
mkdir -p "$TB_SCHEMA_DIR"
|
|
2167
2634
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$TB_SCHEMA_DIR/trust-bundle-schema--deliver.md"
|
|
2168
2635
|
flow_agents_node "$WRITER" init-plan "$TB_SCHEMA_DIR/trust-bundle-schema--deliver.md" \
|
|
@@ -2199,7 +2666,7 @@ NODEOF
|
|
|
2199
2666
|
fi
|
|
2200
2667
|
|
|
2201
2668
|
# ─── AC2: claim status fidelity — pass→verified, fail→disputed ───────────────
|
|
2202
|
-
TB_FIDELITY_DIR="$TMPDIR_EVAL/repo/.flow-agents/trust-bundle-fidelity"
|
|
2669
|
+
TB_FIDELITY_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/trust-bundle-fidelity"
|
|
2203
2670
|
mkdir -p "$TB_FIDELITY_DIR"
|
|
2204
2671
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$TB_FIDELITY_DIR/trust-bundle-fidelity--deliver.md"
|
|
2205
2672
|
flow_agents_node "$WRITER" init-plan "$TB_FIDELITY_DIR/trust-bundle-fidelity--deliver.md" \
|
|
@@ -2239,7 +2706,7 @@ else
|
|
|
2239
2706
|
fi
|
|
2240
2707
|
|
|
2241
2708
|
# ─── AC2: claim status fidelity — critique fail→disputed, pass→verified ──────
|
|
2242
|
-
TB_CRITIQUE_DIR="$TMPDIR_EVAL/repo/.flow-agents/trust-bundle-critique"
|
|
2709
|
+
TB_CRITIQUE_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/trust-bundle-critique"
|
|
2243
2710
|
mkdir -p "$TB_CRITIQUE_DIR"
|
|
2244
2711
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$TB_CRITIQUE_DIR/trust-bundle-critique--deliver.md"
|
|
2245
2712
|
flow_agents_node "$WRITER" init-plan "$TB_CRITIQUE_DIR/trust-bundle-critique--deliver.md" \
|
|
@@ -2290,7 +2757,7 @@ else
|
|
|
2290
2757
|
fi
|
|
2291
2758
|
|
|
2292
2759
|
# ─── AC3: capture authoritative over claimed status + policies present (ADR 0010 maximal) ──
|
|
2293
|
-
TB_CAPTURE_DIR="$TMPDIR_EVAL/repo/.flow-agents/trust-bundle-capture"
|
|
2760
|
+
TB_CAPTURE_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/trust-bundle-capture"
|
|
2294
2761
|
mkdir -p "$TB_CAPTURE_DIR"
|
|
2295
2762
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$TB_CAPTURE_DIR/trust-bundle-capture--deliver.md"
|
|
2296
2763
|
flow_agents_node "$WRITER" init-plan "$TB_CAPTURE_DIR/trust-bundle-capture--deliver.md" \
|
|
@@ -2324,6 +2791,85 @@ else
|
|
|
2324
2791
|
_fail "trust.bundle capture-authoritative setup failed: $(cat "$TMPDIR_EVAL/tb-capture-evidence.out" "$TMPDIR_EVAL/tb-capture-evidence.err")"
|
|
2325
2792
|
fi
|
|
2326
2793
|
|
|
2794
|
+
# ---- #347: hard cutover -- an unstamped (pre-#344) claim in a session trust bundle is a loud,
|
|
2795
|
+
# typed error; checksFromBundle/critiquesFromBundle carry NO claimType-derivation fallback (that
|
|
2796
|
+
# fallback WAS the #268 defect kept reachable). ----------------------------------------------
|
|
2797
|
+
TB_UNSTAMPED_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/trust-bundle-unstamped"
|
|
2798
|
+
mkdir -p "$TB_UNSTAMPED_DIR"
|
|
2799
|
+
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$TB_UNSTAMPED_DIR/trust-bundle-unstamped--deliver.md"
|
|
2800
|
+
flow_agents_node "$WRITER" init-plan "$TB_UNSTAMPED_DIR/trust-bundle-unstamped--deliver.md" \
|
|
2801
|
+
--source-request "Unstamped bundle regression fixture." \
|
|
2802
|
+
--summary "Unstamped bundle regression fixture." \
|
|
2803
|
+
--next-action "Seed a stamped check, then strip its origin stamp to simulate a pre-#344 bundle." \
|
|
2804
|
+
--timestamp "2026-05-09T00:00:00Z" >"$TMPDIR_EVAL/tb-unstamped-init.out" 2>"$TMPDIR_EVAL/tb-unstamped-init.err"
|
|
2805
|
+
flow_agents_node "$WRITER" record-evidence "$TB_UNSTAMPED_DIR" \
|
|
2806
|
+
--verdict pass \
|
|
2807
|
+
--check-json '{"id":"tb-unstamped-check","kind":"test","status":"pass","summary":"Stamped check, about to be corrupted."}' \
|
|
2808
|
+
--timestamp "2026-05-09T00:01:00Z" >"$TMPDIR_EVAL/tb-unstamped-evidence.out" 2>"$TMPDIR_EVAL/tb-unstamped-evidence.err"
|
|
2809
|
+
|
|
2810
|
+
# Simulate a pre-#344 bundle by stripping the origin/check_kind stamp from every claim -- never
|
|
2811
|
+
# done by hand-editing production sessions, only here to recreate the on-disk shape of a bundle
|
|
2812
|
+
# recorded before #344 shipped stamping.
|
|
2813
|
+
export UNSTAMPED_TARGET="$TB_UNSTAMPED_DIR/trust.bundle"
|
|
2814
|
+
node --input-type=module <<NODEOF
|
|
2815
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2816
|
+
const target = process.env.UNSTAMPED_TARGET;
|
|
2817
|
+
const data = JSON.parse(readFileSync(target, 'utf8'));
|
|
2818
|
+
data.claims = (data.claims || []).map((c) => {
|
|
2819
|
+
if (c && c.metadata && typeof c.metadata === 'object') {
|
|
2820
|
+
const rest = { ...c.metadata };
|
|
2821
|
+
delete rest.origin;
|
|
2822
|
+
delete rest.check_kind;
|
|
2823
|
+
return { ...c, metadata: rest };
|
|
2824
|
+
}
|
|
2825
|
+
return c;
|
|
2826
|
+
});
|
|
2827
|
+
writeFileSync(target, JSON.stringify(data, null, 2) + '\n');
|
|
2828
|
+
NODEOF
|
|
2829
|
+
|
|
2830
|
+
if flow_agents_node "$WRITER" record-critique "$TB_UNSTAMPED_DIR" \
|
|
2831
|
+
--id tb-unstamped-review \
|
|
2832
|
+
--reviewer tool-code-reviewer \
|
|
2833
|
+
--verdict pass \
|
|
2834
|
+
--summary "Should never be recorded -- the bundle is unstamped." \
|
|
2835
|
+
--timestamp "2026-05-09T00:02:00Z" >"$TMPDIR_EVAL/tb-unstamped-critique.out" 2>"$TMPDIR_EVAL/tb-unstamped-critique.err"; then
|
|
2836
|
+
_fail "record-critique should refuse to read an unstamped (pre-#344) trust.bundle, not silently reclassify it by claimType"
|
|
2837
|
+
elif rg -q 'pre-supersession trust\.bundle' "$TMPDIR_EVAL/tb-unstamped-critique.out" "$TMPDIR_EVAL/tb-unstamped-critique.err" \
|
|
2838
|
+
&& rg -qF "$TB_UNSTAMPED_DIR" "$TMPDIR_EVAL/tb-unstamped-critique.out" "$TMPDIR_EVAL/tb-unstamped-critique.err" \
|
|
2839
|
+
&& rg -q 're-record evidence to regenerate' "$TMPDIR_EVAL/tb-unstamped-critique.out" "$TMPDIR_EVAL/tb-unstamped-critique.err" \
|
|
2840
|
+
&& rg -q 'record-evidence' "$TMPDIR_EVAL/tb-unstamped-critique.out" "$TMPDIR_EVAL/tb-unstamped-critique.err"; then
|
|
2841
|
+
_pass "record-critique refuses an unstamped (pre-#344) trust.bundle: typed error names the session dir and the record-evidence remedy (no claimType-derivation fallback, #347)"
|
|
2842
|
+
else
|
|
2843
|
+
_fail "record-critique on an unstamped bundle failed for the wrong reason: $(cat "$TMPDIR_EVAL/tb-unstamped-critique.out" "$TMPDIR_EVAL/tb-unstamped-critique.err")"
|
|
2844
|
+
fi
|
|
2845
|
+
|
|
2846
|
+
# The same unstamped bundle also refuses promote (checksFromBundle) -- not just
|
|
2847
|
+
# record-critique/critiquesFromBundle.
|
|
2848
|
+
if flow_agents_node "$WRITER" promote "$TB_UNSTAMPED_DIR" --none --reason "regression probe" \
|
|
2849
|
+
--timestamp "2026-05-09T00:03:00Z" >"$TMPDIR_EVAL/tb-unstamped-promote.out" 2>"$TMPDIR_EVAL/tb-unstamped-promote.err"; then
|
|
2850
|
+
_fail "promote should refuse to read an unstamped (pre-#344) trust.bundle via checksFromBundle"
|
|
2851
|
+
elif rg -q 'pre-supersession trust\.bundle' "$TMPDIR_EVAL/tb-unstamped-promote.out" "$TMPDIR_EVAL/tb-unstamped-promote.err"; then
|
|
2852
|
+
_pass "promote (checksFromBundle) also refuses an unstamped (pre-#344) trust.bundle with the same typed error"
|
|
2853
|
+
else
|
|
2854
|
+
_fail "promote on an unstamped bundle failed for the wrong reason: $(cat "$TMPDIR_EVAL/tb-unstamped-promote.out" "$TMPDIR_EVAL/tb-unstamped-promote.err")"
|
|
2855
|
+
fi
|
|
2856
|
+
|
|
2857
|
+
# (b) STAMPED bundles are unaffected: the earlier, still-stamped trust-bundle-critique fixture
|
|
2858
|
+
# carries the origin stamp on every claim -- the normal write path was never touched by this cutover.
|
|
2859
|
+
export STAMPED_TARGET="$TB_CRITIQUE_DIR/trust.bundle"
|
|
2860
|
+
if [[ -f "$STAMPED_TARGET" ]] && node --input-type=module <<NODEOF 2>"$TMPDIR_EVAL/tb-stamped-unaffected.err"
|
|
2861
|
+
import { readFileSync } from 'node:fs';
|
|
2862
|
+
const target = process.env.STAMPED_TARGET;
|
|
2863
|
+
const bundle = JSON.parse(readFileSync(target, 'utf8'));
|
|
2864
|
+
const unstamped = bundle.claims.filter((c) => !(c.metadata && typeof c.metadata === 'object' && typeof c.metadata.origin === 'string' && c.metadata.origin.length > 0));
|
|
2865
|
+
if (unstamped.length > 0) { process.stderr.write('found ' + unstamped.length + ' claim(s) with no origin stamp in a normally-written bundle\n'); process.exit(1); }
|
|
2866
|
+
NODEOF
|
|
2867
|
+
then
|
|
2868
|
+
_pass "stamped bundles are unaffected: every claim in a normally-written trust bundle carries the origin stamp (#347)"
|
|
2869
|
+
else
|
|
2870
|
+
_fail "stamped-bundle regression: $(cat "$TMPDIR_EVAL/tb-stamped-unaffected.err")"
|
|
2871
|
+
fi
|
|
2872
|
+
|
|
2327
2873
|
# ─── AC4: render-trust-panel projects the bundle to a standalone Surface Trust Panel (ADR 0010 Phase 3) ──
|
|
2328
2874
|
if [[ -f "$TB_CAPTURE_DIR/trust.bundle" ]] && flow_agents_node "$WRITER" render-trust-panel "$TB_CAPTURE_DIR" --out "$TB_CAPTURE_DIR/trust-panel.html" >"$TMPDIR_EVAL/tb-panel.out" 2>"$TMPDIR_EVAL/tb-panel.err"; then
|
|
2329
2875
|
PANEL="$TB_CAPTURE_DIR/trust-panel.html"
|
|
@@ -2382,7 +2928,7 @@ else
|
|
|
2382
2928
|
fi
|
|
2383
2929
|
|
|
2384
2930
|
# ─── AC6: agent liveness (ADR 0012) — held / free-on-lapse / free-on-release ──
|
|
2385
|
-
TB_LIVENESS_ROOT="$TMPDIR_EVAL/liveness/.flow-agents"
|
|
2931
|
+
TB_LIVENESS_ROOT="$TMPDIR_EVAL/liveness/.kontourai/flow-agents"
|
|
2386
2932
|
flow_agents_node "$WRITER" liveness claim held-subj --actor agent-A --at "2026-06-25T11:50:00Z" --ttl 1800 --artifact-root "$TB_LIVENESS_ROOT" >/dev/null 2>&1
|
|
2387
2933
|
flow_agents_node "$WRITER" liveness heartbeat held-subj --actor agent-A --at "2026-06-25T11:58:00Z" --artifact-root "$TB_LIVENESS_ROOT" >/dev/null 2>&1
|
|
2388
2934
|
flow_agents_node "$WRITER" liveness claim stale-subj --actor agent-B --at "2026-06-25T11:00:00Z" --ttl 1800 --artifact-root "$TB_LIVENESS_ROOT" >/dev/null 2>&1
|
|
@@ -2397,25 +2943,207 @@ else
|
|
|
2397
2943
|
_fail "liveness status mismatch (expected held/free/free): $LIVENESS_OUT"
|
|
2398
2944
|
fi
|
|
2399
2945
|
|
|
2400
|
-
# ───
|
|
2401
|
-
|
|
2946
|
+
# ─── F8(i) (#288 fix iteration 2, orphan-heartbeat invariant): direct CLI `liveness
|
|
2947
|
+
# heartbeat`/`release` must die with remediation when no prior claim event exists for the
|
|
2948
|
+
# (subjectId, actor) pair — the exact reproduction the reviewer flagged ("liveness heartbeat
|
|
2949
|
+
# <subj> --actor <a> with no prior claim writes an orphan heartbeat"). `claim` itself is
|
|
2950
|
+
# unaffected (it establishes the pair). ──
|
|
2951
|
+
TB_ORPHAN_ROOT="$TMPDIR_EVAL/liveness-orphan/.kontourai/flow-agents"
|
|
2952
|
+
if flow_agents_node "$WRITER" liveness heartbeat orphan-subj --actor agent-orphan --artifact-root "$TB_ORPHAN_ROOT" >"$TMPDIR_EVAL/orphan-heartbeat.out" 2>"$TMPDIR_EVAL/orphan-heartbeat.err"; then
|
|
2953
|
+
_fail "liveness (F8(i)): heartbeat with no prior claim for the (subject, actor) pair should have exited nonzero"
|
|
2954
|
+
elif rg -qi 'prior claim' "$TMPDIR_EVAL/orphan-heartbeat.err" && rg -qi 'liveness claim' "$TMPDIR_EVAL/orphan-heartbeat.err" && [[ ! -f "$TB_ORPHAN_ROOT/liveness/events.jsonl" ]]; then
|
|
2955
|
+
_pass "liveness (F8(i)): heartbeat with no prior claim dies with remediation naming 'liveness claim' and writes no orphan event"
|
|
2956
|
+
else
|
|
2957
|
+
_fail "liveness (F8(i)) orphan-heartbeat rejection lacked remediation or wrote an event: $(cat "$TMPDIR_EVAL/orphan-heartbeat.out" "$TMPDIR_EVAL/orphan-heartbeat.err")"
|
|
2958
|
+
fi
|
|
2959
|
+
|
|
2960
|
+
if flow_agents_node "$WRITER" liveness release orphan-release-subj --actor agent-orphan-r --artifact-root "$TB_ORPHAN_ROOT" >"$TMPDIR_EVAL/orphan-release.out" 2>"$TMPDIR_EVAL/orphan-release.err"; then
|
|
2961
|
+
_fail "liveness (F8(i)): release with no prior claim for the (subject, actor) pair should have exited nonzero"
|
|
2962
|
+
elif rg -qi 'prior claim' "$TMPDIR_EVAL/orphan-release.err" && rg -qi 'liveness claim' "$TMPDIR_EVAL/orphan-release.err" && ! rg -q '"subjectId":"orphan-release-subj"' "$TB_ORPHAN_ROOT/liveness/events.jsonl" 2>/dev/null; then
|
|
2963
|
+
_pass "liveness (F8(i)): release with no prior claim dies with remediation naming 'liveness claim' and writes no orphan event"
|
|
2964
|
+
else
|
|
2965
|
+
_fail "liveness (F8(i)) orphan-release rejection lacked remediation or wrote an event: $(cat "$TMPDIR_EVAL/orphan-release.out" "$TMPDIR_EVAL/orphan-release.err")"
|
|
2966
|
+
fi
|
|
2967
|
+
|
|
2968
|
+
# A prior claim for the SAME subjectId but a DIFFERENT actor must not satisfy the check — the
|
|
2969
|
+
# invariant is per-(subject, actor) pair, not merely per-subject.
|
|
2970
|
+
flow_agents_node "$WRITER" liveness claim orphan-crossactor-subj --actor agent-orphan-real --artifact-root "$TB_ORPHAN_ROOT" >/dev/null 2>&1
|
|
2971
|
+
if flow_agents_node "$WRITER" liveness heartbeat orphan-crossactor-subj --actor agent-orphan-impostor --artifact-root "$TB_ORPHAN_ROOT" >"$TMPDIR_EVAL/orphan-crossactor.out" 2>"$TMPDIR_EVAL/orphan-crossactor.err"; then
|
|
2972
|
+
_fail "liveness (F8(i)): heartbeat for a different actor than the one who claimed should have exited nonzero"
|
|
2973
|
+
elif rg -qi 'prior claim' "$TMPDIR_EVAL/orphan-crossactor.err" && ! rg -q '"subjectId":"orphan-crossactor-subj","actor":"agent-orphan-impostor","at":"[^"]*","type":"heartbeat"' "$TB_ORPHAN_ROOT/liveness/events.jsonl" 2>/dev/null && ! rg -q '"type":"heartbeat".*"subjectId":"orphan-crossactor-subj".*"actor":"agent-orphan-impostor"' "$TB_ORPHAN_ROOT/liveness/events.jsonl" 2>/dev/null; then
|
|
2974
|
+
_pass "liveness (F8(i)): the prior-claim check is scoped per (subject, actor) pair — another actor's claim on the same subject does not satisfy it"
|
|
2975
|
+
else
|
|
2976
|
+
_fail "liveness (F8(i)) cross-actor orphan-heartbeat check failed: $(cat "$TMPDIR_EVAL/orphan-crossactor.out" "$TMPDIR_EVAL/orphan-crossactor.err")"
|
|
2977
|
+
fi
|
|
2978
|
+
|
|
2979
|
+
# claim itself is unaffected: it must still succeed with no prior claim of any kind.
|
|
2980
|
+
if flow_agents_node "$WRITER" liveness claim orphan-claim-ok-subj --actor agent-orphan-ok --artifact-root "$TB_ORPHAN_ROOT" >"$TMPDIR_EVAL/orphan-claim-ok.out" 2>"$TMPDIR_EVAL/orphan-claim-ok.err" && rg -q '"type":"claim","subjectId":"orphan-claim-ok-subj"' "$TB_ORPHAN_ROOT/liveness/events.jsonl"; then
|
|
2981
|
+
_pass "liveness (F8(i)): claim is unaffected by the prior-claim requirement — it succeeds with no prior events at all"
|
|
2982
|
+
else
|
|
2983
|
+
_fail "liveness (F8(i)) claim regressed: $(cat "$TMPDIR_EVAL/orphan-claim-ok.out" "$TMPDIR_EVAL/orphan-claim-ok.err")"
|
|
2984
|
+
fi
|
|
2985
|
+
|
|
2986
|
+
# ─── AC7: lifecycle-driven liveness (ADR 0012) — init-plan claims, advance-state releases (default-on) ──
|
|
2987
|
+
TB_LC_ROOT="$TMPDIR_EVAL/liveness-lifecycle/.kontourai/flow-agents"
|
|
2402
2988
|
TB_LC_DIR="$TB_LC_ROOT/lc-task"; mkdir -p "$TB_LC_DIR"
|
|
2403
2989
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$TB_LC_DIR/lc-task--deliver.md"
|
|
2404
|
-
|
|
2990
|
+
FLOW_AGENTS_ACTOR=agent-LC flow_agents_node "$WRITER" init-plan "$TB_LC_DIR/lc-task--deliver.md" --task-slug lc-task --source-request x --summary y --next-action z --timestamp "2026-06-25T11:50:00Z" >/dev/null 2>&1
|
|
2405
2991
|
LC_HELD=$(flow_agents_node "$WRITER" liveness status --now "2026-06-25T12:00:00Z" --artifact-root "$TB_LC_ROOT" 2>/dev/null | grep -viE "unknown format")
|
|
2406
|
-
|
|
2992
|
+
LC_CLAIM_EVENTS=$(cat "$TB_LC_ROOT/liveness/events.jsonl" 2>/dev/null)
|
|
2993
|
+
FLOW_AGENTS_ACTOR=agent-LC flow_agents_node "$WRITER" advance-state "$TB_LC_DIR" --status delivered --phase done --task-slug lc-task --timestamp "2026-06-25T11:55:00Z" >/dev/null 2>&1
|
|
2407
2994
|
LC_FREE=$(flow_agents_node "$WRITER" liveness status --now "2026-06-25T12:00:00Z" --artifact-root "$TB_LC_ROOT" 2>/dev/null | grep -viE "unknown format")
|
|
2408
|
-
TB_OFF_ROOT="$TMPDIR_EVAL/liveness-off/.flow-agents"; mkdir -p "$TB_OFF_ROOT/off-task"
|
|
2995
|
+
TB_OFF_ROOT="$TMPDIR_EVAL/liveness-off/.kontourai/flow-agents"; mkdir -p "$TB_OFF_ROOT/off-task"
|
|
2409
2996
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$TB_OFF_ROOT/off-task/off-task--deliver.md"
|
|
2410
|
-
flow_agents_node "$WRITER" init-plan "$TB_OFF_ROOT/off-task/off-task--deliver.md" --task-slug off-task --source-request x --summary y --next-action z >/dev/null 2>&1
|
|
2411
|
-
if echo "$LC_HELD" | grep -qE "lc-task.*agent-LC.*held"
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2997
|
+
FLOW_AGENTS_LIVENESS=off flow_agents_node "$WRITER" init-plan "$TB_OFF_ROOT/off-task/off-task--deliver.md" --task-slug off-task --source-request x --summary y --next-action z >/dev/null 2>&1
|
|
2998
|
+
if echo "$LC_HELD" | grep -qE "lc-task.*agent-LC.*held" \
|
|
2999
|
+
&& echo "$LC_CLAIM_EVENTS" | grep -qE '"type":"claim","subjectId":"lc-task"' \
|
|
3000
|
+
&& echo "$LC_FREE" | grep -qE "lc-task.*agent-LC.*free" \
|
|
3001
|
+
&& [ ! -f "$TB_OFF_ROOT/liveness/events.jsonl" ]; then
|
|
3002
|
+
_pass "liveness lifecycle: no env set → init-plan writes a claim event + shows held (default-on proof), advance→delivered releases (free); FLOW_AGENTS_LIVENESS=off respected (no events written)"
|
|
3003
|
+
else
|
|
3004
|
+
_fail "liveness lifecycle mismatch: held=[$LC_HELD] claim-event=[$(echo "$LC_CLAIM_EVENTS" | head -c 200)] free=[$LC_FREE] off=$([ -f "$TB_OFF_ROOT/liveness/events.jsonl" ] && echo wrote || echo none)"
|
|
3005
|
+
fi
|
|
3006
|
+
|
|
3007
|
+
# ─── F2 (#288 fix iteration 1, cr-HIGH coverage gap): FLOW_AGENTS_LIVENESS_TTL_SECONDS is
|
|
3008
|
+
# honored by the lifecycle auto-claim path — init-plan with the env var set to a custom value
|
|
3009
|
+
# must emit a claim event carrying that exact ttlSeconds, not the DEFAULT_TTL_SECONDS literal ──
|
|
3010
|
+
TB_TTL_ROOT="$TMPDIR_EVAL/liveness-ttl-env/.kontourai/flow-agents"
|
|
3011
|
+
TB_TTL_DIR="$TB_TTL_ROOT/ttl-task"; mkdir -p "$TB_TTL_DIR"
|
|
3012
|
+
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$TB_TTL_DIR/ttl-task--deliver.md"
|
|
3013
|
+
FLOW_AGENTS_ACTOR=agent-TTL FLOW_AGENTS_LIVENESS_TTL_SECONDS=300 flow_agents_node "$WRITER" init-plan "$TB_TTL_DIR/ttl-task--deliver.md" --task-slug ttl-task --source-request x --summary y --next-action z --timestamp "2026-06-25T11:50:00Z" >/dev/null 2>&1
|
|
3014
|
+
TTL_CLAIM_EVENTS=$(cat "$TB_TTL_ROOT/liveness/events.jsonl" 2>/dev/null)
|
|
3015
|
+
if echo "$TTL_CLAIM_EVENTS" | grep -qE '"type":"claim","subjectId":"ttl-task".*"ttlSeconds":300'; then
|
|
3016
|
+
_pass "liveness lifecycle: FLOW_AGENTS_LIVENESS_TTL_SECONDS=300 → emitted claim carries ttlSeconds:300 (F2, AC2)"
|
|
3017
|
+
else
|
|
3018
|
+
_fail "liveness lifecycle did not honor FLOW_AGENTS_LIVENESS_TTL_SECONDS=300: events=[$(echo "$TTL_CLAIM_EVENTS" | head -c 200)]"
|
|
3019
|
+
fi
|
|
3020
|
+
|
|
3021
|
+
# ─── F5 (#288 fix iteration 1, sec-LOW): hostile subjectId is stripped from the terminal print,
|
|
3022
|
+
# but preserved verbatim in the persisted event (display-only concern, not a write-shape change) ──
|
|
3023
|
+
TB_HOSTILE_ROOT="$TMPDIR_EVAL/liveness-hostile-subject/.kontourai/flow-agents"
|
|
3024
|
+
HOSTILE_SUBJECT=$'hostile\x1b[31msubj\x07tail'
|
|
3025
|
+
HOSTILE_OUT=$(flow_agents_node "$WRITER" liveness claim "$HOSTILE_SUBJECT" --actor agent-hostile --at "2026-06-25T11:50:00Z" --ttl 1800 --artifact-root "$TB_HOSTILE_ROOT" 2>&1)
|
|
3026
|
+
HOSTILE_EVENT=$(cat "$TB_HOSTILE_ROOT/liveness/events.jsonl" 2>/dev/null)
|
|
3027
|
+
if printf '%s' "$HOSTILE_OUT" | grep -qF $'\x1b[31m'; then
|
|
3028
|
+
HOSTILE_ESCAPE_LEAKED=true
|
|
3029
|
+
else
|
|
3030
|
+
HOSTILE_ESCAPE_LEAKED=false
|
|
3031
|
+
fi
|
|
3032
|
+
if [[ "$HOSTILE_ESCAPE_LEAKED" == "false" ]] \
|
|
3033
|
+
&& printf '%s' "$HOSTILE_OUT" | grep -qF "hostile" \
|
|
3034
|
+
&& printf '%s' "$HOSTILE_OUT" | grep -qF "tail" \
|
|
3035
|
+
&& echo "$HOSTILE_EVENT" | grep -qF 'hostile'; then
|
|
3036
|
+
_pass "liveness claim: hostile subjectId (ANSI escape + control char) is stripped from the terminal confirmation print, but preserved verbatim in the persisted event (F5)"
|
|
3037
|
+
else
|
|
3038
|
+
_fail "liveness claim hostile-subjectId print check failed: escape-leaked=$HOSTILE_ESCAPE_LEAKED out=$(printf '%s' "$HOSTILE_OUT" | cat -v) event=$(echo "$HOSTILE_EVENT" | head -c 200)"
|
|
3039
|
+
fi
|
|
3040
|
+
|
|
3041
|
+
# ─── AC5 (#287): two auto-derived sessions (no --actor, no FLOW_AGENTS_ACTOR) → two distinct held holders ──
|
|
3042
|
+
# Simulates two concurrent sessions on one host via injected CLAUDE_CODE_SESSION_ID envs (the
|
|
3043
|
+
# runtime-native session-id signal actor-identity.js's resolveActor() reads at priority layer 2).
|
|
3044
|
+
# Neither invocation passes --actor; the actor is fully auto-derived.
|
|
3045
|
+
TB_TWOHOLDERS_ROOT="$TMPDIR_EVAL/liveness-two-holders/.kontourai/flow-agents"
|
|
3046
|
+
CLAUDE_CODE_SESSION_ID=sess-a flow_agents_node "$WRITER" liveness claim two-holder-subj --ttl 1800 --artifact-root "$TB_TWOHOLDERS_ROOT" >"$TMPDIR_EVAL/two-holders-a.out" 2>"$TMPDIR_EVAL/two-holders-a.err"
|
|
3047
|
+
TWO_HOLDERS_A_STATUS=$?
|
|
3048
|
+
CLAUDE_CODE_SESSION_ID=sess-b flow_agents_node "$WRITER" liveness claim two-holder-subj --ttl 1800 --artifact-root "$TB_TWOHOLDERS_ROOT" >"$TMPDIR_EVAL/two-holders-b.out" 2>"$TMPDIR_EVAL/two-holders-b.err"
|
|
3049
|
+
TWO_HOLDERS_B_STATUS=$?
|
|
3050
|
+
flow_agents_node "$WRITER" liveness status --json --subject two-holder-subj --artifact-root "$TB_TWOHOLDERS_ROOT" >"$TMPDIR_EVAL/two-holders-status.json" 2>"$TMPDIR_EVAL/two-holders-status.err"
|
|
3051
|
+
if [[ "$TWO_HOLDERS_A_STATUS" -eq 0 && "$TWO_HOLDERS_B_STATUS" -eq 0 ]] \
|
|
3052
|
+
&& node - "$TMPDIR_EVAL/two-holders-status.json" <<'NODE'
|
|
3053
|
+
const fs = require("node:fs");
|
|
3054
|
+
const rows = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
|
|
3055
|
+
if (!Array.isArray(rows) || rows.length !== 2) throw new Error("expected 2 rows, got " + JSON.stringify(rows));
|
|
3056
|
+
const held = rows.filter((r) => r.label === "held");
|
|
3057
|
+
if (held.length !== 2) throw new Error("expected 2 held rows, got " + JSON.stringify(rows));
|
|
3058
|
+
const actors = new Set(held.map((r) => r.actor));
|
|
3059
|
+
if (actors.size !== 2) throw new Error("expected 2 distinct actors, got " + JSON.stringify([...actors]));
|
|
3060
|
+
if ([...actors].some((a) => String(a).toLowerCase() === "local")) throw new Error("actor collapsed to local: " + JSON.stringify([...actors]));
|
|
3061
|
+
NODE
|
|
3062
|
+
then
|
|
3063
|
+
_pass "liveness (AC5): two auto-derived sessions (no --actor) produce two distinct held holders, not one collapsed 'local' holder"
|
|
3064
|
+
else
|
|
3065
|
+
_fail "liveness (AC5) two-holder check failed: $(cat "$TMPDIR_EVAL/two-holders-a.out" "$TMPDIR_EVAL/two-holders-a.err" "$TMPDIR_EVAL/two-holders-b.out" "$TMPDIR_EVAL/two-holders-b.err" "$TMPDIR_EVAL/two-holders-status.err") json=$(cat "$TMPDIR_EVAL/two-holders-status.json" 2>/dev/null)"
|
|
3066
|
+
fi
|
|
3067
|
+
|
|
3068
|
+
# ─── AC6 (#287): forced-unresolved actor → liveness write exits nonzero with remediation ──
|
|
3069
|
+
# FLOW_AGENTS_ACTOR_TEST_FORCE_UNRESOLVED=1 (together with NODE_ENV=test — F4, #287 fix iteration 1:
|
|
3070
|
+
# the hatch requires BOTH vars) is the test-only escape hatch in actor-identity.js's resolveActor():
|
|
3071
|
+
# it short-circuits to {actor: "", source: "test-forced-unresolved"} before any real runtime/ancestry
|
|
3072
|
+
# detection runs, deterministically proving the fail-loud path without needing to sabotage ps/proc.
|
|
3073
|
+
# No --actor flag, no (non-forced) FLOW_AGENTS_ACTOR set.
|
|
3074
|
+
TB_FORCEUNRES_ROOT="$TMPDIR_EVAL/liveness-forced-unresolved/.kontourai/flow-agents"
|
|
3075
|
+
if FLOW_AGENTS_ACTOR_TEST_FORCE_UNRESOLVED=1 NODE_ENV=test flow_agents_node "$WRITER" liveness claim forced-unresolved-subj --artifact-root "$TB_FORCEUNRES_ROOT" >"$TMPDIR_EVAL/forced-unresolved.out" 2>"$TMPDIR_EVAL/forced-unresolved.err"; then
|
|
3076
|
+
_fail "liveness (AC6): claim with FLOW_AGENTS_ACTOR_TEST_FORCE_UNRESOLVED=1 should have exited nonzero"
|
|
3077
|
+
elif rg -q -- '--actor' "$TMPDIR_EVAL/forced-unresolved.err" && rg -q -- 'FLOW_AGENTS_ACTOR' "$TMPDIR_EVAL/forced-unresolved.err" \
|
|
3078
|
+
&& [[ ! -f "$TB_FORCEUNRES_ROOT/liveness/events.jsonl" ]]; then
|
|
3079
|
+
_pass "liveness (AC6): forced-unresolved actor (no --actor, no runtime/ancestry signal) exits nonzero naming --actor and FLOW_AGENTS_ACTOR"
|
|
3080
|
+
else
|
|
3081
|
+
_fail "liveness (AC6) forced-unresolved rejection lacked remediation or wrote an event: $(cat "$TMPDIR_EVAL/forced-unresolved.out" "$TMPDIR_EVAL/forced-unresolved.err")"
|
|
3082
|
+
fi
|
|
3083
|
+
|
|
3084
|
+
# ─── AC3 (#287): literal "local" actor is rejected even when explicitly set, not just when absent ──
|
|
3085
|
+
# Deviation note (see worker report): `FLOW_AGENTS_ACTOR=local` alone (env override, no --actor) is
|
|
3086
|
+
# REJECTED by actor-identity.js's resolveActor() at the override layer (it can never round-trip back
|
|
3087
|
+
# in via that seam — see the module's own header comment) but the command then falls through to a
|
|
3088
|
+
# real runtime/ancestry-derived actor and SUCCEEDS with that distinct, non-"local" value whenever any
|
|
3089
|
+
# resolution layer is available (true in this sandbox via CLAUDE_CODE_SESSION_ID, and true in nearly
|
|
3090
|
+
# any environment via the process-ancestry fallback) — empirically confirmed exit 0 during this
|
|
3091
|
+
# task's investigation. The `--actor local` explicit-flag path bypasses resolveActor's override
|
|
3092
|
+
# rejection and hits the liveness() guard directly, so it is the deterministic, environment-independent
|
|
3093
|
+
# way to prove "explicitly set literal local is rejected, never silently written" at the CLI level.
|
|
3094
|
+
TB_LITERALLOCAL_ROOT="$TMPDIR_EVAL/liveness-literal-local/.kontourai/flow-agents"
|
|
3095
|
+
if flow_agents_node "$WRITER" liveness claim literal-local-subj --actor local --artifact-root "$TB_LITERALLOCAL_ROOT" >"$TMPDIR_EVAL/literal-local.out" 2>"$TMPDIR_EVAL/literal-local.err"; then
|
|
3096
|
+
_fail "liveness (AC3): claim with --actor local should have exited nonzero"
|
|
3097
|
+
elif rg -q -- '--actor' "$TMPDIR_EVAL/literal-local.err" && rg -q -- 'FLOW_AGENTS_ACTOR' "$TMPDIR_EVAL/literal-local.err" \
|
|
3098
|
+
&& [[ ! -f "$TB_LITERALLOCAL_ROOT/liveness/events.jsonl" ]]; then
|
|
3099
|
+
_pass "liveness (AC3): explicit --actor local (case-insensitive literal) exits nonzero naming --actor and FLOW_AGENTS_ACTOR"
|
|
3100
|
+
else
|
|
3101
|
+
_fail "liveness (AC3) literal-local rejection lacked remediation or wrote an event: $(cat "$TMPDIR_EVAL/literal-local.out" "$TMPDIR_EVAL/literal-local.err")"
|
|
3102
|
+
fi
|
|
3103
|
+
if flow_agents_node "$WRITER" liveness claim literal-local-subj-upper --actor LOCAL --artifact-root "$TB_LITERALLOCAL_ROOT" >"$TMPDIR_EVAL/literal-local-upper.out" 2>"$TMPDIR_EVAL/literal-local-upper.err"; then
|
|
3104
|
+
_fail "liveness (AC3): claim with --actor LOCAL (case-insensitive) should have exited nonzero"
|
|
3105
|
+
else
|
|
3106
|
+
_pass "liveness (AC3): explicit --actor LOCAL is rejected case-insensitively"
|
|
3107
|
+
fi
|
|
3108
|
+
# Env-only override path: FLOW_AGENTS_ACTOR=local (no --actor) must never let "local" round-trip back
|
|
3109
|
+
# in as the persisted actor — it falls through to auto-derivation instead of dying when a resolution
|
|
3110
|
+
# layer is available (documented behavior of the override seam, see comment above).
|
|
3111
|
+
if FLOW_AGENTS_ACTOR=local flow_agents_node "$WRITER" liveness claim literal-local-env-subj --artifact-root "$TB_LITERALLOCAL_ROOT" >"$TMPDIR_EVAL/literal-local-env.out" 2>"$TMPDIR_EVAL/literal-local-env.err" \
|
|
3112
|
+
&& ! rg -q '"actor":"local"' "$TB_LITERALLOCAL_ROOT/liveness/events.jsonl" 2>/dev/null \
|
|
3113
|
+
&& ! rg -qi 'by local$' "$TMPDIR_EVAL/literal-local-env.out"; then
|
|
3114
|
+
_pass "liveness (AC3): FLOW_AGENTS_ACTOR=local override is rejected and never round-trips into the persisted actor"
|
|
3115
|
+
else
|
|
3116
|
+
_fail "liveness (AC3) FLOW_AGENTS_ACTOR=local override handling regressed: $(cat "$TMPDIR_EVAL/literal-local-env.out" "$TMPDIR_EVAL/literal-local-env.err")"
|
|
3117
|
+
fi
|
|
3118
|
+
|
|
3119
|
+
# ─── T4 (#287 fix iteration 2, F7): explicit --actor value that strips to empty under the allowed
|
|
3120
|
+
# [A-Za-z0-9_.-] charset is a hard error on the write path (unlike the env-override seam, which
|
|
3121
|
+
# falls through to derivation) — claim exits nonzero with remediation and writes no event.
|
|
3122
|
+
TB_STRIPEMPTY_ROOT="$TMPDIR_EVAL/liveness-strip-empty/.kontourai/flow-agents"
|
|
3123
|
+
if flow_agents_node "$WRITER" liveness claim strip-empty-subj --actor ':::' --artifact-root "$TB_STRIPEMPTY_ROOT" >"$TMPDIR_EVAL/strip-empty.out" 2>"$TMPDIR_EVAL/strip-empty.err"; then
|
|
3124
|
+
_fail "liveness (T4/F7): claim with --actor ':::' should have exited nonzero"
|
|
3125
|
+
elif rg -q -- '--actor' "$TMPDIR_EVAL/strip-empty.err" && [[ ! -f "$TB_STRIPEMPTY_ROOT/liveness/events.jsonl" ]]; then
|
|
3126
|
+
_pass "liveness (T4/F7): --actor ':::' (strips to empty) exits nonzero with --actor remediation and writes no event"
|
|
3127
|
+
else
|
|
3128
|
+
_fail "liveness (T4/F7) strip-to-empty --actor rejection lacked remediation or wrote an event: $(cat "$TMPDIR_EVAL/strip-empty.out" "$TMPDIR_EVAL/strip-empty.err")"
|
|
3129
|
+
fi
|
|
3130
|
+
|
|
3131
|
+
# ─── AC4 (#287): backward-compatible reads of legacy literal "local" events ──
|
|
3132
|
+
# Hand-seed liveness/events.jsonl directly (bypassing the CLI) to simulate a pre-#287 event whose
|
|
3133
|
+
# actor field is the literal string "local", then confirm `liveness status` still parses, groups, and
|
|
3134
|
+
# labels it correctly — reads must keep tolerating historical "local" events (unlike writes).
|
|
3135
|
+
TB_LEGACY_ROOT="$TMPDIR_EVAL/liveness-legacy/.kontourai/flow-agents"
|
|
3136
|
+
mkdir -p "$TB_LEGACY_ROOT/liveness"
|
|
3137
|
+
printf '%s\n' '{"type":"claim","subjectId":"legacy-subj","actor":"local","at":"2026-06-25T11:50:00Z","ttlSeconds":1800}' > "$TB_LEGACY_ROOT/liveness/events.jsonl"
|
|
3138
|
+
LEGACY_STATUS_OUT=$(flow_agents_node "$WRITER" liveness status --subject legacy-subj --now "2026-06-25T12:00:00Z" --artifact-root "$TB_LEGACY_ROOT" 2>/dev/null)
|
|
3139
|
+
if echo "$LEGACY_STATUS_OUT" | grep -qE "legacy-subj.*local.*held"; then
|
|
3140
|
+
_pass "liveness (AC4): hand-seeded legacy actor:\"local\" event still parses as one held row"
|
|
3141
|
+
else
|
|
3142
|
+
_fail "liveness (AC4) legacy 'local' event failed to parse: $LEGACY_STATUS_OUT"
|
|
2415
3143
|
fi
|
|
2416
3144
|
|
|
2417
3145
|
# ─── AC8: bundle-writers fail LOUDLY when Surface unavailable — no silent data loss (#156) ──
|
|
2418
|
-
TB_FO_DIR="$TMPDIR_EVAL/repo/.flow-agents/failopen"
|
|
3146
|
+
TB_FO_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/failopen"
|
|
2419
3147
|
mkdir -p "$TB_FO_DIR"
|
|
2420
3148
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$TB_FO_DIR/failopen--deliver.md"
|
|
2421
3149
|
flow_agents_node "$WRITER" init-plan "$TB_FO_DIR/failopen--deliver.md" --task-slug failopen --source-request x --summary y --next-action z --timestamp "2026-05-09T00:00:00Z" >/dev/null 2>&1
|
|
@@ -2435,7 +3163,7 @@ fi
|
|
|
2435
3163
|
# field matches @kontourai/surface's exported statusFunctionVersion constant.
|
|
2436
3164
|
# Also run hachure conformance vectors through Surface's deriveClaimStatus to
|
|
2437
3165
|
# confirm our producer path produces canonical statuses.
|
|
2438
|
-
TB_CONF_DIR="$TMPDIR_EVAL/repo/.flow-agents/trust-bundle-conformance"
|
|
3166
|
+
TB_CONF_DIR="$TMPDIR_EVAL/repo/.kontourai/flow-agents/trust-bundle-conformance"
|
|
2439
3167
|
mkdir -p "$TB_CONF_DIR"
|
|
2440
3168
|
cp "$ARTIFACT_DIR/auto-sidecars--deliver.md" "$TB_CONF_DIR/trust-bundle-conformance--deliver.md"
|
|
2441
3169
|
flow_agents_node "$WRITER" init-plan "$TB_CONF_DIR/trust-bundle-conformance--deliver.md" --source-request "Conformance fixture." --summary "Conformance fixture." --next-action "Record evidence and check statusFunctionVersion." --timestamp "2026-05-09T00:00:00Z" >"$TMPDIR_EVAL/tb-conf-init.out" 2>"$TMPDIR_EVAL/tb-conf-init.err"
|
|
@@ -2505,7 +3233,7 @@ fi
|
|
|
2505
3233
|
|
|
2506
3234
|
# ─── Deterministic session slug from work-item ref (#161) ───────────────────
|
|
2507
3235
|
|
|
2508
|
-
WORK_ITEM_ROOT="$TMPDIR_EVAL/work-item-repo/.flow-agents"
|
|
3236
|
+
WORK_ITEM_ROOT="$TMPDIR_EVAL/work-item-repo/.kontourai/flow-agents"
|
|
2509
3237
|
|
|
2510
3238
|
# (a) --work-item derives deterministic slug kontourai-flow-agents-161
|
|
2511
3239
|
if flow_agents_node "$WRITER" ensure-session \
|
|
@@ -2539,7 +3267,7 @@ else
|
|
|
2539
3267
|
fi
|
|
2540
3268
|
|
|
2541
3269
|
# (c) --task-slug wins over --work-item (back-compat: explicit overrides derived)
|
|
2542
|
-
TASK_SLUG_ROOT="$TMPDIR_EVAL/task-slug-repo/.flow-agents"
|
|
3270
|
+
TASK_SLUG_ROOT="$TMPDIR_EVAL/task-slug-repo/.kontourai/flow-agents"
|
|
2543
3271
|
if flow_agents_node "$WRITER" ensure-session \
|
|
2544
3272
|
--artifact-root "$TASK_SLUG_ROOT" \
|
|
2545
3273
|
--task-slug "manual-slug" \
|
|
@@ -2555,7 +3283,7 @@ else
|
|
|
2555
3283
|
fi
|
|
2556
3284
|
|
|
2557
3285
|
# (c2) --task-slug only (no --work-item) still works
|
|
2558
|
-
TASK_SLUG_ONLY_ROOT="$TMPDIR_EVAL/task-slug-only-repo/.flow-agents"
|
|
3286
|
+
TASK_SLUG_ONLY_ROOT="$TMPDIR_EVAL/task-slug-only-repo/.kontourai/flow-agents"
|
|
2559
3287
|
if flow_agents_node "$WRITER" ensure-session \
|
|
2560
3288
|
--artifact-root "$TASK_SLUG_ONLY_ROOT" \
|
|
2561
3289
|
--task-slug "explicit-only" \
|
|
@@ -2572,7 +3300,7 @@ fi
|
|
|
2572
3300
|
# ensure-session establishes the slug; liveness events (emitted by init-plan/advance-state) key
|
|
2573
3301
|
# on that same slug as subjectId. We verify this by emitting two liveness claim events directly
|
|
2574
3302
|
# via `liveness claim` using the slug derived from the ref, then asserting both share subjectId.
|
|
2575
|
-
LIVENESS_WORK_ROOT="$TMPDIR_EVAL/liveness-wi-repo/.flow-agents"
|
|
3303
|
+
LIVENESS_WORK_ROOT="$TMPDIR_EVAL/liveness-wi-repo/.kontourai/flow-agents"
|
|
2576
3304
|
# First: ensure-session --work-item produces the expected slug (directory name proof)
|
|
2577
3305
|
if flow_agents_node "$WRITER" ensure-session \
|
|
2578
3306
|
--artifact-root "$LIVENESS_WORK_ROOT" \
|