From 40b7000ec3b3a54317fe0d6af5fa6720c0ac40a9 Mon Sep 17 00:00:00 2001 From: GeneAI Date: Sat, 29 Aug 2026 00:07:19 -0400 Subject: [PATCH] fix: route progress markdown detail through _item_row (the #61 batch's missed fourth site) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A retro probe (2026-08-29) found the multi-line-detail defect #61 fixed for triage / assumption_review / confirm still live in _progress_lines: a detail carrying newlines was interpolated into the bullet, so every line starting `-` parsed as a NEW bullet. Both progress row styles (task-status and report) now route through _item_row — single-line details render byte-identical, multi-line ones become the indented block. Shipped via the first live consumer run of the hunk-review-as-triage encoding (board on thread q-forms-hunk-review-001's ruling): both hunks chair-ruled `apply`, rulings validated through collect_form_response. Also records the theme-cap bar chair-ruled at the 2026-08-28 retro in the theme docstring: raises buy FAMILIES, not rules. 825 tests passing. Co-Authored-By: Claude Opus 5 --- src/attune_forms/markdown_surface.py | 9 +++++--- src/attune_forms/theme.py | 4 +++- tests/test_markdown_surface.py | 32 ++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/attune_forms/markdown_surface.py b/src/attune_forms/markdown_surface.py index f8bf5be..be75a4f 100644 --- a/src/attune_forms/markdown_surface.py +++ b/src/attune_forms/markdown_surface.py @@ -117,12 +117,15 @@ def _progress_lines(q: FormQuestion) -> list[str]: for item in q.progress_items or []: label = item.get("label", "") status = item.get("status", "") - detail = f" — {item['detail']}" if item.get("detail") else "" if q.progress_style == "report": - lines.append(f"- `{status}` {label}{detail}") + head = f"- `{status}` {label}" else: icon = PROGRESS_STATUS_ICONS.get(status, "•") - lines.append(f"- {icon} {label}{detail}") + head = f"- {icon} {label}" + # _item_row keeps a single-line detail inline (unchanged render) + # and moves a multi-line one below the bullet — the same fix the + # other item-bearing constructs got in the #61 batch. + lines.extend(_item_row(head, item.get("detail"))) if q.options: head = ( "Pick one to go deeper:" diff --git a/src/attune_forms/theme.py b/src/attune_forms/theme.py index ade384d..d17de8e 100644 --- a/src/attune_forms/theme.py +++ b/src/attune_forms/theme.py @@ -28,7 +28,9 @@ excerpt — keep its newlines instead of collapsing inside a flex row, across triage / assumption_review / progress / confirm at once; a trim to fit under 10 KB was offered and declined) — no fonts, no icon -fonts, no images, no @import. +fonts, no images, no @import. Bar for the next raise (chair-ruled at +the 2026-08-28 retro): raises buy FAMILIES, not rules — a single rule +that fits after a trim does not clear it. Copyright 2026 Smart-AI-Memory Licensed under Apache 2.0 diff --git a/tests/test_markdown_surface.py b/tests/test_markdown_surface.py index bb51d5e..6c01f45 100644 --- a/tests/test_markdown_surface.py +++ b/tests/test_markdown_surface.py @@ -288,3 +288,35 @@ def test_multiline_detail_keeps_the_skeleton_round_tripping() -> None: form = form_from_dict(_hunk_board()) skeleton = _skeleton(form_to_markdown(form)) assert skeleton["answers"] == {"hunks": {"src/bridge.py@a1b2c3d:88-96": None}} + + +def test_progress_multiline_detail_stays_inside_its_row() -> None: + """PROGRESS rows route detail through _item_row like the other + item-bearing constructs (retro probe 2026-08-29: the #61 batch + missed this fourth site).""" + md = form_to_markdown( + form_from_dict( + { + "title": "T", + "fields": [ + { + "id": "p", + "type": "progress", + "text": "Status?", + "progress_items": [ + { + "label": "migrate", + "status": "done", + "detail": "a\n- old\n+ new", + }, + {"label": "ship", "status": "blocked", "detail": "one-liner"}, + ], + "options": ["ship"], + } + ], + } + ) + ) + assert " - old" in md + assert not any(ln.startswith("- old") for ln in md.splitlines()) + assert "- ✕ ship — one-liner" in md