Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ jobs:
- name: Routing tables in sync with skill-routing.tsv (render-routing.sh --check)
run: bin/render-routing.sh --check

- name: MDL rules by kind cover every rule and match skills/generated (mdl-rules.sh --check)
run: bin/mdl-rules.sh --check

- name: No macOS-only assumptions reintroduced (check-portability.sh)
run: bin/check-portability.sh

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. Named m

## Unreleased

- new(mdl-rules): **`bin/mdl-rules.sh <kind...> | --for <script.mdl>` prints the MDL rules one script needs, by the kinds of statement it writes** — lazy-load PR 2a. `bin/lib/mdl-rule-kinds.tsv` maps page / microflow / access / workflow / entity / any to sections located by file and heading text (never line numbers): the STOP rows by their `Kind` column, the kind-specific gotchas, `learned-microflow-patterns.md`, `microflow-preflight.md`, `ui-preflight-pages.md`, `design-spacing.md` §1–3, the detection-gaps register rows by construct, `security-is-not-a-later-script.md` and `retesting-learned-rules.md`. Output is the core (Step 0, the `any` STOP rows, gotchas, final self-check: 3,347 words) plus the kind sections, closed by "Rules for kinds K: STOP rows n/n listed" (page 10,223 words, microflow 10,186, access 4,730, entity 5,183, workflow 3,732), against the 29,388 words the mdl helper preloads at Stage 5 today. `--for` reuses exec.sh's statement classifier (`exec.sh --subjects`; Java actions and mappings count as microflow, demo users as access) and exits 1 if it fails; a heading that is gone fails loudly, never prints empty. `skills/generated/rules-<kind>.md` are the same output for harnesses that read files (Copilot, Cursor, Windsurf); `--check` (CI) fails on drift, on any STOP row, gotcha, register row or `##` section that reaches no kind (a section left out on purpose needs an `exclude` row with its reason), and on any register ERE that matches no row by itself, and on an unclosed code fence in a file it reads. No routing change yet: PR 2b demotes the preloads. Behaviour suite: `build-packs.sh --rules "<kinds>"` expands the script in a pack. Fixture `tests/wave2/test-mdl-rules.sh` — lazy-load plan, option C (maintainer)
- process(preflight): **`learned-mdl-preflight.md` moves its STOP-row narrative out of the baseline and gains a `Kind` column (page / microflow / access / workflow / any)** — lazy-load PR 1. The 15 retired rows collapse to one line listing their numbers, the version notes move, and each live row keeps its If/Then text plus one failure clause; the full rows, retired rows and version notes are in `process/baseline-incident-history.md` § PF1, verbatim (`check-moved-text.sh`: 43 of 43 removed lines found). The workflow `DECISION` STOP and the #879 read-first pointer stay in the skill. `Kind` sits at the end of each row so `mdl-scan`'s `| <n> 🔎` markers still match. Baseline 73,946 → 72,891 words (−1,055). — maintainer (Option C lazy-loading plan)
- fix(progress-report): **`progress-report.py` no longer crashes with `TypeError: '<' not supported between instances of 'dict' and 'dict'` when two exec'd scripts share a leading number** (#513). `script_phases()` sorted `(number, phase dict)` pairs, so `10-data.mdl` and `10b-data-flows.mdl` (or one script logged under two paths), both matched to a plan phase, compared the dicts and every `exec.sh` run ended with `WARN: progress-report.html not updated`. It now sorts on (number, script name) only; an unmatched numbered script still takes the phase of the nearest lower-numbered matched one, ties broken by name. Fixture: `test-progress-report.sh` T17 (fails 3/3 on master). — jopterhorst (#513)
- new(canvas): **`project-bin/mf-canvas-facts.py` prints how a microflow or nanoflow lies on the Studio Pro canvas: labels on top of each other, lines through objects, note lines leaving the side that faces away, flows that run right-to-left or curl, captions wider than their shape, and decision captions that ask the opposite of their true branch (SENSE).** It prints facts, one line each, and no verdicts; read-only (it reads units through `mxpatch.py`), exit 2 when a flow could not be read. `verify-module.sh` runs it per module as an info rung (1c, log `14-canvas-facts.log`; a missing script, Python or `.mpr`, an exit 2 or a timeout is an INFO row reading NOT MEASURED, never a gate). Fixture `tests/wave2/test-mf-canvas-facts.sh` runs on a model mxcli v0.27.0 wrote (units and `.mpr` captured); `test-verify-module-446.sh` gains V8 for the rung. Calibration is from Studio Pro 10.24 screenshots, not verified on Studio Pro 11. Field evidence, measured 2026-10-21 on one Mendix 10.24 app: 1,588 flows read in one pass; on the 36 flows an mxcli-built branch added or changed in one module, OVERLAP 19, LINE 27, NOTE-SIDE 17, LEFTWARD 3, TURN 4, SENSE 9 before repair — saingge
Expand Down
74 changes: 74 additions & 0 deletions bin/lib/mdl-rule-kinds.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# mdl-rule-kinds.tsv — which MDL rules a script needs, by the kind of statement it writes.
# Read by bin/mdl-rules.sh (and nothing else); rendered to skills/generated/rules-<kind>.md.
#
# WHY (lazy-load PR 2, 2026-10-23). The mdl helper preloaded every kind-specific skill at Stage 5
# (29,388 words), though a page script needs none of the microflow rules and a microflow script
# none of the page rules. This table says which sections each statement kind needs, so the helper
# loads them per script instead. The skills keep every word; only who preloads them changes.
#
# Sections are located by FILE plus HEADING TEXT, never by line number (the bin/lib/runbook-span.sh
# precedent): a heading matches when its text, after the leading #s, starts with the heading cell.
# A heading that no longer exists makes bin/mdl-rules.sh fail loudly — it never prints empty.
#
# Format: TAB-separated, four columns. Blank lines and #-comments ignored.
# 1 kind page | microflow | access | workflow | entity | any (any = every script)
# 2 file repo-relative path
# 3 selector file the whole file
# top everything above the file's first "## " heading
# section the heading and everything under it, down to the next heading of its level
# stop the STOP table under that heading, rows filtered by their Kind column
# (the kinds asked for, plus `any`; the retired-numbers row always)
# bullet one bullet under that heading: arg is "<heading>::<bullet lead text>"
# rows the table rows under that heading whose FIRST cell matches an ERE
# (case-insensitive): arg is "<heading>::<ERE>"
# exclude kind "-": a `##` section deliberately reaching no kind (it is not a rule
# for writing MDL); arg is "<heading>::<one-line reason>"
# 4 arg heading text, or heading::lead / heading::ERE / heading::reason as above; "-" for
# file and top
#
# Denominators (bin/mdl-rules.sh --check): every STOP row carries a known Kind, every bullet under
# a `bullet` heading is selected by some row here, every table row under a `rows` heading is matched
# by some ERE here and every ERE matches some row on its own, every `##` section of a file read in
# parts (no `file` row) is selected or excluded below, and every generated file equals a fresh
# render. A new gotcha, register row or section that no kind selects fails --check, so it cannot
# silently stop reaching the mdl helper. Headings inside code fences are not headings.
#
# kind file selector arg
any skills/learned-mdl-preflight.md top -
any skills/learned-mdl-preflight.md section Step 0 — choose the write mode
any skills/learned-mdl-preflight.md stop The checklist — run before writing a single line of MDL
any skills/learned-mdl-preflight.md bullet MDL gotchas::**Quote / unquote retry rule:**
any skills/learned-mdl-preflight.md bullet MDL gotchas::**Grants are co-located
any skills/learned-mdl-preflight.md bullet MDL gotchas::**`mxcli check` does not catch corruption.**
any skills/learned-mdl-preflight.md bullet MDL gotchas::**mxcli v0.25 — keep the skills' spellings
any skills/learned-mdl-preflight.md bullet MDL gotchas::**`exec` is not `check`.**
page skills/learned-mdl-preflight.md bullet MDL gotchas::**Cross-module association paths
microflow skills/learned-mdl-preflight.md bullet MDL gotchas::**Cross-module association paths
page skills/learned-mdl-preflight.md bullet MDL gotchas::**Changing an existing DataGrid 2 column
page skills/learned-mdl-preflight.md bullet MDL gotchas::**No `elseif` in page/widget expressions**
entity skills/learned-mdl-preflight.md bullet MDL gotchas::**Enumeration values named with reserved words**
access skills/learned-mdl-preflight.md bullet MDL gotchas::**Demo users:**
any skills/learned-mdl-preflight.md section Final self-check
page skills/ui-preflight-pages.md file -
page skills/design-spacing.md top -
page skills/design-spacing.md section 1. The scale
page skills/design-spacing.md section 2. The rhythm hierarchy
page skills/design-spacing.md section 3. The page scaffold
- skills/design-spacing.md exclude 4. Review-side::judging a screenshot at module review (module-review.md 4d), not writing MDL
- skills/design-spacing.md exclude Related::cross-references to other skills, no rule of its own
microflow skills/learned-microflow-patterns.md file -
microflow skills/microflow-preflight.md file -
access skills/learned-microflow-patterns.md section Current User — Two Separate Mechanisms
entity skills/learned-microflow-patterns.md section Association Direction — Reading SHOW ASSOCIATIONS Correctly
access skills/security-is-not-a-later-script.md file -
entity skills/security-is-not-a-later-script.md file -
any skills/learned-detection-gaps.md top -
any skills/learned-detection-gaps.md section The ladder
any skills/learned-detection-gaps.md rows The register::non-idempotent|mxcli < v0\.26
page skills/learned-detection-gaps.md rows The register::page|widget|datagrid|dg2|dropdownfilter|navigation|dynamictext|contentparams|elseif|bindings|combo box|snippetcall
microflow skills/learned-detection-gaps.md rows The register::java action|getvalue|commit|microflow|on error|create entity|xpath|currentuser|import mapping|get workflows|loop
entity skills/learned-detection-gaps.md rows The register::entity|attribute|enumeration|reserved|calculated by|autocreated
workflow skills/learned-detection-gaps.md rows The register::workflow|parallel split
access skills/learned-detection-gaps.md rows The register::access|currentuser|role
any skills/learned-detection-gaps.md section Operating rules that fall out of this table
any skills/retesting-learned-rules.md file -
1 change: 1 addition & 0 deletions bin/lib/routing-exempt.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ skills/checkpoints/ reached via the checkpoint mechanism (conversion-runbook sta
skills/journey-map.md tombstone — falsification trial failed 2026-08-22, row removed then; file kept so old links resolve
skills/ui-review-loop.md merge tombstone — content lives in skills/module-review.md (routed)
skills/module-completion-loop.md merge tombstone — content lives in skills/module-review.md (routed)
skills/generated/ rendered output of bin/mdl-rules.sh (rules-<kind>.md, drift-checked by bin/mdl-rules.sh --check) — the plain-read twin of that script's output, reached through bin/mdl-rules.sh's own routing row, never routed one by one
Loading
Loading