From 3ea85457fb41c59a6d8987ac84f7467326ba02e5 Mon Sep 17 00:00:00 2001 From: River Lynn Bailey Date: Fri, 11 Sep 2026 10:04:35 -0600 Subject: [PATCH 1/3] docs: plan the pre-build ask timing fix for issue #201 Issue #201 reports a pairing session that tucked the piece-3 pre-build ask under piece 2's stop, read "commit and next" as declining it, built piece 3 without the person's read, and wrote "ask declined" into the feedback record as the person's decision. The skill text permits it: the rule says the ask comes before the build and pairing Step 5 says "ask first", and neither forbids folding the ask into the previous stop. `docs/plans/gh-201-pre-build-ask-timing/` holds the change plan, its decision log, the current-state findings from a structural and behavioral discovery round, and the scope boundary. The plan re-scopes three sections of `collaborative-stop-rule.md` (and its two byte-identical copies), pairing Steps 5 and 6, and the pairing long-form doc, and pins every sentence the three files must agree on. Two behavior changes were put to the operator and accepted: the ask is a turn of its own that a stop never carries, and the record holds the person's words with the run's reading labeled as the run's. A review round with the junior developer, UX designer, and risk analyst extended the first change to a marked first piece, gave the ask's reply a recorded path, and named the run as the cause in the after-build message. Eight items sit under Deferred (YAGNI) with their reopening triggers. --- .../artifacts/change-decision-log.md | 361 ++++++++++++ .../artifacts/current-state-findings.md | 343 ++++++++++++ .../artifacts/scope-boundary.md | 60 ++ .../change-plan.md | 519 ++++++++++++++++++ 4 files changed, 1283 insertions(+) create mode 100644 docs/plans/gh-201-pre-build-ask-timing/artifacts/change-decision-log.md create mode 100644 docs/plans/gh-201-pre-build-ask-timing/artifacts/current-state-findings.md create mode 100644 docs/plans/gh-201-pre-build-ask-timing/artifacts/scope-boundary.md create mode 100644 docs/plans/gh-201-pre-build-ask-timing/change-plan.md diff --git a/docs/plans/gh-201-pre-build-ask-timing/artifacts/change-decision-log.md b/docs/plans/gh-201-pre-build-ask-timing/artifacts/change-decision-log.md new file mode 100644 index 00000000..8ce3c7bd --- /dev/null +++ b/docs/plans/gh-201-pre-build-ask-timing/artifacts/change-decision-log.md @@ -0,0 +1,361 @@ +# Change Decision Log: Pre-build ask timing (issue #201) + + + +## Trivial decisions + +- D-9: The three rule copies stay byte-identical by copying the canonical file over the other two after every edit, + checked with `md5 -q` printing one hash three times, and the rule edit ships as one change unit with its copies. — + Referenced in plan: Change Units, Risks. +- D-10: Nothing is cut for scope. The five backing skills are outside the boundary and need no edit, because the one + clause they can act on (S-1) lands in a section they already read (C-12). — Referenced in plan: Cut for Scope. +- D-11: The reason is classed as a finding already established, with issue #201 as its source; the issue is not a findings + report in the Step 2 sense, so this run ran its own discovery round. — Referenced in plan: Why This Change, Current + State. + +## Full decisions + +### D-1: Place each clause by the section whose responsibility it is + +- **Question:** Where in `collaborative-stop-rule.md` does the sequencing rule live: a new `##` section, a subsection of + "Asking before building, and when", or additions to the sections whose gaps the findings name? +- **Decision:** No new section and no subsection. The clause about a stop's scope goes into "What a stop presents". The + clauses about the ask's turn, what a decline is and is not, and a bundled ask go into "Asking before building, and + when", as bold-lead-in paragraphs, the device that section already uses (`**The test.**`, `**The ask itself**`, + `**Declining is a first-class answer.**`). "Acting on the answer", "Pace", "Who reads this", and `## Contents` are + unchanged. +- **Rationale:** C-3 locates the one-piece gap inside "What a stop presents"; fixing it elsewhere leaves the indicted + section silent and makes a stop's shape depend on a section five of its six readers never open (C-12). C-1 locates the + timing gap in a section titled "and when" that delivers only "before"; the fix makes the section deliver its title. C-5's + gap is a missing negative definition beside the positive one at line 96. A new `##` would be a second home for a + responsibility that already has one and would force a Contents edit (C-13). +- **Evidence:** C-1, C-3, C-5, C-12, C-13; software-architect proposal A1. +- **Behavior impact:** Changing, carried by the entries this decision places (see D-7). +- **Rejected alternatives:** + - A new `##` section "Sequencing the ask" — rejected because it splits one responsibility across two sections, adds a + Contents entry (C-13), and leaves "What a stop presents" silent on C-3. + - One paragraph in the ask section only — rejected because it does not touch the section C-3 indicts and leaves C-5's + decline clause with no negative definition, which is the misread the issue reports. +- **Revisit criterion:** A second rule about the ask's timing appears and the section grows past what a reader can hold. +- **Dissent (if any):** None. +- **Settles delta entry:** S-1, S-2 +- **Dependent decisions:** D-2, D-3, D-4 +- **Referenced in plan:** Target State, Surface Delta + +### D-2: The sequencing rule's sentences, pinned + +- **Question:** What are the exact sentences the rule and pairing Step 5 must agree on? +- **Decision:** Four pinned texts. The rule and the skill carry them; the plan's Target State section holds the full text + under "R1", "R2", "P1", and "P2". In short: + - R1, in "What a stop presents", after the reasoning-last paragraph: a stop covers what just closed and asks nothing + about a later piece; naming the work that comes next is a report, not a question; the one question posed about an + unbuilt piece is the pre-build ask, which has a turn of its own. + - R2, in "Asking before building, and when", after "The ask itself": `**The ask is a turn of its own.**` It opens the + marked piece's turn after the person has responded to the previous piece's stop, is the whole turn, and is never + appended to the previous stop, BECAUSE a reply to a stop is a reply to that stop's piece only. + - P1, pairing Step 5 item 1, replaced whole: the same four points in the loop's own terms (own turn after the previous + reply; ends the turn; a reply to the previous stop answers that piece only; a bundled ask is unanswered and is + presented now, on its own, before building). + - P2, pairing Step 5 item 3, one sentence appended after "their review matters most": naming the next concern is a + report about what comes next, never a question about it. A second sentence restating P1 and R1 was dropped at review + (JD-007); see D-16. +- **Rationale:** R1 is worded "what just closed" rather than "one piece" so it does not contradict "Pace" ("Honor a + request for more than one piece as asked") and leaves C-8 untouched. R1's second sentence keeps C-4's next-concern + naming standing by distinguishing a report from a question. P2 pins the mechanical location C-2 found only implied by + list order. +- **Evidence:** C-1, C-2, C-3, C-4; issue #201 "Suggested fix"; software-architect pins R1, R2, S1, S2. +- **Behavior impact:** Changing. A person sees the ask arrive as its own turn after their reply to the previous stop, + never inside it. User's answer: "accept as described" (D-7). +- **Rejected alternatives:** + - "A stop presents exactly one piece", the issue's wording — rejected because "Pace" already lets a person ask for + several pieces at once and a stop then presents them together (C-8); "what just closed" holds in both gears. + - Leaving Step 5 item 3 alone — rejected because C-4's next-concern sentence would then be the one forward-looking + instruction in the file with no line saying it is a report, not a question. + - A second P2 sentence, "A stop asks nothing about a later piece; a marked piece's ask waits for its own turn, at the + top of the next pass through this step" — rejected at review (JD-007) because R1 and P1 already say both. +- **Revisit criterion:** A report that a run still bundles the ask after these sentences land (reopens D-7 and the + deferred third repeated constraint). +- **Dissent (if any):** None. +- **Settles delta entry:** S-1, S-2, S-4 +- **Dependent decisions:** D-4, D-6, D-7, D-12, D-16 +- **Referenced in plan:** Target State, Surface Delta, Change Units + +### D-3: A reply to a stop answers that stop's piece, and a decline has a negative definition + +- **Question:** How does the text stop a reply aimed at piece N−1's stop from being read as declining piece N's ask, and + what happens to "never require an answer before building"? +- **Decision:** Rewrite the rule's decline paragraph (lines 96–97) as pinned under "R3" in the plan's Target State: + keep "Declining is a first-class answer" and its two examples; scope "Never re-prompt" to "once the person has + replied to the ask" (review finding JD-002, so R4's re-presentation is not a re-prompt); replace "never require an + answer before building" with "never hold the build for a fuller answer than the one given"; add "A decline is a reply + to the ask. A reply to the previous stop, or to the plan, is a reply to that alone, and never counts as declining an + ask the person has not yet answered." and "A question about the ask holds it open: answer the question and end the + turn again." (D-13). The long-form doc's tip at lines 99–100 changes to match (pinned as "L4"), including "advances + the piece" in place of "advances the stop" and "an ask you have not answered" in place of "have not seen" (review + finding UX-001, so the doc promises the same condition the rule delivers). +- **Rationale:** C-5 finds the decline clause defines what counts as a decline and never what does not, and routes + replies by content alone. The literal "never require an answer before building" licenses building with no reply, which + contradicts R2; the replacement keeps what the sentence meant (a decline is enough) and drops what it accidentally + allowed. C-9's "advances the stop" tells the person the ask and the stop are one thing, which is the conflation the + issue reports. +- **Evidence:** C-5, C-9; issue #201 corollary; software-architect R3 and D4; pairing decision log D7 ("a non-answer has + to be accepted"). +- **Behavior impact:** Changing. Nothing is built until the person replies to the ask itself; "I don't know" still + advances the piece. User's answer: "accept as described" (D-7). +- **Rejected alternatives:** + - Keep "never require an answer before building" — rejected because read literally it permits the exact build the + issue reports, and it contradicts R2. + - Put the attribution rule in "Acting on the answer" as a fourth route — rejected because the three routes classify + what the person volunteers, and the corollary restricts the run's reading of the run's own question, not the + person's content (architect A1). +- **Revisit criterion:** A report that a run held the build waiting for a fuller answer after a decline. +- **Dissent (if any):** None. +- **Settles delta entry:** S-2, S-6 +- **Dependent decisions:** D-6, D-7, D-12, D-13 +- **Referenced in plan:** Target State, Surface Delta + +### D-4: A bundled ask is handled at Step 5's re-entry, and Step 6 gains no route + +- **Question:** Where does the issue's fourth clause (re-present a bundled ask) live, and what does a run do when it + learns after the build that the ask was never engaged? +- **Decision:** The rule gains one paragraph, pinned as "R4" in the plan's Target State: `**A bundled ask is an + unanswered ask.**` When an earlier turn put the ask into a stop and the reply spoke only to that stop's piece, present + the ask again, on its own, before building; if the piece was already built when this comes to light, do not ask now, + say that the ask went unanswered, and continue from the stop in hand. Pairing carries the before-build half as the + last sentence of Step 5 item 1 (P1). Step 6 is unchanged: its re-show sentence "Do not return to the pre-build ask; + this piece is already built" already states the after-build half. +- **Rationale:** Step 6 routes the reply to piece N−1 and returns "to the top of Step 5", where item 1 fires the ask. + That re-entry already exists (C-2); item 1 was silent about an ask already mis-posed. C-7 finds no handler for the + after-build case; R4's second sentence supplies it and agrees with both Step 6 and the rule's own reason that an ask + after the build "collects the cost and none of the benefit". +- **Evidence:** C-2, C-7; issue #201 clause four; software-architect A4. +- **Behavior impact:** Changing. A run that bundled the ask asks again before building; a run that learns after the + build says so and moves on. User's answer: "accept as described" (D-7). +- **Rejected alternatives:** + - A fourth Step 6 route for "the ask was misread" — rejected because the loop already re-enters Step 5 item 1 before + building, so the route exists; a fourth route would restate it. + - Echo the after-build say-so sentence in Step 6 — rejected because Step 6 lines 186–187 carry the do-not-ask half + and pairing reads the whole rule for the rest; a third restatement has no finding behind it. +- **Revisit criterion:** A run re-asks after the build despite R4. +- **Dissent (if any):** None. +- **Settles delta entry:** S-2, S-4 +- **Dependent decisions:** D-7, D-14 +- **Referenced in plan:** Target State, Surface Delta + +### D-5: The record holds the person's words, and the run's reading is marked as the run's + +- **Question:** What stops a run's interpretation ("ask declined") from entering the feedback record as the person's + decision? +- **Decision:** The rule's "Recording what the person says" gains one paragraph, pinned as "R5" in the plan's Target + State: an entry holds the person's words and names the stop or ask they answered; a reading the run adds follows the + words and is marked as the run's, never written as what the person decided; an ask with no entry is an ask with no + answer. R5 carries one worked example of an entry, because the entry's form is a contract the rule, Step 6, and the + doc must agree on and the contract-pinning rule closes one with an example, not a description (review finding JD-006; + D-15). Pairing Step 6's first sentence becomes "Write the response into the record, in the person's words and against + the stop or ask it answers, before acting on it." (P3), and a reply to the ask is recorded against the ask by P1 + (D-13). The doc's line 85 changes to match and says any reading the skill adds is labeled as its own (L3, review + finding UX-007). No new field, schema, or three-state marker. +- **Rationale:** C-6 finds the record instruction never says the record holds the person's words rather than the run's + label, and the doc already promises "which piece prompted it" with nothing delivering it. The issue reports the wrong + label reaching the record. Two sentences make the promise true and make "ask declined" unwritable as the person's + decision. "No entry, no answer" closes the never-presented state by derivation, not by a field. +- **Evidence:** C-6, C-9; issue #201 "What didn't work" second bullet; software-architect A3. Unverified: the 2026-09-03 + record itself could not be inspected; whether "ask declined" was a label or a paraphrase is taken from the issue. +- **Behavior impact:** Changing. A person reading the record sees their own words with the run's reading labeled as + such. User's answer: "accept the change as described" (D-8). +- **Rejected alternatives:** + - Nothing, relying on the sequencing rule — rejected because doc lines 30 and 85 would keep promising what no text + delivers, and a future misread of any kind could still land as the person's decision. + - A three-state marker per ask (answered, declined, never presented) — rejected by the simpler-version test; deferred + with its trigger in the plan. +- **Revisit criterion:** A second report of the record misstating an ask outcome after R5 lands. +- **Dissent (if any):** None. +- **Settles delta entry:** S-3, S-5, S-6 +- **Dependent decisions:** D-6, D-8, D-13, D-15 +- **Referenced in plan:** Target State, Surface Delta + +### D-6: The long-form doc promises exactly what the rule delivers + +- **Question:** What does the person get told, so the expectation the issue reports matches a promise the doc makes? +- **Decision:** Five edits to `han-core/docs/skills/pairing.md`, pinned as "L1" to "L5" in the plan's Target State, + each delivering one rule sentence: "A stop" gains "and the stop asks you nothing about a later piece" (R1); "The + pre-build ask" gains the own-turn promise (R2, R3); line 85 gains "in your words, and which stop or ask prompted it" + (R5); the tip at lines 99–100 says "advances the piece" and that approving the previous piece never declines an ask + you have not answered (R3); and the "Cost and latency" line at 117–118 adds one more turn for each marked piece, + because R2 makes the existing "plus one turn per stop" false for a marked piece (review finding UX-006). An earlier + L5, one sentence appended to "Why the ask comes before the build", was dropped at review as a second delivery of R2 + with an uncited mechanism claim (JD-008; D-16). +- **Rationale:** C-9 finds the doc's commitment is narrower than the expectation the issue reports and that its tip + blurs the ask into the stop. A doc that promises more than the rule delivers, or less, is a broken contract with the + reader. +- **Evidence:** C-9, C-6; software-architect D1–D5. +- **Behavior impact:** Preserving. The doc changes no run's behavior; it describes what S-1 through S-5 make true. +- **Rejected alternatives:** + - Leave the doc and let the rule speak — rejected because the doc is the surface the person reads (C-9), and the + issue's expectation came from a reader, not from the rule. + - Leave the cost line alone — rejected because an existing sentence becomes false under R2, which is evidence in its + own right, not an addition. +- **Revisit criterion:** Any later edit to R1–R5. +- **Dissent (if any):** None. +- **Settles delta entry:** S-6 +- **Dependent decisions:** — +- **Referenced in plan:** Target State, Surface Delta, Change Units + +### D-7: The user accepted the sequencing change at the behavior gate + +- **Question:** Does the user accept that the ask becomes its own turn, a stop never carries it, a bundled ask is + re-presented before the build, an after-build discovery is named rather than re-asked, and "never require an answer + before building" goes? +- **Decision:** Accepted in full. +- **Rationale:** The gate escalates every behavior-changing entry whether or not it looks desirable. The question led + with what the person sees at piece 2's stop and piece 3's turn, offered accepting without the after-the-fact clause and + declining as alternatives, and recommended accepting. +- **Evidence:** User input, verbatim: "accept as described". +- **Behavior impact:** Changing, as described in D-2, D-3, D-4. +- **Rejected alternatives:** + - Accept without the after-the-fact clause — offered and not chosen. + - Decline — offered and not chosen. +- **Revisit criterion:** The user reopens it. +- **Dissent (if any):** None. +- **Settles delta entry:** S-1, S-2, S-4 +- **Dependent decisions:** — +- **Referenced in plan:** Behavior Changes + +### D-8: The user accepted the record change at the behavior gate + +- **Question:** Does the user accept that the record holds their words with the run's reading marked as the run's, a + step past the issue's "Suggested fix" paragraph? +- **Decision:** Accepted. +- **Rationale:** The question said plainly that this goes one step past the suggested fix and why it was planned (the + issue's second effect, and the doc's undelivered promise), and offered declining as the alternative. +- **Evidence:** User input, verbatim: "accept the change as described". +- **Behavior impact:** Changing, as described in D-5. +- **Rejected alternatives:** + - Decline — offered and not chosen. +- **Revisit criterion:** The user reopens it. +- **Dissent (if any):** None. +- **Settles delta entry:** S-3, S-5 +- **Dependent decisions:** — +- **Referenced in plan:** Behavior Changes + +### D-12: A marked first piece takes its ask after the plan, and the plan is treated like a stop for attribution + +- **Question:** When the first piece of a plan is the marked one, there is no "previous piece's stop"; the previous turn + is the plan proposal. Can a run append piece 1's ask to the plan and read "looks good" as declining it? +- **Decision:** R2, R3, P1, and L2 say "the previous stop, or the plan when the marked piece is the first", and "a reply + to a stop or a plan is a reply to that alone". R4 says "a stop or the plan". R1 is unchanged; the plan turn is not a + stop and does not gain the four elements. +- **Rationale:** Step 4 ends "Then wait. The person accepts the plan, changes it, or replaces it", so the plan is a turn + the person replies to, and the rule's test at line 77 ("later pieces in the plan would have to be redone to undo it") + makes piece 1 the likeliest marked piece. Without this clause the incident's shape recurs with a different host turn. + The user accepted "the ask becomes its own turn, and a stop never carries it" (D-7); this extends the same behavior to + the one turn that precedes piece 1. Settled from evidence as a necessity of the accepted change, not re-escalated; the + Step 10 summary names it so the user can strike it. +- **Evidence:** Review findings JD-005 and UX-008 (merged); `pairing/SKILL.md` line 145; rule line 77. +- **Behavior impact:** Changing, within D-7's scope: the plan-approval turn carries no ask for piece 1, and "looks + good" never declines one. +- **Rejected alternatives:** + - Say "the previous turn" without naming the plan — rejected because the person reads L2, and "turn" is not a term the + doc has given them; "stop" and "plan" both are. + - Leave piece 1 uncovered — rejected because the reversibility test makes it the likeliest marked piece. +- **Revisit criterion:** The user strikes it, or a report shows the plan turn carrying an ask after this lands. +- **Dissent (if any):** None. +- **Settles delta entry:** S-2, S-4, S-6 +- **Dependent decisions:** — +- **Referenced in plan:** Target State, Surface Delta, Behavior Changes + +### D-13: A reply to the ask is recorded against the ask and then the build begins; it is not routed through Step 6 + +- **Question:** P1 ends the turn after the ask. The reply lands somewhere. Step 6's three routes all presuppose a built + piece ("Fix it within that piece and show it again"), and a question in reply to the ask has two handlers ("Never + re-prompt" in R3; "A question holds the person's place" at Step 6 line 193). +- **Decision:** P1 gains a paragraph: "When the reply arrives, write it into the record in the person's words, against + this ask, then build. A declined answer is a complete one, and a question about the ask holds it open: answer it and + end the turn again. The reply is not routed through Step 6, which handles replies to a stop." R3 gains the matching + clause "A question about the ask holds it open: answer the question and end the turn again." +- **Rationale:** C-2 shows the loop's re-entry is by list order; once item 1 ends the turn, the executing run needs the + next step named or it will either route the reply through Step 6 (nonsense for an unbuilt piece) or skip recording it + (the record defect D-5 fixes). The question clause is a necessity of taking ask replies out of Step 6, because line + 193 then no longer covers them. +- **Evidence:** Review findings JD-001 and UX-005 (merged), JD-009; C-2, C-6; `pairing/SKILL.md` line 193. +- **Behavior impact:** Changing, within D-7 and D-8: the person's reply to the ask is recorded in their words, a + question about the ask gets an answer and the ask stays open. +- **Rejected alternatives:** + - A fourth Step 6 route for ask replies — rejected because the three routes are about a built piece and a fourth would + carry an exception to each of them. + - Leave the question case to line 193 — rejected because P1 takes ask replies out of Step 6, so 193 no longer applies. +- **Revisit criterion:** A report of a run building on a clarifying question, or of an ask reply missing from the + record. +- **Dissent (if any):** None. +- **Settles delta entry:** S-2, S-4 +- **Dependent decisions:** — +- **Referenced in plan:** Target State, Surface Delta + +### D-14: The after-build message names the run as the cause + +- **Question:** R4's "say that the ask went unanswered" names no cause. The person did answer the turn in front of them; + "unanswered" lands on them, which is the attribution defect the issue's second effect reports on another surface. +- **Decision:** R4's after-build sentence reads "say that the run put the ask under an earlier turn so it went + unanswered, and continue from the stop in hand." No offer to re-ask. +- **Rationale:** The overrun clause at rule lines 67–69 is the precedent: it names cause, extent, and offer. The + smallest form that names the cause is one clause. Not re-asking matches lines 73–75. +- **Evidence:** Review finding UX-002; rule lines 67–69, 73–75; issue #201 second effect. +- **Behavior impact:** Changing, within D-7: the after-build message says the run caused the loss. +- **Rejected alternatives:** + - Keep the passive — rejected because it reads as the person's omission. + - Add an offer to re-ask — rejected because an ask after the build "collects the cost and none of the benefit". +- **Revisit criterion:** A report that the message still reads as blame. +- **Dissent (if any):** None. +- **Settles delta entry:** S-2 +- **Dependent decisions:** — +- **Referenced in plan:** Target State + +### D-15: One worked example pins the record entry's form + +- **Question:** R5 says a run's reading is "marked as the run's". Marked how? The rule, P3, and L3 must agree on an + entry's shape. +- **Decision:** R5 gains one example: an entry reads, for example, "Piece 2 stop: 'commit and next' (run's reading: + approved)". No field, no template, no marker syntax beyond the example. +- **Rationale:** The contract-pinning rule closes a contract with a worked example; a prose description does not. D-5 + rejected a field by the simpler-version test, and an example is not a field. Without it, "ask declined" beside the + quote, unlabeled, still satisfies a loose reading. +- **Evidence:** Review finding JD-006; UX-007 (which found the form rightly unpinned as a schema and the doc silent on + the marking); `han-planning/references/contract-pinning-rule.md`. +- **Behavior impact:** Changing, within D-8. +- **Rejected alternatives:** + - Pin a marker syntax — rejected as over-specification with no incident behind it (UX-007). +- **Revisit criterion:** A report that a person could not tell their words from the run's in the file. +- **Dissent (if any):** None. +- **Settles delta entry:** S-3, S-6 +- **Dependent decisions:** — +- **Referenced in plan:** Target State + +### D-16: Two restatements are dropped as YAGNI + +- **Question:** P2's second sentence restates R1 and P1; the original L5 delivers R2 a second time with an uncited + mechanism claim. Does the reason justify either? +- **Decision:** P2 keeps only "That is a report about what comes next, never a question about it." The original L5 is + dropped and recorded under Deferred (YAGNI); the L5 label now names the cost-line edit (UX-006). +- **Rationale:** The simpler-version test. The issue asks for one echo in Step 5, and P1 is it. L2 already delivers R2 + to the person. +- **Evidence:** Review findings JD-007, JD-008; `han-planning/references/yagni-rule.md` Gate 2. +- **Behavior impact:** Preserving; nothing observable changes by dropping a repeat. +- **Rejected alternatives:** + - Keep both — rejected because neither has a finding of its own. +- **Revisit criterion:** A report of a run posing the ask from item 3's next-concern line, or a reader asking why the + ask is a separate turn. +- **Dissent (if any):** None. +- **Settles delta entry:** S-4, S-6 +- **Dependent decisions:** — +- **Referenced in plan:** Target State, Deferred (YAGNI) diff --git a/docs/plans/gh-201-pre-build-ask-timing/artifacts/current-state-findings.md b/docs/plans/gh-201-pre-build-ask-timing/artifacts/current-state-findings.md new file mode 100644 index 00000000..edef8222 --- /dev/null +++ b/docs/plans/gh-201-pre-build-ask-timing/artifacts/current-state-findings.md @@ -0,0 +1,343 @@ +# Current State Findings: Pre-build ask timing (issue #201) + +## Provenance + +Produced by this run's own discovery round on 2026-09-11. `han-core:structural-analyst` and `han-core:behavioral-analyst` +were each given the area named in [scope-boundary.md](scope-boundary.md): the canonical +`han-core/references/collaborative-stop-rule.md` with its two vendored copies, `han-core/skills/pairing/SKILL.md`, and +`han-core/docs/skills/pairing.md`. `han-core:concurrency-analyst` was not dispatched; the area holds no concurrent +access. The structural analyst read the five backing skills' "Running collaboratively" paragraphs only to confirm which +sections of the rule they depend on (C-12). GitHub issue #201 is the recorded reason, not a findings report; nothing here +was extracted from it. + +The project-context items below come from this run's own sweep, not from the specialists. + +## Project Context + +- **Stack:** Markdown skill, agent, and rule text executed by Claude Code, plus Bash under `scripts/`. No application + build. `npm run lint` runs Prettier, ShellCheck, and file-hygiene hooks; `npm test` runs Bats over `*.bats` files + (from CLAUDE.md `## Project Discovery`). +- **Conventions source:** `CLAUDE.md` at the repo root. The authoring guidance for skills lives under + `han-plugin-builder/skills/guidance/references/`. +- **ADRs found:** `docs/adr/0001-project-configurable-default-swarm-size.md` only. It does not concern pairing or the + stop rule. +- **Coding standards found:** `han-communication/references/writing-voice.md` and `readability-rule.md` govern every + doc's prose. `han-plugin-builder/skills/guidance/references/skill-building-guidance/progressive-disclosure.md` line 53 + keeps a SKILL.md body under 500 lines, and `skill-reference-files.md` lines 114–116 require a `## Contents` list on any + reference file over roughly 100 lines. +- **Recent churn:** In the last 90 days the three rule copies changed twice (2026-08-14 `432d1b9` creation, 2026-08-20 + `33ed427` contents-list sweep). `pairing/SKILL.md` changed three times (2026-08-14 creation `2ac091e`, 2026-08-14 + `66fd62b` concern splitting, 2026-08-19 `0e5f44f` config script). `docs/skills/pairing.md` changed three times, all on + 2026-08-14. No commit since 2026-08-20 has touched the area. +- **Design record:** `docs/plans/pairing-skill/artifacts/decision-log.md` carries the decisions that shaped the ask + protocol. D7 settled "the ask comes before the build" and "declining is a first-class response", and rejected "keeping + the ask at the stop after the build, as first drafted — rejected because it inverts the mechanism its own evidence + depends on". D14 settled that the plan announces the reversibility marking so the ask can precede the build. + +## Gaps + +- No ADR records the collaborative stop rule or the pre-build ask. The design rationale exists only in the pairing plan's + decision log (above) and in the long-form doc's "Why it works this way" section. +- No automated test covers any prose in the area. Bats tests exist only beside shell scripts; a wording change here is + verified by reading, and by `npm run lint` for formatting. +- `CONTRIBUTING.md` does not mention `collaborative-stop-rule.md` or the byte-identical vendoring requirement (C-11). +- No file in the area, and no file elsewhere, states what a reply to a stop is a reply to (C-5). + +## Findings + +### C-1: The rule requires the ask to precede the build, and says nothing about which turn carries it + +- **Claim:** The canonical rule's only timing constraint on the pre-build ask is that it comes before the build; it does + not require the ask to be its own turn or to follow the previous piece's stop. "Not at the stop afterward" refers to the + marked piece's own stop. +- **Location:** `han-core/references/collaborative-stop-rule.md`, lines 71–75, section "Asking before building, and when" +- **Evidence:** + + ```markdown + For a piece carrying a choice that is expensive to walk back, the ask comes **before** the build, not at the stop + afterward. Committing to your own expectation before the answer exists is the mechanism; an ask arriving once the work + is on disk collects the cost and none of the benefit. + ``` + +- **Raised by:** structural-analyst S-1, behavioral-analyst B-1 +- **Confidence:** Verified +- **Bears on:** S-1, S-2, D-1, D-2 + +### C-2: Pairing Step 5 echoes the ask as "ask first" and gets turn separation only from the loop's item order + +- **Claim:** Step 5 places the ask at item 1 and "End the turn" at item 4. Followed mechanically, the ask for piece N fires + after Step 6 has routed the reply to piece N−1's stop and returned "to the top of Step 5". That ordering is implied by + the list, never stated as a rule, and nothing forbids appending the ask to the tail of the previous stop, which still + precedes the build. Step 5 also says "a complete one" where the rule says "first-class answer". +- **Location:** `han-core/skills/pairing/SKILL.md`, lines 152–154 and 175–176; Step 6 line 188 +- **Evidence:** + + ```markdown + 1. **If the plan marked this piece expensive to walk back, ask first.** Follow the ask protocol in the stop rule: name + the dimension the choice turns on, offer no candidate answers, and accept a declined answer as a complete one. The ask + comes before the build, never after. + ``` + + ```markdown + 4. **End the turn.** Nothing further is built until the person responds. **Starting the next concern is not an + exception**, however directly it follows from the one that just closed. + ``` + + ```markdown + - **What comes next.** Carry it into the next piece and return to the top of Step 5. + ``` + +- **Raised by:** structural-analyst S-2, behavioral-analyst B-1 +- **Confidence:** Verified +- **Bears on:** S-2, S-4, D-2, D-13 + +### C-3: "What a stop presents" does not scope a stop to one piece or forbid forward-looking content + +- **Claim:** The four required elements of a stop, and the "Then end the turn" instruction, never say a stop presents + exactly one piece or carries no question about a later one. The Position element is forward-looking by design ("what + remains"), scoped to reporting, not asking. +- **Location:** `han-core/references/collaborative-stop-rule.md`, lines 51–65 +- **Evidence:** + + ```markdown + 1. **Position.** Which piece this is against the plan, and what remains. A person deciding whether they have the + attention for two more pieces cannot answer that without it. + ... + Then end the turn. Nothing further is built until the person responds. + ``` + +- **Raised by:** structural-analyst S-3 +- **Confidence:** Verified +- **Bears on:** S-1, D-1, D-2 + +### C-4: Step 5 already authorizes one kind of forward-looking content in a stop: naming the next concern + +- **Claim:** The stop's position line is told to name the concern that comes next when a piece closes a concern. That is + a report about the future, not a question about it, and any new rule against forward-looking questions has to leave it + standing. +- **Location:** `han-core/skills/pairing/SKILL.md`, lines 172–173 +- **Evidence:** + + ```markdown + When the piece closes a concern, say so in the position line and name the concern that comes next. That tells the + person the next response starts different work, which is the moment their review matters most. + ``` + +- **Raised by:** structural-analyst S-4 +- **Confidence:** Verified +- **Bears on:** S-1, S-4, D-2, D-16 + +### C-5: A reply is routed by what it touches, never by which question it answers, and the decline clause has no negative definition + +- **Claim:** Step 6 and the rule's "Acting on the answer" classify a reply by its content into three routes. Neither says + which piece a reply belongs to. "Declining is a first-class answer" defines what counts as a decline and never what does + not, so a reply aimed at piece N−1's stop has no textual barrier to being read as declining a bundled piece-N ask. The + one adjacent guard, "A question holds the person's place", governs the person's questions, not the run's. +- **Location:** `han-core/references/collaborative-stop-rule.md`, lines 96–97 and 112–125; + `han-core/skills/pairing/SKILL.md`, lines 178–193 +- **Evidence:** + + ```markdown + **Declining is a first-class answer.** "I don't know" and "just show me" advance the piece exactly as a considered + answer does. Never re-prompt, and never require an answer before building. + ``` + + ```markdown + Three routes, by what the feedback touches. + ``` + + ```markdown + **A question holds the person's place; it never advances the work.** Answer it and stop again at the same place. + ``` + +- **Raised by:** structural-analyst S-5, behavioral-analyst B-2 +- **Confidence:** Verified +- **Bears on:** S-2, S-6, D-3 + +### C-6: The record holds whatever the run writes, and nothing distinguishes an answered ask from a declined one from one never presented + +- **Claim:** Both files say to write the response into the record before acting on it, and neither says the record holds + the person's words rather than the run's label. A label like "ask declined" enters persisted state at that step. The + only detection is passive (the person reads the record), and the provenance clause fires only after a later piece is + built on the entry. The long-form doc says the record holds "which piece prompted it", a property the rule and SKILL.md + never describe as a mechanism. +- **Location:** `han-core/references/collaborative-stop-rule.md`, lines 105–110; `han-core/skills/pairing/SKILL.md`, + lines 180–181; `han-core/docs/skills/pairing.md`, line 85 +- **Evidence:** + + ```markdown + Write every piece of feedback into the running record before acting on it. A correction given at the second stop has to + still apply at the seventh, and mid-context material is the least reliably recalled. + + The person can read the record whenever they ask. When a recorded entry shapes a later piece, name which entry it was, + ``` + + ```markdown + The record holds each piece of feedback you gave and which piece prompted it. + ``` + +- **Raised by:** behavioral-analyst B-3, structural-analyst S-6 +- **Confidence:** Verified +- **Bears on:** S-3, S-5, S-6, D-5, D-15 + +### C-7: No existing error path covers a build made on a misread ask, and the re-show route forbids returning to the ask + +- **Claim:** The overrun clause fires when a stop is skipped; in the issue's scenario no stop was skipped. The re-show + route is the only defined correction for a built piece and says "Do not return to the pre-build ask; this piece is + already built." The text names no handler for learning, later, that the ask was never engaged. +- **Location:** `han-core/references/collaborative-stop-rule.md`, lines 67–69; `han-core/skills/pairing/SKILL.md`, + lines 185–187 +- **Evidence:** + + ```markdown + That last instruction is a directive, not a guarantee. Nothing in the platform enforces it. When a run does build past a + stop, the next thing it says names the overrun, states which pieces went unreviewed, and offers to walk back through + them. Never present unreviewed work as though it had been approved. + ``` + + ```markdown + - **The piece in hand.** Fix it within that piece and show it again, naming the correction and what it touched. That + re-show is a stop, so return to Step 5's fourth instruction and wait. Do not return to the pre-build ask; this piece is + already built. + ``` + +- **Raised by:** behavioral-analyst B-4 +- **Confidence:** Verified +- **Bears on:** S-2, D-4, D-14 + +### C-8: The batching and finish-without-stopping paths never mention the ask + +- **Claim:** "More than one piece at a time" and "finish without stopping" say nothing about a marked piece inside the + batch or the remainder, so the text does not say whether the ask fires, is absorbed, or goes unreviewed. +- **Location:** `han-core/skills/pairing/SKILL.md`, lines 195–199; `han-core/references/collaborative-stop-rule.md`, + lines 129–131 +- **Evidence:** + + ```markdown + **When the person asks for more than one piece at a time**, honor it as asked, present the pieces together, and return + to the normal pace at the following stop without being asked to. + + **When the person says to finish without stopping**, acknowledge it in the same turn and name what will now go + unreviewed, then continue from the current plan and report at the end. + ``` + +- **Raised by:** behavioral-analyst B-5 +- **Confidence:** Verified +- **Bears on:** Deferred (YAGNI), D-2 + +### C-9: The long-form doc promises "before it builds" and says declining advances "the stop" + +- **Claim:** The doc's commitment to the person is narrower than the expectation the issue reports. It says the ask + arrives before the build, not that it arrives as its own turn after the previous piece is approved. Its tips section says + declining "advances the stop" where the rule says "advance the piece", blurring the ask and the stop. +- **Location:** `han-core/docs/skills/pairing.md`, lines 28–29, 99–100, 144–147 +- **Evidence:** + + ```markdown + - **The pre-build ask.** For a piece the plan marked expensive to walk back, the skill asks what you expect before it + builds. Declining is a complete answer. + ``` + + ```markdown + - **Answer the pre-build ask honestly, including with "I don't know."** Declining advances the stop exactly as a + considered answer does. The ask exists to get an independent read, and a manufactured guess is worth less than none. + ``` + +- **Raised by:** behavioral-analyst B-6, structural-analyst S-8 +- **Confidence:** Verified +- **Bears on:** S-6, D-3, D-6 + +### C-10: The two constraints pairing repeats from the rule do not include ask timing + +- **Claim:** SKILL.md's preamble repeats two constraints it calls "the ones most easily lost": the pacing and the stop's + ordering. Ask timing is not among them and is paraphrased once, at Step 5 item 1. +- **Location:** `han-core/skills/pairing/SKILL.md`, lines 36–42 +- **Evidence:** + + ```markdown + Two constraints from that file govern every step below and are repeated here because they are the ones most easily lost: + + - **The pacing is the deliverable.** ... + - **A stop hands over something to check, never a case for the work.** ... + ``` + +- **Raised by:** structural-analyst S-7 +- **Confidence:** Verified +- **Bears on:** Deferred (YAGNI) + +### C-11: The three rule copies are byte-identical, and two places record the obligation to keep them so + +- **Claim:** `md5` of all three copies is `29db7843077527d17ff7c515b8b062fc`. The rule's own line 20 and `CLAUDE.md` + line 266 state the byte-identical requirement. `CONTRIBUTING.md` does not mention it. +- **Location:** `han-core/references/collaborative-stop-rule.md`, line 20; `CLAUDE.md`, lines 120, 127, 266–267 +- **Evidence:** + + ```markdown + Every vendored copy of this file is byte-identical to the canonical `han-core/references/collaborative-stop-rule.md`. + ``` + + ```markdown + `iterative-plan-review`, and `plan-implementation`. Vendored byte-identical into `han-coding/references/` and + `han-planning/references/`; edit the canonical copy and re-sync the others. + ``` + +- **Raised by:** structural-analyst S-9, this run's sweep +- **Confidence:** Verified +- **Bears on:** Change Unit 1, D-9 + +### C-12: The backing skills' required reading excludes the ask section, and all five read only the stop's shape + +- **Claim:** "Who reads this" makes "Detecting the flag" and "What a stop presents" the whole contract for a backing skill. + All five backing skills' "Running collaboratively" paragraphs cite the rule only for the shape of the stop. A new rule + placed under "Asking before building, and when" binds `pairing` alone unless "Who reads this" changes. +- **Location:** `han-core/references/collaborative-stop-rule.md`, lines 26–30; `han-coding/skills/tdd/SKILL.md` + 253–256; `han-coding/skills/refactor/SKILL.md` 136–139; `han-coding/skills/design-an-api/SKILL.md` 206–209; + `han-planning/skills/iterative-plan-review/SKILL.md` 357–362; `han-planning/skills/plan-implementation/SKILL.md` + 359–364 +- **Evidence:** + + ```markdown + **A skill that gains the collaborative flag** reads "Detecting the flag" and "What a stop presents." Those two sections + are the whole contract for a backing skill. Nothing else here is required reading to add the flag correctly. + ``` + + ```markdown + **Running collaboratively.** When the request asks to review each behavior as it lands, which is what `pairing` does + when it hands work here, stop at this point and hand control back instead of continuing. Present the stop in the shape + [collaborative-stop-rule.md](../../references/collaborative-stop-rule.md) specifies. + ``` + +- **Raised by:** structural-analyst S-10 +- **Confidence:** Verified +- **Bears on:** S-1, D-1, D-10, Risks + +### C-13: The rule file carries a Contents list that a new section must join + +- **Claim:** The rule is 137 lines and opens with a `## Contents` list of its seven `##` headings, as the authoring + guidance requires for a reference file over roughly 100 lines. `pairing/SKILL.md` is 207 lines, well under the 500-line + body guideline, so an added paragraph needs no relocation into `references/`. +- **Location:** `han-core/references/collaborative-stop-rule.md`, lines 3–11; + `han-plugin-builder/skills/guidance/references/skill-building-guidance/skill-reference-files.md`, line 116 +- **Evidence:** + + ```markdown + ## Contents + + - Who reads this + - Detecting the flag + - What a stop presents + - Asking before building, and when + - Recording what the person says + - Acting on the answer + - Pace + ``` + +- **Raised by:** this run's sweep +- **Confidence:** Verified +- **Bears on:** D-1 + +## Findings No Agent Could Audit + +Every evidence class was covered. The area is prose on disk, read in full by both analysts and by this run. The one +thing no one can inspect is the 2026-09-03 session transcript the issue describes; the issue's account of it is taken as +the recorded reason, not as a finding about the text. diff --git a/docs/plans/gh-201-pre-build-ask-timing/artifacts/scope-boundary.md b/docs/plans/gh-201-pre-build-ask-timing/artifacts/scope-boundary.md new file mode 100644 index 00000000..0a419868 --- /dev/null +++ b/docs/plans/gh-201-pre-build-ask-timing/artifacts/scope-boundary.md @@ -0,0 +1,60 @@ +# Scope Boundary: Pre-build ask timing (issue #201) + +## Work Item + +GitHub issue #201 in `testdouble/han`, "Han Feedback: pairing-tdd-han-feedback (2026-09-03)", read through +`gh issue view 201 --repo testdouble/han` on 2026-09-11. It is a feedback report from a pairing session that drove a +four-behavior TDD rewrite. The issue is open, unlabeled, and has no comments. + +## Stated Scope + +The issue's "Suggested fix" paragraph, quoted word for word: + +> Add an explicit rule to `collaborative-stop-rule.md` (and echo it in pairing Step 5): the pre-build ask for piece N is +> its own turn, presented only after the person has responded to the piece N−1 stop. A stop presents exactly one piece +> and asks nothing about future pieces. Corollary: a response to a stop is a response to that stop's piece only — it +> must never be read as answering, or declining, a question about a later piece. If a run has already bundled the ask +> and the reply addresses only the previous piece, the ask is unanswered: re-present it in its own turn before building. + +The issue's "Overall" paragraph restates the fix as: + +> The fix is a sequencing rule: one stop, one piece, no forward-looking questions; the ask for a marked piece opens that +> piece's turn, after the previous piece is approved, and a reply to a stop never answers a question about a later +> piece. + +The issue also names a second effect of the defect, under "What didn't work": + +> The misread compounded silently. The run recorded "ask declined" in the feedback record as if it were the person's +> decision, so the record itself carried the wrong fact until the person corrected it. + +## Stated Exclusions + +None stated. + +## Operator-Stated Scope + +The operator invoked `/han-planning:plan-a-change for https://github.com/testdouble/han/issues/201` and, at the +confirmation turn, accepted the area as proposed with "looks good". The proposed area was: + +- `han-core/references/collaborative-stop-rule.md`, the canonical rule, plus its two byte-identical vendored copies in + `han-coding/references/` and `han-planning/references/` +- `han-core/skills/pairing/SKILL.md`, Steps 5 and 6 +- `han-core/docs/skills/pairing.md`, the long-form doc + +The five backing skills (`tdd`, `refactor`, `design-an-api`, `iterative-plan-review`, `plan-implementation`) were +proposed as outside the area, on the ground that they read only the "Detecting the flag" and "What a stop presents" +sections of the rule and the ask belongs to the driving loop. The operator accepted that exclusion. + +## Direction of Travel + +Unanswered. The confirmation turn did not ask whether the pre-build ask or the collaborative stop rule is being +deprecated, replaced, or migrated away from. Nothing in the issue or the conversation suggests it is: the issue asks for +the ask protocol's timing to be tightened, not for the protocol to go. + +## Visual Material Received + +None received. + +## Record Provenance + +Established by `plan-a-change` in this run on 2026-09-11. Not inherited. diff --git a/docs/plans/gh-201-pre-build-ask-timing/change-plan.md b/docs/plans/gh-201-pre-build-ask-timing/change-plan.md new file mode 100644 index 00000000..5d795bcd --- /dev/null +++ b/docs/plans/gh-201-pre-build-ask-timing/change-plan.md @@ -0,0 +1,519 @@ +# Change Plan: Pre-build ask timing (issue #201) + +## Why This Change + +A pairing session on 2026-09-03 built a piece the plan had marked expensive to walk back without ever collecting the +person's own read of it. The run had tucked the pre-build ask for piece 3 under piece 2's stop, then read "commit and +next" as declining it. The feedback record then said "ask declined" as if the person had decided that. GitHub issue +#201 reports this and says the skill text permits it. The rule says the ask comes before the build, and pairing Step 5 +says "ask first", but neither forbids folding the ask into the tail of the previous stop. The reason class is a finding +already established, with the issue as its source +([D-11](artifacts/change-decision-log.md#trivial-decisions)). + +## What Changes, In One Paragraph + +After this change, the collaborative stop rule says three things it does not say today. A stop covers what just closed +and asks nothing about a later piece. The pre-build ask is a turn of its own: it opens the marked piece's turn after the +person has replied to the previous stop. A reply to a stop answers that stop's piece only, so it never counts as +declining an ask the person has not seen. And the feedback record holds the person's words, with any reading the run +adds labeled as the run's. The pairing skill's loop echoes the first two in Step 5 and the third in Step 6. The +long-form doc promises each one to the person in the same terms. Nothing new is added to the rule's list of sections, +and the five backing skills are not touched. + +## Current State + +The rule's only timing constraint on the ask is "before the build, not at the stop afterward", where "the stop +afterward" is the marked piece's own stop +([C-1](artifacts/current-state-findings.md#c-1-the-rule-requires-the-ask-to-precede-the-build-and-says-nothing-about-which-turn-carries-it)). +Pairing Step 5 says "ask first" and gets turn separation only from its list order. Item 1 asks, item 4 ends the turn, +and Step 6 returns "to the top of Step 5" +([C-2](artifacts/current-state-findings.md#c-2-pairing-step-5-echoes-the-ask-as-ask-first-and-gets-turn-separation-only-from-the-loops-item-order)). +The definition of a stop never scopes it to one piece or forbids a question about a later one +([C-3](artifacts/current-state-findings.md#c-3-what-a-stop-presents-does-not-scope-a-stop-to-one-piece-or-forbid-forward-looking-content)). +One kind of forward-looking content is already required: naming the next concern when a piece closes one +([C-4](artifacts/current-state-findings.md#c-4-step-5-already-authorizes-one-kind-of-forward-looking-content-in-a-stop-naming-the-next-concern)). + +A reply is routed by what it touches, never by which question it answers, and "Declining is a first-class answer" +defines a decline without saying what is not one +([C-5](artifacts/current-state-findings.md#c-5-a-reply-is-routed-by-what-it-touches-never-by-which-question-it-answers-and-the-decline-clause-has-no-negative-definition)). +The record holds whatever the run writes, and the doc promises "which piece prompted it" with nothing delivering it +([C-6](artifacts/current-state-findings.md#c-6-the-record-holds-whatever-the-run-writes-and-nothing-distinguishes-an-answered-ask-from-a-declined-one-from-one-never-presented)). +No error path covers a build made on a misread ask. The overrun clause fires only when a stop is skipped, and the +re-show route says not to return to the ask +([C-7](artifacts/current-state-findings.md#c-7-no-existing-error-path-covers-a-build-made-on-a-misread-ask-and-the-re-show-route-forbids-returning-to-the-ask)). +The doc promises "before it builds" and its tip says declining "advances the stop" where the rule says "the piece" +([C-9](artifacts/current-state-findings.md#c-9-the-long-form-doc-promises-before-it-builds-and-says-declining-advances-the-stop)). + +Three facts bound the change. The rule is vendored byte-identical into two other plugins +([C-11](artifacts/current-state-findings.md#c-11-the-three-rule-copies-are-byte-identical-and-two-places-record-the-obligation-to-keep-them-so)). +The backing skills read only "Detecting the flag" and "What a stop presents" +([C-12](artifacts/current-state-findings.md#c-12-the-backing-skills-required-reading-excludes-the-ask-section-and-all-five-read-only-the-stops-shape)). +And the rule opens with a Contents list a new section would have to join +([C-13](artifacts/current-state-findings.md#c-13-the-rule-file-carries-a-contents-list-that-a-new-section-must-join)). + +## Target State + +Each clause lands in the section whose responsibility it is +([D-1](artifacts/change-decision-log.md#d-1-place-each-clause-by-the-section-whose-responsibility-it-is)). "What a +stop presents" owns the scope of a stop. "Asking before building, and when" owns the ask's turn, what a decline is and +is not, what happens to the reply, and what to do with a bundled ask. "Recording what the person says" owns the entry's +form. "Acting on the answer", "Pace", "Who reads this", and the Contents list are unchanged. Pairing Step 5 and Step 6 +echo the rule; the doc promises it. + +The sentences below are the contract. The rule, the skill, and the doc must agree on them, so the builder copies them +rather than paraphrasing. Wrap by hand at 120 columns; Prettier runs with `proseWrap: preserve` and will not reflow +them. Line numbers are as of 2026-09-11 and locate the insertion; the builder reads the current file. + +### The rule: `han-core/references/collaborative-stop-rule.md` + +**R1.** In "What a stop presents", a new paragraph between the paragraph ending "suppresses scrutiny." (line 63) and +"Then end the turn." (line 65) +([D-2](artifacts/change-decision-log.md#d-2-the-sequencing-rules-sentences-pinned)): + +```markdown +A stop covers what just closed and asks nothing about a later piece. Its position line reports what remains, and naming +the work that comes next is a report, not a question. The one question this convention poses about a piece not yet +built is the pre-build ask, and it has a turn of its own. +``` + +**R2.** In "Asking before building, and when", a new paragraph after the one ending "the point is an independent read." +(line 94) ([D-2](artifacts/change-decision-log.md#d-2-the-sequencing-rules-sentences-pinned), +[D-12](artifacts/change-decision-log.md#d-12-a-marked-first-piece-takes-its-ask-after-the-plan-and-the-plan-is-treated-like-a-stop-for-attribution)): + +```markdown +**The ask is a turn of its own.** It opens the marked piece's turn, after the person has responded to the previous +stop, or to the plan when the marked piece is the first, and it is the whole turn: pose it and end the turn. Never +append it to that stop or plan, BECAUSE a reply to a stop or a plan is a reply to that alone, and answers nothing about +a later piece. +``` + +**R3.** The decline paragraph (lines 96–97) is replaced whole +([D-3](artifacts/change-decision-log.md#d-3-a-reply-to-a-stop-answers-that-stops-piece-and-a-decline-has-a-negative-definition), +[D-13](artifacts/change-decision-log.md#d-13-a-reply-to-the-ask-is-recorded-against-the-ask-and-then-the-build-begins-it-is-not-routed-through-step-6)): + +```markdown +**Declining is a first-class answer.** "I don't know" and "just show me" advance the piece exactly as a considered +answer does. Never re-prompt once the person has replied to the ask, and never hold the build for a fuller answer than +the one given. A decline is a reply to the ask. A reply to the previous stop, or to the plan, is a reply to that alone, +and never counts as declining an ask the person has not yet answered. A question about the ask holds it open: answer +the question and end the turn again. +``` + +**R4.** A new paragraph after R3 and before "**After the build, the reveal is an ordinary stop.**" (line 99) +([D-4](artifacts/change-decision-log.md#d-4-a-bundled-ask-is-handled-at-step-5s-re-entry-and-step-6-gains-no-route), +[D-14](artifacts/change-decision-log.md#d-14-the-after-build-message-names-the-run-as-the-cause)): + +```markdown +**A bundled ask is an unanswered ask.** When an earlier turn put the ask into a stop or the plan and the reply spoke +only to that, the ask was never posed on its own: present it now, on its own, before building. That is the first ask, +not a re-prompt. If the piece was already built when this comes to light, do not ask now; say that the run put the ask +under an earlier turn so it went unanswered, and continue from the stop in hand. +``` + +**R5.** In "Recording what the person says", a new paragraph after the one ending "least reliably recalled." (line 106) +([D-5](artifacts/change-decision-log.md#d-5-the-record-holds-the-persons-words-and-the-runs-reading-is-marked-as-the-runs), +[D-15](artifacts/change-decision-log.md#d-15-one-worked-example-pins-the-record-entrys-form)): + +```markdown +An entry holds the person's words and names the stop or ask they answered. A reading the run adds, such as "declined" +or "approved", follows the words and is marked as the run's, never written as what the person decided. An entry reads, +for example, "Piece 2 stop: 'commit and next' (run's reading: approved)". An ask with no entry is an ask with no answer. +``` + +### The skill: `han-core/skills/pairing/SKILL.md` + +**P1.** Step 5 item 1 (lines 152–154) is replaced whole, as one list item with two paragraphs beneath it, the shape item +2 already uses. It must agree with R2, R3, and R4 on five points. The ask opens piece N's turn after the reply to the +previous stop or the plan, and the ask ends the turn. The reply is recorded against the ask, and then the build +begins. A reply to a stop or the plan answers that alone. A bundled ask was never posed, and it is presented on its own +before building ([D-2](artifacts/change-decision-log.md#d-2-the-sequencing-rules-sentences-pinned), +[D-4](artifacts/change-decision-log.md#d-4-a-bundled-ask-is-handled-at-step-5s-re-entry-and-step-6-gains-no-route), +[D-12](artifacts/change-decision-log.md#d-12-a-marked-first-piece-takes-its-ask-after-the-plan-and-the-plan-is-treated-like-a-stop-for-attribution), +[D-13](artifacts/change-decision-log.md#d-13-a-reply-to-the-ask-is-recorded-against-the-ask-and-then-the-build-begins-it-is-not-routed-through-step-6)): + +```markdown +1. **If the plan marked this piece expensive to walk back, ask first, in a turn of its own.** The ask opens this piece's + turn, after the person has responded to the previous stop, or to the plan when this is the first piece. Name the + dimension the choice turns on, offer no candidate answers, and end the turn. Never append the ask to that stop or + plan, BECAUSE a reply to it is a reply to that alone and answers nothing about this piece. + + When the reply arrives, write it into the record in the person's words, against this ask, then build. A declined + answer is a complete one, and a question about the ask holds it open: answer it and end the turn again. The reply is + not routed through Step 6, which handles replies to a stop. + + When an earlier turn already bundled the ask into a stop or the plan and the reply spoke only to that, the ask was + never posed on its own: present it now, on its own, before building. +``` + +**P2.** Step 5 item 3, one sentence appended after "their review matters most." (line 173), so the one forward-looking +instruction in the file says it is a report +([D-2](artifacts/change-decision-log.md#d-2-the-sequencing-rules-sentences-pinned), +[D-16](artifacts/change-decision-log.md#d-16-two-restatements-are-dropped-as-yagni)): + +```markdown + That is a report about what comes next, never a question about it. +``` + +**P3.** Step 6, first sentence (line 180), replaced +([D-5](artifacts/change-decision-log.md#d-5-the-record-holds-the-persons-words-and-the-runs-reading-is-marked-as-the-runs)): + +```markdown +Write the response into the record, in the person's words and against the stop or ask it answers, before acting on it. +``` + +Step 6's re-show sentence, "Do not return to the pre-build ask; this piece is already built.", stands unchanged. It +carries the do-not-ask half of R4's after-build case. The say-so half lives in the rule only, which pairing reads in +full ([D-4](artifacts/change-decision-log.md#d-4-a-bundled-ask-is-handled-at-step-5s-re-entry-and-step-6-gains-no-route)). + +### The doc: `han-core/docs/skills/pairing.md` + +Each edit delivers one rule sentence, and the plan names which +([D-6](artifacts/change-decision-log.md#d-6-the-long-form-doc-promises-exactly-what-the-rule-delivers)). + +**L1.** The "A stop" key concept (lines 26–27), delivering R1: + +```markdown +- **A stop.** The end of a turn. You get your position in the plan, what was built, what you can check, and what + changed. The reasoning does not lead, and the stop asks you nothing about a later piece. +``` + +**L2.** The "The pre-build ask" key concept (lines 28–29), delivering R2 and R3 +([D-12](artifacts/change-decision-log.md#d-12-a-marked-first-piece-takes-its-ask-after-the-plan-and-the-plan-is-treated-like-a-stop-for-attribution)): + +```markdown +- **The pre-build ask.** For a piece the plan marked expensive to walk back, the skill asks what you expect before it + builds. The ask is a turn of its own: it arrives after you have responded to the previous stop, or to the plan when + the marked piece is the first, and nothing is built until you answer it or decline. Declining is a complete answer. +``` + +**L3.** Line 85, delivering R5 +([D-15](artifacts/change-decision-log.md#d-15-one-worked-example-pins-the-record-entrys-form)): + +```markdown +The record holds each piece of feedback you gave, in your words, and which stop or ask prompted it, and any reading the +skill adds is labeled as its own. When the skill applies a recorded entry to a later piece, it names which entry, so a +misrecorded correction surfaces while it is still cheap to fix. +``` + +**L4.** The tip at lines 99–100, delivering R3 and replacing "advances the stop" +([D-3](artifacts/change-decision-log.md#d-3-a-reply-to-a-stop-answers-that-stops-piece-and-a-decline-has-a-negative-definition)): + +```markdown +- **Answer the pre-build ask honestly, including with "I don't know."** Declining advances the piece exactly as a + considered answer does, and only a reply to the ask counts as one: approving the previous piece never declines an ask + you have not answered. The ask exists to get an independent read, and a manufactured guess is worth less than none. +``` + +**L5.** The "Cost and latency" sentence at lines 117–118, because R2 makes "plus one turn per stop" false for a marked +piece ([D-6](artifacts/change-decision-log.md#d-6-the-long-form-doc-promises-exactly-what-the-rule-delivers)): + +```markdown +Runs on the session model with no dispatch fan-out of its own. The skill itself is thin: the cost is whatever the +backing skill would have cost, plus one turn per stop, and one more for each piece the plan marked expensive to walk +back. +``` + +## Surface Delta + +Every entry is Re-scoped: each element keeps its name and home and gains a responsibility. The three copies of the rule +are one element in three homes, so S-1 through S-3 each cover all three files +([D-9](artifacts/change-decision-log.md#trivial-decisions)). + +### S-1: `collaborative-stop-rule.md` § "What a stop presents" — Re-scoped + +**Target state.** The section defines the four elements of a stop, the reasoning-last ordering, the overrun clause, and +the scope of a stop. The scope covers what just closed, asks nothing about a later piece, and reports what comes next +without asking about it. The pre-build ask is named here as the one question posed about an unbuilt piece, with its own +turn (R1). Every skill that presents a stop, backing skills included, is bound by this section as before. + +**Behavior.** Changing. A person never sees a question about a later piece inside a stop. Backing skills observe no +change, because none of them poses an ask (C-12). Settled by +[D-7](artifacts/change-decision-log.md#d-7-the-user-accepted-the-sequencing-change-at-the-behavior-gate). + +**Why.** C-3 locates the one-piece gap here, and C-12 makes this the one section every reader of the rule opens. + +**Decision.** [D-1](artifacts/change-decision-log.md#d-1-place-each-clause-by-the-section-whose-responsibility-it-is), +[D-2](artifacts/change-decision-log.md#d-2-the-sequencing-rules-sentences-pinned) + +### S-2: `collaborative-stop-rule.md` § "Asking before building, and when" — Re-scoped + +**Target state.** The section owns why the ask precedes the build, the reversibility test, and the ask's content. It +also owns the ask's turn (R2) and what a decline is and is not, including what a question about the ask does (R3). It +owns what to do with a bundled ask before and after the build (R4), and the reveal. "Never require an answer before +building" does not exist; the build waits for a reply to the ask, and a decline is a full reply. The plan turn counts +like a stop for attribution: a reply to it answers nothing about piece 1. + +**Behavior.** Changing. The ask arrives as its own turn after the person's reply to the previous stop, or to the plan +for a marked first piece. A reply to that stop or plan never counts as declining it. A question about the ask keeps it +open. A bundled ask is asked again before the build. An ask discovered unanswered after the build is named, with the +run as the cause, not re-asked. Settled by +[D-7](artifacts/change-decision-log.md#d-7-the-user-accepted-the-sequencing-change-at-the-behavior-gate), extended at +review by [D-12](artifacts/change-decision-log.md#d-12-a-marked-first-piece-takes-its-ask-after-the-plan-and-the-plan-is-treated-like-a-stop-for-attribution). + +**Why.** C-1, C-5, and C-7 locate the timing gap, the missing negative definition, and the missing after-build handler +here. + +**Depends on.** S-1, so "has a turn of its own" in R1 points at a paragraph that exists. + +**Decision.** [D-1](artifacts/change-decision-log.md#d-1-place-each-clause-by-the-section-whose-responsibility-it-is), +[D-2](artifacts/change-decision-log.md#d-2-the-sequencing-rules-sentences-pinned), +[D-3](artifacts/change-decision-log.md#d-3-a-reply-to-a-stop-answers-that-stops-piece-and-a-decline-has-a-negative-definition), +[D-4](artifacts/change-decision-log.md#d-4-a-bundled-ask-is-handled-at-step-5s-re-entry-and-step-6-gains-no-route), +[D-12](artifacts/change-decision-log.md#d-12-a-marked-first-piece-takes-its-ask-after-the-plan-and-the-plan-is-treated-like-a-stop-for-attribution), +[D-13](artifacts/change-decision-log.md#d-13-a-reply-to-the-ask-is-recorded-against-the-ask-and-then-the-build-begins-it-is-not-routed-through-step-6), +[D-14](artifacts/change-decision-log.md#d-14-the-after-build-message-names-the-run-as-the-cause) + +### S-3: `collaborative-stop-rule.md` § "Recording what the person says" — Re-scoped + +**Target state.** The section owns when the record is written and the form of an entry. That form is the person's +words, the stop or ask they answered, and any reading the run adds marked as the run's, with one worked example (R5). +An ask with no entry is unanswered. + +**Behavior.** Changing. A person reading the record sees their own words and sees the run's reading labeled as such. +Settled by [D-8](artifacts/change-decision-log.md#d-8-the-user-accepted-the-record-change-at-the-behavior-gate). + +**Why.** C-6 finds the record holds whatever the run writes, and the issue reports the wrong label reaching it. + +**Decision.** +[D-5](artifacts/change-decision-log.md#d-5-the-record-holds-the-persons-words-and-the-runs-reading-is-marked-as-the-runs), +[D-15](artifacts/change-decision-log.md#d-15-one-worked-example-pins-the-record-entrys-form) + +### S-4: `pairing/SKILL.md` Step 5 — Re-scoped + +**Target state.** Step 5 item 1 carries the ask's own turn, the reply-attribution rule, what happens to the reply, and +the bundled-ask handler in the loop's terms (P1). Item 3 says naming the next concern is a report, never a question +(P2). Items 2 and 4 are unchanged. + +**Behavior.** Changing, the same observation as S-1 and S-2; this is the echo the driving loop reads. Settled by +[D-7](artifacts/change-decision-log.md#d-7-the-user-accepted-the-sequencing-change-at-the-behavior-gate). + +**Why.** C-2 finds the loop's turn separation implied by list order and never stated, and its re-entry after an ask +turn unnamed. The issue asks for the echo. + +**Depends on.** S-1, S-2. The skill must never say more than the rule delivers. + +**Decision.** [D-2](artifacts/change-decision-log.md#d-2-the-sequencing-rules-sentences-pinned), +[D-4](artifacts/change-decision-log.md#d-4-a-bundled-ask-is-handled-at-step-5s-re-entry-and-step-6-gains-no-route), +[D-12](artifacts/change-decision-log.md#d-12-a-marked-first-piece-takes-its-ask-after-the-plan-and-the-plan-is-treated-like-a-stop-for-attribution), +[D-13](artifacts/change-decision-log.md#d-13-a-reply-to-the-ask-is-recorded-against-the-ask-and-then-the-build-begins-it-is-not-routed-through-step-6), +[D-16](artifacts/change-decision-log.md#d-16-two-restatements-are-dropped-as-yagni) + +### S-5: `pairing/SKILL.md` Step 6 — Re-scoped + +**Target state.** Step 6 opens by writing the response into the record in the person's words and against the stop or +ask it answers (P3). Its three routes and its re-show sentence are unchanged. Replies to an ask do not pass through it. + +**Behavior.** Changing, the same observation as S-3. Settled by +[D-8](artifacts/change-decision-log.md#d-8-the-user-accepted-the-record-change-at-the-behavior-gate). + +**Why.** C-6 finds Step 6's "Write the response into the record" never says whose words the record holds. + +**Depends on.** S-3. + +**Decision.** +[D-5](artifacts/change-decision-log.md#d-5-the-record-holds-the-persons-words-and-the-runs-reading-is-marked-as-the-runs) + +### S-6: `docs/skills/pairing.md` — Re-scoped + +**Target state.** The doc promises the person exactly what R1, R2, R3, and R5 deliver. A stop asks nothing about a later +piece (L1). The ask is its own turn after their reply to the previous stop or the plan, and nothing is built until they +answer or decline (L2). The record holds their words and which stop or ask prompted them, with the skill's reading +labeled as its own (L3). Declining advances the piece, and approving the previous piece never declines an ask they have +not answered (L4). A marked piece costs one more turn (L5). + +**Behavior.** Preserving. The doc changes no run's behavior; it describes what S-1 through S-5 make true. The review +confirmed no run reads the doc. + +**Why.** C-9 finds the doc's promise narrower than the expectation the issue reports, and its tip blurs the ask into +the stop. + +**Depends on.** S-1, S-2, S-3. The doc must never promise more than the rule delivers. + +**Decision.** [D-6](artifacts/change-decision-log.md#d-6-the-long-form-doc-promises-exactly-what-the-rule-delivers), +[D-3](artifacts/change-decision-log.md#d-3-a-reply-to-a-stop-answers-that-stops-piece-and-a-decline-has-a-negative-definition), +[D-12](artifacts/change-decision-log.md#d-12-a-marked-first-piece-takes-its-ask-after-the-plan-and-the-plan-is-treated-like-a-stop-for-attribution), +[D-15](artifacts/change-decision-log.md#d-15-one-worked-example-pins-the-record-entrys-form), +[D-16](artifacts/change-decision-log.md#d-16-two-restatements-are-dropped-as-yagni) + +## Behavior Changes + +Two things change for a person pairing, and the user accepted both. The review widened the first in three small ways, +each settled from evidence and named here so the user can strike any of them. + +**The ask is its own turn, and a stop never carries it** (S-1, S-2, S-4). Today a run may show piece 2's stop with the +piece-3 question at the bottom and read "commit and next" as declining it. Afterwards, piece 2's stop ends the turn +with no question about piece 3; the next turn is the piece-3 question alone; nothing is built until the person answers +or declines. A run that bundles the ask anyway asks again on its own before building. A run that learns after the +build that the ask went unanswered says so and continues from the stop in hand. The line "never require an answer +before building" goes, because the build now waits for a reply to the ask, though "I don't know" is a full reply. +Decision: "accept as described" +([D-7](artifacts/change-decision-log.md#d-7-the-user-accepted-the-sequencing-change-at-the-behavior-gate)). + +Three extensions from the review, within that decision: + +- When the marked piece is the first one, the turn before it is the plan, and the plan carries no ask either; "looks + good" never declines one ([D-12](artifacts/change-decision-log.md#d-12-a-marked-first-piece-takes-its-ask-after-the-plan-and-the-plan-is-treated-like-a-stop-for-attribution)). +- A question about the ask keeps it open: the run answers and ends the turn again. The reply to the ask is written into + the record in the person's words before the build ([D-13](artifacts/change-decision-log.md#d-13-a-reply-to-the-ask-is-recorded-against-the-ask-and-then-the-build-begins-it-is-not-routed-through-step-6)). +- The after-build message names the run as the cause: "the run put the ask under an earlier turn so it went unanswered" + ([D-14](artifacts/change-decision-log.md#d-14-the-after-build-message-names-the-run-as-the-cause)). + +**The record holds the person's words, and the run's reading is labeled as the run's** (S-3, S-5). Today the run can +write "ask declined" as if the person decided it. Afterwards, each entry holds what the person typed and names the stop +or ask they answered. A reading the run adds follows their words and is marked as the run's. An ask with no entry is +unanswered. One example entry in the rule pins the shape. This goes one step past the issue's "Suggested fix" +paragraph, and the question said so. Decision: "accept the change as described" +([D-8](artifacts/change-decision-log.md#d-8-the-user-accepted-the-record-change-at-the-behavior-gate)). + +## Change Units + +Three units, in order. Each leaves every file consistent with the rule, because at every step the skill and the doc say +no more than the rule delivers. Ship them as one commit. The risk analyst found that Units 1 and 2 landing without Unit +3 would leave the doc contradicting the corrected rule, which is worse than today's narrower promise. + +### Unit 1: The rule and its two copies + +**What it does.** Applies R1 through R5 to the canonical rule, then copies it over the two vendored copies. + +**Delta entries.** S-1, S-2, S-3. + +**Justification.** Issue #201 "Suggested fix": "Add an explicit rule to `collaborative-stop-rule.md`". + +**How you know it worked.** `md5 -q` over the three paths prints one hash three times, and it is no longer +`29db7843077527d17ff7c515b8b062fc`. `npm run lint` passes. The Contents list is unchanged. Reading the file, every +sentence of R1 through R5 is present verbatim, and "never require an answer before building" is absent +([D-9](artifacts/change-decision-log.md#trivial-decisions)). + +### Unit 2: The pairing skill + +**What it does.** Applies P1, P2, and P3 to `han-core/skills/pairing/SKILL.md`. + +**Delta entries.** S-4, S-5. + +**Ordering constraint.** After Unit 1, so the skill never says more than the rule delivers. + +**Justification.** Issue #201 "Suggested fix": "(and echo it in pairing Step 5)". + +**How you know it worked.** Step 5 item 1 agrees with R2, R3, and R4 on the five points named under P1. Step 5 keeps +four numbered items, because Prettier renumbers ordered lists, and item 1's two trailing paragraphs are indented three +spaces so they stay inside the item. `npm run lint` passes, and `wc -l` stays under 500. The +md5 check from Unit 1 still prints one hash three times. + +### Unit 3: The long-form doc + +**What it does.** Applies L1 through L5 to `han-core/docs/skills/pairing.md`. + +**Delta entries.** S-6. + +**Ordering constraint.** After Unit 1, so the doc never promises more than the rule delivers. + +**Justification.** A necessity of Units 1 and 2: the doc is the surface the person reads (C-9), and the expectation the +issue reports came from a reader. + +**How you know it worked.** Each of L1 through L5 reads beside the rule sentence it delivers and says nothing the rule +does not. `npm run lint` passes. The md5 check still prints one hash three times. + +## Risks + +**A paraphrase where a copy was needed.** The sentences above are contracts across three files. A builder who rewords +one side breaks the agreement the plan exists to pin. Detect it by reading each pair side by side at the end of Units 2 +and 3. + +**A copy that drifts.** Editing a vendored copy directly, or forgetting to copy after a late edit to the canonical file, +leaves the three copies unequal. The md5 check at the end of every unit catches it. + +**Three plugins change.** The rule lives in `han-core`, `han-coding`, and `han-planning`, so a release after this +change touches all three. The plan bumps no version; that is the release skill's call. + +**R1 is read by six skills.** "What a stop presents" is the whole contract for the five backing skills (C-12), so R1 +changes what every collaborative stop may contain, not only pairing's. C-12 verified that none of the five poses an +ask, so they observe no change. The builder still reads R1 once against each of their "Running collaboratively" +paragraphs before closing Unit 1; they are outside the boundary and nobody downstream checks them. + +**No ADR links the rule to its design record.** "Never require an answer before building" traces to the pairing plan's +decision D7. That record will name a sentence the rule no longer has, and nothing links the two. D-3 records why it +went; a reader of the old record has to find this plan. Writing an ADR is outside the boundary. + +**Prettier will not reflow prose.** `proseWrap: preserve` means a line over 120 columns stays over. Wrap the pinned +text by hand as shown. Prettier does renumber ordered lists and trim inline code spans, so P1 stays item 1 and no new +code span carries leading or trailing spaces. + +## Deferred (YAGNI) + +- **A three-state marker per ask in the record** (answered, declined, never presented). R5's quote-and-attribute form + covers the incident with no field, and "no entry, no answer" derives the third state. Reopen when a second report + shows the record misstating an ask outcome after R5 lands. +- **Ask behavior inside a batch or a finish-without-stopping run** (C-8). The issue's run used neither gear. R1 is + worded "what just closed" so it holds in both. R2 and P1 describe the normal gear, one stop per piece, and say + nothing about a marked piece inside a batch. Reopen when a report shows a marked piece going unasked + inside either gear. +- **A third repeated constraint in the SKILL.md preamble** (C-10). P1 carries the constraint with a BECAUSE at its one + point of execution. Reopen when a bundled ask is reported after P1 lands. +- **An instruction for correcting a disputed record entry in place.** The issue reports the person corrected the record, + and under R5 the correction lands as a quote against the ask beside the attributed run label. Reopen when a stale run + label governs a later piece despite a recorded correction. +- **An echo of the after-build say-so in Step 6** (C-7). Step 6's re-show sentence carries the do-not-ask half, and + pairing reads the whole rule for the rest. Reopen when a run re-asks after the build despite R4, or stays silent + about an unanswered ask. +- **A piece anchor on the ask turn** (review finding UX-003), such as a leading "Before piece 3 is built:". The ask + names the dimension the choice turns on and nothing else; a person returning to scrollback reconstructs which piece + from the plan. No incident shows a person misidentifying it. Reopen when a person answers an ask about the piece just + approved, or asks which piece the question concerns. +- **An acknowledgment on a re-presented ask** (review finding UX-004), saying why the same question appears twice. The + re-ask happens once and a one-word decline ends it. Reopen when a person answers a re-presented ask with "I already + answered that" or the like. +- **A sentence in the doc's "Why the ask comes before the build" on why the ask is its own turn** (review finding + JD-008). L2 already delivers R2, and the sentence's mechanism claim has one incident behind it. Reopen when a reader + asks why the ask is a separate turn. + +## Cut for Scope + +Nothing was cut. The boundary excludes the five backing skills, and the plan needed nothing from them. The one clause a +backing skill can act on (R1) lands in a section they already read, and none of them poses an ask +([D-10](artifacts/change-decision-log.md#trivial-decisions)). + +## Open Items + +None block the change. One non-blocking item the builder inherits. The 2026-09-03 session's feedback record was not +inspected, so whether "ask declined" was written as a label or a paraphrase is taken from the issue's wording. R5 +covers both. + +## Review Findings + +One round, at the medium cap of two. `han-core:junior-developer`, `han-core:user-experience-designer`, and +`han-core:risk-analyst` ran in parallel against the draft plan. Nothing blocked. Every finding resolved from evidence, +so no question reached the user; the extensions to accepted behavior are named in Behavior Changes. + +Findings that changed the plan, merged by substance: + +- **A marked first piece has no previous stop** (JD-005, UX-008). R2, R3, R4, P1, and L2 now name the plan turn. + [D-12](artifacts/change-decision-log.md#d-12-a-marked-first-piece-takes-its-ask-after-the-plan-and-the-plan-is-treated-like-a-stop-for-attribution). +- **The ask's reply had no route** (JD-001, UX-005, JD-009). P1 gained a paragraph: record the reply against the ask, + then build; a question holds the ask open; not routed through Step 6. R3 gained the question clause. + [D-13](artifacts/change-decision-log.md#d-13-a-reply-to-the-ask-is-recorded-against-the-ask-and-then-the-build-begins-it-is-not-routed-through-step-6). +- **"Never re-prompt" sat beside "present the ask again"** (JD-002, UX-004). R3 scopes re-prompting to after a reply; + R4 says the bundled ask was never posed, so this is the first ask. UX-004's acknowledgment line is deferred. + [D-3](artifacts/change-decision-log.md#d-3-a-reply-to-a-stop-answers-that-stops-piece-and-a-decline-has-a-negative-definition), + [D-4](artifacts/change-decision-log.md#d-4-a-bundled-ask-is-handled-at-step-5s-re-entry-and-step-6-gains-no-route). +- **The after-build message read as the person's omission** (UX-002). R4 names the run as the cause. + [D-14](artifacts/change-decision-log.md#d-14-the-after-build-message-names-the-run-as-the-cause). +- **The record entry's form was described, not pinned** (JD-006, UX-007). R5 carries one worked example; L3 says the + skill's reading is labeled as its own. [D-15](artifacts/change-decision-log.md#d-15-one-worked-example-pins-the-record-entrys-form). +- **The doc and the rule pinned different conditions** (UX-001). L4 says "have not answered", matching R3. + [D-3](artifacts/change-decision-log.md#d-3-a-reply-to-a-stop-answers-that-stops-piece-and-a-decline-has-a-negative-definition). +- **The doc's cost line became false** (UX-006). L5 now edits "Cost and latency" instead of adding a second delivery + of R2. [D-6](artifacts/change-decision-log.md#d-6-the-long-form-doc-promises-exactly-what-the-rule-delivers). +- **Two restatements failed the simpler-version test** (JD-007, JD-008). P2's second sentence and the original L5 are + gone. [D-16](artifacts/change-decision-log.md#d-16-two-restatements-are-dropped-as-yagni). +- **The claim that Step 6 carried both halves of R4 was overstated** (JD-003). The plan, D-4, and the deferred entry now + say Step 6 carries the do-not-ask half only. +- **Three risks were missing** (risk-analyst): R1's reach across six skills, the lost link to the pairing plan's D7, and + Unit 3 shipping late. All three are in Risks; the units now ship as one commit. + +Findings closed against the findings file (Pass C): the risk analyst's concern that R1's effect on the five backing +skills was unverified is answered by C-12, which read all five. Findings that stayed as recommendations only: JD-004 +(R2 and P1 describe the normal gear; the C-8 deferral now says so). The risk analyst scored every deferral's trigger as +right and promoted none. + +Unverified, and never presented as blocking: every specialist reasoned from the issue's account of the 2026-09-03 +session, because the transcript and its record are not in the repository. That is the plan's one open item. From f7c75b2e417f364bef730e5eb2ac84e5f8a5c9e2 Mon Sep 17 00:00:00 2001 From: River Lynn Bailey Date: Fri, 11 Sep 2026 10:07:29 -0600 Subject: [PATCH 2/3] fix(han-core): give the pre-build ask its own turn Closes #201. The collaborative stop rule said the pre-build ask comes before the build and pairing Step 5 said "ask first", and neither forbade folding the ask into the tail of the previous piece's stop. A run did exactly that, read "commit and next" as declining the ask it had tucked under piece 2's stop, built piece 3 without the person's read, and wrote "ask declined" into the feedback record as the person's decision. `collaborative-stop-rule.md` now says a stop covers what just closed and asks nothing about a later piece; the ask is a turn of its own, opening the marked piece's turn after the person has replied to the previous stop or to the plan; a reply to a stop or the plan answers that alone and never counts as declining an ask the person has not answered; a question about the ask holds it open; a bundled ask was never posed and is presented on its own before building, and one found after the build is named with the run as the cause rather than re-asked. "Never require an answer before building" is gone, because the build now waits for a reply to the ask, though a decline is a full reply. The record's entry form is pinned: the person's words, the stop or ask they answered, and any reading the run adds labeled as the run's, with one worked example. The two vendored copies in `han-coding` and `han-planning` are byte-identical to the canonical file. Pairing Step 5 item 1 carries the same rule in the loop's terms and names what happens to the reply: recorded against the ask, then the build, with no pass through Step 6. Item 3 says naming the next concern is a report, never a question. Step 6 writes the response in the person's words against the stop or ask it answers. The long-form doc promises each of these to the person in the same terms and adds one turn per marked piece to its cost line. The change plan, decision log, and findings behind every sentence are under `docs/plans/gh-201-pre-build-ask-timing/`. --- .../references/collaborative-stop-rule.md | 23 ++++++++++++++++++- han-core/docs/skills/pairing.md | 18 +++++++++------ .../references/collaborative-stop-rule.md | 23 ++++++++++++++++++- han-core/skills/pairing/SKILL.md | 21 ++++++++++++----- .../references/collaborative-stop-rule.md | 23 ++++++++++++++++++- 5 files changed, 92 insertions(+), 16 deletions(-) diff --git a/han-coding/references/collaborative-stop-rule.md b/han-coding/references/collaborative-stop-rule.md index 61f91898..48086b9c 100644 --- a/han-coding/references/collaborative-stop-rule.md +++ b/han-coding/references/collaborative-stop-rule.md @@ -62,6 +62,10 @@ The reasoning behind the choices comes last or not at all. State in one line tha stop there BECAUSE an unannounced affordance in a conversation is the same as no affordance, while a volunteered rationale is the thing that suppresses scrutiny. +A stop covers what just closed and asks nothing about a later piece. Its position line reports what remains, and naming +the work that comes next is a report, not a question. The one question this convention poses about a piece not yet +built is the pre-build ask, and it has a turn of its own. + Then end the turn. Nothing further is built until the person responds. That last instruction is a directive, not a guarantee. Nothing in the platform enforces it. When a run does build past a @@ -93,8 +97,21 @@ test as provisional and revisit it once real runs show whether it marks the piec **The ask itself** names the dimension the choice turns on and stops there. Do not pose a blank question, and do not offer candidate answers, BECAUSE named candidates anchor the guess and the point is an independent read. +**The ask is a turn of its own.** It opens the marked piece's turn, after the person has responded to the previous +stop, or to the plan when the marked piece is the first, and it is the whole turn: pose it and end the turn. Never +append it to that stop or plan, BECAUSE a reply to a stop or a plan is a reply to that alone, and answers nothing about +a later piece. + **Declining is a first-class answer.** "I don't know" and "just show me" advance the piece exactly as a considered -answer does. Never re-prompt, and never require an answer before building. +answer does. Never re-prompt once the person has replied to the ask, and never hold the build for a fuller answer than +the one given. A decline is a reply to the ask. A reply to the previous stop, or to the plan, is a reply to that alone, +and never counts as declining an ask the person has not yet answered. A question about the ask holds it open: answer +the question and end the turn again. + +**A bundled ask is an unanswered ask.** When an earlier turn put the ask into a stop or the plan and the reply spoke +only to that, the ask was never posed on its own: present it now, on its own, before building. That is the first ask, +not a re-prompt. If the piece was already built when this comes to light, do not ask now; say that the run put the ask +under an earlier turn so it went unanswered, and continue from the stop in hand. **After the build, the reveal is an ordinary stop.** It does not restate the person's read, score it, or defend a divergence from it. A stop that grades you teaches you to answer noncommittally, and a stop that argues with you leads @@ -105,6 +122,10 @@ with the reasoning this convention keeps out of the lead. Write every piece of feedback into the running record before acting on it. A correction given at the second stop has to still apply at the seventh, and mid-context material is the least reliably recalled. +An entry holds the person's words and names the stop or ask they answered. A reading the run adds, such as "declined" +or "approved", follows the words and is marked as the run's, never written as what the person decided. An entry reads, +for example, "Piece 2 stop: 'commit and next' (run's reading: approved)". An ask with no entry is an ask with no answer. + The person can read the record whenever they ask. When a recorded entry shapes a later piece, name which entry it was, so a misrecorded correction surfaces while it is still cheap to fix rather than quietly governing the rest of the session. diff --git a/han-core/docs/skills/pairing.md b/han-core/docs/skills/pairing.md index ccd7cd5e..a3be7a18 100644 --- a/han-core/docs/skills/pairing.md +++ b/han-core/docs/skills/pairing.md @@ -24,9 +24,10 @@ use the skill. For what the skill does internally, read the skill definition at - **The plan.** A short list of the concerns and the pieces inside each, proposed before any work begins, that you accept or change. It also names which pieces carry a choice that is expensive to walk back. - **A stop.** The end of a turn. You get your position in the plan, what was built, what you can check, and what - changed. The reasoning does not lead. + changed. The reasoning does not lead, and the stop asks you nothing about a later piece. - **The pre-build ask.** For a piece the plan marked expensive to walk back, the skill asks what you expect before it - builds. Declining is a complete answer. + builds. The ask is a turn of its own: it arrives after you have responded to the previous stop, or to the plan when + the marked piece is the first, and nothing is built until you answer it or decline. Declining is a complete answer. - **The feedback record.** A file holding everything you said, so a correction you gave at the second stop still applies at the seventh. You can read it whenever you ask. - **A backing skill.** An existing skill that does the work while this one handles the pacing. The skills that carry the @@ -82,8 +83,9 @@ Alongside it, one file: the running feedback record. It lives under the output b configuration. Each run gets its own file, so a second run does not overwrite the first. The skill names the path in the plan it proposes, and again when the loop ends. -The record holds each piece of feedback you gave and which piece prompted it. When the skill applies a recorded entry to -a later piece, it names which entry, so a misrecorded correction surfaces while it is still cheap to fix. +The record holds each piece of feedback you gave, in your words, and which stop or ask prompted it, and any reading the +skill adds is labeled as its own. When the skill applies a recorded entry to a later piece, it names which entry, so a +misrecorded correction surfaces while it is still cheap to fix. ## How to get the most out of it @@ -96,8 +98,9 @@ a later piece, it names which entry, so a misrecorded correction surfaces while - **Ask for several pieces at once when you are moving fast.** "Show me the next three" is honored as asked, and the loop returns to its normal pace afterward without being asked. This is the middle gear between full ceremony and turning review off. -- **Answer the pre-build ask honestly, including with "I don't know."** Declining advances the stop exactly as a - considered answer does. The ask exists to get an independent read, and a manufactured guess is worth less than none. +- **Answer the pre-build ask honestly, including with "I don't know."** Declining advances the piece exactly as a + considered answer does, and only a reply to the ask counts as one: approving the previous piece never declines an ask + you have not answered. The ask exists to get an independent read, and a manufactured guess is worth less than none. - **Read the feedback record if a later piece feels subtly wrong.** That is usually a correction recorded in a way you did not intend, and it is much easier to spot in the file than to reconstruct from memory. - **Pair with `/code-review` afterward.** Reviewing as it goes catches direction; a review pass at the end catches @@ -115,7 +118,8 @@ establishes what a run of approvals means. See [YAGNI](../../../docs/yagni.md). ## Cost and latency Runs on the session model with no dispatch fan-out of its own. The skill itself is thin: the cost is whatever the -backing skill would have cost, plus one turn per stop. +backing skill would have cost, plus one turn per stop, and one more for each piece the plan marked expensive to walk +back. The expensive part is your attention, not tokens. A long session with many stops is the shape this is built for, and the several-pieces-at-once gear exists so you can spend that attention unevenly. Built for tight-loop iteration, not for a diff --git a/han-core/references/collaborative-stop-rule.md b/han-core/references/collaborative-stop-rule.md index 61f91898..48086b9c 100644 --- a/han-core/references/collaborative-stop-rule.md +++ b/han-core/references/collaborative-stop-rule.md @@ -62,6 +62,10 @@ The reasoning behind the choices comes last or not at all. State in one line tha stop there BECAUSE an unannounced affordance in a conversation is the same as no affordance, while a volunteered rationale is the thing that suppresses scrutiny. +A stop covers what just closed and asks nothing about a later piece. Its position line reports what remains, and naming +the work that comes next is a report, not a question. The one question this convention poses about a piece not yet +built is the pre-build ask, and it has a turn of its own. + Then end the turn. Nothing further is built until the person responds. That last instruction is a directive, not a guarantee. Nothing in the platform enforces it. When a run does build past a @@ -93,8 +97,21 @@ test as provisional and revisit it once real runs show whether it marks the piec **The ask itself** names the dimension the choice turns on and stops there. Do not pose a blank question, and do not offer candidate answers, BECAUSE named candidates anchor the guess and the point is an independent read. +**The ask is a turn of its own.** It opens the marked piece's turn, after the person has responded to the previous +stop, or to the plan when the marked piece is the first, and it is the whole turn: pose it and end the turn. Never +append it to that stop or plan, BECAUSE a reply to a stop or a plan is a reply to that alone, and answers nothing about +a later piece. + **Declining is a first-class answer.** "I don't know" and "just show me" advance the piece exactly as a considered -answer does. Never re-prompt, and never require an answer before building. +answer does. Never re-prompt once the person has replied to the ask, and never hold the build for a fuller answer than +the one given. A decline is a reply to the ask. A reply to the previous stop, or to the plan, is a reply to that alone, +and never counts as declining an ask the person has not yet answered. A question about the ask holds it open: answer +the question and end the turn again. + +**A bundled ask is an unanswered ask.** When an earlier turn put the ask into a stop or the plan and the reply spoke +only to that, the ask was never posed on its own: present it now, on its own, before building. That is the first ask, +not a re-prompt. If the piece was already built when this comes to light, do not ask now; say that the run put the ask +under an earlier turn so it went unanswered, and continue from the stop in hand. **After the build, the reveal is an ordinary stop.** It does not restate the person's read, score it, or defend a divergence from it. A stop that grades you teaches you to answer noncommittally, and a stop that argues with you leads @@ -105,6 +122,10 @@ with the reasoning this convention keeps out of the lead. Write every piece of feedback into the running record before acting on it. A correction given at the second stop has to still apply at the seventh, and mid-context material is the least reliably recalled. +An entry holds the person's words and names the stop or ask they answered. A reading the run adds, such as "declined" +or "approved", follows the words and is marked as the run's, never written as what the person decided. An entry reads, +for example, "Piece 2 stop: 'commit and next' (run's reading: approved)". An ask with no entry is an ask with no answer. + The person can read the record whenever they ask. When a recorded entry shapes a later piece, name which entry it was, so a misrecorded correction surfaces while it is still cheap to fix rather than quietly governing the rest of the session. diff --git a/han-core/skills/pairing/SKILL.md b/han-core/skills/pairing/SKILL.md index 05ce18fb..95dc6f32 100644 --- a/han-core/skills/pairing/SKILL.md +++ b/han-core/skills/pairing/SKILL.md @@ -149,9 +149,17 @@ Then wait. The person accepts the plan, changes it, or replaces it. Repeat until the plan is finished or the person ends it. The loop walks the concerns in the order the plan named, and the pieces inside each one in the order the plan named. -1. **If the plan marked this piece expensive to walk back, ask first.** Follow the ask protocol in the stop rule: name - the dimension the choice turns on, offer no candidate answers, and accept a declined answer as a complete one. The ask - comes before the build, never after. +1. **If the plan marked this piece expensive to walk back, ask first, in a turn of its own.** The ask opens this piece's + turn, after the person has responded to the previous stop, or to the plan when this is the first piece. Name the + dimension the choice turns on, offer no candidate answers, and end the turn. Never append the ask to that stop or + plan, BECAUSE a reply to it is a reply to that alone and answers nothing about this piece. + + When the reply arrives, write it into the record in the person's words, against this ask, then build. A declined + answer is a complete one, and a question about the ask holds it open: answer it and end the turn again. The reply is + not routed through Step 6, which handles replies to a stop. + + When an earlier turn already bundled the ask into a stop or the plan and the reply spoke only to that, the ask was + never posed on its own: present it now, on its own, before building. 2. **Build one piece.** @@ -170,15 +178,16 @@ the pieces inside each one in the order the plan named. checked, what changed, and one line saying the reasoning is available for the asking. When the piece closes a concern, say so in the position line and name the concern that comes next. That tells the - person the next response starts different work, which is the moment their review matters most. + person the next response starts different work, which is the moment their review matters most. That is a report + about what comes next, never a question about it. 4. **End the turn.** Nothing further is built until the person responds. **Starting the next concern is not an exception**, however directly it follows from the one that just closed. ## Step 6: Act on the Response -Write the response into the record before acting on it. When a recorded entry shapes this piece, name which entry it -was. +Write the response into the record, in the person's words and against the stop or ask it answers, before acting on it. +When a recorded entry shapes this piece, name which entry it was. Then route by what the feedback touches, per the stop rule: diff --git a/han-planning/references/collaborative-stop-rule.md b/han-planning/references/collaborative-stop-rule.md index 61f91898..48086b9c 100644 --- a/han-planning/references/collaborative-stop-rule.md +++ b/han-planning/references/collaborative-stop-rule.md @@ -62,6 +62,10 @@ The reasoning behind the choices comes last or not at all. State in one line tha stop there BECAUSE an unannounced affordance in a conversation is the same as no affordance, while a volunteered rationale is the thing that suppresses scrutiny. +A stop covers what just closed and asks nothing about a later piece. Its position line reports what remains, and naming +the work that comes next is a report, not a question. The one question this convention poses about a piece not yet +built is the pre-build ask, and it has a turn of its own. + Then end the turn. Nothing further is built until the person responds. That last instruction is a directive, not a guarantee. Nothing in the platform enforces it. When a run does build past a @@ -93,8 +97,21 @@ test as provisional and revisit it once real runs show whether it marks the piec **The ask itself** names the dimension the choice turns on and stops there. Do not pose a blank question, and do not offer candidate answers, BECAUSE named candidates anchor the guess and the point is an independent read. +**The ask is a turn of its own.** It opens the marked piece's turn, after the person has responded to the previous +stop, or to the plan when the marked piece is the first, and it is the whole turn: pose it and end the turn. Never +append it to that stop or plan, BECAUSE a reply to a stop or a plan is a reply to that alone, and answers nothing about +a later piece. + **Declining is a first-class answer.** "I don't know" and "just show me" advance the piece exactly as a considered -answer does. Never re-prompt, and never require an answer before building. +answer does. Never re-prompt once the person has replied to the ask, and never hold the build for a fuller answer than +the one given. A decline is a reply to the ask. A reply to the previous stop, or to the plan, is a reply to that alone, +and never counts as declining an ask the person has not yet answered. A question about the ask holds it open: answer +the question and end the turn again. + +**A bundled ask is an unanswered ask.** When an earlier turn put the ask into a stop or the plan and the reply spoke +only to that, the ask was never posed on its own: present it now, on its own, before building. That is the first ask, +not a re-prompt. If the piece was already built when this comes to light, do not ask now; say that the run put the ask +under an earlier turn so it went unanswered, and continue from the stop in hand. **After the build, the reveal is an ordinary stop.** It does not restate the person's read, score it, or defend a divergence from it. A stop that grades you teaches you to answer noncommittally, and a stop that argues with you leads @@ -105,6 +122,10 @@ with the reasoning this convention keeps out of the lead. Write every piece of feedback into the running record before acting on it. A correction given at the second stop has to still apply at the seventh, and mid-context material is the least reliably recalled. +An entry holds the person's words and names the stop or ask they answered. A reading the run adds, such as "declined" +or "approved", follows the words and is marked as the run's, never written as what the person decided. An entry reads, +for example, "Piece 2 stop: 'commit and next' (run's reading: approved)". An ask with no entry is an ask with no answer. + The person can read the record whenever they ask. When a recorded entry shapes a later piece, name which entry it was, so a misrecorded correction surfaces while it is still cheap to fix rather than quietly governing the rest of the session. From 0576c644bf8bb69e4737657dbe796b8d51664b14 Mon Sep 17 00:00:00 2001 From: River Lynn Bailey Date: Fri, 11 Sep 2026 10:11:53 -0600 Subject: [PATCH 3/3] docs(han-core): describe the bundled-ask recovery in the pairing doc Claude-Session: https://claude.ai/code/session_01BJD7BG1DpPxHNySU87BaXk --- han-core/docs/skills/pairing.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/han-core/docs/skills/pairing.md b/han-core/docs/skills/pairing.md index a3be7a18..392d1c9e 100644 --- a/han-core/docs/skills/pairing.md +++ b/han-core/docs/skills/pairing.md @@ -100,7 +100,9 @@ misrecorded correction surfaces while it is still cheap to fix. turning review off. - **Answer the pre-build ask honestly, including with "I don't know."** Declining advances the piece exactly as a considered answer does, and only a reply to the ask counts as one: approving the previous piece never declines an ask - you have not answered. The ask exists to get an independent read, and a manufactured guess is worth less than none. + you have not answered. If a run folds the ask into a stop anyway, it poses the ask again on its own before building, + or, when the piece is already built, tells you the ask went unanswered rather than asking after the fact. The ask + exists to get an independent read, and a manufactured guess is worth less than none. - **Read the feedback record if a later piece feels subtly wrong.** That is usually a correction recorded in a way you did not intend, and it is much easier to spot in the file than to reconstruct from memory. - **Pair with `/code-review` afterward.** Reviewing as it goes catches direction; a review pass at the end catches