Repository navigation
feat(mdl-rules): load MDL rules per statement type instead of preloading (lazy-load PR 2a) - #571
Merged
Merged
Conversation
bin/mdl-rules.sh <kind...> | --for <script.mdl> | --render | --check prints the always-needed core plus the sections bin/lib/mdl-rule-kinds.tsv maps to each statement kind (page, microflow, access, workflow, entity, any), located by file + heading text, and closes with "Rules for kinds K: STOP rows n/n listed". --for reuses exec.sh --subjects. skills/generated/rules-<kind>.md are the rendered, drift-checked plain-read copies; CI runs --check. No routing change: lazy-load PR 2b demotes the mdl preloads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jQvaonym9V1wKKfAEPmRr
…Es, unselected sections - F1: `--for` with a failing classifier exited 0 and printed the core alone (kinds_for's exit 1 ran in a subshell inside a heredoc). It now runs first, `|| exit 1`. Fixture T7. - F2: a register ERE matching no row hid behind its kind's union. Each ERE is now checked on its own, in the lookup and in --check. Fixture T8. - F3: a new `##` section no kind selects passed --check. Every `##` section of a file the table reads in parts must be selected or named by an `exclude` row with a reason (seeded: design-spacing.md §4 Review-side, §Related); a stale exclude fails too. Fixture T9. - --for maps exec.sh's `action` and `mapping` subjects to microflow and demo-user heads to access (T10, on fixtures/import-mapping-range-repro/maptest.mdl plus minimal scripts). - Headings inside code fences are not headings (T11); `page page` is labelled once (T11). Generated files unchanged; baseline 72,891 words. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jQvaonym9V1wKKfAEPmRr
… the sections after it Re-review finding A on #571: an odd number of fence lines in a file the table reads silently swallowed every later heading, so a new rule section after it reached no kind while --check passed. load() and the coverage pass now report "unclosed code fence". Fixture T12 (fails on e7529c5, passes now); test-mdl-rules 39/0; --check clean on the real tree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jQvaonym9V1wKKfAEPmRr
MendixMau
pushed a commit
that referenced
this pull request
Oct 23, 2026
Conflicts: bin/mdl-rules.sh and bin/lib/mdl-rule-kinds.tsv take master's (reviewed) versions, which 2b never changed; 2b's gate fixture moves to T13 after master's T7-T12; CHANGELOG keeps both lines. test-mdl-rules 43/0, mdl-rules --check clean, baseline 63,877. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jQvaonym9V1wKKfAEPmRr
5 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Direct lane
Classification: DISCUSS. The maintainer approved this as option C of the lazy-loading plan. PR 1 is #570.
Split. The whole of PR 2 changes about 630 hand-written lines plus 2,634 generated lines, so it is split per the brief:
claude/loving-gates-hauc1n-lazy-pr2b, stacked on this one, pushed, not opened yet): the routing demotion, the gate-check fix, the mdl stub line and its fixture cases.The word counts and the A/B below cover both halves, because the A/B arm L is the 2b preload.
What changed and why. Today the mdl helper preloads every kind-specific MDL skill at Stage 5: 29,388 words. A page script needs none of the microflow rules, and a microflow script needs none of the page rules. This PR adds the per-statement-kind lookup.
bin/mdl-rules.sh <kind...> | --for <script.mdl> | --render | --check. It prints the always-needed core, then the sections thatbin/lib/mdl-rule-kinds.tsvmaps to each kind (page, microflow, access, workflow, entity, any). It ends withRules for kinds K: STOP rows n/n listed. The denominator is counted by a second, independent pass over the STOP table. If the two counts disagree, the run fails.runbook-span.shprecedent). The table covers:Kindcolumnlearned-microflow-patterns.mdmicroflow-preflight.mdui-preflight-pages.mddesign-spacing.md§1–3security-is-not-a-later-script.mdretesting-learned-rules.md--forreuses the existing classifier by callingproject-bin/exec.sh --subjects. That is the same lexer exec.sh, affected-tests.sh and the change class use. There is no second copy, and exec.sh is not refactored.skills/generated/rules-<kind>.mdhold the same bytes asbin/mdl-rules.sh <kind>, for Copilot, Cursor and Windsurf, which read files. They have arouting-exempt.tsvline: they are rendered output, not routed one by one.--checkruns in CI (new step next torender-routing.sh --check). It checks the denominators: every STOP row has a known Kind, every gotcha bullet and every register row reaches at least one kind, and the generated files match a fresh render. A new gotcha or register row that no kind selects fails CI instead of silently not reaching the mdl helper.tests/behaviour/build-packs.sh --rules "<kinds>"expands the script in a pack to its output for those kinds. That is how the dispatcher will deliver it in PR 3.bin/mdl-rules.sh --check. 2b: the mdl stub gains workflow step 4a: runbin/mdl-rules.sh(or readrules-<kind>.md) before drafting, and report "STOP rows for kinds K: n/n checked" in PREFLIGHT.project-bin/exec.sh --subjects, and its output is unchanged. Producer: a toolkit checkout; the script needs no project. 2b touchesskill-routing.tsv/.sh,gate-check.shandagents/mdl-agent.md.render-routing.sh --check, LC_ALL=C): baseline 72,891 → 63,877 (−9,014, the three mdl-only files go on-demand). mdl Stage 5 29,388 → 14,600 words / 14 → 7 files. The 14,600 counts the 3,347-word core ofmdl-rules.sh, like the runbook slice. Per task the helper adds its kinds on top: page 10,223, microflow 10,186, access 4,730, entity 5,183, workflow 3,732 (each includes the core). So a page task reads about 21.5k words instead of 29.4k. This is above the plan's 12–13k estimate because the core keeps Step 0, the 3anySTOP rows, the gotchas, the final self-check, the detection-gaps ladder and operating rules, andretesting-learned-rules.mdwhole. Other roles do not change.mdl-rules.sh pagetakes about 0.1 s;--checktakes about 1 s.Gate / sync fix (in 2b)
gate-check.shbuild-ready item 2 greppedCLAUDE.local.mdforui-preflight-pages. Once that row is on-demand, a re-synced baseline block no longer names it, so item 2 would flip to FAIL. 2b acceptsui-preflight-pagesorbin/mdl-rules.sh, which is the new baseline row.The
sync-project.sh"§2c" check the brief mentions no longer exists. §2d now renders the routing block instead of grepping for it (see the T9 note intest-bug12-sync.sh), so there is nothing to change in sync. The only check is the gate's.Fixture
test-mdl-rules.shT7 (2b) covers:.mprunderapp/): item 2 passes, and the rendered block holdsbin/mdl-rules.shand noui-preflight-pagesFixtures (scoped runs only; full suites not run)
test-mdl-rules.sh bin/mdl-rules.sh: 26/26 on 2a, 30/30 on 2b. It covers:--foron the real mixed page+entity repropipelines/mendix-mpr/samples/.../D2-page-repeater-content.mdl--foron real workflow, access, microflow and scheduled-event scripts--checkdrift, an unmapped new gotcha, an unmapped register row and an unknown STOP Kind (all on a temp copy).mdlfiles; nothing is hand-written.test-mdl-scan52/0,test-baseline-pack22/0,test-render-routing5/0,test-routing-tier26/0,test-runbook-slice31/0 (T5 now countsmdl-rules.shas its core output),test-bug03-gates47/0,test-source-sufficiency-gate7/0,test-source-ledger55/0,test-bug12-sync62/0,test-authoring-audit5/0.render-routing.sh --checkis clean. Theauthoring-audit.py routingadvisory is unchanged (top-1 49/55, top-3 55/55).check-portabilityandcheck-scriptsare clean.Behaviour A/B (
tests/behaviour/RUNBOOK.md)bin/mdl-rules.shexpanded to its output for the task's kinds via the newbuild-packs.sh --rulesmode. L packs are 19.9k–26.7k words.claude -pagents with only Read and Write, model claude-opus-5-5, run from an empty directory with no CLAUDE.md, arms interleaved.planted). PR 1's traps cover 12, 26, 1b, 33 and 29. New traps: 16 (access XPath with a path inside[%CurrentUser%]) and 18 (callee microflow and workflow in one script).microflow-preflight —where the scorer wantsmicroflow-preflight:)About trap 18. Both L reps did split into two scripts (
scripts: 2, "FILE 1 of 2 / FILE 2 of 2", STOP #18 cited). They wrote both files inside the single ```mdl fence the task format demands, and the ad-hoc scorer counts per fence. Both M reps left the workflow undrafted. Read by hand, both arms obey STOP 18. Read mechanically, L loses.Verdict. Under the decision rule ("no worse on every metric, count at the good value"), L is not shown no-worse. There are three losses, each a single rep, and two of them are output-format misses where the content was present. This goes to the maintainer to decide.
Outputs and scores are in the builder's session scratch. They can be reproduced with
build-packs.shand the PR 1 trap tasks plus the two new ones.Field evidence. None. A field run is owed: this was not run on a real project. It is planned with PR 3, the dispatcher that hands
mdl-rules.shoutput to the helper.skills/generated/, rendered output) — split 2a/2b per the brief.mdl), both layouts (T7 in 2b); Bash 3.2-safe constructs and Git Bash considered (no.exeprobing needed, only bash and awk), but not run on macOS or WindowsCHANGELOG.mdline in this PR (and one in 2b)Open questions for the maintainer
CLAUDE.mdstill nameslearned-microflow-patterns.mdin the "always-on set". After 2b it is on-demand. That one-line edit was left to the maintainer.bin/init-project.shitem 5 andproject-bin/context-pack.shstill point at the skill files directly. They are lead/dispatcher surfaces and left for PR 3.Review: pending independent review
Generated by Claude Code