aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--todo.org44
1 files changed, 44 insertions, 0 deletions
diff --git a/todo.org b/todo.org
index ba7885b..d666170 100644
--- a/todo.org
+++ b/todo.org
@@ -58,6 +58,50 @@ Decisions settled with Craig, 2026-07-28, and shipped:
Remaining: nothing on the design. The change shipped in this session.
+** TODO [#B] wrap-org-table splits logical rows, and lint drives it :bug:
+:PROPERTIES:
+:LAST_REVIEWED: 2026-07-29
+:END:
+Reported by work 2026-07-28 against =arch-00-deepsat-platform-spec-draft.org=. Reproduced here.
+
+*** Verified
+
+Each of these is a measurement, re-run under adversarial review. The analysis I built on top of them was wrong three times, so this section is deliberately separated from the open questions below.
+
+- *The defect.* =wrap-org-table.el= turns one logical table row into two or more, by writing a rule between its continuation lines. Content survives; structure does not.
+- *Root cause.* =wot--continuation-group-p= (=wrap-org-table.el:168=) requires every line past the first to carry at least one empty cell. When a row overflows in every column its continuation line is fully populated, the predicate rejects the group, and =wot--logical-rows= appends each physical line as its own row (=:197=).
+- *Controlled A/B.* Rules present in both, continuation line's middle cell the only variable: blank merges, populated splits.
+- *Idempotence is broken.* Running the tool twice on its own correct output corrupts it. Pass 1 emits a properly rule-delimited three-line row; pass 2 splits it into three rows. The docstring at =:203-204= asserts the opposite, and =wot-reformat-is-idempotent= passes because its fixture overflows only one column.
+- *lint doesn't just miss it, it causes it.* =lint-org.el:424= calls the same predicate. Given the tool's own correct output — a rule after every logical row — lint reports "missing rule between rows — wrap-org-table.el reflows it". Nothing is missing. Follow that advice and the tool splits the row; lint then reports the result 0 mechanical, 0 judgment. Control: a conformant table whose continuation keeps an empty cell returns 0 and 0. So the loop is not two independent green lights, it is the linter manufacturing a false violation and certifying the damage it caused.
+- *A second path.* With no hlines at all, =wot--logical-rows= short-circuits (=:184=) before the predicate is reached, so every physical line becomes a row.
+- *Nothing invokes the tool unattended.* =todo-cleanup.el= names it in comments only; the entry-script guard from the 2026-07-09 incident holds.
+- *rulesets is exposed*: =todo.org= carries a four-row attachment-sanitization table with no rules between rows. Don't reflow it until the tool is fixed — reflowing is the trigger.
+
+*** Two fixes that were verified to work
+
+- *Conformant round-trip.* Replacing the predicate body with =(> (length group) 1)= — pure rule-delimited grouping, no emitter marker, no new field — makes the corrupting pass-1 output round-trip cleanly.
+- *Telling a continuation group from two real rows at runtime.* Provenance isn't available (=wot-reformat-table-string= receives a string), but the test is cheap: merge the group, re-wrap at the allocated widths, compare to the group as given. A continuation group reproduces itself under merge-then-wrap; two genuinely distinct short rows don't, because merged they fit on one line.
+
+Start with a red test from the double-run repro — it needs no unusual input and falsifies the docstring and the passing idempotence test together. Emission is already correct (=:222-224= emits one rule per element of =rows=), so the repair is entirely in how =rows= is computed.
+
+*Prefer the round-trip check to any detector.* work implemented the predicate-based detection I recommended and demonstrated it cannot discriminate at any threshold (2026-07-29, worked examples from their repo). Run bare it flags 144 files — essentially every table — because an ordinary header-plus-body table is one multi-line fully-populated group and rejecting it is the predicate working correctly. Add a per-row-ruled precondition and it cuts to 9, but at 9 it still mixes a genuinely wrapped row (=arch-09:40=, a header row whose second line continues the sentence) with two distinct rows legitimately sharing a rule (their =todo.org:117=, where splitting is the *right* answer). Same structural signature, opposite correct verdicts. The difference is whether one line continues the other as prose, which is semantics and not in the parse.
+
+So =lint-org.el:424= cannot simply inherit the repair, and a checker keyed on the predicate would train people to ignore it. The idempotence property is the checkable one: reflow twice and diff. It sidesteps detection entirely, because round-tripping the tool's own output correctly is true by construction and needs nobody to decide what a group means.
+
+*** Open questions
+
+- *What should no-hline input do?* My "refuse to reflow" instruction was wrong: adding rules to a ruleless table is the tool's main job, and =test-wrap-org-table.el:147= asserts exactly that. The real danger is narrower — a no-hline table where some line carries an empty cell, so a physical line might be a continuation. Needs a decision on refuse, ask, or heuristic.
+- *Which path bit work?* One question settles it: did the =arch-00= Document Status table have rules between its rows before the reflow? I inferred "probably secondary" from a file-level scan, which can't resolve a table-level incident.
+- *How exposed is work?* Partly resolved by their own implementation, 2026-07-29. *Four secondary-path files are exact.* The primary-path number is 9 under a per-row-ruled precondition, which they correctly label a floor on a population they cannot cleanly define rather than a measurement — the precondition also drops the minimal =a_full= fixture, which has only two groups. My earlier "24 secondary-path files" certification was not sound: their original signature also matches every correctly-reflowed table, so it never partitioned.
+- *Does the grade go up?* Currently Major x most users frequently = P2 = [#B] (any table you reflow that overflows every column, which is what a width violation sends you to the tool to fix). The lint-drives-it finding arrived after that grading and may lift it.
+
+*** Provenance
+
+work reverted their table and left it over-budget at 134 columns, correctly: an over-wide table is cosmetic, a table that says something else is not. I hit this same failure on 2026-07-27, wrote "reflowed a table into a worse shape and lint-org then passed it" into a session summary, and never filed it — which is why work met it three weeks later. Their framing beats the apology: a correct observation recorded and then read as fine is the same failure as a green check on a corrupted table.
+
+Process note for whoever picks this up. This task bounded out of its review loop at three rounds. Every finding across all three landed on inference, never on a measurement — the reproductions held throughout while the reasoning built on them was refuted repeatedly. Trust the Verified section; re-derive anything else.
+
+
** TODO [#B] Synced workflows link outside the synced set with ../../ :bug:
:PROPERTIES:
:LAST_REVIEWED: 2026-07-28