@tekyzinc/gsd-t 5.0.13 → 5.1.10

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.
@@ -21,6 +21,9 @@
21
21
  const fs = require("fs");
22
22
  const path = require("path");
23
23
  const crypto = require("crypto");
24
+ // M102 — the marker-block idempotent doc-writer was extracted here into the ONE
25
+ // shared module both this scaffolder and bin/gsd-t-env-registry.cjs call.
26
+ const { upsertMarkedDocBlock } = require("./gsd-t-doc-marker.cjs");
24
27
 
25
28
  const VALID_BACKENDS = ["db-table", "local-sqlite", "local-jsonl"];
26
29
 
@@ -182,24 +185,9 @@ function writeChoiceToProjectDocs(projectDir, envelope) {
182
185
  const targetPath = candidates.find((p) => fs.existsSync(p)) || candidates[0];
183
186
 
184
187
  const block = docBlock(envelope);
185
- let content = "";
186
- if (fs.existsSync(targetPath)) {
187
- content = fs.readFileSync(targetPath, "utf8");
188
- } else {
189
- const dir = path.dirname(targetPath);
190
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
191
- }
192
-
193
- if (content.includes(DOC_MARKER_START) && content.includes(DOC_MARKER_END)) {
194
- const startIdx = content.indexOf(DOC_MARKER_START);
195
- const endIdx = content.indexOf(DOC_MARKER_END) + DOC_MARKER_END.length;
196
- content = content.slice(0, startIdx) + block + content.slice(endIdx);
197
- } else {
198
- content = content.replace(/\s*$/, "") + "\n\n" + block + "\n";
199
- }
200
-
201
- fs.writeFileSync(targetPath, content, "utf8");
202
- return targetPath;
188
+ // M102 delegate to the ONE shared marker-block writer (byte-identical logic
189
+ // to the former inline replace/append; extracted so env-registry reuses it).
190
+ return upsertMarkedDocBlock(targetPath, DOC_MARKER_START, DOC_MARKER_END, block);
203
191
  }
204
192
 
205
193
  // ─── Seam envelope builder ──────────────────────────────────────────────────
