Skip to content

Commit f490f46

Browse files
authored
feat(FAFF-947): widen decision-capture instrumentation to the remaining decision-kernel predicates (#794)
Signed-off-by: Alec Hill <alec@shftwst.dev>
1 parent aef1d53 commit f490f46

9 files changed

Lines changed: 243 additions & 6 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ "all_verified": true }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"issue": "FAFF-947",
3+
"build": {
4+
"status": "complete",
5+
"diff_hash": "d3fabd1b05da6e8e048484cfdbe02c42b7dd1be270bfe5dd35f1ea3429e1b519",
6+
"branch": "faff-947-widen-decision-capture-instrumentation-to-the-remaining",
7+
"pushed_at": "2026-08-31T15:12:27.739Z"
8+
},
9+
"updated_at": "2026-08-31T15:12:27.739Z"
10+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"run_id": "run-20260831-150520-graft-FAFF-947",
3+
"issue": "FAFF-947",
4+
"head_seq": 1,
5+
"head_sha256": "21244f4ed33d84a209cdc99f2e51f81d1f9faca9d3249bfc9b3684e6b50536f6",
6+
"line_count": 2,
7+
"schema_floor": 2
8+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{"schema":2,"run_id":"run-20260831-150520-graft-FAFF-947","seq":0,"ts":"2026-08-31T15:05:20.498Z","prev":"213f71ac4ea186e8ac7d0ae1eee86dcbe63640f26787e36832f411c26e6e0b6f","phase":"run","type":"ledger-write","data":{"ledger_sha256":"e629d80c241b17168ba8c9bd2ff330bc3cdcd9e30da015c6ee06d334c2d8d027"}}
2+
{"schema":2,"run_id":"run-20260831-150520-graft-FAFF-947","seq":1,"ts":"2026-08-31T15:05:20.490Z","prev":"5ba1a6da2114da66d119878ecc30a4c27a14b5dd28b0c53f980e79b23fae3425","phase":"run","type":"run-start"}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ "signal": "pass", "findings": [] }
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"run_id": "run-20260831-150520-graft-FAFF-947",
3+
"level": "L2",
4+
"admitted": [
5+
"FAFF-947"
6+
],
7+
"outcomes": {},
8+
"budget": {
9+
"envelope": {
10+
"ceilings": {},
11+
"at_ceiling": "stop"
12+
}
13+
},
14+
"owner": {
15+
"status": "running",
16+
"session_id": "run-20260831-150520-graft-FAFF-947",
17+
"pid": 389061,
18+
"started_at": "2026-08-31T15:05:20.490Z",
19+
"last_heartbeat": "2026-08-31T15:05:20.490Z"
20+
}
21+
}

