Architecture Improve
Deep-research an architecture-map (map.js) for what to change, then paint each idea
back onto the map as a proposed node carrying a structured proposal. The sibling of
architecture-cleanup: map = WHAT exists → cleanup = what to REMOVE → improve = what to CHANGE.
Core principle — proposals-only. improve surfaces optimisation ideas and draws them on
the map. It NEVER edits source, opens PRs, or applies a change (ADR-012: only cleanup gets an
execution layer; improve's changes are judgment-heavy refactors, not mechanical removals).
When to use
- "Optimise the architecture", "improve the pipeline", "where can this be better".
- After mapping (and ideally cleaning) a repo, to plan structural/flow improvements.
- Not for line-level perf, micro-optimisation, or product/feature redesign (D4 boundary).
- Not for finding dead code to delete — that's
architecture-cleanup.
- Recommended order: cleanup → improve (don't optimise code you're about to delete).
Input — map.js (ADR-010)
The input is <repo>/architecture-map/map.js (window.MAP_DATA). If it doesn't exist, build
it first with the architecture-map skill, then run improve on the result. If a fresh
architecture-cleanup overlay exists, improve reads it (see Cross-skill, ADR-014).
The two lenses (D4)
Every proposal is tagged with exactly one lens:
- 🏗️ structure — coupling, god-nodes (high fan-in + fan-out), duplicate subsystems, layering
violations, missing seams.
- 🔀 pipeline — redundant hops, serial steps that could run in parallel, idempotency/retry
gaps, data stored as expiring temp URLs instead of re-hosted, missing back-pressure.
Step 1 — deep research (fan-out, C3 gate)
- Ensure the map exists & is fresh. No
map.js → build via architecture-map. A stale map
gives stale proposals, so re-map if the repo moved.
- Cheap seed signals (deterministic). Reuse cleanup's topology helper to focus the research —
it gives per-node degree (god-node = high inbound+outbound),
duplicateGroups (dup tech), and
blast-radius:node ../architecture-cleanup/analyze-map.mjs <repo>/architecture-map/map.js > /tmp/seed.json
- Cost gate (C3) — warn on scale BEFORE firing. Reader count = number of subsystems on the
map. If it is > 8, tell the user the count + a rough token estimate and wait for a go.
At/under 8, proceed.
- Fan out, one reader per subsystem. Reuse
architecture-audit's Map-phase pattern
(scout + parallel readers via the Workflow tool / subagents). Each reader carries BOTH lenses
in its brief and is pre-seeded with seed.json hints for its subsystem (high-degree nodes,
dup groups). One reader per subsystem keeps the agent count = subsystem count.
Each reader returns candidate proposals: {problem, change, tradeoff, effort, impact, lens, affectedNodes[]}.
Step 2 — synthesize & prioritise (Q1)
Dedup & merge candidate proposals across subsystems (one synthesis pass).
Light verify the big ones. For high-impact proposals, sanity-check the claim against the
code before committing it to the map (honesty principle — no plausible-but-wrong proposals).
This is a check, not a second full fan-out.
Band each proposal from its effort (S/M/L) × impact (low/med/high) — discrete bands,
never a numeric score (we have no telemetry; a number would be false precision):
| Band |
Condition |
| ⚡ quick win |
impact high · effort S |
| 🎯 big bet |
impact high · effort M/L |
| 🧹 fill-in |
everything else |
| ⛔ skip |
impact low · effort L (surfaced, recommended against) |
Step 3 — write proposals onto the map
Each proposal becomes a proposed node (the change drawn) + edges to the shipped nodes it
affects. The structured proposal:{} object lives on the proposed node, never on a shipped
node — a field on a shipped node would be dropped by merge-map.mjs on the next audit, whereas
proposed nodes/edges survive re-audit (ADR-013).
- Git-snapshot the map FIRST (ADR-011). Make sure
map.js is committed (or stash-clean) so
backout is one git restore.
- Build
proposals.json — an array of {node:{id,label,tech?,engine?,subsystem?}, proposal:{problem,change,tradeoff,effort,impact,lens}, edges:[{from,to,data}]}. See helper
--selftest for the exact shape. ids must be NEW (a proposed id may not clobber a shipped node).
- Apply (additive, idempotent):
node apply-proposals.mjs <repo>/architecture-map/map.js /tmp/proposals.json > /tmp/map.js \
&& mv /tmp/map.js <repo>/architecture-map/map.js
- Refresh the viewer if it predates the proposal panel:
cp ../architecture-map/assets/index.html <repo>/architecture-map/.
Step 4 — report (Q6)
improve has no fixed taxonomy (optimisation is open-ended) — but a fixed proposal shape and
a fixed ordering. Hand the user:
- A header line:
N proposals — X quick wins, Y big bets.
- One plain-language card per proposal (format:
../architecture-cleanup/references/finding-card-and-issues.md — What it is / Why it is an
improvement / What you gain / Risk, technical detail folded). Grouped by band
(⚡ quick wins → 🎯 big bets → 🧹 fill-ins → ⛔ skip). The raw problem/change/tradeoff +
effort/impact + affected nodes + lens live in the folded Evidence block.
- The open command:
open <repo>/architecture-map/index.html. A 💡 Proposals (N) toggle
(on by default) rings the proposed nodes amber; clicking one shows the full proposal block.
Step 5 — PRD-ready tracker issues (on approval)
When the user approves proposals (per proposal or per band), convert them to issues in the
project's tracker (Linear, GitHub Issues, Jira — via its workflow skill if you have one).
Structure, sub-issue PRD template (Background/Solution/Acceptance criteria/Risk/Evidence),
estimate/label/priority mapping: all in
../architecture-cleanup/references/finding-card-and-issues.md. Parent Improve: <repo> (<date>) + one sub-issue per approved proposal. Draft the whole batch, show the user titles +
estimates, ONE go creates them. Unapproved proposals stay on the map only. This does NOT
change ADR-012: improve still never executes — the issues are the handoff to whoever builds.
Cross-skill with cleanup (ADR-014)
If a removable overlay is present, improve reads it and routes around it:
- Exclude removable-flagged nodes from the candidate set — don't optimise code already slated
for deletion. Report: "N nodes skipped (flagged removable by cleanup)".
- Routing around or replacing a removable node is fine (additive).
- If a proposal would build on a removable node, surface the conflict explicitly — never build
silently on something being deleted.
Cost (C3)
Step 1's seed pass is static/cheap. The fan-out warns on scale (reader count > 8) before firing.
There is no removal/execution cost — improve only proposes.
Helpers
apply-proposals.mjs <map.js> <proposals.json> — additive, idempotent write-back of proposed
nodes/edges + proposal:{} objects (ADR-011/013). Validates bands + edge endpoints; throws
rather than write garbage. --selftest to verify.
- Reuses
../architecture-cleanup/analyze-map.mjs for the deterministic seed signals (degree,
duplicate-tech, blast-radius). No second analysis helper.
Red flags — STOP
- About to edit source / open a PR / apply a change → don't. improve is proposals-only (C2/ADR-012).
- About to put
proposal on a shipped node → wrong; it must live on a proposed node (ADR-013).
- About to assign a numeric priority score → wrong; bands only (Q1).
- About to propose a line-level perf tweak or a feature redesign → out of scope (D4).
- About to optimise a node cleanup flagged
removable → stop; exclude or surface the conflict (ADR-014).
- About to fan out > 8 readers without warning the user → stop, warn first (C3).
- About to create tracker issues without the batch-go → stop (Step 5).
- Report card leads with node-ids/paths instead of plain language → wrong; detail goes in the folded Evidence block.
1---2name: architecture-improve3description: Architecture Improve4---56# Architecture Improve78Deep-research an architecture-map (`map.js`) for **what to change**, then paint each idea9back onto the map as a `proposed` node carrying a structured proposal. The sibling of10`architecture-cleanup`: map = WHAT exists → cleanup = what to REMOVE → improve = what to CHANGE.1112**Core principle — proposals-only.** improve surfaces optimisation ideas and draws them on13the map. It NEVER edits source, opens PRs, or applies a change (ADR-012: only cleanup gets an14execution layer; improve's changes are judgment-heavy refactors, not mechanical removals).1516## When to use1718- "Optimise the architecture", "improve the pipeline", "where can this be better".19- After mapping (and ideally cleaning) a repo, to plan structural/flow improvements.20- **Not** for line-level perf, micro-optimisation, or product/feature redesign (D4 boundary).21- **Not** for finding dead code to delete — that's `architecture-cleanup`.22- Recommended order: cleanup → improve (don't optimise code you're about to delete).2324## Input — map.js (ADR-010)2526The input is `<repo>/architecture-map/map.js` (`window.MAP_DATA`). If it doesn't exist, build27it first with the `architecture-map` skill, then run improve on the result. If a fresh28`architecture-cleanup` overlay exists, improve reads it (see Cross-skill, ADR-014).2930## The two lenses (D4)3132Every proposal is tagged with exactly one lens:3334- 🏗️ **structure** — coupling, god-nodes (high fan-in + fan-out), duplicate subsystems, layering35 violations, missing seams.36- 🔀 **pipeline** — redundant hops, serial steps that could run in parallel, idempotency/retry37 gaps, data stored as expiring temp URLs instead of re-hosted, missing back-pressure.3839## Step 1 — deep research (fan-out, C3 gate)40411. **Ensure the map exists & is fresh.** No `map.js` → build via `architecture-map`. A stale map42 gives stale proposals, so re-map if the repo moved.432. **Cheap seed signals (deterministic).** Reuse cleanup's topology helper to focus the research —44 it gives per-node degree (god-node = high inbound+outbound), `duplicateGroups` (dup tech), and45 blast-radius:46 ```bash47 node ../architecture-cleanup/analyze-map.mjs <repo>/architecture-map/map.js > /tmp/seed.json48 ```493. **Cost gate (C3) — warn on scale BEFORE firing.** Reader count = number of subsystems on the50 map. If it is **> 8**, tell the user the count + a rough token estimate and wait for a go.51 At/under 8, proceed.524. **Fan out, one reader per subsystem.** Reuse `architecture-audit`'s Map-phase pattern53 (scout + parallel readers via the Workflow tool / subagents). Each reader carries BOTH lenses54 in its brief and is pre-seeded with `seed.json` hints for its subsystem (high-degree nodes,55 dup groups). One reader per subsystem keeps the agent count = subsystem count.56 Each reader returns candidate proposals: `{problem, change, tradeoff, effort, impact, lens,57 affectedNodes[]}`.5859## Step 2 — synthesize & prioritise (Q1)60611. **Dedup & merge** candidate proposals across subsystems (one synthesis pass).622. **Light verify the big ones.** For high-impact proposals, sanity-check the claim against the63 code before committing it to the map (honesty principle — no plausible-but-wrong proposals).64 This is a check, not a second full fan-out.653. **Band each proposal** from its `effort` (S/M/L) × `impact` (low/med/high) — **discrete bands,66 never a numeric score** (we have no telemetry; a number would be false precision):6768 | Band | Condition |69 |------|-----------|70 | ⚡ **quick win** | impact high · effort S |71 | 🎯 **big bet** | impact high · effort M/L |72 | 🧹 **fill-in** | everything else |73 | ⛔ **skip** | impact low · effort L (surfaced, recommended against) |7475## Step 3 — write proposals onto the map7677Each proposal becomes a `proposed` node (the change drawn) + edges to the shipped nodes it78affects. The structured `proposal:{}` object lives on the **proposed** node, never on a shipped79node — a field on a shipped node would be dropped by `merge-map.mjs` on the next audit, whereas80proposed nodes/edges survive re-audit (ADR-013).81821. **Git-snapshot the map FIRST (ADR-011).** Make sure `map.js` is committed (or stash-clean) so83 backout is one `git restore`.842. **Build `proposals.json`** — an array of `{node:{id,label,tech?,engine?,subsystem?},85 proposal:{problem,change,tradeoff,effort,impact,lens}, edges:[{from,to,data}]}`. See helper86 `--selftest` for the exact shape. `id`s must be NEW (a proposed id may not clobber a shipped node).873. **Apply (additive, idempotent):**88 ```bash89 node apply-proposals.mjs <repo>/architecture-map/map.js /tmp/proposals.json > /tmp/map.js \90 && mv /tmp/map.js <repo>/architecture-map/map.js91 ```924. **Refresh the viewer if it predates the proposal panel:**93 `cp ../architecture-map/assets/index.html <repo>/architecture-map/`.9495## Step 4 — report (Q6)9697improve has **no fixed taxonomy** (optimisation is open-ended) — but a fixed proposal shape and98a fixed ordering. Hand the user:99100- A header line: `N proposals — X quick wins, Y big bets`.101- **One plain-language card per proposal** (format:102 `../architecture-cleanup/references/finding-card-and-issues.md` — What it is / Why it is an103 improvement / What you gain / Risk, technical detail folded). Grouped by band104 (⚡ quick wins → 🎯 big bets → 🧹 fill-ins → ⛔ skip). The raw problem/change/tradeoff +105 effort/impact + affected nodes + lens live in the folded Evidence block.106- The open command: `open <repo>/architecture-map/index.html`. A 💡 **Proposals (N)** toggle107 (on by default) rings the proposed nodes amber; clicking one shows the full proposal block.108109## Step 5 — PRD-ready tracker issues (on approval)110111When the user approves proposals (per proposal or per band), convert them to issues in the112project's tracker (Linear, GitHub Issues, Jira — via its workflow skill if you have one).113Structure, sub-issue PRD template (Background/Solution/Acceptance criteria/Risk/Evidence),114estimate/label/priority mapping: all in115`../architecture-cleanup/references/finding-card-and-issues.md`. Parent `Improve: <repo>116(<date>)` + one sub-issue per approved proposal. Draft the whole batch, show the user titles +117estimates, ONE go creates them. Unapproved proposals stay on the map only. This does NOT118change ADR-012: improve still never executes — the issues are the handoff to whoever builds.119120## Cross-skill with cleanup (ADR-014)121122If a `removable` overlay is present, improve **reads it and routes around it**:123124- **Exclude** removable-flagged nodes from the candidate set — don't optimise code already slated125 for deletion. Report: "N nodes skipped (flagged removable by cleanup)".126- Routing **around** or **replacing** a removable node is fine (additive).127- If a proposal would **build on** a removable node, surface the conflict explicitly — never build128 silently on something being deleted.129130## Cost (C3)131132Step 1's seed pass is static/cheap. The fan-out warns on scale (reader count > 8) before firing.133There is no removal/execution cost — improve only proposes.134135## Helpers136137- `apply-proposals.mjs <map.js> <proposals.json>` — additive, idempotent write-back of `proposed`138 nodes/edges + `proposal:{}` objects (ADR-011/013). Validates bands + edge endpoints; throws139 rather than write garbage. `--selftest` to verify.140- Reuses `../architecture-cleanup/analyze-map.mjs` for the deterministic seed signals (degree,141 duplicate-tech, blast-radius). No second analysis helper.142143## Red flags — STOP144145- About to edit source / open a PR / apply a change → don't. improve is proposals-only (C2/ADR-012).146- About to put `proposal` on a shipped node → wrong; it must live on a proposed node (ADR-013).147- About to assign a numeric priority score → wrong; bands only (Q1).148- About to propose a line-level perf tweak or a feature redesign → out of scope (D4).149- About to optimise a node cleanup flagged `removable` → stop; exclude or surface the conflict (ADR-014).150- About to fan out > 8 readers without warning the user → stop, warn first (C3).151- About to create tracker issues without the batch-go → stop (Step 5).152- Report card leads with node-ids/paths instead of plain language → wrong; detail goes in the folded Evidence block.