diff --git a/AGENTS.md b/AGENTS.md index c89477b..bd32750 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,9 @@ transition and report the conflict rather than creating a silent local variant. ## Required reading -Before planning, changing, reviewing, or delivering product work: +Before planning, changing, reviewing, or delivering product work — and +before answering what to work on next, where the loop stands, what is waiting +on a decision, or what is blocked: 1. read the project's root `AGENTS.md` for project-specific rules; 2. read this file and `PROCESS.md`; @@ -39,6 +41,13 @@ Before planning, changing, reviewing, or delivering product work: 4. read the relevant product sources, requirement records, optional epic, and active work-selection record. +Being asked what to do next is session entry, not a shortcut past it. The +answer is the store's pending human decisions and routed work, read through +`skills/rdd-start/SKILL.md`. Version control, change lists, and the working +tree describe the repository rather than the loop, and never answer that +question. A project's root `AGENTS.md` names the concrete read for its own +store; if it names none, that omission is the report. + ## Binding process Follow `PROCESS.md`. Skills apply it and `file-state/` serializes its records; diff --git a/PROCESS.md b/PROCESS.md index 6a825e8..604eb71 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -51,7 +51,10 @@ be established from authoritative records, code, tests, or runtime evidence. | `EPIC:#
` | Existing Epic record | Missing support is an open question. Conflicting support remains a conflict -until a human resolves it. Code proves existing behavior, not intended behavior. +until a human resolves it. Code proves existing behavior, not intended +behavior. Repository state — branches, diffs, change lists, and version +control's own review queues — proves what the repository contains, not what +the loop holds; it is never a source for selection, status, or priority. Here, **material** means capable of changing correctness, security, data integrity, a public contract, trace completeness, acceptance, or testability. @@ -288,7 +291,7 @@ focused skill alone only when the requested scope explicitly ends at that pass. | Phase | Skill | Required exit | |---|---|---| -| Enter session | `rdd-start` | Store binding and single active release verified from the store; answered gates reconciled; frozen scope routed to its earliest unmet phase | +| Enter session | `rdd-start` | Store binding and single active release verified from the store; answered gates reconciled; frozen scope routed to its earliest unmet phase, or an orientation request answered from the current pending-decision projection | | Source/classify | `rdd-discover` | Authoritative input or an exact confirmation gate; no unconfirmed requirement proceeds | | Plan/reconnaissance | `rdd-plan` | Entry-packet items 1–6 and the human brief at a named revision | | Cold review | `rdd-cold-review` | Current cold-review trace verdict and finding dispositions | @@ -443,6 +446,12 @@ selections, and selection history. `BACKLOG.md` stores unrouted triage items and gap records. Derived queues and progress views — including the pending human-decision projection — are regenerated, not backed up separately. +That projection is never lifecycle authority, and it is the session's answer +to what to work on next: it is read from the store, dated against the store +revision, and presented — ranked by what a single human answer releases. A +projection delivered into a session ahead of the request is that same answer +arriving early, not background context. + | Concern | Authority | |---|---| | Product/domain/architecture/contracts | Product documents and schemas | diff --git a/skills/rdd-audit/audit-citations.mjs b/skills/rdd-audit/audit-citations.mjs index 480703a..24642d3 100755 --- a/skills/rdd-audit/audit-citations.mjs +++ b/skills/rdd-audit/audit-citations.mjs @@ -61,9 +61,22 @@ const ELIDED = /(?:CODE:|`)(?:[A-Za-z0-9_.\\[\\]\-]+\/)*\.\.\.\/[A-Za-z0-9_.\/\\ // C8: a row naming a gap is not a citation. "there is no test_draft_service.py" // is the most useful thing a derivation pass produces, and an audit that counts // it as broken teaches the next pass to stop naming what is missing. -const ABSENCE = /\b(no|not|missing|absent|never|does not exist|there is no|without)\b[^.]{0,60}$/i; +// Bare `not`/`never` are NOT in this list: alone they carry no absence meaning +// ("the handler is not used anymore; its logic moved to `CODE:new.go:900`"), yet +// inside the 60-char window they excused any failing citation trailing an +// unrelated negation — hiding real rot behind a stray "is not". Every word kept +// names absence directly; a deliberate gap still reads "no"/"there is no"/etc. +const ABSENCE = /\b(no|missing|absent|does not exist|there is no|without)\b[^.]{0,60}$/i; const roots = process.argv.slice(2).filter((a) => !a.startsWith("--")); +// A vacuity floor the CALLER sets, because only the caller knows its corpus. A +// generic run stays generic (default 0); a gate over a corpus that always +// carries citations passes --min=N, so a scan that silently matched almost +// nothing — the ".NET estate printed 10/10 while skipping 710" failure in its +// residual form, where the count itself is the tell — exits non-zero instead of +// reading as a clean pass. +const minArg = process.argv.find((a) => a.startsWith("--min=")); +const minCitations = minArg ? Math.max(0, parseInt(minArg.slice(6), 10) || 0) : 0; const targets = roots.length ? roots : ["docs", ...(existsSync("ARCHITECTURE.md") ? ["ARCHITECTURE.md"] : [])]; // Refuse to audit the prompts. Teaching material deliberately @@ -275,6 +288,7 @@ function check(doc, text, m) { } const total = ok + broken.length; +const belowFloor = minCitations > 0 && total < minCitations; console.log(`${ok}/${total} citations resolve across ${docs.length} documents` + (gaps ? ` (+${gaps} named gaps excused — a cited path stated as absent)` : "")); @@ -286,6 +300,10 @@ if (broken.length) { console.log(`\n${broken.length} broken:`); for (const b of broken) console.log(` ${b.doc}:${b.lineNo} ${b.path} — ${b.why}`); } -if (!elided.length && !broken.length) console.log("no elided paths"); +if (belowFloor) { + console.log(`\nvacuity floor: ${total} citation(s) checked, below the required --min ${minCitations} —` + + " too little matched to be a real audit (a broken scan otherwise reads as a clean pass)"); +} +if (!elided.length && !broken.length && !belowFloor) console.log("no elided paths"); -process.exit(broken.length || elided.length ? 1 : 0); +process.exit(broken.length || elided.length || belowFloor ? 1 : 0); diff --git a/skills/rdd-start/SKILL.md b/skills/rdd-start/SKILL.md index bf2e101..30cb70f 100644 --- a/skills/rdd-start/SKILL.md +++ b/skills/rdd-start/SKILL.md @@ -1,6 +1,6 @@ --- name: rdd-start -description: Enter a delivery session — verify the process-store binding and active release, reconcile answered gates, take or prompt for the work scope, and route to the phase the loop actually needs, holding commit and check discipline for the whole session. Use at the start of any product-work session, or when asked to start, continue, or pick up requirement-driven work. Not a substitute for any phase skill. +description: Enter a delivery session — verify the process-store binding and active release, reconcile answered gates, take or prompt for the work scope, and route to the phase the loop actually needs, holding commit and check discipline for the whole session. Use at the start of any product-work session; when asked to start, continue, or pick up requirement-driven work; and whenever the question is what to work on next, where the loop stands, what is waiting on a decision, or what is blocked. Not a substitute for any phase skill. --- # Start a delivery session @@ -25,15 +25,36 @@ Read the project `AGENTS.md` and the canonical `PROCESS.md` — installed at header against the store revision. A stale snapshot is refreshed, never edited. +The pending-decision projection may already have been delivered into the +session by the host — a session-start brief injected as context rather than +requested. That is the store's own answer arriving early, not ambient +background: date it against the store revision before relying on it, and +refresh it when it cannot be dated. A projection whose currency is unknown is +reported as unknown, never presented as current. + An unmet preflight fact is the report. Do not select work past it. ## Take the scope Accept the work scope as the argument: an Epic id, a single SR id, or a raw -request. Without one, present the current work selection and the routed -`PROPOSED`/`TODO` queue and ask the human to choose; never pick a release +request. Without one — including when the request is an orientation question +rather than a scope — answer from the store: read the pending human decisions +and the routed `PROPOSED`/`TODO` queue through the store's own projection +read, present them, and ask the human to choose. Never pick a release commitment silently. +Version control, change lists, and the working tree describe the repository, +not the loop. They are never the source for what to do next; a session that +answers an orientation question from them has skipped this skill. + +Rank what you present by what a single human answer releases: an `OPEN` human +gate holding built `IN_REVIEW` work outranks unstarted work, and a gate +holding many items outranks one holding few. State the distribution across +awaiting-decision, ready-to-build, and awaiting-acceptance. A queue whose +awaiting-acceptance bucket dwarfs its ready bucket is a finding about where +the loop is stalled — report it as one rather than leaving the reader to count +rows. + Freeze the selection per `PROCESS.md` work scope and record it in the work-selection record. Packet depth is proportional to the frozen scope; no packet item may be omitted. @@ -64,3 +85,8 @@ complete loop. Report the store binding and how it was confirmed, the active release and its source, pending human decisions, the frozen scope and fingerprint, and the phase entered — or the exact preflight fact that stopped the session. + +Repository and process work that carries no requirement record — tooling, +instructions, delivery infrastructure — is reported separately and labeled as +such. It is real work and may be urgent, but it is not what the queue is +asking for and never substitutes for the queue in the answer.