fix(#2337): capture and surface todo severity (#2381)

add-todo.md gains a confirm-based infer_severity step (infer from the blocker/major/minor/cosmetic taxonomy, confirm via AskUserQuestion with TEXT_MODE fallback, before writing) and a severity frontmatter field. cmdListTodos and cmdInitTodos now surface severity, backward-compatible (key omitted when absent), in parity.

Closes #2337. Admin-merged (self-review bypass) with full green CI.
This commit is contained in:
Tom Boucher
2026-07-17 14:01:38 -04:00
committed by GitHub
parent dcb4954131
commit b0f672f88c
26 changed files with 185 additions and 20 deletions

View File

@@ -165,7 +165,7 @@ function cmdListTodos(cwd: string, area: string | undefined, raw: boolean): void
const pendingDir = path.join(planningDir(cwd), 'todos', 'pending');
let count = 0;
const todos: Array<{ file: string; created: string; title: string; area: string; path: string }> = [];
const todos: Array<{ file: string; created: string; title: string; area: string; path: string; severity?: string }> = [];
try {
const files = fs.readdirSync(pendingDir).filter(f => f.endsWith('.md'));
@@ -176,6 +176,9 @@ function cmdListTodos(cwd: string, area: string | undefined, raw: boolean): void
const createdMatch = content.match(/^created:\s*(.+)$/m);
const titleMatch = content.match(/^title:\s*(.+)$/m);
const areaMatch = content.match(/^area:\s*(.+)$/m);
// #2337: surface severity when present. Omit the key entirely for todos
// with no severity line so existing consumers of this JSON are unaffected.
const severityMatch = content.match(/^severity:\s*(.+)$/m);
const todoArea = areaMatch ? areaMatch[1].trim() : 'general';
@@ -189,6 +192,7 @@ function cmdListTodos(cwd: string, area: string | undefined, raw: boolean): void
title: titleMatch ? titleMatch[1].trim() : 'Untitled',
area: todoArea,
path: toPosixPath(path.relative(cwd, path.join(pendingDir, file))),
...(severityMatch ? { severity: severityMatch[1].trim() } : {}),
});
}
} catch { /* intentionally empty */ }

View File

@@ -1164,6 +1164,9 @@ function cmdInitTodos(cwd: string, area: string | undefined, raw: boolean): void
const createdMatch = content.match(/^created:\s*(.+)$/m);
const titleMatch = content.match(/^title:\s*(.+)$/m);
const areaMatch = content.match(/^area:\s*(.+)$/m);
// #2337: kept in parity with cmdListTodos — surface severity when
// present, omit the key entirely for todos with no severity line.
const severityMatch = content.match(/^severity:\s*(.+)$/m);
const todoArea = areaMatch ? areaMatch[1].trim() : 'general';
if (area && todoArea !== area) continue;
@@ -1180,6 +1183,7 @@ function cmdInitTodos(cwd: string, area: string | undefined, raw: boolean): void
path.join(planningDir(cwd), 'todos', 'pending', file),
),
),
...(severityMatch ? { severity: severityMatch[1].trim() } : {}),
});
} catch {
/* intentionally empty */