feat(reader): STATUS.md parser + TS project scaffold [skip-tdd: visual for configs]
- vitest+TS scaffold (package.json/tsconfig/vitest.config = config artifacts) - src/parser.ts: parses STATUS.md blocks → StatusBlock[] - tests/parser.test.ts: 6 cases (single, multi, blocker, null-blocker, empty, unknown emoji) - fix emoji contract: align with using-tasks reality (⚪ open / 🔴 in_progress / 🟡 paused / 🔵 blocked / 🟢 done); reader-task acceptance + design doc updated Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
27
tests/fixtures/status-multi.md
vendored
Normal file
27
tests/fixtures/status-multi.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# Task Board
|
||||
_Updated: 2026-05-22_
|
||||
|
||||
## 🔴 [task-a] — active task
|
||||
**Status:** active
|
||||
**Where I stopped:** working on A.
|
||||
**Next action:** continue A.
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
|
||||
## 🔵 [task-b] — blocked task
|
||||
**Status:** blocked
|
||||
**Where I stopped:** waiting.
|
||||
**Next action:** unblock.
|
||||
**Blocker:** task-a
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
|
||||
## ⚪ [task-c] — ready task
|
||||
**Status:** ready
|
||||
**Where I stopped:** not started.
|
||||
**Next action:** start C.
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
10
tests/fixtures/status-single-block.md
vendored
Normal file
10
tests/fixtures/status-single-block.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# Task Board
|
||||
_Updated: 2026-05-22_
|
||||
|
||||
## 🔴 [board-viewer-pointers] — pre-impl: fill Domain conventions with design-context pointers
|
||||
**Status:** active
|
||||
**Where I stopped:** только что промочен дизайн.
|
||||
**Next action:** вставить блок в `.wiki/CLAUDE.md`.
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
56
tests/parser.test.ts
Normal file
56
tests/parser.test.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { parseStatus } from '../src/parser.ts';
|
||||
|
||||
const fixture = (name: string) =>
|
||||
readFileSync(join(__dirname, 'fixtures', name), 'utf8');
|
||||
|
||||
describe('parseStatus', () => {
|
||||
test('parses multiple blocks preserving order and statuses', () => {
|
||||
const blocks = parseStatus(fixture('status-multi.md'));
|
||||
|
||||
expect(blocks).toHaveLength(3);
|
||||
expect(blocks.map((b) => b.slug)).toEqual(['task-a', 'task-b', 'task-c']);
|
||||
expect(blocks.map((b) => b.status)).toEqual(['in_progress', 'blocked', 'open']);
|
||||
});
|
||||
|
||||
test('parses Blocker field when present', () => {
|
||||
const blocks = parseStatus(fixture('status-multi.md'));
|
||||
const blocked = blocks.find((b) => b.slug === 'task-b');
|
||||
|
||||
expect(blocked?.blocker).toBe('task-a');
|
||||
});
|
||||
|
||||
test('Blocker field is null when absent', () => {
|
||||
const blocks = parseStatus(fixture('status-multi.md'));
|
||||
const ready = blocks.find((b) => b.slug === 'task-c');
|
||||
|
||||
expect(ready?.blocker).toBeNull();
|
||||
});
|
||||
|
||||
test('returns empty array for STATUS.md without task blocks', () => {
|
||||
expect(parseStatus('# Task Board\n_Updated: 2026-05-22_\n\nNo tasks yet.\n')).toEqual([]);
|
||||
});
|
||||
|
||||
test('ignores blocks whose H2 has no known status emoji', () => {
|
||||
const text = '## 🚀 [some-task] — title\n**Status:** custom\n**Branch:** master\n---\n';
|
||||
expect(parseStatus(text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('parses a single active block with all fields', () => {
|
||||
const blocks = parseStatus(fixture('status-single-block.md'));
|
||||
|
||||
expect(blocks).toHaveLength(1);
|
||||
expect(blocks[0]).toEqual({
|
||||
slug: 'board-viewer-pointers',
|
||||
title: 'pre-impl: fill Domain conventions with design-context pointers',
|
||||
status: 'in_progress',
|
||||
status_emoji: '🔴',
|
||||
where_stopped: 'только что промочен дизайн.',
|
||||
next_action: 'вставить блок в `.wiki/CLAUDE.md`.',
|
||||
blocker: null,
|
||||
branch: 'master',
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user