Skip to content

Commit 704fe5c

Browse files
committed
Add Helix spec/design/test plan for doc DAG
1 parent 7b200c1 commit 704fe5c

5 files changed

Lines changed: 284 additions & 0 deletions

File tree

docs/helix/01-frame/feature-registry.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ This registry tracks the core Dun features and their current status.
1818
| F-012 | External plugin loading | P2 | Planned | Load plugin dirs via config (no spec file yet) |
1919
| F-013 | Reserved | - | Planned | (no spec file yet) |
2020
| F-014 | Go Quality Checks | P0 | In progress | Tests, coverage, vet, staticcheck |
21+
| F-016 | Doc DAG + Review Stamps | P0 | Planned | Frontmatter DAG, stale detection, stamp command |
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Feature Spec: F-016 Doc DAG + Review Stamps
2+
3+
## Summary
4+
5+
Track documentation dependencies via frontmatter-defined DAGs, detect missing
6+
and stale artifacts, and drive updates through prompt envelopes and review
7+
stamps.
8+
9+
## Requirements
10+
11+
- Parse `dun` frontmatter in Markdown documents to define:
12+
- stable `id`
13+
- `depends_on` relationships
14+
- `prompt` and `inputs`
15+
- `review` stamps
16+
- Support an optional graph file for required roots and default prompts.
17+
- Compute deterministic content hashes that include frontmatter (excluding
18+
`dun.review`).
19+
- Determine stale documents when parent hashes differ from `review.deps`.
20+
- Determine missing documents when required roots or required descendants are
21+
absent.
22+
- Emit prompt envelopes for missing or stale documents using frontmatter
23+
prompt settings or graph defaults.
24+
- Provide `dun stamp` to update `dun.review` fields in docs.
25+
- Keep output deterministic for a given repo state.
26+
27+
## Inputs
28+
29+
- Markdown documents with `dun` frontmatter.
30+
- Optional graph files under `.dun/graphs/*.yaml`.
31+
32+
## Acceptance Criteria
33+
34+
- When a parent document changes, all descendants are marked stale until they
35+
are stamped with updated parent hashes.
36+
- When a required document is missing, Dun reports it as missing with a prompt
37+
to create it.
38+
- `dun stamp` updates `dun.review.self_hash` and `dun.review.deps`.
39+
- Prompt envelopes include parent context inputs by default.
40+
- Results are stable across repeated runs with the same repo state.
41+
42+
## Traceability
43+
44+
- Supports doc reconciliation (F-006) by providing explicit dependency
45+
tracking and review stamps.
46+
- Supports agent operators by surfacing actionable prompts for stale docs.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# US-013: Doc DAG With Review Stamps
2+
3+
As an agent operator, I want Dun to track documentation dependencies via
4+
frontmatter and review stamps so I can quickly see which docs are missing or
5+
stale when upstream requirements change.
6+
7+
## Acceptance Criteria
8+
9+
- A document with a changed parent is flagged as stale until re-stamped.
10+
- Required documents missing from the DAG are reported as missing.
11+
- Dun emits prompts for stale or missing documents with parent context.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Solution Design: Doc DAG + Review Stamps
2+
3+
## Problem
4+
5+
Documentation dependencies are implicit, so Dun cannot reliably identify
6+
which artifacts are missing or stale when upstream docs change.
7+
8+
## Goals
9+
10+
- Encode dependencies in doc frontmatter.
11+
- Detect missing and stale docs deterministically.
12+
- Drive updates through prompt envelopes.
13+
- Persist review stamps in documents (no external cache).
14+
15+
## Approach
16+
17+
1. **Frontmatter parsing**: read `dun` blocks from Markdown to register nodes.
18+
2. **Optional graph defaults**: load `.dun/graphs/*.yaml` for required roots
19+
and default prompts for missing docs.
20+
3. **Hashing**: compute a stable hash of each doc including frontmatter,
21+
excluding `dun.review`.
22+
4. **Staleness**: compare parent hashes to `dun.review.deps`.
23+
5. **Missing detection**: flag required roots or required descendants with no
24+
files.
25+
6. **Prompting**: emit prompts for missing or stale docs with parent inputs.
26+
7. **Stamping**: `dun stamp` writes updated review hashes to frontmatter.
27+
28+
## Components
29+
30+
- **Frontmatter Reader**: extracts `dun` config and review stamps.
31+
- **Doc Graph Builder**: builds the DAG from frontmatter + graph defaults.
32+
- **Hasher**: computes doc content hashes.
33+
- **Doc-DAG Check**: emits missing/stale issues and prompts.
34+
- **Stamp Command**: updates review stamps in files.
35+
36+
## Data Flow
37+
38+
1. `dun check` runs `doc-dag` check.
39+
2. Frontmatter reader registers nodes and dependencies.
40+
3. Graph builder adds required roots/defaults.
41+
4. Hasher computes current hashes.
42+
5. Staleness/missing detection runs.
43+
6. Prompt envelopes are emitted for actionable nodes.
44+
45+
## Data Model
46+
47+
- **Node**: id, path, depends_on, prompt, inputs, review
48+
- **Review**: self_hash, deps map, reviewed_at
49+
- **Edge**: parent -> child from `depends_on`
50+
51+
## Hashing Rules
52+
53+
- Hash includes:
54+
- Markdown body
55+
- Frontmatter contents excluding `dun.review`
56+
- Normalize line endings to `\n`.
57+
- Use a stable YAML encoding for the remaining frontmatter.
58+
59+
## Interface Changes
60+
61+
- New check type: `doc-dag`.
62+
- New command: `dun stamp`.
63+
- Optional graph files: `.dun/graphs/*.yaml`.
64+
65+
## Files (Planned)
66+
67+
- `internal/dun/doc_dag.go` (graph build + staleness detection)
68+
- `internal/dun/frontmatter.go` (parse/serialize frontmatter)
69+
- `internal/dun/hash.go` (doc hashing)
70+
- `internal/dun/stamp.go` (stamp logic)
71+
- `cmd/dun/main.go` (wire `dun stamp`)
72+
73+
## Open Questions
74+
75+
- Should `reviewed_at` be used for display only, or validated?
76+
- How should collection nodes (e.g., US-* chains) map IDs deterministically?
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# TP-013: Doc DAG + Review Stamps
2+
3+
**User Story**: US-013
4+
**Version**: 1.0.0
5+
**Date**: 2026-02-02
6+
**Status**: Draft
7+
**Author**: oscar
8+
9+
## 1. Acceptance Criteria
10+
11+
From US-013:
12+
13+
| ID | Acceptance Criterion |
14+
|----|---------------------|
15+
| AC-1 | A document with a changed parent is flagged as stale until re-stamped |
16+
| AC-2 | Required documents missing from the DAG are reported as missing |
17+
| AC-3 | Dun emits prompts for stale/missing docs with parent context |
18+
19+
## 2. Existing Test Coverage
20+
21+
### 2.1 Tests Mapped to Acceptance Criteria
22+
23+
| AC | Existing Test | File | Status |
24+
|----|---------------|------|--------|
25+
| AC-1 | None | - | Missing |
26+
| AC-2 | None | - | Missing |
27+
| AC-3 | None | - | Missing |
28+
29+
### 2.2 Coverage Analysis
30+
31+
No existing tests cover doc-DAG behavior. All acceptance criteria are gaps.
32+
33+
## 3. Test Gaps
34+
35+
### 3.1 Critical Gaps (P0)
36+
37+
| Gap ID | Description | Priority | Acceptance Criteria |
38+
|--------|-------------|----------|---------------------|
39+
| GAP-001 | No test for cascade stale detection | P0 | AC-1 |
40+
| GAP-002 | No test for missing required roots | P0 | AC-2 |
41+
| GAP-003 | No test for prompt envelope content | P0 | AC-3 |
42+
43+
### 3.2 Secondary Gaps (P1)
44+
45+
| Gap ID | Description | Priority | Acceptance Criteria |
46+
|--------|-------------|----------|---------------------|
47+
| GAP-004 | No test for `dun stamp` updating review deps | P1 | AC-1 |
48+
| GAP-005 | No test for deterministic ordering | P1 | AC-3 |
49+
50+
## 4. Proposed Test Cases
51+
52+
### 4.1 Unit Tests
53+
54+
#### TC-001: Frontmatter Parsing
55+
**File**: `internal/dun/frontmatter_test.go`
56+
**Priority**: P0
57+
**Covers**: AC-1, AC-3
58+
59+
```go
60+
func TestFrontmatterParseDunBlock(t *testing.T) {
61+
// Given: a markdown file with dun frontmatter
62+
// When: parsed
63+
// Then: id, depends_on, prompt, review fields are extracted
64+
}
65+
```
66+
67+
#### TC-002: Hash Excludes Review
68+
**File**: `internal/dun/hash_test.go`
69+
**Priority**: P0
70+
**Covers**: AC-1
71+
72+
```go
73+
func TestHashExcludesReviewSection(t *testing.T) {
74+
// Given: same doc with different dun.review
75+
// Then: hash is identical
76+
}
77+
```
78+
79+
#### TC-003: Missing Required Root
80+
**File**: `internal/dun/doc_dag_test.go`
81+
**Priority**: P0
82+
**Covers**: AC-2
83+
84+
```go
85+
func TestDocDagMissingRequiredRoot(t *testing.T) {
86+
// Given: graph file requiring prd.md, file missing
87+
// Then: missing issue is emitted
88+
}
89+
```
90+
91+
#### TC-004: Stamp Updates Review Deps
92+
**File**: `internal/dun/stamp_test.go`
93+
**Priority**: P1
94+
**Covers**: AC-1
95+
96+
```go
97+
func TestStampUpdatesReviewDeps(t *testing.T) {
98+
// Given: parent + child
99+
// When: dun stamp runs on child
100+
// Then: review.deps[parent] matches current parent hash
101+
}
102+
```
103+
104+
### 4.2 Integration Tests (Required for Day 1)
105+
106+
#### TC-005: Cascade Stale Detection (End-to-End)
107+
**File**: `internal/dun/engine_test.go`
108+
**Priority**: P0
109+
**Covers**: AC-1, AC-3
110+
111+
```go
112+
func TestDocDagCascadeStale(t *testing.T) {
113+
// Given: fixture repo with parent+child, stamped
114+
// When: parent changes
115+
// Then: child is stale and prompt is emitted
116+
}
117+
```
118+
119+
**Fixture**: `internal/testdata/repos/doc-dag-cascade/`
120+
- `docs/helix/01-frame/prd.md` with dun.frontmatter
121+
- `docs/helix/02-design/architecture.md` depending on PRD
122+
- Both have review stamps reflecting initial hashes
123+
124+
**Expected**:
125+
- `doc-dag` check status = warn/fail
126+
- Issue `stale:helix.architecture`
127+
- Prompt envelope includes PRD content as input
128+
129+
#### TC-006: Missing Required Doc Prompt
130+
**File**: `internal/dun/engine_test.go`
131+
**Priority**: P0
132+
**Covers**: AC-2, AC-3
133+
134+
```go
135+
func TestDocDagMissingRequiredPrompt(t *testing.T) {
136+
// Given: graph requires prd.md, file missing
137+
// Then: prompt envelope for prd creation is emitted
138+
}
139+
```
140+
141+
## 5. Test Data Plan
142+
143+
- New fixtures under `internal/testdata/repos/doc-dag-*`.
144+
- Graph file under `.dun/graphs/helix.yaml` in fixtures.
145+
- Minimal prompt templates under `internal/plugins/builtin/helix/prompts/` (or test-local prompt stubs).
146+
147+
## 6. Exit Criteria
148+
149+
- All P0 tests implemented and passing.
150+
- Integration test TC-005 confirms cascade detection from day 1.

0 commit comments

Comments
 (0)