All artifacts + prefs under project .codemap/ (not .claude); generate asks language/output/title -> .codemap/config.json

This commit is contained in:
Xingyu Chen
2026-06-10 18:38:13 -07:00
parent bf03873d34
commit f7c1431c84
4 changed files with 54 additions and 29 deletions
+17 -12
View File
@@ -17,11 +17,16 @@ Three coupled artifacts, kept in sync:
| File | What | Where (default) | | File | What | Where (default) |
|---|---|---| |---|---|---|
| `modules.json` | the **source of truth** (modules, deps, coupling, LoC, hash, score, findings) | `<project>/.claude/codemap/` | | `config.json` | your saved **preferences** (UI language, output location, title) | `<project>/.codemap/` |
| `architecture-map.html` | self-contained **interactive map** (health coloring, filters, dependency highlighting, audit report) | `<project>/docs/` | | `modules.json` | the **source of truth** (modules, deps, coupling, LoC, hash, score, findings) | `<project>/.codemap/` |
| `architecture-audit.md` | the written **report** (per-layer scores, LoC table, worst offenders, themes) | `<project>/docs/` | | `architecture-map.html` | self-contained **interactive map** (health coloring, filters, dependency highlighting, audit report) | `<project>/.codemap/` |
| `architecture-audit.md` | the written **report** (per-layer scores, LoC table, worst offenders, themes) | `<project>/.codemap/` |
The HTML and MD are **generated** from `modules.json` and must never be hand-edited. Everything lives in **`<project>/.codemap/`** by default. On first run (`generate`) the
tool asks your preferences — UI language, output location (point it at `docs/` if you
want the HTML/MD committed/visible), project title — and saves them to
`.codemap/config.json`. The HTML and MD are **generated** from `modules.json` and must
never be hand-edited.
### Interactive map features ### Interactive map features
- Layered bands top→bottom along the data-flow; click a module to highlight what it - Layered bands top→bottom along the data-flow; click a module to highlight what it
@@ -84,16 +89,16 @@ You can also run the deterministic scripts directly (no AI needed for these):
S=~/.claude/skills/codemap S=~/.claude/skills/codemap
# what changed since last audit — incl. a `git` block listing the commits since the # what changed since last audit — incl. a `git` block listing the commits since the
# last codemap run (meta.rev) and which modules they touched # last codemap run (meta.rev) and which modules they touched
python3 $S/scripts/scan.py --root . --state .claude/codemap/modules.json python3 $S/scripts/scan.py --root . --state .codemap/modules.json
# after an update, cache the current HEAD as the new baseline for next time # after an update, cache the current HEAD as the new baseline for next time
python3 $S/scripts/scan.py --root . --state .claude/codemap/modules.json --stamp-rev python3 $S/scripts/scan.py --root . --state .codemap/modules.json --stamp-rev
# find modules to act on without reading the whole state (token-cheap, for agents) # find modules to act on without reading the whole state (token-cheap, for agents)
python3 $S/scripts/query.py --state .claude/codemap/modules.json --max-grade C --format ids python3 $S/scripts/query.py --state .codemap/modules.json --max-grade C --format ids
python3 $S/scripts/query.py --state .claude/codemap/modules.json --tag dual-format python3 $S/scripts/query.py --state .codemap/modules.json --tag dual-format
# regenerate the HTML + MD from the state # regenerate the HTML + MD from the state
python3 $S/scripts/render.py --state .claude/codemap/modules.json \ python3 $S/scripts/render.py --state .codemap/modules.json \
--template $S/assets/template.html \ --template $S/assets/template.html \
--out-html docs/architecture-map.html --out-md docs/architecture-audit.md --out-html .codemap/architecture-map.html --out-md .codemap/architecture-audit.md
``` ```
> On Windows use `python` instead of `python3`. > On Windows use `python` instead of `python3`.
@@ -162,10 +167,10 @@ severities, coupling, and the issue tags with descriptions). Two ways to customi
- **In the map**: open the **Standard** page (header button), click **Edit**, change any - **In the map**: open the **Standard** page (header button), click **Edit**, change any
description, add your own tags (`+ Tag`), then **Export** → save the downloaded description, add your own tags (`+ Tag`), then **Export** → save the downloaded
`standard.json` to `<project>/.claude/codemap/standard.json`. Edits are kept in the `standard.json` to `<project>/.codemap/standard.json`. Edits are kept in the
browser until you export. Custom tags flow through the whole map (cards, filters, browser until you export. Custom tags flow through the whole map (cards, filters,
report) and are used by future audits. report) and are used by future audits.
- **By file**: copy `reference/standard.json` to `<project>/.claude/codemap/standard.json` - **By file**: copy `reference/standard.json` to `<project>/.codemap/standard.json`
and edit it. `render.py` prefers the project file over the skill default. and edit it. `render.py` prefers the project file over the skill default.
The prose version + the exact subagent audit prompt live in `reference/STANDARDS.md` The prose version + the exact subagent audit prompt live in `reference/STANDARDS.md`
+29 -9
View File
@@ -36,9 +36,9 @@ schema is in **`reference/DATA_MODEL.md`**. Do not improvise scoring or invent t
**The standard is configurable per project.** A machine-readable copy lives in **The standard is configurable per project.** A machine-readable copy lives in
`reference/standard.json` (rubric, severities, coupling, and the tag list with `reference/standard.json` (rubric, severities, coupling, and the tag list with
descriptions). A project may override it by placing its own `standard.json` next to the descriptions). A project may override it by placing its own `standard.json` next to the
state file (`<project>/.claude/codemap/standard.json`) — `render.py` picks the project state file (`<project>/.codemap/standard.json`) — `render.py` picks the project
file first, else the skill default, and injects it into the map's editable **Standard** file first, else the skill default, and injects it into the map's editable **Standard**
page. **Honor the project's tag set:** when `.claude/codemap/standard.json` exists, audit page. **Honor the project's tag set:** when `.codemap/standard.json` exists, audit
modules using *its* tags (including any custom tags the user added) — that is how users modules using *its* tags (including any custom tags the user added) — that is how users
capture their own definition of a problem. Keep `STANDARDS.md` (the prose + subagent capture their own definition of a problem. Keep `STANDARDS.md` (the prose + subagent
prompt) and `standard.json` (the machine copy) in sync if you change the defaults. prompt) and `standard.json` (the machine copy) in sync if you change the defaults.
@@ -47,12 +47,16 @@ prompt) and `standard.json` (the machine copy) in sync if you change the default
- `SKILL_DIR` = this skill's directory. Scripts are at `SKILL_DIR/scripts/*.py`, - `SKILL_DIR` = this skill's directory. Scripts are at `SKILL_DIR/scripts/*.py`,
template at `SKILL_DIR/assets/template.html`. Use python3, stdlib only. template at `SKILL_DIR/assets/template.html`. Use python3, stdlib only.
- Default artifact locations (override if the user/project prefers): state (the data) - **Everything lives under `<project>/.codemap/`** — one folder, not `.claude/`:
at `<project>/.claude/codemap/modules.json`; the generated outputs at - `config.json` the user's saved preferences (UI language, output location, title…).
`<project>/dev_docs/architecture-map.html` and `dev_docs/architecture-audit.md`. The - `modules.json` — the state (source of truth).
state lives under `.claude/` (tooling data, kept out of the docs tree); only the two - `standard.json` — optional per-project custom audit standard.
human-facing artifacts go in `dev_docs/`. Set `meta.htmlPath` / `meta.mdPath` so the - `architecture-map.html` + `architecture-audit.md` the generated outputs (default).
reciprocal links are correct.
The output location is a user preference: if they want the HTML/MD committed/visible,
let them point it at `docs/` instead (ask — see `generate` step 0). Set
`meta.htmlPath` / `meta.mdPath` to wherever the outputs land so the reciprocal links
are correct (both outputs sit in the same dir, so the in-page link uses the basename).
- A re-render command (run after any state change): - A re-render command (run after any state change):
``` ```
python3 SKILL_DIR/scripts/render.py --state <state> \ python3 SKILL_DIR/scripts/render.py --state <state> \
@@ -111,8 +115,24 @@ per-module subagent loop — never load the full `modules.json` just to pick tar
## Command: `generate` (first build) ## Command: `generate` (first build)
Use when no `modules.json` exists yet. Use when no `modules.json` exists yet (this is also "init").
0. **Ask the user for preferences first** (use the AskUserQuestion tool), then save them to
`<project>/.codemap/config.json`:
- **UI language** — `en` or `zh` (localizes the map chrome + report; module names are
never translated). → `meta.lang`.
- **Output location** — where the HTML/MD go. Default `.codemap/` (kept with the tool
data); offer `docs/` if they want them committed/visible. → `meta.htmlPath` / `meta.mdPath`.
- **Project title** (defaults to the repo/folder name) and an optional one-line subtitle,
in the chosen language. → `meta.project` / `meta.subtitle`.
Write `config.json` like:
```json
{"lang":"zh","project":"My App","subtitle":"…","outputDir":".codemap",
"htmlFile":"architecture-map.html","mdFile":"architecture-audit.md"}
```
and apply it to `meta` when you build `modules.json`. Re-read `config.json` on later
runs so preferences persist.
1. **Decompose the project into functional modules.** Explore the tree (parallel Explore 1. **Decompose the project into functional modules.** Explore the tree (parallel Explore
agents for big repos). Identify capabilities and group them into **bands** (visual agents for big repos). Identify capabilities and group them into **bands** (visual
layers in data-flow order, e.g. UI → stores → transport → │wire│ → app → handlers → layers in data-flow order, e.g. UI → stores → transport → │wire│ → app → handlers →
+5 -5
View File
@@ -221,8 +221,8 @@ const I18N = {
btnStd:"Standard", stdTitle:"Audit standard", stdIntro:"How modules are scored — the same rubric for every module, language, and run. Click Edit to add your own issue tags.", btnStd:"Standard", stdTitle:"Audit standard", stdIntro:"How modules are scored — the same rubric for every module, language, and run. Click Edit to add your own issue tags.",
stdRubric:"Score → grade", stdSeverity:"Finding severity", stdTags:"Issue tags", stdCoupling:"Coupling (structural, not quality)", close:"Close", stdRubric:"Score → grade", stdSeverity:"Finding severity", stdTags:"Issue tags", stdCoupling:"Coupling (structural, not quality)", close:"Close",
stdEditBtn:"Edit", stdDone:"Done", stdExport:"Export", stdReset:"Reset", stdAddTag:"+ Tag", stdEditBtn:"Edit", stdDone:"Done", stdExport:"Export", stdReset:"Reset", stdAddTag:"+ Tag",
stdEditHint:"Editing — changes save in this browser. Export → save as <code>.claude/codemap/standard.json</code> to make them permanent and used by audits.", stdEditHint:"Editing — changes save in this browser. Export → save as <code>.codemap/standard.json</code> to make them permanent and used by audits.",
stdNewTagId:"New tag id (e.g. perf-risk, security):", stdExported:"Saved standard.json — put it in .claude/codemap/", stdNewTagId:"New tag id (e.g. perf-risk, security):", stdExported:"Saved standard.json — put it in .codemap/",
copyFix:"Copy fix prompt", copied:"Copied — paste into Claude Code / Codex", copyFix:"Copy fix prompt", copied:"Copied — paste into Claude Code / Codex",
trackedLoc:(l,f)=>`${l} tracked LoC · ${f} files` }, trackedLoc:(l,f)=>`${l} tracked LoC · ${f} files` },
zh:{ mapSuffix:"· 功能架构图", sub:"功能模块 · 调用层级 · 耦合 · 质量评分 · 代码行数", zh:{ mapSuffix:"· 功能架构图", sub:"功能模块 · 调用层级 · 耦合 · 质量评分 · 代码行数",
@@ -240,8 +240,8 @@ const I18N = {
btnStd:"评判标准", stdTitle:"评判标准", stdIntro:"模块如何打分 —— 所有模块、所有语言、每一次运行都用同一套标准。点「编辑」可加入你自己的问题标签。", btnStd:"评判标准", stdTitle:"评判标准", stdIntro:"模块如何打分 —— 所有模块、所有语言、每一次运行都用同一套标准。点「编辑」可加入你自己的问题标签。",
stdRubric:"分数 → 等级", stdSeverity:"问题严重度", stdTags:"问题标签", stdCoupling:"耦合(结构维度,非质量)", close:"关闭", stdRubric:"分数 → 等级", stdSeverity:"问题严重度", stdTags:"问题标签", stdCoupling:"耦合(结构维度,非质量)", close:"关闭",
stdEditBtn:"编辑", stdDone:"完成", stdExport:"导出", stdReset:"重置", stdAddTag:"+ 标签", stdEditBtn:"编辑", stdDone:"完成", stdExport:"导出", stdReset:"重置", stdAddTag:"+ 标签",
stdEditHint:"编辑中 —— 改动保存在本浏览器。导出 → 存为 <code>.claude/codemap/standard.json</code> 即永久生效并被审计采用。", stdEditHint:"编辑中 —— 改动保存在本浏览器。导出 → 存为 <code>.codemap/standard.json</code> 即永久生效并被审计采用。",
stdNewTagId:"新标签 id(如 perf-risk、security):", stdExported:"已生成 standard.json —— 放到 .claude/codemap/ 下", stdNewTagId:"新标签 id(如 perf-risk、security):", stdExported:"已生成 standard.json —— 放到 .codemap/ 下",
copyFix:"复制修复指令", copied:"已复制 —— 粘贴到 Claude Code / Codex", copyFix:"复制修复指令", copied:"已复制 —— 粘贴到 Claude Code / Codex",
trackedLoc:(l,f)=>`${l} 行(已跟踪)· ${f} 个文件` }, trackedLoc:(l,f)=>`${l} 行(已跟踪)· ${f} 个文件` },
}; };
@@ -251,7 +251,7 @@ function stdText(o){ return o ? (LANG==="zh" ? (o.zh||o.en||"") : (o.en||o.zh||"
/* ---------- the audit standard — editable, configurable, its own page ---------- /* ---------- the audit standard — editable, configurable, its own page ----------
Effective standard = a saved browser draft (user edits), else the injected file Effective standard = a saved browser draft (user edits), else the injected file
(DATA.standard, from .claude/codemap/standard.json or the skill default), else (DATA.standard, from .codemap/standard.json or the skill default), else
this built-in fallback. Edit it on the Standard page and Export to standard.json this built-in fallback. Edit it on the Standard page and Export to standard.json
to make it permanent and used by audits. Custom tags flow through the whole map. */ to make it permanent and used by audits. Custom tags flow through the whole map. */
const BUILTIN_STD = { const BUILTIN_STD = {
+3 -3
View File
@@ -15,8 +15,8 @@ subagents edit it) and re-render.
"generatedAt": "2026-01-01", "generatedAt": "2026-01-01",
"rev": "abc1234", // git HEAD at the last codemap run (the baseline "rev": "abc1234", // git HEAD at the last codemap run (the baseline
// `update`/`check` diff from; set by scan.py --stamp-rev) // `update`/`check` diff from; set by scan.py --stamp-rev)
"htmlPath": "docs/architecture-map.html", // for reciprocal links "htmlPath": ".codemap/architecture-map.html", // output location (for reciprocal links)
"mdPath": "docs/architecture-audit.md", "mdPath": ".codemap/architecture-audit.md",
"spineDesc": "A user edits … → … → persistence.", // shown on the spine view "spineDesc": "A user edits … → … → persistence.", // shown on the spine view
"tracked_loc": 184900, // filled by scan.py --write (union, de-duped) "tracked_loc": 184900, // filled by scan.py --write (union, de-duped)
"tracked_files": 980, "tracked_files": 980,
@@ -107,6 +107,6 @@ independent: a `core` module can be clean (A) and a `low` leaf can be broken (F)
The scoring standard is data, not code: `reference/standard.json` holds the rubric, The scoring standard is data, not code: `reference/standard.json` holds the rubric,
severities, coupling levels, and the issue `tags` (each `{id,label,labelZh,bad,en,zh}`). severities, coupling levels, and the issue `tags` (each `{id,label,labelZh,bad,en,zh}`).
A project overrides it at `<project>/.claude/codemap/modules.json`'s sibling A project overrides it at `<project>/.codemap/modules.json`'s sibling
`standard.json`. The map renders + lets you edit it on the **Standard** page (Export to `standard.json`. The map renders + lets you edit it on the **Standard** page (Export to
save). Audits must use the project standard's tags when present — including custom ones. save). Audits must use the project standard's tags when present — including custom ones.