plugin/skills/faff/bin/lib/decision-capture.js

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,57 @@ const KERNEL_REGISTRY = {
8888
version: "regions@1",
8989
required_inputs: ["files"],
9090
},
91+
// FAFF-947 widening: the five decision-kernel predicates the state-authority
92+
// map classifies as decision-kernel that FAFF-821 left uninstrumented. `state` is
93+
// deliberately absent (a read-model producer, not a prescribe-an-action
94+
// predicate: it reads the filesystem and emits an issue's resolved state with
95+
// status/eligible/blocked fixed to "unknown", so there is no verdict to replay
96+
// against selected_action); `run-ledger`/`decision-capture` are likewise out
97+
// of scope (a record-mint entry and the instrumentation itself).
98+
// derived from claim-verdict.js claimVerdict(claimedAtISO, nowISO, ttlHours) —
99+
// the three positional argument names, in order (the eligible/regions positional
100+
// precedent), validated against claimVerdictSelftest/CLAIM_VERDICT_CASES.
101+
"claim-verdict": {
102+
version: "claim-verdict@1",
103+
required_inputs: ["claimedAtISO", "nowISO", "ttlHours"],
104+
},
105+
// derived from park-verdict.js parkVerdict(status, draftPr, parkComment, humanTakeover) —
106+
// the four positional argument names, in order; validated against parkVerdictSelftest.
107+
"park-verdict": {
108+
version: "park-verdict@1",
109+
required_inputs: ["status", "draftPr", "parkComment", "humanTakeover"],
110+
},
111+
// derived from project-next.js projectNext({current, kind, total, active, done, hasDod, dodMet}) —
112+
// all seven options-object keys (none optional: dodMet/hasDod gate the DoD Done
113+
// path, the counts drive the all-done rollup); validated against projectNextSelftest.
114+
"project-next": {
115+
version: "project-next@1",
116+
required_inputs: ["current", "kind", "total", "active", "done", "hasDod", "dodMet"],
117+
},
118+
// derived from run-outward.js decideOutward(targetRaw, selfRaw) — recorded POSITIONAL,
119+
// NOT flat-bundle: normalizeTargetRef -> {container, repo, source} and normalizeSelfRef
120+
// -> {container, repo, is_self} collide on container/repo, so a single flat signal list
121+
// cannot disambiguate the two references. Each resolved reference is captured whole under
122+
// its argument name (the eligible/regions positional precedent); normalize* is idempotent
123+
// on an already-resolved ref, so replay re-normalization is a no-op. Validated against
124+
// runOutwardSelftest.
125+
"run-outward": {
126+
version: "run-outward@1",
127+
required_inputs: ["targetRaw", "selfRaw"],
128+
},
129+
// derived from run-start.js deriveRunTrigger(normalizeRunTriggerSignals(raw)) — the seven
130+
// flat signal keys the normalize step reads (the run-done normalize-then-derive precedent,
131+
// since run-start is its mirror predicate); validated against runStartSelftest.
132+
"run-start": {
133+
version: "run-start@1",
134+
required_inputs: ["target_resolved", "outward", "prd_present", "prd_ambiguous", "prd_admissible", "coverage_measurable", "coverage_covered"],
135+
},
91136
};
92137

93-
// The ratified six-name set, sorted — the born-verifiable DoD assertion.
94-
const KERNEL_REGISTRY_RATIFIED_NAMES = ["eligible", "next", "queue-state", "regions", "run-done", "tier"];
138+
// The ratified eleven-name set, sorted — the born-verifiable DoD assertion.
139+
// FAFF-947 widened this from the FAFF-821 six by adding the five replayable
140+
// decision-kernel predicates above.
141+
const KERNEL_REGISTRY_RATIFIED_NAMES = ["claim-verdict", "eligible", "next", "park-verdict", "project-next", "queue-state", "regions", "run-done", "run-outward", "run-start", "tier"];
95142

96143
// ---------------------------------------------------------------------------
97144
// classifyCoverage — the PROCEDURE from spec §4 "Coverage classification". Pure: no I/O,
@@ -444,7 +491,7 @@ function decisionCaptureSelftest() {
444491
let fail = 0;
445492
const ok = (name, cond) => { if (!cond) { fail++; console.log(`FAIL ${name}`); } else console.log(`ok ${name}`); };
446493

447-
ok("KERNEL_REGISTRY seeds EXACTLY the 6 ratified kernels (next/eligible/tier/run-done/queue-state/regions)",
494+
ok("KERNEL_REGISTRY seeds EXACTLY the 11 ratified kernels (claim-verdict/eligible/next/park-verdict/project-next/queue-state/regions/run-done/run-outward/run-start/tier)",
448495
JSON.stringify(Object.keys(KERNEL_REGISTRY).sort()) === JSON.stringify(KERNEL_REGISTRY_RATIFIED_NAMES));
449496
ok("every registry entry carries a version string and a non-empty required_inputs list",
450497
Object.values(KERNEL_REGISTRY).every((s) => typeof s.version === "string" && s.version !== "" && Array.isArray(s.required_inputs) && s.required_inputs.length > 0));

0 commit comments

Comments
 (0)