diff --git a/deferment.md b/deferment.md index 465ecfaf..9d3397c8 100644 --- a/deferment.md +++ b/deferment.md @@ -1280,6 +1280,55 @@ drivers), 3 carried-open archreview findings led by 01/S-1 (`AddressSpaceApplier --- +### 2026-08-10 (later) — #552 + #553 closed: the browse states, the merge preserves + +The two residuals the #550/#551 round exposed, again two isolated-worktree Opus agents, merged +`1f351250` (#552) + `62fe6c83` (#553). Consolidated verification on the merged tree: full build +clean; 8 suites / 3,362 tests green (AdminUI 1262, ControlPlane 261, Sql 363, Sql.Browser 79, +MTConnect 534, Modbus 373, S7 285, TwinCAT 205). + +- **#552 CLOSED** — Sql browse-commit emits a valid `rowSelector`. The **session states, the mapper + never infers** (the MQTT Sparkplug rule): `SqlBrowseSession` names a `topByTimestamp` candidate + from the column `DATA_TYPE` metadata it already reads (`MapColumnType == DateTime` — type only, + never a name heuristic; the fixture pins a `sample_ts TEXT` trap column), tie-break = first in + catalog order (every dialect's `ListColumnsSql` already orders by ordinal), zero extra queries + (pinned by a command-count test). New `SqlBrowseAddressFields` constants in `Driver.Sql.Contracts` + end the producer/consumer agree-by-coincidence on field names. No-candidate tables are refused + **in words at the modal** (`DescribeUncommittableLeaf` — names leaf, table, and the + whereColumn/whereValue fix, whose value is *data* no browse can supply); the emitted blob keeps + the wide-row shape so table/column survive into the typed editor. The blob's top-level + `timestampColumn` (source-timestamp) is deliberately NOT set — ordering by a column is not a + claim it timestamps the value. Emitted blobs are double-accepted (model validator AND the real + `SqlEquipmentTagParser`) with a pre-#552-bytes-refused control; the `RawTagConfigGateTests` Sql + leg flipped from records-the-gap to passes-the-gate. +- **#553 CLOSED — and characterization first shrank it.** On the current tree (post-#550/#551) + MTConnect's invalid-alias/invalid-cell legs were ALREADY caught (raw-key maps never round-trip); + the real defects were the model-backed maps' laundering (Modbus/S7 `"dataType":"Intt16"` → + silent `Int16`) and the **export side actively setting the re-import trap** (`ReadTypedColumns` + read only the canonical key → the typed column printed the *ignored* value, the residual kept the + *winning* alias). Fix is evidence preservation, not a second validator: + `ApplyTypedColumns` restores the base cell's own tokens over the model serialisation for every + key no non-blank column overrode (fragments compose byte-identically; the #551 gate stays the one + authority, now judging unlaundered evidence); `CsvTypedColumn.ReadKeys`/`OwnedJsonKeys` declare + the runtime's full spelling precedence once (MTConnect pairs), so firing columns clear + out-ranking aliases, the export residual strips them, and export cells show the effective value. + Override-contradiction semantics: column wins, OPENLY (review grid names each override) — #549's + doctrine is against *silent* rewrites. Falsification: guard neutered → exactly the 7 + defect-closers red while the #551 gate suites stayed 53/53 green (a layer in front of the gate, + not a replacement). +- **The deliberate-trap discipline in the #552 fixtures is worth copying:** the multi-candidate + table's column names are asserted to DISAGREE with alphabetical order (the tie-break test cannot + pass by luck), and the no-candidate table carries the exact `sample_ts TEXT` column a name + heuristic would have bound to. +- **Residuals filed, not folded in:** **#554** — authoring models validate only enum keys; non-enum + rules (Modbus address shapes, S7 stringLength bounds…) meet no gate until deploy, where the #551 + accept-gate-first Inspect names them — feedback latency, not silent death; closing it means the + models consult the same runtime parse the Inspects wrap, after a fleet survey (N-1 rule). + **#555** — `RawBrowseCommitMapper`'s fallback comment cites a `RawBrowseCommitMapperParityTests` + guard that DOES NOT EXIST; the "every browsable driver handled" invariant is unguarded (9 types + covered by hand-written InlineData) — write the `DriverTypeNames.All`-driven parity test the + comment already describes. + ### 2026-08-10 — #550 + #551 closed: the accept-gate-first fleet conversion The two #549-survey residuals, again two isolated-worktree Opus agents, merged `b50523b1` (#550) +