From 034b0b30fb2f99c507d7a3478e31e67e0e024269 Mon Sep 17 00:00:00 2001 From: MendixMau Date: Fri, 16 Oct 2026 17:53:05 +0800 Subject: [PATCH 1/5] process(change-intake): CRs update the module brief and stay visible until built The BRD stays the source of truth; a CR touching a module's build steps, screens, access or rules gets a CR-tagged Build steps row, every CR that adds work gets a build-plan row, and agreed unbuilt CRs are "waiting" (RESUME.md Waiting changes line). exec.sh --cr CR-NN warns (never blocks) when the module brief lacks the id. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + bin/lib/resume-template.sh | 5 ++ project-bin/exec.sh | 32 ++++++- skills/change-intake-detail.md | 8 +- skills/change-intake.md | 40 ++++----- skills/close-the-loop.md | 9 +- tests/wave2/test-exec-cr-brief-warn.sh | 113 +++++++++++++++++++++++++ 7 files changed, 175 insertions(+), 33 deletions(-) create mode 100755 tests/wave2/test-exec-cr-brief-warn.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aa535dc..a0fa6a01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. Named m ## Unreleased +- process(change-intake): **a change request now updates the module brief and stays visible until it is built.** The rule "most BRD edits need no brief edit" let a CR on a closed module leave the brief's Build steps stale, so `context-pack.sh` had no row for it and nothing counted it. Now the BRD stays the source of truth, the brief gets a CR-tagged Build steps row for any CR touching build steps, screens, access or rules, every CR that adds work gets a build-plan row tagged `CR-NN` (S: the module's phase, M/L: a change round), and agreed unbuilt CRs are "waiting" and are surfaced at session start and module close. RESUME.md gains a `Waiting changes:` line. `exec.sh --cr CR-NN` WARNs (never blocks) when the brief of a module the script writes to does not mention the id, for the folder brief and the merged build-plan form. Skill word counts at or below master (baseline 75,204 to 75,203, budget 80,000). A full unplanned-changes view and change rounds come in a follow-up. Test: `tests/wave2/test-exec-cr-brief-warn.sh` (14 checks, 4 fail on master's exec.sh) — night desk feedback-wiring review - learn(skills): **five lab findings land as compact rows, each paid for by trimming prose in the same files, so always-loaded words do not grow (baseline 75,225 to 75,204, budget 80,000).** Enum value `New` and `AutoCreatedDate`/`AutoOwner` (detection gaps), `[%CurrentDateTime%]` not `currentDateTime()`, expression return types (Decimal from date diffs and `div`, absolute `secondsBetween`, `formatDecimal` on pages), CE2729 from the default home page and page microflow grants, Atlas selector carriers for list views, page body and timelines, `-small` spacing suffixes do not exist, `display: contents` rows paint nothing, CSS pseudo text is invisible to `innerText` — lab field runs, Refs #276 (TK-020, TK-021, TK-022, TK-024) - fix(design-check): **a design system whose palette lives only in scoped `:root.` blocks no longer reads as "0 of N tokens carry the design's value".** Pass 2b compared every token against a bare `:root` of the built sheet, so a themed-only palette always warned, a false warning that teaches agents to ignore the check. A token the design declares only in scoped blocks is now compared block for block against the same-named block in the built sheet, and a wrong value is still named with its block (knob binding stays bare-only: a knob bound inside a theme the app is not wearing is not bound). Synthetic fixtures `ds-themed.css`, `built-themed.css`, `built-themed-wrong.css`; 5 new cases in `test-design-reaches-app.sh` (50 total) — TK-015 part (b) - fix(tests): **`test-exec-hash-verify.sh` case K passes on macOS.** `$TMPDIR` ends in `/`, so the bare `mktemp` path held `//` and the exact `MXPATCH_BACKUP_DIR` path assert could not match; `WORK` is now `cd`-ed into and read back with `pwd -P`. Test only, no script change. 42 pass / 1 fail before, 43 / 0 after — #384 review diff --git a/bin/lib/resume-template.sh b/bin/lib/resume-template.sh index 75c15bb8..26500053 100644 --- a/bin/lib/resume-template.sh +++ b/bin/lib/resume-template.sh @@ -64,6 +64,11 @@ resume doc is worse than none. Step 1 below is how to find out. 3. Overwrite this file before the session ends (\`bin/close-task.sh\` prints the checklist), so the next one does not have to repeat step 1. +## Waiting changes + +None recorded. A closing session lists the agreed change requests that are not built yet, as +\`Waiting changes: CR-07, CR-09\` (\`none\` when there are none), so the overwrite cannot drop them. + ## Do not lose Nothing recorded yet. This section is where a closing session puts the thing that would be diff --git a/project-bin/exec.sh b/project-bin/exec.sh index c3a7ec20..402c3510 100755 --- a/project-bin/exec.sh +++ b/project-bin/exec.sh @@ -814,7 +814,7 @@ fi # b) a "## Module brief - " heading in architecture/build-plan.md # # Platform and marketplace modules are skipped - this project does not author their briefs. -brief_missing="" +brief_missing=""; cr_unbriefed="" if [ "$PATCH_MODE" != "1" ] && [ -f "$SCRIPT" ] && [ -f "$PROJECT_ROOT/architecture/build-plan.md" ]; then # Comments FIRST, before any pattern match. A `-- ... CREATE MODULE errors if ...` line in a # real workshop script otherwise yielded a module named "errors" and would have demanded a @@ -859,12 +859,36 @@ if [ "$PATCH_MODE" != "1" ] && [ -f "$SCRIPT" ] && [ -f "$PROJECT_ROOT/architect case "$m" in System|Administration|Atlas_Core|Atlas_Web_Content|Atlas_UI_Resources|MxModelReflection |CommunityCommons|Encryption|NanoflowCommons|WebActions|DeepLink|MxTest) continue ;; esac - [ -f "$PROJECT_ROOT/architecture/modules/$m/module-brief.md" ] && continue - grep -qiE "^#+[[:space:]]*Module brief[[:space:]]*(—|-|:)[[:space:]]*$m[[:space:]]*$" \ - "$PROJECT_ROOT/architecture/build-plan.md" 2>/dev/null && continue + if [ -f "$PROJECT_ROOT/architecture/modules/$m/module-brief.md" ]; then + # CR advisory: a CR that touches this module should have a CR-tagged Build steps row. + if [ -n "$CR_ID" ] && ! grep -qE "$CR_ID([^0-9]|\$)" "$PROJECT_ROOT/architecture/modules/$m/module-brief.md" 2>/dev/null; then + cr_unbriefed="$cr_unbriefed $m" + fi + continue + fi + if grep -qiE "^#+[[:space:]]*Module brief[[:space:]]*(—|-|:)[[:space:]]*$m[[:space:]]*$" \ + "$PROJECT_ROOT/architecture/build-plan.md" 2>/dev/null; then + if [ -n "$CR_ID" ]; then + # Merged form: look only inside that module's own section (to the next "## " heading). + awk -v m="$m" -v cr="$CR_ID" ' + /^#+[ \t]*[Mm]odule [Bb]rief/ { inb = 0; t = $0; sub(/^#+[ \t]*[Mm]odule [Bb]rief/, "", t); while (t != "" && substr(t, 1, 1) !~ /[A-Za-z0-9_]/) t = substr(t, 2); sub(/[ \t]+$/, "", t); if (tolower(t) == tolower(m)) inb = 1; next } + /^## / { inb = 0 } + inb && index($0, cr) { i = index($0, cr) + length(cr); c = substr($0, i, 1); if (c !~ /[0-9]/) found = 1 } + END { exit found ? 0 : 1 }' "$PROJECT_ROOT/architecture/build-plan.md" 2>/dev/null \ + || cr_unbriefed="$cr_unbriefed $m" + fi + continue + fi brief_missing="$brief_missing $m" done fi +if [ -n "$cr_unbriefed" ]; then + for m in $cr_unbriefed; do + echo "⚠ WARN: the brief of $m does not mention $CR_ID. Add a $CR_ID tagged Build steps row to it" + echo " (skills/change-intake-detail.md Step 4), so the change is specified and stays visible. Proceeding." + done + echo "" +fi if [ -n "$brief_missing" ]; then echo "⚠ No module brief for:$brief_missing — proceeding, but nothing has specified this module." echo "" diff --git a/skills/change-intake-detail.md b/skills/change-intake-detail.md index fca1c690..80beed98 100644 --- a/skills/change-intake-detail.md +++ b/skills/change-intake-detail.md @@ -1,10 +1,10 @@ # Change Intake — Detail: Why, Worked Example, Apply, Prove, Gate Check **Applies to:** any mxcli project with a `PROJECT.md` (migration, requirements-driven, greenfield, change an existing app), from Stage 2 onward. -**Purpose:** the on-demand half of `change-intake.md`. That file is the baseline core every lead and ba-agent session reads (trigger, row format, class → entry artifact, size → ask, owners, Done when). Read this one when you apply or prove a change request, when a class, size or status is unclear, or when the `Change log:` gate line needs explaining. -**Owns:** nothing on its own: `change-intake.md` owns the `## Change log` table in `PROJECT.md` and the classes, sizes and statuses. `conversion-runbook.md` §3b (drift-sync) is the BRD-flush step of this loop; `iterative-build-loop.md`, `close-the-loop.md` and `agent-roles.md` point at `change-intake.md`. +**Purpose:** the on-demand half of `change-intake.md`. That file is the baseline core every lead and ba-agent session reads. Read this one to apply or prove a change request, when a class, size or status is unclear, or to explain the `Change log:` gate line. +**Owns:** nothing: `change-intake.md` owns the `## Change log` table and the classes, sizes and statuses. `conversion-runbook.md` §3b (drift-sync) is this loop's BRD-flush step. -**Trigger:** any message from the user that asks for something to be different from what the artifacts say or what was built, typed, pasted, relayed ("the finance lead wants..."), or said while looking at a screenshot or the running app. Not a trigger: answering a question you asked at a gate (that is `interview-protocol.md`), or a finding from a review pass (that is `finding-disposition.md`). +**Trigger:** any message asking for something different from the artifacts or the build, typed, pasted, relayed or said over a screenshot. Not a trigger: a gate answer (`interview-protocol.md`) or a review finding (`finding-disposition.md`). --- @@ -100,7 +100,7 @@ A row the user rejects is kept, with Status `rejected — `. A rejected ## Step 4 — Apply: top down, as far down as needed 1. Edit the entry artifact (Step 2). -2. Cascade down only to layers that *restate* what changed. Module briefs point to the BRD and do not copy it (`module-brief.md`), so most BRD edits need no brief edit. If the change adds or retires a build step, add or edit that row in the build plan. +2. The BRD stays the source of truth. The module brief's `### Build steps` table is updated, with a CR-tagged row such as `CR-07-1`, for every CR that touches that module's build steps, screens, access or rules, so `context-pack.sh CR-07-1` finds it. Every CR that adds work also gets a build-plan row tagged `CR-NN`: **S** one row in the module's own phase, **M** and **L** wait for a change round (a follow-up adds the full "unplanned changes" view and change rounds). An agreed CR that is not built yet is *waiting*. Surface it at session start and at module close; never let it drop out of sight. 3. Then write the MDL and run it with `./bin/exec.sh --cr CR-NN