@kontourai/flow-agents 1.2.0 → 1.4.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/workflows/ci.yml +6 -1
- package/.github/workflows/kit-gates-demo.yml +6 -2
- package/CHANGELOG.md +33 -0
- package/CONTRIBUTING.md +30 -0
- package/agents/dev.json +1 -1
- package/agents/tool-planner.json +1 -1
- package/build/src/cli/console-learning-projection.d.ts +1 -0
- package/build/src/cli/effective-backlog-settings.d.ts +1 -0
- package/build/src/cli/fixture-retirement-audit.d.ts +2 -0
- package/build/src/cli/init.d.ts +17 -0
- package/build/src/cli/kit.d.ts +1 -0
- package/build/src/cli/promote-workflow-artifact.d.ts +1 -0
- package/build/src/cli/publish-change-helper.d.ts +1 -0
- package/build/src/cli/pull-work-provider.d.ts +1 -0
- package/build/src/cli/runtime-adapter.d.ts +1 -0
- package/build/src/cli/telemetry-doctor.d.ts +1 -0
- package/build/src/cli/usage-feedback.d.ts +1 -0
- package/build/src/cli/utterance-check.d.ts +1 -0
- package/build/src/cli/validate-hook-influence.d.ts +1 -0
- package/build/src/cli/validate-source-tree.d.ts +1 -0
- package/build/src/cli/validate-workflow-artifacts.d.ts +2 -0
- package/build/src/cli/veritas-governance.d.ts +1 -0
- package/build/src/cli/workflow-artifact-cleanup-audit.d.ts +1 -0
- package/build/src/cli/workflow-sidecar.d.ts +32 -0
- package/build/src/cli/workflow-sidecar.js +119 -22
- package/build/src/cli.d.ts +2 -0
- package/build/src/flow-kit/validate.d.ts +81 -0
- package/build/src/flow-kit/validate.js +32 -1
- package/build/src/index.d.ts +5 -0
- package/build/src/index.js +36 -0
- package/build/src/lib/args.d.ts +8 -0
- package/build/src/lib/fs.d.ts +7 -0
- package/build/src/lib/workflow-learning-projection.d.ts +132 -0
- package/build/src/runtime-adapters.d.ts +18 -0
- package/build/src/tools/build-universal-bundles.d.ts +2 -0
- package/build/src/tools/build-universal-bundles.js +14 -0
- package/build/src/tools/common.d.ts +9 -0
- package/build/src/tools/filter-installed-packs.d.ts +2 -0
- package/build/src/tools/generate-context-map.d.ts +2 -0
- package/build/src/tools/validate-package.d.ts +2 -0
- package/build/src/tools/validate-source-tree.d.ts +2 -0
- package/console.telemetry.json +1 -1
- package/docs/adr/0004-gates-expect-surface-claims.md +7 -7
- package/docs/developer-architecture.md +14 -0
- package/docs/kit-authoring-guide.md +99 -6
- package/docs/operating-layers.md +2 -2
- package/docs/spec/runtime-hook-surface.md +16 -1
- package/docs/veritas-integration.md +4 -4
- package/docs/workflow-eval-strategy.md +2 -2
- package/docs/workflow-usage-guide.md +1 -1
- package/evals/acceptance/test_opencode_harness.sh +18 -10
- package/evals/acceptance/test_pi_harness.sh +10 -6
- package/evals/ci/run-baseline.sh +1 -1
- package/evals/fixtures/flow-kit-repository/mixed-runtime-kit/flows/runtime.flow.json +4 -4
- package/evals/fixtures/flow-kit-repository/valid-local-kit/flows/review.flow.json +4 -4
- package/evals/fixtures/kit-conformance-levels/k0-flows-only/flows/review.flow.json +4 -4
- package/evals/fixtures/kit-conformance-levels/k1-agent-extension/flows/build.flow.json +4 -4
- package/evals/fixtures/kit-conformance-levels/k2-with-evals/flows/synthesize.flow.json +4 -4
- package/evals/fixtures/kit-conformance-levels/third-party-extension/flows/review.flow.json +4 -4
- package/evals/fixtures/surface-trust/accepted-claim-trust-report.json +2 -2
- package/evals/fixtures/surface-trust/artifact-absent.json +2 -2
- package/evals/fixtures/surface-trust/integrity-mismatch-trust-report.json +2 -2
- package/evals/fixtures/surface-trust/missing-authority-trust-report.json +2 -2
- package/evals/fixtures/surface-trust/provider-absent.json +2 -2
- package/evals/fixtures/surface-trust/rejected-claim-trust-report.json +2 -2
- package/evals/fixtures/surface-trust/stale-claim-trust-snapshot.json +2 -2
- package/evals/integration/test_console_learning_projection.sh +1 -1
- package/evals/integration/test_goal_fit_hook.sh +144 -0
- package/evals/integration/test_hook_category_behaviors.sh +14 -0
- package/evals/integration/test_kit_conformance_levels.sh +55 -1
- package/evals/integration/test_workflow_sidecar_writer.sh +9 -9
- package/evals/run.sh +2 -0
- package/evals/static/test_library_exports.sh +85 -0
- package/evals/static/test_package.sh +3 -3
- package/evals/static/test_universal_bundles.sh +15 -0
- package/evals/static/test_workflow_skills.sh +4 -4
- package/kits/builder/flows/build.flow.json +48 -48
- package/kits/builder/flows/shape.flow.json +36 -36
- package/kits/knowledge/adapters/obsidian-store/index.js +137 -26
- package/kits/knowledge/evals/contract-suite/suite.test.js +90 -0
- package/kits/knowledge/flows/compile.flow.json +12 -12
- package/kits/knowledge/flows/consolidate.flow.json +16 -16
- package/kits/knowledge/flows/ingest.flow.json +12 -12
- package/kits/knowledge/flows/retire.flow.json +16 -16
- package/kits/knowledge/flows/store-contract.flow.json +12 -12
- package/kits/knowledge/flows/synthesize.flow.json +16 -16
- package/kits/release-evidence/flows/release-evidence.flow.json +3 -3
- package/package.json +14 -2
- package/schemas/workflow-evidence.schema.json +2 -1
- package/scripts/hooks/stop-goal-fit.js +66 -18
- package/src/cli/workflow-sidecar.ts +101 -21
- package/src/flow-kit/validate.ts +55 -1
- package/src/index.ts +53 -0
- package/src/tools/build-universal-bundles.ts +14 -0
- package/tsconfig.json +1 -0
|
@@ -164,7 +164,7 @@ run_inspect "$ROOT/kits/builder" "$out" || true
|
|
|
164
164
|
if node -e "
|
|
165
165
|
const d = require('fs').readFileSync('$out', 'utf8');
|
|
166
166
|
const r = JSON.parse(d);
|
|
167
|
-
const required = ['kit_id','kit_name','conformance','targets','third_party_extensions'];
|
|
167
|
+
const required = ['kit_id','kit_name','conformance','targets','third_party_extensions','trust'];
|
|
168
168
|
for (const k of required) {
|
|
169
169
|
if (!(k in r)) throw new Error('missing key: ' + k);
|
|
170
170
|
}
|
|
@@ -199,6 +199,60 @@ else
|
|
|
199
199
|
cat "$out"
|
|
200
200
|
fi
|
|
201
201
|
|
|
202
|
+
# ===================================================================
|
|
203
|
+
echo ""
|
|
204
|
+
echo "=== 8. Trust axis: first-party allowlist (builder and knowledge) ==="
|
|
205
|
+
# ===================================================================
|
|
206
|
+
|
|
207
|
+
for kit_name in builder knowledge; do
|
|
208
|
+
out="$TMP_DIR/trust-${kit_name}.out"
|
|
209
|
+
run_inspect "$ROOT/kits/$kit_name" "$out" || true
|
|
210
|
+
trust=$(node -e "const d=require('fs').readFileSync('$out','utf8'); console.log(JSON.parse(d).trust)" 2>/dev/null)
|
|
211
|
+
if [[ "$trust" == "first-party" ]]; then
|
|
212
|
+
pass "$kit_name kit trust: first-party (in Kontour allowlist)"
|
|
213
|
+
else
|
|
214
|
+
fail "$kit_name kit trust: expected first-party, got '$trust'"
|
|
215
|
+
cat "$out"
|
|
216
|
+
fi
|
|
217
|
+
done
|
|
218
|
+
|
|
219
|
+
# ===================================================================
|
|
220
|
+
echo ""
|
|
221
|
+
echo "=== 9. Trust axis: unverified for third-party and fixture kits ==="
|
|
222
|
+
# ===================================================================
|
|
223
|
+
|
|
224
|
+
for fixture in k0-flows-only k1-agent-extension k2-with-evals third-party-extension; do
|
|
225
|
+
out="$TMP_DIR/trust-${fixture}.out"
|
|
226
|
+
run_inspect "$ROOT/evals/fixtures/kit-conformance-levels/$fixture" "$out" || true
|
|
227
|
+
trust=$(node -e "const d=require('fs').readFileSync('$out','utf8'); console.log(JSON.parse(d).trust)" 2>/dev/null)
|
|
228
|
+
if [[ "$trust" == "unverified" ]]; then
|
|
229
|
+
pass "$fixture fixture trust: unverified (not in first-party allowlist)"
|
|
230
|
+
else
|
|
231
|
+
fail "$fixture fixture trust: expected unverified, got '$trust'"
|
|
232
|
+
cat "$out"
|
|
233
|
+
fi
|
|
234
|
+
done
|
|
235
|
+
|
|
236
|
+
# ===================================================================
|
|
237
|
+
echo ""
|
|
238
|
+
echo "=== 10. Trust field present in inspect JSON schema ==="
|
|
239
|
+
# ===================================================================
|
|
240
|
+
|
|
241
|
+
out="$TMP_DIR/trust-schema.out"
|
|
242
|
+
run_inspect "$ROOT/kits/builder" "$out" || true
|
|
243
|
+
if node -e "
|
|
244
|
+
const d = require('fs').readFileSync('$out', 'utf8');
|
|
245
|
+
const r = JSON.parse(d);
|
|
246
|
+
if (!('trust' in r)) throw new Error('missing key: trust');
|
|
247
|
+
const valid = ['first-party', 'verified', 'unverified'];
|
|
248
|
+
if (!valid.includes(r.trust)) throw new Error('trust must be one of: ' + valid.join(', ') + '; got: ' + r.trust);
|
|
249
|
+
" 2>/dev/null; then
|
|
250
|
+
pass "inspect JSON output includes trust field with valid value"
|
|
251
|
+
else
|
|
252
|
+
fail "inspect JSON output is missing trust field or has invalid value"
|
|
253
|
+
cat "$out"
|
|
254
|
+
fi
|
|
255
|
+
|
|
202
256
|
# ===================================================================
|
|
203
257
|
echo ""
|
|
204
258
|
if [[ "$errors" -eq 0 ]]; then
|
|
@@ -544,22 +544,22 @@ else
|
|
|
544
544
|
_fail "existing invalid acceptance ref rejection was not fail-closed: $(cat "$TMPDIR_EVAL/invalid-acceptance-ref.out" "$TMPDIR_EVAL/invalid-acceptance-ref.err")"
|
|
545
545
|
fi
|
|
546
546
|
|
|
547
|
-
SURFACE_CHECK='{"id":"surface-trust-fixture","kind":"policy","status":"pass","summary":"
|
|
547
|
+
SURFACE_CHECK='{"id":"surface-trust-fixture","kind":"policy","status":"pass","summary":"Hachure trust.bundle evidence passed.","surface_trust_refs":[{"artifact_kind":"trust.bundle","artifact_ref":"trust/report.json","gate_id":"builder.trust.bundle","claim_type":"builder.trust.bundle","claim_status":"accepted","subject":"builder-kit","freshness":{"status":"fresh","summary":"Issued during this workflow."},"authority":{"producer":"surface-local","summary":"Local Surface trust producer."},"integrity":{"status":"matched","summary":"Artifact digest matched expected subject and gate.","digest":"sha256:abc123"},"status":"pass","summary":"Accepted trust.bundle claim."}]}'
|
|
548
548
|
if flow_agents_node "$WRITER" record-evidence "$ARTIFACT_DIR" \
|
|
549
549
|
--verdict pass \
|
|
550
550
|
--check-json "$SURFACE_CHECK" \
|
|
551
551
|
--timestamp "2026-05-09T00:01:05Z" >"$TMPDIR_EVAL/surface-evidence.out" 2>"$TMPDIR_EVAL/surface-evidence.err" \
|
|
552
552
|
&& rg -q '"surface_trust_refs"' "$ARTIFACT_DIR/evidence.json" \
|
|
553
|
-
&& rg -q '"artifact_kind": "
|
|
553
|
+
&& rg -q '"artifact_kind": "trust.bundle"' "$ARTIFACT_DIR/evidence.json" \
|
|
554
554
|
&& ! rg -q 'veritas' "$ARTIFACT_DIR/evidence.json"; then
|
|
555
|
-
_pass "sidecar writer records
|
|
555
|
+
_pass "sidecar writer records Hachure-aligned trust.bundle refs"
|
|
556
556
|
else
|
|
557
|
-
_fail "sidecar writer did not record
|
|
557
|
+
_fail "sidecar writer did not record Hachure-aligned trust.bundle refs: $(cat "$TMPDIR_EVAL/surface-evidence.out" "$TMPDIR_EVAL/surface-evidence.err")"
|
|
558
558
|
fi
|
|
559
559
|
|
|
560
560
|
if flow_agents_node "$WRITER" record-evidence "$ARTIFACT_DIR" \
|
|
561
561
|
--verdict pass \
|
|
562
|
-
--check-json '{"id":"surface-trust-native-field","kind":"policy","status":"pass","summary":"Should fail.","surface_trust_refs":[{"artifact_kind":"
|
|
562
|
+
--check-json '{"id":"surface-trust-native-field","kind":"policy","status":"pass","summary":"Should fail.","surface_trust_refs":[{"artifact_kind":"trust.bundle","artifact_ref":"trust/snapshot.json","gate_id":"builder.trust.bundle","claim_type":"builder.trust.bundle","claim_status":"accepted","subject":"builder-kit","freshness":{"status":"fresh","summary":"Fresh."},"authority":{"producer":"surface-local","summary":"Producer exists.","veritas_policy":"native-field"},"integrity":{"status":"matched","summary":"Matched."},"status":"pass"}]}' >"$TMPDIR_EVAL/surface-invalid.out" 2>&1; then
|
|
563
563
|
_fail "sidecar writer should reject provider-specific Surface trust fields"
|
|
564
564
|
elif rg -q 'unsupported field' "$TMPDIR_EVAL/surface-invalid.out"; then
|
|
565
565
|
_pass "sidecar writer rejects provider-specific Surface trust fields"
|
|
@@ -581,10 +581,10 @@ check_contradictory_surface_ref() {
|
|
|
581
581
|
fi
|
|
582
582
|
}
|
|
583
583
|
|
|
584
|
-
check_contradictory_surface_ref "rejected-pass" '{"artifact_kind":"
|
|
585
|
-
check_contradictory_surface_ref "stale-pass" '{"artifact_kind":"
|
|
586
|
-
check_contradictory_surface_ref "missing-authority-pass" '{"artifact_kind":"
|
|
587
|
-
check_contradictory_surface_ref "integrity-mismatch-pass" '{"artifact_kind":"
|
|
584
|
+
check_contradictory_surface_ref "rejected-pass" '{"artifact_kind":"trust.bundle","artifact_ref":"trust/report.json","gate_id":"builder.trust.bundle","claim_type":"builder.trust.bundle","claim_status":"rejected","subject":"builder-kit","freshness":{"status":"fresh","summary":"Fresh."},"authority":{"producer":"surface-local","summary":"Producer exists."},"integrity":{"status":"matched","summary":"Matched."},"status":"pass"}'
|
|
585
|
+
check_contradictory_surface_ref "stale-pass" '{"artifact_kind":"trust.bundle","artifact_ref":"trust/report.json","gate_id":"builder.trust.bundle","claim_type":"builder.trust.bundle","claim_status":"accepted","subject":"builder-kit","freshness":{"status":"stale","summary":"Stale."},"authority":{"producer":"surface-local","summary":"Producer exists."},"integrity":{"status":"matched","summary":"Matched."},"status":"pass"}'
|
|
586
|
+
check_contradictory_surface_ref "missing-authority-pass" '{"artifact_kind":"trust.bundle","artifact_ref":"trust/report.json","gate_id":"builder.trust.bundle","claim_type":"builder.trust.bundle","claim_status":"accepted","subject":"builder-kit","freshness":{"status":"fresh","summary":"Fresh."},"authority":{"producer":"unknown","summary":"Producer missing."},"integrity":{"status":"matched","summary":"Matched."},"status":"pass"}'
|
|
587
|
+
check_contradictory_surface_ref "integrity-mismatch-pass" '{"artifact_kind":"trust.bundle","artifact_ref":"trust/report.json","gate_id":"builder.trust.bundle","claim_type":"builder.trust.bundle","claim_status":"accepted","subject":"builder-kit","freshness":{"status":"fresh","summary":"Fresh."},"authority":{"producer":"surface-local","summary":"Producer exists."},"integrity":{"status":"mismatch","summary":"Mismatch."},"status":"pass"}'
|
|
588
588
|
|
|
589
589
|
SURFACE_FIXTURE_DIR="$ROOT/evals/fixtures/surface-trust"
|
|
590
590
|
check_surface_fixture() {
|
package/evals/run.sh
CHANGED
|
@@ -135,6 +135,8 @@ run_static() {
|
|
|
135
135
|
echo ""
|
|
136
136
|
bash "$EVAL_DIR/static/test_evidence_refs.sh" || result=1
|
|
137
137
|
echo ""
|
|
138
|
+
bash "$EVAL_DIR/static/test_library_exports.sh" || result=1
|
|
139
|
+
echo ""
|
|
138
140
|
bash "$EVAL_DIR/static/test_console_presets.sh" || result=1
|
|
139
141
|
echo ""
|
|
140
142
|
bash "$EVAL_DIR/static/test_repo_hooks.sh" || result=1
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# test_library_exports.sh — the package exposes the canonical workflow-sidecar
|
|
3
|
+
# writer/validator as an importable library (issue #99). Guards three things:
|
|
4
|
+
# 1. package.json declares the library entry points (exports/main/types).
|
|
5
|
+
# 2. importing the entry point does NOT execute the CLI (entry guard holds).
|
|
6
|
+
# 3. the CLI still runs when invoked directly (entry guard regression).
|
|
7
|
+
set -uo pipefail
|
|
8
|
+
|
|
9
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
10
|
+
source "$ROOT/evals/lib/node.sh"
|
|
11
|
+
cd "$ROOT"
|
|
12
|
+
|
|
13
|
+
errors=0
|
|
14
|
+
pass() { echo " ✓ $1"; }
|
|
15
|
+
fail() { echo " ✗ $1"; errors=$((errors + 1)); }
|
|
16
|
+
|
|
17
|
+
echo "=== Library Export Surface (#99) ==="
|
|
18
|
+
|
|
19
|
+
# Ensure the build exists (cheap no-op if already built).
|
|
20
|
+
flow_agents_node node_modules/typescript/bin/tsc -p tsconfig.json >/dev/null 2>&1 || npm run build --silent >/dev/null 2>&1 || true
|
|
21
|
+
|
|
22
|
+
# 1. package.json entry points
|
|
23
|
+
if node -e '
|
|
24
|
+
const p = require("./package.json");
|
|
25
|
+
const fail = (m) => { console.error(m); process.exit(1); };
|
|
26
|
+
if (p.main !== "build/src/index.js") fail("main must be build/src/index.js");
|
|
27
|
+
if (p.types !== "build/src/index.d.ts") fail("types must be build/src/index.d.ts");
|
|
28
|
+
if (!p.exports || !p.exports["."]) fail("exports must define the root entry");
|
|
29
|
+
const root = p.exports["."];
|
|
30
|
+
if (root.import !== "./build/src/index.js") fail("exports[.].import must be ./build/src/index.js");
|
|
31
|
+
if (root.types !== "./build/src/index.d.ts") fail("exports[.].types must be ./build/src/index.d.ts");
|
|
32
|
+
' 2>/tmp/lib-exports-pkg.err; then
|
|
33
|
+
pass "package.json declares library entry points (main/types/exports)"
|
|
34
|
+
else
|
|
35
|
+
fail "package.json library entry points missing or wrong: $(cat /tmp/lib-exports-pkg.err)"
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# 2. built artifacts present
|
|
39
|
+
if [[ -f "build/src/index.js" && -f "build/src/index.d.ts" ]]; then
|
|
40
|
+
pass "build emits index.js and index.d.ts"
|
|
41
|
+
else
|
|
42
|
+
fail "build is missing index.js or index.d.ts (run npm run build)"
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# 3. importing the library does not run the CLI, and the public API is present.
|
|
46
|
+
# If importing executed the CLI it would call process.exit before our marker prints.
|
|
47
|
+
if node --input-type=module -e '
|
|
48
|
+
import * as lib from "./build/src/index.js";
|
|
49
|
+
const required = [
|
|
50
|
+
"validateTrustBundle", "normalizeCheck", "normalizeFinding", "normalizeLearning",
|
|
51
|
+
"normalizeEvidenceRefs", "validateEvidenceRef", "validateLearningCorrection",
|
|
52
|
+
"loadJson", "writeJson", "appendJsonl", "sidecarBase", "writeState",
|
|
53
|
+
"readSidecar", "writeSidecar",
|
|
54
|
+
"statuses", "phases", "checkKinds", "checkStatuses", "verdicts",
|
|
55
|
+
];
|
|
56
|
+
const missing = required.filter((name) => lib[name] === undefined);
|
|
57
|
+
if (missing.length) { console.error("missing exports: " + missing.join(", ")); process.exit(1); }
|
|
58
|
+
// Exercise a validator to prove it is the real implementation, not a stub.
|
|
59
|
+
let threw = false;
|
|
60
|
+
try { lib.normalizeCheck({ id: "x" }); } catch { threw = true; }
|
|
61
|
+
if (!threw) { console.error("normalizeCheck should reject an invalid check"); process.exit(1); }
|
|
62
|
+
const ok = lib.normalizeCheck({ id: "b", kind: "test", status: "pass", summary: "ok" });
|
|
63
|
+
if (ok.id !== "b") { console.error("normalizeCheck should return the normalized check"); process.exit(1); }
|
|
64
|
+
console.log("LIBRARY_IMPORT_OK");
|
|
65
|
+
' 2>/dev/null | grep -q "LIBRARY_IMPORT_OK"; then
|
|
66
|
+
pass "importing the library exposes the public API without running the CLI"
|
|
67
|
+
else
|
|
68
|
+
fail "library import failed, ran the CLI, or is missing public exports"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# 4. the CLI still runs when invoked directly (entry guard regression guard).
|
|
72
|
+
# A missing required flag must produce the CLI's own validation error, proving main() ran.
|
|
73
|
+
cli_out="$(node build/src/cli/workflow-sidecar.js ensure-session --artifact-root /tmp/nonexistent-lib-test 2>&1 || true)"
|
|
74
|
+
if echo "$cli_out" | grep -q "task-slug is required"; then
|
|
75
|
+
pass "CLI entry still executes when run directly"
|
|
76
|
+
else
|
|
77
|
+
fail "CLI entry did not run as a script (entry guard regression): $cli_out"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
echo ""
|
|
81
|
+
if [[ "$errors" -gt 0 ]]; then
|
|
82
|
+
echo "Library export checks failed: $errors issue(s)."
|
|
83
|
+
exit 1
|
|
84
|
+
fi
|
|
85
|
+
echo "Library export checks passed."
|
|
@@ -211,8 +211,8 @@ for (const gateId of ["verify-gate", "merge-ready-gate"]) {
|
|
|
211
211
|
const expectations = Object.values(flow.gates || {}).flatMap((gate) => gate.expects || []);
|
|
212
212
|
if (!expectations.length) throw new Error("Builder build flow should declare gate expectations");
|
|
213
213
|
for (const expectation of expectations) {
|
|
214
|
-
if (expectation.kind !== "
|
|
215
|
-
if (!expectation.
|
|
214
|
+
if (expectation.kind !== "trust.bundle") throw new Error(`${expectation.id || "<unknown>"} should remain a trust.bundle expectation`);
|
|
215
|
+
if (!expectation.bundle_claim?.claimType || !expectation.bundle_claim?.accepted_statuses) throw new Error(`${expectation.id || "<unknown>"} should declare bundle_claim claimType and accepted statuses`);
|
|
216
216
|
}
|
|
217
217
|
const flowText = JSON.stringify(flow).toLowerCase();
|
|
218
218
|
for (const term of ["veritas", "trust_provider", "trust-provider", "provider_name", "provider_ref", "veritas_policy", "veritas_readiness"]) {
|
|
@@ -221,7 +221,7 @@ for (const term of ["veritas", "trust_provider", "trust-provider", "provider_nam
|
|
|
221
221
|
console.log("ok");
|
|
222
222
|
NODE
|
|
223
223
|
then
|
|
224
|
-
_pass "installed Builder Kit build flow keeps provider-neutral
|
|
224
|
+
_pass "installed Builder Kit build flow keeps provider-neutral trust.bundle gates"
|
|
225
225
|
else
|
|
226
226
|
_fail "installed Builder Kit build flow route-back or provider-neutral gate policy missing or wrong"
|
|
227
227
|
fi
|
|
@@ -411,6 +411,21 @@ else
|
|
|
411
411
|
_fail "catalog metadata check failed"
|
|
412
412
|
fi
|
|
413
413
|
|
|
414
|
+
# Block Reason Channel (#100): the generated opencode/pi adapters must carry the
|
|
415
|
+
# policy reason into their block path so the model learns why it was blocked.
|
|
416
|
+
# claude/codex deny translation is covered in test_hook_category_behaviors.sh.
|
|
417
|
+
BUILDER_SRC="$ROOT_DIR/src/tools/build-universal-bundles.ts"
|
|
418
|
+
if grep -q "throw new Error(policyResult.reason" "$BUILDER_SRC"; then
|
|
419
|
+
_pass "opencode adapter surfaces the block reason to the model (thrown error)"
|
|
420
|
+
else
|
|
421
|
+
_fail "opencode adapter block path dropped the policy reason"
|
|
422
|
+
fi
|
|
423
|
+
if grep -q "reason: result.reason" "$BUILDER_SRC"; then
|
|
424
|
+
_pass "pi adapter surfaces the block reason to the model (block result reason)"
|
|
425
|
+
else
|
|
426
|
+
_fail "pi adapter block path dropped the policy reason"
|
|
427
|
+
fi
|
|
428
|
+
|
|
414
429
|
echo ""
|
|
415
430
|
echo "==========================="
|
|
416
431
|
total=$((pass + fail))
|
|
@@ -1075,17 +1075,17 @@ const flow = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
|
|
|
1075
1075
|
const expectations = Object.values(flow.gates || {}).flatMap((gate) => gate.expects || []);
|
|
1076
1076
|
if (!expectations.length) throw new Error("no Builder Kit gate expectations found");
|
|
1077
1077
|
for (const expectation of expectations) {
|
|
1078
|
-
if (expectation.kind !== "
|
|
1079
|
-
if (!expectation.
|
|
1078
|
+
if (expectation.kind !== "trust.bundle") throw new Error(`${expectation.id || "<unknown>"} is not a trust.bundle expectation`);
|
|
1079
|
+
if (!expectation.bundle_claim?.claimType || !expectation.bundle_claim?.accepted_statuses) throw new Error(`${expectation.id || "<unknown>"} is missing bundle_claim claimType or accepted statuses`);
|
|
1080
1080
|
}
|
|
1081
1081
|
const flowText = JSON.stringify(flow).toLowerCase();
|
|
1082
1082
|
for (const term of ["veritas", "trust_provider", "trust-provider", "provider_name", "provider_ref", "veritas_policy", "veritas_readiness"]) {
|
|
1083
1083
|
if (flowText.includes(term)) throw new Error(`provider-specific trust field leaked into Builder Kit build flow: ${term}`);
|
|
1084
1084
|
}
|
|
1085
1085
|
NODE
|
|
1086
|
-
pass "Builder build flow keeps provider-neutral
|
|
1086
|
+
pass "Builder build flow keeps provider-neutral trust.bundle expectations"
|
|
1087
1087
|
else
|
|
1088
|
-
fail "Builder build flow keeps provider-neutral
|
|
1088
|
+
fail "Builder build flow keeps provider-neutral trust.bundle expectations"
|
|
1089
1089
|
fi
|
|
1090
1090
|
require_text "$MAP" 'pull-work' "map includes pull-work"
|
|
1091
1091
|
require_text "$MAP" 'pickup Probe before planning' "map documents pickup Probe before planning"
|
|
@@ -19,12 +19,12 @@
|
|
|
19
19
|
"expects": [
|
|
20
20
|
{
|
|
21
21
|
"id": "selected-work",
|
|
22
|
-
"kind": "
|
|
22
|
+
"kind": "trust.bundle",
|
|
23
23
|
"required": true,
|
|
24
24
|
"description": "A ready work item is selected with scope and acceptance context.",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
25
|
+
"bundle_claim": {
|
|
26
|
+
"claimType": "builder.pull-work.selected",
|
|
27
|
+
"subjectType": "work-item",
|
|
28
28
|
"accepted_statuses": ["trusted", "accepted"]
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -35,23 +35,23 @@
|
|
|
35
35
|
"expects": [
|
|
36
36
|
{
|
|
37
37
|
"id": "pickup-probe-readiness",
|
|
38
|
-
"kind": "
|
|
38
|
+
"kind": "trust.bundle",
|
|
39
39
|
"required": true,
|
|
40
40
|
"description": "Pickup Probe evidence is recorded before planning: goal fit and scope, blockers and dependencies, dependency freshness, acceptance criteria quality, provider state, risk, stop-short risks, planning readiness, decisions, unresolved questions, accepted gaps, probe_status, probe_artifact_ref, grouping decision, expected modified files, and conflict risks.",
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
41
|
+
"bundle_claim": {
|
|
42
|
+
"claimType": "builder.design-probe.pickup-readiness",
|
|
43
|
+
"subjectType": "work-item",
|
|
44
44
|
"accepted_statuses": ["trusted", "accepted"]
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"id": "probe-decisions-or-accepted-gaps",
|
|
49
|
-
"kind": "
|
|
49
|
+
"kind": "trust.bundle",
|
|
50
50
|
"required": true,
|
|
51
51
|
"description": "Planning is blocked until pickup Probe decisions are captured in the pull-work or plan handoff artifact, or unresolved questions are explicitly recorded as accepted gaps. Stale broad continuation language after a merge is not sufficient for planning newly selected work.",
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
52
|
+
"bundle_claim": {
|
|
53
|
+
"claimType": "builder.design-probe.decisions",
|
|
54
|
+
"subjectType": "decision",
|
|
55
55
|
"accepted_statuses": ["trusted", "accepted"]
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -62,12 +62,12 @@
|
|
|
62
62
|
"expects": [
|
|
63
63
|
{
|
|
64
64
|
"id": "implementation-plan",
|
|
65
|
-
"kind": "
|
|
65
|
+
"kind": "trust.bundle",
|
|
66
66
|
"required": true,
|
|
67
67
|
"description": "The implementation plan names files, changes, acceptance evidence, and sequencing.",
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
68
|
+
"bundle_claim": {
|
|
69
|
+
"claimType": "builder.plan.implementation",
|
|
70
|
+
"subjectType": "artifact",
|
|
71
71
|
"accepted_statuses": ["trusted", "accepted"]
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -78,12 +78,12 @@
|
|
|
78
78
|
"expects": [
|
|
79
79
|
{
|
|
80
80
|
"id": "implementation-scope",
|
|
81
|
-
"kind": "
|
|
81
|
+
"kind": "trust.bundle",
|
|
82
82
|
"required": true,
|
|
83
83
|
"description": "The implementation scope records changed files and excludes unrelated work.",
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
84
|
+
"bundle_claim": {
|
|
85
|
+
"claimType": "builder.execute.scope",
|
|
86
|
+
"subjectType": "change",
|
|
87
87
|
"accepted_statuses": ["trusted", "accepted"]
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -105,24 +105,24 @@
|
|
|
105
105
|
"expects": [
|
|
106
106
|
{
|
|
107
107
|
"id": "tests-evidence",
|
|
108
|
-
"kind": "
|
|
108
|
+
"kind": "trust.bundle",
|
|
109
109
|
"required": true,
|
|
110
110
|
"description": "Relevant tests or checks have evidence tied to the implemented change.",
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
"
|
|
111
|
+
"bundle_claim": {
|
|
112
|
+
"claimType": "builder.verify.tests",
|
|
113
|
+
"subjectType": "flow-step",
|
|
114
114
|
"accepted_statuses": ["trusted", "accepted"]
|
|
115
115
|
}
|
|
116
116
|
},
|
|
117
117
|
{
|
|
118
118
|
"id": "policy-compliance",
|
|
119
|
-
"kind": "
|
|
119
|
+
"kind": "trust.bundle",
|
|
120
120
|
"required": false,
|
|
121
121
|
"description": "Policy compliance evidence is attached when policy gates apply.",
|
|
122
122
|
"explore_hint": "Use as advisory evidence for scope, security, privacy, release, or repository policy checks.",
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
"
|
|
123
|
+
"bundle_claim": {
|
|
124
|
+
"claimType": "builder.verify.policy-compliance",
|
|
125
|
+
"subjectType": "artifact",
|
|
126
126
|
"accepted_statuses": ["trusted", "accepted", "advisory"]
|
|
127
127
|
}
|
|
128
128
|
}
|
|
@@ -144,12 +144,12 @@
|
|
|
144
144
|
"expects": [
|
|
145
145
|
{
|
|
146
146
|
"id": "merge-readiness",
|
|
147
|
-
"kind": "
|
|
147
|
+
"kind": "trust.bundle",
|
|
148
148
|
"required": true,
|
|
149
149
|
"description": "The change is ready for merge review based on scope, evidence, and unresolved risks.",
|
|
150
|
-
"
|
|
151
|
-
"
|
|
152
|
-
"
|
|
150
|
+
"bundle_claim": {
|
|
151
|
+
"claimType": "builder.merge-ready.readiness",
|
|
152
|
+
"subjectType": "change",
|
|
153
153
|
"accepted_statuses": ["trusted", "accepted"]
|
|
154
154
|
}
|
|
155
155
|
}
|
|
@@ -160,12 +160,12 @@
|
|
|
160
160
|
"expects": [
|
|
161
161
|
{
|
|
162
162
|
"id": "pull-request-opened",
|
|
163
|
-
"kind": "
|
|
163
|
+
"kind": "trust.bundle",
|
|
164
164
|
"required": true,
|
|
165
165
|
"description": "A pull request exists with linked work, implementation summary, and verification evidence.",
|
|
166
|
-
"
|
|
167
|
-
"
|
|
168
|
-
"
|
|
166
|
+
"bundle_claim": {
|
|
167
|
+
"claimType": "builder.pr-open.pull-request",
|
|
168
|
+
"subjectType": "pull-request",
|
|
169
169
|
"accepted_statuses": ["trusted", "accepted"]
|
|
170
170
|
}
|
|
171
171
|
}
|
|
@@ -176,12 +176,12 @@
|
|
|
176
176
|
"expects": [
|
|
177
177
|
{
|
|
178
178
|
"id": "ci-merge-readiness",
|
|
179
|
-
"kind": "
|
|
179
|
+
"kind": "trust.bundle",
|
|
180
180
|
"required": true,
|
|
181
181
|
"description": "CI and review status support a merge-ready decision.",
|
|
182
|
-
"
|
|
183
|
-
"
|
|
184
|
-
"
|
|
182
|
+
"bundle_claim": {
|
|
183
|
+
"claimType": "builder.merge-ready-ci.readiness",
|
|
184
|
+
"subjectType": "pull-request",
|
|
185
185
|
"accepted_statuses": ["trusted", "accepted"]
|
|
186
186
|
}
|
|
187
187
|
}
|
|
@@ -192,23 +192,23 @@
|
|
|
192
192
|
"expects": [
|
|
193
193
|
{
|
|
194
194
|
"id": "decision-evidence",
|
|
195
|
-
"kind": "
|
|
195
|
+
"kind": "trust.bundle",
|
|
196
196
|
"required": true,
|
|
197
197
|
"description": "Durable decision evidence from the build is recorded.",
|
|
198
|
-
"
|
|
199
|
-
"
|
|
200
|
-
"
|
|
198
|
+
"bundle_claim": {
|
|
199
|
+
"claimType": "builder.learn.decisions",
|
|
200
|
+
"subjectType": "decision",
|
|
201
201
|
"accepted_statuses": ["trusted", "accepted"]
|
|
202
202
|
}
|
|
203
203
|
},
|
|
204
204
|
{
|
|
205
205
|
"id": "learning-evidence",
|
|
206
|
-
"kind": "
|
|
206
|
+
"kind": "trust.bundle",
|
|
207
207
|
"required": true,
|
|
208
208
|
"description": "Learning evidence from delivery is recorded for future work.",
|
|
209
|
-
"
|
|
210
|
-
"
|
|
211
|
-
"
|
|
209
|
+
"bundle_claim": {
|
|
210
|
+
"claimType": "builder.learn.evidence",
|
|
211
|
+
"subjectType": "release",
|
|
212
212
|
"accepted_statuses": ["trusted", "accepted"]
|
|
213
213
|
}
|
|
214
214
|
}
|
|
@@ -13,79 +13,79 @@
|
|
|
13
13
|
"expects": [
|
|
14
14
|
{
|
|
15
15
|
"id": "shaped-problem",
|
|
16
|
-
"kind": "
|
|
16
|
+
"kind": "trust.bundle",
|
|
17
17
|
"required": true,
|
|
18
18
|
"description": "The problem is stated in terms a builder can act on.",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
19
|
+
"bundle_claim": {
|
|
20
|
+
"claimType": "builder.shape.problem",
|
|
21
|
+
"subjectType": "decision",
|
|
22
22
|
"accepted_statuses": ["trusted", "accepted"]
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"id": "shaped-outcome",
|
|
27
|
-
"kind": "
|
|
27
|
+
"kind": "trust.bundle",
|
|
28
28
|
"required": true,
|
|
29
29
|
"description": "The intended outcome is explicit enough to evaluate later.",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
30
|
+
"bundle_claim": {
|
|
31
|
+
"claimType": "builder.shape.outcome",
|
|
32
|
+
"subjectType": "flow-run",
|
|
33
33
|
"accepted_statuses": ["trusted", "accepted"]
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"id": "shaped-constraints",
|
|
38
|
-
"kind": "
|
|
38
|
+
"kind": "trust.bundle",
|
|
39
39
|
"required": true,
|
|
40
40
|
"description": "Constraints that affect implementation are captured.",
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
41
|
+
"bundle_claim": {
|
|
42
|
+
"claimType": "builder.shape.constraints",
|
|
43
|
+
"subjectType": "decision",
|
|
44
44
|
"accepted_statuses": ["trusted", "accepted"]
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"id": "shaped-non-goals",
|
|
49
|
-
"kind": "
|
|
49
|
+
"kind": "trust.bundle",
|
|
50
50
|
"required": true,
|
|
51
51
|
"description": "Non-goals are named so the build stays scoped.",
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
52
|
+
"bundle_claim": {
|
|
53
|
+
"claimType": "builder.shape.non-goals",
|
|
54
|
+
"subjectType": "decision",
|
|
55
55
|
"accepted_statuses": ["trusted", "accepted"]
|
|
56
56
|
}
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
"id": "shaped-success",
|
|
60
|
-
"kind": "
|
|
60
|
+
"kind": "trust.bundle",
|
|
61
61
|
"required": true,
|
|
62
62
|
"description": "Success criteria are concrete enough for verification.",
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
63
|
+
"bundle_claim": {
|
|
64
|
+
"claimType": "builder.shape.success",
|
|
65
|
+
"subjectType": "artifact",
|
|
66
66
|
"accepted_statuses": ["trusted", "accepted"]
|
|
67
67
|
}
|
|
68
68
|
},
|
|
69
69
|
{
|
|
70
70
|
"id": "shaped-risk",
|
|
71
|
-
"kind": "
|
|
71
|
+
"kind": "trust.bundle",
|
|
72
72
|
"required": true,
|
|
73
73
|
"description": "Material delivery risks are recorded before breakdown.",
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
74
|
+
"bundle_claim": {
|
|
75
|
+
"claimType": "builder.shape.risk",
|
|
76
|
+
"subjectType": "decision",
|
|
77
77
|
"accepted_statuses": ["trusted", "accepted"]
|
|
78
78
|
}
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
81
|
"id": "open-decisions",
|
|
82
|
-
"kind": "
|
|
82
|
+
"kind": "trust.bundle",
|
|
83
83
|
"required": false,
|
|
84
84
|
"description": "Open decisions are recorded when the shape is not fully settled.",
|
|
85
85
|
"explore_hint": "Attach when unresolved choices could affect slices or issue boundaries.",
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
86
|
+
"bundle_claim": {
|
|
87
|
+
"claimType": "builder.shape.open-decisions",
|
|
88
|
+
"subjectType": "decision",
|
|
89
89
|
"accepted_statuses": ["trusted", "accepted", "advisory"]
|
|
90
90
|
}
|
|
91
91
|
}
|
|
@@ -96,12 +96,12 @@
|
|
|
96
96
|
"expects": [
|
|
97
97
|
{
|
|
98
98
|
"id": "slices-defined",
|
|
99
|
-
"kind": "
|
|
99
|
+
"kind": "trust.bundle",
|
|
100
100
|
"required": true,
|
|
101
101
|
"description": "The shaped work is split into independently useful slices.",
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
102
|
+
"bundle_claim": {
|
|
103
|
+
"claimType": "builder.breakdown.slices",
|
|
104
|
+
"subjectType": "work-item",
|
|
105
105
|
"accepted_statuses": ["trusted", "accepted"]
|
|
106
106
|
}
|
|
107
107
|
}
|
|
@@ -112,12 +112,12 @@
|
|
|
112
112
|
"expects": [
|
|
113
113
|
{
|
|
114
114
|
"id": "work-items-filed",
|
|
115
|
-
"kind": "
|
|
115
|
+
"kind": "trust.bundle",
|
|
116
116
|
"required": true,
|
|
117
117
|
"description": "Work items are filed or otherwise recorded with enough context to pull later.",
|
|
118
|
-
"
|
|
119
|
-
"
|
|
120
|
-
"
|
|
118
|
+
"bundle_claim": {
|
|
119
|
+
"claimType": "builder.file-issues.work-items",
|
|
120
|
+
"subjectType": "work-item",
|
|
121
121
|
"accepted_statuses": ["trusted", "accepted"]
|
|
122
122
|
}
|
|
123
123
|
}
|