@hanzlaa/rcode 4.13.0 → 4.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -243,7 +243,69 @@ Display research complete banner and key findings:
243
243
  Files: `.planning/research/`
244
244
  ```
245
245
 
246
- **If "Skip research":** Continue to Step 7.
246
+ ## 6b. Stack confirmation gate HARD STOP
247
+
248
+ **The stack is never decided for the user. Not by research, not by a
249
+ recommendation, not by "the obvious choice for this domain."** Research produces
250
+ a *suggestion*; only the user turns it into a decision.
251
+
252
+ This gate runs whether research ran or was skipped. If research was skipped, ask
253
+ with no recommendation attached — you have no grounds for one.
254
+
255
+ ```
256
+ AskUserQuestion:
257
+ header: "Stack"
258
+ question: "Research suggests {STACK} because {the one reason that actually drove it}. Confirm?"
259
+ options:
260
+ - label: "Confirm {STACK}"
261
+ description: "{the trade-off the user is accepting, stated plainly}"
262
+ - label: "I'll choose the stack"
263
+ description: "Tell me what to build on and I'll record that instead."
264
+ - label: "Research more first"
265
+ description: "Compare against {the closest alternative} before deciding."
266
+ ```
267
+
268
+ **Nothing proceeds until the user answers.** Not requirements, not the roadmap,
269
+ not a single file. An unanswered question is not a confirmation, and neither is
270
+ silence, `--auto`, or `auto_advance`. **Auto mode does NOT bypass this gate** —
271
+ every other question in this workflow has an auto default; this one does not,
272
+ because a wrong stack is the most expensive thing in the project to reverse.
273
+
274
+ State the reason the suggestion exists, in one sentence, in the user's terms.
275
+ "Research recommends WordPress" is not a reason. "WordPress because a
276
+ non-technical client will update content themselves, with no dev retainer" is —
277
+ and stated that way the user can see immediately whether the premise is true.
278
+
279
+ Record the answer with `state add-decision`, including the premise it rests on:
280
+
281
+ ```bash
282
+ node ".rcode/bin/rcode-tools.cjs" state add-decision \
283
+ "Stack: {chosen}. Premise: {the one reason}. Confirmed by user {date}."
284
+ node ".rcode/bin/rcode-tools.cjs" memlog append --type decision \
285
+ --text "Stack: {chosen}. Premise: {the one reason}. User-confirmed at the stack gate."
286
+ ```
287
+
288
+ ### The premise is part of the decision
289
+
290
+ **A stack decision is only valid while its premise holds.** Write the premise
291
+ into the decision, then re-open the decision the moment the premise changes.
292
+
293
+ Confirmed live: a site was scoped for a non-technical client, so research picked
294
+ WordPress and the roadmap locked it. The project later pivoted to a model with no
295
+ client at all — the maintainer was the technical owner. Every planning doc was
296
+ rewritten for the pivot and the stack stayed "Locked", because nothing in the
297
+ loop treats a locked decision as re-openable. A PHP theme got built and then
298
+ migrated wholesale to a static generator to undo it.
299
+
300
+ **On any pivot, re-run this gate** for every decision whose stated premise the
301
+ pivot invalidated. A decision whose reason has expired is not locked, it is
302
+ stale.
303
+
304
+ **If "Research more first":** run the comparison against the named alternative,
305
+ then return to this gate. Do not proceed past it.
306
+
307
+ **If "Skip research":** Continue to Step 6b — you still need the stack gate,
308
+ you just have no suggestion to offer.
247
309
 
248
310
 
249
311
  ## Next Up
@@ -475,7 +475,12 @@ Proceed to Step 4 (skip Steps 3 and 5).
475
475
 
476
476
  ## 3. Deep Questioning
477
477
 
478
- **If auto mode:** Skip (already handled in Step 2a). Extract project context from provided document instead and proceed to Step 4.
478
+ **If auto mode:** extract project context from the provided document instead of
479
+ asking. **You still owe the user the Mandatory decision set** — resolve each item
480
+ from the document where it answers one, and where it does not, list what you are
481
+ assuming before Step 4 writes PROJECT.md. Auto mode removes the conversation, not
482
+ the accountability. If the document leaves the maintainer or the stack unanswered,
483
+ stop and ask those two regardless of mode.
479
484
 
480
485
  **Display stage banner:**
481
486
 
@@ -491,6 +496,20 @@ Ask inline (freeform, NOT AskUserQuestion):
491
496
 
492
497
  "What do you want to build?"
493
498
 
499
+ **Then, before any deeper questioning, run two short probes from
500
+ `@.rcode/references/questioning.md` — in this order:**
501
+
502
+ 1. **Stakes calibration** — hobby/solo, internal tool, or launch? Scale every
503
+ artifact and gate below to the answer. Do not run the launch-grade pipeline on
504
+ a weekend project.
505
+ 2. **Working mode** — Fast path (batched questions, draft with `[ASSUMPTION]`
506
+ tags) or Coaching path (walk the decisions together)? **Ask it. Never infer it
507
+ from `auto_advance`, from how detailed their opening message was, or from your
508
+ own read of their hurry.** Only `--auto`/yolo picks Fast path without asking.
509
+
510
+ These two answers govern the rest of this workflow. Record them with
511
+ `state add-decision` so a later resume does not re-guess them.
512
+
494
513
  Wait for their response. This gives you the context needed to ask intelligent follow-up questions.
495
514
 
496
515
  **Research-before-questions mode:** Check if `workflow.research_before_questions` is enabled in `.rcode/config.yaml` (via `node .rcode/bin/rcode-tools.cjs config-get workflow.research_before_questions`). When enabled, before asking follow-up questions about a topic:
@@ -527,6 +546,11 @@ Mentally check the context checklist. If gaps remain, weave questions naturally.
527
546
 
528
547
  **Decision gate:**
529
548
 
549
+ **Before the decision gate, show your coverage.** State plainly which items of the
550
+ Mandatory decision set (`@.rcode/references/questioning.md`) the user actually
551
+ answered and which you are assuming, with each assumption spelled out in one line.
552
+ An assumption the user never saw is a decision you made for them.
553
+
530
554
  When you could write a clear PROJECT.md, use AskUserQuestion:
531
555
 
532
556
  - header: "Ready?"
@@ -601,16 +625,61 @@ Synthesize all context into `.planning/PROJECT.md`. If `.rcode/templates/project
601
625
  - [ ] {Requirement 2}
