* chore(#2143): markdown table model + schema registry + fail-loud pilot — Phase 1
Phase 1 of epic #2143 (ADR-2143): consolidate markdown table parsing onto a
canonical seam and migrate the pilot reader.
- Add src/markdown-table.cts: parseMarkdownTable (GFM tables -> typed
{columns, rows} addressed by column NAME; ragged rows are typed parse
errors, not silent), a single-source TABLE_SCHEMAS registry
(RoadmapProgress / RequirementsTraceability / QuickTasks / Security, with
variants under one id), matchTableSchema, and findTableBySchema. Result<T>
is scoped to this seam (distinct from the dispatch Result).
- Migrate deriveProgressFromRoadmap (src/phase-lifecycle.cts) off the
position-anchored regex to name-based resolution via the seam — fixes#2137
(the 5-column milestone-grouped Progress table previously returned all-null).
- Add a schema-backed `gsd-tools quick-tasks-append` subcommand and route
fast.md's log_to_state through it, retiring the inline `awk NF-2` column
arithmetic — fixes#2133 (addresses #2012, #2119). Cell values are escaped
(| and newlines) and the STATE.md read-modify-write is atomic under
readModifyWriteStateMd (lost-update race, cf. #500/#905/#1230).
- Writer/reader/template parity test guards TABLE_SCHEMAS against drift
(ADR-2143 §3 Generative-Fix-Divergence).
Registration: .gitignore, eslint.config.mjs, docs/INVENTORY.md +
INVENTORY-MANIFEST.json, CONTEXT.md glossary, docs/CLI-TOOLS.md.
Behaviour-preserving for the canonical 4-column Progress table; the named
bugs are driven fail-first. Extend-never-mutate (ADR-2143 §2).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore(#2242): backfill changeset PR number (#2248)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(#2242): escape backslash before pipe in markdown-table cell escaping
CodeQL js/incomplete-sanitization (high): escapeCell escaped | -> \| but not
the backslash itself. Now escapes \ -> \\ before | -> \|, and splitTableRow
unescapes both \\ -> \ and \| -> | symmetrically so cell values (incl.
literal backslashes) round-trip exactly. Added backslash round-trip tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(#2242): read ROADMAP Progress table by column name — supersede #2168 ad-hoc scan
Rebase reconciliation with #2168 (the tactical #2137 fix that marked itself
"pending #2143"). deriveProgressFromRoadmap now resolves the Progress table via
a new seam helper findTableWithColumns (first table whose header is a superset of
Phase/Plans Complete/Status/Completed, any order, extra columns ignored) and reads
cells by NAME — order/injection-invariant per ADR-2143 §3 — instead of the exact
TABLE_SCHEMAS match. This satisfies #2168's column-invariance property test while
staying seam-based and preserving its `## Progress` scoping (#2012/#1445).
Ragged Progress tables now resolve to null (ADR-2143 fail-loud); updated the stale
state.test.cjs assertion that predated the Phase-1 migration.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>