Module: Parsing & Validation Priority: MEDIUM Estimated Duration: 2-3 days Dependencies: tasks.markdown-parser.md, tasks.linter.md Status: COMPLETE ✅
Add support for the @doc annotation, which provides semantic linking to external documentation (design docs, requirements, specifications). Unlike @depends-on which expresses blocking dependencies, @doc indicates "read this for context"—informational, non-blocking references.
This enables lean task files that link to richer context on demand, supporting both human developers and agents who can selectively fetch documentation when needed.
@doc: ../docs/design-doc.md
@doc: ../docs/design-doc.md#section-7.2
@doc: requirements/auth-spec.md- Value is a validated relative path (must exist)
- Optional fragment identifier for section targeting
- Multiple
@docannotations allowed per file/task - Can appear at file level (header) or task level (inline metadata)
- Update annotation key whitelist
- Add "doc" to built-in keys in parser
- Update
is_annotation_allowed()inLintContext
- Define
DocRefstruct-
path: String- relative path to document -
fragment: Option<String>- optional#sectionfragment
-
- Implement
DocRef::parse(value: &str) -> Result<DocRef>- Split on
#to extract path and fragment - Validate path format (no empty paths)
- Store fragment if present
- Split on
Priority: HIGH
Estimate: 0.5 days
Dependencies: None
Success Criteria: Parser accepts @doc annotations without "unknown key" errors
- Unit: Parse
@doc: path/to/file.md - Unit: Parse
@doc: path/to/file.md#section - Unit: Reject empty paths
- Unit: Multiple
@docannotations accumulate
- Add
docs: Vec<DocRef>field toFileMetadatastruct- Populated from file-level
@docannotations
- Populated from file-level
- Add
docs: Vec<DocRef>field toTaskMetadatastruct- Populated from task-level
@docannotations
- Populated from task-level
- Update
AnnotationBlockhelper methods- Add
get_docs() -> Vec<DocRef>method
- Add
- Update parser to populate doc refs
- Extract from header annotations
- Extract from task metadata blocks
Priority: HIGH
Estimate: 0.5 days
Dependencies: Task #1
Success Criteria: Parsed files contain populated docs vectors
- Unit: File-level
@docpopulatesFileMetadata.docs - Unit: Task-level
@docpopulatesTaskMetadata.docs - Unit: Multiple docs at both levels
- Create
ValidDocReferenceRule- Code:
E_SEM_INVALID_DOC - Severity: Error
- Check: Referenced file exists on filesystem
- Check: Path is within project root (no escaping via
../../../) - Check: Reject absolute paths
- Code:
- Create
BrokenDocFragmentrule- Code:
W_SEM_DOC_FRAGMENT - Severity: Warning
- Check: If fragment specified, file contains matching heading
- Parse target file for headings using pulldown-cmark
- Code:
- Add rules to default registry
Priority: HIGH Estimate: 1 day Dependencies: Task #2 Success Criteria: Linter catches broken doc references with clear error messages
- Unit: Valid doc reference passes
- Unit: Missing file fails with
E_SEM_INVALID_DOC - Unit: Path escaping project root fails
- Unit: Absolute path rejected
- Unit: Fragment validation passes when heading exists
- Unit: Fragment validation fails with
W_SEM_DOC_FRAGMENTfor missing heading - Unit: Case-insensitive fragment matching
- Unit: All heading levels (H1-H6) are detected
- Add
doc_refstable to schema (migration v3)-
id: INTEGER PRIMARY KEY -
source_file_id: INTEGER- FK to files table -
source_task_id: INTEGER NULL- FK to tasks table (NULL for file-level) -
target_path: TEXT- relative path to document -
fragment: TEXT NULL- optional section fragment
-
- Create
DocRefRepository-
insert(doc_ref: &DocRef, file_id: i64, task_id: Option<i64>) -
find_by_file(file_id: i64) -> Vec<DocRefRow> -
find_by_task(task_id: i64) -> Vec<DocRefRow> -
find_by_target(path: &str) -> Vec<(i64, Option<i64>)>- reverse lookup -
find_by_target_prefix(prefix: &str)- prefix matching
-
- Update indexing engine to persist doc refs
Priority: MEDIUM Estimate: 0.5 days Dependencies: Task #2, tasks.sqlite-schema.md Success Criteria: Doc references queryable from database
- Unit: Insert and retrieve doc refs
- Unit: Reverse lookup by target path
- Integration: Index file with docs, query back
- Update
lash showcommand- Display doc references in output
- Format:
Docs: ../docs/design.md#section-7
- Add
--docsfilter tolash list-
lash list --docs design.md- find tasks referencing this doc
-
- [-] Update
lash agent-promptoutput (deferred - low priority)- [-] Include doc refs in sparse context
- [-] Enable agents to request doc content on demand
- Note: Doc refs are available in DB for future enhancement
Priority: LOW Estimate: 0.5 days Dependencies: Task #4, tasks.cli-commands.md Success Criteria: Doc references visible and queryable via CLI
- Integration:
lash showdisplays docs - Integration:
lash list --docsfilters correctly
Total Estimate: 2-3 days Critical Path: Tasks #1 → #2 → #3 (parsing and validation)
-
@docaccepted as valid annotation - Doc refs stored in data model and database
- Linter validates doc references exist
- CLI displays doc references
- Automatic doc content fetching/embedding
Fragment validation for non-Markdown files(Now implemented for Markdown files)- Bidirectional doc-to-task linking UI
- Design doc section 4.3 (annotation types)
lash-core/src/parser/annotations.rs- existing annotation parsinglash-core/src/linter/rules/- existing linter rules
Completed in commits:
56ade71- Add @doc annotation task for semantic documentation links (Tasks 1-2)3dad6df- Add CLI support for @doc annotation references (Tasks 3-5)730f164- Fix database initialization to include all migrations2c0f9de- Add BrokenDocFragmentRule for validating @doc fragment references