Files

5.8 KiB

modules.json — the state / source of truth

One file per project. The HTML and MD are pure projections of it (regenerated by render.py); never hand-edit the outputs. Edit modules.json (or let the scripts and subagents edit it) and re-render.

{
  "meta": {
    "project": "My App",               // shown in the title (module NAMES are never translated)
    "lang": "en",                       // UI display language: "en"|"zh" (default "en").
                                        //   localizes the chrome + report; module `desc`
                                        //   should be authored in this language. ids/labels stay.
    "subtitle": "short tagline",        // optional header sub-line (write in meta.lang)
    "generatedAt": "2026-01-01",
    "rev": "abc1234",                   // git HEAD at the last codemap run (the baseline
                                        //   `update`/`check` diff from; set by scan.py --stamp-rev)
    "htmlPath": ".codemap/codemap.html",  // output location (for reciprocal links)
    "mdPath": ".codemap/codemap.md",
    "spineDesc": "A user edits … → … → persistence.",  // shown on the spine view
    "tracked_loc": 184900,             // filled by scan.py --write (union, de-duped)
    "tracked_files": 980,
    "locLine": "≈185k first-party LoC …"  // optional override of the report line
  },

  "excludes": ["__pycache__","/node_modules/", "..."],  // optional; sensible defaults if absent

  "bands": [                            // visual layers, top → bottom (data-flow order)
    {"id":"festore","tier":"fe","t":"Frontend · Stores","d":"one store per domain"},
    {"id":"wire1","wire":true,"t":"◀ WebSocket · HTTP ▶"},  // a divider, not a band
    {"id":"becore","tier":"be","t":"Backend · Core","d":"scene model, protocol"}
  ],

  "spine": ["p_viewport","editorStore","ws_svc","be_main","core_scene","persistence"],

  "reportThemes": [
    ["Dual-format is the most-repeated violation", "snake||camel recurs in N handlers …"],
    ["Duplication is the dominant theme", "X and Y reimplement …"]
  ],

  "modules": [
    {
      "id": "core_scene",              // stable unique id (used in deps + edges)
      "label": "Scene",                // shown on the card
      "band": "becore",                // which band it sits in
      "path": "core/scene.py",         // human-readable location (shown in detail)
      "paths": ["src/core/scene.py"],  // globs scan.py counts (root-relative; may use ** wildcards)
      "exclude": [],                   // optional extra excludes for this module
      "coupling": "core",              // low | med | high | core  (manual / structural)
      "deps": ["core_object","core_components"],  // downstream: what this calls
      "desc": "Central data structure …",          // 1-line "what it does", shown on click;
                                                   // author in meta.lang (zh for this project)
      "tests": ["server/.../tests/test_scene.py"], // globs for this module's tests (the
                                                   // regression net); NOT counted in the
                                                   // module's own audit scope / loc
      "lastFix": {                     // optional: outcome of the most recent `fix`
        "at":"2026-06-11","accepted":true,
        "ran":"pytest tests/test_scene.py",
        "scoreBefore":68,"scoreAfter":84
      },

      // ---- filled by scan.py --write ----
      "loc": 1234,
      "contentHash": "ab12…",          // hash of current code

      // ---- filled by apply_audit.py (one subagent's result) ----
      "score": 88, "grade": "B",
      "tags": ["legacy"],
      "findings": [{"sev":"LOW","loc":"core/scene.py:72","text":"… evidence …"}],
      "auditedHash": "ab12…",          // contentHash at audit time → staleness check
      "auditedAt": "2026-06-10",
      "auditedRev": "3837998"
    }
  ]
}

Field ownership

Field Written by When
meta.*, bands, spine, coupling, deps, desc, paths, label, id, band model (decomposition) init, and when structure changes
loc, contentHash, meta.tracked_* scan.py --write every scan
score, grade, tags, findings, auditedHash/At/Rev apply_audit.py (from an auditor subagent) each (re)audit
tests test-author subagent test, and the baseline step of fix
lastFix model (after the acceptance gate) each fix
reportThemes model (synthesis) after a full/partial audit

Test files are excluded from a module's audit scope by default (so editing a test does not mark the module stale and test LoC does not inflate the production-code score). The tests field records them separately as the regression net.

Staleness

A module is stale when contentHash != auditedHash (its code changed since last audit), unaudited when it has no score/auditedHash, empty when its paths match no files (likely deleted → drop it or fix the globs). scan.py reports these; only stale + unaudited modules need a fresh subagent.

Coupling vs score

coupling (low/med/high/core) is a structural property — how central the module is (degree + role). score is a quality property — how clean the code is. They are independent: a core module can be clean (A) and a low leaf can be broken (F).

Custom audit standard (standard.json)

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}). 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 save). Audits must use the project standard's tags when present — including custom ones.