Imported from tz5514/zet-agent-skills-dist (
emergent-grill/SKILL.md). Install upstream withnpx skills add tz5514/zet-agent-skills-dist --skill emergent-grill. Copyright stays with the author.
Before asking any questions
Load the domain context for this session:
-
Formally load the complete
emergent-designskill — the first load of every grill round. Loademergent-designvia the Skill tool where the runtime provides one, otherwise by a complete read of that skill'sSKILL.md, before anything else in this sequence: before readingCONTEXT-MAP.md, anyCONTEXT.md, or any ADR, and before the first question. That skill is the round's engineering-philosophy authority — it governs how deep your questions may go and the documentation gate's carrier-suitability judgment; apply it as loaded, never by restating it here. If the load fails — the skill is missing or unreadable, or you obtained only a description or summary instead of the full body — stop the grill immediately and report the load error: memory, a summary, or locally restated principles never substitute for the loaded skill. If the loaded content is later lost mid-round — context compaction, a reset, or any other loss — reload it the same way before the next judgment that needs it, under the same fail-closed rule. Load success needs no ceremony beyond the tool transcript itself. -
Check if
CONTEXT-MAP.mdexists at the repo root.- If yes: read it, identify which bounded context matches the user's topic, read that bounded context's
CONTEXT.md. - If no: check for a root
CONTEXT.md. Read it if it exists.
- If yes: read it, identify which bounded context matches the user's topic, read that bounded context's
-
Read OUTPUT-FORMAT.md in the same batch — it holds the fixed templates for every recurring output block this round emits (binding, the ADR necessity self-check, documentation-gate results, scan reports, pending-items map, closing blocks). Every such block must use its template; skipping this read means falling back to improvised output for the whole round.
-
Load the bounded context's ADRs by the fixed three-state load sequence. ADRs live in three subfolders of
docs/adr/—draft/(not yet implemented, freely editable),active/(implemented and still in force, immutable),archived/(fully superseded, immutable) — and the folder a file sits in is the single signal of its state and mutability (the full three-state lifecycle model is governed by/emergent-adr— invoke it for the ADR mechanism). Load them in this exact order, never all at once:- All
draft/ADRs — full text. Frame every one as a tentative, editable draft that is not ground truth: it is loaded only so a new decision can be checked against it for conflict (and the draft amended if they clash), never built on as an already-implemented basis. Continuing a discussion on top of a specific draft requires the user to say so explicitly. - All
active/ADRdescriptions — not their full text. Obtain them by invoking/emergent-adrwith theextract-active-adr-descoperation keyword andbounded_context_path, which returns the{filename → description}index table for this bounded context'sactive/folder; read only that table — do not open the active files, and do not bypass/emergent-adrto pick its internal helpers or re-implement the ADR mechanism. Adescriptionis a retrieval trigger (its spec is governed by/emergent-adr), so the table tells you which active decisions exist and when each becomes relevant, without spending context on full text you will not use. - The full text of the active ADRs the current topic makes relevant. Judge relevance from the descriptions and formally load those few in full — that is the real, complete decision context you begin with.
- Never proactively load
archived/. Two exceptions only: the user names a specific archived ADR to read, or the user asks you to scanarchived/for an already-superseded record on a particular topic. Otherwise archived stays out of context, so retired decisions cannot pollute it.
After the opening sequence, keep loading relevant active full text on demand throughout the discussion, at a low threshold, triggered by relevance: once you have genuinely judged an active ADR related to the current topic, read it readily rather than worrying about over-reading — mis-reading an unrelated ADR costs little, while missing a related one is backstopped by the later draft promotion flow, not during the interview. It must still rest on a real, reasoned relevance, not unconditional full loading (which would recreate the load-everything problem the description index exists to solve).
- All
-
Existing terms and active ADRs are your starting constraints. Every question you ask must respect them. If the user's plan conflicts with an existing term or an active ADR, surface the conflict as a question instead of silently ignoring the prior decision.
-
Bind this round and emit the 📍 block. One grill round operates exactly one bounded context — the one identified in step 2 (inferred via
CONTEXT-MAP.md, or implied by the single rootCONTEXT.md; if the inference is uncertain, ask the user directly). Every CONTEXT.md and ADR write this round stays inside that bounded context. If the bound bounded context has no CONTEXT.md yet, create the skeleton file now, at binding time: title + a one-sentence description + an empty Language section — zero terms, which keeps the skeleton compatible with the CONTEXT.md write iron rule (no entry enters the file without the user's confirmation of its shown complete candidate entry; see the documentation gate). The path the binding block prints must always point at a real file. Then output the 📍 binding block using its template in OUTPUT-FORMAT.md, filling the active / archived / draft counts from the folders you just loaded.
What you are doing in this interview
Your primary job is not to walk a checklist of topics. It is to surface the implicit assumptions — the things the user takes for granted and would not think to mention, but which shape the spec. The user is here to be interviewed, not to find questions; if you do not surface an assumption, it will not appear in the conversation, and the resulting PRD will silently bake in a guess.
After every answer, ask yourself before anything else: in what they just said, what did they assume without saying? What context did they presume you already share? What edge cases or trade-offs did they skip past because the answer felt obvious to them? Those are your next questions.
When you identify an assumption to surface, classify its source before framing it: does this follow directly from what the user has said, or are you projecting from your priors? Frame the second kind as a hypothesis to check, not as the user's assumption: "I'm guessing you're assuming X here — is that right, or have you been thinking about it differently?" Never present a projected assumption as a fact about the user's mental model.
No invisible premises. This extends one step further: any premise that a later step will depend on — the next question, a document write, or the downstream spec — must appear in your visible text output, or be archived into CONTEXT.md / an ADR. It must never live only in your reasoning. A premise you formed in thinking and silently treated as settled was never put to the user, so they had no chance to challenge it; and a downstream process that reconstructs context from the conversation text alone (not your thinking) loses it entirely, leaving every decision that rested on it without its reason. So before you build on a premise you projected, surface it as a hypothesis to confirm (per the rule above) — do not carry it forward as if the user had already agreed. This is a behavioural discipline, not a mechanical check: nothing scans your output for hidden premises, so the obligation rests on you. (Purely operational process state — a verifier's retry count, a scan's internal bookkeeping — is not such a premise and is exempt; it shapes no decision and surfaces at the point it actually matters.)
This is the engine that drives the interview. The techniques in <supporting-info> (sharpening fuzzy language, edge-case scenarios, cross-referencing code) are supporting tools that help you execute it — not goals of their own.
Treat depth as obligation, not courtesy. Every additional layer of probing brings more of what would otherwise stay buried in the user's head into the conversation.
A note on word choice. When phrasing your questions and proposals, prefer plain language over jargon. Words like "canonical", "artifact", "kind", "digest", "verdict" feel precise to you but make the conversation harder to follow. Use the simpler word the user would naturally use, unless the technical term carries a meaning that no plain word captures. The user is the domain expert here — speak their language, not yours.
This goes deeper than vocabulary. Your default mode of explanation should be: precise terms from the project's shared vocabulary (the CONTEXT.md glossary) plus a concrete user story illustrating the actual flow. Not abstract noun phrases like "entity transition" or "partial failure semantics" — those are how you think, not how the user lives the system. A user story is: a real role, doing a real action, encountering a real situation, with a real outcome. "A customer hits cancel on an order that has already shipped" lands. "Handling state transitions with side effects under partial failure" does not.
Reach for cross-domain analogies only when the abstraction is genuinely hard to describe directly, or when the user has signalled multiple times they are not following. Default to staying inside the project's own vocabulary and flows — that almost always communicates effectively without leaving the domain. A misplaced analogy can simplify away the very detail that matters.
Why this matters structurally, not as a courtesy: the grill-and-PRD phase is the only phase where the human is fully in the loop before AFK execution begins. If the user does not understand what is being decided, the user is not participating in the decision. A decision the user did not participate in becomes a black box in the spec — and every downstream gate that checks against that spec carries that blindness forward. "Speak so the user understands" is therefore not a polite habit; it is what keeps the spec sound.
Asking each question
The principle behind this filter: every question you ask should carry genuine decision content the user cannot delegate — to general engineering knowledge, to you, or to the implementation itself (the loaded emergent-design philosophy governs that last delegation). Volume of questions is not the concern; the concern is asking questions whose answers you already know or could derive, which dilutes the signal of the questions that genuinely need the user's input.
Before you put forward a point, issue, or recommended answer, ground its load-bearing premises (when unsure whether a premise is load-bearing, treat it as one) — not just the headline claim — against the most direct source available, in this priority order:
- Codebase or existing docs. This tier fires only when the premise actually connects to something the codebase implements, names, or constrains — it is not a per-premise step; trigger it on a real connection to existing code, not for every premise (the triggers are listed in
<supporting-info>under "Cross-reference with code"). When it does fire, the code is the most reliable ground truth for what the system actually does, and an answer built on what you remember is weaker than one built on what the system is. For a brand-new feature the codebase will often have nothing to offer — that is expected, not a failure; move to the next tier rather than hunting for code that does not exist. If a check would need so much code that your context risks saturation, delegate it to an Explore subagent with a focused brief and use only its summary. - The web. If (1) cannot settle it, or local evidence is too thin for high confidence, you must search for high-credibility references — but a pure design judgement, with nothing factual to verify, is exempt and goes straight to tier 3. Treat web lookup as a normal, expected move — not a last resort.
- Your own speculation or design judgement. Only when neither of the above yields solid support — whether because the fact could not be verified, or because the point is a design call with nothing factual to verify. Advance it, but say plainly that its confidence is low.
Your own training knowledge does not count as high-confidence evidence — there is no "I just know" escape hatch: if you believe something is a fact or best practice but the codebase does not show it, find a web source; if you cannot, it drops to low confidence. A premise resting on a checkable fact must be checked; a pure design judgement, with nothing factual to verify, is not web-searched — it is the tier-3 case above, advanced with low confidence. This is where you do not save tokens: the cost of a search is far smaller than the cost of a confident, wrong premise being ratified into the spec.
When you put the point to the user, attach its basis inline. If it has a source (tier 1 or 2), wrap the descriptive text in a markdown link to that source (a code location or a web reference) rather than printing the raw URL. If it has no source — a tier-3 judgement or unverified guess, which by definition has nothing to link — do not manufacture a link; instead say in words, plainly, that this is your own low-confidence call. Let the confidence you state follow the tier — codebase or web can be high, a tier-3 call is low — never a self-rated number. Keep solid-source tags quiet and the no-source / low-confidence flags loud, so your basis-tags concentrate the user's scrutiny on what is weak rather than dispersing it.
This grounding catches only premises you actually surface as claims; a premise you are so sure of that you never state it can still slip through, and that residual is for the user and any downstream review to catch — not something this step can guarantee.
Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each candidate question, form your own recommended answer in your head. Hold this explicitly as your prior — your view, not anything the user has said yet. You will need this distinction later when the engine asks you to classify whether an assumption you are about to surface comes from the user or from your priors. Then run this filter before deciding whether to ask:
-
Does the loaded
emergent-designphilosophy place this decision on the emergent side of its human-decision boundary? Run this before grading the decision as architecture-level: ADR necessity conditions do not decide whether humans own the commitment. If the choice creates none of the commitments that philosophy reserves for humans, do not ask the user to pre-freeze it — and do not settle it yourself either: state in passing that it is left to form through code, tests, and implementation feedback, so the user can pull it back to the table if they disagree. Judge with the loaded skill directly; its boundary is not restated here. Only a decision that remains inside the human-decision boundary continues through the filter. -
First identify the executor: the artifact that will actually perform the designed behavior. Once the goal is clear, retain a question only when it concerns a condition that the executor can still encounter while carrying out that goal as written and whose handling remains undecided by the goal.
-
Is the remaining decision architecture-level? A decision is architecture-level if it meets every ADR necessity condition — the condition semantics live only in the authority document loaded through
/emergent-adr read-necessity-conditions, never in a local restatement here. If yes — or if you are not sure whether it qualifies — you must ask, regardless of whether you can guess a default answer. Architecture-level decisions need explicit user ratification because they shape every downstream question and are expensive to undo. When in doubt, treat as architecture-level: this grading decides whether to ask the user, so uncertainty escalates to asking — it is not the ADR-writing gate, whose strict default points the other way. -
Otherwise: can you answer this from general engineering knowledge or the existing codebase? If yes, decide it yourself, state your choice in passing so the user can object if it is wrong, do not ask. Only ask non-architectural questions where the answer depends on project-specific context, business logic edge cases, or user-specific preferences that general knowledge cannot supply.
Present the ruling point
When the ruling is only a choice between named options and no relationship must be reconstructed, put every named option in one prose question and output only that sentence. Otherwise, match the smallest useful view to the relationship:
- order or handoff → sequence or flow;
- the same choices across roles or cases → table;
- ownership, containment, or inheritance → tree;
- an existing shape changing → before/after sketch or diff.
Preserve the exact meaning, order, and modality of every fixed relation and candidate. Keep the complete relationship in one primary view; use prose only for the one ruling question.
This shapes only the retained question's presentation; the filter and one-question turn control still decide what is asked and when.
Ask the questions one at a time, waiting for feedback on each question before continuing. If a question can be answered by exploring the codebase, explore the codebase instead.
After each answer — documentation gate
Before asking the next question, run this gate.
Cycle semantics — write immediately; batch only the checks. One documentation-gate cycle is the one-time processing of a single ratified answer. Every document write that answer triggers executes in the same cycle, at ratification time — never delay a write into a later cycle to accumulate a batch. A CONTEXT.md write happens the moment the user confirms the shown complete candidate entry; an ADR write happens the moment its write authorization arrives through the staged ADR delivery below — the stages gate the write, they never postpone it to accumulate a batch. "Batch" refers only to what happens after the writes: the delivery-check results merge their output per cycle — batching governs the checks, never the write timing. The interview-time gate runs no supersession scan, so the cycle's output blocks are 🧭 → 📝 → ✅ — the 🔍 / 📣 scan blocks are not emitted at interview time (their templates in OUTPUT-FORMAT.md stay for non-interview or future use).
Ratification check first: the routing in steps 1–3 applies only to answers the user has explicitly ratified — phrases like "yes, decided", "let's go with that", "OK that's the answer", or any equivalent explicit ratification signal in the user's language. If the user is still discussing, weighing, or has not given a clear "this is the answer", skip the routing — the decision is not yet made. The pending-items step at the end always runs.
Carrier suitability — run on every ratified answer, before the ADR necessity self-check. Apply the loaded emergent-design skill's information-carrier responsibility to what the answer settled: one whole-picture judgment, made with the loaded philosophy — not a checklist, scoring form, or classification field. It only routes, and every outcome lands on an existing gate surface: a domain term files through routing outcome 1's CONTEXT.md path unchanged; only content whose lasting decision context could suit an ADR enters the necessity self-check below as a candidate decision; content that belongs in future code, tests, interfaces, or local comments is not an ADR candidate — it takes routing outcome 3's spoken not-filing line, naming that eventual carrier. When this judgment leaves no ADR candidate, it is the prerequisite check the 🧭 one-line variant reports as its reason. The judgment emits no block of its own and no success evidence, and your carrier reasoning never enters the frozen reviewer input — the candidate description stays in the two-block schema form.
ADR necessity self-check — run on every ratified answer, after the carrier-suitability judgment and before routing. The user must be able to tell "judged, and not initiating" apart from "forgot to judge", so every ratified answer gets a visible self-check verdict — even when nothing in it looks like an ADR candidate.
- Authority loading contract. The first time this session needs an ADR necessity judgment, invoke
/emergent-adrwith theread-necessity-conditionsoperation keyword to load and validate the ADR necessity-conditions authority, once; reuse that fixed content for every later self-check in the same continuous session instead of reloading per answer. Reload only when the exact, complete loaded content is no longer available — after context compaction, a reset, or any other loss — and never continue from memory, a summary, or an older version. When loading and reloading both fail, fail closed: this answer's necessity judgment stays unevaluated — emit the 🧭 authority-failure variant naming the failed authority input, never print a ❌ line for a condition that was never evaluated, dispatch no reviewer, stop the documentation gate here and report to the user; after the authority input is repaired, rerun this answer's self-check before moving on. - Order and strictness. First confirm the answer actually ratified a candidate decision; only then judge the candidate against every condition the loaded authority defines, each with a candidate-specific reason, under the authority's own evidence and verdict rules. The default is strict: uncertain means the condition does not pass, and a self-check that does not pass every condition initiates nothing — no reviewer is dispatched and no evidence-extraction cost is paid.
- The 🧭 block. Every ratified answer's output carries the 🧭 ADR necessity self-check block (templates and turn roles in OUTPUT-FORMAT.md). No candidate decision, or a prerequisite check blocking entry into condition judgment → the one-line variant carrying the reason. Condition judgment ran → the per-condition variant: one parent candidate line (
候選/Candidate, or候選 1/Candidate 1, … when several candidates share one answer), with every ✅/❌ condition line and the initiation conclusion nested two spaces beneath it — copy the fence shape from OUTPUT-FORMAT.md, not a flat sibling list. Match each condition by English identity, in authority order: a zh-TW or English environment copies the title from its matching display-name list in OUTPUT-FORMAT.md, while a third-language environment translates the matching English display name from OUTPUT-FORMAT.md; never paste bilingual authority headings onto the block. The visible short reasons are transparency only: they carry no evidence weight, never replace the reviewer's independent evidence work, and never authorize/emergent-adr write. - Freeze the reviewer input before summarizing. When the self-check passes every condition, first compose and freeze the complete reviewer input: the candidate description in the two-block form defined by
/emergent-adr check-should-write-adr'scandidatesinput schema — the decision content to record plus the main agent's per-condition claims, carrying no conversation-evidence locations (that schema, not this skill, is the authority for the description's contract). Only then derive the visible short reasons from that frozen version and dispatch the review through routing outcome 2. Never treat the visible block, or an expansion rewritten from it, as the reviewer input.
Route the ratified answer — don't just dump it. The failure mode this prevents: checking "is this a term?", then "is this a decision?", and when neither fires, falling silent — so an answer that belongs in neither document vanishes without the user noticing. Walk every ratified answer through all three outcomes below. The first two fire independently and can both apply (one answer can be both a term and a decision). The third fires only when neither of the first two did, and it is spoken, not silent.
-
CONTEXT.md — did this answer confirm a shown term candidate, or expose a current ambiguity a term would eliminate? A ratified content decision — product, process, architecture, behavior, or concept — authorizes exactly that decision and nothing about the glossary: not that a formal term should exist, not which name is official, and not any definition text you drafted. Glossary writes have their own ruling. Propose a term candidate when it would eliminate an ambiguity you can point at right now — a single ambiguity in the content in front of you, or a divergence across code, tests, interfaces, and docs where different names cover one concept or one name covers different concepts. That is proposal guidance, not a gate: no scoring, no state machine, no fixed threshold decides whether you may propose — but a purely hypothetical future confusion, with no ambiguity you can point at now, does not grow the glossary. To propose, say which current ambiguity the candidate eliminates, self-check the candidate yourself against the entry contract in CONTEXT-FORMAT.md — the definition holds only the minimal semantic boundary that tells the concept apart, and every
_Avoid_value is a genuine alternative name for the same concept — and show the user the complete candidate entry exactly as it would be written: the formal headword, the full definition text, and the_Avoid_line it will carry, if any. Showing only a headword, a summary, or a "we need a term for this" intent is not a writable preview. The user's review of that shown entry is the only check beyond your own: do not dispatch a sub-agent reviewer for term candidates, and a passed self-check never becomes write authorization. One explicit confirmation of the shown entry ratifies the whole of it at once — that the term exists, its name, the full definition, and the_Avoid_line as displayed; do not split it into multiple approvals. A semantic modification of an existing entry goes through this identical preview-and-confirm path.CONTEXT.mdis a glossary only — no implementation details, no specs, no temporary notes. When a confirmed candidate renames or retires a term, remove the old entry whole — nodeprecatedremnant (the full rule and the_Avoid_-alias mechanism for an old word still living in an immutable ADR body: see the entry contract in CONTEXT-FORMAT.md).The CONTEXT.md write iron rule (holds across the whole grill flow, not just at this step): no entry is written until the user has confirmed the complete candidate entry they were shown — you propose, the user confirms that entry, then you write; no exceptions. Until that confirmation arrives the candidate lives only in the conversation: your self-check, the content decision's own ratification, the user not objecting, or a passing "I'll sync the glossary" line each authorize nothing. The rule binds every path that can propose, write, rename, or sync a term — a naming suggestion while questioning, a ratified content answer, the binding-time skeleton, and rename synchronisation all pass through the same confirmation; none of them is a second write path. Two narrow direct executions exist. First: after the user confirms a rename, propagating that exact new name into references still using the old name — changing no definition, no semantic boundary, and no
_Avoid_value — may proceed directly, shown explicitly in the 📝 block; the moment a propagation would change meaning, stop and rerun the full preview-and-confirm path. Second, symmetric to it: pure formatting cleanup — changing no headword, no definition's semantic boundary, and no_Avoid_value — may proceed directly, shown explicitly in the 📝 block; the moment a cleanup would change meaning, it is a semantic modification: stop and rerun the full preview-and-confirm path. The design goal behind the rule: CONTEXT.md must never contain a word or meaning the user has no memory of ratifying — one unratified entry is how a glossary starts to rot. -
An ADR — did the self-check initiate the staged ADR delivery for this answer? A candidate decision reaches an ADR only through the staged flow — self-check pass → independent review → foreground write — with each stage gating the next; there is no direct write path.
/emergent-adris the authoritative home for ADR writing, ADR quality review, support-data handling, supersession scanning, and lifecycle handoff — follow each operation's structured return rather than embedding those mechanisms here.- Independent review. Dispatch the frozen candidate input by invoking
/emergent-adrwith thecheck-should-write-adroperation keyword — modecreatefor a new decision, modemodifywith the target draft path for a delta to an existing draft. The operation's input schema also requiressession_transcript_path: resolve the current session's transcript file yourself and pass it with the dispatch — supplying it is the caller's responsibility, and/emergent-adrnever infers it. A review round is whatever candidates are ready now: a single candidate dispatches directly, several dispatch in parallel behind the operation's join barrier; never wait for candidates that do not exist yet and never dispatch an empty round. - Write authorization. Only a validated
approvedresult fromcheck-should-write-adr, or the user's explicit clearance naming a rejected scope, authorizes writing that candidate; consume the round's results through step 4 below. The write itself is/emergent-adr write, executed by you in the foreground — a grill records decisions that are not yet implemented, so a new ADR is written intodocs/adr/draft/withstatus: not_implemented_yetand its requireddescription(it moves toactive/only when implemented, the last task of the downstream build); a delta to an existing draft goes throughwrite's modify mode. One authorization also covers later structural or wording fixes that keep the decision's meaning unchanged; a change to the substance of the reviewed scope stops the write and goes back throughcheck-should-write-adrin modify mode.
This is the ADR-lifecycle hinge. Writing or modifying an ADR here is governed by
/emergent-adr's ADR mechanism (format, lifecycle, ADR 品質審查, supersession scanning, and supersession-mark back-derivation). Two boundaries apply at this point, every time, no exceptions:- Immutability guard. The folder a file sits in is the single mutability signal: only
draft/ADRs are editable;active/andarchived/are immutable. If the decision you are about to record changes a decision already in anactive/(orarchived/) ADR, you may not edit that file's decision content — route to writing a new draft ADR that supersedes it./emergent-adrgoverns how the supersession relationship is later recorded into the new draft'ssupersedesand how the active side is marked. Because the interview-time path does not run the supersession scan, nosupersedesdetail is written at grill time — it is produced by/emergent-adr finalize-draft-adrswhen the user carries the draft through draft→active migration, and the active side is marked at that migration. - Deferred scan. The interview-time gate runs no supersession scan: the staged delivery writes the draft in the foreground, and the round's post-write check is only the CONTEXT.md glossary-approval preflight. So at grill time there is no scan result to report, and the two scan output channels (🔍 routine line, 📣 report table) are not emitted during the interview — their templates stay in OUTPUT-FORMAT.md for non-interview or future use, they are simply not triggered here. The full supersession scan is deferred to the user's later draft promotion flow: the user invokes
/emergent-adr finalize-draft-adrs, and that flow runs the full review and supersession scan before promotion; do not callscan-supersessionfrom the gate. This is a deliberate trade of interview-time scan coverage for interview continuity, not a missing step — do not "fix" it by adding a scan back into the gate.
- Independent review. Dispatch the frozen candidate input by invoking
-
Neither — did the answer match neither of the above? Then it does not get filed — but say so in one line, so the user sees the outcome rather than a silent skip: that one line is the 📝 block's single-line not-filing variant (template in OUTPUT-FORMAT.md), naming in one sentence why the answer fits neither document and that it stays in the conversation for the user to record elsewhere if wanted. When the carrier-suitability judgment placed the answer's information in a long-lived carrier this gate does not write, that sentence names the carrier and says the later spec will hand the information off to it — not filing is then a deliberate carrier decision, not a leftover. That spoken "not filing this" is the entire purpose of this outcome: it turns a decision that fits neither document from something that silently evaporates into something the user can see and override. CONTEXT.md and ADRs are the only documents this gate writes — do not invent a third file type to hold the leftover.
After routing a ratified answer, emit the 📝 block (template in OUTPUT-FORMAT.md) once the cycle's document writes have settled — for ADR candidates that is after step 4's foreground write wave, because an ADR counts as filed only when its write has completed; a candidate still awaiting resubmission or a ruling is not yet a filing situation. List exactly the filing situations that occurred in this cycle — new ADR, modified this-round ADR, new CONTEXT.md term, modified existing term — or the single-line not-filing variant when none did. The fixed 🧭 → 📝 → ✅ sequence is the cycle's output order, not its execution order. Whenever this cycle dispatched a review round or wrote any file:
-
Staged delivery — result consumption, failure handling, and the preflight barrier.
- Consume the round's results. After the review round's join, first write every approved candidate in the foreground with
/emergent-adr write, sequentially — never in parallel and never through a sub-agent — without waiting on rejected candidates' adjustments or rulings. A rejected candidate has exactly two exits, and the reviewer's report stays a rejection either way — never write anyway and never extract just the passing parts:- Rejection accepted → abandon the candidate, or adjust the request input and resubmit: every candidate whose adjusted input is ready joins one next
check-should-write-adrround; a single adjusted candidate resubmits immediately, never waiting for other possible adjustments. Changed input is a new review version, never a retry of the old one. - Rejection not accepted → accumulate a user-ruling item carrying the rejected scope, the reviewer's reasons, your specific disagreement, and the risk of writing anyway; write only on the user's explicit clearance naming that scope.
- Rejection accepted → abandon the candidate, or adjust the request input and resubmit: every candidate whose adjusted input is ready joins one next
- One merged ruling stop point, itemized rulings. Present all accumulated ruling items — non-accepted rejections,
needs_context_rulingreturned bywrite, and the failure items below — together at the next user-ruling stop point, after every write and resubmission wave that needs no user input has finished: one report, itemized so the user rules on each item separately, never an all-or-nothing bundle. A single pending item is raised directly, never delayed to collect more. - Three failure classes — each must appear in the visible output; no candidate is ever silently dropped:
- Review not completed — the redispatch budget is exhausted without a valid report, or the operation itself failed (for example the conversation-evidence cutoff could not be produced): the candidate becomes a user-ruling item carrying the failure reason and the candidate content; the user either abandons it or has you repair and resubmit. Until that ruling the candidate is neither written nor abandoned, and the preflight barrier keeps waiting.
- Foreground write failure — the draft cannot be produced or the tool fails: the candidate keeps its review authorization and stays neither written nor abandoned. Retry the write in the foreground on incidental failure under the same stop rule as review redispatch — the redispatch stop semantics defined by
/emergent-adr check-should-write-adr, applied here to write attempts — then surface the failure information and merge it into the ruling stop point above.write's normal terminals arewrittenandneeds_context_ruling; an execution failure is the operation failing, not a status value. - Preflight-round failure — a preflight reviewer is interrupted or its report is invalid: that is a tool failure, not a finding and not a rejection — do not modify the ADR; rerun that ADR's preflight with a fresh reviewer under the same redispatch stop semantics, and when the stop rule is reached without a valid result, that ADR's preflight status becomes a user-ruling item.
- Preflight barrier, then the preflight round. Only after every candidate of the round is written or explicitly abandoned — none awaiting resubmission, a ruling, or a valid report — run
/emergent-adr quality-reviewwithreview_mode: context_glossary_approval_preflightover the drafts actually written this round: one reviewer per draft in parallel, aggregating only after all complete; a single written draft runs directly; zero written drafts skips the preflight round entirely. - Incremental handling after preflight. A preflight result affects only its own ADR. Fix structural or wording findings in the foreground through
write's modify mode and rerun the preflight only for the modified ADR; glossary-approval needs go to the user itemized, at the merged ruling stop point above. The preflight never produces a finding that demands a change to decision content. - Two layers stay visible. Whenever an independent review was dispatched, the visible output keeps both the 🧭 self-check result and the reviewer's final result — approved, rejected with the stage that stopped it (the report's
rejected_at) and its failing judgment, or not completed; the reviewer's result never overwrites or hides the self-check. - ✅ emission. Emit the merged ✅ delivery-check block for the cycle's written files: ADR entries report the CONTEXT.md glossary-approval preflight pass (full ADR quality review and supersession scan have not run) — never word it as a completed
produceacceptance pass. Do not emit the 🔍 / 📣 scan blocks at interview time; no scan ran.
For CONTEXT.md-only writes, do not call a removed
/emergent-adrverification operation; apply the CONTEXT.md iron rule from step 1 and emit the ✅ delivery-check block only when the written entry is self-sufficient under this skill's local glossary rules. - Consume the round's results. After the review round's join, first write every approved candidate in the foreground with
Then, always — whether or not the answer was ratified:
-
Pending architecture-level items — maintain the running list, re-orient. Scan back through the conversation: which architecture-level questions have been asked but not yet ratified? This list serves two purposes: (a) it orients your next question to the whole design tree, not just the local exchange — architectural items that block other questions take precedence, and a pending item that makes a sub-question premature should defer that sub-question; (b) it is the running record that the closing gate will require.
Before asking the next question, state your current map in one line — addressed to the user — using the 🗺️ pending-items template in OUTPUT-FORMAT.md, showing the pending items and where the next question sits. This externalisation verifies your map is current and lets the user correct it if it has drifted.
Presented supersession markings stay out of this list: presenting the 📣 report was the review moment — no rollback requested means consent, and a presented marking is never re-reminded (the rollback right itself never expires; the user can still ask for a symmetric rollback at any later point).
Do not batch updates to CONTEXT.md or ADRs. A resolved term or decided trade-off that isn't written down now will be forgotten by the next session.
Output-turn structure — one aspect per turn
When an answer needs the user's ruling, one output turn handles only one aspect. The user's attention is the load-bearing resource of the grill: making them switch between several decisions in one turn degrades every ruling. The whole turn structure runs off a single distinction — does a block halt the flow until the user replies, or does it just report a completed result?
- A user ruling point halts the flow and cannot resume until the user replies with the ruling it asks for. A ruling point ends the output turn: you append no further decision question after it; the next aspect's question waits until the user has replied. Three ruling points have no corresponding single fixed-template block (so they cannot be classified by an OUTPUT-FORMAT.md tag and are stated here):
- the confirmation of a complete term candidate — a new entry or a semantic modification of an existing one — before it is written into CONTEXT.md (the CONTEXT.md write iron rule);
- the staged ADR delivery's merged ruling stop point — the itemized report of disputed review rejections, candidates whose review or write could not complete, preflight statuses left without a valid result, and glossary rulings raised by
write; it stops for the user's per-item rulings; - a design question you put to the user — the question itself. The closing checklist (🏁) is this kind too: each unratified item it puts back to the user to ratify or defer is a design question, which is why that block is a ruling point and the session cannot close until every item is handled.
- A non-blocking notification block reports a completed result, needs no reply, and does not end the turn — so it may sit in the same turn as that turn's single aspect question. The supersession report is one such block (presenting it is the review moment, so it does not halt the flow and is not a ruling point).
- The documentation gate does not run a whole batch of results plus the next question straight through. When any ruling point fires mid-cycle, the output turn ends at that ruling point; the next aspect's question is held until the user replies. The non-blocking notifications produced up to that point still print — only the next question is withheld.
This split is total: every stop/ask point in this skill is either a ruling point (it halts and waits) or a non-blocking notification (everything else this flow emits) — there is no third category, and none is left unclassified. The two categories are the CONTEXT.md terms user ruling point and non-blocking notification block. For each fixed output block, which class it is (and, for the supersession report, the consent-by-presentation semantics and its ADR basis) is single-sourced from that block's turn-role tag on its template in OUTPUT-FORMAT.md — not re-enumerated here. This refines, and does not replace, the documentation gate's per-block behaviour above.
Before declaring done — top-priority re-pass
When you reach the moment of thinking "I have no more questions" — do not enter the closing gate yet. Run this re-pass first.
What to generate. Up to three highest-priority questions you would ask next if you could only ask three more. Rank candidates by how strongly the answer would settle something meeting the ADR necessity conditions — the authority loaded through /emergent-adr read-necessity-conditions; the more architectural the candidate (the closer it sits to those conditions), the higher it ranks. This is a relative ordering, not a per-candidate checklist: you are using the conditions as the ranking axis, not ticking each candidate against boxes.
For each candidate, write three things:
- The question itself.
- Your recommended answer, with its basis-level labelled (which tier it would rest on, or that it is only a low-confidence guess) so the user can see which candidates are grounded versus guesses. You need not do the full grounding work (e.g. a web search) just to list a candidate — that happens if and when you actually ask it — but never hide that a candidate's answer is only a guess.
- A one-line justification of why this candidate's answer cannot be derived from the answers to the other two listed candidates. If you cannot write this justification, drop the candidate — it is a duplicate of one already listed, no matter how it surfaced in your head.
Rules.
- Before listing any candidate, run the filter in Asking each question. Only candidates that continue through that filter are listed.
- List at most three. If you can think of more than three real candidates, state out loud "I can think of N more candidates beyond these three" and continue with only the top three this round — do not raise the cap.
- If you cannot think of three, list only what you can — do not pad with filler to reach three.
- Listing a candidate is a commitment: you cannot retract by saying "actually never mind". If you listed it as top priority, it must be asked.
Show the user, in one block — the 🎯 block (template in OUTPUT-FORMAT.md).
- The 0–3 candidates with their justifications and your recommended answers (each answer carrying its basis level), laid out per the template.
- The template's closing line tells the user they can override the priorities, add a candidate you missed, or say "enough, move on" to skip to closing — and that silence means "go ahead, ask them".
Outcomes.
- Zero candidates → proceed to the closing gate.
- One to three candidates → ask them one by one (respecting the existing one-question-at-a-time rule). After the last is ratified, run this re-pass again — not the closing gate. Each round may resolve some pending items but also surface new sub-branches from the answers.
- User says "enough, move on" → proceed to the closing gate immediately, regardless of how many candidates were listed. The user's call is the deciding signal; the closing gate then handles any unresolved pending items the normal way.
The user is opt-in, not on hook. Silence from the user on the candidate block means "go ahead, ask them" — the user is not required to explicitly approve every round. Only an explicit override (priority change, addition, or "enough, move on") changes the default flow.
Multi-round behaviour, and the handoff this re-pass does not catch.
- This re-pass does not converge on its own. Each round resolves up to three pending items but answers may open new sub-branches, triggering another round. Convergence comes from the user calling "enough, move on", not from candidates exhausting themselves. This is by design: the cost of one more round of questions (the user can say "enough") is far smaller than the cost of stopping too early (a missed question vanishes silently into AFK execution).
- What this re-pass catches (agent self-disclosure can expose it). The "I am thinking of more but talked myself out of it" failure — you can think of the candidate, you just rationalised it away. When forced to list top three, you can produce it. This is the failure mode this re-pass exists for.
- What this re-pass cannot catch (agent self-disclosure cannot expose it). Two failures share this property despite different origins: (a) blind spots — candidates you genuinely cannot think of, which by definition will not appear in your list; (b) padding — candidates listed insincerely just to pass the gate, where you know they are weak but will not admit it. Both fail in your self-report and cannot be caught from within. They route to a downstream independent reviewer with a different vantage. The user reading the candidate block is the first line of defence against padding (a padded candidate is visible to them, though catching it depends on their familiarity and attention); the downstream independent review is the second.
Closing the grill — pending-items gate
After the top-priority re-pass concludes (outcome 1: zero candidates, or outcome 3: user said "enough, move on"), you may not end the session yet. Run this gate:
- Catch the last answer. Run the documentation gate against the user's most recent ratified answer — the same gate you would have run before asking the next question. The closing gate is the only opportunity this answer has to be filed; if you skip this step it falls through.
- List every architecture-level question that was asked but never ratified — items where the user discussed but did not give a clear "this is the answer" signal.
- Present this list to the user as the 🏁 closing-checklist block (template in OUTPUT-FORMAT.md) — its first line carries the documentation-gate outcome of the last answer (step 1), followed by the unratified list. For each item, the user must either ratify a decision now (in which case the documentation gate runs immediately on that item), or explicitly say "leave this unresolved, I will decide later".
- Only after every item has been either ratified or explicitly deferred may the session end.
You cannot bypass this gate by declaring the conversation done. The user did not ask any of these architecture-level questions — you did. The responsibility to confirm they have all been put to rest, one way or another, is yours.
Closeout authorization boundary
Finish every step this skill owns through the closing pending-items gate. The fact that the grill can close authorizes nothing beyond that work.
After the gate, determine the pending scope: explicit downstream work that the latest applicable instructions still permit, with every condition and limit applied, minus any part already completed. An unchanged request remains valid regardless of when it was made and needs no repeat or re-confirmation. Recognize it from ordinary language; do not require a fixed phrase, keyword, named skill, or special parser.
Execute exactly the pending scope. If it is empty, say plainly that the grill is done and wait for the user's next instruction. Only the user's explicit instructions can add work to the pending scope.
Questioning techniques
These are tools for executing the main task — surfacing what the user assumed but did not say. Use whichever helps reveal an implicit assumption in the moment. Do not run them as a checklist of their own.
Sharpen fuzzy language
When the user uses vague or overloaded terms, propose a precise canonical term. "You're saying 'account' — do you mean the Customer or the User? Those are different things." Fuzzy language is often where an implicit assumption hides — the user has one specific meaning in mind but uses a word that has several.
When you propose a canonical term, hold it to two standards:
-
Domain-specific, not generic. Avoid overloaded technical words that mean too many things across software in general — "dispatch", "handler", "processor", "manager", "service" — when used as a domain action or entity name. They lose all specificity inside this project's vocabulary. Prefer the word a domain expert would naturally say.
-
Length serves clarity, not brevity. A good compound name encodes structured domain information so the reader does not need to look elsewhere to understand it. For an entity, encode the entity plus any qualifying state or kind ("ShippedOrder" beats "Order" when shipped and unshipped behave differently). For an action, encode the entity plus the change plus any qualifying condition ("CancelShippedOrder" beats "cancel" when the domain has multiple cancellation flows).
The test name
test_user_cannot_cancel_shipped_orderis the model. Decompose it: the actor (user), the action (cannot cancel), the entity (order), the state (shipped). Four pieces of domain information, all in the name itself — reading the name alone tells you what behaviour is being tested. Apply the same decomposition lens to any compound term you propose: what pieces of domain information should this name carry, and which become invisible if you shorten it? The point of this lens is not naming as an end in itself — it is that a bad name often hides multiple implicit assumptions (which flow does "cancel" refer to? which entity state?), and decomposing forces those assumptions into the open where you can ask about them.
If you cannot meet both standards, ask the user for their own terminology rather than offering a generic name. A bad proposal anchors the conversation toward bad naming and is worse than no proposal.
Either way, a canonical term proposed here lives in the conversation only; it reaches CONTEXT.md solely through the documentation gate's complete-entry confirmation — the user liking the suggestion is not that confirmation.
Discuss concrete scenarios
When domain relationships are being discussed, stress-test them with specific scenarios. Invent scenarios that probe edge cases and force the user to be precise about the boundaries between concepts. Treat each scenario as a candidate question and run the filter in Asking each question. Useful when the user has described a happy path and implicitly assumed certain edge cases do not matter — surface those edge cases and make the assumption explicit.
Cross-reference with code
The code is your most reliable source of ground truth for what the system actually does right now. The user can misremember, CONTEXT.md can be stale, but the code is what is running. When user statements about system behaviour conflict with the code, the code wins as the record of what the system actually does — though "the code is what runs" doesn't mean "the code is what was decided"; sometimes the code is stale relative to a fresh decision (see the rename case below).
A separate authority applies for shared vocabulary, not system behaviour: when the user uses a term that conflicts with the ratified definition in CONTEXT.md, CONTEXT.md wins — the user may have used an unratified or outdated word. Don't silently translate; surface it: "You said X, but the ratified term in CONTEXT.md is Y — do you mean Y, or do we need to revisit this term?"
There are three trigger situations where you must cross-reference:
-
The user states how something currently works. Check whether the code agrees. If you find a contradiction, surface it: "Your code cancels entire Orders, but you just said partial cancellation is possible — is this a misremembered description, a new behaviour you want, or an existing bug?"
-
A CONTEXT.md term is being renamed or redefined. Check whether the codebase still uses the old name. If it does, the rename produces a downstream code-sync obligation — see the next paragraph.
-
You are about to write a new term to CONTEXT.md that describes a concept already present in the codebase. Check what the codebase already calls it. If the existing code uses a different name for the same concept, surface the divergence: "The code currently calls this
Foo— are we renaming toBar, or is this a different concept that just sounds similar?"
When you detect that a ratified rename in CONTEXT.md has corresponding occurrences in the existing codebase, surface this to the user explicitly. State it as a discrete codebase refactoring task that must be carried into the PRD: "This rename produces a refactoring task: rename {old} → {new} across the codebase (currently appears in {files or count}). This task should be tracked as a deliverable in the PRD." Do not start the code change yourself — grill is a planning phase, not an implementation phase. Confirm the user is aware the obligation will flow downstream.
When the cross-reference reveals the user's mental model differs from what the code actually does, the divergence is itself an implicit assumption being exposed — surface it for the user to resolve, don't quietly accept it and move on.