602
626
  - [ ] {Requirement 3}
603
627
 
604
- ### Out of Scope
628
+ ### Out of Scope (Non-Goals)
629
+
630
+ *What this project is NOT and will NOT do. This does outsized work downstream —
631
+ it is what prevents the "let me also add this nearby thing" failure at every
632
+ level: phase, sprint, task, and code. An unstated exclusion reappears later as a
633
+ gap; a stated one ends the argument before it starts.*
605
634
 
606
635
  - {Exclusion 1} — {why}
607
636
  - {Exclusion 2} — {why}
608
637
 
638
+ **Scope dial:** hobby/solo — the two or three things you keep being tempted by.
639
+ Internal tool — plus anything a stakeholder has already asked for and been told
640
+ no. Launch — plus the "we are not becoming X" statements about the product's
641
+ identity.
642
+
643
+ ## Glossary
644
+
645
+ *Every domain noun this project uses, defined once. Downstream agents and
646
+ documents use these terms verbatim — introducing a synonym anywhere is a
647
+ discipline violation, because two names for one thing is how a codebase ends up
648
+ with two implementations of it.*
649
+
650
+ - **{Term}** — {definition}. {relationship to other terms, cardinality if it matters}
651
+
652
+ **Scope dial:** hobby/solo — only terms that are genuinely ambiguous, often 2-3.
653
+ Internal tool — every domain noun. Launch — every domain noun plus the ones the
654
+ team argues about.
655
+
609
656
  ## Key Decisions
610
657
 
611
- | Decision | Rationale | Outcome |
612
- |----------|-----------|---------|
613
- | {Choice} | {Why} | — Pending |
658
+ | Decision | Premise (what makes it right) | Rationale | Outcome |
659
+ |----------|-------------------------------|-----------|---------|
660
+ | {Choice} | {the condition this rests on} | {Why} | — Pending |
661
+
662
+ *The **Premise** column is load-bearing. A decision is valid only while its
663
+ premise holds — when the project pivots, every decision whose premise the pivot
664
+ invalidated goes back to the user. A decision whose reason has expired is not
665
+ locked, it is stale.*
666
+
667
+ ## Assumptions Index
668
+
669
+ *Every `[ASSUMPTION]` tag in this document and in REQUIREMENTS.md, gathered here
670
+ for explicit confirmation. An assumption the user never saw is a decision nobody
671
+ made.*
672
+
673
+ | # | Assumption | Where | Status |
674
+ |---|-----------|-------|--------|
675
+ | A-1 | {what was inferred} | §{section} | unconfirmed |
676
+
677
+ **This table is walked with the user before the document is treated as settled.**
678
+ Each row ends as confirmed, corrected, or deferred with an owner. Auto mode does
679
+ not skip the walk; it defers it to the first interactive turn.
680
+
681
+ **Scope dial:** the table exists at every stakes level. Hobby/solo may resolve it
682
+ in one exchange; launch resolves it row by row.
614
683
 
