@kontourai/flow-agents 3.6.0 → 3.8.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/CHANGELOG.md +19 -0
- package/build/src/builder-flow-run-adapter.d.ts +22 -2
- package/build/src/builder-flow-run-adapter.js +93 -28
- package/build/src/builder-flow-runtime.d.ts +8 -3
- package/build/src/builder-flow-runtime.js +407 -51
- package/build/src/cli/assignment-provider.d.ts +4 -7
- package/build/src/cli/assignment-provider.js +80 -14
- package/build/src/cli/builder-run.js +14 -18
- package/build/src/cli/workflow-sidecar.d.ts +28 -4
- package/build/src/cli/workflow-sidecar.js +825 -103
- package/build/src/cli/workflow.js +301 -43
- package/build/src/flow-kit/validate.d.ts +17 -0
- package/build/src/flow-kit/validate.js +340 -2
- package/build/src/index.js +5 -5
- package/build/src/lib/observed-command.d.ts +7 -0
- package/build/src/lib/observed-command.js +100 -0
- package/build/src/tools/build-universal-bundles.js +53 -3
- package/build/src/tools/generate-context-map.js +5 -3
- package/context/scripts/hooks/lib/kit-catalog.js +1 -1
- package/context/scripts/hooks/stop-goal-fit.js +78 -9
- package/docs/context-map.md +22 -20
- package/docs/developer-architecture.md +1 -1
- package/docs/getting-started.md +9 -1
- package/docs/public-workflow-cli.md +76 -7
- package/docs/skills-map.md +51 -27
- package/docs/spec/builder-flow-runtime.md +75 -40
- package/docs/workflow-usage-guide.md +109 -42
- package/evals/fixtures/hook-influence/cases.json +2 -2
- package/evals/integration/test_builder_entry_enforcement.sh +52 -41
- package/evals/integration/test_builder_step_producers.sh +330 -6
- package/evals/integration/test_bundle_install.sh +318 -65
- package/evals/integration/test_bundle_lifecycle.sh +4 -6
- package/evals/integration/test_critique_supersession_roundtrip.sh +21 -8
- package/evals/integration/test_current_json_per_actor.sh +12 -0
- package/evals/integration/test_dual_emit_flow_step.sh +62 -43
- package/evals/integration/test_flowdef_session_activation.sh +145 -25
- package/evals/integration/test_flowdef_session_history_preservation.sh +23 -21
- package/evals/integration/test_gate_lockdown.sh +3 -5
- package/evals/integration/test_goal_fit_hook.sh +60 -2
- package/evals/integration/test_install_merge.sh +18 -8
- package/evals/integration/test_liveness_verdict.sh +14 -17
- package/evals/integration/test_phase_map_and_gate_claim.sh +63 -38
- package/evals/integration/test_public_workflow_cli.sh +334 -14
- package/evals/integration/test_pull_work_liveness_preflight.sh +22 -66
- package/evals/integration/test_sidecar_field_preservation.sh +36 -11
- package/evals/integration/test_workflow_sidecar_writer.sh +277 -44
- package/evals/integration/test_workflow_steering_hook.sh +15 -38
- package/evals/run.sh +2 -0
- package/evals/static/test_builder_skill_coherence.sh +247 -0
- package/evals/static/test_library_exports.sh +5 -2
- package/evals/static/test_universal_bundles.sh +44 -1
- package/evals/static/test_workflow_skills.sh +13 -325
- package/kits/builder/flows/build.flow.json +22 -0
- package/kits/builder/flows/shape.flow.json +9 -9
- package/kits/builder/kit.json +70 -16
- package/kits/builder/skills/builder-shape/SKILL.md +75 -75
- package/kits/builder/skills/continue-work/SKILL.md +45 -106
- package/kits/builder/skills/deliver/SKILL.md +96 -442
- package/kits/builder/skills/design-probe/SKILL.md +40 -139
- package/kits/builder/skills/evidence-gate/SKILL.md +59 -201
- package/kits/builder/skills/execute-plan/SKILL.md +54 -125
- package/kits/builder/skills/fix-bug/SKILL.md +42 -132
- package/kits/builder/skills/gate-review/SKILL.md +60 -211
- package/kits/builder/skills/idea-to-backlog/SKILL.md +63 -244
- package/kits/builder/skills/learning-review/SKILL.md +63 -170
- package/kits/builder/skills/pickup-probe/SKILL.md +54 -111
- package/kits/builder/skills/plan-work/SKILL.md +51 -185
- package/kits/builder/skills/pull-work/SKILL.md +136 -485
- package/kits/builder/skills/release-readiness/SKILL.md +66 -107
- package/kits/builder/skills/review-work/SKILL.md +89 -176
- package/kits/builder/skills/tdd-workflow/SKILL.md +53 -147
- package/kits/builder/skills/verify-work/SKILL.md +101 -113
- package/package.json +2 -2
- package/packaging/README.md +1 -1
- package/scripts/README.md +1 -1
- package/scripts/hooks/lib/kit-catalog.js +1 -1
- package/scripts/hooks/stop-goal-fit.js +78 -9
- package/scripts/install-codex-home.sh +63 -23
- package/scripts/install-owned-files.js +18 -2
- package/src/builder-flow-run-adapter.ts +118 -32
- package/src/builder-flow-runtime.ts +426 -64
- package/src/cli/assignment-provider-lock.test.mjs +83 -0
- package/src/cli/assignment-provider.ts +75 -14
- package/src/cli/builder-flow-run-adapter.test.mjs +4 -2
- package/src/cli/builder-flow-runtime.test.mjs +436 -18
- package/src/cli/builder-run.ts +3 -9
- package/src/cli/kit-metadata-security.test.mjs +232 -6
- package/src/cli/public-api.test.mjs +15 -0
- package/src/cli/workflow-sidecar-execution-proof.test.mjs +90 -0
- package/src/cli/workflow-sidecar.ts +746 -103
- package/src/cli/workflow.ts +288 -41
- package/src/flow-kit/validate.ts +320 -2
- package/src/index.ts +6 -5
- package/src/lib/observed-command.ts +96 -0
- package/src/tools/build-universal-bundles.ts +51 -3
- package/src/tools/generate-context-map.ts +5 -3
|
@@ -48,15 +48,20 @@ seed() {
|
|
|
48
48
|
# ─── (a) same-reviewer supersession: fail → pass ──────────────────────────────
|
|
49
49
|
echo ""
|
|
50
50
|
echo "=== (a) record-critique fail→pass (same reviewer) supersedes, history intact, reconcile 0 ==="
|
|
51
|
-
A_AROOT="$TMP/a/
|
|
51
|
+
A_AROOT="$TMP/a/.kontourai/flow-agents"; A_SLUG="supersede-same"; A_DIR="$A_AROOT/$A_SLUG"
|
|
52
52
|
seed "$A_AROOT" "$A_SLUG"
|
|
53
53
|
flow_agents_node "$WRITER" record-evidence "$A_DIR" --verdict pass \
|
|
54
54
|
--check-json '{"id":"c1","kind":"diff","status":"pass","summary":"diff check"}' \
|
|
55
55
|
--timestamp "2026-07-01T00:01:00Z" >/dev/null 2>&1
|
|
56
56
|
flow_agents_node "$WRITER" record-critique "$A_DIR" --id rv --reviewer alice --verdict fail \
|
|
57
|
-
--summary "found a bug"
|
|
57
|
+
--summary "found a bug" \
|
|
58
|
+
--lane-json "{\"id\":\"code\",\"status\":\"fail\",\"summary\":\"bug found\",\"evidence_refs\":[{\"kind\":\"artifact\",\"file\":\"$A_DIR/$A_SLUG--deliver.md\",\"summary\":\"Reviewed the failing delivery artifact.\"}]}" \
|
|
59
|
+
--timestamp "2026-07-01T00:02:00Z" >/dev/null 2>&1
|
|
58
60
|
flow_agents_node "$WRITER" record-critique "$A_DIR" --id rv --reviewer alice --verdict pass \
|
|
59
|
-
--summary "bug fixed"
|
|
61
|
+
--summary "bug fixed" \
|
|
62
|
+
--lane-json "{\"id\":\"code\",\"status\":\"pass\",\"summary\":\"fix verified\",\"evidence_refs\":[{\"kind\":\"artifact\",\"file\":\"$A_DIR/$A_SLUG--deliver.md\",\"summary\":\"Reviewed the corrected delivery artifact.\"}]}" \
|
|
63
|
+
--artifact-ref "$A_DIR/$A_SLUG--deliver.md" \
|
|
64
|
+
--timestamp "2026-07-01T00:03:00Z" >/dev/null 2>&1
|
|
60
65
|
|
|
61
66
|
node - "$A_DIR/trust.bundle" << 'NODE'
|
|
62
67
|
const fs = require('fs');
|
|
@@ -80,7 +85,7 @@ if [[ $? -eq 0 ]]; then _pass "(a) trust-reconcile exits 0 (resolved session con
|
|
|
80
85
|
# ─── (b) HEADLINE: --flow-id session converges ────────────────────────────────
|
|
81
86
|
echo ""
|
|
82
87
|
echo "=== (b) HEADLINE --flow-id builder.build/verify: mixed evidence + critique → reconcile 0 ==="
|
|
83
|
-
B_AROOT="$TMP/b/
|
|
88
|
+
B_AROOT="$TMP/b/.kontourai/flow-agents"; B_SLUG="flowid-converge"; B_DIR="$B_AROOT/$B_SLUG"
|
|
84
89
|
seed "$B_AROOT" "$B_SLUG" --flow-id builder.build
|
|
85
90
|
flow_agents_node "$WRITER" advance-state "$B_DIR" --status in_progress --phase verification \
|
|
86
91
|
--summary "Testing at verify." --next-action "Record evidence." \
|
|
@@ -91,7 +96,10 @@ flow_agents_node "$WRITER" record-evidence "$B_DIR" --verdict pass \
|
|
|
91
96
|
--check-json '{"id":"k-ext","kind":"external","status":"pass","summary":"attested"}' \
|
|
92
97
|
--timestamp "2026-07-01T00:01:00Z" >/dev/null 2>&1
|
|
93
98
|
flow_agents_node "$WRITER" record-critique "$B_DIR" --id code-review --reviewer alice --verdict pass \
|
|
94
|
-
--summary "looks good"
|
|
99
|
+
--summary "looks good" \
|
|
100
|
+
--lane-json "{\"id\":\"code\",\"status\":\"pass\",\"summary\":\"review passed\",\"evidence_refs\":[{\"kind\":\"artifact\",\"file\":\"$B_DIR/$B_SLUG--deliver.md\",\"summary\":\"Reviewed the delivery artifact.\"}]}" \
|
|
101
|
+
--artifact-ref "$B_DIR/$B_SLUG--deliver.md" \
|
|
102
|
+
--timestamp "2026-07-01T00:02:00Z" >/dev/null 2>&1
|
|
95
103
|
|
|
96
104
|
node - "$B_DIR/trust.bundle" << 'NODE'
|
|
97
105
|
const fs = require('fs');
|
|
@@ -132,15 +140,20 @@ if [[ $? -eq 0 ]]; then _pass "(c) critique history survives a later record-evid
|
|
|
132
140
|
# ─── (d) ANTI-GAMING: cross-reviewer cannot supersede a reviewer fail ─────────
|
|
133
141
|
echo ""
|
|
134
142
|
echo "=== (d) ANTI-GAMING: a different reviewer cannot supersede a reviewer's fail ==="
|
|
135
|
-
D_AROOT="$TMP/d/
|
|
143
|
+
D_AROOT="$TMP/d/.kontourai/flow-agents"; D_SLUG="supersede-cross"; D_DIR="$D_AROOT/$D_SLUG"
|
|
136
144
|
seed "$D_AROOT" "$D_SLUG"
|
|
137
145
|
flow_agents_node "$WRITER" record-evidence "$D_DIR" --verdict pass \
|
|
138
146
|
--check-json '{"id":"c1","kind":"diff","status":"pass","summary":"diff check"}' \
|
|
139
147
|
--timestamp "2026-07-01T00:01:00Z" >/dev/null 2>&1
|
|
140
148
|
flow_agents_node "$WRITER" record-critique "$D_DIR" --id rv --reviewer reviewer-bob --verdict fail \
|
|
141
|
-
--summary "reviewer found a real bug"
|
|
149
|
+
--summary "reviewer found a real bug" \
|
|
150
|
+
--lane-json "{\"id\":\"code\",\"status\":\"fail\",\"summary\":\"bug found\",\"evidence_refs\":[{\"kind\":\"artifact\",\"file\":\"$D_DIR/$D_SLUG--deliver.md\",\"summary\":\"Reviewed the failing delivery artifact.\"}]}" \
|
|
151
|
+
--timestamp "2026-07-01T00:02:00Z" >/dev/null 2>&1
|
|
142
152
|
flow_agents_node "$WRITER" record-critique "$D_DIR" --id rv --reviewer worker-mallory --verdict pass \
|
|
143
|
-
--summary "worker claims fixed"
|
|
153
|
+
--summary "worker claims fixed" \
|
|
154
|
+
--lane-json "{\"id\":\"code\",\"status\":\"pass\",\"summary\":\"worker claims review passed\",\"evidence_refs\":[{\"kind\":\"artifact\",\"file\":\"$D_DIR/$D_SLUG--deliver.md\",\"summary\":\"Reviewed the claimed correction.\"}]}" \
|
|
155
|
+
--artifact-ref "$D_DIR/$D_SLUG--deliver.md" \
|
|
156
|
+
--timestamp "2026-07-01T00:03:00Z" >/dev/null 2>&1
|
|
144
157
|
node - "$D_DIR/trust.bundle" << 'NODE'
|
|
145
158
|
const fs = require('fs');
|
|
146
159
|
const b = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
|
|
@@ -371,6 +371,7 @@ set -e
|
|
|
371
371
|
echo "--- 5. record-gate-claim resolves A's own per-actor flow/step, not B's legacy pointer (AC11) ---"
|
|
372
372
|
|
|
373
373
|
AC11_ROOT="$TMPDIR_EVAL/ac11-project/.kontourai/flow-agents"
|
|
374
|
+
AC11_WORK_ITEM="local:gate-actor-a"
|
|
374
375
|
|
|
375
376
|
flow_agents_node "workflow-sidecar" ensure-session \
|
|
376
377
|
--artifact-root "$AC11_ROOT" \
|
|
@@ -388,6 +389,16 @@ flow_agents_node "workflow-sidecar" init-plan "$AC11_DELIVER_MD" \
|
|
|
388
389
|
--source-request "Test" --summary "Testing" \
|
|
389
390
|
--timestamp "2026-07-01T00:00:30Z" >"$TMPDIR_EVAL/ac11-a-initplan.out" 2>"$TMPDIR_EVAL/ac11-a-initplan.err"
|
|
390
391
|
|
|
392
|
+
# A passing selected-work claim must cite pull-work's declared durable artifact. Keep it in A's
|
|
393
|
+
# session so the generic producer/evidence contract is exercised without weakening AC11's
|
|
394
|
+
# per-actor pointer differential.
|
|
395
|
+
AC11_PULL_WORK_ARTIFACT="$AC11_ROOT/gate-actor-a/gate-actor-a--pull-work.md"
|
|
396
|
+
safe_write "$AC11_PULL_WORK_ARTIFACT" <<EOF
|
|
397
|
+
# Pull Work
|
|
398
|
+
|
|
399
|
+
Selected Work Item: $AC11_WORK_ITEM
|
|
400
|
+
EOF
|
|
401
|
+
|
|
391
402
|
# Actor B runs a LATER, plain (non-FlowDefinition) ensure-session on an unrelated subject on the
|
|
392
403
|
# SAME artifact root -- this overwrites the LEGACY global current.json (last-writer-wins, no
|
|
393
404
|
# active_flow_id/active_step_id at all) while leaving actor A's own per-actor current file
|
|
@@ -416,6 +427,7 @@ if flow_agents_node "workflow-sidecar" record-gate-claim "$AC11_GATE_ACTOR_A_DIR
|
|
|
416
427
|
--status pass \
|
|
417
428
|
--summary "Selected issue #291 for implementation." \
|
|
418
429
|
--expectation selected-work \
|
|
430
|
+
--evidence-ref-json "{\"kind\":\"artifact\",\"file\":\"$AC11_PULL_WORK_ARTIFACT\",\"summary\":\"Declared pull-work artifact naming bound Work Item $AC11_WORK_ITEM.\"}" \
|
|
419
431
|
--timestamp "2026-07-01T00:02:00Z" \
|
|
420
432
|
>"$TMPDIR_EVAL/ac11-gate-claim.out" 2>"$TMPDIR_EVAL/ac11-gate-claim.err"; then
|
|
421
433
|
pass "record-gate-claim (actor A) succeeds by resolving A's OWN per-actor current pointer, not B's stale legacy pointer (AC11)"
|
|
@@ -251,43 +251,71 @@ fi
|
|
|
251
251
|
echo ""
|
|
252
252
|
echo "── P-d declared-only: session WITH active_flow_id=builder.build / active_step_id=verify ──"
|
|
253
253
|
|
|
254
|
-
#
|
|
255
|
-
#
|
|
254
|
+
# Each fixture starts at the declared first step with selected-work evidence,
|
|
255
|
+
# then advances by recording the durable artifacts that the declared producers
|
|
256
|
+
# require. current.json is only projected by the writer during those transitions.
|
|
256
257
|
mkdir -p "$SESSION_ROOT"
|
|
257
|
-
if flow_agents_node "$WRITER" ensure-session \
|
|
258
|
-
--artifact-root "$SESSION_ROOT" \
|
|
259
|
-
--task-slug dual-emit-test \
|
|
260
|
-
--flow-id builder.build \
|
|
261
|
-
--skip-ownership-guard \
|
|
262
|
-
--title "Declared-Only Test" \
|
|
263
|
-
--summary "Test declared-only emit for ADR 0016 P-d." \
|
|
264
|
-
--criterion "Tests pass" \
|
|
265
|
-
--timestamp "2026-06-26T00:00:00Z" >"$TMP/ensure.out" 2>"$TMP/ensure.err"; then
|
|
266
|
-
_pass "ensure-session with --flow-id succeeds at the declared first step"
|
|
267
|
-
else
|
|
268
|
-
_fail "ensure-session with --flow-id failed: $(cat "$TMP/ensure.out" "$TMP/ensure.err")"
|
|
269
|
-
fi
|
|
270
|
-
|
|
271
|
-
DUAL_DIR="$SESSION_ROOT/dual-emit-test"
|
|
272
258
|
|
|
273
259
|
advance_builder_to_verify() {
|
|
274
|
-
local
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
260
|
+
local slug="$1"
|
|
261
|
+
local title="$2"
|
|
262
|
+
local summary="$3"
|
|
263
|
+
local session_dir="$SESSION_ROOT/$slug"
|
|
264
|
+
local pull_work="$session_dir/$slug--pull-work.md"
|
|
265
|
+
local plan="$session_dir/$slug--plan-work.md"
|
|
266
|
+
local deliver="$session_dir/$slug--deliver.md"
|
|
267
|
+
local work_item="${slug/-/:}"
|
|
268
|
+
|
|
269
|
+
mkdir -p "$session_dir"
|
|
270
|
+
printf 'Selected Work Item: %s\n' "$work_item" > "$pull_work"
|
|
271
|
+
FLOW_AGENTS_ACTOR="$slug-fixture-actor" node "$ROOT/build/src/cli.js" workflow start \
|
|
272
|
+
--artifact-root "$SESSION_ROOT" \
|
|
273
|
+
--flow builder.build \
|
|
274
|
+
--work-item "$work_item" \
|
|
275
|
+
--assignment-provider local-file \
|
|
276
|
+
--title "$title" \
|
|
277
|
+
--summary "$summary" \
|
|
278
|
+
--criterion "Fixture producer artifacts reach verify." >/dev/null 2>&1 || return 1
|
|
279
|
+
flow_agents_node "$WRITER" init-plan "$deliver" \
|
|
280
|
+
--source-request "Test declared-only producer artifacts." \
|
|
281
|
+
--summary "Fixture plan for declared-only producer artifacts." \
|
|
282
|
+
--timestamp "2026-06-26T00:00:05Z" >/dev/null 2>&1 || return 1
|
|
283
|
+
node - "$session_dir" "$slug" <<'NODE'
|
|
284
|
+
const fs = require('node:fs');
|
|
285
|
+
const path = require('node:path');
|
|
286
|
+
const [dir, slug] = process.argv.slice(2);
|
|
287
|
+
fs.writeFileSync(path.join(dir, `${slug}--plan-work.md`), '# Plan\n\n- AC-1: Reach verify through declared producer artifacts.\n', 'utf8');
|
|
288
|
+
fs.writeFileSync(path.join(dir, 'acceptance.json'), JSON.stringify({
|
|
289
|
+
schema_version: '1.0',
|
|
290
|
+
task_slug: slug,
|
|
291
|
+
criteria: [{
|
|
292
|
+
id: 'AC-1',
|
|
293
|
+
description: 'Reach verify through declared producer artifacts.',
|
|
294
|
+
status: 'pending',
|
|
295
|
+
evidence_refs: [],
|
|
296
|
+
}],
|
|
297
|
+
goal_fit: { status: 'pending', summary: 'Fixture has not completed Goal Fit review.' },
|
|
298
|
+
}, null, 2), 'utf8');
|
|
299
|
+
NODE
|
|
300
|
+
FLOW_AGENTS_ACTOR="$slug-fixture-actor" node "$ROOT/build/src/cli.js" workflow evidence --session-dir "$session_dir" --status pass --expectation pickup-probe-readiness \
|
|
301
|
+
--summary "Pickup readiness is recorded in the selected-work artifact." \
|
|
302
|
+
--evidence-ref-json "{\"kind\":\"artifact\",\"file\":\"$pull_work\",\"summary\":\"Declared durable producer artifact for pickup-probe-readiness.\"}" >/dev/null 2>&1 || return 1
|
|
303
|
+
FLOW_AGENTS_ACTOR="$slug-fixture-actor" node "$ROOT/build/src/cli.js" workflow evidence --session-dir "$session_dir" --status pass --expectation probe-decisions-or-accepted-gaps \
|
|
304
|
+
--summary "Probe decisions are recorded in the selected-work artifact." \
|
|
305
|
+
--evidence-ref-json "{\"kind\":\"artifact\",\"file\":\"$pull_work\",\"summary\":\"Declared durable producer artifact for probe decisions.\"}" >/dev/null 2>&1 || return 1
|
|
306
|
+
FLOW_AGENTS_ACTOR="$slug-fixture-actor" node "$ROOT/build/src/cli.js" workflow evidence --session-dir "$session_dir" --status pass --expectation implementation-plan \
|
|
307
|
+
--summary "Implementation plan is recorded in the plan artifact." \
|
|
308
|
+
--evidence-ref-json "{\"kind\":\"artifact\",\"file\":\"$plan\",\"summary\":\"Declared durable producer artifact for implementation-plan.\"}" >/dev/null 2>&1 || return 1
|
|
309
|
+
FLOW_AGENTS_ACTOR="$slug-fixture-actor" node "$ROOT/build/src/cli.js" workflow evidence --session-dir "$session_dir" --status pass --expectation implementation-scope \
|
|
310
|
+
--summary "Implementation scope is recorded in the delivery artifact." \
|
|
311
|
+
--evidence-ref-json "{\"kind\":\"artifact\",\"file\":\"$deliver\",\"summary\":\"Declared durable producer artifact for implementation-scope.\"}" >/dev/null 2>&1 || return 1
|
|
285
312
|
}
|
|
286
313
|
|
|
287
|
-
|
|
288
|
-
|
|
314
|
+
DUAL_DIR="$SESSION_ROOT/dual-emit-test"
|
|
315
|
+
if advance_builder_to_verify "dual-emit-test" "Declared-Only Test" "Test declared-only emit for ADR 0016 P-d."; then
|
|
316
|
+
_pass "canonical Builder Flow advances through declared producer artifacts to verify"
|
|
289
317
|
else
|
|
290
|
-
_fail "canonical Builder Flow did not reach verify"
|
|
318
|
+
_fail "canonical Builder Flow did not reach verify through declared producer artifacts"
|
|
291
319
|
fi
|
|
292
320
|
|
|
293
321
|
# Verify current.json carries the flow keys
|
|
@@ -345,19 +373,10 @@ echo "── P-d declared-only: policy-kind check maps to builder.verify.policy-
|
|
|
345
373
|
|
|
346
374
|
# Use a separate canonical run because the failing tests evidence above legitimately
|
|
347
375
|
# routes its run back to execute before this independent producer assertion.
|
|
348
|
-
if
|
|
349
|
-
|
|
350
|
-
--task-slug dual-emit-policy \
|
|
351
|
-
--flow-id builder.build \
|
|
352
|
-
--skip-ownership-guard \
|
|
353
|
-
--title "Declared Policy Test" \
|
|
354
|
-
--summary "Test declared-only policy emit for ADR 0016 P-d." \
|
|
355
|
-
--criterion "Policy passes" \
|
|
356
|
-
--timestamp "2026-06-26T00:01:30Z" >/dev/null 2>&1 \
|
|
357
|
-
&& advance_builder_to_verify "$SESSION_ROOT/dual-emit-policy"; then
|
|
358
|
-
_pass "policy fixture canonical Builder Flow reaches verify"
|
|
376
|
+
if advance_builder_to_verify "dual-emit-policy" "Declared Policy Test" "Test declared-only policy emit for ADR 0016 P-d."; then
|
|
377
|
+
_pass "policy fixture canonical Builder Flow reaches verify through declared producer artifacts"
|
|
359
378
|
else
|
|
360
|
-
_fail "policy fixture canonical Builder Flow did not reach verify"
|
|
379
|
+
_fail "policy fixture canonical Builder Flow did not reach verify through declared producer artifacts"
|
|
361
380
|
fi
|
|
362
381
|
|
|
363
382
|
POLICY_DIR="$SESSION_ROOT/dual-emit-policy"
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
# correctly sets active_step_id via the phase_map at each phase.
|
|
7
7
|
#
|
|
8
8
|
# Tests:
|
|
9
|
-
# 1. ensure-session --flow-id
|
|
10
|
-
#
|
|
9
|
+
# 1. Pre-seeded concrete pull-work evidence lets ensure-session --flow-id
|
|
10
|
+
# builder.build bind the local Work Item and project the canonical Flow.
|
|
11
11
|
# 2. advance-state through phases (planning→execution→verification) sets correct
|
|
12
12
|
# active_step_id via phase_map at each transition.
|
|
13
|
-
# 3. At the verify step,
|
|
13
|
+
# 3. At the verify step, public workflow evidence for tests-evidence produces
|
|
14
14
|
# builder.verify.tests (status=verified) in the bundle — producer fires.
|
|
15
15
|
# 4. A TAMPERED builder.verify.tests bundle at the verify step BLOCKS (exit 2)
|
|
16
16
|
# with the tamper warning naming the declared claimType.
|
|
@@ -46,17 +46,17 @@ echo "=== 1. ensure-session --flow-id builder.build activates FlowDefinition-dri
|
|
|
46
46
|
MAIN_AROOT="$TMP/main-project/.kontourai/flow-agents"
|
|
47
47
|
SLUG="activation-test"
|
|
48
48
|
SESSION_DIR="$MAIN_AROOT/$SLUG"
|
|
49
|
-
mkdir -p "$
|
|
49
|
+
mkdir -p "$SESSION_DIR"
|
|
50
|
+
printf 'Selected Work Item: activation:test\n' > "$SESSION_DIR/$SLUG--pull-work.md"
|
|
50
51
|
|
|
51
|
-
if
|
|
52
|
+
if FLOW_AGENTS_ACTOR=activation-test-actor node "$ROOT/build/src/cli.js" workflow start \
|
|
52
53
|
--artifact-root "$MAIN_AROOT" \
|
|
53
|
-
--
|
|
54
|
-
--
|
|
54
|
+
--flow builder.build \
|
|
55
|
+
--work-item activation:test \
|
|
56
|
+
--assignment-provider local-file \
|
|
55
57
|
--title "Step 1 activation test" \
|
|
56
58
|
--summary "Test that --flow-id builder.build activates the FlowDefinition-driven path." \
|
|
57
|
-
--criterion "All gates produce declared claims"
|
|
58
|
-
--flow-id builder.build \
|
|
59
|
-
--timestamp "2026-06-01T00:00:00Z" >/dev/null 2>&1; then
|
|
59
|
+
--criterion "All gates produce declared claims" >/dev/null 2>&1; then
|
|
60
60
|
_pass "ensure-session starts the canonical Builder Flow from a canonical artifact root"
|
|
61
61
|
else
|
|
62
62
|
_fail "ensure-session failed to start the canonical Builder Flow"
|
|
@@ -76,17 +76,54 @@ console.log('current.json: active_flow_id=' + c.active_flow_id + ' active_step_i
|
|
|
76
76
|
&& _pass "ensure-session records trusted selection and projects the canonical Flow run at design-probe" \
|
|
77
77
|
|| _fail "ensure-session did not create and project the canonical Flow run"
|
|
78
78
|
|
|
79
|
+
if node - "$ROOT/kits/builder/kit.json" "$ROOT" <<'NODE'
|
|
80
|
+
const fs = require('node:fs');
|
|
81
|
+
const kit = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
|
|
82
|
+
const { workflowTriggersFor } = require(`${process.argv[3]}/scripts/hooks/lib/kit-catalog.js`);
|
|
83
|
+
const roles = new Map(kit.skill_roles.map((entry) => [entry.skill_id.replace(/^builder\./, ''), entry.role]));
|
|
84
|
+
const trigger = kit.workflow_triggers.find((entry) => entry.id === 'builder-build-work');
|
|
85
|
+
if (roles.get(trigger.default_skill) !== 'entrypoint') process.exit(1);
|
|
86
|
+
if (!trigger.conditional_skills.every((entry) => roles.get(entry.skill) === 'profile')) process.exit(2);
|
|
87
|
+
const [rendered] = workflowTriggersFor(process.argv[3], 'implementation-work-detected');
|
|
88
|
+
if (!rendered?.steering.includes('activate `tdd-workflow`; otherwise activate `deliver`')) process.exit(5);
|
|
89
|
+
if (!rendered.steering.includes('public `flow-agents workflow` interface') || rendered.steering.includes('workflow:sidecar')) process.exit(6);
|
|
90
|
+
for (const action of kit.flow_step_actions) {
|
|
91
|
+
if (!action.skills.every((skill) => roles.get(skill) === 'step')) process.exit(3);
|
|
92
|
+
}
|
|
93
|
+
for (const skill of ['design-probe', 'continue-work', 'gate-review', 'fix-bug']) {
|
|
94
|
+
if (kit.flow_step_actions.some((action) => action.skills.includes(skill))) process.exit(4);
|
|
95
|
+
if (rendered.steering.includes(`activate \`${skill}\``)) process.exit(7);
|
|
96
|
+
}
|
|
97
|
+
NODE
|
|
98
|
+
then
|
|
99
|
+
_pass "runtime steering activates the entrypoint/profile and keeps primitives/extensions outside automatic step actions"
|
|
100
|
+
else
|
|
101
|
+
_fail "activation metadata blurred entrypoint, profile, step, primitive, or extension roles"
|
|
102
|
+
fi
|
|
103
|
+
|
|
79
104
|
# ─── TEST 2: advance-state sets active_step_id via phase_map ─────────────────
|
|
80
105
|
echo ""
|
|
81
106
|
echo "=== 2. advance-state through phases sets active_step_id via phase_map ==="
|
|
82
107
|
|
|
83
|
-
|
|
108
|
+
PHASE_AROOT="$TMP/phase-project/.kontourai/flow-agents"
|
|
109
|
+
PHASE_SLUG="phase-map-test"
|
|
110
|
+
PHASE_DIR="$PHASE_AROOT/$PHASE_SLUG"
|
|
111
|
+
mkdir -p "$PHASE_AROOT"
|
|
112
|
+
|
|
113
|
+
flow_agents_node "$WRITER" ensure-session \
|
|
114
|
+
--artifact-root "$PHASE_AROOT" \
|
|
115
|
+
--task-slug "$PHASE_SLUG" \
|
|
116
|
+
--title "Phase map test" \
|
|
117
|
+
--summary "Test FlowDefinition phase-map projection without an active Flow run." \
|
|
118
|
+
--timestamp "2026-06-01T00:00:30Z" >/dev/null 2>&1
|
|
119
|
+
|
|
120
|
+
flow_agents_node "$WRITER" init-plan "$PHASE_DIR/$PHASE_SLUG--deliver.md" \
|
|
84
121
|
--source-request "Test" --summary "Testing" \
|
|
85
122
|
--timestamp "2026-06-01T00:00:30Z" >/dev/null 2>&1
|
|
86
123
|
|
|
87
124
|
test_phase_step() {
|
|
88
125
|
local phase="$1" expected_step="$2"
|
|
89
|
-
flow_agents_node "$WRITER" advance-state "$
|
|
126
|
+
flow_agents_node "$WRITER" advance-state "$PHASE_DIR" \
|
|
90
127
|
--status in_progress --phase "$phase" \
|
|
91
128
|
--summary "Testing phase $phase." \
|
|
92
129
|
--next-action "Continue." \
|
|
@@ -95,7 +132,7 @@ test_phase_step() {
|
|
|
95
132
|
local actual
|
|
96
133
|
actual=$(node -e "
|
|
97
134
|
const fs = require('fs');
|
|
98
|
-
const c = JSON.parse(fs.readFileSync('$
|
|
135
|
+
const c = JSON.parse(fs.readFileSync('$PHASE_AROOT/current.json', 'utf8'));
|
|
99
136
|
console.log(c.active_step_id || '');
|
|
100
137
|
" 2>/dev/null)
|
|
101
138
|
if [ "$actual" = "$expected_step" ]; then
|
|
@@ -109,18 +146,95 @@ test_phase_step "planning" "plan"
|
|
|
109
146
|
test_phase_step "execution" "execute"
|
|
110
147
|
test_phase_step "verification" "verify"
|
|
111
148
|
|
|
112
|
-
|
|
149
|
+
node - "$SESSION_DIR" <<'NODE'
|
|
150
|
+
const fs = require('node:fs');
|
|
151
|
+
const path = require('node:path');
|
|
152
|
+
const dir = process.argv[2];
|
|
153
|
+
const slug = path.basename(dir);
|
|
154
|
+
fs.writeFileSync(path.join(dir, `${slug}--plan-work.md`), '# Plan\n\n- AC-1: Verify FlowDefinition producer evidence.\n', 'utf8');
|
|
155
|
+
fs.writeFileSync(path.join(dir, 'acceptance.json'), JSON.stringify({ schema_version: '1.0', task_slug: slug, criteria: [{ id: 'AC-1', description: 'Verify FlowDefinition producer evidence.', status: 'pending', evidence_refs: [] }], goal_fit: { status: 'pending', summary: 'Fixture has not completed Goal Fit review.' } }, null, 2), 'utf8');
|
|
156
|
+
NODE
|
|
157
|
+
mkdir -p "$TMP/main-project/checks"
|
|
158
|
+
cat > "$TMP/main-project/checks/check-flow-step.test.mjs" <<'JS'
|
|
159
|
+
import test from 'node:test';
|
|
160
|
+
import assert from 'node:assert/strict';
|
|
161
|
+
import fs from 'node:fs';
|
|
162
|
+
|
|
163
|
+
test('the canonical Builder run reached verify', () => {
|
|
164
|
+
const state = JSON.parse(fs.readFileSync('.kontourai/flow-agents/activation-test/state.json', 'utf8'));
|
|
165
|
+
assert.equal(state.flow_run?.current_step, 'verify');
|
|
166
|
+
});
|
|
167
|
+
JS
|
|
168
|
+
|
|
169
|
+
record_passing_producer_evidence() {
|
|
170
|
+
local expectation="$1" artifact="$2"
|
|
171
|
+
if FLOW_AGENTS_ACTOR=activation-test-actor node "$ROOT/build/src/cli.js" workflow evidence \
|
|
172
|
+
--session-dir "$SESSION_DIR" \
|
|
173
|
+
--status pass \
|
|
174
|
+
--expectation "$expectation" \
|
|
175
|
+
--summary "Fixture records passing $expectation evidence from its declared durable artifact." \
|
|
176
|
+
--evidence-ref-json "{\"kind\":\"artifact\",\"file\":\"$artifact\",\"summary\":\"Declared durable producer artifact for $expectation.\"}" >/dev/null 2>&1; then
|
|
177
|
+
_pass "public workflow evidence records declared durable producer evidence for $expectation"
|
|
178
|
+
else
|
|
179
|
+
_fail "public workflow evidence did not record declared durable producer evidence for $expectation"
|
|
180
|
+
fi
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
# Satisfy the canonical Flow itself. advance-state above tests phase-map projection;
|
|
184
|
+
# these producer claims advance the persisted Flow run to verify.
|
|
185
|
+
record_passing_producer_evidence "pickup-probe-readiness" "$SESSION_DIR/$SLUG--pull-work.md"
|
|
186
|
+
record_passing_producer_evidence "probe-decisions-or-accepted-gaps" "$SESSION_DIR/$SLUG--pull-work.md"
|
|
187
|
+
record_passing_producer_evidence "implementation-plan" "$SESSION_DIR/$SLUG--plan-work.md"
|
|
188
|
+
record_passing_producer_evidence "implementation-scope" "$SESSION_DIR/$SLUG--deliver.md"
|
|
189
|
+
|
|
190
|
+
# ─── TEST 3: clean critique + complete tests evidence at verify ───────────────
|
|
113
191
|
echo ""
|
|
114
|
-
echo "=== 3. verify step:
|
|
192
|
+
echo "=== 3. verify step: clean critique and criterion-backed producer evidence ==="
|
|
193
|
+
|
|
194
|
+
if FLOW_AGENTS_ACTOR=activation-reviewer node "$ROOT/build/src/cli.js" workflow critique \
|
|
195
|
+
--session-dir "$SESSION_DIR" \
|
|
196
|
+
--id "activation-review" \
|
|
197
|
+
--verdict pass \
|
|
198
|
+
--summary "Fixture review found no open findings before verification." \
|
|
199
|
+
--artifact-ref "$SESSION_DIR/$SLUG--deliver.md" \
|
|
200
|
+
--lane-json "{\"id\":\"code-review\",\"status\":\"pass\",\"summary\":\"Reviewed the delivered activation fixture.\",\"evidence_refs\":[{\"kind\":\"artifact\",\"file\":\"$SESSION_DIR/$SLUG--deliver.md\",\"summary\":\"Reviewed delivery artifact.\"}]}" >/dev/null 2>&1; then
|
|
201
|
+
_pass "public workflow critique records a clean review before passing tests-evidence"
|
|
202
|
+
else
|
|
203
|
+
_fail "public workflow critique did not record a clean review before tests-evidence"
|
|
204
|
+
fi
|
|
115
205
|
|
|
116
|
-
|
|
206
|
+
TEST_COMMAND="node --test checks/check-flow-step.test.mjs"
|
|
207
|
+
CRITERION_JSON="$(node - "$TEST_COMMAND" <<'NODE'
|
|
208
|
+
const command = process.argv[2];
|
|
209
|
+
process.stdout.write(JSON.stringify({
|
|
210
|
+
id: 'AC-1',
|
|
211
|
+
status: 'pass',
|
|
212
|
+
evidence_refs: [{
|
|
213
|
+
kind: 'command',
|
|
214
|
+
excerpt: command,
|
|
215
|
+
summary: 'Asserts the exact session is at the verify Flow step.',
|
|
216
|
+
}],
|
|
217
|
+
}));
|
|
218
|
+
NODE
|
|
219
|
+
)"
|
|
220
|
+
COMMAND_REF="$(node - "$TEST_COMMAND" <<'NODE'
|
|
221
|
+
const command = process.argv[2];
|
|
222
|
+
process.stdout.write(JSON.stringify({ kind: 'command', excerpt: command, summary: 'Runs the project-local verify-step assertion.' }));
|
|
223
|
+
NODE
|
|
224
|
+
)"
|
|
225
|
+
|
|
226
|
+
TEST_EVIDENCE_OUTPUT="$(FLOW_AGENTS_ACTOR=activation-test-actor node "$ROOT/build/src/cli.js" workflow evidence \
|
|
227
|
+
--session-dir "$SESSION_DIR" \
|
|
117
228
|
--status pass \
|
|
118
|
-
--summary "
|
|
229
|
+
--summary "The substantive producer fixture command passed for every declared criterion." \
|
|
119
230
|
--expectation "tests-evidence" \
|
|
120
|
-
--
|
|
121
|
-
|
|
231
|
+
--command "$TEST_COMMAND" \
|
|
232
|
+
--criterion-json "$CRITERION_JSON" \
|
|
233
|
+
--evidence-ref-json "$COMMAND_REF" 2>&1)"
|
|
234
|
+
if [ "$?" -eq 0 ]; then
|
|
235
|
+
_pass "public workflow evidence records passing criterion-backed tests-evidence at verify"
|
|
122
236
|
else
|
|
123
|
-
_fail "record
|
|
237
|
+
_fail "public workflow evidence did not record passing criterion-backed tests-evidence: $TEST_EVIDENCE_OUTPUT"
|
|
124
238
|
fi
|
|
125
239
|
|
|
126
240
|
node -e "
|
|
@@ -128,13 +242,17 @@ const fs = require('fs');
|
|
|
128
242
|
const bundlePath = '$SESSION_DIR/trust.bundle';
|
|
129
243
|
if (!fs.existsSync(bundlePath)) throw new Error('trust.bundle not found');
|
|
130
244
|
const bundle = JSON.parse(fs.readFileSync(bundlePath, 'utf8'));
|
|
131
|
-
const declared = (bundle.claims || []).find(c => c.
|
|
245
|
+
const declared = (bundle.claims || []).find(c => c.metadata?.gate_claim?.expectation_id === 'tests-evidence');
|
|
132
246
|
if (!declared) throw new Error('MISSING builder.verify.tests; claims: ' + (bundle.claims||[]).map(c=>c.claimType).join(', '));
|
|
133
|
-
if (declared.status !== 'verified') throw new Error('expected
|
|
134
|
-
|
|
247
|
+
if (declared.claimType !== 'builder.verify.tests' || declared.status !== 'verified') throw new Error('expected verified builder.verify.tests, got ' + JSON.stringify({ claimType: declared.claimType, status: declared.status }));
|
|
248
|
+
const critique = (bundle.claims || []).find(c => c.metadata?.origin === 'critique' && c.value === 'pass' && !c.metadata?.superseded_by);
|
|
249
|
+
if (!critique) throw new Error('MISSING clean live critique before tests-evidence');
|
|
250
|
+
const criterion = (bundle.claims || []).find(c => c.metadata?.origin === 'acceptance' && c.metadata?.criterion?.id === 'AC-1');
|
|
251
|
+
if (!criterion || criterion.value !== 'pass' || criterion.status !== 'verified') throw new Error('MISSING verified completed AC-1 criterion');
|
|
252
|
+
console.log('builder.verify.tests: subjectType=' + declared.subjectType + ' status=' + declared.status + ' value=' + declared.value + '; clean critique and AC-1 verified');
|
|
135
253
|
" 2>&1 \
|
|
136
|
-
&& _pass "bundle contains
|
|
137
|
-
|| _fail "bundle
|
|
254
|
+
&& _pass "bundle contains declared tests evidence with a clean critique and completed AC-1" \
|
|
255
|
+
|| _fail "bundle lacks declared tests evidence, clean critique, or completed AC-1"
|
|
138
256
|
|
|
139
257
|
# ─── TEST 4: tampered bundle at verify step BLOCKS ────────────────────────────
|
|
140
258
|
echo ""
|
|
@@ -145,10 +263,12 @@ TAMPER_SLUG="tamper-verify-test"
|
|
|
145
263
|
mkdir -p "$TAMPER_DIR"
|
|
146
264
|
printf '# Test repo\n' > "$TAMPER_DIR/AGENTS.md"
|
|
147
265
|
mkdir -p "$TAMPER_DIR/.kontourai/flow-agents/$TAMPER_SLUG"
|
|
266
|
+
printf 'Selected Work Item: local:%s\n' "$TAMPER_SLUG" > "$TAMPER_DIR/.kontourai/flow-agents/$TAMPER_SLUG/$TAMPER_SLUG--pull-work.md"
|
|
148
267
|
|
|
149
268
|
flow_agents_node "$WRITER" ensure-session \
|
|
150
269
|
--artifact-root "$TAMPER_DIR/.kontourai/flow-agents" \
|
|
151
270
|
--task-slug "$TAMPER_SLUG" \
|
|
271
|
+
--actor tamper-verify-actor \
|
|
152
272
|
--title "Tamper verify test" \
|
|
153
273
|
--summary "Testing tamper detection at verify step." \
|
|
154
274
|
--flow-id builder.build \
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# test_flowdef_session_history_preservation.sh — Integration eval for ADR 0016 Step 0.
|
|
3
3
|
#
|
|
4
4
|
# Proves:
|
|
5
|
-
# 1. A FlowDefinition-
|
|
5
|
+
# 1. A noncanonical FlowDefinition-projected session (advance-state, step=verify)
|
|
6
6
|
# records a check via the declared builder.verify.tests path, then record-critique and
|
|
7
7
|
# record-learning PRESERVE the prior declared check + critique claims in the rebuilt
|
|
8
8
|
# bundle (no history loss).
|
|
@@ -34,18 +34,18 @@ WRITER="workflow-sidecar"
|
|
|
34
34
|
echo ""
|
|
35
35
|
echo "=== 1. FlowDefinition-driven session: record-critique/record-learning preserve declared claims ==="
|
|
36
36
|
|
|
37
|
-
FLOW_AROOT="$TMP/flow-
|
|
37
|
+
FLOW_AROOT="$TMP/flow-project/.kontourai/flow-agents"
|
|
38
38
|
SLUG="history-flow-test"
|
|
39
39
|
SESSION_DIR="$FLOW_AROOT/$SLUG"
|
|
40
40
|
mkdir -p "$FLOW_AROOT"
|
|
41
41
|
|
|
42
|
-
#
|
|
42
|
+
# Create a plain sidecar session, then project it onto the verify step. This test covers the
|
|
43
|
+
# generic ADR 0016 sidecar path; canonical Builder runs are covered by the public workflow tests.
|
|
43
44
|
flow_agents_node "$WRITER" ensure-session \
|
|
44
45
|
--artifact-root "$FLOW_AROOT" \
|
|
45
46
|
--task-slug "$SLUG" \
|
|
46
47
|
--title "History preservation test" \
|
|
47
48
|
--summary "Test that declared builder.* claims survive round-trips." \
|
|
48
|
-
--flow-id builder.build \
|
|
49
49
|
--timestamp "2026-06-01T00:00:00Z" >/dev/null 2>&1
|
|
50
50
|
|
|
51
51
|
flow_agents_node "$WRITER" init-plan "$SESSION_DIR/$SLUG--deliver.md" \
|
|
@@ -80,6 +80,8 @@ flow_agents_node "$WRITER" record-critique "$SESSION_DIR" \
|
|
|
80
80
|
--id "code-review" \
|
|
81
81
|
--verdict pass \
|
|
82
82
|
--summary "Code review passed." \
|
|
83
|
+
--lane-json "{\"id\":\"code\",\"status\":\"pass\",\"summary\":\"Code review passed.\",\"evidence_refs\":[{\"kind\":\"artifact\",\"file\":\"$SESSION_DIR/$SLUG--deliver.md\",\"summary\":\"Reviewed the delivery artifact.\"}]}" \
|
|
84
|
+
--artifact-ref "$SESSION_DIR/$SLUG--deliver.md" \
|
|
83
85
|
--timestamp "2026-06-01T00:02:00Z" >/dev/null 2>&1
|
|
84
86
|
|
|
85
87
|
# Assert builder.verify.tests survived the record-critique round-trip
|
|
@@ -93,24 +95,21 @@ console.log('after record-critique: builder.verify.tests status=' + declared.sta
|
|
|
93
95
|
&& _pass "builder.verify.tests declared claim preserved after record-critique (no history loss)" \
|
|
94
96
|
|| _fail "builder.verify.tests declared claim LOST after record-critique (history loss)"
|
|
95
97
|
|
|
96
|
-
# Also verify the critique claim itself is present
|
|
97
|
-
#
|
|
98
|
-
#
|
|
99
|
-
# workflow.critique.review is emitted in no-flow sessions only (P-d: shadow retired).
|
|
98
|
+
# Also verify the critique claim itself is present and remains distinct from optional policy
|
|
99
|
+
# evidence. The Builder runtime consumes metadata.origin=critique directly; a code review must
|
|
100
|
+
# not be relabeled as builder.verify.policy-compliance merely because that expectation is open.
|
|
100
101
|
node -e "
|
|
101
102
|
const fs = require('fs');
|
|
102
103
|
const bundle = JSON.parse(fs.readFileSync('$SESSION_DIR/trust.bundle', 'utf8'));
|
|
103
104
|
const claims = bundle.claims || [];
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (legacy) throw new Error('UNEXPECTED workflow.critique.review in flow-driven session (P-d retired shadow); id=' + legacy.id);
|
|
110
|
-
console.log('declared critique claim: claimType=' + crit.claimType + ' value=' + crit.value);
|
|
105
|
+
const crit = claims.find(c => c.claimType === 'workflow.critique.review' && c.metadata?.origin === 'critique');
|
|
106
|
+
if (!crit) throw new Error('MISSING first-class critique claim after record-critique; claims: ' + claims.map(c=>c.claimType).join(', '));
|
|
107
|
+
const mislabeled = claims.find(c => c.claimType === 'builder.verify.policy-compliance' && c.metadata?.origin === 'critique');
|
|
108
|
+
if (mislabeled) throw new Error('critique was mislabeled as optional policy-compliance evidence: ' + mislabeled.id);
|
|
109
|
+
console.log('critique claim remains distinct: claimType=' + crit.claimType + ' value=' + crit.value);
|
|
111
110
|
" 2>&1 \
|
|
112
|
-
&& _pass "
|
|
113
|
-
|| _fail "
|
|
111
|
+
&& _pass "first-class critique preserved without policy-compliance mislabeling" \
|
|
112
|
+
|| _fail "critique claim missing or mislabeled after record-critique"
|
|
114
113
|
|
|
115
114
|
# Now do record-learning (second round-trip)
|
|
116
115
|
flow_agents_node "$WRITER" record-learning "$SESSION_DIR" \
|
|
@@ -140,7 +139,7 @@ console.log('after record-learning: builder.verify.tests status=' + declared.sta
|
|
|
140
139
|
echo ""
|
|
141
140
|
echo "=== 2. workflow.* session (no --flow-id): round-trip unchanged ==="
|
|
142
141
|
|
|
143
|
-
NOFLOW_AROOT="$TMP/noflow-
|
|
142
|
+
NOFLOW_AROOT="$TMP/noflow-project/.kontourai/flow-agents"
|
|
144
143
|
NOFLOW_SLUG="history-noflow-test"
|
|
145
144
|
NOFLOW_DIR="$NOFLOW_AROOT/$NOFLOW_SLUG"
|
|
146
145
|
mkdir -p "$NOFLOW_AROOT"
|
|
@@ -167,6 +166,8 @@ flow_agents_node "$WRITER" record-critique "$NOFLOW_DIR" \
|
|
|
167
166
|
--id "noflow-review" \
|
|
168
167
|
--verdict pass \
|
|
169
168
|
--summary "Review passed." \
|
|
169
|
+
--lane-json "{\"id\":\"code\",\"status\":\"pass\",\"summary\":\"Review passed.\",\"evidence_refs\":[{\"kind\":\"artifact\",\"file\":\"$NOFLOW_DIR/$NOFLOW_SLUG--deliver.md\",\"summary\":\"Reviewed the delivery artifact.\"}]}" \
|
|
170
|
+
--artifact-ref "$NOFLOW_DIR/$NOFLOW_SLUG--deliver.md" \
|
|
170
171
|
--timestamp "2026-06-01T10:02:00Z" >/dev/null 2>&1
|
|
171
172
|
|
|
172
173
|
# Assert only workflow.* claims survived (no builder.* contamination)
|
|
@@ -189,8 +190,8 @@ console.log('after record-critique: workflow.check.test + workflow.critique.revi
|
|
|
189
190
|
echo ""
|
|
190
191
|
echo "=== 3. evidenceClean/critiqueClean correct for builder.* bundle ==="
|
|
191
192
|
|
|
192
|
-
# Create a fresh
|
|
193
|
-
DOGFOOD_AROOT="$TMP/dogfood-
|
|
193
|
+
# Create a fresh noncanonical FlowDefinition-projected session at verify for dogfood-pass.
|
|
194
|
+
DOGFOOD_AROOT="$TMP/dogfood-project/.kontourai/flow-agents"
|
|
194
195
|
DOGFOOD_SLUG="dogfood-clean-test"
|
|
195
196
|
DOGFOOD_DIR="$DOGFOOD_AROOT/$DOGFOOD_SLUG"
|
|
196
197
|
mkdir -p "$DOGFOOD_AROOT"
|
|
@@ -200,7 +201,6 @@ flow_agents_node "$WRITER" ensure-session \
|
|
|
200
201
|
--task-slug "$DOGFOOD_SLUG" \
|
|
201
202
|
--title "Dogfood clean test" \
|
|
202
203
|
--summary "Test evidenceClean/critiqueClean on builder.build session." \
|
|
203
|
-
--flow-id builder.build \
|
|
204
204
|
--timestamp "2026-06-01T20:00:00Z" >/dev/null 2>&1
|
|
205
205
|
|
|
206
206
|
flow_agents_node "$WRITER" init-plan "$DOGFOOD_DIR/$DOGFOOD_SLUG--deliver.md" \
|
|
@@ -224,6 +224,8 @@ flow_agents_node "$WRITER" record-critique "$DOGFOOD_DIR" \
|
|
|
224
224
|
--id "ev-critique" \
|
|
225
225
|
--verdict pass \
|
|
226
226
|
--summary "Critique passed." \
|
|
227
|
+
--lane-json "{\"id\":\"code\",\"status\":\"pass\",\"summary\":\"Critique passed.\",\"evidence_refs\":[{\"kind\":\"artifact\",\"file\":\"$DOGFOOD_DIR/$DOGFOOD_SLUG--deliver.md\",\"summary\":\"Reviewed the delivery artifact.\"}]}" \
|
|
228
|
+
--artifact-ref "$DOGFOOD_DIR/$DOGFOOD_SLUG--deliver.md" \
|
|
227
229
|
--timestamp "2026-06-01T20:02:00Z" >/dev/null 2>&1
|
|
228
230
|
|
|
229
231
|
# dogfood-pass --verdict pass should succeed: evidenceClean=true (builder.verify.tests passes)
|
|
@@ -1156,16 +1156,14 @@ echo "=== Diff scope check ==="
|
|
|
1156
1156
|
# Verify that ONLY the allowed files were modified.
|
|
1157
1157
|
# Round 2 (fix/gate-lockdown) scope: config-protection.js, stop-goal-fit.js, evidence-capture.js.
|
|
1158
1158
|
# The security-hardening files (config-protection.js, stop-goal-fit.js, workflow-sidecar.ts,
|
|
1159
|
-
# flow-resolver.ts, evidence-capture.js) are legitimately modified across the rounds
|
|
1160
|
-
#
|
|
1159
|
+
# flow-resolver.ts, evidence-capture.js) are legitimately modified across the rounds. This
|
|
1160
|
+
# check protects the cross-kit collision boundary; it must not reject legitimate changes to
|
|
1161
|
+
# Builder skills merely because another issue originally treated them as out of scope.
|
|
1161
1162
|
# Use grep patterns to avoid triggering the source path validator.
|
|
1162
1163
|
FORBIDDEN_MODIFIED=""
|
|
1163
1164
|
FORBIDDEN_PATTERNS=(
|
|
1164
1165
|
"kits/knowledge/"
|
|
1165
1166
|
)
|
|
1166
|
-
# continue-work: the collision boundary skill file (not in scripts/hooks/).
|
|
1167
|
-
# Use a conservative basename check to avoid a false src-path reference.
|
|
1168
|
-
FORBIDDEN_PATTERNS+=("continue-work")
|
|
1169
1167
|
for pat in "${FORBIDDEN_PATTERNS[@]}"; do
|
|
1170
1168
|
if git -C "$ROOT" diff --name-only HEAD 2>/dev/null | grep -q "$pat"; then
|
|
1171
1169
|
FORBIDDEN_MODIFIED="$FORBIDDEN_MODIFIED $pat"
|