@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
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# test_assignment_provider_local_file.sh — AssignmentProvider local-file round-trip (#290).
|
|
3
|
+
#
|
|
4
|
+
# Fully deterministic: exercises `assignment-provider claim|status|supersede|release|list
|
|
5
|
+
# --provider local-file` against a temp artifact root and two fixed test-actor fixtures. No
|
|
6
|
+
# network, no `gh` process, no live provider. Follows test_pull_work_provider.sh's
|
|
7
|
+
# pass/fail/json_query idiom exactly.
|
|
8
|
+
#
|
|
9
|
+
# Supports AC5 (local-file round-trip), AC6 (list --actor), AC7 (concurrent claim never
|
|
10
|
+
# silently overwrites), AC9 (no live gh process — none invoked here at all).
|
|
11
|
+
set -uo pipefail
|
|
12
|
+
|
|
13
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
14
|
+
CLI="$ROOT/build/src/cli.js"
|
|
15
|
+
FIXTURES="$ROOT/evals/fixtures/assignment-provider"
|
|
16
|
+
ACTOR_A="$FIXTURES/actor-a.json"
|
|
17
|
+
ACTOR_B="$FIXTURES/actor-b.json"
|
|
18
|
+
SUBJECT_ID="kontourai/flow-agents#9001"
|
|
19
|
+
BRANCH_A="agent/claude-code-eval-actor-a-session-eval-host/flow-agents-9001"
|
|
20
|
+
ARTIFACT_DIR_A=".kontourai/flow-agents/flow-agents-9001"
|
|
21
|
+
|
|
22
|
+
TMPDIR_EVAL="$(mktemp -d)"
|
|
23
|
+
trap 'rm -rf "$TMPDIR_EVAL"' EXIT
|
|
24
|
+
ARTIFACT_ROOT="$TMPDIR_EVAL/artifact-root"
|
|
25
|
+
|
|
26
|
+
errors=0
|
|
27
|
+
pass() { echo " ✓ $1"; }
|
|
28
|
+
fail() { echo " ✗ $1"; errors=$((errors + 1)); }
|
|
29
|
+
|
|
30
|
+
json_query() {
|
|
31
|
+
node -e 'const fs=require("fs"); let cur=JSON.parse(fs.readFileSync(process.argv[1],"utf8")); for (const part of process.argv[2].split(".")) cur=part==="length" ? cur.length : (Array.isArray(cur) ? cur[Number(part)] : cur[part]); console.log(cur);' "$1" "$2"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if [[ ! -f "$CLI" ]]; then
|
|
35
|
+
echo "build/src/cli.js not found — run 'npm run build' first" >&2
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
echo "=== AssignmentProvider: local-file round-trip ==="
|
|
40
|
+
|
|
41
|
+
# 1. claim writes the exact versioned record shape (Design Decision 2) for a fixed test actor.
|
|
42
|
+
node "$CLI" assignment-provider claim \
|
|
43
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" \
|
|
44
|
+
--subject-id "$SUBJECT_ID" \
|
|
45
|
+
--actor-json "$ACTOR_A" \
|
|
46
|
+
--branch "$BRANCH_A" \
|
|
47
|
+
--artifact-dir "$ARTIFACT_DIR_A" \
|
|
48
|
+
--ttl-seconds 1800 \
|
|
49
|
+
> "$TMPDIR_EVAL/claim-a.json"
|
|
50
|
+
status=$?
|
|
51
|
+
[[ "$status" -eq 0 ]] && pass "claim exits successfully" || fail "claim exits successfully"
|
|
52
|
+
|
|
53
|
+
[[ "$(json_query "$TMPDIR_EVAL/claim-a.json" "record.schema_version")" == "1.0" ]] && pass "claim record schema_version is 1.0" || fail "claim record schema_version is 1.0"
|
|
54
|
+
[[ "$(json_query "$TMPDIR_EVAL/claim-a.json" "record.role")" == "AssignmentClaimRecord" ]] && pass "claim record role is AssignmentClaimRecord" || fail "claim record role is AssignmentClaimRecord"
|
|
55
|
+
[[ "$(json_query "$TMPDIR_EVAL/claim-a.json" "record.subject_id")" == "$SUBJECT_ID" ]] && pass "claim record subject_id matches" || fail "claim record subject_id matches"
|
|
56
|
+
[[ "$(json_query "$TMPDIR_EVAL/claim-a.json" "record.actor.session_id")" == "eval-actor-a-session" ]] && pass "claim record actor matches fixed test actor A" || fail "claim record actor matches fixed test actor A"
|
|
57
|
+
[[ "$(json_query "$TMPDIR_EVAL/claim-a.json" "record.ttl_seconds")" == "1800" ]] && pass "claim record ttl_seconds matches" || fail "claim record ttl_seconds matches"
|
|
58
|
+
[[ "$(json_query "$TMPDIR_EVAL/claim-a.json" "record.branch")" == "$BRANCH_A" ]] && pass "claim record branch matches" || fail "claim record branch matches"
|
|
59
|
+
[[ "$(json_query "$TMPDIR_EVAL/claim-a.json" "record.artifact_dir")" == "$ARTIFACT_DIR_A" ]] && pass "claim record artifact_dir matches" || fail "claim record artifact_dir matches"
|
|
60
|
+
[[ "$(json_query "$TMPDIR_EVAL/claim-a.json" "record.status")" == "claimed" ]] && pass "claim record status is claimed" || fail "claim record status is claimed"
|
|
61
|
+
[[ "$(json_query "$TMPDIR_EVAL/claim-a.json" "record.audit_trail.0.transition")" == "claim" ]] && pass "claim record audit_trail records the claim transition" || fail "claim record audit_trail records the claim transition"
|
|
62
|
+
|
|
63
|
+
CLAIMED_AT="$(json_query "$TMPDIR_EVAL/claim-a.json" "record.claimed_at")"
|
|
64
|
+
|
|
65
|
+
# 2. status returns actor/claimedAt matching what claim wrote.
|
|
66
|
+
node "$CLI" assignment-provider status \
|
|
67
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" --subject-id "$SUBJECT_ID" \
|
|
68
|
+
> "$TMPDIR_EVAL/status-a.json"
|
|
69
|
+
[[ "$(json_query "$TMPDIR_EVAL/status-a.json" "assignment.assignee")" == "claude-code:eval-actor-a-session:eval-host" ]] && pass "status reports actor A as assignee" || fail "status reports actor A as assignee"
|
|
70
|
+
[[ "$(json_query "$TMPDIR_EVAL/status-a.json" "assignment.record.claimed_at")" == "$CLAIMED_AT" ]] && pass "status claimed_at matches claim's claimed_at" || fail "status claimed_at matches claim's claimed_at"
|
|
71
|
+
|
|
72
|
+
# 3. supersede A -> B updates the actor and records an audit trail entry.
|
|
73
|
+
node "$CLI" assignment-provider supersede \
|
|
74
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" --subject-id "$SUBJECT_ID" \
|
|
75
|
+
--from-actor-json "$ACTOR_A" --to-actor-json "$ACTOR_B" --reason "handoff-eval" \
|
|
76
|
+
> "$TMPDIR_EVAL/supersede.json"
|
|
77
|
+
status=$?
|
|
78
|
+
[[ "$status" -eq 0 ]] && pass "supersede exits successfully" || fail "supersede exits successfully"
|
|
79
|
+
[[ "$(json_query "$TMPDIR_EVAL/supersede.json" "record.actor.session_id")" == "eval-actor-b-session" ]] && pass "supersede updates the record's actor to B" || fail "supersede updates the record's actor to B"
|
|
80
|
+
[[ "$(json_query "$TMPDIR_EVAL/supersede.json" "record.audit_trail.length")" == "2" ]] && pass "supersede appends to the audit trail (claim + supersede)" || fail "supersede appends to the audit trail (claim + supersede)"
|
|
81
|
+
[[ "$(json_query "$TMPDIR_EVAL/supersede.json" "record.audit_trail.1.transition")" == "supersede" ]] && pass "audit trail records the supersede transition" || fail "audit trail records the supersede transition"
|
|
82
|
+
[[ "$(json_query "$TMPDIR_EVAL/supersede.json" "record.audit_trail.1.from_actor.session_id")" == "eval-actor-a-session" ]] && pass "audit trail supersede entry records from_actor A" || fail "audit trail supersede entry records from_actor A"
|
|
83
|
+
[[ "$(json_query "$TMPDIR_EVAL/supersede.json" "record.audit_trail.1.to_actor.session_id")" == "eval-actor-b-session" ]] && pass "audit trail supersede entry records to_actor B" || fail "audit trail supersede entry records to_actor B"
|
|
84
|
+
[[ "$(json_query "$TMPDIR_EVAL/supersede.json" "record.audit_trail.1.reason")" == "handoff-eval" ]] && pass "audit trail supersede entry records reason" || fail "audit trail supersede entry records reason"
|
|
85
|
+
|
|
86
|
+
node "$CLI" assignment-provider status \
|
|
87
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" --subject-id "$SUBJECT_ID" \
|
|
88
|
+
> "$TMPDIR_EVAL/status-b.json"
|
|
89
|
+
[[ "$(json_query "$TMPDIR_EVAL/status-b.json" "assignment.assignee")" == "claude-code:eval-actor-b-session:eval-host" ]] && pass "status reports actor B after supersede" || fail "status reports actor B after supersede"
|
|
90
|
+
|
|
91
|
+
# 4. release clears the claim; subsequent status reports free.
|
|
92
|
+
node "$CLI" assignment-provider release \
|
|
93
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" --subject-id "$SUBJECT_ID" \
|
|
94
|
+
--actor-json "$ACTOR_B" \
|
|
95
|
+
> "$TMPDIR_EVAL/release.json"
|
|
96
|
+
status=$?
|
|
97
|
+
[[ "$status" -eq 0 ]] && pass "release exits successfully" || fail "release exits successfully"
|
|
98
|
+
[[ "$(json_query "$TMPDIR_EVAL/release.json" "record.status")" == "released" ]] && pass "release sets record status to released" || fail "release sets record status to released"
|
|
99
|
+
|
|
100
|
+
node "$CLI" assignment-provider status \
|
|
101
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" --subject-id "$SUBJECT_ID" \
|
|
102
|
+
--liveness-events-json <(echo '[]') \
|
|
103
|
+
> "$TMPDIR_EVAL/status-free.json"
|
|
104
|
+
[[ "$(json_query "$TMPDIR_EVAL/status-free.json" "assignment.assignee")" == "null" ]] && pass "status reports no assignee after release" || fail "status reports no assignee after release"
|
|
105
|
+
[[ "$(json_query "$TMPDIR_EVAL/status-free.json" "effective.effective_state")" == "free" ]] && pass "status reports effective_state free after release" || fail "status reports effective_state free after release"
|
|
106
|
+
|
|
107
|
+
# 5. list --actor returns exactly that actor's claimed subject ids (claim a second subject
|
|
108
|
+
# under actor A, then verify list --actor A returns exactly that one subject).
|
|
109
|
+
SUBJECT_ID_2="kontourai/flow-agents#9002"
|
|
110
|
+
node "$CLI" assignment-provider claim \
|
|
111
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" \
|
|
112
|
+
--subject-id "$SUBJECT_ID_2" \
|
|
113
|
+
--actor-json "$ACTOR_A" \
|
|
114
|
+
--branch "agent/claude-code-eval-actor-a-session-eval-host/flow-agents-9002" \
|
|
115
|
+
--artifact-dir ".kontourai/flow-agents/flow-agents-9002" \
|
|
116
|
+
> /dev/null
|
|
117
|
+
node "$CLI" assignment-provider list \
|
|
118
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" --actor-json "$ACTOR_A" \
|
|
119
|
+
> "$TMPDIR_EVAL/list-a.json"
|
|
120
|
+
[[ "$(json_query "$TMPDIR_EVAL/list-a.json" "subject_ids.length")" == "1" ]] && pass "list --actor A returns exactly one subject id" || fail "list --actor A returns exactly one subject id"
|
|
121
|
+
[[ "$(json_query "$TMPDIR_EVAL/list-a.json" "subject_ids.0")" == "$SUBJECT_ID_2" ]] && pass "list --actor A returns actor A's currently-claimed subject (released subject excluded)" || fail "list --actor A returns actor A's currently-claimed subject (released subject excluded)"
|
|
122
|
+
|
|
123
|
+
node "$CLI" assignment-provider list \
|
|
124
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" --actor-json "$ACTOR_B" \
|
|
125
|
+
> "$TMPDIR_EVAL/list-b.json"
|
|
126
|
+
[[ "$(json_query "$TMPDIR_EVAL/list-b.json" "subject_ids.length")" == "0" ]] && pass "list --actor B returns no subject ids (its only claim was released)" || fail "list --actor B returns no subject ids (its only claim was released)"
|
|
127
|
+
|
|
128
|
+
# 6. Two concurrent claims on the same subject from different actors: the second call must
|
|
129
|
+
# fail loud (non-zero exit + holder-identifying error), never silently overwrite the first
|
|
130
|
+
# (AC7; artifact-contract.md's "fail loud, never fail-open" persistence rule).
|
|
131
|
+
node "$CLI" assignment-provider claim \
|
|
132
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" \
|
|
133
|
+
--subject-id "$SUBJECT_ID_2" \
|
|
134
|
+
--actor-json "$ACTOR_B" \
|
|
135
|
+
--branch "agent/claude-code-eval-actor-b-session-eval-host/flow-agents-9002" \
|
|
136
|
+
--artifact-dir ".kontourai/flow-agents/flow-agents-9002" \
|
|
137
|
+
> "$TMPDIR_EVAL/concurrent-claim.json" 2> "$TMPDIR_EVAL/concurrent-claim.err"
|
|
138
|
+
concurrent_status=$?
|
|
139
|
+
[[ "$concurrent_status" -ne 0 ]] && pass "second claim from a different actor fails loud (non-zero exit)" || fail "second claim from a different actor fails loud (non-zero exit)"
|
|
140
|
+
grep -q "already claimed by a different actor" "$TMPDIR_EVAL/concurrent-claim.err" && pass "second claim's error identifies the existing holder" || fail "second claim's error identifies the existing holder"
|
|
141
|
+
|
|
142
|
+
node "$CLI" assignment-provider status \
|
|
143
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" --subject-id "$SUBJECT_ID_2" \
|
|
144
|
+
> "$TMPDIR_EVAL/status-after-concurrent.json"
|
|
145
|
+
[[ "$(json_query "$TMPDIR_EVAL/status-after-concurrent.json" "assignment.assignee")" == "claude-code:eval-actor-a-session:eval-host" ]] && pass "record still shows actor A as holder — no silent overwrite" || fail "record still shows actor A as holder — no silent overwrite"
|
|
146
|
+
|
|
147
|
+
# Same-actor re-claim (refresh before TTL expiry) is allowed and idempotent — must not error.
|
|
148
|
+
node "$CLI" assignment-provider claim \
|
|
149
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" \
|
|
150
|
+
--subject-id "$SUBJECT_ID_2" \
|
|
151
|
+
--actor-json "$ACTOR_A" \
|
|
152
|
+
--branch "agent/claude-code-eval-actor-a-session-eval-host/flow-agents-9002" \
|
|
153
|
+
--artifact-dir ".kontourai/flow-agents/flow-agents-9002" \
|
|
154
|
+
> /dev/null 2>&1
|
|
155
|
+
[[ $? -eq 0 ]] && pass "same-actor re-claim (refresh) succeeds without error" || fail "same-actor re-claim (refresh) succeeds without error"
|
|
156
|
+
|
|
157
|
+
echo ""
|
|
158
|
+
|
|
159
|
+
# 7. F1 fix-plan iteration 1 (CRITICAL): GENUINE OS-process concurrency — two REAL,
|
|
160
|
+
# concurrently-launched `claim` processes (background `&` + `wait`, not the sequential case in
|
|
161
|
+
# section 6 above which never actually races) targeting the SAME fresh subject from DIFFERENT
|
|
162
|
+
# actors. Before the withSubjectLock fix, both processes could read "no existing claim" before
|
|
163
|
+
# either wrote, and one write would silently clobber the other (reproduced 29/40 races against
|
|
164
|
+
# the built CLI pre-fix). Assert EXACTLY ONE process exits 0, and the on-disk record shows
|
|
165
|
+
# exactly one holder with an intact, single-entry audit trail (no lost write).
|
|
166
|
+
SUBJECT_ID_RACE="kontourai/flow-agents#9003"
|
|
167
|
+
BRANCH_RACE_A="agent/claude-code-eval-actor-a-session-eval-host/flow-agents-9003"
|
|
168
|
+
BRANCH_RACE_B="agent/claude-code-eval-actor-b-session-eval-host/flow-agents-9003"
|
|
169
|
+
ARTIFACT_DIR_RACE=".kontourai/flow-agents/flow-agents-9003"
|
|
170
|
+
|
|
171
|
+
(
|
|
172
|
+
node "$CLI" assignment-provider claim \
|
|
173
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" \
|
|
174
|
+
--subject-id "$SUBJECT_ID_RACE" \
|
|
175
|
+
--actor-json "$ACTOR_A" \
|
|
176
|
+
--branch "$BRANCH_RACE_A" \
|
|
177
|
+
--artifact-dir "$ARTIFACT_DIR_RACE" \
|
|
178
|
+
> "$TMPDIR_EVAL/race-a.out" 2> "$TMPDIR_EVAL/race-a.err"
|
|
179
|
+
echo $? > "$TMPDIR_EVAL/race-a.rc"
|
|
180
|
+
) &
|
|
181
|
+
PID_A=$!
|
|
182
|
+
(
|
|
183
|
+
node "$CLI" assignment-provider claim \
|
|
184
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" \
|
|
185
|
+
--subject-id "$SUBJECT_ID_RACE" \
|
|
186
|
+
--actor-json "$ACTOR_B" \
|
|
187
|
+
--branch "$BRANCH_RACE_B" \
|
|
188
|
+
--artifact-dir "$ARTIFACT_DIR_RACE" \
|
|
189
|
+
> "$TMPDIR_EVAL/race-b.out" 2> "$TMPDIR_EVAL/race-b.err"
|
|
190
|
+
echo $? > "$TMPDIR_EVAL/race-b.rc"
|
|
191
|
+
) &
|
|
192
|
+
PID_B=$!
|
|
193
|
+
wait "$PID_A" "$PID_B"
|
|
194
|
+
|
|
195
|
+
RACE_RC_A="$(cat "$TMPDIR_EVAL/race-a.rc")"
|
|
196
|
+
RACE_RC_B="$(cat "$TMPDIR_EVAL/race-b.rc")"
|
|
197
|
+
|
|
198
|
+
if { [[ "$RACE_RC_A" -eq 0 && "$RACE_RC_B" -ne 0 ]] || [[ "$RACE_RC_A" -ne 0 && "$RACE_RC_B" -eq 0 ]]; }; then
|
|
199
|
+
pass "genuine concurrent claim race: exactly one process wins (rc_a=$RACE_RC_A rc_b=$RACE_RC_B)"
|
|
200
|
+
else
|
|
201
|
+
fail "genuine concurrent claim race: exactly one process wins (rc_a=$RACE_RC_A rc_b=$RACE_RC_B)"
|
|
202
|
+
fi
|
|
203
|
+
|
|
204
|
+
node "$CLI" assignment-provider status \
|
|
205
|
+
--provider local-file --artifact-root "$ARTIFACT_ROOT" --subject-id "$SUBJECT_ID_RACE" \
|
|
206
|
+
> "$TMPDIR_EVAL/status-race.json"
|
|
207
|
+
[[ "$(json_query "$TMPDIR_EVAL/status-race.json" "assignment.record.audit_trail.length")" == "1" ]] && pass "race winner's on-disk record has exactly one audit_trail entry (no lost/merged write)" || fail "race winner's on-disk record has exactly one audit_trail entry (no lost/merged write)"
|
|
208
|
+
|
|
209
|
+
if [[ "$RACE_RC_A" -eq 0 ]]; then
|
|
210
|
+
EXPECTED_RACE_HOLDER="claude-code:eval-actor-a-session:eval-host"
|
|
211
|
+
else
|
|
212
|
+
EXPECTED_RACE_HOLDER="claude-code:eval-actor-b-session:eval-host"
|
|
213
|
+
fi
|
|
214
|
+
[[ "$(json_query "$TMPDIR_EVAL/status-race.json" "assignment.assignee")" == "$EXPECTED_RACE_HOLDER" ]] && pass "on-disk record holder matches the process that actually exited 0 (no silent overwrite by the loser)" || fail "on-disk record holder matches the process that actually exited 0 (no silent overwrite by the loser)"
|
|
215
|
+
|
|
216
|
+
echo ""
|
|
217
|
+
if [[ "$errors" -eq 0 ]]; then
|
|
218
|
+
echo "test_assignment_provider_local_file: all checks passed."
|
|
219
|
+
else
|
|
220
|
+
echo "test_assignment_provider_local_file: $errors check(s) failed."
|
|
221
|
+
fi
|
|
222
|
+
exit "$errors"
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
# 5. builder.learn.decisions (step: learn, expectation: decision-evidence)
|
|
16
16
|
# 6. builder.learn.evidence (step: learn, expectation: learning-evidence)
|
|
17
17
|
#
|
|
18
|
-
#
|
|
19
|
-
# - All 6 claims above are required:true.
|
|
18
|
+
# Flow Definition confirmation:
|
|
19
|
+
# - All 6 claims above are required:true across builder.build and builder.publish-learn.
|
|
20
20
|
# - policy-compliance remains required:false (advisory — no skill producer).
|
|
21
21
|
#
|
|
22
22
|
# Deterministic, no model spend, self-cleaning.
|
|
@@ -106,21 +106,21 @@ setup_tamper_session() {
|
|
|
106
106
|
local t_dir="$1" slug="$2" step="$3"
|
|
107
107
|
mkdir -p "$t_dir"
|
|
108
108
|
printf '# Repo\n' > "$t_dir/AGENTS.md"
|
|
109
|
-
mkdir -p "$t_dir/.flow-agents/$slug"
|
|
109
|
+
mkdir -p "$t_dir/.kontourai/flow-agents/$slug"
|
|
110
110
|
|
|
111
111
|
flow_agents_node "workflow-sidecar" ensure-session \
|
|
112
|
-
--artifact-root "$t_dir/.flow-agents" \
|
|
112
|
+
--artifact-root "$t_dir/.kontourai/flow-agents" \
|
|
113
113
|
--task-slug "$slug" \
|
|
114
114
|
--title "Tamper test: $step" \
|
|
115
115
|
--summary "Testing tamper detection." \
|
|
116
116
|
--flow-id builder.build \
|
|
117
117
|
--timestamp "2026-06-26T00:00:00Z" >/dev/null 2>&1
|
|
118
118
|
|
|
119
|
-
flow_agents_node "workflow-sidecar" init-plan "$t_dir/.flow-agents/$slug/$slug--deliver.md" \
|
|
119
|
+
flow_agents_node "workflow-sidecar" init-plan "$t_dir/.kontourai/flow-agents/$slug/$slug--deliver.md" \
|
|
120
120
|
--source-request "Test" --summary "Testing" \
|
|
121
121
|
--timestamp "2026-06-26T00:00:00Z" >/dev/null 2>&1
|
|
122
122
|
|
|
123
|
-
set_active_step "$t_dir/.flow-agents" "$slug" "$step"
|
|
123
|
+
set_active_step "$t_dir/.kontourai/flow-agents" "$slug" "$step"
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
# ─── Test: produce a gate claim at a given step ───────────────────────────────
|
|
@@ -178,12 +178,12 @@ test_tamper_blocks() {
|
|
|
178
178
|
setup_tamper_session "$t_dir" "$slug" "$step"
|
|
179
179
|
|
|
180
180
|
# Write a TAMPERED trust.bundle: stored verified, evidence passing=false
|
|
181
|
-
python3 - "$t_dir/.flow-agents/$slug/trust.bundle" "$claim_type" "$subject_type" << 'PY'
|
|
181
|
+
python3 - "$t_dir/.kontourai/flow-agents/$slug/trust.bundle" "$claim_type" "$subject_type" << 'PY'
|
|
182
182
|
import json, sys
|
|
183
183
|
claim_type = sys.argv[2]
|
|
184
184
|
subject_type = sys.argv[3]
|
|
185
185
|
bundle = {
|
|
186
|
-
"schemaVersion":
|
|
186
|
+
"schemaVersion": 5,
|
|
187
187
|
"source": "flow-agents/workflow-sidecar",
|
|
188
188
|
"claims": [{
|
|
189
189
|
"id": "c1",
|
|
@@ -254,13 +254,16 @@ PY
|
|
|
254
254
|
fi
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
# ─── Test 0:
|
|
257
|
+
# ─── Test 0: Flow Definition required:true confirmation ──────────────────────
|
|
258
258
|
echo ""
|
|
259
|
-
echo "=== 0.
|
|
259
|
+
echo "=== 0. Flow Definitions: confirm required:true for produced gates ==="
|
|
260
260
|
|
|
261
261
|
node -e "
|
|
262
262
|
const fs = require('fs');
|
|
263
|
-
const
|
|
263
|
+
const flows = [
|
|
264
|
+
JSON.parse(fs.readFileSync('$ROOT/kits/builder/flows/build.flow.json', 'utf8')),
|
|
265
|
+
JSON.parse(fs.readFileSync('$ROOT/kits/builder/flows/publish-learn.flow.json', 'utf8')),
|
|
266
|
+
];
|
|
264
267
|
const requiredTrue = [
|
|
265
268
|
'selected-work',
|
|
266
269
|
'pickup-probe-readiness',
|
|
@@ -271,26 +274,31 @@ node -e "
|
|
|
271
274
|
];
|
|
272
275
|
const requiredFalse = ['policy-compliance'];
|
|
273
276
|
let ok = true;
|
|
274
|
-
for (const
|
|
275
|
-
for (const
|
|
277
|
+
for (const flow of flows) {
|
|
278
|
+
for (const [gateName, gate] of Object.entries(flow.gates || {})) {
|
|
279
|
+
for (const exp of gate.expects || []) {
|
|
276
280
|
if (requiredTrue.includes(exp.id) && exp.required !== true) {
|
|
277
|
-
console.error('FAIL: ' + exp.id + ' in ' + gateName + ' should be required:true, got ' + exp.required);
|
|
281
|
+
console.error('FAIL: ' + exp.id + ' in ' + flow.id + '/' + gateName + ' should be required:true, got ' + exp.required);
|
|
278
282
|
ok = false;
|
|
279
283
|
}
|
|
280
284
|
if (requiredFalse.includes(exp.id) && exp.required !== false) {
|
|
281
|
-
console.error('FAIL: ' + exp.id + ' in ' + gateName + ' should remain required:false (advisory), got ' + exp.required);
|
|
285
|
+
console.error('FAIL: ' + exp.id + ' in ' + flow.id + '/' + gateName + ' should remain required:false (advisory), got ' + exp.required);
|
|
282
286
|
ok = false;
|
|
283
287
|
}
|
|
288
|
+
}
|
|
284
289
|
}
|
|
285
290
|
}
|
|
286
291
|
if (!ok) process.exit(1);
|
|
287
292
|
" 2>/dev/null \
|
|
288
|
-
&& _pass "
|
|
289
|
-
|| _fail "
|
|
293
|
+
&& _pass "Flow Definitions: 6 produced gates are required:true, policy-compliance is required:false" \
|
|
294
|
+
|| _fail "Flow Definitions: required flag mismatch"
|
|
290
295
|
|
|
291
296
|
node -e "
|
|
292
297
|
const fs = require('fs');
|
|
293
|
-
const
|
|
298
|
+
const flows = [
|
|
299
|
+
JSON.parse(fs.readFileSync('$ROOT/kits/builder/flows/build.flow.json', 'utf8')),
|
|
300
|
+
JSON.parse(fs.readFileSync('$ROOT/kits/builder/flows/publish-learn.flow.json', 'utf8')),
|
|
301
|
+
];
|
|
294
302
|
const producedIds = [
|
|
295
303
|
'selected-work',
|
|
296
304
|
'pickup-probe-readiness',
|
|
@@ -300,18 +308,20 @@ node -e "
|
|
|
300
308
|
'learning-evidence',
|
|
301
309
|
];
|
|
302
310
|
let ok = true;
|
|
303
|
-
for (const
|
|
304
|
-
for (const
|
|
311
|
+
for (const flow of flows) {
|
|
312
|
+
for (const [gateName, gate] of Object.entries(flow.gates || {})) {
|
|
313
|
+
for (const exp of gate.expects || []) {
|
|
305
314
|
if (producedIds.includes(exp.id) && exp.explore_hint) {
|
|
306
|
-
console.error('FAIL: ' + exp.id + ' in ' + gateName + ' still has explore_hint (remove when producer exists)');
|
|
315
|
+
console.error('FAIL: ' + exp.id + ' in ' + flow.id + '/' + gateName + ' still has explore_hint (remove when producer exists)');
|
|
307
316
|
ok = false;
|
|
308
317
|
}
|
|
318
|
+
}
|
|
309
319
|
}
|
|
310
320
|
}
|
|
311
321
|
if (!ok) process.exit(1);
|
|
312
322
|
" 2>/dev/null \
|
|
313
|
-
&& _pass "
|
|
314
|
-
|| _fail "
|
|
323
|
+
&& _pass "Flow Definitions: no explore_hint on produced gate entries" \
|
|
324
|
+
|| _fail "Flow Definitions: produced gate entries still have explore_hint"
|
|
315
325
|
|
|
316
326
|
# ─── Tests 1–6: produce + tamper-block for each of the 6 claims ──────────────
|
|
317
327
|
|
|
@@ -158,13 +158,17 @@ echo "--- Installed Layout ---"
|
|
|
158
158
|
for dir in \
|
|
159
159
|
"$KIRO_DEST/agents" \
|
|
160
160
|
"$BASE_DEST/.flow-agents" \
|
|
161
|
+
"$BASE_DEST/.kontourai/flow-agents" \
|
|
161
162
|
"$CLAUDE_DEST/.claude/agents" \
|
|
162
163
|
"$CLAUDE_DEST/.claude/skills" \
|
|
163
164
|
"$CLAUDE_DEST/.flow-agents" \
|
|
165
|
+
"$CLAUDE_DEST/.kontourai/flow-agents" \
|
|
164
166
|
"$CODEX_DEST/.codex/agents" \
|
|
165
167
|
"$CODEX_DEST/.codex/skills" \
|
|
166
168
|
"$CODEX_DEST/.flow-agents" \
|
|
167
|
-
"$
|
|
169
|
+
"$CODEX_DEST/.kontourai/flow-agents" \
|
|
170
|
+
"$CODEX_FULL_DEST/.flow-agents" \
|
|
171
|
+
"$CODEX_FULL_DEST/.kontourai/flow-agents"; do
|
|
168
172
|
if [[ -d "$dir" ]]; then
|
|
169
173
|
_pass "$dir exists"
|
|
170
174
|
else
|
|
@@ -218,7 +222,7 @@ fi
|
|
|
218
222
|
|
|
219
223
|
if rg -F -q "console_telemetry_url=$LOCAL_KONTOUR_CONSOLE_URL" "$CODEX_INIT_DEST/scripts/telemetry/telemetry.conf" \
|
|
220
224
|
&& rg -q '^console_tenant_id=tenant-a$' "$CODEX_INIT_DEST/scripts/telemetry/telemetry.conf" \
|
|
221
|
-
&& [[ -f "$CODEX_INIT_DEST/.flow-agents/
|
|
225
|
+
&& [[ -f "$CODEX_INIT_DEST/.kontourai/flow-agents/projections/codex/activation.json" ]]; then
|
|
222
226
|
_pass "flow-agents init persists Console config and activates Codex kits"
|
|
223
227
|
else
|
|
224
228
|
_fail "flow-agents init did not persist Console config or activate Codex kits"
|
|
@@ -226,6 +230,7 @@ fi
|
|
|
226
230
|
|
|
227
231
|
if [[ -f "$BASE_INIT_DEST/AGENTS.md" ]] \
|
|
228
232
|
&& [[ -d "$BASE_INIT_DEST/.flow-agents" ]] \
|
|
233
|
+
&& [[ -d "$BASE_INIT_DEST/.kontourai/flow-agents" ]] \
|
|
229
234
|
&& rg -F -q "console_telemetry_url=$LOCAL_KONTOUR_CONSOLE_URL" "$BASE_INIT_DEST/scripts/telemetry/telemetry.conf"; then
|
|
230
235
|
_pass "flow-agents init default installs base AGENTS.md workspace contract"
|
|
231
236
|
else
|
|
@@ -287,7 +292,7 @@ NODE
|
|
|
287
292
|
else
|
|
288
293
|
_fail "$dir is missing Kit Catalog or Builder Kit manifest"
|
|
289
294
|
fi
|
|
290
|
-
if [[ -f "$dir/kits/builder/flows/shape.flow.json" && -f "$dir/kits/builder/flows/build.flow.json" ]]; then
|
|
295
|
+
if [[ -f "$dir/kits/builder/flows/shape.flow.json" && -f "$dir/kits/builder/flows/build.flow.json" && -f "$dir/kits/builder/flows/publish-learn.flow.json" ]]; then
|
|
291
296
|
_pass "$dir includes Builder Kit Flow Definitions"
|
|
292
297
|
else
|
|
293
298
|
_fail "$dir is missing Builder Kit Flow Definitions"
|
|
@@ -316,13 +321,13 @@ const dest = process.argv[2];
|
|
|
316
321
|
const data = JSON.parse(fs.readFileSync(process.argv[3], "utf8"));
|
|
317
322
|
if (data.selected_adapter !== "codex-local") throw new Error("codex-local was not selected");
|
|
318
323
|
const ids = new Set((data.generated_runtime_files || []).map((item) => item.asset_id));
|
|
319
|
-
for (const expected of ["builder.shape", "builder.build", "codex-local.activation"]) {
|
|
324
|
+
for (const expected of ["builder.shape", "builder.build", "builder.publish-learn", "codex-local.activation"]) {
|
|
320
325
|
if (!ids.has(expected)) throw new Error(`missing generated runtime asset: ${expected}`);
|
|
321
326
|
}
|
|
322
327
|
for (const item of data.generated_runtime_files || []) {
|
|
323
328
|
if (!fs.existsSync(path.join(dest, item.path))) throw new Error(`generated runtime file missing: ${item.path}`);
|
|
324
329
|
}
|
|
325
|
-
if (!fs.existsSync(path.join(dest, ".flow-agents/
|
|
330
|
+
if (!fs.existsSync(path.join(dest, ".kontourai/flow-agents/projections/codex/activation.json"))) throw new Error("runtime activation manifest missing");
|
|
326
331
|
console.log("ok");
|
|
327
332
|
NODE
|
|
328
333
|
then
|
|
@@ -335,7 +340,7 @@ if node - "$KIRO_DEST" "$BASE_DEST" "$CLAUDE_DEST" "$CODEX_DEST" <<'NODE'
|
|
|
335
340
|
const fs = require("node:fs");
|
|
336
341
|
const path = require("node:path");
|
|
337
342
|
for (const root of process.argv.slice(2)) {
|
|
338
|
-
for (const rel of ["kits/catalog.json", "kits/builder/kit.json", "kits/builder/flows/shape.flow.json", "kits/builder/flows/build.flow.json"]) {
|
|
343
|
+
for (const rel of ["kits/catalog.json", "kits/builder/kit.json", "kits/builder/flows/shape.flow.json", "kits/builder/flows/build.flow.json", "kits/builder/flows/publish-learn.flow.json"]) {
|
|
339
344
|
JSON.parse(fs.readFileSync(path.join(root, rel), "utf8"));
|
|
340
345
|
}
|
|
341
346
|
}
|
|
@@ -367,25 +372,25 @@ else
|
|
|
367
372
|
_pass "installed bundles are free of machine-local absolute paths"
|
|
368
373
|
fi
|
|
369
374
|
|
|
370
|
-
if [[ -f "$CLAUDE_DEST/.flow-agents/.gitkeep" ]]; then
|
|
375
|
+
if [[ -f "$CLAUDE_DEST/.kontourai/flow-agents/.gitkeep" ]]; then
|
|
371
376
|
_pass "Claude Code task dir scaffold installed"
|
|
372
377
|
else
|
|
373
378
|
_fail "Claude Code task dir scaffold missing"
|
|
374
379
|
fi
|
|
375
380
|
|
|
376
|
-
if [[ -f "$CODEX_DEST/.flow-agents/.gitkeep" ]]; then
|
|
381
|
+
if [[ -f "$CODEX_DEST/.kontourai/flow-agents/.gitkeep" ]]; then
|
|
377
382
|
_pass "Codex task dir scaffold installed"
|
|
378
383
|
else
|
|
379
384
|
_fail "Codex task dir scaffold missing"
|
|
380
385
|
fi
|
|
381
386
|
|
|
382
|
-
if [[ -f "$OPENCODE_DEST/.flow-agents/.gitkeep" ]]; then
|
|
387
|
+
if [[ -f "$OPENCODE_DEST/.kontourai/flow-agents/.gitkeep" ]]; then
|
|
383
388
|
_pass "opencode task dir scaffold installed"
|
|
384
389
|
else
|
|
385
390
|
_fail "opencode task dir scaffold missing"
|
|
386
391
|
fi
|
|
387
392
|
|
|
388
|
-
if [[ -f "$PI_DEST/.flow-agents/.gitkeep" ]]; then
|
|
393
|
+
if [[ -f "$PI_DEST/.kontourai/flow-agents/.gitkeep" ]]; then
|
|
389
394
|
_pass "pi task dir scaffold installed"
|
|
390
395
|
else
|
|
391
396
|
_fail "pi task dir scaffold missing"
|
|
@@ -417,9 +422,10 @@ else
|
|
|
417
422
|
_fail "installed Claude permissions/statusline or Codex profile-v2 progress config is missing"
|
|
418
423
|
fi
|
|
419
424
|
|
|
420
|
-
if [[ -f "$CODEX_DEST/.codex/
|
|
421
|
-
&&
|
|
422
|
-
&& rg -q '
|
|
425
|
+
if [[ -f "$CODEX_DEST/.codex/builder.config.toml" && -f "$CODEX_DEST/.codex/personal.config.toml" ]] \
|
|
426
|
+
&& [[ "$(find "$CODEX_DEST/.codex" -maxdepth 1 -name '*.config.toml' | wc -l | tr -d ' ')" == "2" ]] \
|
|
427
|
+
&& rg -q 'Flow Agents Builder mode' "$CODEX_DEST/.codex/builder.config.toml" \
|
|
428
|
+
&& rg -q 'knowledge-capture' "$CODEX_DEST/.codex/personal.config.toml"; then
|
|
423
429
|
_pass "Codex install includes profile-v2 config files"
|
|
424
430
|
else
|
|
425
431
|
_fail "Codex install is missing profile-v2 config files"
|
|
@@ -517,7 +523,7 @@ const critique = {
|
|
|
517
523
|
}],
|
|
518
524
|
};
|
|
519
525
|
function writeFixture(root) {
|
|
520
|
-
const taskDir = path.join(root, ".flow-agents/installed-hook-demo");
|
|
526
|
+
const taskDir = path.join(root, ".kontourai/flow-agents/installed-hook-demo");
|
|
521
527
|
fs.mkdirSync(taskDir, { recursive: true });
|
|
522
528
|
fs.writeFileSync(path.join(taskDir, "state.json"), JSON.stringify(state), "utf8");
|
|
523
529
|
fs.writeFileSync(path.join(taskDir, "critique.json"), JSON.stringify(critique), "utf8");
|
|
@@ -593,7 +599,7 @@ const critique = {
|
|
|
593
599
|
critiques: [{ id: "oc-review", reviewer: "tool-code-reviewer", reviewed_at: "2026-06-01T00:01:00Z", verdict: "fail", summary: "Blocking.", findings: [{ id: "oc-open", severity: "high", status: "open", description: "Open finding." }] }],
|
|
594
600
|
};
|
|
595
601
|
function writeFixture(root) {
|
|
596
|
-
const taskDir = path.join(root, ".flow-agents/opencode-hook-demo");
|
|
602
|
+
const taskDir = path.join(root, ".kontourai/flow-agents/opencode-hook-demo");
|
|
597
603
|
fs.mkdirSync(taskDir, { recursive: true });
|
|
598
604
|
fs.writeFileSync(path.join(taskDir, "state.json"), JSON.stringify(state), "utf8");
|
|
599
605
|
fs.writeFileSync(path.join(taskDir, "critique.json"), JSON.stringify(critique), "utf8");
|
|
@@ -652,7 +658,7 @@ const critique = {
|
|
|
652
658
|
critiques: [{ id: "pi-review", reviewer: "tool-code-reviewer", reviewed_at: "2026-06-01T00:01:00Z", verdict: "fail", summary: "Blocking.", findings: [{ id: "pi-open", severity: "high", status: "open", description: "Open finding." }] }],
|
|
653
659
|
};
|
|
654
660
|
function writeFixture(root) {
|
|
655
|
-
const taskDir = path.join(root, ".flow-agents/pi-hook-demo");
|
|
661
|
+
const taskDir = path.join(root, ".kontourai/flow-agents/pi-hook-demo");
|
|
656
662
|
fs.mkdirSync(taskDir, { recursive: true });
|
|
657
663
|
fs.writeFileSync(path.join(taskDir, "state.json"), JSON.stringify(state), "utf8");
|
|
658
664
|
fs.writeFileSync(path.join(taskDir, "critique.json"), JSON.stringify(critique), "utf8");
|
|
@@ -231,18 +231,18 @@ OPENCODE_USER="$TMPDIR_EVAL/user-opencode"
|
|
|
231
231
|
# Create user-owned files (unknown to the bundle)
|
|
232
232
|
mkdir -p "$CLAUDE_USER/.claude/custom"
|
|
233
233
|
echo "# user custom agent" > "$CLAUDE_USER/.claude/custom/my-custom-agent.md"
|
|
234
|
-
mkdir -p "$CLAUDE_USER/.flow-agents/my-session"
|
|
235
|
-
echo '{"custom":"data"}' > "$CLAUDE_USER/.flow-agents/my-session/state.json"
|
|
234
|
+
mkdir -p "$CLAUDE_USER/.kontourai/flow-agents/my-session"
|
|
235
|
+
echo '{"custom":"data"}' > "$CLAUDE_USER/.kontourai/flow-agents/my-session/state.json"
|
|
236
236
|
|
|
237
237
|
mkdir -p "$CODEX_USER/.codex/custom"
|
|
238
238
|
printf 'name = "my-custom-agent"\n' > "$CODEX_USER/.codex/custom/my-custom-agent.toml"
|
|
239
|
-
mkdir -p "$CODEX_USER/.flow-agents/my-session"
|
|
240
|
-
echo '{"custom":"data"}' > "$CODEX_USER/.flow-agents/my-session/state.json"
|
|
239
|
+
mkdir -p "$CODEX_USER/.kontourai/flow-agents/my-session"
|
|
240
|
+
echo '{"custom":"data"}' > "$CODEX_USER/.kontourai/flow-agents/my-session/state.json"
|
|
241
241
|
|
|
242
242
|
mkdir -p "$OPENCODE_USER/.opencode/custom"
|
|
243
243
|
echo "# user custom agent" > "$OPENCODE_USER/.opencode/custom/my-custom-agent.md"
|
|
244
|
-
mkdir -p "$OPENCODE_USER/.flow-agents/my-session"
|
|
245
|
-
echo '{"custom":"data"}' > "$OPENCODE_USER/.flow-agents/my-session/state.json"
|
|
244
|
+
mkdir -p "$OPENCODE_USER/.kontourai/flow-agents/my-session"
|
|
245
|
+
echo '{"custom":"data"}' > "$OPENCODE_USER/.kontourai/flow-agents/my-session/state.json"
|
|
246
246
|
|
|
247
247
|
# Modify an installed skill file to simulate user edits
|
|
248
248
|
CLAUDE_INSTALLED_SKILL="$CLAUDE_USER/.claude/skills/plan-work/SKILL.md"
|
|
@@ -272,19 +272,19 @@ fi
|
|
|
272
272
|
(cd "$ROOT_DIR/dist/opencode" && bash install.sh "$OPENCODE_USER" >/dev/null 2>&1) || true
|
|
273
273
|
|
|
274
274
|
# Assert: user-owned unknown files survive
|
|
275
|
-
if [[ -f "$CLAUDE_USER/.claude/custom/my-custom-agent.md" && -f "$CLAUDE_USER/.flow-agents/my-session/state.json" ]]; then
|
|
275
|
+
if [[ -f "$CLAUDE_USER/.claude/custom/my-custom-agent.md" && -f "$CLAUDE_USER/.kontourai/flow-agents/my-session/state.json" ]]; then
|
|
276
276
|
_pass "claude-code re-install: user-owned files not removed by rsync"
|
|
277
277
|
else
|
|
278
278
|
_fail "claude-code re-install: user-owned files were removed"
|
|
279
279
|
fi
|
|
280
280
|
|
|
281
|
-
if [[ -f "$CODEX_USER/.codex/custom/my-custom-agent.toml" && -f "$CODEX_USER/.flow-agents/my-session/state.json" ]]; then
|
|
281
|
+
if [[ -f "$CODEX_USER/.codex/custom/my-custom-agent.toml" && -f "$CODEX_USER/.kontourai/flow-agents/my-session/state.json" ]]; then
|
|
282
282
|
_pass "codex re-install: user-owned files not removed by rsync"
|
|
283
283
|
else
|
|
284
284
|
_fail "codex re-install: user-owned files were removed"
|
|
285
285
|
fi
|
|
286
286
|
|
|
287
|
-
if [[ -f "$OPENCODE_USER/.opencode/custom/my-custom-agent.md" && -f "$OPENCODE_USER/.flow-agents/my-session/state.json" ]]; then
|
|
287
|
+
if [[ -f "$OPENCODE_USER/.opencode/custom/my-custom-agent.md" && -f "$OPENCODE_USER/.kontourai/flow-agents/my-session/state.json" ]]; then
|
|
288
288
|
_pass "opencode re-install: user-owned files not removed by rsync"
|
|
289
289
|
else
|
|
290
290
|
_fail "opencode re-install: user-owned files were removed"
|
|
@@ -528,7 +528,7 @@ fi
|
|
|
528
528
|
# and point CLAUDE_PROJECT_DIR there so the hook can resolve its scripts.
|
|
529
529
|
# This mirrors the real dogfood use case where the repo root has scripts/ from the bundle.
|
|
530
530
|
DOGFOOD_WORKSPACE="$CLAUDE_IDEM" # reuse the installed workspace from the idempotent section
|
|
531
|
-
mkdir -p "$DOGFOOD_WORKSPACE/.flow-agents"
|
|
531
|
+
mkdir -p "$DOGFOOD_WORKSPACE/.kontourai/flow-agents"
|
|
532
532
|
|
|
533
533
|
if node - "$DOGFOOD_DEST2/.claude/settings.json" "$DOGFOOD_WORKSPACE" << 'NODE'
|
|
534
534
|
const fs = require("node:fs");
|
|
@@ -537,7 +537,7 @@ const { spawnSync } = require("node:child_process");
|
|
|
537
537
|
const [settingsPath, workspace] = process.argv.slice(2);
|
|
538
538
|
|
|
539
539
|
// Write minimal fixtures for workflow-steering into the workspace
|
|
540
|
-
const taskDir = path.join(workspace, ".flow-agents", "dogfood-hook-demo");
|
|
540
|
+
const taskDir = path.join(workspace, ".kontourai", "flow-agents", "dogfood-hook-demo");
|
|
541
541
|
fs.mkdirSync(taskDir, { recursive: true });
|
|
542
542
|
const state = {
|
|
543
543
|
schema_version: "1.0",
|