615
684
  ## Constraints
616
685
 
@@ -628,19 +697,44 @@ This document evolves at phase transitions and milestone boundaries.
628
697
  1. Requirements invalidated? → Move to Out of Scope with reason
629
698
  2. Requirements validated? → Move to Validated with phase reference
630
699
  3. New requirements emerged? → Add to Active
631
- 4. Decisions to log? → Add to Key Decisions
700
+ 4. Decisions to log? → Add to Key Decisions, WITH its premise
632
701
  5. "What This Is" still accurate? → Update if drifted
702
+ 6. New domain nouns introduced? → Add to Glossary in the same pass
703
+ 7. Any `[ASSUMPTION]` resolved or added? → Update the Assumptions Index
704
+ 8. Did anything invalidate a recorded premise? → That decision reopens
633
705
 
634
706
  **After each milestone** (via `/rcode-complete-milestone`):
635
707
  1. Full review of all sections
636
708
  2. Core Value check — still the right priority?
637
709
  3. Audit Out of Scope — reasons still valid?
638
710
  4. Update Context with current state
711
+ 5. Assumptions Index — any row still `unconfirmed` after a whole milestone is a
712
+ finding, not a formality. Resolve or escalate it
713
+ 6. Key Decisions — check every premise still holds
714
+ 7. **Memlog audit** — `rcode-tools.cjs memlog open` lists every assumption,
715
+ override, and blocker logged during the milestone. Walk it: each one is
716
+ captured in PROJECT.md, resolved, or explicitly deferred with an owner.
717
+ Entries that survive a whole milestone unexamined are the ones that turn into
718
+ "nobody knows why this is like this"
639
719
 
640
720
  ---
641
721
  *Last updated: {date} after initialization*
642
722
  ```
643
723
 
724
+ **Scale every section to the stakes answer from Step 3.** The template is one
725
+ document that serves a weekend project and a launch; the scope dials on each
726
+ section say how. Running the launch-grade depth on a hobby project is its own
727
+ failure — the user abandons the process, not the project.
728
+
729
+ | Stakes | PROJECT.md target |
730
+ |---|---|
731
+ | Hobby / solo | About a page. Glossary only where terms are ambiguous |
732
+ | Internal tool | Two to four pages. Every section present, lightly filled |
733
+ | Launch | As long as the requirements and concerns need |
734
+
735
+ Never pad a section to look thorough, and never drop one silently — if a section
736
+ genuinely does not apply, say so in one line where it would have been.
737
+
644
738
  **For greenfield projects:** Initialize requirements as hypotheses (all Active).
645
739
 
646
740
  **For brownfield projects (codebase map exists):** Read `.planning/codebase/ARCHITECTURE.md` and `STACK.md`. Identify what the codebase already does — these become the initial Validated set.
@@ -100,6 +100,24 @@ drafting tasks inline, the run has lost its orchestrator — spawn the planner
100
100
  instead. A SPRINT.md with no planner `Task()` behind it is the failure this rule
101
101
  exists to prevent (see step 8).
102
102
 
103
+ ## 0.4. Record the authorized scope
104
+
105
+ ```bash
106
+ # Project overrides for this workflow — appended after everything below, and
107
+ # they win on conflict. The installer never writes .rcode/custom/, so these
108
+ # survive `rcode install`.
109
+ node ".rcode/bin/rcode-tools.cjs" customize resolve plan
110
+ node ".rcode/bin/rcode-tools.cjs" state set-intent plan --source plan.md
111
+ node ".rcode/bin/rcode-tools.cjs" memlog append --type event --text "Planning started for phase ${PHASE}" --phase "${PHASE}"
112
+ ```
113
+
114
+ **Log as you go from here.** Every decision the panel forces, every checker issue
115
+ you accept or reject, every assumption the planner had to make — one
116
+ `memlog append` line each, at the moment it happens.
117
+
118
+ This is what the user asked for on THIS invocation, and it is what `resume-work`
119
+ will restore later. Planning does not authorize building — see step 15.
120
+
103
121
  ## 0.5. Project-Status Preflight
104
122
 
105
123
  ```bash
