dflow-sdd-ddd 0.13.0 → 0.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.
Files changed (96) hide show
  1. package/CHANGELOG.md +824 -1
  2. package/CONTRIBUTING.md +16 -10
  3. package/README.en.md +156 -200
  4. package/README.md +89 -144
  5. package/TEMPLATE-COVERAGE.md +15 -8
  6. package/TEMPLATE-LANGUAGE-GLOSSARY.md +15 -1
  7. package/bin/dflow.js +36 -4
  8. package/docs/commands.en.md +110 -0
  9. package/docs/commands.md +101 -0
  10. package/docs/doctor-uncertainty.en.md +212 -0
  11. package/docs/doctor-uncertainty.md +212 -0
  12. package/docs/evaluating-dflow.en.md +29 -11
  13. package/docs/evaluating-dflow.md +8 -6
  14. package/docs/npm-publish-checklist.md +3 -1
  15. package/docs/release-versioning-policy.md +8 -2
  16. package/docs/upgrading.en.md +196 -0
  17. package/docs/upgrading.md +197 -0
  18. package/docs/using-with-claude-code.en.md +25 -10
  19. package/docs/using-with-claude-code.md +20 -7
  20. package/docs/using-with-codex.en.md +18 -6
  21. package/docs/using-with-codex.md +16 -5
  22. package/docs/using-with-github-copilot.en.md +25 -10
  23. package/docs/using-with-github-copilot.md +21 -8
  24. package/lib/doc-shapes.json +997 -0
  25. package/lib/doctor-checks.js +2654 -0
  26. package/lib/init.js +3583 -107
  27. package/lib/render-diagrams.js +1474 -0
  28. package/lib/render.js +865 -49
  29. package/package.json +2 -2
  30. package/templates/brownfield/references/drift-verification.md +4 -0
  31. package/templates/brownfield/references/finish-feature-flow.md +635 -88
  32. package/templates/brownfield/references/finish-feature-follow-up.md +60 -0
  33. package/templates/brownfield/references/finish-feature-minimal-host.md +406 -0
  34. package/templates/brownfield/references/finish-feature-post-hoc-hotfix.md +95 -0
  35. package/templates/brownfield/references/git-integration.md +160 -15
  36. package/templates/brownfield/references/init-project-flow.md +26 -4
  37. package/templates/brownfield/references/modify-existing-flow.md +412 -87
  38. package/templates/brownfield/references/modify-existing-follow-up.md +121 -0
  39. package/templates/brownfield/references/modify-existing-post-hoc-hotfix.md +82 -0
  40. package/templates/brownfield/references/new-feature-flow.md +61 -6
  41. package/templates/brownfield/references/new-phase-flow.md +57 -7
  42. package/templates/brownfield/references/pr-review-checklist.md +303 -10
  43. package/templates/brownfield/scaffolding/AI-AGENT-GUIDE.md +158 -34
  44. package/templates/brownfield/scaffolding/CLAUDE-md-snippet.md +1 -1
  45. package/templates/brownfield/scaffolding/Git-principles-gitflow.md +75 -6
  46. package/templates/brownfield/scaffolding/Git-principles-trunk.md +82 -8
  47. package/templates/brownfield/scaffolding/_conventions.md +50 -28
  48. package/templates/brownfield/scaffolding/_overview.md +1 -0
  49. package/templates/brownfield/templates/_index.md +151 -7
  50. package/templates/brownfield/templates/analysis.md +79 -0
  51. package/templates/brownfield/templates/behavior.md +1 -0
  52. package/templates/brownfield/templates/context-definition.md +1 -0
  53. package/templates/brownfield/templates/context-map.md +2 -1
  54. package/templates/brownfield/templates/glossary.md +1 -0
  55. package/templates/brownfield/templates/lightweight-spec.md +154 -11
  56. package/templates/brownfield/templates/models.md +1 -0
  57. package/templates/brownfield/templates/phase-spec.md +9 -1
  58. package/templates/brownfield/templates/rules.md +1 -0
  59. package/templates/brownfield/templates/tech-debt.md +1 -0
  60. package/templates/common/references/ddd-modeling-guide.md +33 -16
  61. package/templates/{greenfield → common}/references/dflow-feedback-flow.md +2 -1
  62. package/templates/common/references/flow-rationale-registry.md +130 -0
  63. package/templates/common/skill/SKILL.md +13 -11
  64. package/templates/greenfield/references/drift-verification.md +4 -0
  65. package/templates/greenfield/references/finish-feature-flow.md +625 -89
  66. package/templates/greenfield/references/finish-feature-follow-up.md +60 -0
  67. package/templates/greenfield/references/finish-feature-minimal-host.md +363 -0
  68. package/templates/greenfield/references/finish-feature-post-hoc-hotfix.md +95 -0
  69. package/templates/greenfield/references/git-integration.md +148 -15
  70. package/templates/greenfield/references/init-project-flow.md +28 -8
  71. package/templates/greenfield/references/modify-existing-flow.md +378 -85
  72. package/templates/greenfield/references/modify-existing-follow-up.md +103 -0
  73. package/templates/greenfield/references/modify-existing-post-hoc-hotfix.md +82 -0
  74. package/templates/greenfield/references/new-feature-flow.md +67 -4
  75. package/templates/greenfield/references/new-phase-flow.md +56 -7
  76. package/templates/greenfield/references/pr-review-checklist.md +287 -8
  77. package/templates/greenfield/scaffolding/AI-AGENT-GUIDE.md +153 -32
  78. package/templates/greenfield/scaffolding/CLAUDE-md-snippet.md +5 -2
  79. package/templates/greenfield/scaffolding/Git-principles-gitflow.md +74 -6
  80. package/templates/greenfield/scaffolding/Git-principles-trunk.md +88 -12
  81. package/templates/greenfield/scaffolding/_conventions.md +50 -28
  82. package/templates/greenfield/scaffolding/_overview.md +6 -2
  83. package/templates/greenfield/templates/_index.md +137 -7
  84. package/templates/greenfield/templates/aggregate-design.md +1 -0
  85. package/templates/greenfield/templates/analysis.md +79 -0
  86. package/templates/greenfield/templates/behavior.md +1 -0
  87. package/templates/greenfield/templates/context-definition.md +1 -0
  88. package/templates/greenfield/templates/context-map.md +2 -1
  89. package/templates/greenfield/templates/events.md +4 -1
  90. package/templates/greenfield/templates/glossary.md +1 -0
  91. package/templates/greenfield/templates/lightweight-spec.md +154 -11
  92. package/templates/greenfield/templates/models.md +1 -0
  93. package/templates/greenfield/templates/phase-spec.md +9 -1
  94. package/templates/greenfield/templates/rules.md +1 -0
  95. package/templates/greenfield/templates/tech-debt.md +1 -0
  96. package/templates/brownfield/references/dflow-feedback-flow.md +0 -251
