From 3a3b2135c2a7084feeb51dfa921e6dd3e333c737 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Sat, 20 Jun 2026 13:36:57 -0400 Subject: [PATCH] chore(#1073): purge phantom pre-migration issue refs from source, tests, docs (#1471) #2551/#3182/#2361 are pre-migration get-shit-done-redux issue numbers with no equivalent in open-gsd/gsd-core; they mislead triage and manufacture phantom blockers. Repoint to real successors (#717 byte-budget rework, #720) or rewrite as prose referencing the discuss-phase/modes progressive-disclosure split. Correct co-located 'line budget'/'<500 lines' framing to the byte-based reality (#717). Add a CI guard (tests/no-phantom-issue-refs.test.cjs) that fails if a phantom ref is reintroduced. SSH-key patterns (id_ed25519) left untouched. No user-facing runtime behavior change. Closes #1073 --- CONTRIBUTING.md | 2 +- docs/ARCHITECTURE.md | 4 +- docs/INVENTORY.md | 2 +- docs/TESTING-SUITES.md | 2 +- docs/ja-JP/ARCHITECTURE.md | 2 +- docs/ja-JP/INVENTORY.md | 2 +- docs/ko-KR/ARCHITECTURE.md | 4 +- docs/ko-KR/INVENTORY.md | 2 +- docs/pt-BR/ARCHITECTURE.md | 6 +- docs/pt-BR/INVENTORY.md | 2 +- docs/zh-CN/ARCHITECTURE.md | 4 +- docs/zh-CN/INVENTORY.md | 2 +- gsd-core/references/scout-codebase.md | 4 +- gsd-core/workflows/discuss-phase.md | 3 +- .../discuss-phase/templates/context.md | 2 +- tests/agent-frontmatter.test.cjs | 4 +- ...9-2550-2552-discuss-phase-context.test.cjs | 6 +- tests/chain-flag-plan-phase.test.cjs | 6 +- tests/discuss-checkpoint.test.cjs | 2 +- tests/discuss-phase-power.test.cjs | 4 +- tests/no-phantom-issue-refs.test.cjs | 58 +++++++++++++++++++ tests/thinking-partner.test.cjs | 2 +- tests/workflow-size-baseline.json | 2 +- tests/workflow-size-budget.test.cjs | 10 ++-- 24 files changed, 97 insertions(+), 40 deletions(-) create mode 100644 tests/no-phantom-issue-refs.test.cjs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2594adee7..6f4d0cdd7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -847,7 +847,7 @@ gsd-core/ pattern: workflows//modes/*.md + workflows//templates/*. Parent dispatches to mode files. See workflows/discuss-phase/ as - the canonical example (#2551). New modes for + the canonical example (the discuss-phase/modes split, #717). New modes for discuss-phase land in workflows/discuss-phase/modes/.md. Per-file sizes are pinned by a committed baseline diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index b224abd1a..c8cfa0a4e 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -148,7 +148,7 @@ Orchestration logic that commands reference. Contains the step-by-step process i Workflow files are loaded verbatim into Claude's context every time the corresponding `/gsd-*` command is invoked. The workflow size budget enforced by `tests/workflow-size-budget.test.cjs` keeps each file bounded, mirroring the -agent budget from #2361. The budget is measured in **bytes** (#717), not lines: +the agent size-budget convention. The budget is measured in **bytes** (#717), not lines: line count over-penalizes prose and under-catches token-dense tables and code blocks, whereas bytes are deterministic and match the unit our vendors bound on — Codex truncates instruction docs past 32,768 bytes (`project_doc_max_bytes`). @@ -180,7 +180,7 @@ that is still eagerly `@`-imported shrinks the measured file without shrinking loaded context, which games the proxy rather than serving the goal. `workflows/discuss-phase.md` is held to a stricter <30,000-byte ceiling per -issue #2551 (originally <500 lines; re-based to bytes for #717). When a workflow grows +the discuss-phase byte budget (#717; the discuss-phase/modes split keeps it ≈32000 bytes). When a workflow grows beyond its tier, extract per-mode bodies into `workflows//modes/.md`, templates into `workflows//templates/`, and shared knowledge into diff --git a/docs/INVENTORY.md b/docs/INVENTORY.md index ccfb97d5f..a81c459ec 100644 --- a/docs/INVENTORY.md +++ b/docs/INVENTORY.md @@ -307,7 +307,7 @@ Full roster at `gsd-core/references/*.md`. References are shared knowledge docum | `prohibition-probe.md` | Spec-phase prohibition-completeness probe — the two-stage adversarial-recall → precision protocol that surfaces the unwritten *must-NOT* constraints (values/safety/ethics), with status×verification (`test`/`judgment`) tiering and canon-referral breadcrumbs (Step 5.6); second adapter of the `probe-core` resolution model. | | `gate-prompts.md` | Gate/checkpoint prompt templates. | | `loop-hook-dispatch.md` | Generic dispatch contract for consuming `gsd_run loop render-hooks --raw` output in any host-loop workflow — envelope shape, per-kind dispatch rules (contribution/step/gate), and liveness banner. | -| `scout-codebase.md` | Phase-type→codebase-map selection table for discuss-phase scout step (extracted via #2551). | +| `scout-codebase.md` | Phase-type→codebase-map selection table for discuss-phase scout step (extracted via the discuss-phase/modes progressive-disclosure split, #717). | | `revision-loop.md` | Plan revision iteration patterns. | | `universal-anti-patterns.md` | Universal anti-patterns to detect and avoid. | | `worktree-branch-check.md` | Canonical spawn-time worktree HEAD/base guard (worktree_branch_check): verify-only and fail-closed — per-agent-branch assertion, protected-ref refusal (#2924), and an exact-base assertion that halts with `exit 42` on mismatch so the orchestrator (worktree lifecycle owner) performs recovery (#48). Embedded into worktree sub-agent prompts at dispatch. | diff --git a/docs/TESTING-SUITES.md b/docs/TESTING-SUITES.md index c026b61bc..6cd890305 100644 --- a/docs/TESTING-SUITES.md +++ b/docs/TESTING-SUITES.md @@ -82,7 +82,7 @@ from day-to-day to last-resort: | **New-file cap** | A workflow not yet in the baseline must stay under `32768` bytes (the Codex `project_doc_max_bytes` anchor) unless explicitly tiered into `XL_WORKFLOWS`/`LARGE_WORKFLOWS` in the same PR. Keeps net-new orchestrators from being born oversized. | `NEW_FILE_CAP` | `discuss-phase.md` additionally has a thin-dispatcher target of `< 32000` bytes -(issue [#2551](https://github.com/open-gsd/gsd-core/issues/2551)). +(the discuss-phase progressive-disclosure split, #717). **Agents** (`tests/agent-size-budget.test.cjs`) use the same per-agent baseline (`tests/agent-size-baseline.json`) + loose tier hard caps — `XL ≤ 57344` / diff --git a/docs/ja-JP/ARCHITECTURE.md b/docs/ja-JP/ARCHITECTURE.md index 236aace0f..18cfae29f 100644 --- a/docs/ja-JP/ARCHITECTURE.md +++ b/docs/ja-JP/ARCHITECTURE.md @@ -139,7 +139,7 @@ eager なスキルリストはターンごとの 2 つの主要コストの一 #### ワークフローのプログレッシブディスクロージャー -ワークフローファイルは、対応する `/gsd-*` コマンドが呼び出されるたびに Claude のコンテキストにそのまま読み込まれます。そのコストを制限するため、`tests/workflow-size-budget.test.cjs` で強制されるワークフローサイズバジェットは #2361 のエージェントバジェットを反映します: +ワークフローファイルは、対応する `/gsd-*` コマンドが呼び出されるたびに Claude のコンテキストにそのまま読み込まれます。そのコストを制限するため、`tests/workflow-size-budget.test.cjs` で強制されるワークフローサイズバジェットはエージェントサイズバジェット規則を反映します: | ティア | ファイルごとの行数制限 | |-----------|--------------------| diff --git a/docs/ja-JP/INVENTORY.md b/docs/ja-JP/INVENTORY.md index b5c953b79..a1d5a6a70 100644 --- a/docs/ja-JP/INVENTORY.md +++ b/docs/ja-JP/INVENTORY.md @@ -298,7 +298,7 @@ | `continuation-format.md` | セッション継続/再開フォーマット。 | | `domain-probes.md` | discuss-phase 向けのドメイン固有のプロービング質問。 | | `gate-prompts.md` | ゲート/チェックポイントのプロンプトテンプレート。 | -| `scout-codebase.md` | discuss-phase スカウトステップ向けのフェーズタイプ→コードベースマップ選択テーブル(#2551 で抽出)。 | +| `scout-codebase.md` | discuss-phase スカウトステップ向けのフェーズタイプ→コードベースマップ選択テーブル(discuss-phase/modes プログレッシブディスクロージャー分割により抽出、#717)。 | | `revision-loop.md` | プラン修正の反復パターン。 | | `universal-anti-patterns.md` | 検出して避けるべきユニバーサルアンチパターン。 | | `worktree-path-safety.md` | ワークツリーガードスイート: HEAD アサーション、cwd ドリフトセンチネル(ステップ 0a、#3097)、絶対パスガード(ステップ 0b、#3099)— `` 経由でエグゼキュータースポーンプロンプトに読み込まれる。 | diff --git a/docs/ko-KR/ARCHITECTURE.md b/docs/ko-KR/ARCHITECTURE.md index beca3a794..3c8481647 100644 --- a/docs/ko-KR/ARCHITECTURE.md +++ b/docs/ko-KR/ARCHITECTURE.md @@ -144,7 +144,7 @@ GSD Core는 사용자와 AI 코딩 에이전트(Claude Code, Gemini CLI, OpenCod #### 워크플로우를 위한 점진적 공개 -워크플로우 파일은 해당 `/gsd-*` 명령어가 호출될 때마다 Claude의 컨텍스트에 그대로 로드된다. 이 비용을 제한하기 위해 `tests/workflow-size-budget.test.cjs`가 시행하는 워크플로우 크기 예산은 #2361의 에이전트 예산을 반영한다: +워크플로우 파일은 해당 `/gsd-*` 명령어가 호출될 때마다 Claude의 컨텍스트에 그대로 로드된다. 이 비용을 제한하기 위해 `tests/workflow-size-budget.test.cjs`가 시행하는 워크플로우 크기 예산은 에이전트 크기 예산 관례를 반영한다: | 등급 | 파일당 줄 제한 | |-----------|--------------------| @@ -152,7 +152,7 @@ GSD Core는 사용자와 AI 코딩 에이전트(Claude Code, Gemini CLI, OpenCod | `LARGE` | 1500 — 다단계 플래너 및 대형 기능 워크플로우 | | `DEFAULT` | 1000 — 집중된 단일 목적 워크플로우 (목표 등급) | -`workflows/discuss-phase.md`는 이슈 #2551에 따라 더 엄격한 <500줄 상한을 유지한다. 워크플로우가 등급을 초과하면 모드별 본문은 `workflows//modes/.md`로, 템플릿은 `workflows//templates/`로, 공유 지식은 `get-shit-done/references/`로 추출한다. 부모 파일은 현재 호출에 필요한 모드 및 템플릿 파일만 읽는 얇은 디스패처가 된다. +`workflows/discuss-phase.md`는 discuss-phase 바이트 예산(#717; discuss-phase/modes 분할로 ≈32000 바이트 유지)에 따라 더 엄격한 상한을 유지한다. 워크플로우가 등급을 초과하면 모드별 본문은 `workflows//modes/.md`로, 템플릿은 `workflows//templates/`로, 공유 지식은 `get-shit-done/references/`로 추출한다. 부모 파일은 현재 호출에 필요한 모드 및 템플릿 파일만 읽는 얇은 디스패처가 된다. `workflows/discuss-phase/`가 이 패턴의 정규 예시이다 — 부모는 디스패치하고, modes/는 플래그별 동작(`power.md`, `all.md`, `auto.md`, `chain.md`, `text.md`, `batch.md`, `analyze.md`, `default.md`, `advisor.md`)을 담으며, templates/는 해당 출력 파일이 작성될 때만 읽히는 CONTEXT.md, DISCUSSION-LOG.md, checkpoint.json 스키마를 담는다. diff --git a/docs/ko-KR/INVENTORY.md b/docs/ko-KR/INVENTORY.md index 1e8aac327..a73860461 100644 --- a/docs/ko-KR/INVENTORY.md +++ b/docs/ko-KR/INVENTORY.md @@ -298,7 +298,7 @@ | `continuation-format.md` | 세션 연속/재개 포맷. | | `domain-probes.md` | discuss-phase를 위한 도메인별 탐색 질문. | | `gate-prompts.md` | 게이트/체크포인트 프롬프트 템플릿. | -| `scout-codebase.md` | discuss-phase 스카우트 단계를 위한 단계 유형→코드베이스 맵 선택 테이블(#2551로 추출). | +| `scout-codebase.md` | discuss-phase 스카우트 단계를 위한 단계 유형→코드베이스 맵 선택 테이블(discuss-phase/modes 프로그레시브 디스클로저 분할을 통해 추출, #717). | | `revision-loop.md` | 계획 수정 반복 패턴. | | `universal-anti-patterns.md` | 감지하고 피해야 할 보편적인 안티패턴. | | `worktree-path-safety.md` | 워크트리 가드 스위트: HEAD 어설션, cwd-드리프트 센티널(0a단계, #3097), 절대 경로 가드(0b단계, #3099) — ``를 통해 executor 스폰 프롬프트에 로드됨. | diff --git a/docs/pt-BR/ARCHITECTURE.md b/docs/pt-BR/ARCHITECTURE.md index 009ddf150..4b2f1cf3f 100644 --- a/docs/pt-BR/ARCHITECTURE.md +++ b/docs/pt-BR/ARCHITECTURE.md @@ -149,7 +149,7 @@ Lógica de orquestração que os comandos referenciam. Contém o processo passo Os arquivos de workflow são carregados verbatim no contexto do Claude cada vez que o comando `/gsd-*` correspondente é invocado. Para manter esse custo limitado, o orçamento de tamanho de workflow aplicado por `tests/workflow-size-budget.test.cjs` -espelha o orçamento de agentes de #2361: +espelha a convenção de orçamento de tamanho de agentes: | Tier | Limite de linhas por arquivo | |-----------|------------------------------| @@ -157,8 +157,8 @@ espelha o orçamento de agentes de #2361: | `LARGE` | 1500 — planejadores com múltiplas etapas e workflows de funcionalidades grandes | | `DEFAULT` | 1000 — workflows simples e de propósito único (o tier alvo) | -`workflows/discuss-phase.md` é mantido em um teto mais restrito de <500 linhas conforme -a issue #2551. Quando um workflow cresce além de seu tier, extraia os corpos por modo +`workflows/discuss-phase.md` é mantido em um teto mais restrito conforme +o orçamento de bytes do discuss-phase (#717; a divisão discuss-phase/modes mantém ≈32000 bytes). Quando um workflow cresce além de seu tier, extraia os corpos por modo em `workflows//modes/.md`, templates em `workflows//templates/`, e conhecimento compartilhado em `get-shit-done/references/`. O arquivo pai se torna um despachante leve que diff --git a/docs/pt-BR/INVENTORY.md b/docs/pt-BR/INVENTORY.md index ed9f9fe1d..c10cbe76e 100644 --- a/docs/pt-BR/INVENTORY.md +++ b/docs/pt-BR/INVENTORY.md @@ -298,7 +298,7 @@ Registro completo em `get-shit-done/references/*.md`. Referências são document | `continuation-format.md` | Formato de continuação/retomada de sessão. | | `domain-probes.md` | Perguntas de sondagem específicas de domínio para a discuss-phase. | | `gate-prompts.md` | Templates de prompt de portão/checkpoint. | -| `scout-codebase.md` | Tabela de seleção de tipo de fase → mapa de base de código para a etapa de scout da discuss-phase (extraída via #2551). | +| `scout-codebase.md` | Tabela de seleção de tipo de fase → mapa de base de código para a etapa de scout da discuss-phase (extraída via a divisão progressiva discuss-phase/modes, #717). | | `revision-loop.md` | Padrões de iteração de revisão de plano. | | `universal-anti-patterns.md` | Antipadrões universais a detectar e evitar. | | `worktree-path-safety.md` | Suite de guarda do worktree: asserção de HEAD, sentinela de drift de cwd (etapa 0a, #3097) e guarda de caminho absoluto (etapa 0b, #3099) — carregados nos prompts de spawn do executor via ``. | diff --git a/docs/zh-CN/ARCHITECTURE.md b/docs/zh-CN/ARCHITECTURE.md index 08bd971cd..5a92e72bb 100644 --- a/docs/zh-CN/ARCHITECTURE.md +++ b/docs/zh-CN/ARCHITECTURE.md @@ -144,7 +144,7 @@ GSD Core 是一个**元提示框架**,位于用户与 AI 编码 Agent(Claude #### 工作流的渐进式披露 -工作流文件在每次调用对应的 `/gsd-*` 命令时会被完整加载到 Claude 的上下文中。为控制该成本,`tests/workflow-size-budget.test.cjs` 强制执行的工作流大小预算与 #2361 中的 Agent 预算保持一致: +工作流文件在每次调用对应的 `/gsd-*` 命令时会被完整加载到 Claude 的上下文中。为控制该成本,`tests/workflow-size-budget.test.cjs` 强制执行的工作流大小预算与 Agent 大小预算惯例保持一致: | 层级 | 每文件行数限制 | |-----------|--------------------| @@ -152,7 +152,7 @@ GSD Core 是一个**元提示框架**,位于用户与 AI 编码 Agent(Claude | `LARGE` | 1500 — 多步骤规划器和大型功能工作流 | | `DEFAULT` | 1000 — 聚焦于单一目的的工作流(目标层级) | -根据 issue #2551,`workflows/discuss-phase.md` 须严格遵守 <500 行上限。当工作流超出其层级时,应将各模式的主体提取到 `workflows//modes/.md`,将模板提取到 `workflows//templates/`,将共享知识提取到 `get-shit-done/references/`。父文件成为轻量级调度器,仅读取当前调用所需的模式和模板文件。 +根据 discuss-phase 字节预算(#717;discuss-phase/modes 分割使其保持在 ≈32000 字节),`workflows/discuss-phase.md` 须严格遵守更严格的上限。当工作流超出其层级时,应将各模式的主体提取到 `workflows//modes/.md`,将模板提取到 `workflows//templates/`,将共享知识提取到 `get-shit-done/references/`。父文件成为轻量级调度器,仅读取当前调用所需的模式和模板文件。 `workflows/discuss-phase/` 是该模式的典型示例——父文件负责调度,`modes/` 存放各标志的行为(`power.md`、`all.md`、`auto.md`、`chain.md`、`text.md`、`batch.md`、`analyze.md`、`default.md`、`advisor.md`),`templates/` 存放 CONTEXT.md、DISCUSSION-LOG.md 以及仅在写入对应输出文件时才读取的 checkpoint.json schema。 diff --git a/docs/zh-CN/INVENTORY.md b/docs/zh-CN/INVENTORY.md index 4b6b01a4b..d6344bfba 100644 --- a/docs/zh-CN/INVENTORY.md +++ b/docs/zh-CN/INVENTORY.md @@ -298,7 +298,7 @@ | `continuation-format.md` | 会话续传/恢复格式。 | | `domain-probes.md` | discuss-phase 的领域特定探究问题。 | | `gate-prompts.md` | 关卡/检查点提示模板。 | -| `scout-codebase.md` | discuss-phase 侦察步骤的阶段类型→代码库映射选择表(通过 #2551 提取)。 | +| `scout-codebase.md` | discuss-phase 侦察步骤的阶段类型→代码库映射选择表(通过 discuss-phase/modes 渐进式披露分割提取,#717)。 | | `revision-loop.md` | 计划修订迭代模式。 | | `universal-anti-patterns.md` | 需要检测和避免的通用反模式。 | | `worktree-path-safety.md` | Worktree 守卫套件:HEAD 断言、cwd 漂移哨兵(步骤 0a,#3097)和绝对路径守卫(步骤 0b,#3099)— 通过 `` 加载到执行器生成提示中。 | diff --git a/gsd-core/references/scout-codebase.md b/gsd-core/references/scout-codebase.md index d01a386a2..ecfc2e643 100644 --- a/gsd-core/references/scout-codebase.md +++ b/gsd-core/references/scout-codebase.md @@ -1,8 +1,8 @@ # Codebase scout — map selection table > Lazy-loaded reference for the `scout_codebase` step in -> `workflows/discuss-phase.md` (extracted via #2551 progressive-disclosure -> refactor). Read this only when prior `.planning/codebase/*.md` maps exist +> `workflows/discuss-phase.md` (extracted via the discuss-phase/modes progressive-disclosure split, #717). +> Read this only when prior `.planning/codebase/*.md` maps exist > and the workflow needs to pick which 2–3 to load. ## Phase-type → recommended maps diff --git a/gsd-core/workflows/discuss-phase.md b/gsd-core/workflows/discuss-phase.md index 66eeeeaef..41e87272f 100644 --- a/gsd-core/workflows/discuss-phase.md +++ b/gsd-core/workflows/discuss-phase.md @@ -19,8 +19,7 @@ You are a thinking partner, not an interviewer. The user is the visionary — yo **Per-mode bodies, templates, and the advisor flow are lazy-loaded** to keep -this file under the 500-line workflow budget (#2551, mirrors #2361's agent -budget). Read only the files needed for the current invocation: +this file under the discuss-phase byte budget (32000 bytes, #717; mirrors the agent size-budget convention). Read only the files needed for the current invocation: | When | Read | |---|---| diff --git a/gsd-core/workflows/discuss-phase/templates/context.md b/gsd-core/workflows/discuss-phase/templates/context.md index 019b05aa9..28dc3e2e2 100644 --- a/gsd-core/workflows/discuss-phase/templates/context.md +++ b/gsd-core/workflows/discuss-phase/templates/context.md @@ -4,7 +4,7 @@ > `workflows/discuss-phase.md`, immediately before writing > `${phase_dir}/${padded_phase}-CONTEXT.md`. Do not put a reference to this > file in `` — that defeats the progressive-disclosure -> savings introduced by issue #2551. +> savings from the discuss-phase/modes split (#717). ## Variable substitutions diff --git a/tests/agent-frontmatter.test.cjs b/tests/agent-frontmatter.test.cjs index 9cfe0918f..56af97659 100644 --- a/tests/agent-frontmatter.test.cjs +++ b/tests/agent-frontmatter.test.cjs @@ -386,7 +386,7 @@ describe('VERIFY: data-flow trace, environment audit, and behavioral spot-checks describe('DISCUSS: discussion log generation', () => { test('discuss-phase workflow references DISCUSSION-LOG.md generation', () => { - // After #2551 progressive-disclosure refactor, the DISCUSSION-LOG.md template + // After the discuss-phase progressive-disclosure split (#717), the DISCUSSION-LOG.md template // body lives in workflows/discuss-phase/templates/discussion-log.md and is // read at the git_commit step. Both files together must satisfy the // documentation contract. @@ -402,7 +402,7 @@ describe('DISCUSS: discussion log generation', () => { ); assert.ok( content.includes('Audit trail only'), - 'discuss-phase (or its discussion-log template after #2551) must mark discussion log as audit-only' + 'discuss-phase (or its discussion-log template after the discuss-phase/modes split) must mark discussion log as audit-only' ); }); diff --git a/tests/bug-2549-2550-2552-discuss-phase-context.test.cjs b/tests/bug-2549-2550-2552-discuss-phase-context.test.cjs index bc09f8650..f3e9f855b 100644 --- a/tests/bug-2549-2550-2552-discuss-phase-context.test.cjs +++ b/tests/bug-2549-2550-2552-discuss-phase-context.test.cjs @@ -21,14 +21,14 @@ const path = require('node:path'); const DISCUSS_PHASE = path.join( __dirname, '..', 'gsd-core', 'workflows', 'discuss-phase.md', ); -// After #2551 progressive-disclosure refactor, the scout_codebase phase-type +// After the discuss-phase progressive-disclosure split (#717), the scout_codebase phase-type // table and split-reads warning live in references/scout-codebase.md. const SCOUT_REF = path.join( __dirname, '..', 'gsd-core', 'references', 'scout-codebase.md', ); function readDiscussContext() { - // Both files are required after #2551 — fail loudly if either is missing + // Both files are required after the discuss-phase/modes split — fail loudly if either is missing // rather than silently weakening the regression coverage. for (const p of [DISCUSS_PHASE, SCOUT_REF]) { assert.ok(fs.existsSync(p), `Required discuss-phase context source missing: ${p}`); @@ -42,7 +42,7 @@ describe('discuss-phase context fixes (#2549, #2550, #2552)', () => { assert.ok(fs.existsSync(DISCUSS_PHASE), 'discuss-phase.md must exist'); assert.ok( fs.existsSync(SCOUT_REF), - 'references/scout-codebase.md must exist after #2551 extraction', + 'references/scout-codebase.md must exist after the discuss-phase/modes progressive-disclosure split', ); src = readDiscussContext(); }); diff --git a/tests/chain-flag-plan-phase.test.cjs b/tests/chain-flag-plan-phase.test.cjs index 9f8f8d558..29c18798b 100644 --- a/tests/chain-flag-plan-phase.test.cjs +++ b/tests/chain-flag-plan-phase.test.cjs @@ -21,13 +21,13 @@ const path = require('path'); describe('plan-phase chain flag preservation (#1620)', () => { const planPath = path.join(__dirname, '..', 'gsd-core', 'workflows', 'plan-phase.md'); const discussPath = path.join(__dirname, '..', 'gsd-core', 'workflows', 'discuss-phase.md'); - // After #2551, discuss-phase chain logic moved to modes/chain.md. + // After the discuss-phase/modes split (#717), discuss-phase chain logic moved to modes/chain.md. const discussChainPath = path.join(__dirname, '..', 'gsd-core', 'workflows', 'discuss-phase', 'modes', 'chain.md'); const readDiscuss = () => { // Fail loudly if either source is missing — silent filtering would let a // regression that deletes modes/chain.md pass this whole suite. assert.ok(fs.existsSync(discussPath), `discuss-phase.md missing: ${discussPath}`); - assert.ok(fs.existsSync(discussChainPath), `discuss-phase/modes/chain.md missing after #2551 split: ${discussChainPath}`); + assert.ok(fs.existsSync(discussChainPath), `discuss-phase/modes/chain.md missing after discuss-phase/modes split: ${discussChainPath}`); return [discussPath, discussChainPath].map(p => fs.readFileSync(p, 'utf8')).join('\n'); }; @@ -61,7 +61,7 @@ describe('plan-phase chain flag preservation (#1620)', () => { ); assert.ok( discussContent.includes(guardPattern), - 'discuss-phase (or discuss-phase/modes/chain.md after #2551 split) should use the dual-flag guard pattern' + 'discuss-phase (or discuss-phase/modes/chain.md after the discuss-phase/modes split) should use the dual-flag guard pattern' ); }); diff --git a/tests/discuss-checkpoint.test.cjs b/tests/discuss-checkpoint.test.cjs index 0f271e7d3..2c90efc92 100644 --- a/tests/discuss-checkpoint.test.cjs +++ b/tests/discuss-checkpoint.test.cjs @@ -19,7 +19,7 @@ const path = require('path'); describe('discuss-phase incremental checkpoint saves (#1485)', () => { const workflowPath = path.join(__dirname, '..', 'gsd-core', 'workflows', 'discuss-phase.md'); - // After #2551 progressive-disclosure refactor, checkpoint logic lives in the + // After the discuss-phase progressive-disclosure split (#717), checkpoint logic lives in the // default mode file and the JSON schema lives in the templates directory. const defaultModePath = path.join(__dirname, '..', 'gsd-core', 'workflows', 'discuss-phase', 'modes', 'default.md'); const checkpointTplPath = path.join(__dirname, '..', 'gsd-core', 'workflows', 'discuss-phase', 'templates', 'checkpoint.json'); diff --git a/tests/discuss-phase-power.test.cjs b/tests/discuss-phase-power.test.cjs index d873cc12f..86c181ed1 100644 --- a/tests/discuss-phase-power.test.cjs +++ b/tests/discuss-phase-power.test.cjs @@ -42,7 +42,7 @@ describe('discuss-phase power user mode (#1513)', () => { describe('main workflow file (discuss-phase.md)', () => { test('has power_user_mode section or references discuss-phase-power.md', () => { - // After #2551, the power dispatch lives in discuss-phase/modes/power.md and + // After the discuss-phase/modes split (#717), the power dispatch lives in discuss-phase/modes/power.md and // the parent references it via the dispatch table. const parentContent = fs.readFileSync(workflowPath, 'utf8'); const powerModePath = path.join(__dirname, '..', 'gsd-core', 'workflows', 'discuss-phase', 'modes', 'power.md'); @@ -52,7 +52,7 @@ describe('discuss-phase power user mode (#1513)', () => { const hasReference = content.includes('discuss-phase-power'); assert.ok( hasPowerSection || hasReference, - 'discuss-phase.md (or modes/power.md after #2551) should have power_user_mode section or reference discuss-phase-power.md' + 'discuss-phase.md (or modes/power.md after the discuss-phase/modes split) should have power_user_mode section or reference discuss-phase-power.md' ); }); diff --git a/tests/no-phantom-issue-refs.test.cjs b/tests/no-phantom-issue-refs.test.cjs new file mode 100644 index 000000000..cc204a9a1 --- /dev/null +++ b/tests/no-phantom-issue-refs.test.cjs @@ -0,0 +1,58 @@ +// allow-test-rule: runtime-contract-is-the-product (see #1073) — this guard asserts the +// ABSENCE of phantom pre-migration issue references in repo text (docs, tests, +// workflows). The file *content* is the product surface here (#1073): dangling +// refs like #2551/#3182 that don't exist in open-gsd/gsd-core (highest real +// issue is in the low thousands of the redux repo, not here) mislead triage and +// manufacture phantom blockers. This test fails CI if such a ref is reintroduced. + +'use strict'; + +const { test } = require('node:test'); +const assert = require('node:assert'); +const fs = require('node:fs'); +const path = require('node:path'); + +const ROOT = path.resolve(__dirname, '..'); + +// Phantom pre-migration (get-shit-done-redux) issue numbers with NO equivalent +// in open-gsd/gsd-core. Matched only with a leading '#' or in an issues/ URL so +// SSH key patterns like `id_ed25519` (which contain the digits "2551") are NOT +// false-positives. +const PHANTOM = ['2551', '3182', '2361']; +const REF_RE = new RegExp( + '(?:#(?:' + PHANTOM.join('|') + ')\\b)|(?:issues/(?:' + PHANTOM.join('|') + ')\\b)', +); + +const SCAN_EXT = new Set(['.md', '.cjs', '.js', '.cts', '.ts']); +const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'coverage', '.changeset']); +// This guard file itself names the phantom numbers (by necessity); exclude it. +const SELF = path.relative(ROOT, __filename); + +function walk(dir, acc) { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + if (entry.isDirectory()) { + if (!SKIP_DIRS.has(entry.name)) walk(path.join(dir, entry.name), acc); + } else if (SCAN_EXT.has(path.extname(entry.name))) { + acc.push(path.join(dir, entry.name)); + } + } + return acc; +} + +test('no phantom pre-migration issue references remain in repo text (#1073)', () => { + const offenders = []; + for (const file of walk(ROOT, [])) { + const rel = path.relative(ROOT, file); + if (rel === SELF) continue; + const lines = fs.readFileSync(file, 'utf8').split(/\r?\n/); + lines.forEach((line, i) => { + if (REF_RE.test(line)) offenders.push(`${rel}:${i + 1}: ${line.trim().slice(0, 120)}`); + }); + } + assert.strictEqual( + offenders.length, + 0, + `Phantom issue refs (${PHANTOM.map((n) => '#' + n).join('/')}) found — repoint to a real ` + + `successor (#717/#720) or rewrite as prose (see #1073):\n` + offenders.join('\n'), + ); +}); diff --git a/tests/thinking-partner.test.cjs b/tests/thinking-partner.test.cjs index 4ce997736..ecef48358 100644 --- a/tests/thinking-partner.test.cjs +++ b/tests/thinking-partner.test.cjs @@ -93,7 +93,7 @@ describe('Thinking Partner Integration (#1726)', () => { }); // Workflow integration tests - // After #2551 progressive-disclosure refactor, the thinking-partner block + // After the discuss-phase progressive-disclosure split (#717), the thinking-partner block // moved into the per-mode files (default.md, advisor.md) since the prompt // is mode-specific (only fires inside discuss_areas, after a user answer). describe('Discuss-phase integration', () => { diff --git a/tests/workflow-size-baseline.json b/tests/workflow-size-baseline.json index 5f50cf975..9429ef735 100644 --- a/tests/workflow-size-baseline.json +++ b/tests/workflow-size-baseline.json @@ -19,7 +19,7 @@ "discovery-phase.md": 8651, "discuss-phase-assumptions.md": 26984, "discuss-phase-power.md": 11273, - "discuss-phase.md": 31965, + "discuss-phase.md": 31990, "do.md": 10068, "docs-update.md": 55662, "edit-phase.md": 12883, diff --git a/tests/workflow-size-budget.test.cjs b/tests/workflow-size-budget.test.cjs index ce2de9e68..46a80f75e 100644 --- a/tests/workflow-size-budget.test.cjs +++ b/tests/workflow-size-budget.test.cjs @@ -102,7 +102,7 @@ const DEFAULT_CAP = 40960; // 40 KiB const NEW_FILE_CAP = 32768; // 32 KiB // Top-level orchestrators that own end-to-end multi-phase rubrics. -// Grandfathered at current sizes — see PR #2551 for the progressive-disclosure +// Grandfathered at current sizes — see the discuss-phase/modes split (#717) for the progressive-disclosure // pattern that future shrinks should follow. Byte counts noted for reference. const XL_WORKFLOWS = new Set([ 'execute-phase', // 92880 bytes (grew in #381 CLAUDE_ENV_FILE persist clause) @@ -210,8 +210,8 @@ describe('SIZE: per-file workflow baseline (issue #1074)', () => { }); }); -describe('SIZE: discuss-phase progressive disclosure (issue #2551)', () => { - // Issue #2551 targets discuss-phase.md as a thin dispatcher, separate from +describe('SIZE: discuss-phase progressive disclosure (#717 byte budget)', () => { + // The discuss-phase progressive-disclosure split (#717) targets discuss-phase.md as a thin dispatcher, separate from // the per-tier grandfathered budgets above. Originally expressed as <500 // lines; re-based to bytes for #717 (500 lines ≈ 28 KB at these files' // density; set to 30 KB to preserve the thin-dispatcher intent with modest @@ -221,12 +221,12 @@ describe('SIZE: discuss-phase progressive disclosure (issue #2551)', () => { // Target raised from 30000 to 32000 in #891 (launcher shim expansion added 17 runtime home arms, // adding ~960 bytes to the preamble; the thin-dispatcher intent is preserved — actual=30935). const DISCUSS_PHASE_TARGET = 32000; - test(`discuss-phase.md is under ${DISCUSS_PHASE_TARGET} bytes (issue #2551 target)`, () => { + test(`discuss-phase.md is under ${DISCUSS_PHASE_TARGET} bytes (#717 byte budget)`, () => { const filePath = path.join(WORKFLOWS_DIR, 'discuss-phase.md'); const bytes = byteCount(filePath); assert.ok( bytes < DISCUSS_PHASE_TARGET, - `discuss-phase.md is ${bytes} bytes — must be under ${DISCUSS_PHASE_TARGET} per #2551. ` + + `discuss-phase.md is ${bytes} bytes — must be under ${DISCUSS_PHASE_TARGET} per #717. ` + `Per-mode logic belongs in workflows/discuss-phase/modes/.md, ` + `templates in workflows/discuss-phase/templates/.` );