@kontourai/flow-agents 1.4.0 → 2.0.1
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/runtime-compat.yml +1 -1
- package/.github/workflows/trust-reconcile.yml +113 -0
- package/AGENTS.md +13 -0
- package/CHANGELOG.md +103 -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 +316 -8
- package/build/src/cli/workflow-sidecar.js +1996 -91
- package/build/src/cli.js +2 -3
- package/build/src/lib/flow-resolver.d.ts +111 -0
- package/build/src/lib/flow-resolver.js +308 -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 +55 -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_fork_classification.sh +134 -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_kit_identity_trust.sh +393 -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 +47 -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 +6 -6
- 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 +1524 -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/scripts/repair-command-log.js +115 -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 +2127 -84
- package/src/cli.ts +2 -3
- package/src/lib/flow-resolver.ts +369 -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,393 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# test_kit_identity_trust.sh — Regression eval for kit identity end-to-end in the trust chain.
|
|
3
|
+
#
|
|
4
|
+
# Proves Fix 1 and Fix 2 from the kit-identity task:
|
|
5
|
+
#
|
|
6
|
+
# Fix 1 (surfaceCheckFromArtifact reads kit from bundle, never hardcodes "builder"):
|
|
7
|
+
# 1a. KNOWLEDGE-TYPED bundle → kitIdentityFromBundle derives kitId="knowledge", subject="knowledge-kit"
|
|
8
|
+
# 1b. BUILDER-TYPED bundle → kitIdentityFromBundle derives kitId="builder", subject="builder-kit"
|
|
9
|
+
# 1c. WORKFLOW-ONLY bundle (no kit-typed claim, no current.json) → kitId="unknown", subject="unknown-kit"
|
|
10
|
+
# 1d. record-evidence --surface-trust-json <knowledge-fixture> completes without crash
|
|
11
|
+
#
|
|
12
|
+
# Fix 2 (route-back guard is FlowDefinition-driven, not hardcoded to builder.build):
|
|
13
|
+
# 2a. builder.build: verification→execution still enforced (identical behavior preserved)
|
|
14
|
+
# 2b. Custom non-builder flow WITH route_back_policy: verification→execution ENFORCED
|
|
15
|
+
# 2c. Custom flow WITHOUT route_back_policy: verification→execution NOT ENFORCED
|
|
16
|
+
#
|
|
17
|
+
# Deterministic, no model spend, self-cleaning.
|
|
18
|
+
# Usage: bash evals/integration/test_kit_identity_trust.sh
|
|
19
|
+
|
|
20
|
+
set -uo pipefail
|
|
21
|
+
|
|
22
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
23
|
+
source "$ROOT/evals/lib/node.sh"
|
|
24
|
+
|
|
25
|
+
TMP="$(mktemp -d)"
|
|
26
|
+
errors=0
|
|
27
|
+
|
|
28
|
+
_pass() { echo " ✓ $1"; }
|
|
29
|
+
_fail() { echo " ✗ $1"; errors=$((errors + 1)); }
|
|
30
|
+
|
|
31
|
+
cleanup() { rm -rf "$TMP"; }
|
|
32
|
+
trap cleanup EXIT
|
|
33
|
+
|
|
34
|
+
SIDECAR_JS="${ROOT}/build/src/cli/workflow-sidecar.js"
|
|
35
|
+
SIDECAR_BUNDLE_WRITER="workflow-sidecar"
|
|
36
|
+
|
|
37
|
+
echo ""
|
|
38
|
+
echo "=== Fix 1: kitIdentityFromBundle reads kit from bundle claims (not hardcoded 'builder') ==="
|
|
39
|
+
|
|
40
|
+
# ─── Write fixture bundle files (note: argv[2] = file path since argv[1] = "-" for stdin) ─────────
|
|
41
|
+
|
|
42
|
+
node - "$TMP/knowledge.bundle" << 'NODE'
|
|
43
|
+
const fs = require('fs');
|
|
44
|
+
// argv[0]=node, argv[1]="-", argv[2]=file path
|
|
45
|
+
const bundlePath = process.argv[2];
|
|
46
|
+
const bundle = {
|
|
47
|
+
schemaVersion: 3, source: "test-fixture",
|
|
48
|
+
claims: [{
|
|
49
|
+
id: "c-knowledge-1", claimType: "knowledge.verify.tests",
|
|
50
|
+
subjectType: "flow-step", subjectId: "test-slug/knowledge-ev",
|
|
51
|
+
surface: "flow-agents.workflow", fieldOrBehavior: "knowledge verification",
|
|
52
|
+
value: "pass", status: "verified",
|
|
53
|
+
createdAt: "2026-06-27T00:00:00Z", updatedAt: "2026-06-27T00:00:00Z",
|
|
54
|
+
impactLevel: "high", verificationPolicyId: "policy:knowledge.verify.tests"
|
|
55
|
+
}],
|
|
56
|
+
evidence: [], policies: [], events: []
|
|
57
|
+
};
|
|
58
|
+
fs.writeFileSync(bundlePath, JSON.stringify(bundle, null, 2));
|
|
59
|
+
NODE
|
|
60
|
+
|
|
61
|
+
node - "$TMP/builder.bundle" << 'NODE'
|
|
62
|
+
const fs = require('fs');
|
|
63
|
+
const bundlePath = process.argv[2];
|
|
64
|
+
const bundle = {
|
|
65
|
+
schemaVersion: 3, source: "test-fixture",
|
|
66
|
+
claims: [{
|
|
67
|
+
id: "c-builder-1", claimType: "builder.verify.tests",
|
|
68
|
+
subjectType: "flow-step", subjectId: "test-slug/builder-ev",
|
|
69
|
+
surface: "flow-agents.workflow", fieldOrBehavior: "builder verification",
|
|
70
|
+
value: "pass", status: "verified",
|
|
71
|
+
createdAt: "2026-06-27T00:00:00Z", updatedAt: "2026-06-27T00:00:00Z",
|
|
72
|
+
impactLevel: "high", verificationPolicyId: "policy:builder.verify.tests"
|
|
73
|
+
}],
|
|
74
|
+
evidence: [], policies: [], events: []
|
|
75
|
+
};
|
|
76
|
+
fs.writeFileSync(bundlePath, JSON.stringify(bundle, null, 2));
|
|
77
|
+
NODE
|
|
78
|
+
|
|
79
|
+
node - "$TMP/workflow-only.bundle" << 'NODE'
|
|
80
|
+
const fs = require('fs');
|
|
81
|
+
const bundlePath = process.argv[2];
|
|
82
|
+
const bundle = {
|
|
83
|
+
schemaVersion: 3, source: "test-fixture",
|
|
84
|
+
claims: [{
|
|
85
|
+
id: "c-wf-1", claimType: "workflow.check.build",
|
|
86
|
+
subjectType: "workflow-check", subjectId: "test-slug/build",
|
|
87
|
+
surface: "flow-agents.workflow", fieldOrBehavior: "build check",
|
|
88
|
+
value: "pass", status: "verified",
|
|
89
|
+
createdAt: "2026-06-27T00:00:00Z", updatedAt: "2026-06-27T00:00:00Z",
|
|
90
|
+
impactLevel: "high", verificationPolicyId: "policy:workflow.check.build"
|
|
91
|
+
}],
|
|
92
|
+
evidence: [], policies: [], events: []
|
|
93
|
+
};
|
|
94
|
+
fs.writeFileSync(bundlePath, JSON.stringify(bundle, null, 2));
|
|
95
|
+
NODE
|
|
96
|
+
|
|
97
|
+
echo ""
|
|
98
|
+
echo "=== 1a. KNOWLEDGE-TYPED bundle → kitIdentityFromBundle derives knowledge kit ==="
|
|
99
|
+
KNOWLEDGE_BUNDLE="$TMP/knowledge.bundle"
|
|
100
|
+
SIDECAR_JS_PATH="$SIDECAR_JS"
|
|
101
|
+
node --input-type=module << JSEOF
|
|
102
|
+
import { kitIdentityFromBundle } from '${SIDECAR_JS_PATH}';
|
|
103
|
+
import { readFileSync } from 'node:fs';
|
|
104
|
+
const raw = JSON.parse(readFileSync('${KNOWLEDGE_BUNDLE}', 'utf8'));
|
|
105
|
+
const result = kitIdentityFromBundle(raw, '${KNOWLEDGE_BUNDLE}');
|
|
106
|
+
if (result.kitId !== 'knowledge') throw new Error('Expected kitId=knowledge, got: ' + result.kitId);
|
|
107
|
+
if (result.subject !== 'knowledge-kit') throw new Error('Expected subject=knowledge-kit, got: ' + result.subject);
|
|
108
|
+
if (!result.claimType.startsWith('knowledge.')) throw new Error('Expected claimType to start with knowledge., got: ' + result.claimType);
|
|
109
|
+
if (result.claimType === 'knowledge.trust.bundle') throw new Error('Should use the specific claim type, not the generic fallback, got: ' + result.claimType);
|
|
110
|
+
JSEOF
|
|
111
|
+
if [ $? -eq 0 ]; then
|
|
112
|
+
_pass "KNOWLEDGE bundle: kitId=knowledge, subject=knowledge-kit, claimType=knowledge.verify.tests (not builder)"
|
|
113
|
+
else
|
|
114
|
+
_fail "KNOWLEDGE bundle: expected kitId=knowledge and subject=knowledge-kit, not builder hardcode"
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
echo ""
|
|
118
|
+
echo "=== 1b. BUILDER-TYPED bundle → kitIdentityFromBundle derives builder kit ==="
|
|
119
|
+
BUILDER_BUNDLE="$TMP/builder.bundle"
|
|
120
|
+
node --input-type=module << JSEOF
|
|
121
|
+
import { kitIdentityFromBundle } from '${SIDECAR_JS_PATH}';
|
|
122
|
+
import { readFileSync } from 'node:fs';
|
|
123
|
+
const raw = JSON.parse(readFileSync('${BUILDER_BUNDLE}', 'utf8'));
|
|
124
|
+
const result = kitIdentityFromBundle(raw, '${BUILDER_BUNDLE}');
|
|
125
|
+
if (result.kitId !== 'builder') throw new Error('Expected kitId=builder, got: ' + result.kitId);
|
|
126
|
+
if (result.subject !== 'builder-kit') throw new Error('Expected subject=builder-kit, got: ' + result.subject);
|
|
127
|
+
if (!result.claimType.startsWith('builder.')) throw new Error('Expected claimType to start with builder., got: ' + result.claimType);
|
|
128
|
+
JSEOF
|
|
129
|
+
if [ $? -eq 0 ]; then
|
|
130
|
+
_pass "BUILDER bundle: kitId=builder, subject=builder-kit (correctly derived from claims, not hardcoded)"
|
|
131
|
+
else
|
|
132
|
+
_fail "BUILDER bundle: expected kitId=builder and subject=builder-kit"
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
echo ""
|
|
136
|
+
echo "=== 1c. WORKFLOW-ONLY bundle (no kit-typed claim, no current.json) → unknown identity ==="
|
|
137
|
+
ISOLATED_DIR="$TMP/isolated-session"
|
|
138
|
+
mkdir -p "$ISOLATED_DIR"
|
|
139
|
+
cp "$TMP/workflow-only.bundle" "$ISOLATED_DIR/workflow-only.bundle"
|
|
140
|
+
WORKFLOW_BUNDLE="$ISOLATED_DIR/workflow-only.bundle"
|
|
141
|
+
node --input-type=module << JSEOF
|
|
142
|
+
import { kitIdentityFromBundle } from '${SIDECAR_JS_PATH}';
|
|
143
|
+
import { readFileSync } from 'node:fs';
|
|
144
|
+
const raw = JSON.parse(readFileSync('${WORKFLOW_BUNDLE}', 'utf8'));
|
|
145
|
+
const result = kitIdentityFromBundle(raw, '${WORKFLOW_BUNDLE}');
|
|
146
|
+
if (result.kitId !== 'unknown') throw new Error('Expected kitId=unknown (no kit-typed claim, no active flow), got: ' + result.kitId);
|
|
147
|
+
if (result.subject !== 'unknown-kit') throw new Error('Expected subject=unknown-kit, got: ' + result.subject);
|
|
148
|
+
if (result.claimType !== 'unknown.trust.bundle') throw new Error('Expected claimType=unknown.trust.bundle, got: ' + result.claimType);
|
|
149
|
+
JSEOF
|
|
150
|
+
if [ $? -eq 0 ]; then
|
|
151
|
+
_pass "WORKFLOW-ONLY bundle: kitId=unknown, subject=unknown-kit (never falls back to builder)"
|
|
152
|
+
else
|
|
153
|
+
_fail "WORKFLOW-ONLY bundle: expected kitId=unknown (no hardcoded builder fallback)"
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
echo ""
|
|
157
|
+
echo "=== 1d. Full pipeline: record-evidence --surface-trust-json with knowledge fixture ==="
|
|
158
|
+
PIPELINE_AROOT="$TMP/pipeline-test/.flow-agents"
|
|
159
|
+
PIPELINE_SLUG="pipeline-kit-identity"
|
|
160
|
+
PIPELINE_DIR="$PIPELINE_AROOT/$PIPELINE_SLUG"
|
|
161
|
+
mkdir -p "$PIPELINE_AROOT"
|
|
162
|
+
|
|
163
|
+
flow_agents_node "$SIDECAR_BUNDLE_WRITER" ensure-session \
|
|
164
|
+
--artifact-root "$PIPELINE_AROOT" \
|
|
165
|
+
--task-slug "$PIPELINE_SLUG" \
|
|
166
|
+
--title "Pipeline kit identity test" \
|
|
167
|
+
--summary "Proves record-evidence processes knowledge bundle without crashing." \
|
|
168
|
+
--criterion "Kit identity preserved" \
|
|
169
|
+
--timestamp "2026-06-27T10:00:00Z" > "$TMP/pipeline-ensure.out" 2>&1
|
|
170
|
+
|
|
171
|
+
KNOWLEDGE_BUNDLE_PATH="$TMP/knowledge.bundle"
|
|
172
|
+
if flow_agents_node "$SIDECAR_BUNDLE_WRITER" record-evidence "$PIPELINE_DIR" \
|
|
173
|
+
--verdict not_verified \
|
|
174
|
+
--surface-trust-json "$KNOWLEDGE_BUNDLE_PATH" \
|
|
175
|
+
--timestamp "2026-06-27T10:01:00Z" > "$TMP/pipeline-evidence.out" 2>&1; then
|
|
176
|
+
if [[ -f "$PIPELINE_DIR/trust.bundle" ]]; then
|
|
177
|
+
_pass "record-evidence --surface-trust-json with knowledge bundle completes (pipeline proof: fix is in production code path)"
|
|
178
|
+
else
|
|
179
|
+
_fail "record-evidence --surface-trust-json with knowledge bundle did not write trust.bundle"
|
|
180
|
+
fi
|
|
181
|
+
else
|
|
182
|
+
_fail "record-evidence --surface-trust-json with knowledge bundle failed: $(cat "$TMP/pipeline-evidence.out")"
|
|
183
|
+
fi
|
|
184
|
+
|
|
185
|
+
echo ""
|
|
186
|
+
echo "=== Fix 2: FlowDefinition-driven route-back guard ==="
|
|
187
|
+
|
|
188
|
+
# ─── 2a. builder.build: verification→execution still enforced ─────────────────
|
|
189
|
+
echo ""
|
|
190
|
+
echo "=== 2a. builder.build route-back guard: still enforces verification→execution ==="
|
|
191
|
+
BUILDER_DIR="$TMP/fix2-builder/.flow-agents/builder-fix2"
|
|
192
|
+
mkdir -p "$TMP/fix2-builder/.flow-agents"
|
|
193
|
+
|
|
194
|
+
flow_agents_node "$SIDECAR_BUNDLE_WRITER" ensure-session \
|
|
195
|
+
--artifact-root "$TMP/fix2-builder/.flow-agents" \
|
|
196
|
+
--task-slug "builder-fix2" \
|
|
197
|
+
--title "Fix2 builder route-back test" \
|
|
198
|
+
--summary "Verify builder.build route-back still enforced." \
|
|
199
|
+
--timestamp "2026-06-27T10:00:00Z" > "$TMP/fix2-builder-ensure.out" 2>&1
|
|
200
|
+
|
|
201
|
+
flow_agents_node "$SIDECAR_BUNDLE_WRITER" advance-state "$BUILDER_DIR" \
|
|
202
|
+
--status verifying --phase verification \
|
|
203
|
+
--summary "Moving to verification." \
|
|
204
|
+
--flow-definition builder.build \
|
|
205
|
+
--timestamp "2026-06-27T10:01:00Z" > "$TMP/fix2-builder-verify.out" 2>&1
|
|
206
|
+
|
|
207
|
+
if flow_agents_node "$SIDECAR_BUNDLE_WRITER" advance-state "$BUILDER_DIR" \
|
|
208
|
+
--status in_progress --phase execution \
|
|
209
|
+
--summary "Route back without reason." \
|
|
210
|
+
--flow-definition builder.build \
|
|
211
|
+
--timestamp "2026-06-27T10:02:00Z" > "$TMP/fix2-builder-noReason.out" 2>&1; then
|
|
212
|
+
_fail "builder.build route-back should require --route-back-reason"
|
|
213
|
+
elif grep -q 'route_back_reason_required' "$TMP/fix2-builder-noReason.out"; then
|
|
214
|
+
_pass "builder.build: verification→execution requires --route-back-reason (identical behavior preserved)"
|
|
215
|
+
else
|
|
216
|
+
_fail "builder.build route-back lacked expected diagnostic (got: $(cat "$TMP/fix2-builder-noReason.out"))"
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
if flow_agents_node "$SIDECAR_BUNDLE_WRITER" advance-state "$BUILDER_DIR" \
|
|
220
|
+
--status in_progress --phase execution \
|
|
221
|
+
--summary "Route back with reason." \
|
|
222
|
+
--flow-definition builder.build \
|
|
223
|
+
--route-back-reason implementation_defect \
|
|
224
|
+
--timestamp "2026-06-27T10:03:00Z" > "$TMP/fix2-builder-withReason.out" 2>&1; then
|
|
225
|
+
_pass "builder.build: verification→execution with reason succeeds (identical behavior preserved)"
|
|
226
|
+
else
|
|
227
|
+
_fail "builder.build route-back with reason should succeed (got: $(cat "$TMP/fix2-builder-withReason.out"))"
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
# ─── 2b. Custom non-builder flow WITH route_back_policy: enforced ─────────────
|
|
231
|
+
echo ""
|
|
232
|
+
echo "=== 2b. Custom non-builder flow WITH route_back_policy: enforced ==="
|
|
233
|
+
|
|
234
|
+
CUSTOM_FLOWS_DIR="$TMP/custom-flows"
|
|
235
|
+
mkdir -p "$CUSTOM_FLOWS_DIR"
|
|
236
|
+
|
|
237
|
+
# Write acme.deliver flow with route_back_policy (using argv[2] correctly)
|
|
238
|
+
node - "$CUSTOM_FLOWS_DIR/acme.deliver.flow.json" << 'NODE'
|
|
239
|
+
const fs = require('fs');
|
|
240
|
+
const flowPath = process.argv[2];
|
|
241
|
+
const flow = {
|
|
242
|
+
id: "acme.deliver", version: "1.0",
|
|
243
|
+
phase_map: { execution: "execute", verification: "verify" },
|
|
244
|
+
steps: [{ id: "execute", next: "verify" }, { id: "verify", next: "done" }, { id: "done", next: null }],
|
|
245
|
+
gates: {
|
|
246
|
+
"execute-gate": {
|
|
247
|
+
step: "execute",
|
|
248
|
+
expects: [{ id: "execution-scope", kind: "trust.bundle", required: true,
|
|
249
|
+
bundle_claim: { claimType: "acme.execute.scope", subjectType: "change", accepted_statuses: ["trusted","accepted"] } }]
|
|
250
|
+
},
|
|
251
|
+
"verify-gate": {
|
|
252
|
+
step: "verify",
|
|
253
|
+
on_route_back: { implementation_defect: "execute", missing_evidence: "verify", default: "verify" },
|
|
254
|
+
route_back_policy: { max_attempts: 2, on_exceeded: "block" },
|
|
255
|
+
expects: [{ id: "verify-evidence", kind: "trust.bundle", required: true,
|
|
256
|
+
bundle_claim: { claimType: "acme.verify.tests", subjectType: "flow-step", accepted_statuses: ["trusted","accepted"] } }]
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
fs.writeFileSync(flowPath, JSON.stringify(flow, null, 2));
|
|
261
|
+
NODE
|
|
262
|
+
|
|
263
|
+
ACME_DIR="$TMP/fix2-acme/.flow-agents/acme-fix2"
|
|
264
|
+
mkdir -p "$TMP/fix2-acme/.flow-agents"
|
|
265
|
+
|
|
266
|
+
flow_agents_node "$SIDECAR_BUNDLE_WRITER" ensure-session \
|
|
267
|
+
--artifact-root "$TMP/fix2-acme/.flow-agents" \
|
|
268
|
+
--task-slug "acme-fix2" \
|
|
269
|
+
--title "Fix2 acme route-back test" \
|
|
270
|
+
--summary "Verify non-builder flow with route_back_policy is enforced." \
|
|
271
|
+
--timestamp "2026-06-27T10:00:00Z" > "$TMP/fix2-acme-ensure.out" 2>&1
|
|
272
|
+
|
|
273
|
+
# Set FLOW_AGENTS_FLOW_DEFS_DIR and export it for the duration of this block
|
|
274
|
+
export FLOW_AGENTS_FLOW_DEFS_DIR="$CUSTOM_FLOWS_DIR"
|
|
275
|
+
|
|
276
|
+
flow_agents_node "$SIDECAR_BUNDLE_WRITER" advance-state "$ACME_DIR" \
|
|
277
|
+
--status verifying --phase verification \
|
|
278
|
+
--summary "Moving acme to verification." \
|
|
279
|
+
--flow-definition acme.deliver \
|
|
280
|
+
--timestamp "2026-06-27T10:01:00Z" > "$TMP/fix2-acme-verify.out" 2>&1
|
|
281
|
+
|
|
282
|
+
if flow_agents_node "$SIDECAR_BUNDLE_WRITER" advance-state "$ACME_DIR" \
|
|
283
|
+
--status in_progress --phase execution \
|
|
284
|
+
--summary "Acme route back without reason." \
|
|
285
|
+
--flow-definition acme.deliver \
|
|
286
|
+
--timestamp "2026-06-27T10:02:00Z" > "$TMP/fix2-acme-noReason.out" 2>&1; then
|
|
287
|
+
_fail "acme.deliver route-back should require --route-back-reason when route_back_policy is declared"
|
|
288
|
+
elif grep -q 'route_back_reason_required' "$TMP/fix2-acme-noReason.out"; then
|
|
289
|
+
_pass "acme.deliver (non-builder): verification→execution requires reason when route_back_policy declared"
|
|
290
|
+
else
|
|
291
|
+
_fail "acme.deliver route-back lacked expected diagnostic (got: $(cat "$TMP/fix2-acme-noReason.out"))"
|
|
292
|
+
fi
|
|
293
|
+
|
|
294
|
+
# Do 2 successful route-backs
|
|
295
|
+
flow_agents_node "$SIDECAR_BUNDLE_WRITER" advance-state "$ACME_DIR" \
|
|
296
|
+
--status in_progress --phase execution \
|
|
297
|
+
--summary "Acme route back 1." --flow-definition acme.deliver \
|
|
298
|
+
--route-back-reason implementation_defect \
|
|
299
|
+
--timestamp "2026-06-27T10:03:00Z" > "$TMP/fix2-acme-rb1.out" 2>&1
|
|
300
|
+
flow_agents_node "$SIDECAR_BUNDLE_WRITER" advance-state "$ACME_DIR" \
|
|
301
|
+
--status verifying --phase verification \
|
|
302
|
+
--summary "Back to verify." --flow-definition acme.deliver \
|
|
303
|
+
--timestamp "2026-06-27T10:04:00Z" > "$TMP/fix2-acme-fwd1.out" 2>&1
|
|
304
|
+
flow_agents_node "$SIDECAR_BUNDLE_WRITER" advance-state "$ACME_DIR" \
|
|
305
|
+
--status in_progress --phase execution \
|
|
306
|
+
--summary "Acme route back 2." --flow-definition acme.deliver \
|
|
307
|
+
--route-back-reason implementation_defect \
|
|
308
|
+
--timestamp "2026-06-27T10:05:00Z" > "$TMP/fix2-acme-rb2.out" 2>&1
|
|
309
|
+
flow_agents_node "$SIDECAR_BUNDLE_WRITER" advance-state "$ACME_DIR" \
|
|
310
|
+
--status verifying --phase verification \
|
|
311
|
+
--summary "Back to verify again." --flow-definition acme.deliver \
|
|
312
|
+
--timestamp "2026-06-27T10:06:00Z" > "$TMP/fix2-acme-fwd2.out" 2>&1
|
|
313
|
+
|
|
314
|
+
# Third attempt should exceed max_attempts=2 (flow declares max 2, not hardcoded 3)
|
|
315
|
+
if flow_agents_node "$SIDECAR_BUNDLE_WRITER" advance-state "$ACME_DIR" \
|
|
316
|
+
--status in_progress --phase execution \
|
|
317
|
+
--summary "Acme exceeds route-back limit." --flow-definition acme.deliver \
|
|
318
|
+
--route-back-reason implementation_defect \
|
|
319
|
+
--timestamp "2026-06-27T10:07:00Z" > "$TMP/fix2-acme-exceeded.out" 2>&1; then
|
|
320
|
+
_fail "acme.deliver should block after flow-declared max_attempts=2 route-backs"
|
|
321
|
+
elif grep -q 'route_back_attempts_exceeded' "$TMP/fix2-acme-exceeded.out"; then
|
|
322
|
+
_pass "acme.deliver: blocks after flow-declared max_attempts=2 (not the hardcoded 3 from old builder code)"
|
|
323
|
+
else
|
|
324
|
+
_fail "acme.deliver exceeded max_attempts but wrong diagnostic (got: $(cat "$TMP/fix2-acme-exceeded.out"))"
|
|
325
|
+
fi
|
|
326
|
+
|
|
327
|
+
unset FLOW_AGENTS_FLOW_DEFS_DIR
|
|
328
|
+
|
|
329
|
+
# ─── 2c. Custom flow WITHOUT route_back_policy: NOT enforced ──────────────────
|
|
330
|
+
echo ""
|
|
331
|
+
echo "=== 2c. Custom flow WITHOUT route_back_policy: verification→execution NOT enforced ==="
|
|
332
|
+
|
|
333
|
+
CUSTOM_FLOWS_DIR_2="$TMP/custom-flows-2"
|
|
334
|
+
mkdir -p "$CUSTOM_FLOWS_DIR_2"
|
|
335
|
+
|
|
336
|
+
node - "$CUSTOM_FLOWS_DIR_2/acme.nodecl.flow.json" << 'NODE'
|
|
337
|
+
const fs = require('fs');
|
|
338
|
+
const flowPath = process.argv[2];
|
|
339
|
+
const flow = {
|
|
340
|
+
id: "acme.nodecl", version: "1.0",
|
|
341
|
+
phase_map: { execution: "execute", verification: "verify" },
|
|
342
|
+
steps: [{ id: "execute", next: "verify" }, { id: "verify", next: "done" }, { id: "done", next: null }],
|
|
343
|
+
gates: {
|
|
344
|
+
"verify-gate": {
|
|
345
|
+
step: "verify",
|
|
346
|
+
expects: [{ id: "verify-evidence", kind: "trust.bundle", required: true,
|
|
347
|
+
bundle_claim: { claimType: "acme.verify.tests", subjectType: "flow-step", accepted_statuses: ["trusted","accepted"] } }]
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
fs.writeFileSync(flowPath, JSON.stringify(flow, null, 2));
|
|
352
|
+
NODE
|
|
353
|
+
|
|
354
|
+
NODECL_DIR="$TMP/fix2-nodecl/.flow-agents/nodecl-fix2"
|
|
355
|
+
mkdir -p "$TMP/fix2-nodecl/.flow-agents"
|
|
356
|
+
|
|
357
|
+
flow_agents_node "$SIDECAR_BUNDLE_WRITER" ensure-session \
|
|
358
|
+
--artifact-root "$TMP/fix2-nodecl/.flow-agents" \
|
|
359
|
+
--task-slug "nodecl-fix2" \
|
|
360
|
+
--title "Fix2 nodecl route-back test" \
|
|
361
|
+
--summary "Verify flow without route_back_policy is not guarded." \
|
|
362
|
+
--timestamp "2026-06-27T10:00:00Z" > "$TMP/fix2-nodecl-ensure.out" 2>&1
|
|
363
|
+
|
|
364
|
+
export FLOW_AGENTS_FLOW_DEFS_DIR="$CUSTOM_FLOWS_DIR_2"
|
|
365
|
+
|
|
366
|
+
flow_agents_node "$SIDECAR_BUNDLE_WRITER" advance-state "$NODECL_DIR" \
|
|
367
|
+
--status verifying --phase verification \
|
|
368
|
+
--summary "Moving nodecl to verification." \
|
|
369
|
+
--flow-definition acme.nodecl \
|
|
370
|
+
--timestamp "2026-06-27T10:01:00Z" > "$TMP/fix2-nodecl-verify.out" 2>&1
|
|
371
|
+
|
|
372
|
+
if flow_agents_node "$SIDECAR_BUNDLE_WRITER" advance-state "$NODECL_DIR" \
|
|
373
|
+
--status in_progress --phase execution \
|
|
374
|
+
--summary "Nodecl route back — should be free without reason." \
|
|
375
|
+
--flow-definition acme.nodecl \
|
|
376
|
+
--timestamp "2026-06-27T10:02:00Z" > "$TMP/fix2-nodecl-rb.out" 2>&1 \
|
|
377
|
+
&& [[ ! -f "$NODECL_DIR/transition-attempts.json" ]]; then
|
|
378
|
+
_pass "acme.nodecl (no route_back_policy): verification→execution freely allowed, no attempts file"
|
|
379
|
+
else
|
|
380
|
+
_fail "acme.nodecl without route_back_policy should allow route-back freely (got: $(cat "$TMP/fix2-nodecl-rb.out"))"
|
|
381
|
+
fi
|
|
382
|
+
|
|
383
|
+
unset FLOW_AGENTS_FLOW_DEFS_DIR
|
|
384
|
+
|
|
385
|
+
echo ""
|
|
386
|
+
echo "────────────────────────────────────────────"
|
|
387
|
+
if [[ "$errors" -eq 0 ]]; then
|
|
388
|
+
echo "test_kit_identity_trust: all checks passed."
|
|
389
|
+
exit 0
|
|
390
|
+
else
|
|
391
|
+
echo "test_kit_identity_trust: $errors check(s) FAILED."
|
|
392
|
+
exit 1
|
|
393
|
+
fi
|