-
Notifications
You must be signed in to change notification settings - Fork 0
OM-M1.1: the model takes the front door, protocol moves to pyquadcortex.protocol #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3e3a1f5
818b891
c31a24a
34b3ddb
11a180c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -73,3 +73,20 @@ Records are append-only once `Decided` and built upon: a shipped decision is nev | |
| - **Open Questions:** None. | ||
| - **Rationale:** The model becomes the documented front door the moment it exists, with no release where `connect()` is ambiguous. The protocol layer loses nothing: same API, same support, one import deeper. | ||
| - **Consequences:** Refines ADR-0004's "additive namespace" consequence: the model is still additive code-wise and the protocol API is still public and unchanged, but import paths flip at M1 - existing 0.x scripts update one import line. The flip and its changelog/readme messaging land in the M1 Epic. The Intent Brief's "Additive, not breaking" requirement is amended to match (owner decision, 2026-08-05). | ||
|
|
||
| ## ADR-0007: The model may represent a control whose wire path is still open | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This rule has no code, no exception type and no test yet, which is consistent but leaves the first user of it with nothing to inherit. I am not calling this a defect. The ADR says the exception shape stays open until M3, the pull request says no tempo surface ships here, and The thing worth noticing is that the four-test safety case in this change does not touch ADR-0007 at all, so nothing mechanical will stop the first M3 surface from guessing. Two decisions are much cheaper to pin now, while the reasoning is fresh, than to retrofit later: The refusal wants its own exported exception. The pattern already exists here in There also needs to be a way to ask without touching. With a property that raises, "read it if you can, skip it if you cannot" forces a When the first refusing property does land, the test worth writing is that the refusal happens with a client whose
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed it is not a defect, and I have not turned it into code. Not resolving. ADR-0007's Open Questions already parks the exception shape until the first such Your two constraints are the useful part and I think both are right. Reusing I did correct one fact in the record while I was in it. It said all three tests Whether to pin the exception and the predicate now is your call. |
||
|
|
||
| - **Status:** Decided (2026-08-11) | ||
| - **Decision:** When we understand what a control does on the unit but have not found the message that drives it, the model represents the control the way the unit presents it, and refuses the operation it cannot yet perform. It never guesses. This is a different case from design principle 3's "omission over caveat", which covers a control whose behaviour ON THE DEVICE we do not understand; that one is still omitted. | ||
| - **Context:** TEMPO MODE is the case that raised this. The unit's Tempo menu has a GLOBAL / PRESET switch. In PRESET mode the tempo and all seven metronome settings are stored in the preset, which is exactly what the wire shows: every preset carries a `TempoControl` block and it is writable (`protocol.md`, "Per-preset tempo, LED and metronome"). Cortex Control offers the same switch, so some route to it exists. What we have not found is that route. Three independent tests watched for a broadcast when the switch is changed, and saw nothing; two of the three also committed the menu, and the third's action script records only the toggle. The design doc recorded all of this as "not on the wire at all". That conclusion is now understood to be too strong. **"Broadcasts nothing" is not "not readable".** A control the device never announces may still answer a READ, or be carried in a message we have not decoded, and no test so far has ruled either out. | ||
| - **Options:** | ||
| - **(a) Model the switch, refuse what cannot be driven - chosen.** The player sees a switch, so the model has one. Reading it, or writing it, raises with a message saying the wire path is not known yet. | ||
| - **(b) Omit tempo from the model entirely.** Throws away a control we do understand - the BPM and the whole metronome are confirmed writable - to avoid one field we do not. | ||
| - **(c) Let a tempo write through and work out the scope afterwards.** A guess behind a clean API. The write lands in whichever scope the unit happens to be in, and the caller is told nothing. This is the "the model lies" failure the Intent names, and it is the worst of the three because it looks like it worked. | ||
| - **Open Questions:** How the refusal reads in practice - one exception type for "no wire path known", or a per-feature message. Settled when the first such control ships, which is M3 at the earliest. | ||
| - **Rationale:** The model's job is to look like the unit. A switch the player can see, missing from the model with no explanation, is its own kind of lie. Refusing is honest in both directions: it tells the caller the control is real and tells them we cannot drive it. It also keeps the door open, because a model with a `mode` on it has somewhere to put the answer the day the wire path turns up. Option (c) is rejected on the project's oldest rule: the device accepts a write it does not understand and says nothing, so a guess and a success are indistinguishable to the caller. | ||
| - **Consequences:** | ||
| - The design doc's `Tempo` gains `mode`, and the appendix's "Tempo MODE" row changes from a permanent omission to an open protocol investigation. `docs/domain-model.md` §13 says the same. | ||
| - Finding the MODE wire path becomes a prerequisite of M3's device-settings Epic, not of M1. **No tempo surface ships at M1**, so nothing in this record is user-visible yet. | ||
| - Design principle 3 keeps its meaning and gains a boundary: omission is for behaviour we do not understand, refusal is for behaviour we understand and cannot yet drive. A record that says which one applies is now expected of anything the model leaves out. | ||
| - This does not license modelling controls on a hunch. It applies where the unit's behaviour is confirmed and only the message is missing; a control we have not understood on the hardware is still omitted. | ||
Uh oh!
There was an error while loading. Please reload this page.