@kontourai/flow-agents 1.4.0 → 2.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 +29 -0
- package/.github/actions/trust-verify/action.yml +145 -0
- package/.github/workflows/ci.yml +11 -4
- package/.github/workflows/kit-gates-demo.yml +2 -2
- package/.github/workflows/publish-npm.yml +10 -2
- package/.github/workflows/release-please.yml +1 -1
- package/.github/workflows/trust-reconcile.yml +113 -0
- package/AGENTS.md +13 -0
- package/CHANGELOG.md +95 -0
- package/CONTRIBUTING.md +4 -4
- package/README.md +1 -0
- package/agents/tool-planner.json +1 -1
- package/build/src/cli/init.js +242 -20
- package/build/src/cli/validate-workflow-artifacts.js +19 -2
- package/build/src/cli/verify.d.ts +1 -0
- package/build/src/cli/verify.js +90 -0
- package/build/src/cli/workflow-sidecar.d.ts +300 -8
- package/build/src/cli/workflow-sidecar.js +1934 -83
- package/build/src/cli.js +2 -3
- package/build/src/lib/flow-resolver.d.ts +82 -0
- package/build/src/lib/flow-resolver.js +237 -0
- package/build/src/tools/build-universal-bundles.js +34 -22
- package/build/src/tools/generate-context-map.js +3 -16
- package/build/src/tools/validate-source-tree.d.ts +1 -1
- package/build/src/tools/validate-source-tree.js +42 -162
- package/context/contracts/artifact-contract.md +10 -0
- package/context/contracts/delivery-contract.md +1 -0
- package/context/contracts/review-contract.md +1 -0
- package/context/contracts/verification-contract.md +2 -0
- package/context/gate-awareness.md +39 -0
- package/context/scripts/hooks/stop-goal-fit.js +632 -70
- package/docs/adr/0001-flow-agents-consumes-flow.md +1 -1
- package/docs/adr/0002-flow-kits-as-extension-unit.md +1 -1
- package/docs/adr/0004-gates-expect-surface-claims.md +2 -0
- package/docs/adr/0005-kubernetes-inspired-resource-contracts.md +2 -0
- package/docs/adr/0007-skill-audit.md +1 -1
- package/docs/adr/0009-canonical-hook-core-kit-boundary.md +95 -0
- package/docs/adr/0010-workflow-trust-state-as-hachure-bundle.md +139 -0
- package/docs/adr/0011-mcp-posture.md +100 -0
- package/docs/adr/0012-agent-coordination-as-liveness-claims.md +119 -0
- package/docs/adr/0013-context-lifecycle.md +151 -0
- package/docs/adr/0014-core-vs-domain-kit-boundary.md +143 -0
- package/docs/adr/0015-flow-flow-agents-boundary-reconciliation.md +120 -0
- package/docs/adr/0016-three-hard-boundary-model.md +71 -0
- package/docs/adr/0017-anti-gaming-trust-security-model.md +155 -0
- package/docs/agent-system-guidebook.md +5 -12
- package/docs/context-map.md +4 -10
- package/docs/index.md +3 -2
- package/docs/integrations/framework-adapter.md +19 -6
- package/docs/integrations/index.md +2 -2
- package/docs/north-star.md +4 -4
- package/docs/operating-layers.md +3 -3
- package/docs/plans/adr-0010-phase2-gate-recompute.md +55 -0
- package/docs/repository-structure.md +2 -2
- package/docs/skills-map.md +1 -0
- package/docs/spec/runtime-hook-surface.md +62 -9
- package/docs/standards-register.md +3 -3
- package/docs/survey-utterance-check.md +1 -1
- package/docs/trust-anchor-adoption.md +197 -0
- package/docs/verifiable-trust.md +95 -0
- package/docs/veritas-integration.md +2 -2
- package/docs/workflow-usage-guide.md +69 -0
- package/evals/acceptance/DEMO-false-completion.md +144 -0
- package/evals/acceptance/demo-cast.sh +92 -0
- package/evals/acceptance/demo-false-completion.sh +72 -0
- package/evals/acceptance/demo-real-evidence.sh +104 -0
- package/evals/acceptance/demo.tape +29 -0
- package/evals/acceptance/prove-capture-teeth-declared.sh +335 -0
- package/evals/acceptance/prove-capture-teeth.sh +114 -0
- package/evals/acceptance/prove-teeth.sh +105 -0
- package/evals/ci/antigaming-suite.sh +54 -0
- package/evals/ci/run-baseline.sh +2 -0
- package/evals/fixtures/flow-kit-repository/invalid-missing-extension-asset/flows/review.flow.json +26 -0
- package/evals/fixtures/flow-kit-repository/invalid-missing-extension-asset/kit.json +20 -0
- package/evals/fixtures/flow-kit-repository/valid-unknown-extension/flows/review.flow.json +26 -0
- package/evals/fixtures/flow-kit-repository/valid-unknown-extension/kit.json +18 -0
- package/evals/integration/test_builder_step_producers.sh +379 -0
- package/evals/integration/test_bundle_install.sh +35 -71
- package/evals/integration/test_bundle_lifecycle.sh +39 -2
- package/evals/integration/test_captured_fail_reconciliation.sh +820 -0
- package/evals/integration/test_checkpoint_signing.sh +489 -0
- package/evals/integration/test_claim_lookup.sh +352 -0
- package/evals/integration/test_command_log_integrity.sh +275 -0
- package/evals/integration/test_context_map.sh +0 -2
- package/evals/integration/test_dual_emit_flow_step.sh +278 -0
- package/evals/integration/test_enforcer_expects_driven.sh +281 -0
- package/evals/integration/test_evidence_capture_hook.sh +185 -0
- package/evals/integration/test_flow_kit_repository.sh +2 -0
- package/evals/integration/test_flowdef_session_activation.sh +273 -0
- package/evals/integration/test_flowdef_session_history_preservation.sh +250 -0
- package/evals/integration/test_gate_bypass_chain.sh +448 -0
- package/evals/integration/test_gate_lockdown.sh +1137 -0
- package/evals/integration/test_gate_review_inquiry_records.sh +399 -0
- package/evals/integration/test_goal_fit_escape_hatch.sh +73 -0
- package/evals/integration/test_goal_fit_hook.sh +69 -4
- package/evals/integration/test_goal_fit_rederive.sh +263 -0
- package/evals/integration/test_install_merge.sh +1176 -0
- package/evals/integration/test_mint_attestation.sh +373 -0
- package/evals/integration/test_phase_map_and_gate_claim.sh +365 -0
- package/evals/integration/test_publish_delivery.sh +269 -0
- package/evals/integration/test_reconcile_soundness.sh +528 -0
- package/evals/integration/test_resolvefirststep_security.sh +208 -0
- package/evals/integration/test_session_resume_roundtrip.sh +286 -0
- package/evals/integration/test_trust_checkpoint.sh +325 -0
- package/evals/integration/test_trust_reconcile.sh +293 -0
- package/evals/integration/test_verify_cli.sh +208 -0
- package/evals/integration/test_workflow_sidecar_writer.sh +549 -34
- package/evals/lib/node.sh +0 -6
- package/evals/run.sh +45 -0
- package/evals/static/test_workflow_skills.sh +6 -13
- package/install.sh +0 -7
- package/integrations/strands-ts/README.md +25 -15
- package/integrations/veritas/flow-agents.adapter.json +1 -2
- package/kits/builder/flows/build.flow.json +59 -12
- package/kits/builder/kit.json +85 -15
- package/kits/builder/skills/continue-work/SKILL.md +116 -0
- package/kits/builder/skills/deliver/SKILL.md +36 -6
- package/kits/builder/skills/design-probe/SKILL.md +28 -0
- package/kits/builder/skills/execute-plan/SKILL.md +9 -1
- package/kits/builder/skills/gate-review/SKILL.md +234 -0
- package/kits/builder/skills/learning-review/SKILL.md +30 -0
- package/kits/builder/skills/pickup-probe/SKILL.md +29 -0
- package/kits/builder/skills/plan-work/SKILL.md +13 -1
- package/kits/builder/skills/pull-work/SKILL.md +19 -0
- package/kits/knowledge/adapters/default-store/index.js +38 -0
- package/kits/knowledge/adapters/flow-runner/index.js +1620 -0
- package/kits/knowledge/adapters/obsidian-store/index.js +36 -6
- package/kits/knowledge/docs/store-contract.md +314 -0
- package/kits/knowledge/evals/audit-freshness/suite.test.js +368 -0
- package/kits/knowledge/evals/canonicalize-category/suite.test.js +383 -0
- package/kits/knowledge/evals/contract-suite/suite.test.js +111 -0
- package/kits/knowledge/evals/detect-contradictions/suite.test.js +324 -0
- package/kits/knowledge/evals/entities/suite.test.js +40 -0
- package/kits/knowledge/evals/glossary-sync/suite.test.js +416 -0
- package/kits/knowledge/evals/hygiene-review/suite.test.js +396 -0
- package/kits/knowledge/evals/retirement/suite.test.js +145 -0
- package/kits/knowledge/flows/audit-freshness.flow.json +44 -0
- package/kits/knowledge/flows/canonicalize-category.flow.json +44 -0
- package/kits/knowledge/flows/detect-contradictions.flow.json +44 -0
- package/kits/knowledge/flows/glossary-sync.flow.json +61 -0
- package/kits/knowledge/flows/hygiene-review.flow.json +43 -0
- package/kits/knowledge/kit.json +51 -1
- package/package.json +4 -4
- package/packaging/conformance/README.md +10 -2
- package/packaging/conformance/fixtures/evidence-capture--allow-records-command.json +29 -0
- package/packaging/conformance/fixtures/stop-goal-fit--block-bundle-disputed-claim.json +29 -0
- package/packaging/conformance/fixtures/stop-goal-fit--block-capture-contradicts-claimed-pass.json +30 -0
- package/packaging/conformance/fixtures/stop-goal-fit--block-mode.json +23 -0
- package/packaging/conformance/fixtures/stop-goal-fit--off-mode.json +24 -0
- package/packaging/conformance/fixtures/stop-goal-fit--warn-active-delivery.json +5 -2
- package/packaging/conformance/fixtures/stop-goal-fit--warn-no-bundle.json +23 -0
- package/packaging/conformance/fixtures/workflow-steering--reground-active-prompt.json +30 -0
- package/packaging/conformance/fixtures/workflow-steering--reground-session-start.json +30 -0
- package/packaging/conformance/run-conformance.js +1 -1
- package/scripts/README.md +2 -1
- package/scripts/build-universal-bundles.js +0 -1
- package/scripts/ci/mint-attestation.js +221 -0
- package/scripts/ci/trust-reconcile.js +545 -0
- package/scripts/hooks/config-protection.js +423 -1
- package/scripts/hooks/evidence-capture.js +348 -0
- package/scripts/hooks/lib/liveness-read.js +113 -0
- package/scripts/hooks/run-hook.js +6 -1
- package/scripts/hooks/stop-goal-fit.js +1471 -79
- package/scripts/hooks/workflow-steering.js +135 -5
- package/scripts/install-codex-home.sh +39 -0
- package/scripts/install-merge.js +330 -0
- package/src/cli/init.ts +218 -20
- package/src/cli/validate-workflow-artifacts.ts +18 -2
- package/src/cli/verify.ts +100 -0
- package/src/cli/workflow-sidecar.ts +2064 -77
- package/src/cli.ts +2 -3
- package/src/lib/flow-resolver.ts +284 -0
- package/src/tools/build-universal-bundles.ts +34 -21
- package/src/tools/generate-context-map.ts +3 -17
- package/src/tools/validate-source-tree.ts +44 -104
- package/build/src/tools/filter-installed-packs.d.ts +0 -2
- package/build/src/tools/filter-installed-packs.js +0 -135
- package/packaging/packs.json +0 -49
- package/scripts/filter-installed-packs.js +0 -2
- package/src/tools/filter-installed-packs.ts +0 -132
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# test_goal_fit_rederive.sh — Killer test for ADR 0010 Phase 2b re-derive-at-gate hardening.
|
|
3
|
+
#
|
|
4
|
+
# Proves that:
|
|
5
|
+
# 1. A TAMPERED trust.bundle (stored status "verified" but evidence re-derives to
|
|
6
|
+
# "disputed" because evidence[].passing === false) still BLOCKS (exit 2) and emits
|
|
7
|
+
# the "stored status does not match recompute (possible tampered bundle)" warning.
|
|
8
|
+
# 2. A LEGITIMATE bundle (stored "verified" AND evidence re-derives to "verified") is
|
|
9
|
+
# ALLOWED (no false-block).
|
|
10
|
+
# 3. The existing stored-status path still fires for a stored "disputed" claim (no
|
|
11
|
+
# regression from #133).
|
|
12
|
+
#
|
|
13
|
+
# Design: self-cleaning, deterministic (no model spend, no live commands).
|
|
14
|
+
# Usage: bash evals/integration/test_goal_fit_rederive.sh
|
|
15
|
+
|
|
16
|
+
set -uo pipefail
|
|
17
|
+
|
|
18
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
19
|
+
GATE="$ROOT/scripts/hooks/stop-goal-fit.js"
|
|
20
|
+
|
|
21
|
+
export FLOW_AGENTS_GOAL_FIT_MAX_BLOCKS=100000
|
|
22
|
+
|
|
23
|
+
TMP="$(mktemp -d)"
|
|
24
|
+
errors=0
|
|
25
|
+
_pass() { echo " ✓ $1"; }
|
|
26
|
+
_fail() { echo " ✗ $1"; errors=$((errors + 1)); }
|
|
27
|
+
|
|
28
|
+
cleanup() { rm -rf "$TMP"; }
|
|
29
|
+
trap cleanup EXIT
|
|
30
|
+
|
|
31
|
+
# ─── helper: seed a minimal delivered workflow artifact ───────────────────────
|
|
32
|
+
seed_repo() { # $1=dir $2=slug
|
|
33
|
+
local p="$1" slug="$2"
|
|
34
|
+
mkdir -p "$p/.flow-agents/$slug"
|
|
35
|
+
printf '# Repo\n' > "$p/AGENTS.md"
|
|
36
|
+
printf '%s' "{\"schema_version\":\"1.0\",\"task_slug\":\"$slug\",\"status\":\"delivered\",\"phase\":\"done\",\"updated_at\":\"2026-06-23T00:00:00Z\",\"next_action\":{\"status\":\"done\",\"summary\":\"done\"}}" \
|
|
37
|
+
> "$p/.flow-agents/$slug/state.json"
|
|
38
|
+
cat > "$p/.flow-agents/$slug/$slug--deliver.md" << MD
|
|
39
|
+
# $slug
|
|
40
|
+
|
|
41
|
+
branch: main
|
|
42
|
+
status: delivered
|
|
43
|
+
type: deliver
|
|
44
|
+
|
|
45
|
+
## Definition Of Done
|
|
46
|
+
- [x] tests pass
|
|
47
|
+
|
|
48
|
+
## Goal Fit Gate
|
|
49
|
+
- [x] acceptance verified
|
|
50
|
+
|
|
51
|
+
### Verdict: PASS
|
|
52
|
+
MD
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# ─── Test 1: TAMPERED bundle — stored "verified" but evidence re-derives to disputed ─
|
|
56
|
+
# A trust.bundle where the agent wrote claim.status="verified" to bypass the gate,
|
|
57
|
+
# but the evidence array has passing:false (a failing command result folded in by
|
|
58
|
+
# buildTrustBundle). Surface's deriveClaimStatus must re-derive "disputed" from
|
|
59
|
+
# that evidence, and the gate must block with a tamper warning.
|
|
60
|
+
echo "Test 1: tampered bundle (stored verified, evidence→disputed) must BLOCK"
|
|
61
|
+
|
|
62
|
+
TAMPER_DIR="$TMP/tamper"
|
|
63
|
+
seed_repo "$TAMPER_DIR" "tampered"
|
|
64
|
+
|
|
65
|
+
# Build a trust.bundle:
|
|
66
|
+
# - claim.status = "verified" (stored, tampered to look safe)
|
|
67
|
+
# - evidence[passing=false] (real command failed, fold in by sidecar)
|
|
68
|
+
# Surface.deriveClaimStatus will see passing:false evidence and return "disputed".
|
|
69
|
+
python3 - "$TAMPER_DIR/.flow-agents/tampered/trust.bundle" << 'PY'
|
|
70
|
+
import json, sys
|
|
71
|
+
bundle = {
|
|
72
|
+
"schemaVersion": 3,
|
|
73
|
+
"source": "flow-agents/workflow-sidecar",
|
|
74
|
+
"claims": [{
|
|
75
|
+
"id": "c1",
|
|
76
|
+
"subjectId": "tampered/unit-tests",
|
|
77
|
+
"subjectType": "workflow-check",
|
|
78
|
+
"claimType": "workflow.check.command",
|
|
79
|
+
"fieldOrBehavior": "unit tests",
|
|
80
|
+
"value": "pass",
|
|
81
|
+
"impactLevel": "high",
|
|
82
|
+
"status": "verified", # tampered: agent edited this from "disputed" → "verified"
|
|
83
|
+
"createdAt": "2026-06-23T00:00:00Z",
|
|
84
|
+
"updatedAt": "2026-06-23T00:00:00Z"
|
|
85
|
+
}],
|
|
86
|
+
"evidence": [{
|
|
87
|
+
"id": "ev1",
|
|
88
|
+
"claimId": "c1",
|
|
89
|
+
"evidenceType": "test_output",
|
|
90
|
+
"method": "validation",
|
|
91
|
+
"sourceRef": "command-log.jsonl",
|
|
92
|
+
"excerptOrSummary": "npm test failed with exit 1",
|
|
93
|
+
"observedAt": "2026-06-23T00:00:00Z",
|
|
94
|
+
"collectedBy": "harness",
|
|
95
|
+
"passing": False, # the actual command FAILED — surface sees this
|
|
96
|
+
"blocking": True
|
|
97
|
+
}],
|
|
98
|
+
"policies": [],
|
|
99
|
+
"events": [{
|
|
100
|
+
"id": "evt1",
|
|
101
|
+
"claimId": "c1",
|
|
102
|
+
"status": "verified", # the event says verified (tampered)
|
|
103
|
+
"actor": "agent",
|
|
104
|
+
"method": "workflow-check",
|
|
105
|
+
"evidenceIds": ["ev1"],
|
|
106
|
+
"createdAt": "2026-06-23T00:00:00Z"
|
|
107
|
+
}]
|
|
108
|
+
}
|
|
109
|
+
json.dump(bundle, open(sys.argv[1], 'w'))
|
|
110
|
+
PY
|
|
111
|
+
|
|
112
|
+
# Run the gate in block mode.
|
|
113
|
+
set +e
|
|
114
|
+
result_out="$(FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_BACKSTOP=skip \
|
|
115
|
+
node "$GATE" 2>&1 <<< "{\"hook_event_name\":\"Stop\",\"cwd\":\"$TAMPER_DIR\"}")"
|
|
116
|
+
result_exit="$?"
|
|
117
|
+
set -e
|
|
118
|
+
|
|
119
|
+
if [ "$result_exit" -eq 2 ]; then
|
|
120
|
+
_pass "tampered bundle blocks (exit 2)"
|
|
121
|
+
else
|
|
122
|
+
_fail "tampered bundle did NOT block: exit=$result_exit output=$result_out"
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
if echo "$result_out" | grep -qE "stored status.*does not match recompute|possible tampered bundle"; then
|
|
126
|
+
_pass "tampered bundle emits tamper warning"
|
|
127
|
+
else
|
|
128
|
+
_fail "tampered bundle missing tamper warning: $result_out"
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
if echo "$result_out" | grep -q "caught false-completion"; then
|
|
132
|
+
_pass "tampered bundle emits caught false-completion"
|
|
133
|
+
else
|
|
134
|
+
_fail "tampered bundle missing caught false-completion: $result_out"
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# ─── Test 2: LEGITIMATE bundle — stored "verified" AND evidence re-derives to "verified" ─
|
|
138
|
+
# A bundle where both the stored status and the re-derived status agree on "verified"
|
|
139
|
+
# (a passing:true evidence + a "verified" event). Must ALLOW (exit 0 in warn mode).
|
|
140
|
+
echo ""
|
|
141
|
+
echo "Test 2: legitimate bundle (stored verified, evidence→verified) must ALLOW"
|
|
142
|
+
|
|
143
|
+
LEGIT_DIR="$TMP/legit"
|
|
144
|
+
seed_repo "$LEGIT_DIR" "legit"
|
|
145
|
+
|
|
146
|
+
python3 - "$LEGIT_DIR/.flow-agents/legit/trust.bundle" << 'PY'
|
|
147
|
+
import json, sys
|
|
148
|
+
bundle = {
|
|
149
|
+
"schemaVersion": 3,
|
|
150
|
+
"source": "flow-agents/workflow-sidecar",
|
|
151
|
+
"claims": [{
|
|
152
|
+
"id": "c2",
|
|
153
|
+
"subjectId": "legit/unit-tests",
|
|
154
|
+
"subjectType": "workflow-check",
|
|
155
|
+
"claimType": "workflow.check.command",
|
|
156
|
+
"fieldOrBehavior": "unit tests",
|
|
157
|
+
"value": "pass",
|
|
158
|
+
"impactLevel": "high",
|
|
159
|
+
"status": "verified",
|
|
160
|
+
"createdAt": "2026-06-23T00:00:00Z",
|
|
161
|
+
"updatedAt": "2026-06-23T00:00:00Z"
|
|
162
|
+
}],
|
|
163
|
+
"evidence": [{
|
|
164
|
+
"id": "ev2",
|
|
165
|
+
"claimId": "c2",
|
|
166
|
+
"evidenceType": "test_output",
|
|
167
|
+
"method": "validation",
|
|
168
|
+
"sourceRef": "command-log.jsonl",
|
|
169
|
+
"excerptOrSummary": "npm test passed",
|
|
170
|
+
"observedAt": "2026-06-23T00:00:00Z",
|
|
171
|
+
"collectedBy": "harness",
|
|
172
|
+
"passing": True, # command genuinely passed
|
|
173
|
+
"blocking": False
|
|
174
|
+
}],
|
|
175
|
+
"policies": [],
|
|
176
|
+
"events": [{
|
|
177
|
+
"id": "evt2",
|
|
178
|
+
"claimId": "c2",
|
|
179
|
+
"status": "verified",
|
|
180
|
+
"actor": "agent",
|
|
181
|
+
"method": "workflow-check",
|
|
182
|
+
"evidenceIds": ["ev2"],
|
|
183
|
+
"createdAt": "2026-06-23T00:00:00Z"
|
|
184
|
+
}]
|
|
185
|
+
}
|
|
186
|
+
json.dump(bundle, open(sys.argv[1], 'w'))
|
|
187
|
+
PY
|
|
188
|
+
|
|
189
|
+
set +e
|
|
190
|
+
legit_out="$(FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_BACKSTOP=skip \
|
|
191
|
+
node "$GATE" 2>&1 <<< "{\"hook_event_name\":\"Stop\",\"cwd\":\"$LEGIT_DIR\"}")"
|
|
192
|
+
legit_exit="$?"
|
|
193
|
+
set -e
|
|
194
|
+
|
|
195
|
+
if [ "$legit_exit" -ne 2 ]; then
|
|
196
|
+
_pass "legitimate bundle not blocked (exit $legit_exit)"
|
|
197
|
+
else
|
|
198
|
+
_fail "legitimate bundle false-blocked (exit 2): $legit_out"
|
|
199
|
+
fi
|
|
200
|
+
|
|
201
|
+
if echo "$legit_out" | grep -q "caught false-completion"; then
|
|
202
|
+
_fail "legitimate bundle incorrectly emits false-completion: $legit_out"
|
|
203
|
+
else
|
|
204
|
+
_pass "legitimate bundle does not emit false-completion"
|
|
205
|
+
fi
|
|
206
|
+
|
|
207
|
+
# ─── Test 3: existing stored-disputed path still fires (no regression from #133) ──
|
|
208
|
+
echo ""
|
|
209
|
+
echo "Test 3: stored-disputed bundle must still BLOCK (no regression from #133)"
|
|
210
|
+
|
|
211
|
+
STORED_DIR="$TMP/stored"
|
|
212
|
+
seed_repo "$STORED_DIR" "stored"
|
|
213
|
+
|
|
214
|
+
python3 - "$STORED_DIR/.flow-agents/stored/trust.bundle" << 'PY'
|
|
215
|
+
import json, sys
|
|
216
|
+
bundle = {
|
|
217
|
+
"schemaVersion": 3,
|
|
218
|
+
"source": "flow-agents/workflow-sidecar",
|
|
219
|
+
"claims": [{
|
|
220
|
+
"id": "c3",
|
|
221
|
+
"subjectId": "stored/unit-tests",
|
|
222
|
+
"subjectType": "workflow-check",
|
|
223
|
+
"claimType": "workflow.check.command",
|
|
224
|
+
"fieldOrBehavior": "unit tests",
|
|
225
|
+
"value": "fail",
|
|
226
|
+
"impactLevel": "high",
|
|
227
|
+
"status": "disputed", # stored as disputed (not tampered — correctly flagged)
|
|
228
|
+
"createdAt": "2026-06-23T00:00:00Z",
|
|
229
|
+
"updatedAt": "2026-06-23T00:00:00Z"
|
|
230
|
+
}],
|
|
231
|
+
"evidence": [],
|
|
232
|
+
"policies": [],
|
|
233
|
+
"events": []
|
|
234
|
+
}
|
|
235
|
+
json.dump(bundle, open(sys.argv[1], 'w'))
|
|
236
|
+
PY
|
|
237
|
+
|
|
238
|
+
set +e
|
|
239
|
+
stored_out="$(FLOW_AGENTS_GOAL_FIT_MODE=block FLOW_AGENTS_GOAL_FIT_BACKSTOP=skip \
|
|
240
|
+
node "$GATE" 2>&1 <<< "{\"hook_event_name\":\"Stop\",\"cwd\":\"$STORED_DIR\"}")"
|
|
241
|
+
stored_exit="$?"
|
|
242
|
+
set -e
|
|
243
|
+
|
|
244
|
+
if [ "$stored_exit" -eq 2 ]; then
|
|
245
|
+
_pass "stored-disputed bundle blocks (exit 2)"
|
|
246
|
+
else
|
|
247
|
+
_fail "stored-disputed bundle did NOT block (exit $stored_exit): $stored_out"
|
|
248
|
+
fi
|
|
249
|
+
|
|
250
|
+
if echo "$stored_out" | grep -q "caught false-completion"; then
|
|
251
|
+
_pass "stored-disputed bundle emits caught false-completion"
|
|
252
|
+
else
|
|
253
|
+
_fail "stored-disputed bundle missing caught false-completion: $stored_out"
|
|
254
|
+
fi
|
|
255
|
+
|
|
256
|
+
# ─── Summary ─────────────────────────────────────────────────────────────────
|
|
257
|
+
echo ""
|
|
258
|
+
if [ "$errors" -eq 0 ]; then
|
|
259
|
+
echo "Re-derive-at-gate hardening tests passed."
|
|
260
|
+
exit 0
|
|
261
|
+
fi
|
|
262
|
+
echo "Re-derive-at-gate hardening tests FAILED: $errors issue(s)."
|
|
263
|
+
exit 1
|