@@ -306,11 +324,11 @@ If `TEXT_MODE` is true, present as a plain-text numbered list:
306
324
  ```
307
325
  No CONTEXT.md found for Phase {X}. Plans will use research and requirements only — your design preferences won't be included.
308
326
 
309
- 1. Continue without context — Plan using research + requirements only
310
327
  [If DISCUSS_MODE is "assumptions":]
311
- 2. Gather context (assumptions mode) — Analyze codebase and surface assumptions before planning
328
+ 1. Gather context (assumptions mode) [recommended] — Analyze codebase and surface assumptions before planning
312
329
  [If DISCUSS_MODE is "discuss" or unset:]
313
- 2. Run discuss-phase first — Capture design decisions before planning
330
+ 1. Run discuss-phase first [recommended] — Capture design decisions before planning
331
+ 2. Continue without context — Plan using research + requirements only; your design preferences will not be in the plan
314
332
 
315
333
  Enter number:
316
334
  ```
@@ -319,11 +337,13 @@ Otherwise use AskUserQuestion:
319
337
  - header: "No context"
320
338
  - question: "No CONTEXT.md found for Phase {X}. Plans will use research and requirements only — your design preferences won't be included. Continue or capture context first?"
321
339
  - options:
322
- - "Continue without context" Plan using research + requirements only
340
+ (Recommended option FIRSTrcode was recommending the skip, which is how phases
341
+ got planned with the user's design decisions never captured.)
323
342
  If `DISCUSS_MODE` is `"assumptions"`:
324
- - "Gather context (assumptions mode)" — Analyze codebase and surface assumptions before planning
343
+ - "Gather context (assumptions mode) (Recommended)" — Analyze codebase and surface assumptions before planning
325
344
  If `DISCUSS_MODE` is `"discuss"` (or unset):
326
- - "Run discuss-phase first" — Capture design decisions before planning
345
+ - "Run discuss-phase first (Recommended)" — Capture design decisions before planning
346
+ - "Continue without context" — Plan using research + requirements only; your design preferences will not be in the plan
327
347
 
328
348
  If "Continue without context": Proceed to step 5.
329
349
  If "Run discuss-phase first":
@@ -926,7 +946,30 @@ Returns (else branch only):
926
946
 
927
947
  After plans pass the checker (or checker is skipped), verify that all phase requirements are covered by at least one plan.
928
948
 
929
- **Skip if:** `phase_req_ids` is null, `TBD`, or an empty array/list (no requirements mapped to this phase) `[[ -z "$phase_req_ids" || "$phase_req_ids" == "TBD" || "$phase_req_ids" == "[]" || "$phase_req_ids" == "null" ]]` — proceed to step 14.
949
+ **If `phase_req_ids` is empty, the gate does NOT silently skipit reports why.**
950
+ An empty array has two very different causes and they must not look the same:
951
+
952
+ 1. This phase genuinely maps to no requirements. Fine, say so and continue.
953
+ 2. REQUIREMENTS.md HAS a traceability table and nothing parsed out of it. That is
954
+ a broken gate reporting as a passing one.
955
+
956
+ Distinguish them before proceeding:
957
+
958
+ ```bash
959
+ if [ -f .planning/REQUIREMENTS.md ] && grep -qE '\b[A-Z][A-Z0-9]{1,15}-[0-9]+\b' .planning/REQUIREMENTS.md; then
960
+ echo "⚠ Requirements coverage gate SKIPPED but REQUIREMENTS.md contains requirement IDs."
961
+ echo " phase_req_ids came back empty — the phase→requirement mapping in ROADMAP.md"
962
+ echo " is missing or unparseable, so nothing is verifying coverage for this phase."
963
+ echo " Fix the phase's **Requirements:** line in ROADMAP.md, then re-run."
964
+ fi
965
+ ```
966
+
967
+ Surface that warning to the user; do not bury it. Confirmed live: a project's
968
+ requirement IDs were all domain-prefixed (`FOUND-01`, `RENT-04`), the extractor
969
+ only matched `REQ-*`, and this gate skipped itself on every phase while
970
+ appearing to pass.
971
+
972
+ Then proceed to step 14 when the array really is empty.
930
973
 
931
974
  **Step 1: Extract requirement IDs claimed by plans**
932
975
  ```bash
@@ -1028,7 +1071,34 @@ if ([[ "$ARGUMENTS" =~ --auto ]] || [[ "$ARGUMENTS" =~ --chain ]]) && [[ "$AUTO_
1028
1071
  fi
1029
1072
  ```
1030
1073
 
1031
- **If `--auto` or `--chain` flag present OR `AUTO_CHAIN` is true OR `AUTO_CFG` is true:**
1074
+ **`AUTO_CFG` alone is NOT sufficient.** A persistent `workflow.auto_advance: true`
1075
+ in settings must never silently turn "plan this" into "plan and build this". The
1076
+ user's invocation is their declared scope: they typed a planning command, so
1077
+ planning is what was authorized. A config flag set weeks ago is not consent for
1078
+ this build.
1079
+
1080
+ Confirmed live: a user asked for a project to be planned, `auto_advance` was on,
1081
+ and the session planned and then built a WordPress theme, then migrated the whole
1082
+ thing to Astro to undo its own stack choice. The user's words were "plan karo".
1083
+ Nothing in the loop stopped at the boundary they actually drew.
1084
+
1085
+ **If `AUTO_CFG` is true but neither `--auto`/`--chain` nor `AUTO_CHAIN` is set:**
1086
+ ask before advancing, and default to stopping:
1087
+
1088
+ ```
1089
+ AskUserQuestion:
1090
+ question: "Plans are ready. auto_advance is on in your config — execute phase {N} now?"
1091
+ options:
1092
+ - label: "Stop here (Recommended)"
1093
+ description: "Plans written and verified. Review them, then run /rcode-execute {N} when ready."
1094
+ - label: "Execute now"
1095
+ description: "Chain straight into execution, as auto_advance requests."
1096
+ ```
1097
+
1098
+ In `--text` mode present this as a numbered list. If the user does not answer,
1099
+ STOP — an unanswered question is not approval.
1100
+
1101
+ **If `--auto` or `--chain` flag present OR `AUTO_CHAIN` is true:**
1032
1102
 
1033
1103
  Display banner:
1034
1104
  ```
@@ -1156,6 +1226,7 @@ ${WINDOWS === 'true' ? '@.rcode/references/plan-windows-troubleshooting.md' : ''
1156
1226
  - [ ] Phase directory created if needed
1157
1227
  - [ ] CONTEXT.md loaded early (step 4) and passed to ALL agents
1158
1228
  - [ ] Research completed (unless --skip-research or --gaps or exists)
1229
+ - [ ] Auto-advance fired only on an explicit `--auto`/`--chain` or an answered confirmation, never on `auto_advance` config alone
1159
1230
  - [ ] Specialist review panel spawned (Waleed + Fatima + domain agents) and its blocking issues fed into the revision loop, or `workflow.specialist_review: false` recorded
1160
1231
  - [ ] rcode-phase-researcher spawned with CONTEXT.md
1161
1232
  - [ ] Existing plans checked
@@ -197,6 +197,24 @@ Based on project state, determine the most logical next action:
197
197
  </step>
198
198
 
199
199
  <step name="offer_options">
200
+ **"Resume" restores position, never scope.** It tells you WHERE the work stopped;
201
+ it does not tell you what the user authorized. Present options and wait — do not
202
+ pick one and start.
203
+
204
+ The failure this prevents: a user asks for a project to be planned, the session
205
+ plans it, the user later types "resume", and the session reads that as "keep
206
+ going" and starts building. The standing instruction was still "plan". Confirmed
207
+ live, and the cleanup cost more than the work.
208
+
209
+ Two rules:
210
+
211
+ - **Never begin implementation from a resume.** If the state says the phase is
212
+ ready to execute, that is an option to OFFER, not an action to take. Execution
213
+ starts when the user runs `/rcode-execute`, not when a menu suggests it.
214
+ - **Say what the last authorized scope was**, if the state records one (see
215
+ `state read` → `last_intent`, written by plan.md and execute.md). If it does not, say that plainly rather than
216
+ inferring one: `Last recorded scope: unknown — tell me plan or build.`
217
+
200
218
  Present contextual options based on project state:
201
219
 
202
220
  ```