Decompose architecture into 28 atomic implementation tasks
Break the @alkdev/taskgraph architecture specs into dependency-ordered implementation tasks across 8 component directories: setup, schema, error, graph, analysis, cost-benefit, frontmatter, api, and review. Each task has clear acceptance criteria referencing specific architecture docs. Three review tasks serve as quality gates at critical junction points (schemas-and-errors, graph-complete, complete-library). The dependency graph is validated acyclic with 9 topological levels enabling significant parallelism across independent work streams.
This commit is contained in:
54
tasks/implementation/frontmatter/file-io-and-serialize.md
Normal file
54
tasks/implementation/frontmatter/file-io-and-serialize.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
id: frontmatter/file-io-and-serialize
|
||||
name: Implement parseTaskFile, parseTaskDirectory, and serializeFrontmatter
|
||||
status: pending
|
||||
depends_on:
|
||||
- frontmatter/parsing
|
||||
- schema/input-schemas
|
||||
scope: moderate
|
||||
risk: low
|
||||
impact: component
|
||||
level: implementation
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Implement the file I/O frontmatter functions and the serializer. These are convenience wrappers for common use cases and the reverse operation (TaskInput → markdown).
|
||||
|
||||
Per [frontmatter.md](../../../docs/architecture/frontmatter.md):
|
||||
- `parseTaskFile`/`parseTaskDirectory` depend on `node:fs/promises` (Node.js only)
|
||||
- `parseFrontmatter` is runtime-agnostic
|
||||
- `serializeFrontmatter` uses `yaml.stringify()` for the data portion
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] `parseTaskFile(filePath: string): Promise<TaskInput>`:
|
||||
- Reads file using `node:fs/promises.readFile`
|
||||
- Delegates to `parseFrontmatter` for parsing and validation
|
||||
- Throws underlying Node.js error for I/O failures (ENOENT, EACCES, etc.)
|
||||
- [ ] `parseTaskDirectory(dirPath: string): Promise<TaskInput[]>`:
|
||||
- Recursive directory scanning via `node:fs/promises.readdir` with `{ recursive: true }` or manual recursion
|
||||
- Filters for `.md` files only
|
||||
- Silently skips files without valid `---`-delimited frontmatter (no error thrown, just omitted from results)
|
||||
- Throws underlying Node.js error for I/O failures
|
||||
- Uses `parseTaskFile` per file
|
||||
- [ ] `serializeFrontmatter(task: TaskInput, body?: string): string`:
|
||||
- Constructs `---`-delimited markdown output
|
||||
- Uses `yaml.stringify()` for the `TaskInput` data (excludes `id` from frontmatter? No — per Rust CLI convention, `id` comes from the filename, but in the schema it's part of `TaskInput`. Follow schema: include all `TaskInput` fields in the YAML.)
|
||||
- Appends body content (default: empty string) after closing `---`
|
||||
- Handles nullable fields correctly: `risk: null` → `risk: null` in YAML (explicit null), absent fields → omitted from YAML
|
||||
- [ ] File I/O functions documented as Node.js-only in JSDoc comments
|
||||
- [ ] Unit tests: parseTaskFile with temp file, parseTaskDirectory with temp dir (including non-.md files, missing frontmatter files), serializeFrontmatter round-trip parseFrontmatter(serializeFrontmatter(task)) ≈ task
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/frontmatter.md — file I/O functions, splitter, serializer
|
||||
- docs/architecture/schemas.md — TaskInput definition for serialization
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
51
tasks/implementation/frontmatter/parsing.md
Normal file
51
tasks/implementation/frontmatter/parsing.md
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
id: frontmatter/parsing
|
||||
name: Implement parseFrontmatter with YAML parsing and TypeBox validation
|
||||
status: pending
|
||||
depends_on:
|
||||
- frontmatter/splitter
|
||||
- schema/input-schemas
|
||||
- error/error-hierarchy
|
||||
scope: narrow
|
||||
risk: low
|
||||
impact: component
|
||||
level: implementation
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Implement `parseFrontmatter(markdown: string): TaskInput` in `src/frontmatter/parse.ts`. This combines the splitter with `yaml.parse()` and TypeBox validation. Invalid frontmatter throws `InvalidInputError` with field-level details.
|
||||
|
||||
Per [frontmatter.md](../../../docs/architecture/frontmatter.md), the function uses:
|
||||
- The custom splitter for `---` extraction
|
||||
- `yaml.parse()` (from `yaml` package, zero dependencies) for YAML↔JS conversion
|
||||
- TypeBox `Value.Check()` + `Value.Errors()` for structured field-level validation
|
||||
- `Value.Clean()` to strip unknown properties from untrusted input
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] `parseFrontmatter(markdown: string): TaskInput`:
|
||||
- Calls splitter to extract YAML string
|
||||
- Throws `InvalidInputError` if no valid frontmatter found (not `null` return — the caller expects TaskInput)
|
||||
- Calls `yaml.parse(yamlString)` for YAML 1.2 parsing
|
||||
- Runs `Value.Clean(TaskInput, parsed)` to strip unknown properties
|
||||
- Runs `Value.Check(TaskInput, cleaned)` — if fails, runs `Value.Errors()` and throws `InvalidInputError` with structured field/path/message/value details
|
||||
- Returns validated `TaskInput`
|
||||
- [ ] `InvalidInputError` is populated with field-level details from `Value.Errors()` output
|
||||
- [ ] YAML 1.2 used exclusively (the `yaml` package default) — no YAML 1.1 type coercion
|
||||
- [ ] Handles YAML `null` values (e.g., `risk:` with no value) correctly — becomes `null` in the TaskInput (distinction from absent field)
|
||||
- [ ] Unit tests: valid frontmatter, missing required fields, invalid enum values, unknown fields stripped, null categorical values preserved
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/frontmatter.md — parseFrontmatter, yaml package, no gray-matter
|
||||
- docs/architecture/schemas.md — TaskInput schema, Nullable helper
|
||||
- docs/architecture/errors-validation.md — InvalidInputError
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
45
tasks/implementation/frontmatter/splitter.md
Normal file
45
tasks/implementation/frontmatter/splitter.md
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
id: frontmatter/splitter
|
||||
name: Implement frontmatter delimiter splitter (~40 lines)
|
||||
status: pending
|
||||
depends_on:
|
||||
- setup/project-init
|
||||
scope: single
|
||||
risk: trivial
|
||||
impact: component
|
||||
level: implementation
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Implement the self-contained `---` delimited frontmatter splitter in `src/frontmatter/parse.ts`. This is a ~40 line function that extracts the YAML data string and markdown content body from a markdown string. No gray-matter dependency.
|
||||
|
||||
Per [frontmatter.md](../../../docs/architecture/frontmatter.md), the splitter:
|
||||
1. Checks for opening `---` delimiter (not `----`)
|
||||
2. Finds closing `\n---` delimiter
|
||||
3. Extracts YAML data string and markdown content body
|
||||
4. Returns `{ data: string, content: string }` or `null` if no valid frontmatter
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] `splitFrontmatter(markdown: string): { data: string; content: string } | null`
|
||||
- [ ] Opening `---` must be at the start of the file (or after optional BOM/whitespace on first line)
|
||||
- [ ] `----` (4+ dashes) is NOT a valid delimiter — only exact `---`
|
||||
- [ ] Closing delimiter requires `\n---` (newline before dashes)
|
||||
- [ ] Returns `null` if no valid frontmatter found
|
||||
- [ ] Returns `{ data: "", content: "" }` if frontmatter is present but empty (e.g., `---\n---`)
|
||||
- [ ] Content body starts after the closing `---` + newline
|
||||
- [ ] Handles edge cases: no closing delimiter (returns null), file with only `---\n---`, file with no `---` at all
|
||||
- [ ] Unit tests: standard frontmatter, no frontmatter, empty frontmatter, multi-line content, dashes in content body (shouldn't be treated as delimiters), 4+ dashes ignored
|
||||
|
||||
## References
|
||||
|
||||
- docs/architecture/frontmatter.md — splitter design, supply chain decision
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
Reference in New Issue
Block a user