@@ -307,6 +307,8 @@ function _detectDefaultTrack2(projectDir, notes) {
307
307
 
308
308
  plan.push({ id: 'logging-envelope', cmd: 'node', args: [path.join(__dirname, 'gsd-t-logging-envelope-check.cjs'), '--project', projectDir], timeoutMs: 30000 }); // M100 D3: structural trace+audit envelope gate, FAIL-CLOSED
309
309
 
310
+ plan.push({ id: 'env-registry', cmd: 'node', args: [path.join(__dirname, 'gsd-t-env-registry-check.cjs'), '--project', projectDir], timeoutMs: 30000 }); // M102 D3: no-secret-in-registry + rule-without-table gate, FAIL-CLOSED
311
+
310
312
  // secrets — gitleaks (PATH detection deferred to runtime)
311
313
  if (_hasOnPath('gitleaks')) {
312
314
  plan.push({
package/bin/gsd-t.js CHANGED
@@ -2999,6 +2999,16 @@ const PROJECT_BIN_TOOLS = [
2999
2999
  // ship to every project or the consumers can't classify. Same propagation class as
3000
3000
  // gsd-t-graph-store-resolver.cjs above. [[project_global_bin_propagation_gap]]
3001
3001
  "gsd-t-graph-availability.cjs",
3002
+ // M102 — Environment Registry. The shared marker-block doc-writer + the
3003
+ // registry helper (record/lookup/detect/add-permission/ensure-gitignore).
3004
+ // Sandboxed workflows (init/populate + provisioning execute/quick tasks) call
3005
+ // the registry via project-local Bash, and the registry `require`s the shared
3006
+ // writer at load — BOTH must ship or the registry throws / the writer is a
3007
+ // second copy. Same propagation class as the graph tools above.
3008
+ // [[project_global_bin_propagation_gap]]
3009
+ // Plus the verify-gate lint (gsd-t-verify-gate.cjs invokes it via __dirname,
3010
+ // so it must sit alongside the gate in the project's bin/).
3011
+ "gsd-t-doc-marker.cjs", "gsd-t-env-registry.cjs", "gsd-t-env-registry-check.cjs",
3002
3012
  ];
3003
3013
 
3004
3014
  // Files that older versions of this installer copied into project bin/ but
@@ -79,6 +79,18 @@ The subagent works through the six stages IN ORDER. Each can kill or reshape the
79
79
  the simpler fix actually works** — if the plan says "handled elsewhere / picked up later,"
80
80
  VERIFY that's true; do not assert self-healing you haven't checked. (This is the trap that
81
81
  hides inside a simplification.)
82
+ 6b. **NO-FALLBACK-EVER** — Does the design add ANY fallback (anything that CONTINUES after a
83
+ failure: catch-and-continue, `|| default`, silent degrade, try-X-else-Y where Y masks X
84
+ failing)? If yes, do NOT design it in — surface it as an OPEN QUESTION for the user, UNLESS
85
+ you can cite a confirmed reproducible case only a fallback catches. The straight-line process
86
+ that produces the result is the goal; where it can fail, prefer a **HALT** (stop + demand
87
+ fix), which is NOT a fallback. (See CLAUDE.md § No-Fallback-Ever Doctrine.)
88
+ 7. **SIMPLY-STATED** (clarity gate — the review is NOT done until this passes) — state every
89
+ finding and the verdict SIMPLY: precise and complete, but every word load-bearing, the logic
90
+ in a straight line, ZERO jargon standing in for a clear idea, no nested clauses hiding a
91
+ tangle. If a finding cannot be stated simply, the thinking on it is not finished — RE-THINK
92
+ the muddled part, do not re-word it. "Too sophisticated to simplify" is a BANNED escape hatch
93
+ (simplify the expression, never the idea). (See CLAUDE.md § Simply Stated Doctrine.)
82
94
 
83
95
  A stage the subagent cannot answer with evidence is a HALT — surface it as an open question for
84
96
  the user, do not paper over it with a guess.
@@ -94,6 +106,10 @@ a summary table, near-zero preamble. For each CURRENT block, say **why it does w
94
106
  successive fixes). Unless `--chat-only`, write it to `.gsd-t/pseudocode/PseudoCode-<Target>.md`.
95
107
 
96
108
  **B — Session summary** (always printed, even under `--build`):
109
+ - **Simply Stated** (REQUIRED FIRST LINE — the clarity gate) — the verdict + the single most
110
+ important finding in ONE clean, jargon-free, straight-line statement a smart non-specialist
111
+ acts on without re-reading. If you cannot write this line cleanly, the review is NOT done —
112
+ re-think, don't re-word. Everything below is the depth for whoever wants it.
97
113
  - **Core objective** (one line)
98
114
  - **Is this a "complicated over time" issue?** (yes/no + the accretion history if yes)
99
115
  - **What's reusable** (process or a stored output already available)
@@ -296,6 +296,12 @@ docs/
296
296
 
297
297
  These are the living documents that persist across milestones and keep institutional knowledge alive. The `infrastructure.md` is especially important — it captures the exact commands for provisioning cloud resources, setting up databases, managing secrets, and deploying, so this knowledge doesn't get lost between sessions.
298
298
 
299
+ The `infrastructure.md` template ships with a marker-delimited `## Environments` table (`<!-- gsd-t-env-registry:start -->` / `:end`) — the committed, **secret-free** connection registry (M102). It is created empty by init and populated by the two triggers:
300
+ - **Greenfield (record-at-create):** whenever this project later BUILDS/PROVISIONS/CONFIGURES an environment (a local test DB, a remote server, credentials, or hands the user setup instructions), record the map row in the SAME pass:
301
+ `node bin/gsd-t-env-registry.cjs record '{"projectDir":".","scope":"local","kind":"postgres","host":"localhost","port":"5432","name":"appdb","authMethod":"password","secretVault":"local (.env)","secretEnvVarName":"DATABASE_URL","fetchCommand":"read $DATABASE_URL from .env","connectCommand":"psql \"$DATABASE_URL\""}'`
302
+ Records only the MAP + vault pointer + env-var NAME + fetch/connect commands — **never a secret VALUE** (a literal password/token in a command is REJECTED). `scope=prod` defaults `read-only=YES`.
303
+ - Also run `node bin/gsd-t-env-registry.cjs ensure-gitignore .` so `.env` is gitignored (auto-add + report; secret-leak precheck).
304
+
299
305
  ## Step 8: Ensure README.md Exists
300
306
 
301
307
  If no `README.md` exists, create one with:
@@ -29,6 +29,11 @@ Scan this codebase and populate the GSD-T documentation. Analyze the actual code
29
29
  - List Credentials and Secrets from .env.example (local) and any secret manager configs
30
30
  - Document Deployment from CI/CD configs, Dockerfiles, cloud configs
31
31
  - Document Logging and Monitoring from any logging setup or dashboard configs
32
+ - **Back-fill the `## Environments` registry (M102 — brownfield capture).** For an existing project whose non-local environments are undocumented, back-fill the map-only Environments table WITHOUT ever reading or writing a secret VALUE:
33
+ 1. `node bin/gsd-t-env-registry.cjs detect .` → proposes the vault + fetch command from `.env.example` var NAMES, connection-string SHAPES, and `vercel.json`/`.vercel` (Vercel) · `cloudbuild.yaml`/`.gcloudignore` (Google Secret Manager) · neon dep (Neon) · plain `.env` (local). Map only — never a value.
34
+ 2. Confirm/fill gaps with the human, then `node bin/gsd-t-env-registry.cjs record '<json>'` per environment (upsert by `(scope, kind)` — a re-provision replaces the stale row).
35
+ 3. `node bin/gsd-t-env-registry.cjs ensure-gitignore .` — auto-add `.env` to `.gitignore` if missing + report.
36
+ - **No-Fallback-Ever:** a genuinely undocumented environment reached for the first time HALTs → detect → ask → record → `add-permission` → proceed. NEVER guess a connection string, NEVER grep transcripts to rediscover.
32
37
 
33
38
  ## Graph Structural Slice — who-imports + cluster (M94-D10)
34
39
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekyzinc/gsd-t",
3
- "version": "5.0.13",
3
+ "version": "5.1.10",
4
4
  "description": "GSD-T: Contract-Driven Development for Claude Code — 54 slash commands with headless-by-default workflow spawning, unattended supervisor relay with event stream, graph-powered code analysis, real-time agent dashboard, task telemetry, doc-ripple enforcement, backlog management, impact analysis, test sync, milestone archival, and PRD generation",
5
5
  "author": "Tekyz, Inc.",
6
6
  "license": "MIT",
@@ -33,13 +33,23 @@
33
33
  const fs = require("fs");
34
34
  const path = require("path");
35
35
 
36
- // One line. A pointer, not the doctrine. Keeps context cost ~nil.
36
+ // A pointer, not the doctrine. Keeps context cost ~nil. Carries TWO reminders:
37
+ // the Six-Stage Pass (design-first) and the No-Fallback-Ever rule (never branch
38
+ // around a failure without asking) — both fire at the write-code moment.
37
39
  const REMINDER =
38
40
  "[GSD-T ARCHITECT] About to write/edit code — run the Architect's Oversight " +
39
41
  "Six-Stage Pass FIRST (Objective → Conflict → Reuse[query the graph] → " +
40
42
  "Simplicity → Reuse-forecast → Risk), each answered with evidence not conviction. " +
41
43
  "Is this the simplest design, and does something reusable already exist? " +
42
- "See ~/.claude/CLAUDE.md § Architect's Oversight Doctrine.";
44
+ "NO-FALLBACK-EVER: if this adds anything that CONTINUES AFTER A FAILURE " +
45
+ "(catch-and-continue, || default, silent degrade, try-X-else-Y) — STOP and ask the " +
46
+ "user first, unless you can cite a confirmed reproducible case only a fallback catches. " +
47
+ "A HALT (stop + demand fix) is NOT a fallback and is the preferred move. " +
48
+ "SIMPLY-STATED: before presenting an architecture/plan/finding, state it SIMPLY — every " +
49
+ "word load-bearing, logic in a straight line, no jargon or nested clauses. If you can't " +
50
+ "state it cleanly the thinking isn't done (muddle in the words = muddle in the design) — " +
51
+ "RE-THINK, don't re-word. 'Too sophisticated to simplify' is a banned escape hatch. " +
52
+ "See ~/.claude/CLAUDE.md § Architect's Oversight + No-Fallback-Ever + Simply Stated Doctrines.";
43
53
 
44
54
  // File extensions that are PROSE/config, not code — skip the reminder for these.
45
55
  // (The doctrine's own artifacts are markdown; reminding while authoring them is noise.)
@@ -99,6 +99,26 @@ NEED TO UNDERSTAND SOMETHING?
99
99
  └── Not documented? → Research, then DOCUMENT IT
100
100
  ```
101
101
 
102
+ ### Environment Access — read-first, HALT-and-document (M102)
103
+
104
+ **EXTENDS No-Re-Research; obeys No-Fallback-Ever.** Before reaching ANY non-local environment (staging/prod DB, remote server, hosted API, SSH host), the connection MAP is read from the committed `## Environments` table in `docs/infrastructure.md` — NEVER re-discovered.
105
+
106
+ ```
107
+ NEED TO REACH A NON-LOCAL ENVIRONMENT?
108
+ ├── lookupEnvironment(scope, kind) FIRST → bin/gsd-t-env-registry.cjs lookup
109
+ ├── Row exists → use its connect command; the secret is pulled at runtime via
110
+ │ the recorded env-var NAME from its vault (never a value in the doc).
111
+ │ scope=prod + read-only=YES + a WRITE op → HALT, confirm with human.
112
+ └── Row MISSING → HALT the connect. Do NOT guess a connection string. Do NOT grep
113
+ transcripts to rediscover. The brownfield path:
114
+ detectEnvConfig → ask human to confirm/fill → recordEnvironment
115
+ → addPermissionEntry → THEN proceed. First need = last rediscovery.
116
+ ```
117
+
118
+ - The registry stores only the MAP + which vault holds the secret + the env-var NAME + the fetch/connect commands — **never a secret VALUE**.
119
+ - **Zero fallback.** A missing row resolves by DOCUMENTING (detect → ask → record → proceed), never by a guessed connstring or a transcript re-grep. That HALT-then-document is NOT a fallback.
120
+ - Greenfield: when GSD-T builds/provisions an env, it records the row in the SAME pass (`recordEnvironment`) — so staleness self-heals (a re-provision upserts by `(scope, kind)` and replaces the stale row).
121
+
102
122
 
103
123
  # Versioning
104
124
 
@@ -456,6 +476,35 @@ See memory pointer: `feedback_auto_research_external_gaps`.
456
476
 
457
477
  **§Enforcement (three layers — same shape as Unproven-Assumption):** (1) this doctrine = the *definition* (reference, always available); (2) a **PreToolUse hook on Write/Edit** = the *trigger* — injects a one-line reminder pointing here at the build moment, so it can't be missed under load; (3) the **plan/milestone workflow gate** = the *execution* — the Six-Stage Pass runs as blocking `agent()` steps with graph/doc evidence, and pseudocode-completeness is a verify check. Injecting the doctrine ≠ executing it; the workflow does the doing.
458
478
 
479
+ ### No-Fallback-Ever Doctrine (governed, enforced — the strongest sibling of No-Silent-Degradation)
480
+
481
+ **Pretend every project is a vampire and the word "fallback" is garlic.** A fallback — **anything that continues after a failure** (a `catch` that keeps going, `|| default`, a silent degrade, a secondary path, a "try X else Y" where Y masks X failing) — is **BANNED unless the user explicitly approves it first, OR you can cite a confirmed, reproducible case where the straight-line path provably fails and ONLY a fallback catches it.** No trivial exception. This is a Destructive-Action-Guard-class STOP: before writing any such branch, **halt and ask the user.**
482
+
483
+ **Why:** the reflex to add a fallback "just in case" is what hides real failures — a fallback that guards an *unproven* case doesn't add safety, it adds a place for a real failure to hide (e.g. a graph query that silently falls back to grep when the graph is actually broken). The desired discipline is the **straight-line process that produces the result**; if the straight line can fail, the answer is **HALT and surface it**, not branch around it.
484
+
485
+ **The one thing that is NOT a fallback (and is REQUIRED where a straight line can fail):** a **HALT** — refusing to continue and demanding a fix (return `blocked-needs-human`, exit non-zero, loud message). A halt is the *opposite* of a fallback: it stops the hiding instead of enabling it. When you're tempted to write a fallback, the correct move is almost always a halt.
486
+
487
+ **Test before writing any "continue after failure" branch:**
488
+ 1. Is this a fallback (continues past a failure) or a halt (stops)? Halt → allowed. Fallback → continue to 2.
489
+ 2. Can I name a **confirmed, reproducible** failing case where ONLY this fallback catches it? If NO → **STOP and ask the user.** If YES → cite it in a comment + the commit, then proceed.
490
+ 3. Never judge "trivial" yourself — the trivial-fallback judgment is exactly the one that has been failing. Ask.
491
+
492
+ **Applies to the release process too:** a publish/propagate step must **verify the change actually landed** (installed version advanced; a sample project received the new file) and **HALT if it didn't** — never trust an install/copy that *reports* success. A package manager silently keeping the old version is itself a banned silent fallback.
493
+
494
+ **§Enforcement (three layers):** (1) this doctrine = the definition; (2) the **Architect's Oversight Write/Edit trigger is extended** to challenge every fallback at the build moment ("is this a fallback? name the proven case or ask"); (3) mechanical guards where they already exist — the graph consumers' `try→catch→grep` fallback is caught by `bin/gsd-t-graph-anti-grep-lint.cjs` (reused, not duplicated); a general static "detect every fallback" lint is deliberately NOT built (it can't judge *proven-necessary* — that is the human/architect ask, which is layer 2).
495
+
496
+ ### Simply Stated Doctrine (governed, enforced — clarity as a defect gate, not a writing-style reminder)
497
+
498
+ **Before GSD-T presents an architecture, plan, finding, review, or milestone definition, it must first state it *simply* — precise and complete, every word earning its place, the logic in a straight line, with no jargon standing in for a clear idea and no nested clauses hiding a tangle. If it cannot be stated simply, the thinking is NOT finished: the muddle in the words IS a muddle in the design. It goes back to be RE-THOUGHT, not re-worded.** The simply-stated version leads the deliverable; the technical depth sits below it for whoever wants it.
499
+
500
+ **This is a DIFFERENT mechanism from the Reader Contract / jargon lint.** Those treat verbosity as an OUTPUT-polish problem — trim the prose after the thinking is done — and repeatedly fail because a reminder loses to "but this case needs the detail" under load. Simply Stated treats verbosity as what it is: **a symptom of unclear thinking, and the same unclear thinking ships the bugs.** If you cannot express it cleanly, you do not yet understand it — and not-understanding is where defects come from. The inability to state it simply is a DEFECT SIGNAL, gated like the No-Fallback HALT, not a soft nudge.
501
+
502
+ **"Simply" is NOT "dumbed down."** The content stays as sophisticated as the problem demands — sophisticated IN its simplicity and conciseness (simplify the *expression*, never the *idea*). The test is NOT "could a novice understand the topic." The test is: **is every word load-bearing, and is the logic a straight line?** "This topic is too sophisticated to state simply" is the banned escape hatch.
503
+
504
+ **The HALT (the teeth):** a deliverable whose simply-stated lead cannot be written cleanly is NOT done — stop, surface it, re-think the muddled part. Do not ship the verbose version with an apology; the verbose version is evidence the design has a gap.
505
+
506
+ **§Enforcement (three layers):** (1) this doctrine = the definition; (2) the **Architect's Oversight Write/Edit trigger** carries a Simply-Stated line; (3) the **plan/milestone Six-Stage Pass + `/gsd-t-architect` gain a Simply-Stated gate** — the pass does not complete until its finding/plan has a clean simply-stated lead, and the validation protocols flag a deliverable that lacks one. The simply-stated lead is a REQUIRED ARTIFACT (like the pseudocode file), not advice.
507
+
459
508
  ### Phase Flow
460
509
  - Upon completing a phase, automatically proceed to the next phase
461
510
  - ONLY run Discussion phase if truly required (clear path → skip to Plan)
@@ -68,6 +68,46 @@ cp .env.example .env
68
68
  {command}
69
69
  ```
70
70
 
71
+ <!-- gsd-t-env-registry:start -->
72
+ ## Environments
73
+
74
+ > **Map, not secrets.** This table records only WHERE an environment lives and
75
+ > HOW to reach it — host/port/name/auth-method/which-vault-holds-the-secret/the
76
+ > env-var NAME/the fetch + connect commands. It NEVER stores a secret VALUE.
77
+ > The value lives in the vault (`.env` / Vercel / Neon / Google Secret Manager)
78
+ > and is pulled at runtime via the env-var NAME. A missing row → HALT and
79
+ > document (detect → ask → record → proceed); never guess a connection string,
80
+ > never grep transcripts to rediscover.
81
+
82
+ | id | scope | kind | host | port | db/name | auth method | secret vault | secret env-var NAME | fetch command | connect command | access gotchas | read-only default | recorded |
83
+ | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
84
+ <!-- gsd-t-env-registry:end -->
85
+
86
+ <!--
87
+ Column notes:
88
+ scope = local | staging | prod
89
+ kind = postgres | mysql | redis | http-api | ssh-host | ...
90
+ secret vault = local (.env) | Vercel | Neon | Google Secret Manager | ...
91
+ secret env-var NAME = e.g. DATABASE_URL_PROD — the NAME only, NEVER the value
92
+ host = POSITIVE shape: localhost | IPv4 | dotted DNS hostname |
93
+ short lowercase service name (letters+hyphen, no digits, e.g. db, postgres)
94
+ db/name = short lowercase snake identifier (<=16, e.g. binvoice_prod, analytics)
95
+ auth method = ENUMERATED — password | iam | oauth | oauth2 | service-account |
96
+ ssh-key | api-key | none | scram-sha-256 | md5 | trust | token | key | ...
97
+ fetch command = how to pull the secret from its vault (e.g. `vercel env pull`)
98
+ POSITIVE allowlist: a token is accepted ONLY if it IS a $VAR/${VAR} ref,
99
+ a flag, a hostname/IP, a .env dotfile, or a curated CLI/db word.
100
+ Any OTHER bare literal is REJECTED (move it to an env var, reference as $VAR).
101
+ connect command = references the env-var by name: `psql "$DATABASE_URL_PROD"` (same allowlist)
102
+ access gotchas = ENUMERATED — vpn | ip-allowlist | ssh-tunnel | bastion | none,
103
+ optionally `via <hostname>` (e.g. `ssh-tunnel via bastion.example.com`).
104
+ Free prose is FORBIDDEN (nowhere for a secret to hide).
105
+ read-only default = YES for scope=prod unless a human explicitly recorded write-ok
106
+ There is deliberately NO secret-value column — a row is structurally incapable
107
+ of holding a secret. Populated by `gsd-t-env-registry` (record-at-create +
108
+ capture-on-first-need).
109
+ -->
110
+
71
111
  ## Credentials & Secrets
72
112
 
73
113
  ### Local (.env)
@@ -928,6 +928,19 @@ const _architectPassLine = _ARCHITECT_PHASES.has(phaseName)
928
928
  ` if stability forbids touching it → build new BUT register a "reuse-candidate" graph link`,
929
929
  ` to the twin (never a silent rogue duplicate).`,
930
930
  ` 6. RISK — any security or stability/scalability risk? Am I sure?`,
931
+ ` 6b. NO-FALLBACK-EVER — does this plan add ANY fallback (anything that CONTINUES after a`,
932
+ ` failure: catch-and-continue, || default, silent degrade, try-X-else-Y where Y masks X`,
933
+ ` failing)? If yes: STOP and surface it as an OPEN QUESTION for the user — do NOT design`,
934
+ ` it in — UNLESS you can cite a confirmed reproducible case only a fallback catches. The`,
935
+ ` straight-line process that produces the result is the goal; where it can fail, prefer a`,
936
+ ` HALT (stop + demand fix), which is NOT a fallback. Fallbacks are rare and ask-first.`,
937
+ ` 7. SIMPLY-STATED (clarity gate — the plan is NOT done until this passes) — write the ${phaseName}`,
938
+ ` as a SIMPLY-STATED lead FIRST: precise and complete, but every word load-bearing, the logic`,
939
+ ` in a straight line, ZERO jargon standing in for a clear idea, no nested clauses hiding a`,
940
+ ` tangle. If you CANNOT state it simply, the thinking is not finished — the muddle in the`,
941
+ ` words is a muddle in the design; RE-THINK the muddled part, do not re-word it. "Too`,
942
+ ` sophisticated to simplify" is a BANNED escape hatch (simplify the expression, never the`,
943
+ ` idea). This simply-stated lead heads the deliverable; the depth sits below it.`,
931
944
  `A stage you cannot answer with evidence HALTS the plan (needs-human) — do not proceed on a hunch.`,
932
945
  ].join("\n")
933
946
  : "";