Skip to content

Stage 3 interaction model, part 2: gate facts + artifact manifest (#291) - #333

Draft
MendixMau wants to merge 8 commits into
masterfrom
feat/interaction-model-gate-v2
Draft

MendixMau wants to merge 8 commits into
masterfrom
feat/interaction-model-gate-v2

Conversation

@MendixMau

@MendixMau MendixMau commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Direct lane

Supersedes #332. These are the same two commits as #332, replayed onto master after the integration batch (#329) squash-merged. The tree is identical to #332's head c236e62 plus master's #330 changes.

Review status. An independent review returned MERGE-AFTER-FIX, the fixes landed as c236e62, and a confirmation review returned MERGE at c236e62. Minor follow-ups remain: "Review audit log" is a false FAIL; an id-only mention under Inbox counts as covered; "Order approval" is missed without mdlRefs; a <td>-split contract line is not parsed. This needs one field run on a real project before merging (CLAUDE.md "Shipping an instrument", rule 4).

What changed and why (one paragraph):
Part 1 (#317) added skills/interaction-model.md and the wireframe wf-contract block, but nothing yet noticed when the artifact was missing or incomplete. This PR adds the facts half and leaves judgement in the skill.

  • Manifest row. bin/lib/artifact-manifest.tsv gains an interaction-model row (stage 3, report-only). If design/interaction-model.md is missing, the artifact check reports it PENDING out loud. This does not block.
  • New check, run once the file exists. bin/lib/interaction-model-check.sh is sourced by gate-check.sh after the artifact block. Its findings print under Interaction model (stage 3 facts): with denominators:
    • (b) FAIL: a BRD approval, review, sign-off or user-task use case that is not named on any line under an "Inbox" heading. A table row or a bullet both count.
    • (c) FAIL: a design/wireframes/*.html whose wf-contract block has no valid Page parameter: line.
    • (a) MANUAL, never FAIL: a BRD actor with no "Role homes" row. BRD actors are not the confirmed role model, so the check asks a person to confirm instead of failing.
  • Effect on Stage 3. check_stage_3 turns any un-waived FAIL into a Stage-3 FAIL. If the only open findings are MANUAL ones, Stage 3 is MANUAL (exit 2).
  • checkpoint-design.md gains Q1b, "who lands where, and how does each role find its work", asked next to the layout question.
  • brd-to-build-plan.md Step 7 gets one sentence telling the build plan to read its wire points from the artifact. Without it, the manifest row's build-plan consumer would be a false citation.

Changes after review (c236e62):

  1. Inbox coverage. Any line under an "Inbox" heading covers a task: a table row, a - or * bullet, or a numbered item. The skill's own Step 2 writes inboxes as bullets.

  2. Roles. A BRD actor with no Role homes row is now MANUAL. The message names the actor and says: confirm it is a user role, or add a | <actor> | none — <reason> | row (system actor / merged into another role). A none — <reason> row counts as covered.

  3. Which use cases count as tasks. A use case is checked only when:

    • its title starts with approve, review or sign-off / sign off (case-insensitive, after an optional id prefix such as UC013:); or
    • its title contains "user task"; or
    • its mdlRefs names a user task.

    "View approval history", "Configure approval thresholds" and "Disapprove…" no longer FAIL, and fixture cases assert that.

  4. Wireframe parser.

    • Inline tags are stripped before matching, so <b>Page parameter:</b> Sales.Order and <code>Sales.Order</code> read.
    • The end of the wf-contract block is found by counting <div> depth, not by taking the first </div>.
    • The separator in none — <reason> may be a hyphen, an en dash or an em dash, and HTML entities for the dashes are decoded.
    • CRLF files read the same as LF files.
  5. Projects that write the interaction model mid-build. The Stage-3 check runs again on every gate run. A project that writes design/interaction-model.md during the build therefore gets one FAIL per wireframe drawn before the model existed. That is intended. The FAIL output now ends with one remedy line: add <p>Page parameter: …</p> to the wireframe's wf-contract block, or waive that wireframe with Waived artifact interaction-model/<file>.html: <reason>.

Ambiguities, resolved narrowly:

  • Where roles come from. No bin/ script reads a role model from PROJECT.md. The only role list any bin/ script reads is the BRD top-level actors, in bin/brd-report.sh, so that is the source. Because it is not the confirmed role model, a missing actor is MANUAL only.
  • Which heading counts. Role homes are read from the table under a heading containing "Role homes", with columns found by the header names Role and Home page. Inbox lines are any lines under a heading containing "Inbox".
  • Id matching. Use-case ids repeat across BRDs, so a mention of UC002 covers that id in every BRD. Waivers and FAIL lines use <BRD id>/<UC id>.
  • Which wireframes. Only top-level design/wireframes/*.html, the glob as written.
  • Waiver syntax. No new flag.
    • Waived artifact interaction-model: … waives the whole artifact. This is the artifact check's existing hand-written line.
    • Waived artifact interaction-model/<unit>: … waives one finding. The unit is an actor name, <BRD>/<UC>, or a wireframe file name.
    • Waived stage 3 does not hide these FAILs, which is consistent with waiver_applies.
  • Projects adopted above stage 3 report ADOPTED and get no findings.
  • A missing artifact is report-only PENDING, not a FAIL. This follows the part-2 design rather than the issue's acceptance criterion 4, so projects already past Stage 3 are not suddenly blocked.

Field evidence: none yet. This has run only on synthetic project trees, including the independent reviewer's probe trees, reproduced as fixture cases T3c and T9–T12. A field run is still owed on a real project the maintainer chooses.

  • No client data anywhere in the diff

  • Size cap: within cap, excluding the fixture and CHANGELOG

  • Test tier: fixture level, on synthetic trees. tests/wave2/test-interaction-model-gate.sh results:

    gate-check version Passed Failed
    base branch 19 25
    previous head 986f4e7 27 17
    head c236e62 44 0

    Existing fixtures on head, all with 0 failed:

    Fixture Passed
    test-bug03-gates.sh 31
    test-source-sufficiency-gate.sh 7
    test-source-ledger.sh 55
    test-closeout.sh 34
    test-wrong-verdicts.sh 20
    test-wireframe-count.sh 5
  • New instrument, golden input: synthetic, built from the skill shapes and the reviewer's probes, not captured from a real project.

    • Layouts: both covered, single-tree and nested analysis/<name>/.
    • Platform: bash 3.2-safe; uses jq, which gate-check already requires; no mac-only tools; CRLF covered. Not run on Git Bash.
  • CHANGELOG line, credited "field retro (Usability/flow defects pass every gate: proposal for a Stage-3 interaction-model deliverable and gate #291)"

Checks run (head c236e62): all exit 0.

  • bin/render-routing.sh --check: in sync. Baseline is 74,959 words before and after; checkpoint-design.md is not in the always-on set.
  • bin/check-scripts.sh
  • bin/check-portability.sh
  • LEAKGUARD_ALLOW_NO_DENYLIST=1 bin/check-no-client-data.sh
  • bin/check-pr-discipline.sh origin/master
  • Forbidden-term grep over added lines: 0 hits.

Risks:

  • A project that already has design/interaction-model.md can turn red at Stage 3. A project that writes it mid-build gets one FAIL per legacy wireframe, with the remedy line shown above.
  • An actor with no home makes Stage 3 MANUAL (exit 2) until someone confirms it or adds a none — <reason> row.
  • Changing brd-to-build-plan.md and checkpoint-design.md triggers the protocol-changed notice at stages 3 and 4.

Refs #291


Update 2026-11-03

Head c90aad0. This merges origin/master (dbd9b3e, 155 commits) into the branch. There was no rebase and no force-push.

Merge. There was one conflict, in bin/gate-check.sh check_stage_3. Master had added the process-map freshness check (design/process-model.json → process-map.html) at the same spot where this branch adds the interaction-model verdict. Both are kept: master's process-map check runs first, then the interaction-model case. Every other file merged cleanly. The manifest row now sits next to master's new process-map row, and artifact-check.sh's helpers (_art_field, _art_adopted_stage, _art_rank) still exist with the same signatures after master's register-cache rewrite (#583).

Dropped, because master already has it. Part 1 (#317) is on master: skills/interaction-model.md, its routing row, design-artifacts.md Step 2b, and the wf-contract block. This branch never touched those files, so nothing was removed from the diff. Part 2 (the check, the manifest row, Q1b and the Step 7 sentence) is not on master; it is all still here. One part of the CHANGELOG was dropped: the branch's two lines had ended up inside the released v2026.10.19 section. They are now one line under ## Unreleased, using the post-review wording.

Verdict-flip analysis (what changes for an existing project after sync-project.sh). The check is called from the toolkit's bin/, so sync-project.sh copies nothing new into the project. The change reaches a project with the next git pull.

  • Artifact absent (any project from before part 1): the artifact check reports PENDING and the facts line reports PENDING. The Stage-3 verdict does not change (fixture T2).
  • Adopted above stage 3: the result is ADOPTED with no findings (T7).
  • Artifact present and wrong: the result is FAIL, which is the intended meaning of "there and wrong". This is the one real flip. A project that reached Stage 3 on master in the last weeks has an interaction-model.md written by the Stage 3 workers, and it can now go from PASS to FAIL or MANUAL.
  • Probe on real worker output. I ran master's gate-check and this branch's against copies of six Stage-3 worker outputs. These come from a synthetic requirements project used in the Stage-3 A/B runs, not from a client project. All six are FAIL on master for other reasons (no Stage-3 CONFIRMED decision, or a stale render). Findings:
    • Defect, fixed in c90aad0. In 2 of 6 runs Stage 3 went FAIL → MANUAL (exit 2). The MANUAL return ran before the register check, so a MANUAL role finding hid "no Stage-3 CONFIRMED decision". Now a FAIL still returns early, and a MANUAL only replaces a PASS. Fixture T13.
    • Defect, fixed. A Role homes cell with a trailing note, such as Owner (signed-in User who owns dashboards), did not name the role Owner (1 of 6 runs). The note in parentheses is now dropped before matching. Fixture T14.
    • Left as is, for the reviewer to decide. 3 wireframes in 2 of 6 runs write Page parameter: Puffin.Dashboard (new) or Puffin.ViewContext (built from …) and FAIL as "neither Module.Entity nor none — ". That is correct under design-artifacts.md ("exactly that form"), but workers produce the shape often. Accepting a trailing parenthetical would be a one-line parser change.
    • Left as is. One run headed its table "Homes and inboxes" instead of "Role homes", which gives MANUAL for all 3 actors. Another wrote User (as owner) for actor Owner, which is also MANUAL. Both are correct MANUALs.
    • In the remaining runs the facts line reads PASS with 3/3 actors and 9/9 wireframes.

Test evidence (head c90aad0, scoped fixtures only). Every run exited 0.

Fixture Result
test-interaction-model-gate.sh 48 passed, 0 failed. The pre-fix code gives 44 passed, 4 failed: the new T13 and T14 assertions bite.
test-bug03-gates.sh 55 ok, 0 FAIL
test-process-map.sh 84 ok, 0 FAIL. It covers the conflict region.
test-closeout.sh 34 passed, 0 failed
test-wrong-verdicts.sh 20 passed, 0 failed
test-wireframe-count.sh 5 ok, 0 FAIL
test-source-ledger.sh 55 passed, 0 failed
test-source-sufficiency-gate.sh 7 passed, 0 failed

These scripts also exit 0: bin/check-scripts.sh, bin/check-portability.sh, LEAKGUARD_ALLOW_NO_DENYLIST=1 bin/check-no-client-data.sh, and bin/check-pr-discipline.sh origin/master.

Word delta. bin/render-routing.sh --check is in sync. Baseline is 64,252 words on master and on head, against a budget of 80,000, so the delta is 0. None of the changed skill files is in the always-loaded set.

Still owed. A field run on a client project the maintainer chooses (rule 4). The worker-output probe above was run, but it is not that field run.

Review: pending independent review

🤖 Generated with Claude Code

… row (#291, part 2)

Once design/interaction-model.md exists, bin/lib/interaction-model-check.sh
(sourced by gate-check.sh) reports one FAIL per:
- BRD role (top-level actors) with no row in the "Role homes" table;
- BRD approval/user-task use case with neither an inbox row nor a stated reason;
- design/wireframes/*.html without a valid `Page parameter:` line in its
  wf-contract block (Module.Entity or "none — <reason>").
Any un-waived finding fails Stage 3. Findings are waived by hand in the
register ("Waived artifact interaction-model[/<unit>]: reason"); a project
adopted above stage 3 reports ADOPTED.

artifact-manifest.tsv gains the interaction-model row (stage 3, report-only),
so a missing artifact reports PENDING through the artifact check.
checkpoint-design.md asks "who lands where, and how does each role find its
work" next to the layout question; brd-to-build-plan.md Step 7 reads wire
points from the artifact (the build-plan consumer the manifest row cites).

Fixture: tests/wave2/test-interaction-model-gate.sh — base 10 passed/19 failed,
head 29/0. Synthetic trees only; no field run yet.

Refs #291

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw
…oles MANUAL, tighter task match, robust wf-contract parse

- Inbox coverage: any line under an "Inbox" heading (table row or -/*/1. bullet)
  names a task; the skill's own Step 2 writes inboxes as bullets.
- Roles: BRD actors are not the confirmed role model, so an actor with no
  "Role homes" row is MANUAL ("confirm it is a user role, or add a row
  `none — <reason>`"), never FAIL; a `none — <reason>` row covers it.
- Task selection: title starts with approve/review/sign-off (after an
  optional id prefix), title contains "user task", or mdlRefs names a user
  task. "View approval history", "Configure approval thresholds" and
  "Disapprove…" are no longer demanded an inbox.
- Wireframes: inline tags stripped before matching (<b>, <code>), block end
  found by <div> depth, hyphen and en dash accepted next to the em dash,
  CRLF read like LF.
- Wireframe FAILs print one remedy line (add the line, or waive per
  wireframe) — the expected path for wireframes drawn before the model.

Fixture: the reviewer's probe trees are cases T3c, T9–T12. 44/0 on head,
27/17 on the previous head 986f4e7, 19/25 on the base branch.

Refs #291

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw
@MendixMau

Copy link
Copy Markdown
Owner Author

After 1.0: part 2 of #291 is still not on master. This needs a rebase over bin/gate-check.sh and the one field run the description asks for.

Conflict: bin/gate-check.sh check_stage_3 — master added the process-map
freshness check where this branch added the interaction-model verdict.
Both kept: master's process-map check first, then the interaction-model
case.

Already on master and left as master has it: part 1 (#317) —
skills/interaction-model.md, its routing row, design-artifacts.md Step 2b
and the wf-contract block. Part 2 is not on master.

CHANGELOG: this branch's two lines had landed inside the released
v2026.10.19 section. They are now one line (the post-review wording) under
Unreleased.

Run against six Stage-3 worker outputs (a synthetic "puffin" requirements
project from the Stage-3 A/B runs), comparing master's gate-check with this
branch's. That found two defects, both fixed here:
- A MANUAL interaction-model finding returned before the register check,
  so a project with no Stage-3 CONFIRMED decision reported MANUAL (exit 2)
  where master reports FAIL (2 of 6 runs). FAIL still returns early;
  MANUAL now replaces only a PASS.
- A Role homes cell with a trailing note in parentheses ("Owner (signed-in
  User who owns dashboards)") did not name the role Owner (1 of 6 runs).
  The note is dropped before the match.
Fixture cases T13 and T14: 44/4 on the pre-fix code, 48/0 on head.

Refs #291

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LeNWZV2sVH62vkgfYh5u5
…med remedy, read "Homes" headings (#291 review)

Review fixes for #333:
- Page parameter accepts a trailing parenthesised note after Module.Entity
  (`Puffin.Dashboard (new)`); `Puffin Dashboard` and `Puffin.Dashboard or none`
  still FAIL. design-artifacts.md Step 3 says a trailing (note) is allowed.
- A Page parameter line that is there but malformed gets its own remedy (write
  the bare Module.Entity, optionally with a (note), or none — <reason>); the
  add-the-line remedy stays for a missing block or line.
- An interaction-model FAIL at Stage 3 also says "; also: no Stage-3 CONFIRMED
  decision" when the register has none.
- A heading naming "homes" (e.g. "Homes and inboxes") and a `Home` column read
  as the Role homes table; a heading naming both is read both ways, so inbox
  detection matches exactly the headings it did before.

Fixture cases T15-T18 (each fails on the previous head). Re-run against the six
Stage-3 worker outputs with a Stage-3 CONFIRMED row: S1, S3, PA2, PA3 PASS;
S2, PA1 MANUAL (unmatched actor names).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LeNWZV2sVH62vkgfYh5u5
…d as an inbox (review fix)

The previous round made the inbox heading test unconditional, so a heading such as
'Role homes and inbox notes' over a role table counted that table as inbox coverage
(a false PASS). Restore the 'role homes' exclusion; 'Homes and inboxes' is still read
both ways. New fixture case T18c fails on 97c9d89 (61/1) and passes here (62/0).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LeNWZV2sVH62vkgfYh5u5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants