Skip to content

accommodations: make the hard constraint hard - #4

Open
inquerium wants to merge 1 commit into
corps-step-3from
corps-step-4
Open

inquerium wants to merge 1 commit into
corps-step-3from
corps-step-4

Conversation

@inquerium

Copy link
Copy Markdown
Owner

Stand-up step 4. Stacked on #3.

The gap

SPEC.md has always said every generated interface must honor every active accommodation, and called it a hard constraint rather than a hint. It was a hint. validateInterface took a string of HTML and never learned who the activity was for, so the only thing standing between a child who cannot be timed and a countdown was the tutor remembering.

It now takes the child's standing instructions, and a violation refuses the save the same way a syntax error does. Four kinds checked mechanically: countdowns, typography, whether anything on the page can be heard, unguarded motion.

The rule that governs the rest

A check that cannot be performed does not pass. It reports that it could not be performed.

Silent success on an accommodation nobody wrote a check for is worse than having no checker, because a reviewer reading a clean report reasonably concludes the activity was verified. Every unknown kind, and every kind that cannot be settled from source text, comes back unverifiable and appears in the parent's review under a heading that says so.

Contrast is the honest example. It needs the page rendered and the computed colours compared, so it is never claimed either way. Inventing a proxy would be worse than leaving it to a person.

The audit caught a defect in the checker on its first run

Accommodation kinds are free text, written by an adult about their own child. no_read_aloud_pressure matched the audio check — which then refused every page that did not speak. The precise inversion of what the parent asked for.

A check that can invert an instruction is worse than no check. That phrasing now falls through to unverifiable, and the rule is written into the lane's charter: when a kind is phrased as a prohibition, a check that turns it into a requirement is worse than no check, and abstaining is correct.

Coverage, reported honestly

ok    no_timers                countdown
ok    dyslexia_typography      text_too_small, italics, serif_only
ok    audio_first              no_audio
ok    reduced_motion           unguarded_motion

coverage 5/10 kinds mechanically checked

unchecked  high_contrast
unchecked  needs_movement_breaks
unchecked  large_targets
unchecked  no_read_aloud_pressure
unchecked  single_task_at_a_time

Five of ten, reported as five of ten. The other five rest on an adult reading the activity, which is the truth and is the marshal's backlog rather than a number to round up. The watcher fires when that set grows, and fires harder when a check stops firing — a check that no longer catches violations is worse than one that never existed, because its report reads clean.

One rule I broke, named rather than buried

This touches src/mcp/tools.ts, which the engineering-lane charter forbids its agents from editing. That rule is about widening what the unattended tutor can reach. This narrows it: save_interface now refuses work it previously accepted. Still worth naming rather than letting a reviewer find the exception themselves.

Checks

npm test passes, 245 tests (16 new). npm run accommodations is the marshal's instrument.

CI cannot run upstream: the account is billing-locked.

🤖 Generated with Claude Code

SPEC.md has always said every generated interface must honor every active
accommodation, and called it a hard constraint rather than a hint. It was a
hint. validateInterface took a string of HTML and never learned who the
activity was for, so the only thing between a child who cannot be timed and a
countdown was the tutor remembering. test/fixtures.test.ts pinned that gap by
asserting the function took one argument.

It now takes the child's standing instructions, and a violation refuses the
save the same way a syntax error does: the tutor is told what it broke and
retries, and a child never meets the version that ignored them. Four kinds are
checked mechanically. Countdowns, typography, whether anything on the page can
be heard, and unguarded motion.

The rule that governs the rest of it: a check that cannot be performed does not
pass. It reports that it could not be performed. Silent success on an
accommodation nobody wrote a check for is worse than having no checker at all,
because a reviewer reading a clean report reasonably concludes the activity was
verified. Every unknown kind, and every kind that cannot be settled from source
text, comes back unverifiable and appears in the parent's review under a
heading that says so.

Contrast is the honest example. It needs the page rendered and the computed
colours compared, so it is never claimed either way, and inventing a proxy for
it would be worse than leaving it to a person.

The audit caught a defect in the checker on its first run, which is the reason
that instrument exists. Accommodation kinds are free text written by an adult
about their own child, and "no_read_aloud_pressure" matched the audio check,
which then refused every page that did not speak. That is the precise inversion
of what the parent asked for. A check that can invert an instruction is worse
than no check, so that phrasing now falls through to unverifiable, and the rule
is written into the lane's charter.

Coverage is five of ten kinds and is reported as five of ten. The other five
rest on an adult reading the activity, which is the truth and is the marshal's
backlog rather than a number to round up.

This touches src/mcp/tools.ts, which the engineering-lane charter forbids its
agents from editing. The rule is about widening what the unattended tutor can
reach. This narrows it: save_interface now refuses work it previously accepted.
Worth naming rather than letting a reader discover the exception on their own.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant