From 3ded0ec45119789a4858f07510f7c695ba61a8ba Mon Sep 17 00:00:00 2001 From: r Date: Wed, 23 Sep 2026 16:10:29 +0000 Subject: [PATCH] existing-app-change: ask Stage 0 in plain words MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What do you want to work on, do you have input documents, what else does it touch — replaces slice / blast radius in the mode's user-facing text: the skill, intake Q4–Q5, the Stage 0 gate message, the pipeline walk, the routing row and CAC-1's mode table. Migration keeps its own vocabulary. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw --- CHANGELOG.md | 1 + CONVERSION-RUNBOOK.md | 2 +- README.md | 4 +- ROUTING.md | 2 +- agents/architect-agent.md | 2 +- agents/ba-agent.md | 2 +- bin/gate-check.sh | 4 +- bin/lib/intake-template.sh | 17 +++-- bin/lib/skill-routing.tsv | 2 +- docs/pipeline-walks.html | 18 ++--- skills/app-analysis.md | 16 ++--- skills/checkpoints/checkpoint-scope.md | 1 + skills/conversion-runbook.md | 2 +- skills/existing-app-change.md | 91 ++++++++++++++------------ 14 files changed, 91 insertions(+), 73 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ba727d1..b574dd26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ three commits past it), and a bug report can name a release instead of a sha nob Sections dated before 2026-09-19 predate the cycle and stay as they are. ## Unreleased +- docs(existing-app-change): **Stage 0 in the change-an-existing-app mode now asks in plain words.** "What do you want to work on", "do you have input documents", "what else does it touch" replace slice / blast radius in the skill, intake Q4–Q5, the gate message, the pipeline walk and the routing row; migration keeps its own vocabulary — Maurits Visser - new(existing-app-change): **map the app first, ask what to do with the findings, and let a project park until the change is named.** Stage 0 in this mode now opens with the app analysis (`app-facts.sh` + `app-report.sh`, `skills/app-analysis.md`), run without asking since it is read-only and takes about a minute, followed by the question the user owns: fix / log / accept per top finding. Kickoff no longer opens with "which slice?"; the slice and its blast radius (read from the map's tangles and edges, not recomputed) come at Stage 0b, when the change arrives. `artifact-manifest.tsv` owes the map in this mode (`app-report`, Stage 0); gate-check reports a mapped project with no change as Stage 0 `PENDING` instead of a permanent FAIL, and its Stage 1 hint names Path D instead of an extractor. `existing-app-assurance.md` Track A starts from the same report, so an audit that turns into a change does not redo it. Fixture: `test-bug03-gates.sh` T12. Field run: a live client workflow app — 28 modules, one tangle of 7 of 9 own modules, 213 loop microflows, mapped in 76 s; gate-check read it PENDING/parked with 0 needing attention — Maurits Visser - docs(pipeline-walks): **`docs/pipeline-walks.html` — a process diagram per entry mode, with the scripts run at every step.** Shared spine, migration, requirements-driven (incl. the docs-ready fast path), greenfield, change-an-existing-app (opening with the app-mapping step: `SHOW STRUCTURE`, `graph-report`, `lint`, `report`, security matrix, `marketplace diff`), à-la-carte tracks A/A2/B, and the Stage 5 BUILD→GATE→PROVE→LOOK→CONFIRM loop, each as a mermaid flowchart plus a stage/what/scripts table. Linked from the README entry-modes paragraph — Maurits Visser - fix(bin/doctor.sh): **doctor told every Podman user "docker is not installed"** — the section advertised Podman in its advice text ("Rancher Desktop or Podman … are common substitutes") while all four probes ran `docker` only: `docker info`, the `command -v docker` gate, the not-installed warning, and a start hint that said `open -a Docker`. So a machine fully able to run the container lane on Podman, but without the docker shim, was reported broken — and on a team that cannot licence Docker Desktop that reads as "go install software you are not allowed to have" (a colleague's machine-ready status carried "Docker not installed" as a known issue; they may have had Podman all along). Detection is now docker-then-podman (`MXTK_CONTAINER_RUNTIME` forces one), the runtime is **named** in the report (`podman responding — …`), the start hint knows `podman machine start` / `podman.socket`, and the not-installed warning names Podman as the licence-free option instead of implying Docker Desktop is required. Same bounded background/poll/kill probe for both, same 0/1/2 exit contract; `mxcli docker check` invocation deliberately untouched (different repo). **Not field-run** — no container runtime in the authoring container; needs one run on a Mac with Podman and no `docker` on PATH. Driver: the Mendix migration team's Docker Desktop licensing constraint — Maurits Visser diff --git a/CONVERSION-RUNBOOK.md b/CONVERSION-RUNBOOK.md index 710e0e5a..ca339816 100644 --- a/CONVERSION-RUNBOOK.md +++ b/CONVERSION-RUNBOOK.md @@ -22,7 +22,7 @@ Then open your agent (Claude Code or equivalent) in the workspace and say what y | Legacy source code | Migration | P, 0–7 | | Requirements/specs only, no code | Requirements-driven | P, 1–6 | | Just an idea / existing plan | Greenfield | P (light), 5–6 | -| A live Mendix app you are changing | Change an existing app | P, 0–6 per slice | +| A live Mendix app you are changing | Change an existing app | P, 0–6 per change | ## Where you run this — detected, not asked diff --git a/README.md b/README.md index 1528a9e5..d207470e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Serves five ways in — four pipeline entry modes that share the same stages, pl - **Migrations** (legacy source code) — all stages. - **Requirements-driven builds** (specs/BRDs/SME input, no legacy code) — stages 1–6; document discovery replaces source triage, extraction Path B/C replaces code extractors. - **Greenfield mxcli builds** — Stage 5 onward; the standard Mendix build discipline is not migration-specific. -- **Changing an existing app** (a live `.mpr`, a slice being added or altered) — stages P, 0–6 per slice; the knowledge base is queried from the model itself (Path D), a regression net goes under the app first, and Stage 7 is N/A because the app never stops being live. `skills/existing-app-change.md`. +- **Changing an existing app** (a live `.mpr`, a feature or flow being added or altered) — stages P, 0–6 per change; the knowledge base is queried from the model itself (Path D), a regression net goes under the app first, and Stage 7 is N/A because the app never stops being live. `skills/existing-app-change.md`. - **Existing apps — à la carte, no pipeline** — audit, lint, or put a regression/e2e test net under a Mendix app you already have. No intake, no stages, no gates: start at `skills/existing-app-assurance.md` and grab only the tools you need. Used across all mxcli-powered projects — OS migrations, Java/Angular migrations, Node/Express+React migrations, and other client integration work. @@ -532,7 +532,7 @@ Every mxcli project has a `.ai-context/skills/` directory (bundled by `mxcli ini | Stage 0 sign-off when the inventory is at or under 1 module / 8 screens / 25 use cases, or the user says the app is small — declare the tier, then apply its per-stage caps and the three artifact waivers | `skills/small-project-tier.md` | | Generating a new project's CLAUDE.md — baseline routing plus project-specific facts | `skills/bootstrap-project.md` | | Setting up or resuming an mxcli project in a cloud/ephemeral container — the one-time setup order (mxcli download → mxcli init → init-project.sh → sources decision → push) and the commit-and-push loop that survives container reclaim | `skills/cloud-dev-environment.md` | -| Changing an EXISTING Mendix app — adding a feature, altering a flow, restructuring a module — when it has no BRDs, no architecture doc and no wireframes: the knowledge base comes from the live model (Path D), stages 2–4 run over the changed slice plus its blast radius only, and the Track B regression baseline is the precondition; audit-only stays in existing-app-assurance | `skills/existing-app-change.md` | +| Changing an EXISTING Mendix app — adding a feature, altering a flow, restructuring a module — when it has no BRDs, no architecture doc and no wireframes: the knowledge base comes from the live model (Path D), stages 2–4 run over what changes plus what it touches, nothing more, and the Track B regression baseline is the precondition; audit-only stays in existing-app-assurance | `skills/existing-app-change.md` | | Setting up or wiring a COMPANY BRAIN — the private tier between the toolkit and a project for own skills, conventions, lint rules, MDL snippets and approved MPKs; and deciding whether something goes to the toolkit, the company brain or docs/brain/ | `skills/company-brain.md` | | Cutover and retrospective — promoting proven patterns back into the toolkit | `skills/close-the-loop.md` | | Before citing ANY behavioural claim about the harness, the Mendix runtime or a test tool as evidence — a claim not in the register may not be cited | `skills/measured-claims.md` | diff --git a/ROUTING.md b/ROUTING.md index bca5d9ab..6bcf33aa 100644 --- a/ROUTING.md +++ b/ROUTING.md @@ -51,7 +51,7 @@ picks the row up. That is the whole procedure — there is no second list to rem | Deciding who answers a question — before putting any batch to the user. gap/conflict/choice/user-only is what keeps a gate batch at four questions instead of 127 | `bin/question-kinds.sh` | ba | 1,2,3 | baseline | | Generating a new project's CLAUDE.md — baseline routing plus project-specific facts | `skills/bootstrap-project.md` | ba | P | ondemand | | Setting up or resuming an mxcli project in a cloud/ephemeral container — the one-time setup order (mxcli download → mxcli init → init-project.sh → sources decision → push) and the commit-and-push loop that survives container reclaim | `skills/cloud-dev-environment.md` | all | P | ondemand | -| Changing an EXISTING Mendix app — adding a feature, altering a flow, restructuring a module — when it has no BRDs, no architecture doc and no wireframes: the knowledge base comes from the live model (Path D), stages 2–4 run over the changed slice plus its blast radius only, and the Track B regression baseline is the precondition; audit-only stays in existing-app-assurance | `skills/existing-app-change.md` | ba,architect | P,0 | ondemand | +| Changing an EXISTING Mendix app — adding a feature, altering a flow, restructuring a module — when it has no BRDs, no architecture doc and no wireframes: the knowledge base comes from the live model (Path D), stages 2–4 run over what changes plus what it touches, nothing more, and the Track B regression baseline is the precondition; audit-only stays in existing-app-assurance | `skills/existing-app-change.md` | ba,architect | P,0 | ondemand | | Setting up or wiring a COMPANY BRAIN — the private tier between the toolkit and a project for own skills, conventions, lint rules, MDL snippets and approved MPKs; and deciding whether something goes to the toolkit, the company brain or docs/brain/ | `skills/company-brain.md` | all | - | ondemand | | Cutover and retrospective — promoting proven patterns back into the toolkit | `skills/close-the-loop.md` | all | 7 | ondemand | | Before citing ANY behavioural claim about the harness, the Mendix runtime or a test tool as evidence — a claim not in the register may not be cited | `skills/measured-claims.md` | all | - | ondemand | diff --git a/agents/architect-agent.md b/agents/architect-agent.md index 09db2f50..d3be5b8d 100644 --- a/agents/architect-agent.md +++ b/agents/architect-agent.md @@ -52,7 +52,7 @@ You own architecture and build-plan decisions for {{PROJECT}}. Hard rule: you ne | `project-bin/assemble-prototype.js` | After every wireframe edit: assembles design/wireframes/*.html into design/prototype.html, one hash-routed page a stakeholder can click through instead of twenty separate files. Generated, never edited (design-artifacts.md Step 3) | | `project-bin/check-prototype-links.js` | Before wireframes pass to the build loop, and with --brd before a BRD is signed off: dead #/route links, orphan screens, controls with no data-bind and no data-cut, BRD routes no screen has, screens no use case walks (design-artifacts.md Step 3c, brd-validation.md check 8) | | `skills/cloud-dev-environment.md` | Setting up or resuming an mxcli project in a cloud/ephemeral container — the one-time setup order (mxcli download → mxcli init → init-project.sh → sources decision → push) and the commit-and-push loop that survives container reclaim | -| `skills/existing-app-change.md` | Changing an EXISTING Mendix app — adding a feature, altering a flow, restructuring a module — when it has no BRDs, no architecture doc and no wireframes: the knowledge base comes from the live model (Path D), stages 2–4 run over the changed slice plus its blast radius only, and the Track B regression baseline is the precondition; audit-only stays in existing-app-assurance | +| `skills/existing-app-change.md` | Changing an EXISTING Mendix app — adding a feature, altering a flow, restructuring a module — when it has no BRDs, no architecture doc and no wireframes: the knowledge base comes from the live model (Path D), stages 2–4 run over what changes plus what it touches, nothing more, and the Track B regression baseline is the precondition; audit-only stays in existing-app-assurance | | `project-bin/app-facts.sh` | Collecting the facts an app dossier is written from: forces a full catalog build, module edges through the real module column, strongly connected components, describes every loop-containing microflow and parses the loop bodies; exit 2 on a stale, fast-mode or schema-incomplete catalog, never a verdict | | `skills/app-analysis.md` | Building or refreshing the standing dossier of an EXISTING app before changing it: inventory, module dependency shape, loop risk patterns, each section with a verdict and a fault where nothing was measured (a standing document; nothing else in the toolkit reads it yet) | | `skills/layering-review.md` | Checking whether an EXISTING app's module boundaries still hold: the layer map (bin/app-layer-map.sh) computes the order the modules would stack in and draws only the edges that point back up, so one tangle of N mutually reachable modules becomes a named list of edges with a weight and a ref kind; Stage 3 in existing-app-change mode, and the honest blast radius for a slice | diff --git a/agents/ba-agent.md b/agents/ba-agent.md index 04e7b03b..a64df0a1 100644 --- a/agents/ba-agent.md +++ b/agents/ba-agent.md @@ -64,7 +64,7 @@ You run discovery and the interview gates for {{PROJECT}}. You never touch the ` | `bin/brd-report.sh` | Reviewing what the BRDs actually say — the Stage 2 surface, for BRDs from any source. Reads every knowledge base at once, and keeps a section that is absent-because-not-applicable apart from one that is absent-because-expected | | `skills/bootstrap-project.md` | Generating a new project's CLAUDE.md — baseline routing plus project-specific facts | | `skills/cloud-dev-environment.md` | Setting up or resuming an mxcli project in a cloud/ephemeral container — the one-time setup order (mxcli download → mxcli init → init-project.sh → sources decision → push) and the commit-and-push loop that survives container reclaim | -| `skills/existing-app-change.md` | Changing an EXISTING Mendix app — adding a feature, altering a flow, restructuring a module — when it has no BRDs, no architecture doc and no wireframes: the knowledge base comes from the live model (Path D), stages 2–4 run over the changed slice plus its blast radius only, and the Track B regression baseline is the precondition; audit-only stays in existing-app-assurance | +| `skills/existing-app-change.md` | Changing an EXISTING Mendix app — adding a feature, altering a flow, restructuring a module — when it has no BRDs, no architecture doc and no wireframes: the knowledge base comes from the live model (Path D), stages 2–4 run over what changes plus what it touches, nothing more, and the Track B regression baseline is the precondition; audit-only stays in existing-app-assurance | | `skills/app-analysis.md` | Building or refreshing the standing dossier of an EXISTING app before changing it: inventory, module dependency shape, loop risk patterns, each section with a verdict and a fault where nothing was measured (a standing document; nothing else in the toolkit reads it yet) | | `skills/layering-review.md` | Checking whether an EXISTING app's module boundaries still hold: the layer map (bin/app-layer-map.sh) computes the order the modules would stack in and draws only the edges that point back up, so one tangle of N mutually reachable modules becomes a named list of edges with a weight and a ref kind; Stage 3 in existing-app-change mode, and the honest blast radius for a slice | | `skills/assess-migration.md` | Assessing or planning a migration up front, before any pipeline is chosen | diff --git a/bin/gate-check.sh b/bin/gate-check.sh index a902c938..82a2086c 100755 --- a/bin/gate-check.sh +++ b/bin/gate-check.sh @@ -827,9 +827,9 @@ check_stage_0() { elif printf '%s' "$signer" | grep -q '\[' && [ "$ENTRY_MODE" = "existing-app-change" ] \ && [ -s "$PROJECT_DIR/analysis/app-report.json" ]; then # Mapped and waiting for a change is a normal state in this mode (existing-app-change.md - # §"Map the app first"): there is no slice to sign off yet, so this is not-started, not wrong. + # §"Map the app first"): there is nothing to sign off yet, so this is not-started, not wrong. # Without it a parked project read "needs attention" forever (existing-app field run, 2026-09-22). - echo "PENDING|app mapped (analysis/app-report.html), waiting on the change — triage.md is signed off at Stage 0b, once the user names the slice and its blast radius is written ($f, ## Sign-off)" + echo "PENDING|app mapped (analysis/app-report.html), waiting on the change — triage.md is signed off at Stage 0b, once the user says what to work on and what it touches is written ($f, ## Sign-off)" elif printf '%s' "$signer" | grep -q '\['; then echo "FAIL|'Confirmed by:' still holds the shipped placeholder: \"$signer\" — replace it with whatever the user actually said (\"confirmed in chat 2026-08-20\" is fine; a full name is not required) ($f, ## Sign-off)" else diff --git a/bin/lib/intake-template.sh b/bin/lib/intake-template.sh index d3fd2b0e..a6243275 100644 --- a/bin/lib/intake-template.sh +++ b/bin/lib/intake-template.sh @@ -69,17 +69,24 @@ _Not yet asked._ Default inherited from Q2 — (b) implies as-is, (c) licenses r put the inherited default to the user and ask what to override. This decides whether every Stage 3 fit-gap finding is a gap to close or an opportunity to take. -## 4. Scope boundary: the whole application, or a slice? +## 4. What are we working on: the whole application, or a part of it — and what else does that touch? -_Not yet asked._ Name what is explicitly OUT, not just what is in — "out" is the half that +_Not yet asked._ Name the topic in plain words — a feature, a flow, a module, a fix, or the +whole app. Say what else it touches, and name what is explicitly OUT — "out" is the half that gets forgotten and rebuilt anyway. A module-sized source is the common case and is easy to -mistake for a whole app; if it is a slice, say what the slice must keep working with. +mistake for a whole app. Also ask whether there are input documents — user stories, tickets, +a spec: they go in `sources/`, and "none, the app plus my description" is a fine answer. For +an existing app this is settled at Stage 0b, after the map, so +`Unverified — how to verify: named when the change request arrives (Stage 0b)` is a legitimate +kickoff answer. -## 5. What must NOT change? +## 5. Of what we touch, what must stay exactly as it is? _Not yet asked._ Integrations, data contracts, external URLs, scheduled jobs, reports other systems consume. These are the constraints that invalidate an architecture late and cheaply -if found now; they are rarely visible in the source, because they live in its consumers. +if found now; they are rarely visible in the source, because they live in its consumers. For +an existing app the default is that nothing beyond the ask changes — this question names the +things the change must not break. ## 6. Are there licence/security constraints on storing this client's source in this workspace? diff --git a/bin/lib/skill-routing.tsv b/bin/lib/skill-routing.tsv index 9a63104f..44876f15 100644 --- a/bin/lib/skill-routing.tsv +++ b/bin/lib/skill-routing.tsv @@ -112,7 +112,7 @@ mxcli-bugs bug-logs/mxcli-bugs.md Reading a whole class of tool defects (a retes bootstrap-project skills/bootstrap-project.md Generating a new project's CLAUDE.md — baseline routing plus project-specific facts ba P ondemand spine cloud-dev-environment skills/cloud-dev-environment.md Setting up or resuming an mxcli project in a cloud/ephemeral container — the one-time setup order (mxcli download → mxcli init → init-project.sh → sources decision → push) and the commit-and-push loop that survives container reclaim all P ondemand spine existing-app-assurance skills/existing-app-assurance.md Auditing or regression/e2e-testing an EXISTING app — no intake, no stages, no gates test,review 6 ondemand verify -existing-app-change skills/existing-app-change.md Changing an EXISTING Mendix app — adding a feature, altering a flow, restructuring a module — when it has no BRDs, no architecture doc and no wireframes: the knowledge base comes from the live model (Path D), stages 2–4 run over the changed slice plus its blast radius only, and the Track B regression baseline is the precondition; audit-only stays in existing-app-assurance ba,architect P,0 ondemand spine +existing-app-change skills/existing-app-change.md Changing an EXISTING Mendix app — adding a feature, altering a flow, restructuring a module — when it has no BRDs, no architecture doc and no wireframes: the knowledge base comes from the live model (Path D), stages 2–4 run over what changes plus what it touches, nothing more, and the Track B regression baseline is the precondition; audit-only stays in existing-app-assurance ba,architect P,0 ondemand spine app-facts project-bin/app-facts.sh Collecting the facts an app dossier is written from: forces a full catalog build, module edges through the real module column, strongly connected components, describes every loop-containing microflow and parses the loop bodies; exit 2 on a stale, fast-mode or schema-incomplete catalog, never a verdict architect,review 0,6 ondemand architecture app-analysis skills/app-analysis.md Building or refreshing the standing dossier of an EXISTING app before changing it: inventory, module dependency shape, loop risk patterns, each section with a verdict and a fault where nothing was measured (a standing document; nothing else in the toolkit reads it yet) ba,architect,review P,0,6 ondemand architecture layering-review skills/layering-review.md Checking whether an EXISTING app's module boundaries still hold: the layer map (bin/app-layer-map.sh) computes the order the modules would stack in and draws only the edges that point back up, so one tangle of N mutually reachable modules becomes a named list of edges with a weight and a ref kind; Stage 3 in existing-app-change mode, and the honest blast radius for a slice architect,ba 0,3 ondemand architecture diff --git a/docs/pipeline-walks.html b/docs/pipeline-walks.html index 7e390a8b..dbd31540 100644 --- a/docs/pipeline-walks.html +++ b/docs/pipeline-walks.html @@ -244,7 +244,7 @@

Greenfield Just an idea, or a running s

Change an existing app A live .mpr you are altering, not rebuilding

-

The knowledge base comes from the model itself (Path D). The first real step is mapping the whole app, run without asking, followed by the one question the user owns: what to do with each top finding. The project may park there until a change is named; Stage 0b then adds the blast radius of the slice, read from the map. A regression net goes under the app before anything changes, and every gate from Stage 5 on is also a regression gate.

+

The knowledge base comes from the model itself (Path D). The first real step is mapping the whole app, run without asking, followed by the one question the user owns: what to do with each top finding. The project may park there until a change is named; Stage 0b then asks what the user wants to work on, whether there are input documents, and what else it touches, read from the map. A regression net goes under the app before anything changes, and every gate from Stage 5 on is also a regression gate.

 flowchart TD
   P["P Kickoff light
./mxcli in place, then init-project.sh
open question: what is driving it?
register: Change an existing app CONFIRMED"] --> M["0a Map the app, not asked, just run
bin/app-facts.sh then bin/app-report.sh
(app-analysis.md, about a minute)"] @@ -254,18 +254,18 @@

Change an existing app A live .mpr yo PARK -.->|change arrives| S0 PK -- "only audits / tests wanted" --> AS["switch to existing-app-assurance
Track A starts from the same report"] PK -- "yes" --> S0 - S0["0b Triage ✋ which slice,
what is its blast radius"] --> S0a["blast radius into triage.md, read from the map:
dependencies.json tangles and edges,
then associations, SEARCH, SHOW PAGES IN,
published / consumed services"] + S0["0b Scope ✋ what do you want to work on,
what else does it touch"] --> S0a["what it touches into triage.md, read from the map:
dependencies.json tangles and edges,
then associations, SEARCH, SHOW PAGES IN,
published / consumed services"] S0a --> S0b["capability map from SHOW MODULES
extraction rows N/A
CAC-1, sign-off"] S0b --> RN["Regression net under the app
Track B baseline from existing-app-assurance"] - RN --> S1["1 Analysis Path D
DESCRIBE ENTITY, SHOW MICROFLOWS IN,
graph-report scoped to slice + blast radius
counts recorded, Path A = N/A, CAC-1b"] - S1 --> S2["2 Requirements
slice-only BRDs, as-is / to-be
CAC-2, CAC-3"] + RN --> S1["1 Analysis Path D
DESCRIBE ENTITY, SHOW MICROFLOWS IN,
graph-report scoped to the change + what it touches
counts recorded, Path A = N/A, CAC-1b"] + S1 --> S2["2 Requirements
BRDs for what changes only, as-is / to-be
CAC-2, CAC-3"] S2 --> Q{"crosses a module boundary,
adds an integration,
alters the domain model?"} Q -- "yes" --> S3["3 Architecture and Design ✋ in full
wireframes for changed screens only
design system = captured existing styling"] Q -- "no" --> S3b["3 collapses to:
which existing module owns this"] S3 --> S4 - S3b --> S4["4 Build Plan ✋ slice only
respects live data
coverage ledger = mxcli brain plan
CAC-5, build-ready"] + S3b --> S4["4 Build Plan ✋ what changes only
respects live data
coverage ledger = mxcli brain plan
CAC-5, build-ready"] S4 --> S5["5 Build
module loop + regression net must stay green
mxcli brain capture per leaf"] - S5 --> S6["6 Test
slice journeys + full regression suite"] + S5 --> S6["6 Test
journeys of the change + full regression suite"] S6 --> S7["7 Cutover N/A: the app is live"] classDef stop fill:#f8dedb,stroke:#b3261e,color:#1d2430 class S0,S3,S4 stop @@ -278,12 +278,12 @@

Change an existing app A live .mpr yo StepWhat it doesScripts and commands P lightScaffold. Intake answers come from the model, not from the user's memory. Run the machine check once.bin/doctor.sh
bin/init-project.sh <project> 0a Map the appRun, do not ask: it is read-only and takes about a minute. Inventory, module tangles, loop-risk microflows, dead elements, with a fix-first list. Show the report and ask the user to disposition each top finding (fix in this work / log / accept); answers go to PROJECT.md. The project may then park until a change is named. Owed in this mode as the app-report artifact. Lint, security matrix and marketplace drift fill the report's Security and Lint sections.bin/app-facts.sh (app-analysis.md)
bin/app-report.sh <project>
./mxcli lint -p app.mpr
./mxcli -p app.mpr -c "SHOW SECURITY MATRIX"
./mxcli marketplace diff <content-id> -p app.mpr (v0.18+) - 0b Triage ✋Once the change is named: which slice, and what is its blast radius, starting from the map's tangles and edges. The radius is written into triage.md as its own section, with counts. Capability map from the module list. CAC-1 and sign-off.SHOW ASSOCIATIONS IN <Module> · DESCRIBE ENTITY M.E
SEARCH '<entity>' · SHOW PAGES IN <Module>
SHOW REFERENCES OF M.E · SHOW IMPACT OF M.E
analysis/app-facts/dependencies.json for the tangle
bin/gate-check.sh <project> 0 + 0b Scope ✋Once the change is named: what do you want to work on, do you have input documents, and what else does it touch — starting from the map's tangles and edges. What it touches is written into triage.md as its own section, with counts. Capability map from the module list. CAC-1 and sign-off.SHOW ASSOCIATIONS IN <Module> · DESCRIBE ENTITY M.E
SEARCH '<entity>' · SHOW PAGES IN <Module>
SHOW REFERENCES OF M.E · SHOW IMPACT OF M.E
analysis/app-facts/dependencies.json for the tangle
bin/gate-check.sh <project> 0 Regression netTrack B from the assurance skill, before any change: harness, action inventory, one journey per action, DB assertions, wiring sweep, LOOK pass, committed baseline.see Track B below
project-bin/coverage-preflight.sh --assess --module <M> - 1 Path DQuery the model into the knowledge base, scoped to slice plus blast radius. Record counts. Path A declared N/A with attribution. Path C matters most here: the people who know why the app is the way it is.SHOW ENTITIES IN · DESCRIBE ENTITY · SHOW MICROFLOWS IN
DESCRIBE MICROFLOW · DESCRIBE PAGE
bin/extraction-report.sh <project>
bin/gate-check.sh <project> 1 + 1 Path DQuery the model into the knowledge base, scoped to the change plus what it touches. Record counts. Path A declared N/A with attribution. Path C matters most here: the people who know why the app is the way it is.SHOW ENTITIES IN · DESCRIBE ENTITY · SHOW MICROFLOWS IN
DESCRIBE MICROFLOW · DESCRIBE PAGE
bin/extraction-report.sh <project>
bin/gate-check.sh <project> 1 2 RequirementsOne as-is / to-be BRD per capability being changed. Nothing for the untouched rest.bin/brd-report.sh · bin/open-questions.sh --stage 2 3 DesignFull only when the change crosses a module boundary, adds an integration or alters the domain model. Otherwise "which module owns this". Wireframes for changed screens only.bin/gate-check.sh <project> 3 - 4 Build plan ✋Slice-only plan that respects live data. Coverage ledger lives in the brain, not a hand-kept file../mxcli brain init · ./mxcli brain plan
bin/gate-check.sh <project> build-ready + 4 Build plan ✋Plan for what changes only, that respects live data. Coverage ledger lives in the brain, not a hand-kept file../mxcli brain init · ./mxcli brain plan
bin/gate-check.sh <project> build-ready 5–6Module loop unchanged. Every gate also re-runs the regression net. Each finished leaf is captured in the brain.bin/exec.sh s.mdl · project-bin/verify-module.sh <M>
./mxcli brain capture "<leaf>" · ./mxcli brain check 7N/A in the register: the app is already live.register line only

diff --git a/skills/app-analysis.md b/skills/app-analysis.md index ad213ff4..f633826d 100644 --- a/skills/app-analysis.md +++ b/skills/app-analysis.md @@ -1,7 +1,7 @@ # Skill: app-analysis — a standing dossier of an existing app before you change it **Use when:** you are handed an app you did not build (inheritance, takeover, review, -"continue development on this"), before the first change slice and again at every milestone. +"continue development on this"), before the first change and again at every milestone. The output is `architecture/app-dossier.md`, a document the team keeps, plus an HTML render of it for people who will not open a repository. @@ -89,7 +89,7 @@ Use the toolkit verdict vocabulary (`skills/report-schema.md`): | status | meaning here | |---|---| | `pass` | collected, judged, nothing above threshold, or every finding has a disposition that is a decision | -| `fail` | collected, judged, at least one finding above threshold without a decision (`later` with no slice or date, `undecided`, or a missing line all count as no decision) | +| `fail` | collected, judged, at least one finding above threshold without a decision (`later` with no named change or date, `undecided`, or a missing line all count as no decision) | | `fault` | not collected, or collected but not trustworthy (partial describe, parse mismatch above `MAX_PARSE_MISMATCH_PCT`) | | `manual` | collected, but the verdict needs a person (dead elements, every "accepted" disposition) | | `skipped` | deliberately not run this time, with the reason in the summary row | @@ -250,7 +250,7 @@ verdict stands; the dossier only quotes it). Automating both is tracked in the C asset type, and the top 20 modules by count. Do not list every asset. Always `manual` until a dead-element instrument exists: the catalog cannot see Java code, published REST operations called by name, or workflow references, so "no inbound reference" is a candidate, not a -verdict. Confirm each in Studio Pro ("Find usages") before it reaches a change slice. +verdict. Confirm each in Studio Pro ("Find usages") before it reaches a change. Every finding table in sections 3 and 4 carries a **severity** column, first, with the score in brackets, and is sorted worst first. Write the id in backticks and the target name in brackets @@ -259,10 +259,10 @@ renderer matches a decision to the finding it scored, and an unmatched decision undecided finding on the page. **8. Dispositions.** One line per finding: ` · · - · `. Finding ids come from the companion skills (`DEP-CYCLE-01`, -`LOOP-DB-014`, and so on). It is where the team's decisions live, and a refresh never -rewrites it; that is what makes the dossier a standing document and not a report. -A `later` is a decision only with a slice or a date; `later, undecided` is a placeholder and + · `. Finding ids come from the companion skills +(`DEP-CYCLE-01`, `LOOP-DB-014`, and so on). It is where the team's decisions live, and a +refresh never rewrites it; that is what makes the dossier a standing document and not a report. +A `later` is a decision only with a named change or a date; `later, undecided` is a placeholder and leaves the section `fail`. Ids are never reused or deleted: a finding that stops existing (module reclassified, loop removed) keeps its line, marked `closed : `. @@ -300,7 +300,7 @@ decided otherwise. - `skills/module-dependency-review.md`, `skills/microflow-loop-antipatterns.md` (the judgement) - `skills/existing-app-assurance.md` (the à-la-carte audit this dossier is the map for) - `skills/existing-app-change.md` — **wired 2026-09-22.** Its Stage 0a runs this procedure before any - slice is named, asks the user to disposition the top findings, and reads the blast radius for Stage + change is named, asks the user to disposition the top findings, and reads the blast radius for Stage 0b from `analysis/app-facts/dependencies.json`. In that mode `bin/lib/artifact-manifest.tsv` owes the report (`app-report`, Stage 0), so a map nobody ran reports PENDING. `existing-app-assurance.md` Track A starts from the same report. What is still NOT wired: the dossier itself diff --git a/skills/checkpoints/checkpoint-scope.md b/skills/checkpoints/checkpoint-scope.md index e958c282..4011c0ad 100644 --- a/skills/checkpoints/checkpoint-scope.md +++ b/skills/checkpoints/checkpoint-scope.md @@ -20,6 +20,7 @@ What varies is only where the capability map comes from: | Migration | `triage.md`'s Business Capability Map, from the codebase. | | Requirements-driven | The same table in `triage.md`, built from the document corpus and any DB schema — `document-discovery.md` and `bin/source-sufficiency.sh`'s pass-1 inventory feed it. A spec pack has capabilities exactly like a codebase does. | | Greenfield | There is no corpus. Run the brainstorm anyway, off the user's own description, and record the result — it is the only scope statement the project will have. | +| Change an existing app | The app map (`analysis/app-report.json`, run at Stage 0a) plus the user's own answers to *what do you want to work on* and *do you have input documents*. The brainstorm is about what the change touches, not about ordering the whole app. | **Do not skip the brainstorm because the map was easy to build.** A short capability list makes the conversation faster, not unnecessary. diff --git a/skills/conversion-runbook.md b/skills/conversion-runbook.md index a4b69b58..eadca9e7 100644 --- a/skills/conversion-runbook.md +++ b/skills/conversion-runbook.md @@ -125,7 +125,7 @@ The stages are the same for everyone; what differs is where you enter and which | **Legacy source code** (± docs, ± SME) | **Migration** | P, 0–7 (all) | The default everything below describes. Path A (code extractors) always runs. | | **Requirements only** — BRDs, specs, workshop outputs, wireframes; no legacy code | **Requirements-driven** | P, 0–6 (skip 7) | Stage 0 runs. `document-discovery.md` runs over the whole corpus for the inventory, **and** the extraction call runs per extractable structure inside it — a schema, a table dump, a data export or entity tables in a spec each get one; `N/A` is earned on evidence, never on the mode label (`source-triage.md` owns that rule — see "Stage 0 runs in every entry mode" below). Stage 1 runs Path B (`kb-generation.md`) + Path C (SME) only; Path A is declared not-applicable, not "skipped". Stages 2–6 run unchanged — BRDs come from documents instead of extraction. Stage 7 only if legacy data exists somewhere to cut over. **A text-native corpus — Markdown and HTML pages, no legacy code, no Office/PDF containers — takes the docs-ready fast path below.** | | **Just an idea / a running start on the model** | **Greenfield** | P (light), 0 (scope only), 5–6 | Stages 1–4 collapse to whatever plan the user already has. Stage 0 does **not** collapse: with no corpus there is nothing to grade, but the scope conversation is exactly as load-bearing as it is anywhere else, so Stage 0 reduces to CAC-1's brainstorm and its sign-off. If you find yourself inventing requirements mid-build, you're actually in requirements-driven mode — back up to Stage 2. | -| **A live Mendix app you are changing** — a slice is being added or altered, the rest stays as it is | **Change an existing app** | P, 0–6 per slice (skip 7 — the app is live) | `existing-app-change.md` owns the mode. Stage 1 runs **Path D** — `mxcli` queries the `.mpr` into the knowledge base, scoped to the slice **plus its blast radius**, which Stage 0 writes into `triage.md` as its own section. A regression net (Track B baseline) goes under the app before anything changes. Stages 2–4 run over the slice only: one as-is/to-be BRD per capability being changed, Stage 3 in full only when the change crosses a module boundary, adds an integration or alters the domain model — otherwise it collapses to "which existing module owns this". Stage 7 is N/A in the register with that reason. The coverage ledger is `mxcli brain plan`, not a hand-kept file. | +| **A live Mendix app you are changing** — a feature or flow is being added or altered, the rest stays as it is | **Change an existing app** | P, 0–6 per change (skip 7 — the app is live) | `existing-app-change.md` owns the mode. Stage 1 runs **Path D** — `mxcli` queries the `.mpr` into the knowledge base, scoped to the change **plus what it touches**, which Stage 0 writes into `triage.md` as its own section. A regression net (Track B baseline) goes under the app before anything changes. Stages 2–4 run over the change only: one as-is/to-be BRD per capability being changed, Stage 3 in full only when the change crosses a module boundary, adds an integration or alters the domain model — otherwise it collapses to "which existing module owns this". Stage 7 is N/A in the register with that reason. The coverage ledger is `mxcli brain plan`, not a hand-kept file. | ### Stage 0 runs in every entry mode diff --git a/skills/existing-app-change.md b/skills/existing-app-change.md index bce3e7d2..9f3774d1 100644 --- a/skills/existing-app-change.md +++ b/skills/existing-app-change.md @@ -5,7 +5,7 @@ document and no wireframes, that you now need to change. **Requires:** the app's `.mpr`, a runnable local environment, bash and Python 3. Run `bin/doctor.sh` once on a new machine. Windows: Git Bash, and see `conversion-runbook.md` → Prerequisites. **Purpose:** The recipe for changing an app the pipeline never built. The knowledge base comes from -**the model itself**, not from an extractor, and stages 2–4 run over the **slice you are changing** — +**the model itself**, not from an extractor, and stages 2–4 run over **the change you are making** — not over the whole application. **Source:** Field run #1, 2026-08-20. The three entry modes all assume the target app does not exist yet, and the classification rules sent an existing `.mpr` to Migration — i.e. to migrating the app to @@ -31,9 +31,9 @@ that loop. | A brand-new app | `conversion-runbook.md` → Requirements-driven or Greenfield | | A one-line fix you would not open a ticket for | Just do it. This skill is overhead for a typo. | -The line between "a change" and "a new app inside an old one" is scope, and Stage 0 draws it. If the -slice turns out to be most of the app, you are in Migration mode with a Mendix source — say so and -switch. +The line between "a change" and "a new app inside an old one" is scope, and Stage 0 draws it. If what +you're working on turns out to be most of the app, you are in Migration mode with a Mendix source — +say so and switch. --- @@ -49,11 +49,11 @@ your change touches. Skip it and you have no way to tell a bug you introduced from behaviour that was always like that. That is the entire risk of this entry mode, concentrated in one decision. -**2. The slice is the unit of work, not the app.** +**2. The change is the unit of work, not the app.** You are not writing BRDs for a five-year-old application. You are writing them for what changes, plus what that change touches. Everything downstream — the ledger denominator, the coverage claim, the -gates — is scoped to the slice. A coverage number that silently means "of the slice" while reading +gates — is scoped to the change. A coverage number that silently means "of the change" while reading like "of the app" is the false-green this toolkit keeps producing; say which one you mean, every time. **3. The model is ground truth. Memory and the UI are not.** @@ -69,12 +69,12 @@ from git history of a `.mpr`, which is not a readable record. --- -## Map the app first — before anyone names a slice +## Map the app first — before anyone says what to work on -**Do not open with "which slice?".** At kickoff most people do not know the change yet, or know it -vaguely ("the approval flow is slow"), and a slice named before anyone has seen the app is a guess. +**Do not open with "what is the scope?".** At kickoff most people do not know the change yet, or know +it vaguely ("the approval flow is slow"), and a scope named before anyone has seen the app is a guess. Intake Q2 (*what is driving it?*) is the open question, and a change, if they have one, arrives in -their own words there or later. Q4 (scope) may legitimately be answered +their own words there or later. Q4 (what are we working on) may legitimately be answered `Unverified — how to verify: named when the change request arrives (Stage 0b)`. **Stage 0a — the map, not asked for, just run.** It is read-only and costs about a minute (field @@ -99,8 +99,17 @@ reports Stage 1 `PENDING` with "Waiting on the change is a normal state", and no the map the user never wants a change, only audits or a regression net, the mode was wrong: switch to `existing-app-assurance.md`, whose Track A starts from the same report. -**Stage 0b — when the change arrives:** scope the slice, then compute its blast radius *from the facts -already collected* (below), not from scratch. +**Stage 0b — when the change arrives:** ask three plain questions, in this order. + +1. **What do you want to work on?** A feature, a change, a fix — the topic, in the user's own words. +2. **Do you have input documents?** User stories, tickets, a spec — drop them in `sources/` and say + so; "none, the app plus my description" is a fine answer. +3. **What else does it touch?** The agent computes this from the app map already collected (below — + `analysis/app-facts/dependencies.json` tangles and edges) and the user confirms; this is what the + skill used to call the blast radius. + +And the standing question, asked alongside: **of what we touch, what must stay exactly as it is?** +Default for an existing app: nothing beyond the ask changes. --- @@ -133,31 +142,31 @@ Still record the counts. `SHOW MODULES` returning 6 when the person who asked fo --- -## Blast radius — the question Stage 0 exists to answer here +## What the change touches — the question Stage 0 exists to answer here In every other mode, Stage 0 asks *what do we build first*. Here it asks a second question that has no equivalent elsewhere: **what does this change touch that nobody mentioned?** Work outward from the entities the change affects. Start from the map (Stage 0a): a module in -`analysis/app-facts/dependencies.json` → `tangles` puts the whole tangle in the radius, and `edges` -names who depends on the module you change. The queries below confirm and extend that; they do not -repeat it. +`analysis/app-facts/dependencies.json` → `tangles` puts the whole tangle in what it touches, and +`edges` names who depends on the module you change. The queries below confirm and extend that; they +do not repeat it. 1. **Associations** — `SHOW ASSOCIATIONS`, then `DESCRIBE ENTITY` each end. An entity you are changing - that is on the far end of an association from a module nobody mentioned is your blast radius. + that is on the far end of an association from a module nobody mentioned is part of what it touches. 2. **Microflows that read or write those entities** — `SEARCH` for the entity name across microflows. A change to a validation rule lands in every flow that writes the entity, not only the one on the screen you were shown. 3. **Pages bound to them** — `SHOW PAGES IN `, and check which are bound to the entity. 4. **Module dependencies** — already in the map (`dependencies.json`); rerun `bin/app-facts.sh` only - if the model changed since. If the module you are changing is in a tangle, the blast radius is the - tangle. + if the model changed since. If the module you are changing is in a tangle, the whole tangle is what + it touches. 5. **Published and consumed services** — a changed entity behind a published REST service is a contract change, and the consumer is not in the `.mpr`. -**Write the blast radius into `triage.md` as its own section and get it confirmed.** It is the single -most valuable output of Stage 0 in this mode, and it is the thing the person requesting the change is -least able to give you — they know what they want, not what it touches. +**Write what the change touches into `triage.md` as its own section and get it confirmed.** It is the +single most valuable output of Stage 0 in this mode, and it is the thing the person requesting the +change is least able to give you — they know what they want, not what it touches. --- @@ -165,12 +174,12 @@ least able to give you — they know what they want, not what it touches. | Stage | Runs? | What changes in this mode | |---|---|---| -| **P — Kickoff** | Yes, light | `bin/init-project.sh` as normal — **with `./mxcli` already in the project root**, because init runs `mxcli init` and skips it when the binary is missing. Many intake questions are already answered by the app existing — answer them from the model, not by asking. The scope question is open: the change may not be known yet. Record entry mode `Change an existing app` `CONFIRMED` in `PROJECT.md`. | -| **0 — Triage & Scope ✋** | **Yes, always, in two halves** | **0a:** map the app and disposition its findings with the user (above) — owed as the `app-report` artifact. May park here. **0b**, once the change is named: which slice, and its blast radius (above), read from the map. The Coverage Matrix's *extraction* rows are N/A — Path D has no extractor to choose. The Business Capability Map is built from `SHOW MODULES` + the change request. **CAC-1 runs.** | -| **1 — Analysis** | Yes, **Path D** | Query the model into the knowledge base, scoped to the slice **plus** its blast radius. Path A is declared not-applicable with attribution, not "skipped". Path C (SME) matters more here than anywhere: the model tells you what the app does and nobody wrote down why. **CAC-1b runs** — its scope-out diff is the slice-vs-app statement. | -| **2 — Requirements** | Yes, **slice only** | One BRD per capability *being changed*, each carrying **as-is** and **to-be**. Do not BRD untouched capabilities; record explicitly that you did not, and why. **CAC-2 and CAC-3 run.** | +| **P — Kickoff** | Yes, light | `bin/init-project.sh` as normal — **with `./mxcli` already in the project root**, because init runs `mxcli init` and skips it when the binary is missing. The app itself answers Q1 and, in part, Q4 — propose those answers from the model and ask the user to confirm; the rest are asked. A `CONFIRMED` mark is earned by the user answering, never by the agent filling the line in. The scope question is open: the change may not be known yet. Record entry mode `Change an existing app` `CONFIRMED` in `PROJECT.md`. | +| **0 — Triage & Scope ✋** | **Yes, always, in two halves** | **0a:** map the app and disposition its findings with the user (above) — owed as the `app-report` artifact. May park here. **0b**, once the change is named: three plain questions — what do you want to work on, do you have input documents (in `sources/`, or none), and what else does it touch (above, read from the map). The Coverage Matrix's *extraction* rows are N/A — Path D has no extractor to choose. The Business Capability Map is built from `SHOW MODULES` + the change request. **CAC-1 runs.** | +| **1 — Analysis** | Yes, **Path D** | Query the model into the knowledge base, scoped to the change **plus** what it touches. Path A is declared not-applicable with attribution, not "skipped". Path C (SME) matters more here than anywhere: the model tells you what the app does and nobody wrote down why. **CAC-1b runs** — its scope-out diff is the change-vs-app statement. | +| **2 — Requirements** | Yes, **the change only** | One BRD per capability *being changed*, each carrying **as-is** and **to-be**. Do not BRD untouched capabilities; record explicitly that you did not, and why. **CAC-2 and CAC-3 run.** | | **3 — Architecture & Design ✋** | **Conditionally** | Run it in full if the change crosses module boundaries, adds an integration, or alters the domain model. Otherwise it collapses to: which existing module owns this, and does that still hold. **Never invent new module boundaries for an app that already has them** — `modularize-domain.md` is being used to *check* a boundary here, not to draw one. Wireframes only for screens that change; the design system is the app's existing styling, captured, not designed. **CAC-4 runs, scoped to what changes.** | -| **4 — Build Plan ✋** | Yes, **slice only** | `brd-to-build-plan.md` as normal, over the slice's BRDs. Ordering must respect what already exists: you cannot stub an entity that is live and has data in it. **CAC-5 runs.** | +| **4 — Build Plan ✋** | Yes, **the change only** | `brd-to-build-plan.md` as normal, over the change's BRDs. Ordering must respect what already exists: you cannot stub an entity that is live and has data in it. **CAC-5 runs.** | | **5–6 — Build & Verify** | Yes, unchanged | `iterative-build-loop.md`, the STOP table, module briefs, gates. Plus the rule below. | | **7 — Cutover** | **N/A** | There is no legacy system to cut over from. Mark it N/A in the register with that reason — an unstated skip and a settled one are different things, which is the whole reason the register exists. | @@ -193,21 +202,21 @@ end — a regression found three modules later costs the same to fix and much mo ## Coverage in this mode The ledger in this mode is `mxcli brain plan`, not a hand-kept `coverage-ledger.md`. Each BRD leaf -is captured as a requirement of the slice with a **forward** anchor at the element that will -satisfy it: +is captured as a requirement of the change with a **forward** anchor at the element that will +satisfy it — `mxcli brain capture`'s own name for this unit is still "slice", passed as `--slice`: ```bash mxcli brain capture "Admins can archive a user group from the overview" \ --slice 03-usergroups-archive -a @UserGroups.ACT_UserGroup_Archive -p app.mpr ``` -`brain plan` then reports `BUILT n · PLANNED m` per slice, derived by resolving those anchors -against the model. There is no status column to update and none to go stale; building the thing -is what moves the number. The denominator is the slice by construction, because the slice *is* -the shard. +`brain plan` then reports `BUILT n · PLANNED m` per slice (mxcli's own term for the unit), +derived by resolving those anchors against the model. There is no status column to update and +none to go stale; building the thing is what moves the number. The denominator is the change by +construction, because the change *is* the shard. -That does not remove the duty to say what is **not** claimed. Put it in the slice's first entry, -in these terms: *"N requirements covering the click-and-collect change and its blast radius. The +That does not remove the duty to say what is **not** claimed. Put it in the change's first entry, +in these terms: *"N requirements covering the click-and-collect change and what it touches. The remaining 14 modules of this app have no requirements here and are not claimed by this plan."* `BUILT 12 · PLANNED 0` without that sentence tells the reader the app is fully specified, and it is not. @@ -221,12 +230,12 @@ it is the only entry mode where that is true. ## Deliverables -- `PROJECT.md` — gate register: entry mode `Change an existing app` `CONFIRMED`, blast radius confirmed, Stage 7 marked N/A with its reason. -- `docs/brain/` — `mxcli brain init` run once; the slice under `plan/`, and the as-is facts nobody wrote down captured as decisions anchored to the modules they are about. `brain check` green at every commit. +- `PROJECT.md` — gate register: entry mode `Change an existing app` `CONFIRMED`, what the change touches confirmed, Stage 7 marked N/A with its reason. +- `docs/brain/` — `mxcli brain init` run once; the change under `plan/` (mxcli's own `--slice` unit), and the as-is facts nobody wrote down captured as decisions anchored to the modules they are about. `brain check` green at every commit. - `analysis/app-report.html` + `.json` — the map of the whole app (`app-analysis.md`), with every top finding dispositioned in `PROJECT.md`. -- `triage.md` — slice + blast radius, signed off. -- Knowledge base — Path D, scoped, with counts recorded: modules, and per in-scope module the entity, page and microflow totals `SHOW …` returned, so a reader can see the slice against the app. -- BRDs for the changed slice, each with as-is and to-be — and one line saying how many capabilities were *not* BRD'd and why. -- A build plan over the slice. +- `triage.md` — the change plus what it touches, signed off. +- Knowledge base — Path D, scoped, with counts recorded: modules, and per in-scope module the entity, page and microflow totals `SHOW …` returned, so a reader can see the change against the app. +- BRDs for the change, each with as-is and to-be — and one line saying how many capabilities were *not* BRD'd and why. +- A build plan over the change. - **A regression baseline that was green before the change and is green after it** — stated as N journeys over M modules, re-run at every module gate. Without this the rest is unverified. - Anything reusable learned about the app → `skills/learned-*.md`; process learnings → `process/process-learnings.md`.