* 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>
This commit is contained in:
@@ -441,25 +441,27 @@ describe('bug #3805: fast.md log_to_state must be schema-aware', () => {
|
||||
});
|
||||
|
||||
test('fast.md log_to_state step references the 5-column quick.md schema', () => {
|
||||
// The fix must handle the 5-col schema: | # | Description | Date | Commit | Directory |
|
||||
// Test that all 5 column names appear in the log_to_state step's context.
|
||||
// Extract the log_to_state step content to scope the check.
|
||||
// Schema-awareness no longer lives inline in fast.md as hardcoded column
|
||||
// names — it was moved to the schema-backed `quick-tasks-append` helper
|
||||
// (`appendQuickTaskRow` in markdown-table.cjs; #2133, ADR-2143 §3/§7),
|
||||
// which introspects the existing table's schema (5-col or 6-col) itself.
|
||||
// Assert the step delegates to that helper instead of requiring the old
|
||||
// literal column names.
|
||||
const logToStateMatch = fastMdContent.match(/<step name="log_to_state">([\s\S]*?)<\/step>/);
|
||||
assert.ok(logToStateMatch, 'fast.md must contain a <step name="log_to_state"> element');
|
||||
|
||||
const stepContent = logToStateMatch[1];
|
||||
|
||||
// All 5 column names from quick.md Step 7 must be referenced in the step.
|
||||
for (const col of QUICK_MD_STEP7_COLUMNS) {
|
||||
assert.ok(
|
||||
stepContent.toLowerCase().includes(col.toLowerCase()),
|
||||
[
|
||||
`fast.md log_to_state step does not reference column "${col}"`,
|
||||
`Expected all 5 columns from quick.md Step 7: ${QUICK_MD_STEP7_COLUMNS.join(', ')}`,
|
||||
`(${QUICK_MD_STEP7_COL_COUNT}-column schema)`,
|
||||
].join('\n')
|
||||
);
|
||||
}
|
||||
assert.ok(
|
||||
stepContent.includes('quick-tasks-append'),
|
||||
[
|
||||
'fast.md log_to_state step does not invoke the schema-aware quick-tasks-append helper.',
|
||||
'Schema-awareness now lives in the gsd-tools quick-tasks-append subcommand',
|
||||
`(appendQuickTaskRow, handling both the ${QUICK_MD_STEP7_COL_COUNT}-column quick.md Step 7 schema`,
|
||||
`${QUICK_MD_STEP7_COLUMNS.join(', ')} and the 6-column with-status variant) —`,
|
||||
'the step must delegate to it rather than hardcoding column names inline.',
|
||||
].join('\n')
|
||||
);
|
||||
});
|
||||
|
||||
test('fast.md log_to_state step skips STATE.md write on unrecognized schema', () => {
|
||||
|
||||
Reference in New Issue
Block a user