@@ -0,0 +1,110 @@
1
+ # Dflow Command Reference
2
+
3
+ > [繁體中文](commands.md) | **English**
4
+
5
+ > **You do not need this page for normal use.** Describe what you want to do and the AI
6
+ > picks the workflow, stopping at each decision point to confirm with you — that is how
7
+ > Dflow is meant to be used, see
8
+ > [README "You don't need to learn the commands first"](../README.en.md#you-dont-need-to-learn-the-commands-first).
9
+ >
10
+ > This page is for three situations: you want to name a flow directly, the AI picked the
11
+ > wrong one and you want to correct it, or you are taking stock of what Dflow covers.
12
+
13
+ ## Command Inventory
14
+
15
+ Dflow commands fall into four roles.
16
+
17
+ ### Entry commands (start a workflow)
18
+
19
+ Start a workflow run; usable with no existing feature. The three are independent — none
20
+ is a prerequisite for another.
21
+
22
+ | Flow | When | Typical output |
23
+ |---|---|---|
24
+ | `/dflow:new-feature` | A brand-new capability, or a new business rule the system must implement | Feature directory + `_index.md` + first phase-spec (always T1) |
25
+ | `/dflow:modify-existing` | Changing existing behavior — use it when **you are not sure which category the change falls into**; the AI routes internally | T1 → escalate to new-phase / new-feature; T2 → lightweight-spec; T3 → one inline row in `_index.md` |
26
+ | `/dflow:bug-fix` | A defect you can state as expected vs actual behavior | The AI judges the tier (usually a T2 lightweight-spec). An orphan bug with no host feature opens a minimal (zero-phase) host: a **functional bug** goes to `bugfix/BUG-{NUMBER}-{slug}`, other standalone T2 / T3 work to `feature/{SPEC-ID}-{slug}` |
27
+
28
+ ⚠ `/dflow:bug-fix` and `/dflow:modify-existing` **run the same flow document**; the tier
29
+ comes from the ceremony cascade, not from which command you typed. Picking the wrong one
30
+ of these two has no consequence.
31
+
32
+ ### Feature-internal commands (active feature only)
33
+
34
+ Available only inside a started, active feature. Pointing them at a `completed/` feature
35
+ is rejected.
36
+
37
+ | Flow | When | Typical output |
38
+ |---|---|---|
39
+ | `/dflow:new-phase` | An active feature needs another implementation slice | A new `phase-spec-{date}-{slug}.md` + Implementation Tasks + implementation / verification + phase marked complete (always T1) |
40
+ | `/dflow:finish-feature` | Every phase is done and the feature is being closed out | `git mv` the whole feature dir to `completed/`, sync the BR Snapshot to the BC layer, emit an Integration Summary (no auto-merge) |
41
+
42
+ ### Workflow control (manage an in-progress run)
43
+
44
+ | Flow | When |
45
+ |---|---|
46
+ | `/dflow:status` | See which workflow / Step you are in and how far along |
47
+ | `/dflow:next` | Confirm a Step Gate (same as saying "OK" / "continue") |
48
+ | `/dflow:cancel` | Abandon the current run and return to free conversation. Artifacts already created are kept |
49
+
50
+ ### Standalone tools (callable any time, not tied to a feature or workflow)
51
+
52
+ | Flow | When | Typical output |
53
+ |---|---|---|
54
+ | `/dflow:verify` | You need to confirm docs, code, tests and debt records still agree | A drift report across specs, domain docs, implementation, tests and debt |
55
+ | `/dflow:pr-review` | A change is ready for review | An SDD/DDD compliance review list with risks, gaps and follow-ups |
56
+ | `/dflow:report-dflow-feedback` | You or the AI hit a problem in Dflow itself | A sanitized local draft, field-by-field aligned with the upstream issue form and ready to paste; nothing is sent automatically |
57
+
58
+ ## What should I run? (rule of thumb)
59
+
60
+ **If you are not sure, you do not have to choose** — say what you want, or just run
61
+ `/dflow:modify-existing` and let the AI route it. The table below is for when you want to
62
+ skip that and name the flow yourself.
63
+
64
+ | What I want to do | Command |
65
+ |---|---|
66
+ | A brand-new capability (unrelated to any existing feature) | `/dflow:new-feature` |
67
+ | Add the next planned phase to an active feature | `/dflow:new-phase` |
68
+ | Fix a specific bug | `/dflow:bug-fix` |
69
+ | **Not sure** how to classify it, but it changes something that exists | `/dflow:modify-existing` |
70
+ | Every phase of a feature is done and it needs closing out | `/dflow:finish-feature` |
71
+ | Run a change review | `/dflow:pr-review` |
72
+ | Check for doc / code drift | `/dflow:verify` |
73
+
74
+ ## How to type them in each AI tool
75
+
76
+ `/dflow:*` is Dflow's canonical shared vocabulary; each AI tool's `/` parser behaves
77
+ differently. Type them like this:
78
+
79
+ | Tool | How to invoke |
80
+ |---|---|
81
+ | Claude Code (after installing `--command-adapters`) | `/dflow:<id>`, e.g. `/dflow:new-feature` |
82
+ | GitHub Copilot (VS Code Chat) | Use `/dflow-<id>` as the command entry (hyphen, needs `--command-adapters`); natural-language auto-trigger also works. `/dflow:<id>` (colon) is only a way to refer to it in prose, not a command |
83
+ | GitHub Copilot CLI | No per-id commands; type `/dflow` to invoke the skill, then describe the workflow in natural language |
84
+ | Codex CLI | Plain text without a slash: `dflow:<id>`, e.g. `dflow:new-feature` |
85
+
86
+ If your tool has no custom slash commands, type the workflow name as an ordinary chat
87
+ message. Dflow is Markdown-based workflow material plus a scaffolding CLI, and works with
88
+ any AI coding assistant that can read project instructions and repository context.
89
+
90
+ **Command adapters are not required.** They are opt-in (`dflow configure-agents
91
+ --command-adapters`) and only turn these names into native `/` menu entries; natural
92
+ language triggering and plain-text invocation work without them.
93
+
94
+ ## CLI commands (run in a terminal, not said to the AI)
95
+
96
+ The `/dflow:*` names above are workflows for your AI assistant. These four are the
97
+ `dflow` CLI itself:
98
+
99
+ | Command | Purpose |
100
+ |---|---|
101
+ | `dflow init` | Initialize Dflow in a project: asks for the track, Git policy, AI commit marking, and which AI tools to configure |
102
+ | `dflow configure-agents` | Idempotent re-projection: add AI tools, refresh the workflow bundle; `--skills` regenerates skills, `--command-adapters` generates native `/` commands |
103
+ | `dflow doctor` | Read-only health check and drift detection |
104
+ | `dflow render` | Turn `dflow/specs/` into browsable static HTML for humans |
105
+
106
+ Each command’s full set of flags is in its own `--help` (for example `dflow render --help`).
107
+ When to reach for `init`, `configure-agents` and `render`, and the version-control advice, are
108
+ in [README "Get Started"](../README.en.md#get-started); what to do about what `doctor` reports
109
+ is in [Upgrading an Existing Dflow Project](upgrading.en.md) and
110
+ [When `dflow doctor` is not sure](doctor-uncertainty.en.md).
@@ -0,0 +1,101 @@
1
+ # Dflow 指令參考
2
+
3
+ > **繁體中文** | [English](commands.en.md)
4
+
5
+ > **一般使用不需要這一頁。** 你把想做的事講出來,AI 會判斷該走哪一條 workflow,並在每個
6
+ > 決策點停下來問你——這是 Dflow 的預設用法,見 [README「你不用先學指令」](../README.md#你不用先學指令)。
7
+ >
8
+ > 這一頁是給以下三種情況看的:你想直接指定某條 flow、AI 選錯了你要糾正它、
9
+ > 或你在盤點 Dflow 到底涵蓋哪些情境。
10
+
11
+ ## 指令一覽
12
+
13
+ Dflow 指令依角色分四類。
14
+
15
+ ### 入口指令(從這裡開始一個 workflow)
16
+
17
+ 啟動一次 workflow run;可在沒有任何既有 feature 的狀態下使用。三者彼此獨立、不互為前置。
18
+
19
+ | Flow | 何時用 | 典型產出 |
20
+ |---|---|---|
21
+ | `/dflow:new-feature` | 完全新功能、新增一條系統要實現的業務規則 | feature 目錄 + `_index.md` + 第 1 份 phase-spec(一律 T1) |
22
+ | `/dflow:modify-existing` | 改既有行為 — **不確定改動屬於哪類**時用,AI 內部會分流 | T1 → 升 new-phase / new-feature;T2 → lightweight-spec;T3 → `_index.md` inline 一行 |
23
+ | `/dflow:bug-fix` | 可清楚陳述預期行為的 defect | AI 判 tier(多為 T2 lightweight-spec)。無所屬 feature 的 orphan bug 會開一個 minimal(zero-phase)host:**功能性 bug** 走 `bugfix/BUG-{NUMBER}-{slug}`,其餘 standalone T2/T3 走 `feature/{SPEC-ID}-{slug}` |
24
+
25
+ ⚠ `/dflow:bug-fix` 與 `/dflow:modify-existing` **走的是同一份 flow 文件**;tier 由
26
+ ceremony cascade 判定,不是由你選了哪個指令決定。所以這兩個名字選錯不會有後果。
27
+
28
+ ### Feature 內指令(限 active feature)
29
+
30
+ 只在已啟動的 active feature 內可用。指向 `completed/` 的 feature 會被拒絕。
31
+
32
+ | Flow | 何時用 | 典型產出 |
33
+ |---|---|---|
34
+ | `/dflow:new-phase` | active feature 需要再一個實作切片 | 新一份 `phase-spec-{date}-{slug}.md` + Implementation Tasks + 程式實作 / 驗證 + phase 標記完成(一律 T1) |
35
+ | `/dflow:finish-feature` | feature 全部 phase 完成、要收尾 | `git mv` 整個 feature dir 到 `completed/`、sync BR Snapshot 到 BC 層、Integration Summary(不 auto-merge) |
36
+
37
+ ### 流程控制(管理進行中的 workflow run)
38
+
39
+ | Flow | 何時用 |
40
+ |---|---|
41
+ | `/dflow:status` | 看現在在哪個 workflow / Step / 進度 |
42
+ | `/dflow:next` | 確認過 Step Gate(等同自然語言「OK」/「繼續」) |
43
+ | `/dflow:cancel` | 放棄目前 workflow run、回到自由對話。已建立的 artifacts 保留 |
44
+
45
+ ### 獨立工具(任何時候可呼叫,不綁定 feature 或 workflow)
46
+
47
+ | Flow | 何時用 | 典型產出 |
48
+ |---|---|---|
49
+ | `/dflow:verify` | 需要確認文件、程式、測試、債務紀錄是否一致 | 跨規格、領域文件、實作、測試、債務的 drift report |
50
+ | `/dflow:pr-review` | 變更已準備接受審查 | SDD/DDD 合規 review 清單,含風險、缺口、後續項目 |
51
+ | `/dflow:report-dflow-feedback` | 你或 AI 在使用中發現 Dflow 本身的問題 | sanitized 的本地草稿,逐欄對齊上游 issue 表單可直接貼上;不自動送出 |
52
+
53
+ ## 該選哪個指令(rule of thumb)
54
+
55
+ **不確定就不用選** —— 把事情講出來,或直接下 `/dflow:modify-existing`,AI 會分流。
56
+ 下表是你想跳過那一步、直接指定時用的。
57
+
58
+ | 我要做的事 | 直接下指令 |
59
+ |---|---|
60
+ | 完全新功能(與現有 feature 無關) | `/dflow:new-feature` |
61
+ | 為 active feature 加規劃中的下一個 phase | `/dflow:new-phase` |
62
+ | 修一個明確的 bug | `/dflow:bug-fix` |
63
+ | **不確定**怎麼分類、反正是改既有的 | `/dflow:modify-existing` |
64
+ | feature 全部 phase 都完成、要收尾 | `/dflow:finish-feature` |
65
+ | 跑變更 review | `/dflow:pr-review` |
66
+ | 檢查文件與程式碼 drift | `/dflow:verify` |
67
+
68
+ ## 各 AI 工具怎麼輸入
69
+
70
+ `/dflow:*` 是 Dflow 的 canonical 共同詞彙;各 AI 工具的 `/` parser 行為不同。
71
+ 實際輸入方式如下:
72
+
73
+ | 工具 | 建議叫法 |
74
+ |---|---|
75
+ | Claude Code(安裝 `--command-adapters` 後) | `/dflow:<id>`,例如 `/dflow:new-feature` |
76
+ | GitHub Copilot(VS Code Chat) | 命令入口用 `/dflow-<id>`(連字號,需 `--command-adapters`);也可自然語言自動觸發。`/dflow:<id>`(冒號)僅當文字稱呼、非命令 |
77
+ | GitHub Copilot CLI | 沒有 per-id 命令;先打 `/dflow` 喚起 skill,再用自然語言描述 workflow |
78
+ | Codex CLI | 不帶斜線的純文字 `dflow:<id>`,例如 `dflow:new-feature` |
79
+
80
+ 若你的工具不支援自訂 slash command,把 workflow 名稱當成普通對話訊息輸入即可。Dflow 是
81
+ Markdown-based 的 workflow 材料加一個 scaffolding CLI,能與任何可讀專案指示與 repo
82
+ 上下文的 AI 程式設計助理一起運作。
83
+
84
+ **沒裝 command adapters 也能用。** adapters 是 opt-in 的(`dflow configure-agents
85
+ --command-adapters`),它只是把這些名字變成工具原生的 `/` 選單項;自然語言觸發與純文字
86
+ 輸入都不需要它。
87
+
88
+ ## CLI 指令(在終端機執行,不是對 AI 講)
89
+
90
+ 上面的 `/dflow:*` 是給 AI 助理的 workflow;下面四個是 `dflow` CLI 本身:
91
+
92
+ | 指令 | 用途 |
93
+ |---|---|
94
+ | `dflow init` | 在專案裡初始化 Dflow:問模式、Git policy、AI commit 標記、要設定哪些 AI 工具 |
95
+ | `dflow configure-agents` | 冪等地重新投影:加新的 AI 工具、刷新 workflow bundle;`--skills` 重生成 skill、`--command-adapters` 產生原生 `/` 命令 |
96
+ | `dflow doctor` | 唯讀健康檢查與漂移偵測 |
97
+ | `dflow render` | 把 `dflow/specs/` 轉成人類可讀的靜態 HTML |
98
+
99
+ 每個指令的完整旗標見它自己的 `--help`(例如 `dflow render --help`)。
100
+ `init`、`configure-agents`、`render` 的使用情境與版控建議見 [README「開始使用」](../README.md#開始使用);
101
+ `doctor` 報出來的東西怎麼處理,見[升級既有 Dflow 專案](upgrading.md)與[當 `dflow doctor` 說它沒有把握](doctor-uncertainty.md)。
@@ -0,0 +1,212 @@
1
+ # When `dflow doctor` says it is not sure
2
+
3
+ > [繁體中文](doctor-uncertainty.md) | **English**
4
+
5
+ > This page tracks the source `main` branch and can describe behavior still listed under `## Unreleased` in the changelog. `@latest` installs the latest **published** CLI; it does not guarantee that every `main`-branch feature below has been released:
6
+ >
7
+ > ```bash
8
+ > npm install -g dflow-sdd-ddd@latest
9
+ > ```
10
+ >
11
+ > Everything on this page is done by editing your own Markdown, so the repairs remain forward-compatible. If your `dflow doctor` never prints an `[uncertain]` line, your installed CLI may predate the feature. Use this page as forward guidance; the reports appear only in a published release whose changelog includes them.
12
+
13
+ ## What `uncertain` means
14
+
15
+ Most of this page is about one question `dflow doctor` answers about the two files whose content it makes claims about — `dflow/specs/shared/_conventions.md` and `dflow/specs/shared/AI-AGENT-GUIDE.md`: **are the rules and settings from the upstream template still in your file?** One id is about something else: the shape marker line in your spec docs (`unreadable-shape-marker`, below).
16
+
17
+ To answer it, doctor has to work out which section each line belongs to — which means reading Markdown block structure. Its reader is a deliberately small one, and there are shapes it is known to get wrong. Rather than guess, doctor now says so:
18
+
19
+ ```text
20
+ [uncertain] dflow/specs/shared/_conventions.md, line 42: an HTML comment begins part-way through a line (inline-html-comment)
21
+ ...
22
+ Ran, but cannot be trusted while this shape is present — their silence is NOT a pass, and anything they DO report may be an artefact of the shape: ...
23
+ ```
24
+
25
+ Three things follow from an `[uncertain]` line, and the second is the one people miss:
26
+
27
+ 1. **`All checks passed` is not printed.** A project in this state never gets the same verdict a clean one gets.
28
+ 2. **The named checks ran — but you cannot trust what they said, in either direction.** Doctor reports by exception, so a check that says nothing normally means "this is fine". For the checks listed in the finding, that silence means *nothing reliable was measured* — do not read it as a pass. The other direction holds too: a `warn` from one of those checks may be the shape confusing the reader rather than real drift.
29
+ 3. **The exit code is still `0`.** Uncertainty is not a build failure. Doctor has never used a non-zero exit for a finding, and this did not change that.
30
+
31
+ ## Why doctor doesn't just fix the shape instead
32
+
33
+ Some of these are fixable and some genuinely are not, and pretending otherwise is what this page exists to avoid:
34
+
35
+ - For some the fix is a rewrite of the reader itself, and rewrites of *this* reader have a measured record of introducing new defects while closing old ones.
36
+ - One would change what counts as a table, which would move an unrelated formatting check with it.
37
+ - And for at least one shape — the table-indent gap described at the end of this page, which is deliberately **not** reported — there is **no available arbiter** to implement against.
38
+
39
+ So the honest position is: **narrow the reader where that is safe, disclose what can be detected, and record the rest in the source.** Detecting *whether a shape is present* needs none of the block-boundary logic that could be wrong, which is why these warnings can be trusted even though the thing they warn about cannot.
40
+
41
+ ## The shapes
42
+
43
+ Each heading is the detector id doctor prints in brackets.
44
+
45
+ > This list is **not** exhaustive. It covers the shapes that are both known and detectable today. Markdown has more edge cases than any list, and a shape that is absent here is not thereby certified safe — it is either not yet known, or known and judged not worth warning about (see the last section).
46
+
47
+ ### `inline-html-comment`
48
+
49
+ **The shape.** An HTML comment that begins part-way through a line:
50
+
51
+ ```markdown
52
+ Selected Git policy: `gitflow` <!-- was trunk, revisit in Q3 -->
53
+ ```
54
+
55
+ **Why it cannot be read reliably.** Doctor classifies Markdown one line at a time. A comment that *starts* a line opens a block, and doctor correctly treats its contents as invisible. A comment that opens mid-line is not a block at all — it is an inline span — so its contents are counted as live document text.
56
+
57
+ **Which way it fails.** Silently. A rule you commented out mid-line still reads as present, so doctor reports your file as current when part of it has been switched off. This is the worst direction, which is why it is disclosed rather than left alone.
58
+
59
+ **How to rewrite it.** Move the comment to a line of its own **starting at column 0**, outside any list item or block quote. There it opens a real HTML block and its contents stop being read:
60
+
61
+ ```markdown
62
+ <!-- was trunk, revisit in Q3 -->
63
+ Selected Git policy: `gitflow`
64
+ ```
65
+
66
+ Deleting it works too.
67
+
68
+ > ⚠ **Indenting it under a list item is not enough**, and this is worth stating because it is the obvious way to follow the instruction above. A comment indented under `- item` stays *inside* the item, where Dflow still reads it — see the next shape. The column is what matters, not the fact of being alone on the line.
69
+
70
+ Note that a comment inside a code span — `` `<!-- like this -->` `` — is *rendered*, so a reader does see it; that is not this shape and doctor does not report it.
71
+
72
+ > ⚠ **If the cited comment is inside a `<textarea>`, leave that line unchanged** — including when it is reported under *this* id, which is what happens when the tag and the comment share a line. A `<textarea>` holds raw text, so moving the line out would hide text the reader already sees. But do **not** ignore the overall uncertainty result: doctor reports only the first occurrence of each shape in a file, so this harmless line can shadow a later, genuinely hidden comment with the same id. Inspect the rest of the cited file for other apparent comment openers before trusting the affected checks.
73
+
74
+ > ⚠ **Renderer scope:** a markerless continuation of list-owned raw HTML is calibrated to the renderer Dflow ships (`dflow render`, powered by Marked). Another Markdown renderer may expose an escaped apparent opener there; if you publish through a different renderer, inspect its output before applying the repair.
75
+
76
+ > ⚠ **If the comment is inside an HTML block** (`<details>`, `<div>`, `<pre>`, …), moving it to column 0 is not the whole repair — you are still inside the block. See `comment-inside-container` below for the per-tag rule.
77
+
78
+ ### `comment-inside-container`
79
+
80
+ **The shape.** An HTML comment on its own line, but inside a container. A list item and a block quote are the everyday cases:
81
+
82
+ ```markdown
83
+ - Ceremony scaling
84
+ <!-- Escalate-only, no de-escalation. -->
85
+ ```
86
+
87
+ An HTML block is one too, and it catches people out because the comment looks perfectly ordinary at column 0:
88
+
89
+ ```markdown
90
+ <details>
91
+ <!-- Selected Git policy: `trunk` -->
92
+ </details>
93
+ ```
94
+
95
+ **Why it cannot be read reliably.** Doctor does not parse the interior of a container as its own sequence of blocks, so a comment opened inside one never opens an HTML block as far as doctor is concerned. Its text stays in the pool of live document content. What makes something a container here is that behaviour, not its syntax — so treat the two examples above as illustrations rather than as the full set.
96
+
97
+ **Which way it fails.** Silently in `dflow render`. Its Marked renderer normally shows no comment text there; doctor reads the comment's contents as though you had written them as ordinary text. **This holds whether or not the comment is closed** — closing it changes nothing, because the problem is where it sits, not whether it ends. The `<details>` form is the more dangerous of the two, because a commented-out setting inside it can be *contradicted* by a visible line further down and doctor will still trust the hidden one.
98
+
99
+ > ⚠ **Renderer scope:** for a markerless continuation of list-owned raw HTML, the direction above is calibrated to `dflow render` (Marked). Some other Markdown renderers expose an escaped apparent opener instead. If you publish through another renderer, inspect that output before moving or deleting the comment.
100
+
101
+ **How to rewrite it.** Move the comment out of the enclosing container — or delete it. Leaving the container is the whole repair, and *how* you leave depends on which container you are in:
102
+
103
+ - **List item or block quote** — put the comment on a line of its own at column 0, with no list marker or `>` before it.
104
+ - **HTML block, most tags (`<details>`, `<div>`, …)** — a **blank line** is what ends the block; the closing tag does not. So put a blank line between the block and the comment, or move the comment above the block entirely.
105
+ - **`<pre>`** — the exception, and its rule is the opposite one: it ends at its own **closing tag**. Move the comment *below* `</pre>`. Adding a blank line inside the block does nothing, because a blank line does not end it.
106
+
107
+ ⚠ **If the comment sits inside more than one container, the outermost one is the one you have to leave.** A `<pre>` inside a list item, a `<details>` inside a block quote: apply only the inner rule and the comment is still in the list item or the quote, and doctor reports the same finding again. Work outwards until the comment is at column 0 with nothing enclosing it.
108
+
109
+ ⚠ The middle rule is the one that catches people: for `<details>` and friends, moving the comment below `</details>` with no blank line leaves it inside the block, and doctor will report the same finding again. It is the same blank-line rule described under `unclosed-html-block`. ⚠ And do not generalise it — apply it to `<pre>` and you will add a blank line, see the finding survive, and have no idea why.
110
+
111
+ #### `<textarea>` is not one of these shapes — and doctor sometimes reports it anyway
112
+
113
+ `<textarea>` looks like `<pre>` but behaves in the opposite way here. Its interior is **raw text**, so `<!-- like this -->` is displayed to the reader exactly as written. Nothing is hidden, so there is nothing to disclose — and **moving such a comment out would be the one edit that genuinely hides it.**
114
+
115
+ Doctor reports it anyway, deliberately. Suppressing it was tried three times and each attempt created a case where a *genuinely* hidden comment went unreported — the failure this whole check exists to prevent. Keeping the harmless line reported is safer than a clean verdict over a file doctor read wrong, so the exemption was removed rather than patched again.
116
+
117
+ > **If you get `comment-inside-container` and the cited comment is inside a `<textarea>`, leave that line unchanged, but keep the overall finding open.** Doctor reports only the first occurrence of this id in a file, so inspect the rest of the file for a later apparent comment opener before treating the affected checks as reliable.
118
+
119
+ #### A fenced example can still be reported
120
+
121
+ Doctor masks fenced code before looking for these shapes, so an example inside ```` ``` ```` normally does not fire. Its fence scanner reads raw document lines, though, and never strips a container prefix — so there are fences it does not recognise. The known ones:
122
+
123
+ - a fence opened **inside a block quote** (`> ` before the backticks);
124
+ - a fence whose **raw indent is four spaces or more**, which happens under an ordinary `- item` as soon as you indent the fence that far;
125
+ - a fence opened **on the list-marker line itself** (`` - ```md ``), whose raw line starts with `-`, so the un-indent repair below cannot reach it.
126
+
127
+ > ⚠ This list is **not** exhaustive. An earlier version said the scanner "misses exactly two shapes", and the very next review round found the third (`p084gate-x14`). The rule is that the fence's raw line does not start at column 0, or carries a container prefix — not a list you can check off.
128
+
129
+ A comment inside any of them is still reported, and there is a second consequence that is easy to miss: **the text inside an unmasked fence is read as ordinary section content.** If your example happens to quote a rule that has since been changed elsewhere in the file, doctor can read the example as the live rule and report the file as current. So an unmasked fence is not only noisy — it can also hide real drift.
130
+
131
+ They clear differently:
132
+
133
+ - **The indent case** — un-indent the fence to two or three spaces and the report stops. This is the one place where re-indenting helps, and it is the exception to the rule stated above.
134
+ - **The block quote case** — re-indenting does **not** help at any depth, because the line still starts with `>` and the fence scanner never sees the fence at all. Move the example out of the quote, or ignore the report.
135
+ - **The list-marker-line case** — un-indenting cannot help either, because the raw line begins with the marker. Move the fence to a line of its own below the marker, or ignore the report. ⚠ Do **not** follow the generic repair the CLI prints for this id here: moving or deleting the comment would remove example text your reader can see.
136
+
137
+ Re-indenting the **comment** inside the container never helps. ⚠ That is about the comment. Un-indenting a *fence* is a different edit and it does help — see the fenced-example note above, which is the one exception on this page.
138
+
139
+ ### `unclosed-html-block`
140
+
141
+ **The shape.** An HTML block opened at the start of a line that never closes — most often a `<!--` left behind mid-edit.
142
+
143
+ **Why it cannot be read reliably.** Everything from that line to the end of the file is inside the block, so it is not section content and cannot be assessed.
144
+
145
+ **Which way it fails.** Both ways at once, and this is the one worth reading twice. A `missing` or `is missing the rule` finding below the block may be caused by the block rather than by real drift — *and* a rule that genuinely has drifted below it can go unreported entirely, because the block hides the text the check would have read. Treat every result about content below that line as unknown, not as passing.
146
+
147
+ **How to rewrite it.** Close the block. For an HTML comment that means adding `-->`; other block types that carry an end condition (`<script>`, `<style>`, `<pre>`, `<textarea>`, `<?`, `<!DOCTYPE`, `<![CDATA[`) each have their own closing form.
148
+
149
+ Only blocks with an end condition can produce this finding at all. A tag like `<details>` opens a different kind of HTML block that ends at the next **blank line**, so it always "closes" and never reaches this report — if a `<details>` section is swallowing content, the shape you are looking for is the missing blank line, not a missing tag.
150
+
151
+ ### `html-block-type-7`
152
+
153
+ **The shape.** A complete tag whose name is not one of CommonMark's known block tag names, standing alone at the start of a block, directly above a `---` or `===` line:
154
+
155
+ ```markdown
156
+ <my-widget>
157
+ ---
158
+ ```
159
+
160
+ A **closing** tag counts as well — `</my-widget>` above the same underline is the same shape and is reported the same way. So does a self-closing one.
161
+
162
+ **Why it cannot be read reliably.** That construction is HTML block type 7. It is the only HTML block type that cannot interrupt a paragraph, and recognising it properly needs a real tag parser. Doctor does not implement it.
163
+
164
+ **Which way it fails.** Usually loudly: doctor ends the section earlier than a renderer does, so it reports drift that is not there — and a `stale` you cannot reproduce is its own problem, which is why it is named rather than left as a mystery. ⚠ But not *only* loudly, and this was stated too confidently for several rounds: ending the section early also drops the rest of it, so a retired rule sitting below the shape stops being seen and its finding disappears. Treat results about that section as unknown in **both** directions.
165
+
166
+ **How to rewrite it.** Put a blank line between the tag and the underline. If the tag is being *shown* rather than used, fence it as an example.
167
+
168
+ ### `unreadable-shape-marker`
169
+
170
+ **The shape.** A spec doc under `dflow/specs/` whose shape marker — the `<!-- dflow-shape: {track}/{template} {number} -->` line it takes from its template, with any text after the number optional (see [Shape markers](upgrading.en.md#shape-markers)) — doctor cannot read: the line where the marker belongs (the first line, or the one right after the frontmatter's closing `---`) is malformed (for example a number that is not a positive whole number, such as `0` or `01`); a line containing `dflow-shape:` sits anywhere else (quoted as an example, commented out, inside a list or a quote — all count; so does a marker under frontmatter that a byte-order mark at the start of the file hides, because `dflow render` does not see that frontmatter either); the doc has two or more lines containing `dflow-shape:`; or the line names a template this CLI does not ship (a typo, or a template only the other track has).
171
+
172
+ **Why it cannot be read reliably.** The marker is the only record of which template shape the doc was written against. With the line damaged, doctor does not guess: a guessed number could keep it silent about a doc that is behind, or have it report one that is not. Nor does doctor decide whether a marker line anywhere else is the live one: that would mean reading lists, quotes, comments and code blocks exactly as `dflow render` does, and it would rather say it cannot tell than report a doc it cannot read as passing.
173
+
174
+ **Which way it fails.** Only in silence, and only for the docs listed: doctor did not judge their shape, so saying nothing about it is not a pass. For a feature `_index.md` the same holds for the section-by-section comparison doctor otherwise runs on a dashboard without a marker. Every other check is unaffected.
175
+
176
+ **How to rewrite it.** Leave exactly one marker line in the doc, on the line where it belongs. A marker quoted as an example, or an old one commented out, counts too: reword it so it no longer contains `dflow-shape:`. If the doc was copied whole from the bundle's template copy and its first line is `<!-- dflow-generated: workflow-bundle -->`, delete that line and the blank line after it (doctor names this case). If the file starts with a byte-order mark (BOM) in front of its frontmatter, save it as UTF-8 without a BOM (doctor names this case too). If you know which template and number it had, write the line back with that number: the line in the installed template carries the current number, so copying it marks an older doc as current. If you are not sure of the number, remove the damaged lines and treat the doc as one without a marker — the one-time procedure in [Shape markers](upgrading.en.md#shape-markers) decides the number. ⚠ A doc in a zero-phase feature that has not closed out yet is listed apart: leave it alone until closeout, after which it moves to `features/completed/` and is no longer checked. A feature whose Phase Specs table is empty while its directory holds a phase spec is one doctor cannot place, and is listed apart too: leave it alone if it is a minimal host, and rewrite as above if it is not.
177
+
178
+ ## Shapes that are known and deliberately not reported
179
+
180
+ Disclosure has a cost of its own: a warning that fires on correct files teaches people to ignore all of them.
181
+
182
+ **A malformed table delimiter row** — one whose cell count differs from the header row above it — is in this section too, and its reason is different enough to be worth stating.
183
+
184
+ GFM requires the delimiter row to carry exactly as many cells as the header, and treats a mismatched pair as ordinary prose: it is **not a table at all**. Doctor does not enforce that rule, so the two can disagree about whether this is a table, and then about where the section ends. The shape genuinely does make doctor misread, in **both** directions — the section can run on past where you see it end, or be cut short so content below is never examined.
185
+
186
+ So why is it not reported? **Because it was, and it could not be made to work.** Across six consecutive review rounds, every round found a document the detector stayed silent on — and silence here is worse than saying nothing, because it prints `All checks passed` over a file that has drifted. Narrowing it to the shapes where a divergence had been measured failed five times; widening it back to every mismatch failed on the sixth, because the remaining list had simply moved into the code that recognises a delimiter row. One of those rounds also measured the same silent failure with a delimiter row whose cell count was **correct**, which means the detector's scope was only ever part of the problem.
187
+
188
+ The durable fix is a different instrument rather than a better list of shapes: `marked` — the renderer `dflow render` uses — is already a dependency of this package, so the section boundary can be taken **from** the renderer instead of guessed alongside it and compared shape by shape. That is a separate design change with its own evaluation. Until then this page says plainly that the check is not made, rather than shipping one that goes quiet on documents nobody thought to try.
189
+
190
+ If you are chasing a drift result that makes no sense and your file has a delimiter row whose cell count differs from its header, that is worth fixing first.
191
+
192
+ Another known gap — **an indented continuation line inside a table** — is left unreported for a different reason. A prototype detector for it produced five false reports across 151 real files, all of them triggered by ordinary indented code and examples. There is also no reference implementation available that can settle who is right about that shape: the two that could arbitrate disagree, and one of them has no notion of tables at all. For it, the warning really would be worse than the gap.
193
+
194
+ It is not the only unreported one. Others are recorded in the source (`lib/doctor-checks.js`, under "what this deliberately does not implement") rather than here, because they have no detectable shape to key a report to — the interior of a nested container not being parsed as its own sequence of blocks is the broadest of them, and the two comment shapes above are the specific cases of it that *could* be detected.
195
+
196
+ So if you are chasing a drift result that makes no sense and none of the shapes above are present in your file, the table-indent gap is **one** candidate worth checking — not the last one. The end of this page is not the end of the list.
197
+
198
+ **One more deliberate silence, of a different kind: command files and skill files that are not there at all.** Everything above is about a file doctor might *misread*. This one is not a misreading — it is a whole layer doctor does not look for.
199
+
200
+ `dflow doctor` does check `.claude/commands/dflow/`, `.github/prompts/dflow-*.prompt.md` and the three `SKILL.md` files, but it judges **only the ones already present**: a partial set is reported, a `0.5.0`-era filename left behind is reported, and a Dflow-generated `SKILL.md` that has fallen behind this version is reported. **When none of them exist at all, it says nothing.**
201
+
202
+ **The failure this leaves open.** A project never ran `dflow configure-agents --command-adapters` — or ran it once and the files were not regenerated after a clone — so not one `/dflow:*` command is available, and `dflow doctor` reports `All checks passed` throughout. This is not hypothetical: one real project went six releases with no `.claude/commands/dflow/` files at all, and doctor was silent the whole way.
203
+
204
+ **Why it is deliberately not defended.** Doctor cannot separate two kinds of adopter — "I never wanted those files" and "I had them and they are gone" — because the two states are identical on disk, and **both are legitimate**. Dflow never records which tools a project intends to use (the boundary `PROPOSAL-058` set, which `checkRootAgentShims` also follows), while `PROPOSAL-037` positively **recommends** that adopters gitignore these generated files and regenerate them after a clone — so "not one of them present" in a fresh clone is exactly what following that advice looks like. A detector for this was specified three times, and each time a path was found where it fired on an innocent project; one version reported on **every fresh `dflow init`**. The sentence this section opens with — a warning that fires on correct files teaches people to ignore all of them — is about precisely this.
205
+
206
+ **Who carries the residual risk.** The adopter. Doctor states the boundary at the end of every run and names who picks it up: the AI you run Dflow with. ⚠ **That is a delegation, not a guarantee** — nothing makes it happen, and nothing verifies afterwards that it did.
207
+
208
+ **What would make us reconsider.** If command adapters became installed by default, the "I never wanted them" adopter would no longer exist and the detection collapses into the simple question "is it there?". That is a separate product decision — it would overturn `PROPOSAL-074`'s explicit choice to keep adapters opt-in — and it has not been made. If it is, this entry gets revisited with it.
209
+
210
+ ## If none of this explains your result
211
+
212
+ Doctor is read-only; it never edits your files, so nothing here can have damaged anything. A drift report you cannot account for is worth reporting — include the `_conventions.md` section it points at, and the detector id if one was printed.