chart-map
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesechart-map
绘制决策映射图
Chart the way; don't charge at the goal. The output is a Decision map — one
item indexing the whole effort — plus child Decision tickets: questions whose
resolution is a decision, each sized to one session.
Plan, don't do. Charting creates the map and hand-resolves nothing (ADR
0041). One charting run is one session, and it ends at Step 5.
Emit this diagram once, at the start, so the user can see the whole run:
CHART A DECISION MAP — one session, then stop
─────────────────────────────────────────────
① PREFLIGHT — ask which backend
│ local docs/decision-map/<slug>/
│ or GitHub issues + sub-issues
│ name it BEFORE any charting
▼
② DESTINATION (HITL — the human answers)
│ what does arriving look like?
│ one or two sentences, one line, first
▼
③ FRONTIER — breadth-first, never deep
│ HITL too: you ask, the human answers
│ can you STATE the question now?
│ yes → ticket · no → fog
│ past the destination → out of scope
│
│ no fog anywhere? ■ STOP — no map
│ needed; hand to grill-then-plan
▼
④ GATE — dry run first, always
│ create · skip (exists) · merge
│ show every label → get a yes → --real
▼
⑤ RESEARCH subagents, in parallel
│ findings posted back with `resolve`
▼
⑥ LINT — run the check, report it
│ exit 0 clean · exit 3 findings
▼
■ STOP — report the `frontier`, hand off
charting hand-resolves nothing规划路径,而非直奔目标。输出内容为决策映射图——一个索引整个任务的条目——加上子级决策事项:需通过决策解决的问题,每个事项的规模适配单个会话。
仅规划,不执行。绘制映射图仅创建映射本身,不手动解决任何问题(ADR 0041)。一次绘制流程对应一个会话,在步骤5结束。
在流程开始时先输出以下流程图,方便用户查看完整流程:
CHART A DECISION MAP — one session, then stop
─────────────────────────────────────────────
① PREFLIGHT — ask which backend
│ local docs/decision-map/<slug>/
│ or GitHub issues + sub-issues
│ name it BEFORE any charting
▼
② DESTINATION (HITL — the human answers)
│ what does arriving look like?
│ one or two sentences, one line, first
▼
③ FRONTIER — breadth-first, never deep
│ HITL too: you ask, the human answers
│ can you STATE the question now?
│ yes → ticket · no → fog
│ past the destination → out of scope
│
│ no fog anywhere? ■ STOP — no map
│ needed; hand to grill-then-plan
▼
④ GATE — dry run first, always
│ create · skip (exists) · merge
│ show every label → get a yes → --real
▼
⑤ RESEARCH subagents, in parallel
│ findings posted back with `resolve`
▼
⑥ LINT — run the check, report it
│ exit 0 clean · exit 3 findings
▼
■ STOP — report the `frontier`, hand off
charting hand-resolves nothingStep 0 — Preflight: name the backend before you chart
步骤0 — 预检查:绘制前确定后端存储方式
Two backends exist. Ask which one, before anything else happens — even if
the user never mentioned a tracker. Someone who expected their map on a shared
board needs to learn where it lands here, not after spending a session
charting.
| backend | where the map lives | how it is shared | needs |
|---|---|---|---|
| local markdown (default) | | by committing the repo | nothing |
| GitHub Issues | an issue per map, a sub-issue per ticket, native | the repo's issue tracker — visible to anyone with access | |
Default to local and say so; only use GitHub if the user asks for a board or
names a repo. Azure DevOps is not available (ADR 0059 — its half of the
marker probe has never been run). If ADO specifically is a hard requirement,
stop and say decision-map cannot do that yet.
Do not offer to install or in either case —
neither plugin can drive a decision map, so offering them would be a false
promise. in particular is a findings-to-issues pipeline, not
a decision map; the two write different things to the same tracker.
ado-backloggithub-backloggithub-backlogThen fix these two, and use them for every command from Step 1 down:
| local | GitHub | |
|---|---|---|
| | |
| extra flag on every call | none — | |
Run with , from the repo root, so a local map lands at its
ADR-0042 default location. Everything from Step 1 down is backend-neutral — the
subcommands, the flags, the JSON shapes and the gate are identical on both
(ADR 0062); only and that one flag change.
<ops>python<ops>On GitHub, two limits are hard and worth knowing before you grill breadth-first:
a map cannot exceed 100 tickets (GitHub's sub-issue ceiling) and a ticket
cannot be blocked by more than 50 others. checks both before it
writes anything rather than failing partway.
chartContract — every subcommand, flag and JSON shape used below is fixed by
. Where this skill and the
contract disagree, the contract wins.
${CLAUDE_PLUGIN_ROOT}/references/data-contracts.mdThe map is repo docs, so it is committed through assisted git — offer the
commit, never make it automatically.
有两种后端存储方式。在开始任何操作前先询问用户选择哪一种——即使用户从未提及跟踪工具。预期在共享看板查看映射图的用户需要在此处了解存储位置,而非在花费一个会话绘制后才知晓。
| backend | 映射图存储位置 | 共享方式 | 所需条件 |
|---|---|---|---|
| 本地markdown(默认) | 当前仓库的 | 通过提交仓库代码共享 | 无额外要求 |
| GitHub Issues | 每个映射图对应一个Issue,每个事项对应一个子Issue,使用原生 | 仓库的Issue跟踪系统——所有有权限的用户均可查看 | 需要 |
默认使用本地存储并告知用户;仅当用户要求使用看板或指定仓库时才使用GitHub。暂不支持Azure DevOps(ADR 0059——相关探测从未执行)。如果用户明确要求使用ADO,需停止操作并告知当前决策映射图功能暂不支持该平台。
无论哪种情况,都不要主动提供安装或插件——这两个插件均无法驱动决策映射图,提供它们属于虚假承诺。特别是是一个“调研结果转Issue”的流水线,而非决策映射图工具;二者虽使用同一跟踪系统,但写入的内容完全不同。
ado-backloggithub-backloggithub-backlog确定后端后,固定以下两个配置,并在步骤1及之后的所有命令中使用:
| 本地 | GitHub | |
|---|---|---|
| | |
| 每次调用的额外参数 | 无—— | |
从仓库根目录使用运行,确保本地映射图存储在ADR-0042指定的默认位置。步骤1及之后的所有操作均与后端无关——子命令、参数、JSON结构和闸门逻辑在两种后端下完全一致(ADR 0062);仅和上述单个参数会变化。
python<ops><ops>在GitHub平台上,有两个硬性限制需要在广度优先调研前了解清楚:一个映射图最多包含100个事项(GitHub子Issue上限),一个事项最多被50个其他事项阻塞。命令会在写入任何内容前检查这两个限制,避免中途失败。
chart约定——以下使用的所有子命令、参数和JSON结构均由定义。若本技能与该约定存在冲突,以约定为准。
${CLAUDE_PLUGIN_ROOT}/references/data-contracts.md映射图属于仓库文档,因此需通过辅助git提交——仅向用户提交请求,切勿自动提交。
Step 1 — Name the destination
步骤1 — 确定目标终点
Run a short grilling exchange (load the way your harness loads
skills, if it is available; otherwise ask directly, one question at a time):
what does reaching the end look like? A written spec, a locked decision, a
change made in place?
sp-grill-with-docOne or two sentences. The destination is what every ticket is measured against,
and what makes "out of scope" decidable. Write it down before any ticket exists.
It is stored as a single line — the tool collapses any line break to a
space, in and alike, so that a stray newline can
never truncate the value or inject a heading into the map document. Write it as prose,
not as a bulleted list or a paragraph break. ( is different: it is a
list region now, one bullet per entry, and each bullet is flattened the
same way — ADR 0101.)
titledestinationnotes进行简短的调研交互(如果可用,按照你的工具加载技能的方式加载;否则直接逐个提问):**达成最终目标的状态是什么样的?**是一份书面规范、一个确定的决策、还是一项已完成的变更?
sp-grill-with-doc用一到两句话描述。目标终点是衡量每个事项的基准,也是判断“超出范围”的依据。在创建任何事项前先记录下来。
目标终点需存储为单行文本——工具会将和中的所有换行符转换为空格,避免意外换行截断内容或在映射文档中插入标题。请以散文形式书写,不要使用项目符号列表或分段。(字段不同:它现在是一个列表区域,每个条目对应一个项目符号,且每个项目符号会以相同方式扁平化处理——ADR 0101。)
titledestinationnotesThe HITL guard — it governs this step and Step 2 both
HITL防护规则——适用于本步骤和步骤2
Naming the destination is itself a HITL grilling exchange, and so is the
breadth-first grill that follows. An agent that answers its own grilling
questions has broken the type. A map charted that way is fiction: every
ticket on it is measured against a destination the human never actually agreed
to, and the whole effort then runs off it.
The line is who supplies the answer, not who does the work:
- Explore for yourself the factual questions — what the code does today, which services exist, what the repo has already decided. Reading is not asking, and the more you find out, the sharper your questions get.
- Ask the human every preference, trade-off, scope and destination question. One at a time.
- Never pose a question and answer it in the same breath. Your own recommended answer is a recommendation, never an accepted answer: offer it, then wait for the human to accept, reject or reshape it. Silence is not acceptance, and neither is a plausible-sounding default.
If the human is not available to answer, stop and say so rather than charting
alone.
确定目标终点本身就是一次HITL调研交互,后续的广度优先调研也是如此。自行回答调研问题的Agent属于异常状态。以此方式绘制的映射图是虚构的:每个事项都基于人类从未真正认可的目标终点,整个任务会因此偏离方向。
核心界限在于谁提供答案,而非谁执行工作:
- 自行探索事实类问题——当前代码的功能、现有服务、仓库已做出的决策。查阅资料不属于提问,你了解的信息越多,提出的问题就越精准。
- 向人类询问所有偏好、权衡、范围和目标终点相关的问题。逐个提问。
- 切勿在提问的同时自行回答。你给出的建议仅为推荐,绝非已接受的答案:提出建议后,等待人类接受、拒绝或调整。沉默不代表接受,看似合理的默认值也不代表接受。
如果人类无法提供答案,请停止操作并告知用户,切勿单独绘制映射图。
Step 2 — Map the frontier, breadth-first
步骤2 — 广度优先绘制前沿范围
Grill again, this time breadth-first: fan out across the whole space, never deep
on one thread. Depth is what the individual sessions are for.
The HITL guard above applies here too. The classification below is yours to
make — but the answers that feed it come from the human, not from you.
For each area, apply one test — can you state the question precisely, right
now? Not answer it. State it.
| Verdict | When | What you record |
|---|---|---|
| Ticket | you can state the question precisely now, even if it is blocked | a typed ticket (below) |
| Fog | you cannot phrase it sharply yet | one line under "Not yet specified" |
| Out of scope | it lies past the destination | one line under "Out of scope" |
Do not pre-slice fog into ticket-sized pieces. Fog that is left as fog graduates
into real tickets later, once an earlier decision has sharpened it.
再次进行调研,本次采用广度优先方式:全面覆盖整个任务空间,切勿深入单个分支。深入分支是单个会话的工作内容。
上述HITL防护规则同样适用于本步骤。以下的分类由你完成——但分类依据的答案必须来自人类,而非你自己。
针对每个领域,应用一项测试——**你现在能否精准表述问题?**不是回答问题,而是表述问题。
| 判断结果 | 适用场景 | 记录内容 |
|---|---|---|
| 事项 | 你现在可以精准表述问题,即使该问题存在阻塞 | 一个带类型的事项(见下文) |
| 模糊需求 | 你无法清晰表述问题 | 在“尚未明确”下记录一行内容 |
| 超出范围 | 内容超出目标终点 | 在“超出范围”下记录一行内容 |
不要预先将模糊需求拆分为事项大小的片段。模糊需求会在后续逐步转化为真实事项,通常是在前期决策使其清晰之后。
Ask what ships first (ADR 0100)
询问优先交付内容(ADR 0100)
Once every ticket on this pass is named, ask one more question — in the
user's own terms, not the tool's: "what do you want to be able to demo
first?", not "how do you want to group these tickets?". One question, and
it is skippable — say plainly that skipping it costs nothing, because the
grouping can be declared later from once the map exists to group.
Keep it short: at most two options, and lead with your own recommendation
before asking — the framing every HITL question in these two skills should
use, and the one the HITL guard above already requires (a recommendation is
offered, never accepted on the human's behalf).
work-mapThe answer becomes the map's first milestone in Step 3's input — which
ticket keys ship in that first increment. Everything else stays unassigned
until a later session groups it; that is a legal, unfinished state, not a gap
to fill now.
Type every ticket — the type picks its resolver and its mode (ADR 0038):
| Type | Mode | Resolved by |
|---|---|---|
| AFK | a research subagent, fired at chart time (Step 4) |
| HITL | a cheap artifact the user reacts to |
| HITL | a live grilling exchange — the default |
| either | doing the thing that unblocks a decision |
If this step surfaces no fog at all, stop. The way is already clear and the
whole journey fits one session, so a map would be overhead. Say that plainly and
point the user at instead.
grill-then-plan在本次调研确定所有事项后,再问一个问题——使用用户熟悉的表述,而非工具术语:“你希望首先能演示什么内容?”,而非“你希望如何分组这些事项?”。这是一个可选问题——明确告知用户跳过此问题没有任何影响,因为映射图创建完成后,可通过在后续会话中进行分组。保持问题简短:最多提供两个选项,先给出你的建议再提问——这是这两个技能中所有HITL问题应采用的框架,也是上述HITL防护规则的要求(仅提供建议,绝不能代表人类接受)。
work-map该问题的答案会成为步骤3输入中的第一个里程碑——即哪些事项键属于第一个交付增量。其他事项保持未分配状态,直到后续会话进行分组;这是合法的未完成状态,并非需要立即填补的空白。
为每个事项指定类型——类型决定了其解决者和模式(ADR 0038):
| 类型 | 模式 | 解决者 |
|---|---|---|
| AFK | 研究子Agent,在绘制阶段启动(步骤4) |
| HITL | 用户可反馈的低成本成果 |
| HITL | 实时调研交互——默认类型 |
| 任意 | 执行解除决策阻塞的具体工作 |
如果本步骤未发现任何模糊需求,请停止操作。路径已清晰,整个任务可在单个会话内完成,创建映射图属于额外开销。明确告知用户并引导其使用。
grill-then-planStep 3 — Create the map (gated)
步骤3 — 创建映射图(闸门管控)
Build a in a scratch working directory. These JSON files are
working files, never a store — the map itself is the source of truth.
map_input.jsonjson
{
"target": { "slug": "billing-migration" },
"map": {
"title": "Decision map - migrate billing to the new provider",
"destination": "<the destination from Step 1, as one line>",
"notes": ["<a skill every session should consult>", "<a standing preference>"],
"notYetSpecified": ["<fog line>"],
"outOfScope": ["<ruled-out line>"],
"milestones": [
{ "slug": "mvp", "label": "demo the search page",
"members": ["provider-choice"] }
]
},
"tickets": [
{ "key": "provider-choice", "title": "Provider - which one do we commit to?",
"type": "grilling", "question": "<the decision this resolves>",
"blocks": ["cutover-order"] },
{ "key": "cutover-order", "title": "Cutover order - big bang or per-tenant ramp?",
"type": "grilling", "question": "<the decision this resolves>" }
]
}- and every ticket
slugare lowercase-kebab, must matchkey, and must not contain[A-Za-z0-9][A-Za-z0-9_-]*.-- - is optional; each entry is
milestones, in the order you want them to ship — order is the list's own order, not the tickets' key order. A milestone{slug, label, members}follows the same rule as a ticketslug(nokey). A ticket belongs to at most one milestone, and a ticket in none is legal: it means "not yet scheduled", not an error.-- - A later on the same map only appends a milestone that is entirely new and unions a new member into one that already exists. A member the map already places in a different milestone, a different relative order of two milestones that both already exist, or a changed
chartare each reported underlabeland left unapplied — the same contract asdivergence/title. Edit the milestones region by hand to move a ticket, reorder the list, or change a label.destination - is downstream — the tickets this one holds up. Readers see the upstream
blocksinstead; do not confuse the two.blockedBy - Every target must already exist, either in this same input's
blocksor on the map on disk. Naming one that exists in neither is a validation error: the run exitstickets[]and writes nothing. That is why the template above carries2as well as the ticket that blocks it.cutover-order - /
mapTypein the contract are Azure DevOps work-item types. They have no effect on the local backend — leave them out.ticketType
在临时工作目录中创建。这些JSON文件是工作文件,而非存储文件——映射图本身才是事实来源。
map_input.jsonjson
{
"target": { "slug": "billing-migration" },
"map": {
"title": "Decision map - migrate billing to the new provider",
"destination": "<the destination from Step 1, as one line>",
"notes": ["<a skill every session should consult>", "<a standing preference>"],
"notYetSpecified": ["<fog line>"],
"outOfScope": ["<ruled-out line>"],
"milestones": [
{ "slug": "mvp", "label": "demo the search page",
"members": ["provider-choice"] }
]
},
"tickets": [
{ "key": "provider-choice", "title": "Provider - which one do we commit to?",
"type": "grilling", "question": "<the decision this resolves>",
"blocks": ["cutover-order"] },
{ "key": "cutover-order", "title": "Cutover order - big bang or per-tenant ramp?",
"type": "grilling", "question": "<the decision this resolves>" }
]
}- 和每个事项的
slug均使用小写短横线格式,必须匹配key,且不得包含[A-Za-z0-9][A-Za-z0-9_-]*。-- - 为可选字段;每个条目为
milestones,顺序为交付顺序——顺序由列表本身决定,与事项键的顺序无关。里程碑{slug, label, members}遵循与事项slug相同的规则(不得包含key)。一个事项最多属于一个里程碑,未分配里程碑的事项是合法的:表示“尚未排期”,而非错误。-- - 针对同一映射图的后续操作仅追加全新的里程碑,并合并已有里程碑中的新成员。若映射图已将某个成员分配到不同里程碑、已有两个里程碑的相对顺序发生变化、或
chart被修改,这些情况会在label下报告且不会应用——与divergence/title的约定相同。需手动编辑里程碑区域来移动事项、重新排序列表或修改标签。destination - 表示下游——当前事项阻塞的其他事项。读者看到的是上游的
blocks字段;请勿混淆二者。blockedBy - 每个目标必须已存在,要么在本次输入的
blocks中,要么在磁盘上的映射图中。若指定的目标不存在,会触发验证错误:流程以tickets[]退出且不写入任何内容。这就是上述模板中同时包含2和阻塞它的事项的原因。cutover-order - 约定中的/
mapType是Azure DevOps工作项类型。在本地后端中无任何作用——请忽略。ticketType
The create-class gate (never skip it)
创建类闸门(切勿跳过)
1. Dry run. is dry-run by default; is what writes.
chart--realpython "<ops>" chart --input <workdir>/map_input.jsonThe plan lands twice: as JSON on stdout (machine-readable) and as a human
rendering on stderr. Show the user the stderr rendering.
2. Read the labels — they are what the user is approving. Every item the run
would touch appears exactly once, with one of four actions:
| Action | What it means for that item |
|---|---|
| it does not exist yet and will be created |
| it exists and nothing will be written to it |
| it exists and will be modified in place, additively — added to, never overwritten |
| |
Every carries a naming exactly what it gains. A ticket
merge reads — and that is the only thing a ticket
merge ever does. A map-body merge counts the lines,
; when it adds none but still rewrites a
region it says so instead — , which is what you see after a hand edit left a region empty or ragged
and the run is only restoring the tool-owned placeholder. Read those
details out; then add the part the count cannot convey: it is a union, so it
can add lines but never removes or reorders the ones already there, and a fog
line the input omits stays on the map.
mergedetailunions blockedBy: <key>adds 2 fog lines, 1 out-of-scope linenormalises the map body's list regions (no new lines)- (none)On a first chart every line is . On a later chart most lines are
— that is the design, not a failure: is additive (ADR
0054/0055). It adds what is absent and never removes, reorders or overwrites
what is there, so re-running the identical input is a byte-identical no-op, and
a partially-failed chart is resumable by simply re-running it. If you see an
line and did not deliberately pass , stop and investigate.
createskip (exists)chartOVERWRITE--force3. Ask for explicit approval. Never create without it. The approval is for
the plan you just showed — if the input changes at all, re-run the dry run and
show the new plan.
Carry the end-of-session commit offer in this same ask, on local. In the
same message, ask whether to commit the new folder
once the session ends, alongside any repo docs it produced -- so the session
pauses once, here, instead of twice. This does not weaken assisted git: a
bundled offer is still an explicit offer the user answers, and nothing is
committed without that yes. On GitHub there is nothing to commit for the map
itself, but any repo docs still need the same ask.
docs/decision-map/<slug>/4. On approval, re-run with :
--realpython "<ops>" chart --input <workdir>/map_input.json --output <workdir>/map.json --realKeep the returned as this session's working file. Show the user the
map's name and its path, and the tickets by name — never a wall of bare keys.
The script wires the blocking edges itself, in a second pass once every
ticket exists. There are no parent links to wire: on the local backend
containment is the directory — a ticket belongs to this map because it sits in
that map's tickets — and the map document holds no index of open tickets, only
the "Decisions so far" list that projects from the closed ones. Each
created ticket also carries a generated position diagram below ,
written and maintained by the script rather than by you (ADR 0063/0064).
map.jsonresolve## Question5. Check in the result. A non-empty list means the input asked
for something an additive run deliberately did not apply — most often a
changed / on a map that already exists. Report
every line. The fix is to edit the map document by hand, never to reach for .
is not on that list on any map carrying the notes region: there it is a
list region that unions like the fog lines (ADR 0101), so a later
should carry only NEW note lines. (On a legacy map that predates the region,
is still a scalar and still diverges.) An
existing note restated in any other shape — the bullets joined into one string,
or pasted back with their prefixes — is a new line to the union, so it is
appended, silently, with no to catch it.
divergencetitledestination--forcenoteschartnotes- divergenceOn failure: a known, actionable failure exits with one line on stderr
and empty stdout. That line names the field to fix. Correct
, re-run the dry run, and re-approve.
2map_input.jsonThe gate will not remove a graduated fog line. If this chart turns a line
that already sits under "Not yet specified" into a real ticket, union never
deletes, so the line is still sitting there. Delete it by hand from between the
marker comments in the map document, leaving the markers themselves
alone — otherwise the map keeps advertising fog that is now a real ticket, and
the list slowly becomes a log of questions already answered.
decision-map:fog1. 试运行。命令默认处于试运行模式;参数才会执行写入操作。
chart--realpython "<ops>" chart --input <workdir>/map_input.json计划会输出两次:一次是标准输出中的JSON格式(机器可读),一次是标准错误输出中的人类可读格式。向用户展示标准错误输出的内容。
2. 查看标签——这是用户需要批准的内容。流程会触及的每个条目仅出现一次,并带有以下四种操作之一:
| 操作 | 含义 |
|---|---|
| 条目不存在,将被创建 |
| 条目已存在,不会写入任何内容 |
| 条目已存在,将原地增量修改——仅添加内容,绝不会覆盖 |
| 仅在使用 |
每个操作都会附带字段,明确说明新增内容。事项合并会显示——这是事项合并仅有的操作。映射图主体合并会统计行数,例如;若未添加任何内容但仍重写了区域,则会显示——这通常发生在手动编辑后区域为空或格式混乱,流程仅恢复工具默认的占位符。请读出这些细节;然后补充统计无法传达的信息:这是合并操作,因此仅添加内容,绝不会删除或重新排序已有内容,输入中未包含的模糊需求行仍会保留在映射图中。
mergedetailunions blockedBy: <key>adds 2 fog lines, 1 out-of-scope linenormalises the map body's list regions (no new lines)- (none)首次绘制时所有行均为。后续绘制时大多数行是——这是设计预期,而非失败:是增量式的(ADR 0054/0055)。仅添加缺失内容,绝不会删除、重新排序或覆盖已有内容,因此重新运行相同输入是完全无操作的,部分失败的绘制可通过重新运行恢复。若未刻意使用却出现行,请停止操作并排查问题。
createskip (exists)chart--forceOVERWRITE3. 请求明确批准。切勿未经批准就创建内容。批准针对的是你刚刚展示的计划——若输入发生任何变化,需重新运行试运行并展示新计划。
在本地存储场景下,可在本次请求中同时询问会话结束后的提交操作。在同一条消息中,询问用户会话结束后是否提交新的文件夹及其生成的仓库文档——这样会话仅在此处暂停一次,而非两次。这不会弱化辅助git的规则:捆绑请求仍是用户需明确答复的请求,未经同意不会提交任何内容。在GitHub场景下,映射图本身无需提交,但生成的仓库文档仍需同样的请求。
docs/decision-map/<slug>/4. 获得批准后,添加参数重新运行:
--realpython "<ops>" chart --input <workdir>/map_input.json --output <workdir>/map.json --real将返回的作为本次会话的工作文件。向用户展示映射图的名称和路径,以及事项的名称——切勿仅展示一堆裸键。脚本会在所有事项创建完成后,通过二次处理自动连接阻塞关系。无需连接父链接:在本地后端中,包含关系由目录决定——事项属于该映射图是因为它位于该映射图的事项目录中——映射文档不包含未完成事项的索引,仅包含命令从已完成事项生成的“已做出的决策”列表。每个创建的事项还会在下方携带一个生成的位置图,由脚本而非你负责编写和维护(ADR 0063/0064)。
map.jsonresolve## Question5. 检查结果中的字段。非空列表表示输入请求了增量式流程刻意不应用的内容——最常见的情况是已有映射图的/被修改。报告每一行内容。修复方法是手动编辑映射文档,切勿使用。在包含notes区域的映射图中,不在此列表中:它是一个像模糊需求行一样合并的列表区域(ADR 0101),因此后续操作应仅携带新的note行。(在不支持该区域的旧版映射图中,仍是标量且仍会触发divergence。)若现有note以其他形式重新表述——例如项目符号合并为单个字符串,或粘贴时保留前缀——会被视为新行进行合并,且不会触发。
divergencetitledestination--forcenoteschartnotes- divergence失败处理:已知的可处理失败会以退出,并在标准错误输出中显示一行内容,标准输出为空。该行内容会指出需要修复的字段。修改,重新运行试运行并重新获得批准。
2map_input.json闸门不会移除已转化的模糊需求行。若本次绘制将“尚未明确”下的某行内容转化为真实事项,由于合并操作不会删除内容,该行仍会保留。需手动从映射文档的标记注释之间删除该行,保留标记本身——否则映射图会持续显示已转化为真实事项的模糊需求,列表会逐渐变成已解决问题的日志。
decision-map:fog--force
is an escape hatch, never a remedy
--force--force
是应急出口,绝非常规解决方案
--force--forceOVERWRITE${CLAUDE_PLUGIN_ROOT}/references/data-contracts.mdDo not suggest because a re-chart printed , because
the map looks stale, or because a run half-failed. Additive already
covers all three, and is never required to add a ticket or an edge.
Offer it only when the user explicitly asks for an existing map to be rewritten
from a new input — and only after showing the dry run's
lines and naming, per line, what will be destroyed. The plan will not name it
for you: an entry carries , so you have to work each
line's cost out of the contract's table and say it out loud yourself.
--forceskip (exists)chart--force--forceOVERWRITEOVERWRITEdetail: null--force--forceOVERWRITE${CLAUDE_PLUGIN_ROOT}/references/data-contracts.md切勿因重新绘制显示、映射图看起来过时或流程部分失败而建议使用。增量式已覆盖所有这些场景,添加事项或关系永远不需要。仅当用户明确要求从新输入重写已有映射图时才提供该选项——且必须先展示试运行的行,并逐行说明会销毁的内容。计划不会自动说明这些内容:条目的为,因此你必须从约定的表格中自行分析每行的代价并明确告知用户。
skip (exists)--forcechart--force--forceOVERWRITEOVERWRITEdetailnull--forceStep 4 — Fire the research subagents
步骤4 — 启动研究子Agent
Every ticket is AFK, and they are the one exception to
one-ticket-per-session. For each one just created:
research- Dispatch a research subagent — all of them in parallel, the way your harness runs subagents. Give it that ticket's Question verbatim plus the destination line for context, and ask for raw markdown findings, not a polished summary.
- Write each set of findings to a scratch file and post it onto its ticket:
python "<ops>" resolve --map <slug> --ticket <key> --gist "<one-line answer>" --body-file <workdir>/findings-<key>.mdresolveEscalation (ADR 0038). If a research question can only be answered from a
live system — a real schema, a real org's data, the actual code — do not answer
it from outside knowledge. Leave the ticket open and note on it that it
should be resolved via in its own session:
study-design-verifypython "<ops>" comment --map <slug> --ticket <key> --body-file <workdir>/note-<key>.md每个类型的事项均为AFK模式,且是“单会话单事项”规则的唯一例外。对于每个刚创建的此类事项:
research- 调度一个研究子Agent——所有子Agent并行运行,方式与你的工具运行子Agent一致。向其提供该事项的问题原文及目标终点行作为上下文,并要求返回原始markdown格式的调研结果,而非 polished 的摘要。
- 将每组调研结果写入临时文件,并发布到对应的事项:
python "<ops>" resolve --map <slug> --ticket <key> --gist "<one-line answer>" --body-file <workdir>/findings-<key>.mdresolve升级处理(ADR 0038)。若研究问题只能从实时系统获取答案——真实的 schema、真实组织的数据、实际代码——请勿使用外部知识回答。保持事项开放,并在事项上注明应通过在单独会话中解决:
study-design-verifypython "<ops>" comment --map <slug> --ticket <key> --body-file <workdir>/note-<key>.mdStep 5 — Stop
步骤5 — 停止操作
Run the check on the map you just made (ADR 0067). reads it and writes
nothing — exit clean, exit with findings:
lint03python "<ops>" lint --map <slug>A fresh chart should be clean. If it is not, an input that passed the gate still
produced a broken map — a blocking cycle is the one the gate cannot see, because
each edge is valid on its own. Fix it before reporting a map the next session
will trip over.
Read the frontier before you report it. The split you are about to show
answers "what can the next session pick up", and cannot answer that:
its deliberately lists every recorded blocker, open or closed.
Step 4 has just produced exactly the state that trips this up — a
ticket you resolved may have been blocking something, and in that
something still looks blocked. counts only the open
blockers, which is the whole point of it:
map.jsonblockedByresearchmap.jsonfrontier.jsonpython "<ops>" frontier --map <slug>Its three buckets — , , — are what you report.
stays the full picture; the frontier is the answer to "what is
takeable".
frontierblockedclaimedmap.jsonReport, in this order:
- any finding, errors first — and say explicitly when it came back clean;
lint - the map's name and path;
- the frontier tickets by name — what the next session can pick up;
- the blocked tickets by name, each with the open blocker still holding it;
- what the research subagents resolved, one gist each;
- the fog lines still unspecified;
- what was ruled out of scope.
One line per bullet, no filler, around ten lines in total -- group rather than
itemize when a bullet would otherwise run to a list of its own.
On local, offer to commit the new folder
(assisted git — offer, never automatic). On GitHub there is nothing to
commit: the map is already live in the tracker the moment returned, so
give the map issue's URL instead and say that anyone with repo access can see it
now. If the Step 3 gate already carried this offer and the user approved it
there, commit now without asking a second time -- the yes you are holding is
that explicit offer, answered.
docs/decision-map/<slug>/--realThen suggest for the next session, and stop. Do not
claim a ticket, do not resolve one, do not start the first decision. Charting is
one session's work, and the map — not this conversation — carries the state from
here on.
/decision-map:workFog graduates into new tickets later through this same Step 3 gate, driven from
: is one operation serving both acts (ADR 0057).
work-mapchart对你刚创建的映射图进行检查(ADR 0067)。命令会读取映射图但不写入任何内容——以退出表示检查通过,以退出表示发现问题:
lint03python "<ops>" lint --map <slug>新绘制的映射图应检查通过。若未通过,说明通过闸门的输入仍生成了有问题的映射图——最常见的是闸门无法检测到的阻塞循环,因为每个单独的关系都是有效的。在报告映射图前先修复问题,避免后续会话遇到障碍。
报告前先查看前沿范围。你即将展示的分类回答了“下一个会话可处理哪些内容”,而无法回答此问题:其字段会列出所有已记录的阻塞项,无论是否已完成。步骤4刚创建的状态恰好会导致此问题——你解决的事项可能阻塞了其他事项,但在中这些事项仍显示为阻塞状态。仅统计未完成的阻塞项,这正是其核心作用:
map.jsonblockedByresearchmap.jsonfrontier.jsonpython "<ops>" frontier --map <slug>其三个分类——、、——就是你需要报告的内容。是完整视图;前沿范围是“可处理内容”的答案。
frontierblockedclaimedmap.json按以下顺序报告:
- 所有发现的问题,优先报告错误——明确说明检查通过的情况;
lint - 映射图的名称和路径;
- 前沿范围的事项名称——下一个会话可处理的内容;
- 阻塞状态的事项名称,每个事项需注明仍在阻塞它的未完成项;
- 研究子Agent解决的问题,每个问题对应一行摘要;
- 仍未明确的模糊需求行;
- 已排除的超出范围内容。
每个项目用一行表示,无需冗余内容,总共约十行——若某个项目本身会包含列表,可进行分组而非逐条列出。
在本地存储场景下,询问用户是否提交新的文件夹(辅助git——仅请求,切勿自动提交)。在GitHub场景下,无需提交任何内容:映射图在命令返回时已在跟踪系统中生效,因此只需提供映射图Issue的URL,并告知所有拥有仓库权限的用户现在均可查看。若步骤3的闸门已包含此请求且用户已批准,现在无需再次询问即可提交——你已获得明确同意。
docs/decision-map/<slug>/--real然后建议下一个会话使用,并停止操作。切勿认领事项、解决事项或启动第一个决策。绘制映射图是一个会话的工作,从现在起,状态由映射图而非本次对话承载。
/decision-map:work模糊需求会在后续通过驱动的同一步骤3闸门转化为新事项:是同时服务于这两种场景的操作(ADR 0057)。
work-mapchart