From 63f74fd6e80cf896edcb63c6a70329dca0ade9bf Mon Sep 17 00:00:00 2001 From: MendixMau Date: Fri, 16 Oct 2026 22:48:58 +0800 Subject: [PATCH] learn(unit-test): name the per-flow Unit flows list next to Unit modules Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + skills/unit-test.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5592c10d..fd45eefe 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 +- learn(unit-test): the unit-test skill names the per-flow `Unit flows:` list next to `Unit modules:`, so whether a flow gets a test reads the same in both places (follow-up to #435) — MendixMau - process(testing): **unit tests are chosen per flow, not per module: a module brief lists `Unit flows:` (one `- ACT_X: reason` line each) and `affected-tests.sh` runs only the listed flows the change touched.** Follow-up to #417 on the maintainer's policy that unit-testing everything is overkill (logic and integrations only, UI journeys catch the rest). Module done runs the `--module` modules' listed flows only; a list wins for its module even under `Unit tests default: yes`; bullets (`-`, `*`, `+`, `1.`, `1)`) may be separated by blank lines, carry `(note)` or `Module.` forms, or sit inline (`Unit flows: A: money, B: rest`), a `## Unit flows` heading works with or without a colon, a line that cannot be read warns with its text, and a Unit flows block that yields no flow warns; under default yes a test is dropped only when every module it names has a list that excludes it; CRLF briefs are read; `Unit tests: yes` or `Unit modules:` with no list keeps the module-level selection; a flow listed without a reason, with no test, with a different casing than the model, or not in the model (`SHOW MICROFLOWS IN`), and a module the model lacks, warn. Test: wave2 `test-affected-tests.sh` L10 (35 checks). Baseline unchanged at 75,194 words (budget 80,000) — MendixMau - fix(sync-project, doctor): **a project whose `.claude/settings.json` lacks the `look-ledger.sh seen` hook now gets it back on the next sync, and `doctor.sh` warns when it is missing.** In a lab project the look ledger read "0 of 31 pages seen" while 22 of them had screenshots: `install-claude-permissions.sh` (the only writer of the hook) had never run there, `sync-project.sh` only printed a warning in a long report, and `doctor.sh` checked the allow-list but not the two hooks, so `seen.tsv` stayed empty and any gate built on the ledger would have stalled the build. `install-claude-permissions.sh` gains `--hooks-only` (add the SessionStart and PostToolUse hooks, touch no allow, deny or ask entry, prune nothing, write nothing to `settings.local.json`); `sync-project.sh` runs it when the hooks are missing (`--dry-run` says what it would add); `doctor.sh` names the missing hook and the fix. `tests/wave2/test-look-ledger-hook-repair.sh` reproduces the gap, then proves detect, repair, idempotence and that a Read of a screenshot writes a seen row. Review follow-up: sync repairs only a project that installed the profile before (sidecar with a non-empty allow, or `.mxtk/permission-profile`; checked by `--consent-check`), otherwise it WARNs with the one-line `--hooks-only` command; `.mxtk/no-hook-repair` is the documented opt-out (sync and doctor); `--hooks-only` creates no empty allow/deny, leaves no `.bak`, keeps the file's indent and non-ASCII, and leaves a hand-formatted file untouched (exit 3, lines printed). — lab project field run (night 2026-10-16) - new(bug-log): **`docs/bugs.jsonl` per project plus `bin/file-bugs.sh` to file it safely to mendixlabs/mxcli or this repo.** A session that hits or works around a tool bug appends a row (`--add`, next free `PBUG-NN`, project-local so it never collides with the toolkit's BUG-n; the public number is the issue; the one-line instruction sits in learned-detection-gaps.md). The script normalises Unicode (NFKC, zero-width and lookalike letters, names split by a line break), redacts every title and body (home and spaced paths, user and host names, emails, IPv4/IPv6, tokens, key=value, JSON and `--flag value` secrets, hex tokens, AWS keys, any dotted hostname, server names from config files, URLs other than the two repos matched exactly and cut to the repo prefix plus /issues/N or /pull/N, a URL scheme from a fixed list (jdbc, postgres, mysql, mongodb, redis, amqp, ssh, git and the like) stays and loses the host, any other scheme becomes ``, the project's .mpr, module, entity, attribute, page and microflow names (distinctive ones inside identifiers; ordinary-word and short names only as whole words or segments, never inside mxcli verbs, toolkit file names or other words), Authorization and cookie header values, `$LEAKGUARD_DENY` as a regex plus the project's .leakguard-deny), builds the versions line from version-shaped strings only, scans again with the same matcher and refuses a bug that still looks unsafe: a refused bug gets no duplicate search, no URL and no text in `--links`/`--json`. Default is a dry run with likely duplicates; posting needs `--file PBUG-NN` or `--all` and a y/N per bug read from /dev/tty only (no stdin test hook; a pty cannot be told from a human, so the shipped permissions deny `file-bugs.sh` and `file-bugs.py` with `--file` or `--all`, abbreviations are refused, and a human runs posting with `!`), and a deny list must exist and be valid (an invalid pattern counts as missing) or posting, `--links` and `--json` are refused, passes `--repo= --title= --body-file=` to gh, keeps the log's file mode; `--links` caps title and body under the URL limit. `tests/wave2/test-file-bugs.sh` covers each case with a stubbed gh and a pty helper — MendixMau diff --git a/skills/unit-test.md b/skills/unit-test.md index 448a1238..3c1ba896 100644 --- a/skills/unit-test.md +++ b/skills/unit-test.md @@ -7,8 +7,8 @@ assertion is live, how to run it without breaking the live app, and how to repor the false-green rows are `testing-shape.md` §4. **Whether** a module gets unit tests, and **when** they run, is the project's test strategy -(PROJECT.md `## Test strategy`, `Unit modules:`, decided at CAC-5). Each change runs only the -touched unit tests of opted-in modules; module done runs that module's; build complete and +(PROJECT.md `## Test strategy`, `Unit modules:` or per flow in the module brief's `Unit flows:`, decided at CAC-5). Each change runs only the +touched unit tests of opted-in modules or listed flows; module done runs that module's; build complete and before each later deploy run everything once. This file does not decide that. When the user asks for unit tests outside a pipeline, they have decided. ---