diff --git a/.claude/settings.json b/.claude/settings.json index 7e421974..dd9f0acf 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,4 +1,5 @@ { + "plansDirectory": "./.plans", "attribution": { "commit": "", "pr": "" diff --git a/.gitignore b/.gitignore index bf904e0a..2e986584 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ node_modules/ dist/ *.tsbuildinfo +# Generated intermediate artifacts (not website-published) +docs-generated/ + # IDE .idea/ .vscode/ @@ -36,3 +39,4 @@ npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* +.plans/ diff --git a/.husky/pre-commit b/.husky/pre-commit old mode 100644 new mode 100755 diff --git a/.husky/pre-push b/.husky/pre-push index b5f0ba12..2a88d9ac 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,5 +1,8 @@ set -e +echo "Running format check..." +pnpm format:check + echo "Running tests..." pnpm test diff --git a/CLAUDE.md b/CLAUDE.md index 5d75e01e..7e28b2e5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -41,52 +41,52 @@ This package uses itself as the primary test case: - `_claude-md/validation/process-guard.md` → compact AI context - `docs/PROCESS-GUARD.md` → detailed human reference -Both generated from the SAME annotated sources. When the POC succeeds here, the pattern applies to the entire monorepo. - -#### Session Planning Principle - -Features are planned for **reusability across the monorepo**, not for minimal output in this package. +Both generated from the SAME annotated sources. Features are planned for **reusability across the monorepo**, not for minimal output in this package. --- -### Target Monorepo +## Context Gathering Protocol -**Location:** `~/dev-projects/convex-event-sourcing/libar-platform` +### Context Gathering Protocol (MANDATORY) -The package is actively used as a dev dependency. The monorepo contains: +**Rule: Always query the Process Data API BEFORE using grep, explore agents, or reading files.** -| Component | Purpose | -| ------------------------- | -------------------------------------------------------------------------- | -| `packages/platform-*` | 6 platform packages with annotated TypeScript sources | -| `delivery-process/specs/` | Tier 1 roadmap specifications | -| `docs-living/` | Generated documentation output (patterns, phases, requirements, decisions) | +The API returns structured, current data using 5-10x less context than file reads. Annotations and relationships in source files feed the API — invest in annotations, not manual notes. -**Manual docs being replaced:** `~/dev-projects/convex-event-sourcing/docs/` contains 150+ manually maintained files including architecture decisions, pattern theory, roadmap phases, and project management docs—all candidates for code-first generation. +#### PR / Session Start (run these FIRST) -#### What Gets Generated +| Step | Command | What You Get | +| ---- | ---------------------------------------------------------- | ------------------------------------------- | +| 1 | `pnpm process:query -- overview` | Project health, active phases, blockers | +| 2 | `pnpm process:query -- scope-validate ` | Pre-flight: FSM violations, missing deps | +| 3 | `pnpm process:query -- context --session ` | Curated context bundle for the session | +| 4 | `pnpm process:query -- files --related` | File reading list with implementation paths | -| Output Type | Purpose | -| ---------------------------- | ------------------------------------------ | -| `PATTERNS.md` + detail pages | Pattern registry from annotated TypeScript | -| `ROADMAP.md` + phase files | Roadmap from Tier 1 feature specs | -| `REMAINING-WORK.md` | Outstanding work summary | -| `CURRENT-WORK.md` | Active work tracking | -| `DECISIONS.md` + ADRs | Architecture decision records | -| `BUSINESS-RULES.md` | Business rules from Gherkin | +Session types: `planning` (minimal), `design` (full: stubs + deps + deliverables), `implement` (focused: deliverables + FSM + tests). ---- +#### When You Need More Context -### Why No Shortcuts +| Need | Command (NOT grep) | Why | +| ----------------------- | ------------------------------------------- | ------------------------------------------- | +| Find code structure | `arch context [name]` / `arch layer [name]` | Structured by annotations, not file paths | +| Find dependencies | `dep-tree ` | Shows status of each dependency | +| Find business rules | `rules --pattern ` | Extracted from Gherkin Rule: blocks | +| Find unannotated files | `unannotated --path ` | Catches missing @libar-docs markers | +| Check FSM state | `query getProtectionInfo ` | Protection level + allowed actions | +| Check valid transitions | `query getValidTransitionsFrom ` | Valid next states from current status | +| Tag inventory | `tags` | Counts per tag and value across all sources | +| Annotation coverage | `arch coverage` | Files with/without @libar-docs annotations | -Every shortcut in this package ripples across: +#### Why Annotations Beat Grep -- Multiple platform packages with annotated sources -- Many Gherkin feature specifications -- All generated documentation files +- **Structured**: `arch context` groups by bounded context; grep returns unstructured matches +- **Queryable**: `rules --only-invariants` extracts 140+ business rules; grep can't parse Rule: blocks +- **Feed generation**: Annotations produce generated docs; grep results are ephemeral +- **Discoverable**: `unannotated --path` finds gaps; grep doesn't know what's missing -**Test rigor matches mission-critical status.** A bug in the codec system means many files generate incorrectly. A gap in the extractor means patterns are missed across source files. +**When adding new code:** Add `@libar-docs` annotations and relationship tags (`@libar-docs-depends-on`, `@libar-docs-uses`) so future sessions can discover the code via API queries instead of grep. -The validation in this repo is a **proof of concept**. When it succeeds here, the same validation applies to the entire monorepo's delivery workflow. +Full CLI reference: `pnpm process:query -- --help` --- @@ -107,18 +107,12 @@ pnpm test # Run tests matching pattern (e.g., pnpm test scanner) # Linting pnpm lint # ESLint on src and tests pnpm lint:fix # Auto-fix lint issues -pnpm lint-patterns # Lint pattern annotations in src/**/*.ts - -# Validation -pnpm validate:patterns # Cross-source pattern validation -pnpm validate:dod # Definition of Done validation -pnpm validate:all # All validations including anti-patterns -# Documentation generation -pnpm docs:patterns # Generate pattern docs -pnpm docs:all # Generate all doc types (patterns, roadmap, remaining, changelog) +# Validation + Documentation +pnpm validate:all # All validations including anti-patterns and DoD +pnpm docs:all # Generate all doc types -# Data API (see "Data API CLI" section for full reference) +# Data API (see Context Gathering Protocol above) pnpm process:query -- --help # All subcommands and options pnpm process:query -- context --session design # Session context bundle pnpm process:query -- overview # Project health summary @@ -134,54 +128,7 @@ Query delivery process state directly from the terminal. **Use this instead of r **Run `pnpm process:query -- --help` for the full command reference**, including workflow recipes, session types, architecture queries, output modifiers, and available API methods. -#### Session Start Recipe - -1. `pnpm process:query -- overview` — project health (progress, active phases, blockers) -2. `pnpm process:query -- scope-validate ` — pre-flight check (FSM, deps, prereqs) -3. `pnpm process:query -- context --session ` — curated context bundle - -Session types: `planning` (minimal), `design` (full: stubs + deps + deliverables), `implement` (focused: deliverables + FSM + tests). - -#### Key Commands - -| Command | When to Use | -| ----------------------- | ------------------------------------------------------------------------------------- | -| `scope-validate` | **Highest impact** — prevents wasted sessions by catching violations before you start | -| `context --session` | Primary context gathering — replaces manual file reads | -| `dep-tree ` | Understand dependency chains before implementation | -| `list --status roadmap` | Find available patterns to work on | -| `arch blocking` | Find patterns stuck on incomplete dependencies | -| `stubs --unresolved` | Find design stubs missing implementations | -| `rules` | Business rules and invariants from Gherkin `Rule:` blocks | -| `files ` | File reading list with implementation paths — replaces manual path discovery | -| `decisions ` | Design decisions (AD-N) from stub descriptions | -| `pdr ` | Cross-reference patterns mentioning a PDR number | -| `handoff --pattern` | Capture session-end state for multi-session work | - -#### Annotation Exploration - -Run these **before** making annotation changes — they prevent debugging cycles: - -| Command | When to Use | -| -------------------------- | ----------------------------------------------------------------------------- | -| `unannotated --path ` | Find TS files missing `@libar-docs` — **run first** in any enrichment session | -| `tags` | Tag usage inventory (counts per tag and value) | -| `sources` | File inventory by type (TS, Gherkin, Stubs) | -| `query getPattern ` | Full pattern JSON including `extractedShapes` and `productArea` | - -**Lesson learned:** `unannotated --path src/types` would have immediately caught missing `@libar-docs` annotations on `result.ts` and `errors.ts` — saving ~30 minutes of debugging why shapes weren't appearing in generated docs. - -#### Architecture Queries - -Query architectural structure directly — avoids explore agents for structural questions: - -| Command | When to Use | -| --------------------- | ---------------------------------------------------- | -| `arch coverage` | Annotation completeness across the project | -| `arch context [name]` | Patterns in bounded context (list all if no name) | -| `arch layer [name]` | Patterns in architecture layer (list all if no name) | -| `arch dangling` | Broken references — pattern names that don't resolve | -| `arch orphans` | Isolated patterns with no relationships | +See the **Context Gathering Protocol** section above for mandatory session start commands and query recipes. #### Tips @@ -215,31 +162,22 @@ CONFIG → SCANNER → EXTRACTOR → TRANSFORMER → CODEC - **Pipeline Factory**: Shared `buildMasterDataset()` in `src/generators/pipeline/build-pipeline.ts` — all consumers (orchestrator, process-api, validate-patterns) call this instead of wiring inline pipelines. Per-consumer behavior via `PipelineOptions`. - **Single Read Model** (ADR-006): MasterDataset is the sole read model. No consumer re-derives data from raw scanner/extractor output. Anti-patterns: Parallel Pipeline, Lossy Local Type, Re-derived Relationship. -### Module Structure +**Live module inventory:** `pnpm process:query -- arch context` and `pnpm process:query -- arch layer` -| Module | Purpose | -| -------------------------- | -------------------------------------------------------------------- | -| `src/config/` | Configuration factory, presets (generic, ddd-es-cqrs) | -| `src/taxonomy/` | Tag definitions - categories, status values, format types | -| `src/scanner/` | TypeScript and Gherkin file scanning | -| `src/extractor/` | Pattern extraction from AST/Gherkin | -| `src/generators/` | Document generators, orchestrator, and pipeline factory | -| `src/generators/pipeline/` | `buildMasterDataset()` factory, `mergePatterns()`, dataset transform | -| `src/renderable/` | Markdown codec system | -| `src/validation/` | FSM validation, DoD checks, anti-patterns | -| `src/lint/` | Pattern linting and process guard | -| `src/api/` | Query layer: Data API CLI, business rules query (`rules-query.ts`) | -| `delivery-process/stubs/` | Design session code stubs (outside src/ for TS/ESLint isolation) | +### Decision Specs -**Live inventory:** `pnpm process:query -- arch context` and `pnpm process:query -- arch layer` reflect the actual annotated codebase structure. +Architecture and process decisions are recorded as annotated Gherkin specs in `delivery-process/decisions/`: -### Three Presets +| Spec | Key Decision | +| ------- | -------------------------------------------------------------------------- | +| ADR-001 | Taxonomy canonical values — tag registry is the single source of truth | +| ADR-002 | Gherkin-only testing — no `.test.ts` files, all tests are `.feature` | +| ADR-003 | Source-first pattern architecture — code drives docs, not the reverse | +| ADR-005 | Codec-based markdown rendering — Zod codecs transform data to markdown | +| ADR-006 | Single read model — MasterDataset is the sole read model for all consumers | +| PDR-001 | Session workflow commands — Process Data API CLI design decisions | -| Preset | Tag Prefix | Categories | Use Case | -| ------------------------- | -------------- | ---------- | ---------------------------------- | -| `libar-generic` (default) | `@libar-docs-` | 3 | Simple projects (this package) | -| `ddd-es-cqrs` | `@libar-docs-` | 21 | DDD/Event Sourcing architectures | -| `generic` | `@docs-` | 3 | Simple projects with @docs- prefix | +Query decisions: `pnpm process:query -- decisions ` --- @@ -371,30 +309,16 @@ describeFeature(feature, ({ Background, Rule }) => { }); ``` -### Docstring Pattern for Pipes - -Use docstrings when Gherkin content contains pipe characters: - -```typescript -Then('the output contains the table:', (_ctx: unknown, docString: string) => { - for (const line of docString.trim().split('\n')) { - expect(state!.markdown).toContain(line.trim()); - } -}); -``` - ### vitest-cucumber Quirks & Constraints The library behaves differently than standard Cucumber.js. -| Issue | Description | Fix | -| ------------------------ | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -| Repeated Step Patterns | Using exact same step pattern twice in one scenario fails to match or overwrites registrations | Avoid generic regex steps if reused. Use strict string matching. Consolidate assertions into DataTables | -| `{phrase}` not supported | vitest-cucumber does not support `{phrase}` type | Use `{string}` and wrap value in quotes in Feature file | -| Docstring stripping | Markdown headers (`## Header`) inside docstrings may be stripped or parsed incorrectly | Hardcode complex multi-line strings in step definition TS file | -| Feature descriptions | Starting a description line with `Given`, `When`, or `Then` breaks the parser | Ensure free-text descriptions do not start with reserved Gherkin keywords | -| Multiple And same text | Multiple `And` steps with identical text (different values) fail | Consolidate into single step with DataTable | -| No regex step patterns | `Then(/pattern/, ...)` throws `StepAbleStepExpressionError` | Use only string patterns with `{string}`, `{int}` placeholders | +| Issue | Description | Fix | +| ---------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| Docstring stripping | Markdown headers (`## Header`) inside docstrings may be stripped or parsed incorrectly | Hardcode complex multi-line strings in step definition TS file | +| Feature descriptions | Starting a description line with `Given`, `When`, or `Then` breaks the parser | Ensure free-text descriptions do not start with reserved Gherkin keywords | +| Multiple And same text | Multiple `And` steps with identical text (different values) fail | Consolidate into single step with DataTable | +| No regex step patterns | `Then(/pattern/, ...)` throws `StepAbleStepExpressionError` | Use only string patterns with `{string}`, `{int}` placeholders | ### Gherkin Parser: Hash Comments in Descriptions (CRITICAL) @@ -455,15 +379,6 @@ Issues discovered during step definition implementation: | `behaviorFileVerified` undefined | Patterns created without explicit verification status | Add `behaviorFileVerified: true/false` to `createTestPattern()` when testing traceability | | Discovery tags missing | SessionFindingsCodec shows "No Findings" | Pass `discoveredGaps`, `discoveredImprovements`, `discoveredLearnings` to factory | -### Codec vs. Spec Reality Gap - -Tier 1 specs are often idealistic drafts. The code is the reality. - -| Issue | Description | Fix | -| ------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -| Output Structure Mismatch | Spec expects "Phase 1" but Codec outputs derived name, or Spec expects table that Codec suppresses when empty | Run debug script to dump actual `RenderableDocument` JSON structure. Align Feature file to Codec's actual behavior | -| Data Normalization | Feature files use plain language (`planned`, `p1`) vs. Schema requirements (`roadmap`, `pattern-00...`) | Implement helper functions: `normalizeStatus(str)` maps 'planned' → 'roadmap'. `generatePatternId(n)` generates valid IDs | - ### Coding & Linting Standards The project has strict linting rules. Save time by coding defensively. @@ -473,22 +388,7 @@ The project has strict linting rules. Save time by coding defensively. | Unused variables: `(_ctx, count, text)` throws lint errors if `count` isn't used | Prefix **immediately**: `(_ctx, _count, text)` | | Type safety: `ListItem` is an object, not a string. `item + '\n'` throws errors | Check types before concatenation: `(typeof item === 'string' ? item : item.text)` | -### Deliverable Status Taxonomy (CRITICAL) - -Deliverable status is enforced by `z.enum()` at schema level. The 6 canonical values are defined in `src/taxonomy/deliverable-status.ts`: - -| Value | Meaning | Helper | -| ------------- | ------------------- | --------------------------------- | -| `complete` | Work is done | `isDeliverableStatusComplete()` | -| `in-progress` | Work is ongoing | `isDeliverableStatusInProgress()` | -| `pending` | Work hasn't started | `isDeliverableStatusPending()` | -| `deferred` | Work postponed | | -| `superseded` | Replaced by another | | -| `n/a` | Not applicable | | - -**NEVER** use freeform status strings. The Zod schema rejects non-canonical values at parse time. - -**Terminal statuses:** `complete`, `n/a`, and `superseded` are terminal per `isDeliverableStatusTerminal()`. Used by DoD validation — `deferred` is NOT terminal. +**Deliverable statuses:** 6 values enforced by `z.enum()`: `complete`, `in-progress`, `pending`, `deferred`, `superseded`, `n/a`. Terminal: `complete`, `n/a`, `superseded` (NOT `deferred`). NEVER use freeform strings. ### Efficient Debugging Strategy @@ -507,174 +407,107 @@ console.log(JSON.stringify(doc.sections, null, 2)); - **Do** use `pnpm test remaining-work` (or specific filename) to run focused tests. -### Implementation Workflow Checklist - -1. [ ] **Read Feature File:** identify Scenario counts and data types -2. [ ] **Check Factories:** Ensure `pattern-factories.ts` supports the fields needed (e.g., `phase`, `priority`) -3. [ ] **Prototype:** Run a `tsx` script to see what the Codec actually outputs for given inputs -4. [ ] **Adjust Spec:** Update Feature file to match Codec reality (e.g., quotes for lists, valid status names) -5. [ ] **Write Steps:** Implement steps with `_` prefixes for unused args -6. [ ] **Verify:** Run specific test file → Run related group → Run full suite - --- ## Session Workflows -**Core Thesis:** Git is the event store. Documentation artifacts are projections. Feature files are the single source of truth. - -For detailed guides, see [SESSION-GUIDES.md](./docs/SESSION-GUIDES.md). - -### Session Decision Tree - -``` -Starting from pattern brief? -├── Yes → Need code stubs now? → Yes → Planning + Design -│ → No → Planning -└── No → Ready to code? → Yes → Complex decisions? → Yes → Design first - → No → Implementation - → No → Planning -``` +### SessionGuidesModuleSource -| Session | Input | Output | FSM Change | -| ----------------- | ------------------- | --------------------------- | -------------------------- | -| Planning | Pattern brief | Roadmap spec (`.feature`) | Creates `roadmap` | -| Design | Complex requirement | Decision specs + code stubs | None | -| Implementation | Roadmap spec | Code + tests | `roadmap→active→completed` | -| Planning + Design | Pattern brief | Spec + stubs | Creates `roadmap` | +#### SESSION-GUIDES.md is the authoritative public human reference -### Planning Session +**Invariant:** `docs/SESSION-GUIDES.md` exists and is not deleted, shortened, or replaced with a redirect. Its comprehensive checklists, CLI command examples, and session decision trees serve developers on libar.dev. -**Goal:** Create a roadmap spec. Do NOT write implementation code. +**Rationale:** Session workflow guidance requires two formats for two audiences. Public developers need comprehensive checklists with full examples. AI sessions need compact invariants they can apply without reading 389 lines. -| Do | Do NOT | -| --------------------------------------------------------- | --------------------------- | -| Extract metadata from pattern brief | Create `.ts` implementation | -| Create spec file with proper tags | Transition to `active` | -| Add deliverables table in Background | Ask "Ready to implement?" | -| Convert constraints to `Rule:` blocks | Write full implementations | -| Add scenarios: 1 `@happy-path` + 1 `@validation` per Rule | | +#### CLAUDE.md session workflow content is derived, not hand-authored -### Design Session +**Invariant:** After Phase 39 generation deliverables complete, the "Session Workflows" section in CLAUDE.md contains no manually-authored content. It is composed from generated `_claude-md/workflow/` modules. -**Goal:** Make architectural decisions. Create code stubs with interfaces. Do NOT implement. +**Rationale:** A hand-maintained CLAUDE.md session section creates two copies of session workflow guidance with no synchronization mechanism. Regeneration from annotated source eliminates drift. -| Use Design Session | Skip Design Session | -| -------------------------- | ------------------- | -| Multiple valid approaches | Single obvious path | -| New patterns/capabilities | Bug fix | -| Cross-context coordination | Clear requirements | +#### Session type determines artifacts and FSM changes -**Context Gathering (BEFORE explore agents):** +**Invariant:** Four session types exist, each with defined input, output, and FSM impact. Mixing outputs across session types (e.g., writing code in a planning session) violates session discipline. -```bash -pnpm process:query -- context --session design -pnpm process:query -- dep-tree -pnpm process:query -- stubs -pnpm process:query -- overview -``` +**Rationale:** Session type confusion causes wasted work — a design mistake discovered mid-implementation wastes the entire session. Clear contracts prevent scope bleeding between session types. -Only use explore agents for comprehension questions (implementation patterns, formatting conventions) that the API doesn't cover. +| Session | Input | Output | FSM Change | +| ----------------- | ------------------- | --------------------------- | ------------------------------ | +| Planning | Pattern brief | Roadmap spec (.feature) | Creates roadmap | +| Design | Complex requirement | Decision specs + code stubs | None | +| Implementation | Roadmap spec | Code + tests | roadmap to active to completed | +| Planning + Design | Pattern brief | Spec + stubs | Creates roadmap | -**Code Stub Pattern** — stubs go in `delivery-process/stubs/{pattern-name}/`: +#### Planning sessions produce roadmap specs only -```typescript -// delivery-process/stubs/{pattern-name}/my-function.ts -/** - * @libar-docs - * @libar-docs-status roadmap - * @libar-docs-implements MyPattern - * @libar-docs-uses Workpool, EventStore - * - * ## My Pattern - Description - * - * Target: src/path/to/final/location.ts - * See: PDR-001 (Design Decision) - * Since: DS-1 - */ -export function myFunction(args: MyArgs): Promise { - throw new Error('MyPattern not yet implemented - roadmap pattern'); -} -``` +**Invariant:** A planning session creates a roadmap spec with metadata, deliverables table, Rule: blocks with invariants, and scenarios. It must not produce implementation code, transition to active, or prompt for implementation readiness. -Stubs live outside `src/` to avoid TypeScript compilation and ESLint issues. +**Rationale:** Planning is the cheapest session type — it produces .feature file edits, no compilation needed. Mixing implementation into planning defeats the cost advantage and introduces untested code without a locked scope. -### Implementation Session +| Do | Do NOT | +| --------------------------------------------------- | -------------------------- | +| Extract metadata from pattern brief | Create .ts implementation | +| Create spec file with proper tags | Transition to active | +| Add deliverables table in Background | Ask Ready to implement | +| Convert constraints to Rule: blocks | Write full implementations | +| Add scenarios: 1 happy-path + 1 validation per Rule | | -**Goal:** Write code. The roadmap spec is the source of truth. +#### Design sessions produce decisions and stubs only -**Context Gathering (BEFORE writing code):** +**Invariant:** A design session makes architectural decisions and creates code stubs with interfaces. It must not produce implementation code. Context gathering via the Process Data API must precede any explore agent usage. -```bash -pnpm process:query -- context --session implement -pnpm process:query -- dep-tree -pnpm process:query -- stubs -``` +**Rationale:** Design sessions resolve ambiguity before implementation begins. Code stubs in delivery-process/stubs/ live outside src/ to avoid TypeScript compilation and ESLint issues, making them zero-risk artifacts. -**Execution Order (CRITICAL):** +| Use Design Session | Skip Design Session | +| -------------------------- | ------------------- | +| Multiple valid approaches | Single obvious path | +| New patterns/capabilities | Bug fix | +| Cross-context coordination | Clear requirements | -1. **Transition to `active` FIRST** — before any code changes -2. **Create executable spec stubs** — if `@libar-docs-executable-specs` present -3. **For each deliverable:** implement, test, update status to `completed` -4. **Transition to `completed`** — only when ALL deliverables done -5. **Regenerate docs:** `pnpm docs:all` +#### Implementation sessions follow FSM-enforced execution order -| Do NOT | Why | -| ------------------------------------- | --------------------------------------- | -| Add new deliverables to `active` spec | Scope-locked state prevents scope creep | -| Mark `completed` with incomplete work | Hard-locked state cannot be undone | -| Skip FSM transitions | Process Guard will reject | -| Edit generated docs directly | Regenerate from source | +**Invariant:** Implementation sessions must follow a strict 5-step execution order. Transition to active must happen before any code changes. Transition to completed must happen only when ALL deliverables are done. Skipping steps causes Process Guard rejection at commit time. -### FSM Protection Quick Reference +**Rationale:** The execution order ensures FSM state accurately reflects work state at every point. Writing code before transitioning to active means Process Guard sees changes to a roadmap spec (no scope protection). Marking completed with incomplete work creates a hard-locked state that requires unlock-reason to fix. -| State | Protection | Can Add Deliverables | Needs Unlock | -| ----------- | ------------ | -------------------- | ------------ | -| `roadmap` | None | Yes | No | -| `active` | Scope-locked | No | No | -| `completed` | Hard-locked | No | Yes | -| `deferred` | None | Yes | No | +| Do NOT | Why | +| ----------------------------------- | --------------------------------------- | +| Add new deliverables to active spec | Scope-locked state prevents scope creep | +| Mark completed with incomplete work | Hard-locked state cannot be undone | +| Skip FSM transitions | Process Guard will reject | +| Edit generated docs directly | Regenerate from source | -**Live query:** `pnpm process:query -- query getProtectionInfo ` and `query getValidTransitionsFrom ` return current FSM rules from code. +#### FSM errors have documented fixes -**Valid FSM Transitions:** +**Invariant:** Every Process Guard error code has a defined cause and fix. The error codes, causes, and fixes form a closed set — no undocumented error states exist. -``` -roadmap ──→ active ──→ completed (terminal) - │ │ - │ ↓ - │ roadmap (blocked/regressed) - ↓ -deferred ──→ roadmap -``` +**Rationale:** Undocumented FSM errors cause session-blocking confusion. A lookup table from error code to fix eliminates guesswork and prevents workarounds that bypass process integrity. -### FSM Error Messages and Fixes +| Error | Cause | Fix | +| ------------------------- | ---------------------------------------------- | ------------------------------------------- | +| completed-protection | File has completed status but no unlock tag | Add libar-docs-unlock-reason tag | +| invalid-status-transition | Skipped FSM state (e.g., roadmap to completed) | Follow path: roadmap to active to completed | +| scope-creep | Added deliverable to active spec | Remove deliverable OR revert to roadmap | +| session-scope (warning) | Modified file outside session scope | Add to scope OR use --ignore-session | +| session-excluded | Modified excluded pattern during session | Remove from exclusion OR override | -| Error | Cause | Fix | -| --------------------------- | --------------------------------------------- | ----------------------------------------- | -| `completed-protection` | File has `completed` status but no unlock tag | Add `@libar-docs-unlock-reason:'reason'` | -| `invalid-status-transition` | Skipped FSM state (e.g., `roadmap→completed`) | Follow path: `roadmap→active→completed` | -| `scope-creep` | Added deliverable to `active` spec | Remove deliverable OR revert to `roadmap` | -| `session-scope` (warning) | Modified file outside session scope | Add to scope OR use `--ignore-session` | -| `session-excluded` | Modified excluded pattern during session | Remove from exclusion OR override | +| Situation | Solution | Example | +| ---------------------------- | --------------------- | -------------------------------------- | +| Fix bug in completed spec | Add unlock reason tag | libar-docs-unlock-reason:Fix-typo | +| Modify outside session scope | Use ignore flag | lint-process --staged --ignore-session | +| CI treats warnings as errors | Use strict flag | lint-process --all --strict | -### Escape Hatches +#### Handoff captures session-end state for continuity -| Situation | Solution | Example | -| ---------------------------- | --------------------- | ---------------------------------------- | -| Fix bug in completed spec | Add unlock reason tag | `@libar-docs-unlock-reason:'Fix-typo'` | -| Modify outside session scope | Use ignore flag | `lint-process --staged --ignore-session` | -| CI treats warnings as errors | Use strict flag | `lint-process --all --strict` | +**Invariant:** Multi-session work requires handoff documentation generated from the Process Data API. Handoff output always reflects actual annotation state, not manual notes. -### Handoff Documentation +**Rationale:** Manual session notes drift from actual deliverable state. The handoff command derives state from annotations, ensuring the next session starts from ground truth rather than stale notes. -For multi-session work, generate handoff state from the API: +#### ClaudeModuleGeneration is the generation mechanism -```bash -pnpm process:query -- handoff --pattern -# Options: --git (include recent commits), --session -``` +**Invariant:** Phase 39 depends on ClaudeModuleGeneration (Phase 25). Adding `@libar-docs-claude-module` and `@libar-docs-claude-section:workflow` tags to this spec will cause ClaudeModuleGeneration to produce `_claude-md/workflow/` output files. The hand-written `_claude-md/workflow/` files are deleted after successful verified generation. -Generates: deliverable statuses, blockers, modification date, and next steps — always reflects actual annotation state. +**Rationale:** The annotation work (Rule blocks in this spec) is immediately useful — queryable via `pnpm process:query -- rules`. Generation deliverables cannot complete until Phase 25 ships the ClaudeModuleCodec. This sequencing is intentional: the annotation investment has standalone value regardless of whether the codec exists yet. --- @@ -684,25 +517,8 @@ Generates: deliverable statuses, blockers, modification date, and next steps — Process Guard validates delivery workflow changes at commit time using a Decider pattern. -#### 6 Validation Rules - -| Rule ID | Severity | Description | -| --------------------------- | -------- | --------------------------------------------------- | -| `completed-protection` | error | Completed specs require `@libar-docs-unlock-reason` | -| `invalid-status-transition` | error | Must follow FSM path | -| `scope-creep` | error | Active specs cannot add new deliverables | -| `session-excluded` | error | Cannot modify explicitly excluded files | -| `session-scope` | warning | File outside session scope | -| `deliverable-removed` | warning | Deliverable was removed | - -#### Protection Levels - -| Status | Protection | Allowed Actions | Blocked Actions | -| ----------- | ------------ | ------------------------------ | ----------------------------- | -| `roadmap` | None | Full editing, add deliverables | - | -| `deferred` | None | Full editing, add deliverables | - | -| `active` | Scope-locked | Edit existing deliverables | Adding new deliverables | -| `completed` | Hard-locked | Nothing | Any change without unlock tag | +Query validation rules: `pnpm process:query -- rules --pattern ProcessGuard` +Query protection levels: `pnpm process:query -- query getProtectionInfo ` #### CLI Usage @@ -720,17 +536,6 @@ lint-process --staged --show-state lint-process --staged --ignore-session ``` -#### CLI Options - -| Flag | Description | -| ------------------ | --------------------------------------- | -| `--staged` | Validate staged files only (pre-commit) | -| `--all` | Validate all tracked files (CI) | -| `--strict` | Treat warnings as errors (exit 1) | -| `--ignore-session` | Skip session scope validation | -| `--show-state` | Debug: show derived process state | -| `--format json` | Machine-readable JSON output | - #### Exit Codes | Code | Meaning | @@ -751,16 +556,6 @@ Enforces dual-source architecture ownership between TypeScript and Gherkin files | `@libar-docs-quarter` | Feature files | TypeScript | Gherkin owns timeline metadata | | `@libar-docs-team` | Feature files | TypeScript | Gherkin owns ownership metadata | -#### Single Read Model Anti-Patterns (ADR-006) - -| Anti-Pattern | Signal | -| ----------------------- | ----------------------------------------------------------------------------------- | -| Parallel Pipeline | Consumer imports from `scanner/` or `extractor/` instead of consuming MasterDataset | -| Lossy Local Type | Local interface with subset of `ExtractedPattern` fields | -| Re-derived Relationship | Building `Map`/`Set` from raw `implements`/`uses` arrays in consumer code | - -**Exception:** `lint-patterns.ts` is a stage-1 consumer (validates annotation syntax, no cross-source resolution). - #### DoD Validation For patterns with `completed` status, validates: @@ -768,22 +563,7 @@ For patterns with `completed` status, validates: - All deliverables have terminal status (`complete`, `n/a`, or `superseded`) per `isDeliverableStatusTerminal()` — `deferred` is NOT terminal - At least one `@acceptance-criteria` scenario exists in the spec -#### Running Validation - -```bash -# Anti-pattern check only -npx validate-patterns \ - -i "src/**/*.ts" \ - -F "specs/**/*.feature" \ - --anti-patterns - -# Full validation with DoD -npx validate-patterns \ - -i "src/**/*.ts" \ - -F "specs/**/*.feature" \ - --anti-patterns \ - --dod -``` +Run: `pnpm validate:all` for full validation including anti-patterns and DoD. --- @@ -820,16 +600,7 @@ Feature: Process Guard Linter | Value-First | `**Business Value:**`, `**How It Works:**` | TDD-style specs | | Context/Approach | `**Context:**`, `**Approach:**` | Technical patterns | -#### Tag Conventions - -| Tag | Purpose | -| ---------------------- | --------------------------- | -| `@happy-path` | Primary success scenario | -| `@edge-case` | Boundary conditions | -| `@error-handling` | Error recovery scenarios | -| `@validation` | Input validation rules | -| `@acceptance-criteria` | Required for DoD validation | -| `@integration` | Cross-component behavior | +Tag inventory: `pnpm process:query -- tags` (counts per tag and value across all sources). #### Rule Block Structure (Mandatory) @@ -879,59 +650,6 @@ Rule: Reservations use atomic claim Code stubs live in `delivery-process/stubs/{pattern-name}/` — annotated TypeScript with `throw new Error("not yet implemented")`. -#### Rule Block Structure (Mandatory) - -Every feature file MUST use `Rule:` blocks with structured descriptions: - -```gherkin -Rule: Reservations prevent race conditions - - **Invariant:** Only one reservation can exist for a given key at a time. - - **Rationale:** Check-then-create patterns have TOCTOU vulnerabilities. - - **Verified by:** Concurrent reservations, Expired reservation cleanup - - @acceptance-criteria @happy-path - Scenario: Concurrent reservations - ... -``` - -| Element | Purpose | Extracted By | -| ------------------ | --------------------------------------- | ------------------------ | -| `**Invariant:**` | Business constraint (what must be true) | Business Rules generator | -| `**Rationale:**` | Business justification (why it exists) | Business Rules generator | -| `**Verified by:**` | Comma-separated scenario names | Traceability generator | - -#### Feature Description Structure - -Choose headers that fit your pattern (flexible, not rigid): - -| Structure | Headers | Best For | -| ---------------- | ------------------------------------------ | ------------------------- | -| Problem/Solution | `**Problem:**`, `**Solution:**` | Pain point to fix | -| Value-First | `**Business Value:**`, `**How It Works:**` | TDD-style, Gherkin spirit | -| Context/Approach | `**Context:**`, `**Approach:**` | Technical patterns | - -Always include a benefits table: - -```gherkin -**Business Value:** -| Benefit | Impact | -| ... | ... | -``` - -#### Valid Rich Content - -| Content Type | Syntax | Appears in Docs | -| ------------- | ----------------------- | ---------------- | -| Plain text | Regular paragraphs | Yes | -| Bold/emphasis | `**bold**`, `*italic*` | Yes | -| Tables | Markdown pipe tables | Yes | -| Lists | `- item` or `1. item` | Yes | -| DocStrings | `"""typescript`...`"""` | Yes (code block) | -| Comments | `# comment` | No (ignored) | - #### Forbidden in Feature Descriptions | Forbidden | Why | Alternative | @@ -941,41 +659,6 @@ Always include a benefits table: | Nested DocStrings | Gherkin parser error | Reference code stub file | | `#` at line start | Gherkin comment — kills parsing | Remove, use `//`, or step DocStr | -#### Description `"""` Blocks vs Step DocStrings (CRITICAL) - -**`"""` inside Feature/Rule descriptions is plain text, NOT a DocString.** Only `"""` as step arguments (Given/When/Then) creates real DocStrings. This means description content between `"""` is subject to Gherkin parser rules — including `#` = comment. - -**Symptom:** `expected: #EOF, #BackgroundLine... got 'some-content'` - -```gherkin -Rule: My Rule - - """bash - # This breaks! Parser sees Gherkin comment, terminates description - generate-docs --output docs - """ -``` - -**Workarounds:** - -| Approach | When to Use | -| --------------------------- | ---------------------------------- | -| Remove `#` lines | Simple cases | -| Use `//` for comments | When comment syntax doesn't matter | -| Move to step DocString | When you need code with `#` | -| Reference stub file instead | Complex examples (preferred) | - -**Safe pattern — step DocString (content is real DocString, `#` is safe):** - -```gherkin - Scenario: Example usage - Given the following script: - """bash - # This is safe — real DocString, not description text - generate-docs --output docs - """ -``` - #### Tag Value Constraints **Tag values cannot contain spaces.** Use hyphens instead: @@ -986,108 +669,3 @@ Rule: My Rule | `@libar-docs-pattern:My Pattern` | `@libar-docs-pattern:MyPattern` | --- - -## Guides - -### Product Area Enrichment Guide - -Workflow for adding live Mermaid diagrams, enriched intros, and API Types sections to product area documents in `docs-live/product-areas/`. - -**Completed:** Annotation, Configuration, CoreTypes -**Remaining:** Generation, Validation, DataAPI, Process - -#### Pre-Flight (Run First) - -```bash -# 1. Find unannotated TS files in the product area's source directory -pnpm process:query -- unannotated --path src/ - -# 2. Check if product area has arch-context mappings -# Empty [] means use @libar-docs-include tags instead -grep -A5 ':' src/renderable/codecs/reference.ts | head -10 - -# 3. List patterns in the product area -pnpm process:query -- list --product-area --names-only -``` - -#### Step-by-Step Workflow - -| Step | Action | Why | -| ---- | ------------------------------------------------------------------------ | -------------------------------------------- | -| 1 | Add `@libar-docs` to unannotated TS files | Scanner ignores files without opt-in marker | -| 2 | Add `@libar-docs-include:` to all feature files | Enables diagram scoping via `include` filter | -| 3 | Add `@libar-docs-depends-on` to feature files | Creates relationship edges in diagrams | -| 4 | Add `@libar-docs-shape` + `@libar-docs-include` to key type declarations | Populates API Types section | -| 5 | Add `@libar-docs-product-area:` to TS file annotations | Routes TS patterns to product area | -| 6 | Update `PRODUCT_AREA_META` in `reference.ts` (~line 237) | Enriched intro, invariants, `diagramScopes` | -| 7 | `pnpm build && pnpm test && pnpm docs:product-areas` | Verify end-to-end | - -#### PRODUCT_AREA_META Entry Structure - -```typescript -AreaName: { - question: 'What does this area do?', // Shown as bold question before intro - covers: 'capability1, capability2, capability3', // Comma-separated coverage summary - intro: 'Full paragraph describing the area...', // Rich prose, can use backticks - diagramScopes: [ - { include: ['scope'], diagramType: 'C4Context', title: 'System Overview' }, - { include: ['scope'], direction: 'LR', title: 'Data Flow' }, - ], - keyInvariants: [ - 'Invariant name: Description with detail', - ], - keyPatterns: ['Pattern1', 'Pattern2'], -}, -``` - -#### DiagramScope Filter Options - -Filters are OR'd — a pattern matching ANY filter appears in the diagram: - -| Filter | Source Tag | Best For | -| ---------------------- | ------------------------------- | ------------------------------------------------ | -| `include: ['scope']` | `@libar-docs-include:scope` | Areas with empty `PRODUCT_AREA_ARCH_CONTEXT_MAP` | -| `archContext: ['ctx']` | `@libar-docs-arch-context:ctx` | Areas with existing arch-context mappings | -| `patterns: ['Name']` | Direct pattern name list | Small, curated diagrams | -| `archLayer: 'domain'` | `@libar-docs-arch-layer:domain` | Layer-filtered views | - -#### Common Pitfalls - -| Pitfall | Symptom | Fix | -| ------------------------------------------ | -------------------------------------------------- | ----------------------------------------------------- | -| TS file missing `@libar-docs` marker | Shapes not extracted, pattern absent from registry | Add file-level `@libar-docs` annotation block | -| Empty `PRODUCT_AREA_ARCH_CONTEXT_MAP` | No diagrams render | Use `include` filter in `diagramScopes` | -| No relationship tags on patterns | Diagrams show isolated nodes (no edges) | Add `@libar-docs-depends-on` to feature files | -| TS pattern name collides with Gherkin | Duplicate pattern error | Use different name + `@libar-docs-implements` to link | -| Declaration merging (`type X` + `const X`) | Shape for type alias not extracted | Fixed — `findDeclarations` returns arrays per name | -| Generic arrows in `.ts` with `jsx: true` | Parse error on `(val: T) =>` | Fixed — `jsx` flag now based on file extension | - -#### Shape Extraction Prerequisites - -For a shape to appear in the API Types section: - -1. **File must have `@libar-docs`** opt-in marker (file-level JSDoc) -2. **File must have `@libar-docs-product-area:`** to route to product area -3. **Declaration must have `@libar-docs-shape`** in its JSDoc (declaration-level) -4. **Declaration must have `@libar-docs-include:`** matching the `diagramScopes` filter -5. **File must be `.ts`** (shape extraction uses typescript-estree parser) - -Shape extraction works on both exported and non-exported declarations. - -#### Verification Checklist - -After regenerating docs, verify `docs-live/product-areas/.md` has: - -- [ ] Enriched intro paragraph (not just 1-2 sentences) -- [ ] Key Invariants section (3-4 invariants) -- [ ] Mermaid diagram(s) with nodes AND edges (not isolated nodes) -- [ ] API Types section with extracted shapes (if TS source declarations were tagged) -- [ ] Behavior Specifications listing all patterns with invariants and scenarios - -```bash -# Quick verification -grep -c "mermaid" docs-live/product-areas/.md # Should be >= 2 -grep -c "API Types" docs-live/product-areas/.md # Should be 1 -``` - ---- diff --git a/docs/PUBLISHING.md b/MAINTAINERS.md similarity index 99% rename from docs/PUBLISHING.md rename to MAINTAINERS.md index ac7d0ba4..8491e633 100644 --- a/docs/PUBLISHING.md +++ b/MAINTAINERS.md @@ -1,4 +1,4 @@ -# Publishing Guide +# Maintainer Guide This guide covers how to publish `@libar-dev/delivery-process` to npm. diff --git a/README.md b/README.md index bef847f4..8d99a708 100644 --- a/README.md +++ b/README.md @@ -8,44 +8,12 @@ Turn TypeScript annotations and Gherkin specs into a **structured, queryable del [![Build Status](https://github.com/libar-dev/delivery-process/workflows/CI/badge.svg)](https://github.com/libar-dev/delivery-process/actions) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Node.js Version](https://img.shields.io/node/v/@libar-dev/delivery-process.svg)](https://nodejs.org/) -[![npm provenance](https://img.shields.io/badge/provenance-verified-brightgreen)](https://docs.npmjs.com/generating-provenance-statements) - -> **v1.0.0-pre.0** — Pre-release for validation. We welcome feedback and contributions. --- ## Why This Exists -AI coding agents (Claude Code, Cursor, Copilot Workspace) need architectural context to generate correct code. Today they scrape README files, parse stale Markdown, and guess at relationships — leading to hallucinated imports, violated patterns, and wasted context windows. - -This package makes **code the single source of truth** for both humans and machines: - -| Aspect | Traditional Docs | Context Engineering (This Package) | -| ------------------ | ---------------------------- | ----------------------------------- | -| **Source** | Separate Markdown/Confluence | Annotations in code + Gherkin specs | -| **Freshness** | Manual updates → drift | Generated → always current | -| **Enforcement** | Guidelines (ignored) | FSM-validated transitions | -| **Traceability** | Manual links | Auto-generated dependency graphs | -| **AI Integration** | Parse stale Markdown | CLI queries with typed JSON output | - ---- - -## Built for AI-Assisted Development - -Traditional docs optimize for human reading. This package optimizes for **AI agent consumption**. - -```bash -# Instead of: "Read ROADMAP.md and tell me what's active" -pnpm process:query -- query getCurrentWork - -# Instead of: "Can we start working on TransformDataset?" -pnpm process:query -- query isValidTransition roadmap active - -# Instead of: "What does DualSourceExtractor depend on?" -pnpm process:query -- dep-tree DualSourceExtractor -``` - -**Claude Code, Cursor, GitHub Copilot Workspace** — any AI that can run shell commands gets typed JSON access to your delivery state. No Markdown parsing. No context drift. No hallucinated relationships. +AI coding agents need architectural context to generate correct code. This package makes **code the single source of truth** for both humans and machines — annotations in code and Gherkin specs replace manually maintained docs that drift out of date. --- @@ -59,20 +27,12 @@ npm install @libar-dev/delivery-process@pre # pnpm (recommended) pnpm add @libar-dev/delivery-process@pre - -# yarn -yarn add @libar-dev/delivery-process@pre ``` -**Requirements:** - -- Node.js >= 18.0.0 -- ESM project (`"type": "module"` in package.json) +**Requirements:** Node.js >= 18.0.0, ESM project (`"type": "module"` in package.json) ### 2. Annotate Your Code -Add opt-in marker and pattern metadata: - ```typescript /** @docs */ @@ -90,7 +50,7 @@ export class UserAuthentication { } ``` -> **Note:** Tag prefix is configurable. The `generic` preset uses `@docs-*` (shown above). The default `libar-generic` preset uses `@libar-docs-*`. See [Configuration](#configuration). +> Tag prefix is configurable. The `generic` preset uses `@docs-*` (shown above). The default `libar-generic` preset uses `@libar-docs-*`. See [docs/CONFIGURATION.md](docs/CONFIGURATION.md). ### 3. Generate Documentation @@ -110,8 +70,6 @@ This validates FSM transitions and blocks invalid status changes. ## How It Works -This package documents itself using its own annotation system. Here's a real example from the codebase: - **TypeScript annotations** define pattern metadata and relationships: ```typescript @@ -120,45 +78,13 @@ This package documents itself using its own annotation system. Here's a real exa * @libar-docs-pattern TransformDataset * @libar-docs-status completed * @libar-docs-uses MasterDataset, ExtractedPattern, TagRegistry - * @libar-docs-used-by Orchestrator - * - * ## TransformDataset - Single-Pass Pattern Transformation - * - * Transforms raw extracted patterns into a MasterDataset with all - * pre-computed views in a single O(n) pass. */ export function transformToMasterDataset(input: TransformInput): MasterDataset { // ... } ``` -**Gherkin feature files** own planning metadata: - -```gherkin -@libar-docs -@libar-docs-pattern:TransformDataset -@libar-docs-status:completed -@libar-docs-phase:12 -Feature: Transform Dataset - - Background: Deliverables - | Deliverable | Status | - | Single-pass transformer | completed | - | Pre-computed views | completed | - - Scenario: Transform patterns to MasterDataset - Given extracted patterns from TypeScript and Gherkin - When I call transformToMasterDataset - Then I get a MasterDataset with status, phase, and category groups -``` - -**Run the generator:** - -```bash -npx generate-docs -g patterns -i "src/**/*.ts" --features "specs/**/*.feature" -o docs -f -``` - -**Get living documentation** — pattern registries, dependency graphs, roadmaps — all generated from your annotated source. +**Gherkin feature files** own planning metadata (status, phase, deliverables). The generator merges both sources into a unified MasterDataset. **Pipeline:** `Config → Scanner → Extractor → Transformer → Codec` — files become patterns, patterns become a MasterDataset, the MasterDataset renders to Markdown and JSON. @@ -166,336 +92,53 @@ npx generate-docs -g patterns -i "src/**/*.ts" --features "specs/**/*.feature" - ## What Gets Generated -The codec pipeline produces rich, multi-format documents from a single config declaration. Every content block below is **derived from annotations** — not hand-authored: - -| Content Block | Source | Example | -| --------------------------------- | ---------------------------------------------- | --------------------------------------------------------- | -| **Convention tables** | Gherkin `Rule:` Invariant/Rationale | FSM protection levels, tag format types, source ownership | -| **Live Mermaid diagrams** | `@docs-uses`, `@docs-depends-on` relationships | C4Context, sequence, class, state, flowchart (6 types) | -| **API Types** | `@docs-shape` on TypeScript declarations | Functions, interfaces, constants, type aliases with JSDoc | -| **Behavior specifications** | Feature descriptions + `Rule:` blocks | Collapsible rules with verified-by scenario lists | -| **Architecture decision records** | Decision feature files | Context/Decision/Consequences with structured tables | -| **Roadmap & status tracking** | `@docs-status`, `@docs-phase` tags | Phase progress, deliverable tables, completion metrics | +All output goes to [`docs-live/`](docs-live/INDEX.md) — 57+ auto-generated files from annotated source code: -**Config-driven generation:** A single `ReferenceDocConfig` object produces a complete reference document — convention tables, scoped diagrams, extracted types, and behavior specs composed automatically. 13 configs produce 27 generators (detailed + AI-compact pairs). +| Output | Files | Source | +| --------------------------------- | ----: | ----------------------------------------------- | +| **Product area docs** | 7 | `@docs-uses`, `@docs-status`, relationship tags | +| **Business rules** | 7 | Gherkin `Rule:` Invariant/Rationale blocks | +| **Architecture decisions (ADRs)** | 7 | Decision feature files | +| **Reference guides** | 8 | CLI schema, codec patterns, annotations | +| **Live Mermaid diagrams** | — | `@docs-uses`, `@docs-depends-on` relationships | +| **API type shapes** | — | `@docs-shape` on TypeScript declarations | +| **Validation rules** | 3 | Process Guard FSM specs | +| **Taxonomy reference** | 3 | Tag registry | +| **AI context modules** | 13 | `@docs-claude-module` tagged specs | +| **Changelog** | 1 | Release specs | -**See it live:** [docs-live/product-areas/](docs-live/product-areas/) contains 7 generated product area documents with live Mermaid diagrams and extracted API types — all from annotations in this codebase. +**Browse it:** [`docs-live/INDEX.md`](docs-live/INDEX.md) is the navigation hub with reading order, document roles, and product area statistics. --- ## CLI Commands -| Command | Purpose | Docs | -| ----------------------- | ------------------------------------------------------ | ----------------------------------------- | -| `generate-docs` | Generate documentation from annotated sources | See flags below | -| `process-api` | Query delivery state for AI coding sessions | [PROCESS-API.md](docs/PROCESS-API.md) | -| `lint-patterns` | Validate annotation quality (missing tags, etc.) | [VALIDATION.md](docs/VALIDATION.md) | -| `lint-process` | Validate delivery workflow FSM transitions | [PROCESS-GUARD.md](docs/PROCESS-GUARD.md) | -| `lint-steps` | Validate vitest-cucumber feature/step compatibility | [VALIDATION.md](docs/VALIDATION.md) | -| `validate-patterns` | Cross-source validation with Definition of Done checks | [VALIDATION.md](docs/VALIDATION.md) | -| `generate-tag-taxonomy` | _(Deprecated)_ Generate tag reference from taxonomy | See flags below | - -### generate-docs - -Generate documentation from annotated sources. - -```bash -generate-docs [options] -``` - -| Flag | Short | Description | Default | -| ---------------------------- | ----- | ---------------------------------------------- | ------------------- | -| `--input ` | `-i` | Glob pattern for TypeScript files (repeatable) | from config | -| `--generators ` | `-g` | Generator names (comma-separated) | `patterns` | -| `--features ` | | Glob pattern for Gherkin files | - | -| `--exclude ` | `-e` | Exclude pattern (repeatable) | - | -| `--output ` | `-o` | Output directory | `docs/architecture` | -| `--base-dir ` | `-b` | Base directory | cwd | -| `--overwrite` | `-f` | Overwrite existing files | false | -| `--workflow ` | `-w` | Workflow config JSON file | - | -| `--list-generators` | | List available generators | - | -| `--git-diff-base ` | | PR Changes: base branch for diff | - | -| `--changed-files ` | | PR Changes: explicit file list | - | -| `--release-filter ` | | PR Changes: filter by release | - | - -```bash -# Generate pattern docs -generate-docs -g patterns -i "src/**/*.ts" -o docs -f - -# List all available generators -generate-docs --list-generators - -# Generate with Gherkin specs -generate-docs -g patterns -i "src/**/*.ts" --features "specs/**/*.feature" -o docs -f -``` - -### generate-tag-taxonomy - -> **Deprecated:** Use `generate-docs -g taxonomy` instead for codec-based generation with progressive disclosure. This standalone command will be removed in a future version. - -Generate a complete tag reference document from the TypeScript taxonomy source. - -```bash -generate-tag-taxonomy [options] -``` - -| Flag | Short | Description | Default | -| ------------------ | ----- | ----------------------- | ----------------------------------- | -| `--output ` | `-o` | Output file path | `docs/architecture/TAG_TAXONOMY.md` | -| `--overwrite` | `-f` | Overwrite existing file | false | -| `--base-dir ` | `-b` | Base directory | cwd | - -```bash -npx generate-tag-taxonomy -o TAG_TAXONOMY.md -f -``` - -For tag concepts and taxonomy architecture, see [docs/TAXONOMY.md](docs/TAXONOMY.md). - ---- - -## Proven at Scale - -This methodology was validated across **422 executable specifications** and an **8.8M line monorepo** (43,949 files). The results challenged assumptions about AI context management. - -### The Discovery - -| Metric | Traditional Prompts | Structured Specs | -| ---------------------------------- | ------------------- | ------------------------------------ | -| Context usage during heavy editing | ~100% (fills up) | **50-65%** (stays low) | -| After context compaction | Breaks continuity | **No impact** — results stay perfect | -| Work completed per session | 1X baseline | **5X increase** | -| Planning/decision overhead | High | **Near zero** | - -### Why It Works - -Traditional AI prompts are verbose and imprecise. Structured specs are concise and typed: - -```gherkin -Rule: Status transitions must follow FSM - - Scenario Outline: Valid transitions pass - Given a file with status "" - When status changes to "" - Then validation passes - - Examples: - | from | to | - | roadmap | active | - | active | completed | -``` - -**The AI understands structure better than prose.** Gherkin files compress into context more efficiently than explanatory paragraphs. - -### Real Results: 3-Session MVP - -The Process Guard validation system was implemented in 3 sessions using only structured specs as context: - -| Session | Context Used | Observation | -| ------- | ----------------- | -------------------------------------------------- | -| 1 | 100% → compressed | Speed **increased** after compression | -| 2 | **65%** | First time context stayed low during heavy editing | -| 3 | **55%** | Context actually **decreased** during work | - -### Before/After: ESLint Rules - -Before structured specs, AI assistants generated patterns that violated architectural constraints. The workaround was **106 custom ESLint rules** — each requiring tests, maintenance, and exception lists. With structured specs, the AI reads the spec and generates correct patterns from the start. **106 ESLint rules → 0.** - ---- - -## FSM-Enforced Workflow - -Status transitions are **validated programmatically**, not just documented: - -``` -roadmap ──→ active ──→ completed - │ │ - │ ↓ - │ roadmap (blocked/regressed) - ↓ -deferred ──→ roadmap -``` - -| State | Protection Level | What's Allowed | -| ----------- | ---------------- | ---------------------------------------- | -| `roadmap` | None | Full editing | -| `active` | **Scope-locked** | Implementation only, no new deliverables | -| `completed` | **Hard-locked** | Requires `@docs-unlock-reason` to modify | -| `deferred` | None | Full editing | - -**Pre-commit enforcement:** - -```bash -# In package.json scripts -"lint:process": "lint-process --staged" - -# Or in .husky/pre-commit -npx lint-process --staged -``` - -Invalid transitions are **rejected at commit time** — not discovered weeks later. - ---- - -## Data API CLI - -For AI coding sessions, use the CLI to query delivery state directly from annotated sources: - -```bash -# Status overview -pnpm process:query -- overview - -# What's currently being worked on? -pnpm process:query -- query getCurrentWork - -# Session context bundle for a pattern -pnpm process:query -- context MyPattern --session design - -# FSM transition check -pnpm process:query -- query isValidTransition roadmap active - -# Dependency tree -pnpm process:query -- dep-tree Orchestrator -``` - -| Approach | Context Cost | Accuracy | Speed | -| ------------------------ | ------------ | --------------------- | ------- | -| Parse generated Markdown | High | Snapshot at gen time | Slow | -| **Data API CLI** | Low | Real-time from source | Instant | - ---- - -## Rich Relationship Model - -The package supports a full taxonomy of relationships: - -| Relationship | Tag(s) | Meaning | -| ------------ | ------------------------------------ | -------------------- | -| Dependency | `@docs-uses` / `@docs-used-by` | Technical coupling | -| Sequencing | `@docs-depends-on` / `@docs-enables` | Roadmap ordering | -| Hierarchy | `@docs-parent` / `@docs-level` | Epic → Phase → Task | -| Realization | `@docs-implements` | Code realizes a spec | - -Auto-generated Mermaid dependency graph: - -```mermaid -graph TD - Orchestrator --> PatternScanner - Orchestrator --> DocExtractor - Orchestrator --> GeneratorRegistry - DualSourceExtractor --> DocExtractor - DualSourceExtractor --> GherkinExtractor - DataAPICLI -.-> MasterDataset -``` - ---- - -## How It Compares - -| Tool | Living Docs | FSM Enforcement | AI API | Code-First | AI Context Optimized | -| -------------------------- | ----------- | --------------- | ------ | ---------- | -------------------- | -| **This package** | Yes | Yes | Yes | Yes | Yes (50-65%) | -| Backstage | Yes | No | No | No (YAML) | No | -| Mintlify / GitBook | Partial | No | No | No | No | -| Notion / Confluence | No | No | No | No | No | -| Docusaurus / VitePress | No | No | No | Partial | No | -| Gherkin Living Doc | Yes | No | No | Yes | Partial | -| CLAUDE.md / manual prompts | No | No | No | No | No (100%) | - -**Key differentiators:** - -- **FSM enforcement** — Not just docs; validated state machine transitions at commit time -- **Dual-source** — TypeScript owns runtime relationships, Gherkin owns planning constraints = complete picture -- **AI-native** — CLI provides typed JSON queries, not string parsing -- **Context efficient** — Structured specs use 50-65% context vs 100% for prose prompts -- **Compaction resilient** — Specs survive context compression; prose doesn't - -**Note on AI models:** This methodology was validated primarily with Claude (Anthropic). The structured spec approach benefits any LLM-based coding assistant, leveraging pattern-recognition capabilities particularly well. - ---- - -## Design-First Development - -The package enforces a clear separation between **design artifacts** (stubs in `delivery-process/stubs/`) and **production code** (in `src/`). Design stubs use `throw new Error('not yet implemented')` and are excluded from ESLint, avoiding the need for lint exceptions on unfinished code. See [docs/METHODOLOGY.md](docs/METHODOLOGY.md) for the full stub workflow. - ---- - -## Document Durability Model - -Not all specs are equal. Decision docs and behavior specs are **permanent** (tested, durable). Tier 1 roadmap specs are **temporary** (tracking until completion). Generated docs are **derived** (regenerated from source). This hierarchy enables documentation generation from durable sources — details in [docs/METHODOLOGY.md](docs/METHODOLOGY.md). - ---- - -## Use Cases - -| Scenario | How This Package Helps | -| ------------------------------ | ----------------------------------------- | -| **Multi-phase roadmaps** | FSM-enforced status transitions | -| **AI coding sessions** | Data API CLI for typed context | -| **Documentation generation** | Mermaid diagrams, pattern registries | -| **Traceability requirements** | Two-tier specs link planning to code | -| **Pre-commit validation** | `lint-process` blocks invalid transitions | -| **Architecture documentation** | Auto-generated dependency graphs | - ---- - -## Configuration - -```typescript -// delivery-process.config.ts -import { defineConfig } from '@libar-dev/delivery-process/config'; - -// Libar-generic preset (default) — this package uses it -export default defineConfig({ - preset: 'libar-generic', - sources: { typescript: ['src/**/*.ts'], features: ['specs/*.feature'] }, - output: { directory: 'docs-generated', overwrite: true }, -}); - -// DDD-ES-CQRS preset — complex domain architectures -export default defineConfig({ - preset: 'ddd-es-cqrs', - sources: { typescript: ['packages/*/src/**/*.ts'] }, -}); - -// Generic preset — shorter tag names (@docs-* prefix) -export default defineConfig({ - preset: 'generic', - sources: { typescript: ['src/**/*.ts'] }, -}); -``` - -| Preset | Tag Prefix | Categories | Use Case | -| ------------------------- | --------------- | ---------- | ---------------------------------- | -| `libar-generic` (default) | `@libar-docs-*` | 3 | Simple projects (this package) | -| `ddd-es-cqrs` | `@libar-docs-*` | 21 | DDD/Event Sourcing architectures | -| `generic` | `@docs-*` | 3 | Simple projects with @docs- prefix | - -See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for custom presets. +| Command | Purpose | Docs | +| ------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------- | +| `generate-docs` | Generate documentation from annotated sources | `generate-docs --help` | +| `process-api` | Query delivery state for AI coding sessions | [Process API Reference](docs-live/reference/PROCESS-API-REFERENCE.md) | +| `lint-patterns` | Validate annotation quality (missing tags, etc.) | [Validation Rules](docs-live/VALIDATION-RULES.md) | +| `lint-process` | Validate delivery workflow FSM transitions | [Process Guard Reference](docs-live/reference/PROCESS-GUARD-REFERENCE.md) | +| `lint-steps` | Validate vitest-cucumber feature/step compatibility | [Validation Rules](docs-live/VALIDATION-RULES.md) | +| `validate-patterns` | Cross-source validation with Definition of Done checks | [Validation Rules](docs-live/VALIDATION-RULES.md) | --- ## Documentation -**[docs/INDEX.md](docs/INDEX.md)** provides a complete table of contents with section links, line numbers, and reading paths by role. - -**Start here:** +### Generated Docs (auto-maintained) -| Document | When to read | -| -------------------------------------- | ---------------------------- | -| [README](README.md) | Installation and quick start | -| [CONFIGURATION](docs/CONFIGURATION.md) | Setting up presets and tags | -| [METHODOLOGY](docs/METHODOLOGY.md) | Understanding the "why" | +**[`docs-live/INDEX.md`](docs-live/INDEX.md)** is the navigation hub — 57+ files generated from annotated source code, organized into product areas, reference guides, business rules, ADRs, taxonomy, and validation rules. -**Go deeper:** +### Editorial Docs (hand-maintained) -| Document | Audience | Focus | -| -------------------------------------------- | ---------- | ------------------------- | -| [ARCHITECTURE](docs/ARCHITECTURE.md) | Developers | Pipeline, codecs, schemas | -| [SESSION-GUIDES](docs/SESSION-GUIDES.md) | AI/Devs | Day-to-day workflows | -| [GHERKIN-PATTERNS](docs/GHERKIN-PATTERNS.md) | Writers | Writing effective specs | -| [PROCESS-GUARD](docs/PROCESS-GUARD.md) | Team Leads | FSM enforcement rules | -| [VALIDATION](docs/VALIDATION.md) | CI/CD | Automated quality checks | -| [TAXONOMY](docs/TAXONOMY.md) | Reference | Tag taxonomy and API | +| Document | Focus | +| ----------------------------------------------- | ------------------------------ | +| [CONFIGURATION.md](docs/CONFIGURATION.md) | Presets, tags, config files | +| [METHODOLOGY.md](docs/METHODOLOGY.md) | Core thesis, dual-source "why" | +| [GHERKIN-PATTERNS.md](docs/GHERKIN-PATTERNS.md) | Writing effective specs | +| [SESSION-GUIDES.md](docs/SESSION-GUIDES.md) | Day-to-day AI/dev workflows | +| [VALIDATION.md](docs/VALIDATION.md) | Automated quality checks | --- diff --git a/_claude-md/CLAUDE-MODULES.md b/_claude-md/CLAUDE-MODULES.md new file mode 100644 index 00000000..a5691c8d --- /dev/null +++ b/_claude-md/CLAUDE-MODULES.md @@ -0,0 +1,9 @@ +### Claude Modules + +#### Generated Modules + +1 module(s) generated from annotated behavior specs. + +| Module | Section | Source Pattern | Content | +| --- | --- | --- | --- | +| session-workflows | workflow | SessionGuidesModuleSource | 9 rules | diff --git a/_claude-md/api/data-api-cli.md b/_claude-md/api/data-api-cli.md index b59c4bd2..a9b501a8 100644 --- a/_claude-md/api/data-api-cli.md +++ b/_claude-md/api/data-api-cli.md @@ -4,54 +4,7 @@ Query delivery process state directly from the terminal. **Use this instead of r **Run `pnpm process:query -- --help` for the full command reference**, including workflow recipes, session types, architecture queries, output modifiers, and available API methods. -#### Session Start Recipe - -1. `pnpm process:query -- overview` — project health (progress, active phases, blockers) -2. `pnpm process:query -- scope-validate ` — pre-flight check (FSM, deps, prereqs) -3. `pnpm process:query -- context --session ` — curated context bundle - -Session types: `planning` (minimal), `design` (full: stubs + deps + deliverables), `implement` (focused: deliverables + FSM + tests). - -#### Key Commands - -| Command | When to Use | -| ----------------------- | ------------------------------------------------------------------------------------- | -| `scope-validate` | **Highest impact** — prevents wasted sessions by catching violations before you start | -| `context --session` | Primary context gathering — replaces manual file reads | -| `dep-tree ` | Understand dependency chains before implementation | -| `list --status roadmap` | Find available patterns to work on | -| `arch blocking` | Find patterns stuck on incomplete dependencies | -| `stubs --unresolved` | Find design stubs missing implementations | -| `rules` | Business rules and invariants from Gherkin `Rule:` blocks | -| `files ` | File reading list with implementation paths — replaces manual path discovery | -| `decisions ` | Design decisions (AD-N) from stub descriptions | -| `pdr ` | Cross-reference patterns mentioning a PDR number | -| `handoff --pattern` | Capture session-end state for multi-session work | - -#### Annotation Exploration - -Run these **before** making annotation changes — they prevent debugging cycles: - -| Command | When to Use | -| -------------------------- | ----------------------------------------------------------------------------- | -| `unannotated --path ` | Find TS files missing `@libar-docs` — **run first** in any enrichment session | -| `tags` | Tag usage inventory (counts per tag and value) | -| `sources` | File inventory by type (TS, Gherkin, Stubs) | -| `query getPattern ` | Full pattern JSON including `extractedShapes` and `productArea` | - -**Lesson learned:** `unannotated --path src/types` would have immediately caught missing `@libar-docs` annotations on `result.ts` and `errors.ts` — saving ~30 minutes of debugging why shapes weren't appearing in generated docs. - -#### Architecture Queries - -Query architectural structure directly — avoids explore agents for structural questions: - -| Command | When to Use | -| --------------------- | ---------------------------------------------------- | -| `arch coverage` | Annotation completeness across the project | -| `arch context [name]` | Patterns in bounded context (list all if no name) | -| `arch layer [name]` | Patterns in architecture layer (list all if no name) | -| `arch dangling` | Broken references — pattern names that don't resolve | -| `arch orphans` | Isolated patterns with no relationships | +See the **Context Gathering Protocol** section above for mandatory session start commands and query recipes. #### Tips diff --git a/_claude-md/authoring/feature-content.md b/_claude-md/authoring/feature-content.md index 1ec04db7..5e0e0aa3 100644 --- a/_claude-md/authoring/feature-content.md +++ b/_claude-md/authoring/feature-content.md @@ -20,59 +20,6 @@ Rule: Reservations use atomic claim Code stubs live in `delivery-process/stubs/{pattern-name}/` — annotated TypeScript with `throw new Error("not yet implemented")`. -#### Rule Block Structure (Mandatory) - -Every feature file MUST use `Rule:` blocks with structured descriptions: - -```gherkin -Rule: Reservations prevent race conditions - - **Invariant:** Only one reservation can exist for a given key at a time. - - **Rationale:** Check-then-create patterns have TOCTOU vulnerabilities. - - **Verified by:** Concurrent reservations, Expired reservation cleanup - - @acceptance-criteria @happy-path - Scenario: Concurrent reservations - ... -``` - -| Element | Purpose | Extracted By | -| ------------------ | --------------------------------------- | ------------------------ | -| `**Invariant:**` | Business constraint (what must be true) | Business Rules generator | -| `**Rationale:**` | Business justification (why it exists) | Business Rules generator | -| `**Verified by:**` | Comma-separated scenario names | Traceability generator | - -#### Feature Description Structure - -Choose headers that fit your pattern (flexible, not rigid): - -| Structure | Headers | Best For | -| ---------------- | ------------------------------------------ | ------------------------- | -| Problem/Solution | `**Problem:**`, `**Solution:**` | Pain point to fix | -| Value-First | `**Business Value:**`, `**How It Works:**` | TDD-style, Gherkin spirit | -| Context/Approach | `**Context:**`, `**Approach:**` | Technical patterns | - -Always include a benefits table: - -```gherkin -**Business Value:** -| Benefit | Impact | -| ... | ... | -``` - -#### Valid Rich Content - -| Content Type | Syntax | Appears in Docs | -| ------------- | ----------------------- | ---------------- | -| Plain text | Regular paragraphs | Yes | -| Bold/emphasis | `**bold**`, `*italic*` | Yes | -| Tables | Markdown pipe tables | Yes | -| Lists | `- item` or `1. item` | Yes | -| DocStrings | `"""typescript`...`"""` | Yes (code block) | -| Comments | `# comment` | No (ignored) | - #### Forbidden in Feature Descriptions | Forbidden | Why | Alternative | @@ -82,41 +29,6 @@ Always include a benefits table: | Nested DocStrings | Gherkin parser error | Reference code stub file | | `#` at line start | Gherkin comment — kills parsing | Remove, use `//`, or step DocStr | -#### Description `"""` Blocks vs Step DocStrings (CRITICAL) - -**`"""` inside Feature/Rule descriptions is plain text, NOT a DocString.** Only `"""` as step arguments (Given/When/Then) creates real DocStrings. This means description content between `"""` is subject to Gherkin parser rules — including `#` = comment. - -**Symptom:** `expected: #EOF, #BackgroundLine... got 'some-content'` - -```gherkin -Rule: My Rule - - """bash - # This breaks! Parser sees Gherkin comment, terminates description - generate-docs --output docs - """ -``` - -**Workarounds:** - -| Approach | When to Use | -| --------------------------- | ---------------------------------- | -| Remove `#` lines | Simple cases | -| Use `//` for comments | When comment syntax doesn't matter | -| Move to step DocString | When you need code with `#` | -| Reference stub file instead | Complex examples (preferred) | - -**Safe pattern — step DocString (content is real DocString, `#` is safe):** - -```gherkin - Scenario: Example usage - Given the following script: - """bash - # This is safe — real DocString, not description text - generate-docs --output docs - """ -``` - #### Tag Value Constraints **Tag values cannot contain spaces.** Use hyphens instead: diff --git a/_claude-md/authoring/gherkin-patterns.md b/_claude-md/authoring/gherkin-patterns.md index 709e850c..8e5bdbb8 100644 --- a/_claude-md/authoring/gherkin-patterns.md +++ b/_claude-md/authoring/gherkin-patterns.md @@ -29,16 +29,7 @@ Feature: Process Guard Linter | Value-First | `**Business Value:**`, `**How It Works:**` | TDD-style specs | | Context/Approach | `**Context:**`, `**Approach:**` | Technical patterns | -#### Tag Conventions - -| Tag | Purpose | -| ---------------------- | --------------------------- | -| `@happy-path` | Primary success scenario | -| `@edge-case` | Boundary conditions | -| `@error-handling` | Error recovery scenarios | -| `@validation` | Input validation rules | -| `@acceptance-criteria` | Required for DoD validation | -| `@integration` | Cross-component behavior | +Tag inventory: `pnpm process:query -- tags` (counts per tag and value across all sources). #### Rule Block Structure (Mandatory) diff --git a/_claude-md/core/architecture.md b/_claude-md/core/architecture.md index dc29aff6..1d0dfcee 100644 --- a/_claude-md/core/architecture.md +++ b/_claude-md/core/architecture.md @@ -19,28 +19,19 @@ CONFIG → SCANNER → EXTRACTOR → TRANSFORMER → CODEC - **Pipeline Factory**: Shared `buildMasterDataset()` in `src/generators/pipeline/build-pipeline.ts` — all consumers (orchestrator, process-api, validate-patterns) call this instead of wiring inline pipelines. Per-consumer behavior via `PipelineOptions`. - **Single Read Model** (ADR-006): MasterDataset is the sole read model. No consumer re-derives data from raw scanner/extractor output. Anti-patterns: Parallel Pipeline, Lossy Local Type, Re-derived Relationship. -### Module Structure - -| Module | Purpose | -| -------------------------- | -------------------------------------------------------------------- | -| `src/config/` | Configuration factory, presets (generic, ddd-es-cqrs) | -| `src/taxonomy/` | Tag definitions - categories, status values, format types | -| `src/scanner/` | TypeScript and Gherkin file scanning | -| `src/extractor/` | Pattern extraction from AST/Gherkin | -| `src/generators/` | Document generators, orchestrator, and pipeline factory | -| `src/generators/pipeline/` | `buildMasterDataset()` factory, `mergePatterns()`, dataset transform | -| `src/renderable/` | Markdown codec system | -| `src/validation/` | FSM validation, DoD checks, anti-patterns | -| `src/lint/` | Pattern linting and process guard | -| `src/api/` | Query layer: Data API CLI, business rules query (`rules-query.ts`) | -| `delivery-process/stubs/` | Design session code stubs (outside src/ for TS/ESLint isolation) | - -**Live inventory:** `pnpm process:query -- arch context` and `pnpm process:query -- arch layer` reflect the actual annotated codebase structure. - -### Three Presets - -| Preset | Tag Prefix | Categories | Use Case | -| ------------------------- | -------------- | ---------- | ---------------------------------- | -| `libar-generic` (default) | `@libar-docs-` | 3 | Simple projects (this package) | -| `ddd-es-cqrs` | `@libar-docs-` | 21 | DDD/Event Sourcing architectures | -| `generic` | `@docs-` | 3 | Simple projects with @docs- prefix | +**Live module inventory:** `pnpm process:query -- arch context` and `pnpm process:query -- arch layer` + +### Decision Specs + +Architecture and process decisions are recorded as annotated Gherkin specs in `delivery-process/decisions/`: + +| Spec | Key Decision | +| ------- | -------------------------------------------------------------------------- | +| ADR-001 | Taxonomy canonical values — tag registry is the single source of truth | +| ADR-002 | Gherkin-only testing — no `.test.ts` files, all tests are `.feature` | +| ADR-003 | Source-first pattern architecture — code drives docs, not the reverse | +| ADR-005 | Codec-based markdown rendering — Zod codecs transform data to markdown | +| ADR-006 | Single read model — MasterDataset is the sole read model for all consumers | +| PDR-001 | Session workflow commands — Process Data API CLI design decisions | + +Query decisions: `pnpm process:query -- decisions ` diff --git a/_claude-md/core/common-commands.md b/_claude-md/core/common-commands.md index 08a64624..f5ac8092 100644 --- a/_claude-md/core/common-commands.md +++ b/_claude-md/core/common-commands.md @@ -13,18 +13,12 @@ pnpm test # Run tests matching pattern (e.g., pnpm test scanner) # Linting pnpm lint # ESLint on src and tests pnpm lint:fix # Auto-fix lint issues -pnpm lint-patterns # Lint pattern annotations in src/**/*.ts -# Validation -pnpm validate:patterns # Cross-source pattern validation -pnpm validate:dod # Definition of Done validation -pnpm validate:all # All validations including anti-patterns +# Validation + Documentation +pnpm validate:all # All validations including anti-patterns and DoD +pnpm docs:all # Generate all doc types -# Documentation generation -pnpm docs:patterns # Generate pattern docs -pnpm docs:all # Generate all doc types (patterns, roadmap, remaining, changelog) - -# Data API (see "Data API CLI" section for full reference) +# Data API (see Context Gathering Protocol above) pnpm process:query -- --help # All subcommands and options pnpm process:query -- context --session design # Session context bundle pnpm process:query -- overview # Project health summary diff --git a/_claude-md/core/context-protocol.md b/_claude-md/core/context-protocol.md new file mode 100644 index 00000000..bf06292a --- /dev/null +++ b/_claude-md/core/context-protocol.md @@ -0,0 +1,40 @@ +### Context Gathering Protocol (MANDATORY) + +**Rule: Always query the Process Data API BEFORE using grep, explore agents, or reading files.** + +The API returns structured, current data using 5-10x less context than file reads. Annotations and relationships in source files feed the API — invest in annotations, not manual notes. + +#### PR / Session Start (run these FIRST) + +| Step | Command | What You Get | +| ---- | ---------------------------------------------------------- | ------------------------------------------- | +| 1 | `pnpm process:query -- overview` | Project health, active phases, blockers | +| 2 | `pnpm process:query -- scope-validate ` | Pre-flight: FSM violations, missing deps | +| 3 | `pnpm process:query -- context --session ` | Curated context bundle for the session | +| 4 | `pnpm process:query -- files --related` | File reading list with implementation paths | + +Session types: `planning` (minimal), `design` (full: stubs + deps + deliverables), `implement` (focused: deliverables + FSM + tests). + +#### When You Need More Context + +| Need | Command (NOT grep) | Why | +| ----------------------- | ------------------------------------------- | ------------------------------------------- | +| Find code structure | `arch context [name]` / `arch layer [name]` | Structured by annotations, not file paths | +| Find dependencies | `dep-tree ` | Shows status of each dependency | +| Find business rules | `rules --pattern ` | Extracted from Gherkin Rule: blocks | +| Find unannotated files | `unannotated --path ` | Catches missing @libar-docs markers | +| Check FSM state | `query getProtectionInfo ` | Protection level + allowed actions | +| Check valid transitions | `query getValidTransitionsFrom ` | Valid next states from current status | +| Tag inventory | `tags` | Counts per tag and value across all sources | +| Annotation coverage | `arch coverage` | Files with/without @libar-docs annotations | + +#### Why Annotations Beat Grep + +- **Structured**: `arch context` groups by bounded context; grep returns unstructured matches +- **Queryable**: `rules --only-invariants` extracts 140+ business rules; grep can't parse Rule: blocks +- **Feed generation**: Annotations produce generated docs; grep results are ephemeral +- **Discoverable**: `unannotated --path` finds gaps; grep doesn't know what's missing + +**When adding new code:** Add `@libar-docs` annotations and relationship tags (`@libar-docs-depends-on`, `@libar-docs-uses`) so future sessions can discover the code via API queries instead of grep. + +Full CLI reference: `pnpm process:query -- --help` diff --git a/_claude-md/core/project-overview.md b/_claude-md/core/project-overview.md index 97f4b9fd..8f713d92 100644 --- a/_claude-md/core/project-overview.md +++ b/_claude-md/core/project-overview.md @@ -33,49 +33,4 @@ This package uses itself as the primary test case: - `_claude-md/validation/process-guard.md` → compact AI context - `docs/PROCESS-GUARD.md` → detailed human reference -Both generated from the SAME annotated sources. When the POC succeeds here, the pattern applies to the entire monorepo. - -#### Session Planning Principle - -Features are planned for **reusability across the monorepo**, not for minimal output in this package. - ---- - -### Target Monorepo - -**Location:** `~/dev-projects/convex-event-sourcing/libar-platform` - -The package is actively used as a dev dependency. The monorepo contains: - -| Component | Purpose | -| ------------------------- | -------------------------------------------------------------------------- | -| `packages/platform-*` | 6 platform packages with annotated TypeScript sources | -| `delivery-process/specs/` | Tier 1 roadmap specifications | -| `docs-living/` | Generated documentation output (patterns, phases, requirements, decisions) | - -**Manual docs being replaced:** `~/dev-projects/convex-event-sourcing/docs/` contains 150+ manually maintained files including architecture decisions, pattern theory, roadmap phases, and project management docs—all candidates for code-first generation. - -#### What Gets Generated - -| Output Type | Purpose | -| ---------------------------- | ------------------------------------------ | -| `PATTERNS.md` + detail pages | Pattern registry from annotated TypeScript | -| `ROADMAP.md` + phase files | Roadmap from Tier 1 feature specs | -| `REMAINING-WORK.md` | Outstanding work summary | -| `CURRENT-WORK.md` | Active work tracking | -| `DECISIONS.md` + ADRs | Architecture decision records | -| `BUSINESS-RULES.md` | Business rules from Gherkin | - ---- - -### Why No Shortcuts - -Every shortcut in this package ripples across: - -- Multiple platform packages with annotated sources -- Many Gherkin feature specifications -- All generated documentation files - -**Test rigor matches mission-critical status.** A bug in the codec system means many files generate incorrectly. A gap in the extractor means patterns are missed across source files. - -The validation in this repo is a **proof of concept**. When it succeeds here, the same validation applies to the entire monorepo's delivery workflow. +Both generated from the SAME annotated sources. Features are planned for **reusability across the monorepo**, not for minimal output in this package. diff --git a/_claude-md/metadata.json b/_claude-md/metadata.json index b8fe9071..4581dd4d 100644 --- a/_claude-md/metadata.json +++ b/_claude-md/metadata.json @@ -16,6 +16,17 @@ } ] }, + { + "title": "Context Gathering Protocol", + "tags": ["core"], + "subsections": [ + { + "path": "core/context-protocol.md", + "tags": ["core"], + "description": "Mandatory API-first context gathering rules and PR preparation recipes" + } + ] + }, { "title": "Common Commands", "tags": ["core"], @@ -77,17 +88,7 @@ { "path": "workflow/session-workflows.md", "tags": ["core"], - "description": "Session decision tree and session types" - }, - { - "path": "workflow/session-details.md", - "tags": ["core"], - "description": "Planning, Design, and Implementation session details" - }, - { - "path": "workflow/fsm-handoff.md", - "tags": ["core"], - "description": "FSM protection, error messages, escape hatches, and handoff documentation" + "description": "Session types, FSM contracts, escape hatches, handoff (generated from SessionGuidesModuleSource spec)" } ] }, @@ -151,11 +152,11 @@ }, { "title": "Guides", - "tags": ["core"], + "tags": ["api-reference"], "subsections": [ { "path": "guides/product-area-enrichment.md", - "tags": ["core"], + "tags": ["api-reference"], "description": "Workflow for adding live diagrams and enriched intros to product area docs" } ] diff --git a/_claude-md/testing/test-implementation.md b/_claude-md/testing/test-implementation.md index 0bca31d9..f59e5c19 100644 --- a/_claude-md/testing/test-implementation.md +++ b/_claude-md/testing/test-implementation.md @@ -10,15 +10,6 @@ Issues discovered during step definition implementation: | `behaviorFileVerified` undefined | Patterns created without explicit verification status | Add `behaviorFileVerified: true/false` to `createTestPattern()` when testing traceability | | Discovery tags missing | SessionFindingsCodec shows "No Findings" | Pass `discoveredGaps`, `discoveredImprovements`, `discoveredLearnings` to factory | -### Codec vs. Spec Reality Gap - -Tier 1 specs are often idealistic drafts. The code is the reality. - -| Issue | Description | Fix | -| ------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -| Output Structure Mismatch | Spec expects "Phase 1" but Codec outputs derived name, or Spec expects table that Codec suppresses when empty | Run debug script to dump actual `RenderableDocument` JSON structure. Align Feature file to Codec's actual behavior | -| Data Normalization | Feature files use plain language (`planned`, `p1`) vs. Schema requirements (`roadmap`, `pattern-00...`) | Implement helper functions: `normalizeStatus(str)` maps 'planned' → 'roadmap'. `generatePatternId(n)` generates valid IDs | - ### Coding & Linting Standards The project has strict linting rules. Save time by coding defensively. @@ -28,22 +19,7 @@ The project has strict linting rules. Save time by coding defensively. | Unused variables: `(_ctx, count, text)` throws lint errors if `count` isn't used | Prefix **immediately**: `(_ctx, _count, text)` | | Type safety: `ListItem` is an object, not a string. `item + '\n'` throws errors | Check types before concatenation: `(typeof item === 'string' ? item : item.text)` | -### Deliverable Status Taxonomy (CRITICAL) - -Deliverable status is enforced by `z.enum()` at schema level. The 6 canonical values are defined in `src/taxonomy/deliverable-status.ts`: - -| Value | Meaning | Helper | -| ------------- | ------------------- | --------------------------------- | -| `complete` | Work is done | `isDeliverableStatusComplete()` | -| `in-progress` | Work is ongoing | `isDeliverableStatusInProgress()` | -| `pending` | Work hasn't started | `isDeliverableStatusPending()` | -| `deferred` | Work postponed | | -| `superseded` | Replaced by another | | -| `n/a` | Not applicable | | - -**NEVER** use freeform status strings. The Zod schema rejects non-canonical values at parse time. - -**Terminal statuses:** `complete`, `n/a`, and `superseded` are terminal per `isDeliverableStatusTerminal()`. Used by DoD validation — `deferred` is NOT terminal. +**Deliverable statuses:** 6 values enforced by `z.enum()`: `complete`, `in-progress`, `pending`, `deferred`, `superseded`, `n/a`. Terminal: `complete`, `n/a`, `superseded` (NOT `deferred`). NEVER use freeform strings. ### Efficient Debugging Strategy @@ -61,12 +37,3 @@ console.log(JSON.stringify(doc.sections, null, 2)); ``` - **Do** use `pnpm test remaining-work` (or specific filename) to run focused tests. - -### Implementation Workflow Checklist - -1. [ ] **Read Feature File:** identify Scenario counts and data types -2. [ ] **Check Factories:** Ensure `pattern-factories.ts` supports the fields needed (e.g., `phase`, `priority`) -3. [ ] **Prototype:** Run a `tsx` script to see what the Codec actually outputs for given inputs -4. [ ] **Adjust Spec:** Update Feature file to match Codec reality (e.g., quotes for lists, valid status names) -5. [ ] **Write Steps:** Implement steps with `_` prefixes for unused args -6. [ ] **Verify:** Run specific test file → Run related group → Run full suite diff --git a/_claude-md/testing/vitest-cucumber.md b/_claude-md/testing/vitest-cucumber.md index 4b96854c..ffc52856 100644 --- a/_claude-md/testing/vitest-cucumber.md +++ b/_claude-md/testing/vitest-cucumber.md @@ -84,36 +84,23 @@ describeFeature(feature, ({ Background, Rule }) => { }); ``` -### Docstring Pattern for Pipes - -Use docstrings when Gherkin content contains pipe characters: - -```typescript -Then('the output contains the table:', (_ctx: unknown, docString: string) => { - for (const line of docString.trim().split('\n')) { - expect(state!.markdown).toContain(line.trim()); - } -}); -``` - ### vitest-cucumber Quirks & Constraints The library behaves differently than standard Cucumber.js. -| Issue | Description | Fix | -| ------------------------ | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -| Repeated Step Patterns | Using exact same step pattern twice in one scenario fails to match or overwrites registrations | Avoid generic regex steps if reused. Use strict string matching. Consolidate assertions into DataTables | -| `{phrase}` not supported | vitest-cucumber does not support `{phrase}` type | Use `{string}` and wrap value in quotes in Feature file | -| Docstring stripping | Markdown headers (`## Header`) inside docstrings may be stripped or parsed incorrectly | Hardcode complex multi-line strings in step definition TS file | -| Feature descriptions | Starting a description line with `Given`, `When`, or `Then` breaks the parser | Ensure free-text descriptions do not start with reserved Gherkin keywords | -| Multiple And same text | Multiple `And` steps with identical text (different values) fail | Consolidate into single step with DataTable | -| No regex step patterns | `Then(/pattern/, ...)` throws `StepAbleStepExpressionError` | Use only string patterns with `{string}`, `{int}` placeholders | +| Issue | Description | Fix | +| ---------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| Docstring stripping | Markdown headers (`## Header`) inside docstrings may be stripped or parsed incorrectly | Hardcode complex multi-line strings in step definition TS file | +| Feature descriptions | Starting a description line with `Given`, `When`, or `Then` breaks the parser | Ensure free-text descriptions do not start with reserved Gherkin keywords | +| Multiple And same text | Multiple `And` steps with identical text (different values) fail | Consolidate into single step with DataTable | +| No regex step patterns | `Then(/pattern/, ...)` throws `StepAbleStepExpressionError` | Use only string patterns with `{string}`, `{int}` placeholders | ### Gherkin Parser: Hash Comments in Descriptions (CRITICAL) **Root Cause:** The @cucumber/gherkin parser interprets `#` at the start of a line as a Gherkin comment, even inside Feature/Rule descriptions. This terminates the description context and causes subsequent lines to fail parsing. **Symptom:** Parse error like: + ``` expected: #EOF, #Comment, #BackgroundLine, #TagLine, #ScenarioLine, #RuleLine, #Empty got 'generate-docs --decisions ...' @@ -133,6 +120,7 @@ Rule: My Rule ``` The parser sees: + 1. `"""bash` → literal text in description 2. `# This comment...` → Gherkin comment (TERMINATES description) 3. `generate-docs...` → unexpected content (PARSE ERROR) @@ -145,11 +133,11 @@ The parser sees: **Workarounds:** -| Option | Example | When to Use | -| ------ | ------- | ----------- | -| Remove hash comments | `generate-docs --output docs` | Simple cases | -| Use `//` instead | `// Generate docs` | When comment syntax doesn't matter | -| Move to step DocString | `Given the script: """bash...` | When you need executable examples | -| Manual parsing | Regex extraction bypassing Gherkin parser | When file must contain `#` | +| Option | Example | When to Use | +| ---------------------- | ----------------------------------------- | ---------------------------------- | +| Remove hash comments | `generate-docs --output docs` | Simple cases | +| Use `//` instead | `// Generate docs` | When comment syntax doesn't matter | +| Move to step DocString | `Given the script: """bash...` | When you need executable examples | +| Manual parsing | Regex extraction bypassing Gherkin parser | When file must contain `#` | **Note:** The `parseDescriptionWithDocStrings()` helper extracts `"""` blocks from description text AFTER parsing succeeds. The issue is the Gherkin parser itself failing before that helper runs. diff --git a/_claude-md/validation/anti-patterns.md b/_claude-md/validation/anti-patterns.md index de6ccd38..b5ebacf6 100644 --- a/_claude-md/validation/anti-patterns.md +++ b/_claude-md/validation/anti-patterns.md @@ -11,16 +11,6 @@ Enforces dual-source architecture ownership between TypeScript and Gherkin files | `@libar-docs-quarter` | Feature files | TypeScript | Gherkin owns timeline metadata | | `@libar-docs-team` | Feature files | TypeScript | Gherkin owns ownership metadata | -#### Single Read Model Anti-Patterns (ADR-006) - -| Anti-Pattern | Signal | -| ----------------------- | ----------------------------------------------------------------------------------- | -| Parallel Pipeline | Consumer imports from `scanner/` or `extractor/` instead of consuming MasterDataset | -| Lossy Local Type | Local interface with subset of `ExtractedPattern` fields | -| Re-derived Relationship | Building `Map`/`Set` from raw `implements`/`uses` arrays in consumer code | - -**Exception:** `lint-patterns.ts` is a stage-1 consumer (validates annotation syntax, no cross-source resolution). - #### DoD Validation For patterns with `completed` status, validates: @@ -28,19 +18,4 @@ For patterns with `completed` status, validates: - All deliverables have terminal status (`complete`, `n/a`, or `superseded`) per `isDeliverableStatusTerminal()` — `deferred` is NOT terminal - At least one `@acceptance-criteria` scenario exists in the spec -#### Running Validation - -```bash -# Anti-pattern check only -npx validate-patterns \ - -i "src/**/*.ts" \ - -F "specs/**/*.feature" \ - --anti-patterns - -# Full validation with DoD -npx validate-patterns \ - -i "src/**/*.ts" \ - -F "specs/**/*.feature" \ - --anti-patterns \ - --dod -``` +Run: `pnpm validate:all` for full validation including anti-patterns and DoD. diff --git a/_claude-md/validation/process-guard.md b/_claude-md/validation/process-guard.md index 4e252ac9..70d3c365 100644 --- a/_claude-md/validation/process-guard.md +++ b/_claude-md/validation/process-guard.md @@ -2,25 +2,8 @@ Process Guard validates delivery workflow changes at commit time using a Decider pattern. -#### 6 Validation Rules - -| Rule ID | Severity | Description | -| --------------------------- | -------- | --------------------------------------------------- | -| `completed-protection` | error | Completed specs require `@libar-docs-unlock-reason` | -| `invalid-status-transition` | error | Must follow FSM path | -| `scope-creep` | error | Active specs cannot add new deliverables | -| `session-excluded` | error | Cannot modify explicitly excluded files | -| `session-scope` | warning | File outside session scope | -| `deliverable-removed` | warning | Deliverable was removed | - -#### Protection Levels - -| Status | Protection | Allowed Actions | Blocked Actions | -| ----------- | ------------ | ------------------------------ | ----------------------------- | -| `roadmap` | None | Full editing, add deliverables | - | -| `deferred` | None | Full editing, add deliverables | - | -| `active` | Scope-locked | Edit existing deliverables | Adding new deliverables | -| `completed` | Hard-locked | Nothing | Any change without unlock tag | +Query validation rules: `pnpm process:query -- rules --pattern ProcessGuard` +Query protection levels: `pnpm process:query -- query getProtectionInfo ` #### CLI Usage @@ -38,17 +21,6 @@ lint-process --staged --show-state lint-process --staged --ignore-session ``` -#### CLI Options - -| Flag | Description | -| ------------------ | --------------------------------------- | -| `--staged` | Validate staged files only (pre-commit) | -| `--all` | Validate all tracked files (CI) | -| `--strict` | Treat warnings as errors (exit 1) | -| `--ignore-session` | Skip session scope validation | -| `--show-state` | Debug: show derived process state | -| `--format json` | Machine-readable JSON output | - #### Exit Codes | Code | Meaning | diff --git a/_claude-md/workflow/fsm-handoff.md b/_claude-md/workflow/fsm-handoff.md deleted file mode 100644 index 0379ccd4..00000000 --- a/_claude-md/workflow/fsm-handoff.md +++ /dev/null @@ -1,50 +0,0 @@ -### FSM Protection Quick Reference - -| State | Protection | Can Add Deliverables | Needs Unlock | -| ----------- | ------------ | -------------------- | ------------ | -| `roadmap` | None | Yes | No | -| `active` | Scope-locked | No | No | -| `completed` | Hard-locked | No | Yes | -| `deferred` | None | Yes | No | - -**Live query:** `pnpm process:query -- query getProtectionInfo ` and `query getValidTransitionsFrom ` return current FSM rules from code. - -**Valid FSM Transitions:** - -``` -roadmap ──→ active ──→ completed (terminal) - │ │ - │ ↓ - │ roadmap (blocked/regressed) - ↓ -deferred ──→ roadmap -``` - -### FSM Error Messages and Fixes - -| Error | Cause | Fix | -| --------------------------- | --------------------------------------------- | ----------------------------------------- | -| `completed-protection` | File has `completed` status but no unlock tag | Add `@libar-docs-unlock-reason:'reason'` | -| `invalid-status-transition` | Skipped FSM state (e.g., `roadmap→completed`) | Follow path: `roadmap→active→completed` | -| `scope-creep` | Added deliverable to `active` spec | Remove deliverable OR revert to `roadmap` | -| `session-scope` (warning) | Modified file outside session scope | Add to scope OR use `--ignore-session` | -| `session-excluded` | Modified excluded pattern during session | Remove from exclusion OR override | - -### Escape Hatches - -| Situation | Solution | Example | -| ---------------------------- | --------------------- | ---------------------------------------- | -| Fix bug in completed spec | Add unlock reason tag | `@libar-docs-unlock-reason:'Fix-typo'` | -| Modify outside session scope | Use ignore flag | `lint-process --staged --ignore-session` | -| CI treats warnings as errors | Use strict flag | `lint-process --all --strict` | - -### Handoff Documentation - -For multi-session work, generate handoff state from the API: - -```bash -pnpm process:query -- handoff --pattern -# Options: --git (include recent commits), --session -``` - -Generates: deliverable statuses, blockers, modification date, and next steps — always reflects actual annotation state. diff --git a/_claude-md/workflow/session-details.md b/_claude-md/workflow/session-details.md deleted file mode 100644 index e0fd1a3e..00000000 --- a/_claude-md/workflow/session-details.md +++ /dev/null @@ -1,82 +0,0 @@ -### Planning Session - -**Goal:** Create a roadmap spec. Do NOT write implementation code. - -| Do | Do NOT | -| --------------------------------------------------------- | --------------------------- | -| Extract metadata from pattern brief | Create `.ts` implementation | -| Create spec file with proper tags | Transition to `active` | -| Add deliverables table in Background | Ask "Ready to implement?" | -| Convert constraints to `Rule:` blocks | Write full implementations | -| Add scenarios: 1 `@happy-path` + 1 `@validation` per Rule | | - -### Design Session - -**Goal:** Make architectural decisions. Create code stubs with interfaces. Do NOT implement. - -| Use Design Session | Skip Design Session | -| -------------------------- | ------------------- | -| Multiple valid approaches | Single obvious path | -| New patterns/capabilities | Bug fix | -| Cross-context coordination | Clear requirements | - -**Context Gathering (BEFORE explore agents):** - -```bash -pnpm process:query -- context --session design -pnpm process:query -- dep-tree -pnpm process:query -- stubs -pnpm process:query -- overview -``` - -Only use explore agents for comprehension questions (implementation patterns, formatting conventions) that the API doesn't cover. - -**Code Stub Pattern** — stubs go in `delivery-process/stubs/{pattern-name}/`: - -```typescript -// delivery-process/stubs/{pattern-name}/my-function.ts -/** - * @libar-docs - * @libar-docs-status roadmap - * @libar-docs-implements MyPattern - * @libar-docs-uses Workpool, EventStore - * - * ## My Pattern - Description - * - * Target: src/path/to/final/location.ts - * See: PDR-001 (Design Decision) - * Since: DS-1 - */ -export function myFunction(args: MyArgs): Promise { - throw new Error('MyPattern not yet implemented - roadmap pattern'); -} -``` - -Stubs live outside `src/` to avoid TypeScript compilation and ESLint issues. - -### Implementation Session - -**Goal:** Write code. The roadmap spec is the source of truth. - -**Context Gathering (BEFORE writing code):** - -```bash -pnpm process:query -- context --session implement -pnpm process:query -- dep-tree -pnpm process:query -- stubs -``` - -**Execution Order (CRITICAL):** - -1. **Transition to `active` FIRST** — before any code changes -2. **Create executable spec stubs** — if `@libar-docs-executable-specs` present -3. **For each deliverable:** implement, test, update status to `completed` -4. **Transition to `completed`** — only when ALL deliverables done -5. **Regenerate docs:** `pnpm docs:all` - -| Do NOT | Why | -| ------------------------------------- | --------------------------------------- | -| Add new deliverables to `active` spec | Scope-locked state prevents scope creep | -| Mark `completed` with incomplete work | Hard-locked state cannot be undone | -| Skip FSM transitions | Process Guard will reject | -| Edit generated docs directly | Regenerate from source | diff --git a/_claude-md/workflow/session-workflows.md b/_claude-md/workflow/session-workflows.md index b80ba428..f8f8b4c6 100644 --- a/_claude-md/workflow/session-workflows.md +++ b/_claude-md/workflow/session-workflows.md @@ -1,21 +1,97 @@ -**Core Thesis:** Git is the event store. Documentation artifacts are projections. Feature files are the single source of truth. - -For detailed guides, see [SESSION-GUIDES.md](./docs/SESSION-GUIDES.md). - -### Session Decision Tree - -``` -Starting from pattern brief? -├── Yes → Need code stubs now? → Yes → Planning + Design -│ → No → Planning -└── No → Ready to code? → Yes → Complex decisions? → Yes → Design first - → No → Implementation - → No → Planning -``` - -| Session | Input | Output | FSM Change | -| ----------------- | ------------------- | --------------------------- | -------------------------- | -| Planning | Pattern brief | Roadmap spec (`.feature`) | Creates `roadmap` | -| Design | Complex requirement | Decision specs + code stubs | None | -| Implementation | Roadmap spec | Code + tests | `roadmap→active→completed` | -| Planning + Design | Pattern brief | Spec + stubs | Creates `roadmap` | +### SessionGuidesModuleSource + +#### SESSION-GUIDES.md is the authoritative public human reference + +**Invariant:** `docs/SESSION-GUIDES.md` exists and is not deleted, shortened, or replaced with a redirect. Its comprehensive checklists, CLI command examples, and session decision trees serve developers on libar.dev. + +**Rationale:** Session workflow guidance requires two formats for two audiences. Public developers need comprehensive checklists with full examples. AI sessions need compact invariants they can apply without reading 389 lines. + +#### CLAUDE.md session workflow content is derived, not hand-authored + +**Invariant:** After Phase 39 generation deliverables complete, the "Session Workflows" section in CLAUDE.md contains no manually-authored content. It is composed from generated `_claude-md/workflow/` modules. + +**Rationale:** A hand-maintained CLAUDE.md session section creates two copies of session workflow guidance with no synchronization mechanism. Regeneration from annotated source eliminates drift. + +#### Session type determines artifacts and FSM changes + +**Invariant:** Four session types exist, each with defined input, output, and FSM impact. Mixing outputs across session types (e.g., writing code in a planning session) violates session discipline. + +**Rationale:** Session type confusion causes wasted work — a design mistake discovered mid-implementation wastes the entire session. Clear contracts prevent scope bleeding between session types. + +| Session | Input | Output | FSM Change | +| ----------------- | ------------------- | --------------------------- | ------------------------------ | +| Planning | Pattern brief | Roadmap spec (.feature) | Creates roadmap | +| Design | Complex requirement | Decision specs + code stubs | None | +| Implementation | Roadmap spec | Code + tests | roadmap to active to completed | +| Planning + Design | Pattern brief | Spec + stubs | Creates roadmap | + +#### Planning sessions produce roadmap specs only + +**Invariant:** A planning session creates a roadmap spec with metadata, deliverables table, Rule: blocks with invariants, and scenarios. It must not produce implementation code, transition to active, or prompt for implementation readiness. + +**Rationale:** Planning is the cheapest session type — it produces .feature file edits, no compilation needed. Mixing implementation into planning defeats the cost advantage and introduces untested code without a locked scope. + +| Do | Do NOT | +| --------------------------------------------------- | -------------------------- | +| Extract metadata from pattern brief | Create .ts implementation | +| Create spec file with proper tags | Transition to active | +| Add deliverables table in Background | Ask Ready to implement | +| Convert constraints to Rule: blocks | Write full implementations | +| Add scenarios: 1 happy-path + 1 validation per Rule | | + +#### Design sessions produce decisions and stubs only + +**Invariant:** A design session makes architectural decisions and creates code stubs with interfaces. It must not produce implementation code. Context gathering via the Process Data API must precede any explore agent usage. + +**Rationale:** Design sessions resolve ambiguity before implementation begins. Code stubs in delivery-process/stubs/ live outside src/ to avoid TypeScript compilation and ESLint issues, making them zero-risk artifacts. + +| Use Design Session | Skip Design Session | +| -------------------------- | ------------------- | +| Multiple valid approaches | Single obvious path | +| New patterns/capabilities | Bug fix | +| Cross-context coordination | Clear requirements | + +#### Implementation sessions follow FSM-enforced execution order + +**Invariant:** Implementation sessions must follow a strict 5-step execution order. Transition to active must happen before any code changes. Transition to completed must happen only when ALL deliverables are done. Skipping steps causes Process Guard rejection at commit time. + +**Rationale:** The execution order ensures FSM state accurately reflects work state at every point. Writing code before transitioning to active means Process Guard sees changes to a roadmap spec (no scope protection). Marking completed with incomplete work creates a hard-locked state that requires unlock-reason to fix. + +| Do NOT | Why | +| ----------------------------------- | --------------------------------------- | +| Add new deliverables to active spec | Scope-locked state prevents scope creep | +| Mark completed with incomplete work | Hard-locked state cannot be undone | +| Skip FSM transitions | Process Guard will reject | +| Edit generated docs directly | Regenerate from source | + +#### FSM errors have documented fixes + +**Invariant:** Every Process Guard error code has a defined cause and fix. The error codes, causes, and fixes form a closed set — no undocumented error states exist. + +**Rationale:** Undocumented FSM errors cause session-blocking confusion. A lookup table from error code to fix eliminates guesswork and prevents workarounds that bypass process integrity. + +| Error | Cause | Fix | +| ------------------------- | ---------------------------------------------- | ------------------------------------------- | +| completed-protection | File has completed status but no unlock tag | Add libar-docs-unlock-reason tag | +| invalid-status-transition | Skipped FSM state (e.g., roadmap to completed) | Follow path: roadmap to active to completed | +| scope-creep | Added deliverable to active spec | Remove deliverable OR revert to roadmap | +| session-scope (warning) | Modified file outside session scope | Add to scope OR use --ignore-session | +| session-excluded | Modified excluded pattern during session | Remove from exclusion OR override | + +| Situation | Solution | Example | +| ---------------------------- | --------------------- | -------------------------------------- | +| Fix bug in completed spec | Add unlock reason tag | libar-docs-unlock-reason:Fix-typo | +| Modify outside session scope | Use ignore flag | lint-process --staged --ignore-session | +| CI treats warnings as errors | Use strict flag | lint-process --all --strict | + +#### Handoff captures session-end state for continuity + +**Invariant:** Multi-session work requires handoff documentation generated from the Process Data API. Handoff output always reflects actual annotation state, not manual notes. + +**Rationale:** Manual session notes drift from actual deliverable state. The handoff command derives state from annotations, ensuring the next session starts from ground truth rather than stale notes. + +#### ClaudeModuleGeneration is the generation mechanism + +**Invariant:** Phase 39 depends on ClaudeModuleGeneration (Phase 25). Adding `@libar-docs-claude-module` and `@libar-docs-claude-section:workflow` tags to this spec will cause ClaudeModuleGeneration to produce `_claude-md/workflow/` output files. The hand-written `_claude-md/workflow/` files are deleted after successful verified generation. + +**Rationale:** The annotation work (Rule blocks in this spec) is immediately useful — queryable via `pnpm process:query -- rules`. Generation deliverables cannot complete until Phase 25 ships the ClaudeModuleCodec. This sequencing is intentional: the annotation investment has standalone value regardless of whether the codec exists yet. diff --git a/delivery-process.config.ts b/delivery-process.config.ts index 548bf9a2..3eb27b64 100644 --- a/delivery-process.config.ts +++ b/delivery-process.config.ts @@ -11,6 +11,50 @@ */ import { defineConfig } from './src/config/define-config.js'; import { createProductAreaConfigs } from './src/generators/built-in/reference-generators.js'; +import { loadPreambleFromMarkdown } from './src/renderable/load-preamble.js'; +import type { DocumentEntry } from './src/renderable/codecs/index-codec.js'; + +const sessionWorkflowGuidePreamble = loadPreambleFromMarkdown( + 'docs-sources/session-workflow-guide.md' +); + +const annotationGuidePreamble = loadPreambleFromMarkdown( + 'docs-sources/annotation-guide.md' +); + +const indexNavigationPreamble = loadPreambleFromMarkdown( + 'docs-sources/index-navigation.md' +); + +// DD-2: Document entries configured statically, not via filesystem discovery. +// All paths are relative to docs-live/ (where INDEX.md is generated). +const INDEX_DOCUMENT_ENTRIES: readonly DocumentEntry[] = [ + // --- Overview --- + { title: 'Architecture', path: 'ARCHITECTURE.md', description: 'Architecture diagram from source annotations', audience: 'Developers', topic: 'Overview' }, + { title: 'Product Areas', path: 'PRODUCT-AREAS.md', description: 'Product area overviews with live statistics and diagrams', audience: 'Everyone', topic: 'Overview' }, + { title: 'Taxonomy', path: 'TAXONOMY.md', description: 'Tag taxonomy configuration and format types', audience: 'Reference', topic: 'Overview' }, + { title: 'Changelog', path: 'CHANGELOG-GENERATED.md', description: 'Project changelog from release specs', audience: 'Everyone', topic: 'Overview' }, + // --- Governance --- + { title: 'Decisions', path: 'DECISIONS.md', description: 'Architecture Decision Records extracted from specs', audience: 'Developers', topic: 'Governance' }, + { title: 'Business Rules', path: 'BUSINESS-RULES.md', description: 'Domain constraints and invariants from feature files', audience: 'Developers', topic: 'Governance' }, + { title: 'Validation Rules', path: 'VALIDATION-RULES.md', description: 'Process Guard validation rules and FSM reference', audience: 'CI/CD', topic: 'Governance' }, + // --- Reference Guides --- + { title: 'Annotation Reference', path: 'reference/ANNOTATION-REFERENCE.md', description: 'Annotation mechanics, shape extraction, tag reference', audience: 'Developers', topic: 'Reference Guides' }, + { title: 'Session Workflow Guide', path: 'reference/SESSION-WORKFLOW-GUIDE.md', description: 'Planning, Design, Implementation session workflows', audience: 'AI/Devs', topic: 'Reference Guides' }, + { title: 'Process API Reference', path: 'reference/PROCESS-API-REFERENCE.md', description: 'CLI command reference with flags and examples', audience: 'AI/Devs', topic: 'Reference Guides' }, + { title: 'Process API Recipes', path: 'reference/PROCESS-API-RECIPES.md', description: 'CLI workflow recipes and session guides', audience: 'AI/Devs', topic: 'Reference Guides' }, + { title: 'Process Guard Reference', path: 'reference/PROCESS-GUARD-REFERENCE.md', description: 'Pre-commit hooks, error codes, programmatic API', audience: 'Team Leads', topic: 'Reference Guides' }, + { title: 'Architecture Codecs', path: 'reference/ARCHITECTURE-CODECS.md', description: 'All codecs with factory patterns and options', audience: 'Developers', topic: 'Reference Guides' }, + { title: 'Architecture Types', path: 'reference/ARCHITECTURE-TYPES.md', description: 'MasterDataset interface and type shapes', audience: 'Developers', topic: 'Reference Guides' }, + // --- Product Area Details --- + { title: 'Annotation', path: 'product-areas/ANNOTATION.md', description: 'Annotation product area patterns and statistics', audience: 'Developers', topic: 'Product Area Details' }, + { title: 'Configuration', path: 'product-areas/CONFIGURATION.md', description: 'Configuration product area patterns and statistics', audience: 'Users', topic: 'Product Area Details' }, + { title: 'Core Types', path: 'product-areas/CORE-TYPES.md', description: 'Core types product area patterns and statistics', audience: 'Developers', topic: 'Product Area Details' }, + { title: 'Data API', path: 'product-areas/DATA-API.md', description: 'Data API product area patterns and statistics', audience: 'AI/Devs', topic: 'Product Area Details' }, + { title: 'Generation', path: 'product-areas/GENERATION.md', description: 'Generation product area patterns and statistics', audience: 'Developers', topic: 'Product Area Details' }, + { title: 'Process', path: 'product-areas/PROCESS.md', description: 'Process product area patterns and statistics', audience: 'Team Leads', topic: 'Product Area Details' }, + { title: 'Validation', path: 'product-areas/VALIDATION.md', description: 'Validation product area patterns and statistics', audience: 'CI/CD', topic: 'Product Area Details' }, +]; export default defineConfig({ preset: 'libar-generic', @@ -32,6 +76,156 @@ export default defineConfig({ // Product area overview docs (ADR-001 canonical values) // Output redirected to docs-live/ via product-area-docs generatorOverride ...createProductAreaConfigs(), + { + title: 'Process Guard Reference', + conventionTags: ['process-guard-errors'], + shapeSources: [], + behaviorCategories: [], + claudeMdSection: 'validation', + docsFilename: 'PROCESS-GUARD-REFERENCE.md', + claudeMdFilename: 'process-guard.md', + preamble: [ + // --- Pre-commit Setup --- + { + type: 'heading' as const, + level: 2, + text: 'Pre-commit Setup', + }, + { + type: 'paragraph' as const, + text: 'Configure Process Guard as a pre-commit hook using Husky.', + }, + { + type: 'code' as const, + language: 'bash', + content: + '#!/usr/bin/env sh\n. "$(dirname -- "$0")/_/husky.sh"\n\nnpx lint-process --staged', + }, + { + type: 'heading' as const, + level: 3, + text: 'package.json Scripts', + }, + { + type: 'code' as const, + language: 'json', + content: JSON.stringify( + { + scripts: { + 'lint:process': 'lint-process --staged', + 'lint:process:ci': 'lint-process --all --strict', + }, + }, + null, + 2 + ), + }, + // --- Programmatic API --- + { + type: 'heading' as const, + level: 2, + text: 'Programmatic API', + }, + { + type: 'paragraph' as const, + text: 'Use Process Guard programmatically for custom validation workflows.', + }, + { + type: 'code' as const, + language: 'typescript', + content: [ + "import {", + " deriveProcessState,", + " detectStagedChanges,", + " validateChanges,", + " hasErrors,", + " summarizeResult,", + "} from '@libar-dev/delivery-process/lint';", + "", + "// 1. Derive state from annotations", + "const state = (await deriveProcessState({ baseDir: '.' })).value;", + "", + "// 2. Detect changes", + "const changes = detectStagedChanges('.').value;", + "", + "// 3. Validate", + "const { result } = validateChanges({", + " state,", + " changes,", + " options: { strict: false, ignoreSession: false },", + "});", + "", + "// 4. Handle results", + "if (hasErrors(result)) {", + " console.log(summarizeResult(result));", + " process.exit(1);", + "}", + ].join('\n'), + }, + { + type: 'heading' as const, + level: 3, + text: 'API Functions', + }, + { + type: 'table' as const, + columns: ['Category', 'Function', 'Description'], + rows: [ + ['State', 'deriveProcessState(cfg)', 'Build state from file annotations'], + ['Changes', 'detectStagedChanges(dir)', 'Parse staged git diff'], + ['Changes', 'detectBranchChanges(dir)', 'Parse all changes vs main'], + ['Validate', 'validateChanges(input)', 'Run all validation rules'], + ['Results', 'hasErrors(result)', 'Check for blocking errors'], + ['Results', 'summarizeResult(result)', 'Human-readable summary'], + ], + }, + // --- Architecture --- + { + type: 'heading' as const, + level: 2, + text: 'Architecture', + }, + { + type: 'paragraph' as const, + text: 'Process Guard uses the Decider pattern: pure functions with no I/O.', + }, + { + type: 'mermaid' as const, + content: [ + 'graph LR', + ' A[deriveProcessState] --> C[validateChanges]', + ' B[detectChanges] --> C', + ' C --> D[ValidationResult]', + ].join('\n'), + }, + ], + }, + { + title: 'Available Codecs Reference', + conventionTags: ['codec-registry'], + shapeSources: [], + behaviorCategories: [], + claudeMdSection: 'architecture', + docsFilename: 'ARCHITECTURE-CODECS.md', + claudeMdFilename: 'architecture-codecs.md', + }, + { + title: 'Architecture Types Reference', + conventionTags: ['pipeline-architecture'], + shapeSources: [], + shapeSelectors: [{ group: 'master-dataset' }], + behaviorCategories: [], + shapesFirst: true, + claudeMdSection: 'architecture', + docsFilename: 'ARCHITECTURE-TYPES.md', + claudeMdFilename: 'architecture-types.md', + diagramScopes: [ + { + title: 'MasterDataset View Fan-out', + source: 'master-dataset-views', + }, + ], + }, { title: 'Reference Generation Sample', conventionTags: ['taxonomy-rules'], @@ -77,19 +271,46 @@ export default defineConfig({ docsFilename: 'REFERENCE-SAMPLE.md', claudeMdFilename: 'reference-sample.md', }, + { + title: 'Session Workflow Guide', + conventionTags: [], + shapeSources: [], + behaviorCategories: [], + includeTags: ['session-workflows'], + claudeMdSection: 'workflow', + docsFilename: 'SESSION-WORKFLOW-GUIDE.md', + claudeMdFilename: 'session-workflow-guide.md', + preamble: [...sessionWorkflowGuidePreamble], + }, + { + title: 'Annotation Reference Guide', + conventionTags: ['annotation-system'], + shapeSources: [], + behaviorCategories: [], + claudeMdSection: 'annotation', + docsFilename: 'ANNOTATION-REFERENCE.md', + claudeMdFilename: 'annotation-reference.md', + preamble: [...annotationGuidePreamble], + }, ], generatorOverrides: { 'business-rules': { replaceFeatures: ['tests/features/**/*.feature'], + outputDirectory: 'docs-live', }, changelog: { additionalFeatures: ['delivery-process/decisions/*.feature'], + outputDirectory: 'docs-live', + }, + architecture: { + outputDirectory: 'docs-live', }, 'doc-from-decision': { replaceFeatures: ['delivery-process/decisions/*.feature'], }, 'reference-docs': { additionalFeatures: ['delivery-process/decisions/*.feature'], + outputDirectory: 'docs-live', }, 'product-area-docs': { outputDirectory: 'docs-live', @@ -97,8 +318,32 @@ export default defineConfig({ adrs: { outputDirectory: 'docs-live', }, + taxonomy: { + outputDirectory: 'docs-live', + }, + 'validation-rules': { + outputDirectory: 'docs-live', + }, requirements: { outputDirectory: 'docs-live', }, + 'claude-modules': { + outputDirectory: '_claude-md', + }, + 'process-api-reference': { + outputDirectory: 'docs-live', + }, + 'cli-recipe': { + outputDirectory: 'docs-live', + }, + index: { + outputDirectory: 'docs-live', + }, + }, + codecOptions: { + index: { + preamble: [...indexNavigationPreamble], + documentEntries: [...INDEX_DOCUMENT_ENTRIES], + }, }, }); diff --git a/delivery-process/specs/architecture-doc-refactoring.feature b/delivery-process/specs/architecture-doc-refactoring.feature new file mode 100644 index 00000000..be714ed3 --- /dev/null +++ b/delivery-process/specs/architecture-doc-refactoring.feature @@ -0,0 +1,442 @@ +@libar-docs +@libar-docs-pattern:ArchitectureDocRefactoring +@libar-docs-status:completed +@libar-docs-unlock-reason:Implement-test-coverage-and-fix-spec-metadata +@libar-docs-phase:36 +@libar-docs-effort:2d +@libar-docs-product-area:Generation +@libar-docs-depends-on:DocsConsolidationStrategy +@libar-docs-business-value:decomposes-1287-line-manual-architecture-doc-into-curated-overview-with-generated-references +@libar-docs-priority:high +Feature: Architecture Document Refactoring + + **Problem:** + ARCHITECTURE.md is 1,287 lines of manually-maintained documentation covering 14 + sections. The codec system already generates much of this content (codec references + via convention tags, MasterDataset types via shape extraction, pipeline diagrams + via architecture annotations). Maintaining parallel manual and generated versions + creates drift and duplication. + + **Solution:** + Decompose ARCHITECTURE.md into a curated architecture overview (~320 lines of + editorial narrative optimized for Claude as primary consumer) that links to generated + reference documents for detailed content. Phase 2 established the convention-tag + pattern by extracting the 368-line Available Codecs section. Phase 4 applies + product area absorption, generated shapes, architecture diagram references, and + usefulness-driven editorial trimming to the remaining consolidatable content. + + **Why It Matters:** + | Benefit | How | + | Reduced drift | Generated sections always match current code annotations | + | Focused overview | Editorial narrative explains "why" without duplicating "what" | + | Dual output | Each generated section gets docs/ detailed + _claude-md/ compact versions | + | Convention-driven | Adding a new codec only requires adding a convention tag to its JSDoc | + + **Section Disposition (line ranges from original 1,287-line pre-refactoring document):** + | Section | Lines | Action | Target | + | Executive Summary | 28-69 | Keep | Editorial narrative | + | Configuration Architecture | 70-139 | Phase 4: absorb | Configuration product area | + | Four-Stage Pipeline | 140-343 | Keep, trim | Editorial narrative (core concepts) | + | Unified Transformation | 345-478 | Phase 4: generate | Shapes reference doc (MasterDataset types) | + | Codec Architecture | 481-527 | Keep | Editorial narrative (concepts only) | + | Available Codecs | 529-534 | Phase 2: done | Pointer to ARCHITECTURE-CODECS.md | + | Progressive Disclosure | 535-584 | Keep | Editorial narrative | + | Source Systems | 585-692 | Phase 4: absorb | Annotation product area (examples merge to Pipeline) | + | Key Design Patterns | 693-772 | Phase 4: trim | Result pointer to CoreTypes, summaries for others (DD-5) | + | Data Flow Diagrams | 774-957 | Phase 4: generate | Architecture diagrams reference | + | Workflow Integration | 959-1068 | Phase 4: absorb | Process product area | + | Programmatic Usage | 1070-1125 | Phase 4: drop | Claude reads source directly (DD-9) | + | Extending the System | 1127-1194 | Phase 4: drop | Claude infers from codec patterns (DD-9) | + | Quick Reference | 1196-1287 | Phase 2: done | Pointer to ARCHITECTURE-CODECS.md + CLI | + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | Convention-tag codec-registry on 14 codec files | complete | src/renderable/codecs/*.ts | Yes | integration | + | Machine-extractable JSDoc format for codecs | complete | src/renderable/codecs/*.ts | Yes | integration | + | Codec-registry reference config | complete | delivery-process.config.ts | Yes | integration | + | Convention-extractor heading match bugfix | complete | src/renderable/codecs/convention-extractor.ts | Yes | unit | + | Available Codecs section replaced with pointer | complete | docs/ARCHITECTURE.md | No | n/a | + | Configuration Architecture to product area | complete | docs/ARCHITECTURE.md | Yes | integration | + | MasterDataset Schema to shapes reference | complete | docs/ARCHITECTURE.md | Yes | integration | + | Source Systems to Annotation product area | complete | docs/ARCHITECTURE.md | Yes | integration | + | Data Flow Diagrams to architecture diagrams | complete | docs/ARCHITECTURE.md | Yes | integration | + | Workflow Integration to Process product area | complete | docs/ARCHITECTURE.md | Yes | integration | + | Key Design Patterns to CoreTypes product area | complete | docs/ARCHITECTURE.md | Yes | integration | + | Usefulness-driven editorial trim (DD-9) | complete | docs/ARCHITECTURE.md | No | n/a | + + Rule: Convention-tagged JSDoc produces machine-extractable codec documentation + + **Invariant:** Every codec source file annotated with `@libar-docs-convention + codec-registry` must have structured JSDoc following the machine-extractable + format. The convention extractor splits multi-codec files by `## Heading` into + separate convention rules, each rendered as its own section in the generated + reference document. + + **Rationale:** DD-1: Convention tag approach over dedicated codec. Rather than + creating a new "codec inventory" codec that enumerates codecs from source, the + existing convention-tag mechanism is reused. Each codec file's JSDoc is treated + as convention rules tagged with `codec-registry`. This avoids new codec + infrastructure and leverages the proven convention extractor path. The reference + codec already handles 4-layer composition, so convention tags slot into the + existing Layer 1 (conventions) position. + + **Verified by:** Multi-codec file produces separate sections, + Options table renders in both detail levels, + Codec without structured JSDoc produces fallback content + + @acceptance-criteria @happy-path + Scenario: Multi-codec file produces separate convention sections + Given a codec file with three codecs under separate headings + """ + ## SessionContextCodec + **Purpose:** Current session context for AI agents. + **Output Files:** SESSION-CONTEXT.md + + ## RemainingWorkCodec + **Purpose:** Incomplete work across phases. + **Output Files:** REMAINING-WORK.md + + ## CurrentWorkCodec + **Purpose:** Active development work in progress. + **Output Files:** CURRENT-WORK.md + """ + And the file is annotated with @libar-docs-convention codec-registry + When the convention extractor processes the file + Then three separate convention rules are produced + And each rule has its own Purpose and Output Files + + @acceptance-criteria @happy-path + Scenario: Options table renders correctly in both detail levels + Given a codec JSDoc with an options table + """ + | Option | Type | Default | Description | + | generateDetailFiles | boolean | true | Create phase detail files | + | detailLevel | string | standard | Output verbosity level | + """ + When the reference codec generates at detailed level + Then the options table appears with all columns + When the reference codec generates at summary level + Then the options table appears in the compact output + + @acceptance-criteria @edge-case + Scenario: Codec file without structured JSDoc produces fallback + Given a codec file with @libar-docs-convention codec-registry + But the JSDoc lacks structured headings + When the convention extractor processes the file + Then the entire JSDoc description is treated as a single convention rule + + Rule: Machine-extractable JSDoc format follows structured heading convention + + **Invariant:** DD-2: Multi-codec JSDoc splitting uses one `## Heading` per codec + per file. Each heading block contains structured fields in a fixed order: + `**Purpose:**` one-liner, `**Output Files:**` file paths, options table with + Type/Default/Description columns, `**When to Use:**` bullet list, and + `**Factory Pattern:**` code example. Fields are optional -- codecs without options + omit the table, codecs without factory patterns omit the code block. + + **Rationale:** The convention extractor uses `## ` heading regex to split + descriptions into rules. Without this structure, a file like `session.ts` + (3 codecs) would produce a single undifferentiated blob. The heading text becomes + the convention rule title in the generated reference. The fixed field order ensures + consistent rendering across all 20+ codec entries. + + **Verified by:** Heading text becomes convention rule title, + Field order is consistent across all codec files + + @acceptance-criteria @happy-path + Scenario: Heading text becomes the convention rule title + Given a codec JSDoc heading "## ValidationRulesCodec" + When the convention extractor splits the description + Then the convention rule title is "ValidationRulesCodec" + And the content below the heading becomes the rule body + + @acceptance-criteria @validation + Scenario: All codec files follow the structured format + Given the 14 codec files tagged with codec-registry + Then each file has at least one heading starting with "## " + And each heading block contains a "Purpose:" field + And each heading block contains an "Output Files:" field + + Rule: Heading match in convention extractor handles whitespace correctly + + **Invariant:** The convention extractor's heading parser uses `matchEnd` (the + character position after the full regex match) rather than `indexOf('\n', + heading.index)` to calculate where content starts after a heading. This prevents + the `\s*` prefix in the heading regex from consuming leading newlines, which + would cause `heading.index` to point to those newlines instead of the heading text. + + **Rationale:** Discovered during Phase 2 implementation. The heading regex + `/^\s*##\s+(.+)$/gm` matches headings with optional leading whitespace. When a + heading has leading newlines, `heading.index` points to the first newline (part + of the `\s*` match), not the `##` character. Using `indexOf('\n', heading.index)` + then finds the newline BEFORE the heading, producing content that includes the + heading text itself. The fix uses the regex match's end position directly. + + **Verified by:** Heading with leading whitespace splits correctly, + Heading at start of description splits correctly + + @acceptance-criteria @happy-path + Scenario: Convention extraction splits headings with leading whitespace + Given a JSDoc description with a heading preceded by blank lines + When the convention extractor splits the description + Then the heading text is extracted without leading whitespace + And the content starts after the heading line + + @acceptance-criteria @edge-case + Scenario: Heading at start of description splits correctly + Given a JSDoc description starting directly with a heading + When the convention extractor splits the description + Then the heading is extracted as the first rule + And no empty content precedes it + + Rule: Section disposition follows content-type routing + + **Invariant:** DD-3: Each ARCHITECTURE.md section is routed based on content type. + Three routing strategies apply: (1) product area absorption -- sections describing + a specific pipeline stage move to the corresponding product area document where + they get live diagrams and relationship graphs; (2) generated shapes -- sections + documenting TypeScript interfaces move to generated shape reference docs; + (3) generated diagrams -- ASCII/text data flow diagrams are replaced by live + Mermaid diagrams generated from architecture annotations. + + **Rationale:** The routing heuristic is: if a generated equivalent already exists, + replace with pointer; if content is convention-taggable in source files, tag and + generate; if editorial content that cannot be expressed as annotations, retain. + This ensures each section lands in the location with the best maintenance model + for its content type. + + **Verified by:** Product area absorption captures equivalent content, + Shape reference covers MasterDataset documentation, + No content is lost in routing + + @acceptance-criteria @happy-path + Scenario: Product area absorption captures section content + Given the Configuration Architecture section in ARCHITECTURE.md + And the Configuration product area doc with annotated source content + When the section is compared with the product area output + Then the product area doc covers the same config resolution flow + And the ARCHITECTURE.md section can be replaced with a pointer + + @acceptance-criteria @happy-path + Scenario: Shape reference covers MasterDataset documentation + Given the Unified Transformation section with MasterDataset schema + And TypeScript types tagged with @libar-docs-shape in the source + When a shapes reference doc config targets MasterDataset types + Then the generated shapes section contains the same type definitions + And the manual schema documentation can be replaced + + @acceptance-criteria @validation + Scenario: No content is lost in section routing + Given all sections being routed to generated equivalents + When each manual section is compared with its target generated doc + Then every technical fact in the manual section appears in the generated output + And editorial context is preserved in the retained overview sections + + Rule: Product area absorption validates content coverage before pointer replacement + + **Invariant:** DD-4: Product area absorption replaces ARCHITECTURE.md sections with + pointers only when the target product area document already covers the equivalent + content. Three sections route to product areas: Configuration Architecture (L70-139) + to CONFIGURATION.md, Source Systems (L585-692) to ANNOTATION.md, and Workflow + Integration (L959-1068) to PROCESS.md. Annotation format examples from Source + Systems merge into the Four-Stage Pipeline retained section rather than being lost. + Workflow API code examples are dropped -- Claude reads source files directly. + + **Rationale:** Product area documents are generated from annotated source code and + already contain live diagrams, relationship graphs, and API types. Absorbing manual + Architecture sections into these generated docs eliminates drift while preserving + the content in a maintained location. The key test is: does the product area doc + cover the same technical facts? If yes, the manual section becomes a 4-line pointer. + + **Verified by:** Configuration section covered by product area, + Source Systems covered with annotation examples preserved, + Workflow Integration covered without API tutorials, + Annotation format examples appear in Four-Stage Pipeline + + @acceptance-criteria @happy-path + Scenario: Configuration Architecture section absorbed by Configuration product area + Given the Configuration Architecture section in ARCHITECTURE.md (L70-139) + And the generated CONFIGURATION.md product area document + When the product area content is compared with the manual section + Then CONFIGURATION.md covers config resolution flow, presets, and key types + And the manual section is replaced with a 4-line pointer + + @acceptance-criteria @happy-path + Scenario: Source Systems section absorbed by Annotation product area + Given the Source Systems section in ARCHITECTURE.md (L585-692) + And the generated ANNOTATION.md product area document + When the product area content is compared with the manual section + Then ANNOTATION.md covers scanner types, tag dispatch, and extraction pipeline + And annotation format examples (L598-631) merge into Four-Stage Pipeline section + And the manual section is replaced with a 4-line pointer + + @acceptance-criteria @happy-path + Scenario: Workflow Integration section absorbed by Process product area + Given the Workflow Integration section in ARCHITECTURE.md (L959-1068) + And the generated PROCESS.md product area document + When the product area content is compared with the manual section + Then PROCESS.md covers FSM lifecycle, session types, and workflow handoffs + And API code examples are dropped because Claude reads source directly + And the manual section is replaced with a 4-line pointer + + @acceptance-criteria @validation + Scenario: Annotation format examples preserved in Four-Stage Pipeline section + Given the annotation format examples from Source Systems (L598-631) + When the Source Systems section is absorbed + Then the annotation format examples appear in the Four-Stage Pipeline section + And the examples explain how to read and write libar-docs tags + + Rule: MasterDataset shapes generate a dedicated ARCHITECTURE-TYPES reference document + + **Invariant:** DD-6: A new ReferenceDocConfig produces ARCHITECTURE-TYPES.md using + shapeSelectors with group master-dataset to extract MasterDataset schema types, + RuntimeMasterDataset, RawDataset, PipelineOptions, and PipelineResult. Source files + tagged with libar-docs-shape master-dataset and libar-docs-include master-dataset + contribute shapes to the reference doc. The Unified Transformation section (L345-478) + is replaced with a condensed narrative (~15 lines) and pointer to ARCHITECTURE-TYPES.md. + + **Rationale:** The MasterDataset is the central data structure -- the sole read model + per ADR-006. It deserves dedicated reference doc treatment alongside ARCHITECTURE-CODECS.md. + Shape extraction from TypeScript declarations provides exact type signatures that stay + in sync with code, unlike the manual schema table in ARCHITECTURE.md. + + **Verified by:** MasterDataset shapes extracted into reference doc, + Pipeline types included alongside schema types, + Unified Transformation section replaced with pointer + + @acceptance-criteria @happy-path + Scenario: MasterDataset shapes extracted via shape selectors + Given source files tagged with libar-docs-shape master-dataset + And a ReferenceDocConfig with shapeSelectors targeting master-dataset group + When the reference codec generates ARCHITECTURE-TYPES.md + Then MasterDatasetSchema, RuntimeMasterDataset, and RawDataset types appear + And each shape includes its TypeScript declaration and JSDoc description + + @acceptance-criteria @happy-path + Scenario: Pipeline types included in ARCHITECTURE-TYPES reference doc + Given PipelineOptions and PipelineResult tagged with libar-docs-shape master-dataset + And libar-docs-include master-dataset on their source files + When the reference codec generates ARCHITECTURE-TYPES.md + Then PipelineOptions and PipelineResult shapes appear in the API Types section + And both detailed and compact outputs are produced + + @acceptance-criteria @happy-path + Scenario: Unified Transformation section replaced with pointer and narrative + Given the Unified Transformation section in ARCHITECTURE.md (L345-478) + And ARCHITECTURE-TYPES.md generated with MasterDataset shapes + When the section is consolidated + Then the section is replaced with a condensed narrative and pointer + And the narrative explains MasterDataset role as the sole read model + And no type definitions remain in ARCHITECTURE.md + + Rule: Pipeline architecture convention content replaces ASCII data flow diagrams + + **Invariant:** DD-7: The Data Flow Diagrams section (L774-957) contains 4 ASCII + diagrams totaling ~183 lines. These are replaced using a hybrid approach: convention + tag pipeline-architecture (already registered, currently unused) on orchestrator.ts + and build-pipeline.ts produces prose descriptions of pipeline steps and consumer + architecture. A new master-dataset-views hardcoded diagram source generates a + Mermaid fan-out diagram showing dataset view relationships. DD-8: Both convention + content and diagram source are configured on the ARCHITECTURE-TYPES.md ReferenceDocConfig, + keeping all architecture reference content in one generated document. + + **Rationale:** ASCII diagrams cannot be generated from code annotations. The hybrid + approach maximizes generated coverage: convention-tagged JSDoc captures the narrative + (pipeline steps, ADR-006 consumer pattern) while the hardcoded diagram source produces + visual Mermaid output. Using the already-registered pipeline-architecture convention + tag avoids new taxonomy entries. + + **Verified by:** Convention tag produces pipeline flow content, + Diagram source generates Mermaid fan-out, + Data Flow Diagrams section replaced with pointer + + @acceptance-criteria @happy-path + Scenario: Convention tag pipeline-architecture produces pipeline flow content + Given orchestrator.ts annotated with libar-docs-convention pipeline-architecture + And build-pipeline.ts annotated with libar-docs-convention pipeline-architecture + When the reference codec generates ARCHITECTURE-TYPES.md + Then convention content describing pipeline steps appears in the document + And consumer architecture patterns from build-pipeline.ts appear + + @acceptance-criteria @happy-path + Scenario: master-dataset-views diagram source generates Mermaid fan-out diagram + Given master-dataset-views added to DIAGRAM_SOURCE_VALUES in reference.ts + And buildMasterDatasetViewsDiagram builder function implemented + And ARCHITECTURE-TYPES.md config includes master-dataset-views in diagramScopes + When the reference codec generates the document + Then a Mermaid diagram showing MasterDataset view fan-out is rendered + And the diagram appears in both detailed and compact outputs + + @acceptance-criteria @happy-path + Scenario: Data Flow Diagrams section replaced with pointer to generated reference + Given ARCHITECTURE-TYPES.md generated with convention content and diagrams + When the Data Flow Diagrams section (L774-957) is consolidated + Then the 4 ASCII diagrams are removed from ARCHITECTURE.md + And a 5-line pointer to ARCHITECTURE-TYPES.md replaces the section + + Rule: Usefulness-driven editorial trimming targets Claude as primary consumer + + **Invariant:** DD-9: ARCHITECTURE.md serves Claude (primary audience) and human + developers (secondary). Content retained must answer architectural "why" and "how + things connect" questions. Content available via source file reads or generated + reference documents is removed. Post-decomposition target: ~320 lines (~75% reduction + from 1,287 lines). Sections dropped entirely: Programmatic Usage (L1070-1125) and + Extending the System (L1127-1194) -- Claude reads source files directly and infers + extension patterns from existing codec implementations. DD-5: Key Design Patterns + section (L693-772) trimmed from ~80 to ~15 lines: Result Monad becomes a pointer to + CORE-TYPES.md, Schema-First Validation becomes a 3-line summary with source pointer, + Tag Registry becomes a 4-line summary with source pointer. + + **Rationale:** Claude has direct access to source files and generated reference docs. + Duplicating this content in ARCHITECTURE.md wastes context window tokens. The + remaining editorial sections (Executive Summary, Four-Stage Pipeline, Codec Architecture, + Progressive Disclosure) provide the mental model and architectural "why" that cannot + be inferred from code alone. + + **Verified by:** Tutorial sections removed for Claude efficiency, + Four-Stage Pipeline trimmed to conceptual model, + Key Design Patterns trimmed to pointers and summaries, + Post-decomposition file is under target size, + Every pointer resolves to covering generated doc + + @acceptance-criteria @validation + Scenario: Tutorial sections removed because Claude reads source directly + Given the Programmatic Usage section (L1070-1125) + And the Extending the System section (L1127-1194) + When Phase 4 editorial trimming is applied + Then both sections are removed entirely from ARCHITECTURE.md + And no replacement pointers are needed because content is in source files + + @acceptance-criteria @validation + Scenario: Key Design Patterns trimmed to pointers and summaries + Given the Key Design Patterns section (L693-772) with three subsections + When editorial trimming is applied + Then Result Monad subsection is replaced with a pointer to CORE-TYPES.md + And Schema-First Validation is trimmed to a 3-line summary with source pointer + And Tag Registry is trimmed to a 4-line summary with source pointer + And the section shrinks from ~80 to ~15 lines + + @acceptance-criteria @validation + Scenario: Four-Stage Pipeline trimmed to conceptual model with annotation examples + Given the Four-Stage Pipeline section (L140-343) + When editorial trimming is applied + Then the section is trimmed to approximately 120 lines + And the conceptual pipeline model is retained + And annotation format examples merged from Source Systems are included + And detailed function walkthrough code is removed + + @acceptance-criteria @validation + Scenario: Post-decomposition ARCHITECTURE.md is under 400 lines + Given all Phase 4 pointer replacements are complete + And editorial trimming is applied to retained sections + When the final line count is measured + Then ARCHITECTURE.md is approximately 320 lines + And the document contains Executive Summary, Pipeline, Codec Architecture, and Progressive Disclosure + + @acceptance-criteria @validation + Scenario: Every pointer links to a generated doc that covers the replaced content + Given all Phase 4 pointer replacements in ARCHITECTURE.md + When each pointer target is checked + Then every pointer links to an existing generated document + And the generated document contains the technical facts from the replaced section diff --git a/delivery-process/specs/claude-module-generation.feature b/delivery-process/specs/claude-module-generation.feature index acb1d022..71c869e9 100644 --- a/delivery-process/specs/claude-module-generation.feature +++ b/delivery-process/specs/claude-module-generation.feature @@ -1,10 +1,10 @@ @libar-docs @libar-docs-pattern:ClaudeModuleGeneration -@libar-docs-status:roadmap +@libar-docs-status:completed +@libar-docs-unlock-reason:Skip-Feature-description-in-module-output @libar-docs-phase:25 @libar-docs-effort:1.5d @libar-docs-product-area:Generation -@libar-docs-depends-on:ArchitectureDiagramGeneration @libar-docs-business-value:automated-claude-md-modules-from-source @libar-docs-priority:high @libar-docs-executable-specs:tests/features/behavior/claude-modules @@ -41,17 +41,17 @@ Feature: CLAUDE.md Module Generation from Source Annotations Background: Deliverables Given the following deliverables: | Deliverable | Status | Location | Tests | Test Type | - | claude-module tag definition | pending | taxonomy/registry-builder.ts | Yes | unit | - | claude-section tag definition | pending | taxonomy/registry-builder.ts | Yes | unit | - | claude-tags tag definition | pending | taxonomy/registry-builder.ts | Yes | unit | - | DocDirective schema fields | pending | validation-schemas/doc-directive.ts | Yes | unit | - | ExtractedPattern schema fields | pending | validation-schemas/extracted-pattern.ts | Yes | unit | - | Gherkin parser tag extraction | pending | extractor/gherkin-extractor.ts | Yes | unit | - | ClaudeModuleCodec | pending | renderable/codecs/claude-module.ts | Yes | unit | - | Claude module generator | pending | generators/built-in/claude-module-generator.ts | Yes | unit | - | Generator registry integration | pending | generators/built-in/codec-generators.ts | Yes | unit | - | Process Guard annotated example | pending | tests/features/validation/process-guard.feature | No | - | - | Example generated module | pending | _example-output/process-guard.md | No | - | + | claude-module tag definition | complete | taxonomy/registry-builder.ts | Yes | unit | + | claude-section tag definition | complete | taxonomy/registry-builder.ts | Yes | unit | + | claude-tags tag definition | complete | taxonomy/registry-builder.ts | Yes | unit | + | DocDirective schema fields | complete | validation-schemas/doc-directive.ts | Yes | unit | + | ExtractedPattern schema fields | complete | validation-schemas/extracted-pattern.ts | Yes | unit | + | Gherkin parser tag extraction | complete | extractor/gherkin-extractor.ts | Yes | unit | + | ClaudeModuleCodec | complete | renderable/codecs/claude-module.ts | Yes | unit | + | Claude module generator | complete | generators/built-in/codec-generators.ts | Yes | unit | + | Generator registry integration | complete | generators/built-in/codec-generators.ts | Yes | unit | + | Process Guard annotated example | n/a | tests/features/validation/process-guard.feature | No | - | + | Example generated module | n/a | _example-output/process-guard.md | No | - | # ============================================================================ # RULE 1: Claude Module Tags in Registry @@ -83,7 +83,7 @@ Feature: CLAUDE.md Module Generation from Source Annotations When querying for tag "claude-section" Then the tag should exist And the tag format should be "enum" - And the tag should have values including "core", "delivery-process", "testing", "infrastructure" + And the tag should have values including "core", "delivery-process", "testing", "infrastructure", "workflow" @acceptance-criteria @happy-path Scenario: Tag registry contains claude-tags @@ -153,17 +153,20 @@ Feature: CLAUDE.md Module Generation from Source Annotations Rule: Module content is extracted from feature file structure - **Invariant:** The codec must extract content from standard feature file elements: - Feature description (Problem/Solution), Rule blocks, and Scenario Outline Examples. + **Invariant:** The codec extracts content from Rule blocks and Scenario Outline + Examples only. Feature descriptions (Problem/Solution preamble) are skipped because + they contain meta-documentation about why the spec exists, not operational content + for AI sessions. - **Rationale:** Behavior specs already contain well-structured, prescriptive content. - The extraction preserves structure rather than flattening to prose. + **Rationale:** Behavior specs contain well-structured, prescriptive content in Rule + blocks. Feature descriptions waste context in compact AI modules — the invariants + and rationale in Rule blocks are the actionable content. - **Verified by:** Feature description becomes intro, Rule names become section headers, + **Verified by:** Feature description is excluded, Rule names become section headers, Rule descriptions become content, Scenario Outline Examples become tables @acceptance-criteria @happy-path - Scenario: Feature description becomes module introduction + Scenario: Feature description is excluded from module output Given a feature file with description: """gherkin Feature: Process Guard @@ -179,8 +182,8 @@ Feature: CLAUDE.md Module Generation from Source Annotations """ When generating the claude module Then the module should start with "### Process Guard" - And the module should contain the Problem section - And the module should contain the Solution section + And the module should not contain the Problem section + And the module should not contain the Solution section @acceptance-criteria @happy-path Scenario: Rule blocks become module sections diff --git a/delivery-process/specs/cli-recipe-codec.feature b/delivery-process/specs/cli-recipe-codec.feature new file mode 100644 index 00000000..5a62a1e8 --- /dev/null +++ b/delivery-process/specs/cli-recipe-codec.feature @@ -0,0 +1,265 @@ +@libar-docs +@libar-docs-pattern:CliRecipeCodec +@libar-docs-status:completed +@libar-docs-unlock-reason:Initial-commit-with-all-deliverables-complete +@libar-docs-phase:35 +@libar-docs-effort:2w +@libar-docs-product-area:Generation +@libar-docs-depends-on:DocsConsolidationStrategy +@libar-docs-depends-on:ProcessApiHybridGeneration +@libar-docs-business-value:replaces-460-lines-of-manual-PROCESS-API-md-prose-with-generated-recipe-and-narrative-content +@libar-docs-priority:medium +Feature: CLI Recipe Codec + + **Problem:** + `docs/PROCESS-API.md` (~509 lines) retains ~460 lines of editorial prose after + Phase 43 (ProcessApiHybridGeneration) extracted 3 reference tables to + `docs-live/reference/PROCESS-API-REFERENCE.md`. The remaining content includes: + "Why Use This" motivation (30 lines), Quick Start with example output (32 lines), + Session Types decision tree (12 lines), Session Workflow Commands with 6 narrative + command descriptions and output examples (125 lines), Pattern Discovery with 8 + command descriptions (95 lines), Architecture Queries reference (28 lines), + Metadata and Inventory (39 lines), and Common Recipes with 5 recipe blocks + (42 lines). This prose is manually maintained and risks drifting from the CLI + implementation when commands are added, renamed, or removed. + + **Solution:** + Create a standalone `CliRecipeGenerator` that extends CLI_SCHEMA with recipe + definitions and narrative metadata, producing `docs-live/reference/PROCESS-API-RECIPES.md`. + The generator is a sibling to `ProcessApiReferenceGenerator` -- both are standalone + (ADR-006 compliant) and consume CLI_SCHEMA directly. Editorial content that cannot + be derived from schema (motivation prose, session decision tree) uses the preamble + mechanism. `docs/PROCESS-API.md` retains a slim editorial introduction and links + to both generated files (reference tables + recipes). + + **Why It Matters:** + | Benefit | How | + | Zero-drift recipes | Recipe command sequences regenerate from schema when CLI changes | + | Session decision tree stays current | Session types defined in schema, decision tree generated | + | Command narratives from schema | Each command group carries description and example output in schema | + | Hybrid integrity preserved | Editorial "Why Use This" prose lives in preamble, not duplicated | + | Two generated files complement each other | Reference tables (what flags exist) + recipes (how to use them) | + + **Design Questions (for design session):** + | Question | Options | Recommendation | + | How to structure recipe definitions in schema? | (A) Inline in CLIOptionGroup, (B) Separate RecipeGroup[] | (B) Separate -- recipes are multi-command sequences, not per-option | + | Should command narrative descriptions come from schema? | (A) Extend CLIOptionGroup.description, (B) New CommandNarrative type | (A) Extend -- description field already exists and is rendered | + | How to handle example CLI output blocks? | (A) Static strings in schema, (B) Live execution at gen time | (A) Static -- deterministic output, no build-time side effects | + | Where does Quick Start content belong? | (A) Preamble, (B) First recipe group | (A) Preamble -- it is introductory editorial with example output | + | Should the generator produce claude-md output? | (A) Yes via ReferenceDocConfig, (B) No, standalone only | (B) No -- CLAUDE.md already has Data API CLI section from CLAUDE.md authoring | + + **Design Session Findings (2026-03-06):** + | Finding | Impact | Resolution | + | DD-1: Recipes need separate RecipeGroup[] field, not inline per-option | Recipes span multiple option groups (e.g., "Starting a Session" uses overview + scope-validate + context) | Added RecipeGroup[] and CommandNarrativeGroup[] as optional fields on CLISchema -- existing consumers unchanged | + | DD-2: CLI_SCHEMA extension is additive with two new optional fields | ProcessApiReferenceGenerator and showHelp ignore unknown fields | recipes and commandNarratives fields added to CLISchema interface, not a separate extended type | + | DD-3: Preamble mechanism proven by ReferenceDocConfig and ErrorGuideCodec stubs | Why Use This (30 lines), Quick Start (32 lines), Session Types (12 lines) are editorial judgment | Generator accepts preamble SectionBlock[] via CliRecipeGeneratorConfig, configured in delivery-process.config.ts | + | DD-4: CommandNarrative type needed, not just CLIOptionGroup.description extension | Session Workflow has 6 commands each needing description + usage example + expected output | New CommandNarrative interface with command, description, usageExample, details, expectedOutput fields | + | DD-5: Recipes grouped by task intent, not session type or command | Matches existing Common Recipes structure in PROCESS-API.md | 5 groups: Starting a Session, Finding Work, Investigating, Design Prep, Ending a Session | + | Content audit: ~460 lines map to 3 schema locations + preamble | Zero information loss from manual to generated | recipes (42 lines), commandNarratives (287 lines), preamble (74 lines), kept in manual (70 lines) | + | ProcessApiReferenceGenerator is 113 lines and proven stable | Extending it risks regressions on Phase 43 deliverables | CliRecipeGenerator is a separate sibling class, same DocumentGenerator interface | + | Generator registration follows process-api-reference pattern | generatorOverrides already has process-api-reference entry | Add cli-recipe entry with same outputDirectory: docs-live | + + **Design Stubs:** + | Stub | Location | Key Decisions | + | Recipe schema types | delivery-process/stubs/cli-recipe-codec/recipe-schema.ts | DD-1 RecipeGroup/RecipeExample/RecipeStep, DD-4 CommandNarrative/CommandNarrativeGroup, CLISchema extension | + | Generator class | delivery-process/stubs/cli-recipe-codec/cli-recipe-generator.ts | DD-1 separate generator, DD-3 preamble config, DD-5 no claude-md output | + | Recipe data examples | delivery-process/stubs/cli-recipe-codec/recipe-data.ts | DD-2 schema data mapping, DD-4 narrative examples, preamble content examples | + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | Extend CLI_SCHEMA with recipe definitions per command group | complete | src/cli/cli-schema.ts | Yes | unit | + | Create CliRecipeGenerator producing PROCESS-API-RECIPES.md | complete | src/generators/built-in/cli-recipe-generator.ts | Yes | integration | + | Register generator in orchestrator config | complete | delivery-process.config.ts | Yes | integration | + | Preamble content for Why Use This and session decision tree | complete | delivery-process.config.ts | No | n/a | + | Replace PROCESS-API.md prose sections with pointers to generated files | complete | docs/PROCESS-API.md | No | n/a | + | Behavior spec with scenarios for recipe generation | n/a | tests/features/behavior/cli/cli-recipe-generation.feature | Yes | acceptance | + + Rule: CLI recipes are a separate generator from reference tables + + **Invariant:** The `CliRecipeGenerator` is a standalone sibling to + `ProcessApiReferenceGenerator`, not an extension of it. Both implement + `DocumentGenerator`, both consume `CLI_SCHEMA` directly, and both produce + independent `OutputFile[]` via the standard orchestrator write path. The recipe + generator produces `docs-live/reference/PROCESS-API-RECIPES.md` while the + reference generator produces `docs-live/reference/PROCESS-API-REFERENCE.md`. + + **Rationale:** Reference tables and recipe guides serve different audiences and + change at different cadences. Reference tables change when CLI flags are added + or removed. Recipes change when workflow recommendations evolve. Coupling them + in one generator would force both to change together and make the generator + responsible for two distinct content types. ProcessApiReferenceGenerator is + already completed and tested (Phase 43) -- extending it risks regressions. Two + small standalone generators are easier to test and maintain than one large one. + + **Verified by:** Two separate generator classes exist, + Each produces its own output file independently + + @acceptance-criteria @happy-path + Scenario: CliRecipeGenerator produces recipe file independently + Given the CliRecipeGenerator is registered in the orchestrator + And the ProcessApiReferenceGenerator is also registered + When docs:all runs + Then docs-live/reference/PROCESS-API-RECIPES.md is created + And docs-live/reference/PROCESS-API-REFERENCE.md is also created + And neither generator imports nor depends on the other + + @acceptance-criteria @validation + Scenario: Recipe generator has no MasterDataset dependency + Given the CliRecipeGenerator source file + When inspecting its import statements + Then it does not import MasterDataset or any pipeline module + And it imports only from src/cli/cli-schema.ts and generator infrastructure + + Rule: Recipe content uses a structured schema extension + + **Invariant:** `CLI_SCHEMA` is extended with a `recipes` field containing + `RecipeGroup[]`. Each `RecipeGroup` has a title, optional description, and an + array of `RecipeExample` objects. Each `RecipeExample` has a title, a purpose + description, an array of RecipeStep entries (each with a command string and optional comment), and an optional expected output block. + The schema extension is additive -- existing `CLIOptionGroup` types are unchanged. + + **Rationale:** Recipes are multi-command sequences ("run these 3 commands in + order") with explanatory context. They do not fit into `CLIOptionGroup` which + models individual flags. A separate `RecipeGroup[]` keeps the schema type-safe + and makes recipes independently testable. Static expected output strings in the + schema are deterministic -- no build-time CLI execution needed. + + **Verified by:** Schema type includes RecipeGroup definition, + Recipe data drives generated output + + @acceptance-criteria @happy-path + Scenario: CLI schema includes recipe definitions + Given the CLI_SCHEMA constant in src/cli/cli-schema.ts + When recipe groups are added for session startup and pattern investigation + Then each recipe group has a title and at least one recipe example + And each recipe example includes a title, purpose, and command array + And the schema TypeScript compiles without errors + + @acceptance-criteria @happy-path + Scenario: Generated recipe file renders multi-command sequences + Given a RecipeGroup titled "Starting a Session" with 3 recipe commands + And each command has a trailing comment explaining its purpose + When the CliRecipeGenerator renders this group + Then the output contains a section heading "Starting a Session" + And a code block with all 3 commands in sequence + And purpose text appears before the code block + + @acceptance-criteria @validation + Scenario: Recipe with expected output renders output block + Given a RecipeExample with an expectedOutput string + When the CliRecipeGenerator renders this recipe + Then the output contains the command code block + And a separate "Example output" code block follows with the expected output text + + Rule: Narrative prose uses preamble mechanism + + **Invariant:** Editorial content that cannot be derived from the CLI schema -- + specifically "Why Use This" motivational prose, the Quick Start example with + output, and the session type decision tree -- uses a preamble mechanism in the + generator configuration. Preamble content is manually authored in + `delivery-process.config.ts` as structured section data and appears before all + generated recipe content in the output file. + + **Rationale:** The "Why Use This" section explains the value proposition of the + Data API CLI with a comparison table (CLI vs reading markdown). This is editorial + judgment, not derivable from command metadata. The Quick Start shows a specific + 3-command workflow with example terminal output. The session decision tree maps + cognitive states ("Starting to code?") to session types. None of these have a + source annotation -- they are instructional content authored for human + understanding. The preamble mechanism exists precisely for this (proven by + DocsConsolidationStrategy Phase 2 preamble implementation). + + **Verified by:** Preamble sections appear before recipe content, + Preamble content is not duplicated in schema recipe definitions + + @acceptance-criteria @happy-path + Scenario: Generated file starts with preamble editorial content + Given a CliRecipeGenerator with preamble containing Why Use This prose + And the preamble includes a comparison table and Quick Start example + When the generator produces PROCESS-API-RECIPES.md + Then the file begins with the Why Use This section + And the Quick Start section follows with command examples and output + And generated recipe sections appear after the preamble content + + @acceptance-criteria @validation + Scenario: Empty preamble produces no extra content + Given a CliRecipeGenerator with no preamble configured + When the generator produces the recipe file + Then the file begins directly with the first recipe group heading + And no empty sections or separators appear at the top + + Rule: Generated recipe file complements manual PROCESS-API.md + + **Invariant:** After this pattern completes, `docs/PROCESS-API.md` is trimmed to + a slim editorial introduction (~30 lines) containing the document title, a + one-paragraph purpose statement, and links to both generated files: + `docs-live/reference/PROCESS-API-REFERENCE.md` (option tables from Phase 43) and + `docs-live/reference/PROCESS-API-RECIPES.md` (recipes and narratives from this + pattern). The manual file retains the JSON Envelope, Exit Codes, and JSON Piping + sections (~40 lines) which are operational reference unlikely to drift. + All other prose sections are replaced by the generated recipe file. + + **Rationale:** Phase 43 established the hybrid pattern: keep editorial prose in + the manual file, extract derivable content to generated files. This pattern + extends the hybrid by recognizing that recipe content IS derivable from a + structured schema. The ~460 lines of command descriptions, example output, + and recipe blocks can be maintained as schema data rather than freeform markdown. + What remains in the manual file (~70 lines total) is true operational reference + (JSON envelope format, exit codes, piping tips) that changes rarely and has no + schema source. + + **Verified by:** Manual file links to both generated files, + Recipe sections no longer duplicated in manual file + + @acceptance-criteria @happy-path + Scenario: PROCESS-API.md links to both generated files + Given PROCESS-API.md has been trimmed after CliRecipeCodec completion + When reading the manual file + Then it contains a link to docs-live/reference/PROCESS-API-REFERENCE.md + And it contains a link to docs-live/reference/PROCESS-API-RECIPES.md + And the total line count is under 100 lines + + @acceptance-criteria @validation + Scenario: No recipe content duplicated between manual and generated files + Given PROCESS-API.md and PROCESS-API-RECIPES.md both exist + When comparing their content + Then the Common Recipes section does not appear in PROCESS-API.md + And Session Workflow Commands section does not appear in PROCESS-API.md + And Pattern Discovery section does not appear in PROCESS-API.md + And these sections appear in PROCESS-API-RECIPES.md + + Rule: Command narrative descriptions are sourced from schema metadata + + **Invariant:** Each command group in the generated recipe file includes a + narrative description sourced from the CLI schema, not hardcoded in the generator. + The existing `CLIOptionGroup.description` and `CLIOptionGroup.postNote` fields + carry per-group narrative text. For command groups not currently in CLI_SCHEMA + (Session Workflow Commands, Pattern Discovery, Architecture Queries, Metadata + and Inventory), new `CommandGroup` entries are added to the schema with title, + description, and per-command narrative metadata. + + **Rationale:** The manual PROCESS-API.md contains narrative descriptions for each + command ("Highest-impact command. Pre-flight readiness check that prevents wasted + sessions.") that are valuable developer context. Hardcoding these in the generator + would create a second maintenance location. Placing them in CLI_SCHEMA co-locates + command metadata (what the command does) with command definition (what flags it + accepts), following the same single-source-of-truth principle that drove Phase 43. + + **Verified by:** Command narratives render from schema data, + Generator contains no hardcoded command descriptions + + @acceptance-criteria @happy-path + Scenario: Command descriptions render from schema metadata + Given CLI_SCHEMA contains a command group for Session Workflow Commands + And the overview command has a description "Executive summary: progress, active phases, blocking patterns" + When the CliRecipeGenerator renders the Session Workflow Commands section + Then the overview command appears with its schema-sourced description + And no description text is hardcoded in the generator source + + @acceptance-criteria @happy-path + Scenario: All six session workflow commands have narrative descriptions + Given CLI_SCHEMA command groups include all 6 session workflow commands + When the CliRecipeGenerator renders the session workflow section + Then overview, scope-validate, context, dep-tree, files, and handoff each have descriptions + And each description includes a usage example code block diff --git a/delivery-process/specs/docs-consolidation-strategy.feature b/delivery-process/specs/docs-consolidation-strategy.feature new file mode 100644 index 00000000..9bc09bcf --- /dev/null +++ b/delivery-process/specs/docs-consolidation-strategy.feature @@ -0,0 +1,185 @@ +@libar-docs +@libar-docs-pattern:DocsConsolidationStrategy +@libar-docs-status:roadmap +@libar-docs-phase:35 +@libar-docs-effort:4w +@libar-docs-product-area:Generation +@libar-docs-depends-on:CodecDrivenReferenceGeneration +@libar-docs-business-value:right-size-all-14-manual-docs-via-generation-relocation-and-audience-alignment +@libar-docs-priority:high +Feature: Documentation Consolidation Strategy + + **Problem:** + 14 manually-maintained docs (~5,400 lines in `docs/`) duplicate information that + already exists in annotated source code and generated reference documents. Code + changes require updating both source annotations and manual docs, creating + maintenance burden and inevitable drift. + + **Solution:** + A 13-phase consolidation that replaces manual doc sections with generated equivalents + using convention tags, reference doc configs, product area absorption, and the + preamble capability. Each phase validates that a generated equivalent exists or + creates one, then replaces the manual content with a pointer to the generated output. + + **Why It Matters:** + | Benefit | How | + | Single source of truth | Manual docs cannot drift from code when generated from annotations | + | Reduced maintenance | ~2,400 fewer manual lines to maintain across 13 phases | + | Consistent quality | Generated docs always reflect current annotation state | + | AI context accuracy | Compact claude-md versions stay current automatically | + | Incremental delivery | Each phase is independently deliverable as a single PR | + + **Scope:** + | Document | Lines | Disposition | + | ARCHITECTURE.md | 1,287 | Phases 2 + 4: codec listings extracted, remaining sections decomposed to ~320 lines | + | PROCESS-GUARD.md | 341 | Phase 3: enhanced ValidationRulesCodec | + | TAXONOMY.md | 105 | Phase 1: redirect to generated taxonomy output | + | ANNOTATION-GUIDE.md | 268 | Phase 5: trim 30 lines of duplicated tag reference | + | CONFIGURATION.md | 357 | Phase 5: trim 67 lines of duplicated preset detail | + | INDEX.md | 354 | Phase 6: update navigation for hybrid manual+generated structure | + | METHODOLOGY.md | 238 | Keep: philosophy and core thesis | + | SESSION-GUIDES.md | 389 | Phase 39: retained as public reference; CLAUDE.md session section generated from annotated behavior specs | + | GHERKIN-PATTERNS.md | 515 | Phase 41: trim to ~250 lines, Step Linting moves to VALIDATION.md | + | PROCESS-API.md | 507 | Phase 43: keep prose, generate 3 reference tables from CLI schema | + | PUBLISHING.md | 144 | Phase 40: relocate to MAINTAINERS.md at repo root | + | README.md | ~504 | Phase 42: trim to ~150 lines, move pitch content to website | + | docs-generated/ structure | n/a | Phase 37: consolidate to docs-live/ as single output directory | + | Generated doc quality | n/a | Phase 38: fix REFERENCE-SAMPLE duplication, enrich Generation compact, add TOC | + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | Preamble capability on ReferenceDocConfig | complete | src/renderable/codecs/reference.ts | Yes | unit | + | Phase 1 - Taxonomy consolidation | pending | docs/TAXONOMY.md | No | n/a | + | Phase 2 - Codec listings extraction | complete | delivery-process.config.ts, src/renderable/codecs/*.ts | Yes | integration | + | Phase 3 - Process Guard consolidation | complete | src/renderable/codecs/validation-rules.ts | Yes | integration | + | Phase 4 - Architecture decomposition | complete | docs/ARCHITECTURE.md | Yes | integration | + | Phase 5 - Guide trimming | pending | docs/ANNOTATION-GUIDE.md, docs/CONFIGURATION.md | No | n/a | + | Phase 6 - Index navigation update | pending | docs-live/INDEX.md, docs/INDEX.md | No | n/a | + | Phase 37 - docs-live/ directory consolidation | complete | delivery-process.config.ts | Yes | integration | + | Phase 38 - Generated doc quality improvements | pending | src/renderable/codecs/reference.ts | Yes | integration | + | Phase 39 - Session workflow CLAUDE.md module generation | complete | delivery-process/specs/, _claude-md/workflow/ | No | n/a | + | Phase 40 - PUBLISHING.md relocation to MAINTAINERS.md | complete | docs/PUBLISHING.md | No | n/a | + | Phase 41 - GHERKIN-PATTERNS.md restructure | complete | docs/GHERKIN-PATTERNS.md, docs/VALIDATION.md | No | n/a | + | Phase 42 - README.md rationalization | complete | README.md | No | n/a | + | Phase 43 - PROCESS-API.md hybrid generation | complete | docs/PROCESS-API.md, src/cli/ | Yes | integration | + | Promote architecture generator from preview to docs:all | complete | package.json, delivery-process.config.ts | No | n/a | + | Promote changelog generator from preview to docs:all | complete | package.json, delivery-process.config.ts | No | n/a | + + Rule: Convention tags are the primary consolidation mechanism + + **Invariant:** Each consolidation phase follows the same pattern: register a + convention tag value in `src/taxonomy/conventions.ts`, annotate source files with + `@libar-docs-convention` tags using structured JSDoc, add a `ReferenceDocConfig` + entry in `delivery-process.config.ts`, and replace the manual doc section with a + pointer to the generated reference document. + + **Rationale:** Convention-tagged annotations are the only sustainable way to keep + docs in sync with implementation. The reference codec (`createReferenceCodec`) + already handles the 4-layer composition so each phase only needs annotation work + and config — no new codec infrastructure required. + + **Verified by:** Convention tag produces generated reference, + Phase 2 demonstrates the pattern end-to-end + + @acceptance-criteria @happy-path + Scenario: Convention tag produces a generated reference document + Given source files annotated with a convention tag value + And a ReferenceDocConfig entry matching that convention tag + When the reference codec generates output + Then a detailed docs-live/ file and a compact _claude-md/ file are produced + And both contain the convention content extracted from source JSDoc + + Rule: Preamble preserves editorial context in generated docs + + **Invariant:** `ReferenceDocConfig.preamble` accepts `readonly SectionBlock[]` + that are prepended before all generated content. Preamble sections appear in both + detailed and summary (claude-md) outputs, followed by a separator. A config + without preamble produces no extra separator or empty sections. + + **Rationale:** Not all documentation content can be extracted from code annotations. + Introductory prose, cross-cutting context, and reading guides require human + authorship. The preamble provides a designated place for this content within the + generated document structure, avoiding a separate hand-maintained file. + + **Verified by:** Preamble appears in both detail levels, + Empty preamble produces no artifacts + + @acceptance-criteria @happy-path + Scenario: Preamble sections appear before generated content + Given a ReferenceDocConfig with preamble containing heading and paragraph blocks + When the reference codec generates at both detail levels + Then preamble sections appear first in both outputs + And a separator follows the preamble before generated content + + Rule: Each consolidation phase is independently deliverable + + **Invariant:** Each phase can be implemented and validated independently. A phase + is complete when: the manual doc section has been replaced with a pointer to the + generated equivalent, `pnpm docs:all` produces the generated output without errors, + and the generated content covers the replaced manual content. No phase requires + another uncompleted phase to function. + + **Rationale:** Independent phases allow incremental consolidation without blocking + on the full initiative. Each merged PR reduces manual maintenance immediately. + Phase ordering in the plan is a suggested sequence (simplest first), not a + dependency chain. + + **Verified by:** Phases have no inter-dependencies, + Each phase validates independently + + @acceptance-criteria @happy-path + Scenario: Completed phase validates independently + Given Phase 2 (codec listings) is complete + And Phase 1 (taxonomy) is not started + When running documentation generation + Then Phase 2 generated output is correct + And no errors relate to incomplete phases + + Rule: Manual docs retain editorial and tutorial content + + **Invariant:** Documents containing philosophy (METHODOLOGY.md) remain fully manual + with no generated equivalent (~238 lines). Documents that were originally manual but + now have generated equivalents or have been restructured (SESSION-GUIDES.md, + GHERKIN-PATTERNS.md, PROCESS-API.md) retain their editorial content as preamble + within generated outputs. PUBLISHING.md was relocated to MAINTAINERS.md at the + repository root. + + **Rationale:** The consolidation targets sections most likely to drift when code + changes: reference tables, codec listings, validation rules, API types. Editorial + content changes at a different cadence and requires human judgment to update. + Forcing this into annotations would produce worse documentation. Documents that + transitioned to hybrid generation preserve their editorial voice via preamble + while keeping reference content in sync with source annotations. + + **Verified by:** METHODOLOGY.md has no generated equivalent, + Consolidated docs preserve information completeness + + @acceptance-criteria @happy-path + Scenario: Fully manual documents have no generated equivalent + Given METHODOLOGY.md as the retained fully-manual document + Then no ReferenceDocConfig exists targeting its content + And its sections do not duplicate any generated output + + Rule: Audience alignment determines document location + + **Invariant:** Each document lives in the location matching its primary audience: + `docs/` (deployed to libar.dev) for content that serves package users and developers; + repo root for GitHub-visible metadata (CONTRIBUTING.md, SECURITY.md, MAINTAINERS.md); + CLAUDE.md for AI session context. A document appearing in docs/ must be useful to + a developer or user visiting the website — maintainer-only operational procedures + (npm publishing workflow, GitHub Actions setup) belong at the repo root. + + **Rationale:** The audit found PUBLISHING.md (maintainer-only) in docs/ alongside + user-facing guides. SESSION-GUIDES.md (AI session procedures) duplicates CLAUDE.md + with 95% overlap. Audience mismatches increase website noise for users and + create drift risk when the same content lives in two locations. + + **Verified by:** No maintainer-only content in docs/, + No AI-session content duplicated between docs/ and CLAUDE.md + + @acceptance-criteria @happy-path + Scenario: Maintainer content does not appear in website docs + Given the docs/ directory after Phase 40 (PublishingRelocation) + Then no file in docs/ contains npm publishing or GitHub Actions workflow instructions + And those instructions exist in MAINTAINERS.md at the repo root diff --git a/delivery-process/specs/docs-live-consolidation.feature b/delivery-process/specs/docs-live-consolidation.feature new file mode 100644 index 00000000..27f8aed1 --- /dev/null +++ b/delivery-process/specs/docs-live-consolidation.feature @@ -0,0 +1,95 @@ +@libar-docs +@libar-docs-pattern:DocsLiveConsolidation +@libar-docs-status:completed +@libar-docs-phase:37 +@libar-docs-effort:0.5d +@libar-docs-product-area:Generation +@libar-docs-depends-on:DocsConsolidationStrategy +@libar-docs-business-value:single-output-directory-for-all-website-published-and-claude-readable-content +@libar-docs-priority:high +@libar-docs-unlock-reason:Move-business-rules-taxonomy-to-docs-live +Feature: Docs Live Directory Consolidation + + **Problem:** + `docs-generated/` mixes production reference documents (ARCHITECTURE-CODECS.md, + ARCHITECTURE-TYPES.md at 19 KB and 14 KB) with intermediate build artifacts + (business-rules/, taxonomy/). The `_claude-md/architecture/` compact context + files live in `docs-generated/` while the equivalent product-area compacts live + in `docs-live/`. Website visitors and Claude agents have no single location for + all generated reference content — they must know which directory holds which type. + + **Solution:** + Establish `docs-live/` as the single output directory for all website-published + and Claude-readable content. Move reference docs to `docs-live/reference/` and + architecture compact files to `docs-live/_claude-md/architecture/` by updating + output directory configs in `delivery-process.config.ts`. + After consolidation, `docs-generated/` contains no production artifacts — all generated reference content lives in `docs-live/`. + + **Why It Matters:** + | Benefit | How | + | Clear contract | One directory (docs-live/) for all generated reference content | + | No missed content | Claude sessions directed to docs-live/ find all compacts | + | Simpler gitignore | docs-generated/ can be fully ignored; docs-live/ is committed | + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | Reference docs output → docs-live/reference/ | complete | delivery-process.config.ts | Yes | integration | + | Architecture _claude-md/ → docs-live/_claude-md/architecture/ | complete | delivery-process.config.ts | Yes | integration | + | Remove root-level compact duplicates from docs-generated/ | complete | delivery-process.config.ts | No | n/a | + | Update .gitignore: docs-generated/ ignored, docs-live/ committed | complete | .gitignore | No | n/a | + + Rule: docs-live/ is the single directory for website-published content + + **Invariant:** Every file appearing on `libar.dev` or referenced by CLAUDE.md + comes from `docs-live/`. No production reference document is published from + `docs-generated/`. The `docs-generated/` directory contains no production reference + content after `docs:all` runs. Business-rules, taxonomy, and + validation-rules output to `docs-live/` alongside other reference docs. + + **Rationale:** DD-1: Splitting production output across two directories creates + ambiguity about where authoritative content lives. Website configuration, CLAUDE.md + path references, and team navigation all benefit from a single source directory. + `docs-generated/` name signals "build cache", not "publishable output". + + **Verified by:** All reference docs accessible from docs-live/, + docs-generated/ contains no website-published files + + @acceptance-criteria @happy-path + Scenario: Reference docs are generated into docs-live/reference/ + Given ARCHITECTURE-CODECS.md and ARCHITECTURE-TYPES.md configured with docs-live/reference/ output + When pnpm docs:all runs successfully + Then docs-live/reference/ARCHITECTURE-CODECS.md exists + And docs-live/reference/ARCHITECTURE-TYPES.md exists + And docs-generated/ contains no reference document .md files + + Rule: Architecture reference compacts generate under docs-live/_claude-md/ + + **Invariant:** Architecture reference summary files live under + `docs-live/_claude-md/architecture/`. Architecture-scoped compacts (architecture-codecs, + architecture-types) move from `docs-generated/_claude-md/architecture/` to + `docs-live/_claude-md/architecture/`. This consolidation does not affect the + separate claude-modules output at the repository root `_claude-md/`. + + **Rationale:** DD-2: `_claude-md/` compact versions are the Claude consumption + contract — agents read compacts, not full product area docs. Having compacts + split across two directories (docs-generated/ and docs-live/) means Claude + sessions following "read from docs-live/" miss the architecture compacts entirely. + + **Verified by:** All compact files under docs-live/_claude-md/, + No _claude-md/ files remain under docs-generated/ + + @acceptance-criteria @happy-path + Scenario: Architecture compact files output to docs-live/_claude-md/architecture/ + Given reference doc configs with claudeMdSection: architecture + When pnpm docs:all runs + Then docs-live/_claude-md/architecture/architecture-codecs.md exists + And docs-live/_claude-md/architecture/architecture-types.md exists + And docs-generated/_claude-md/ directory does not exist + + @acceptance-criteria @validation + Scenario: docs-generated/ contains no Markdown artifacts after standard generation + Given consolidation config changes applied + When pnpm docs:all runs + Then docs-generated/ contains no .md files + And all business-rules, taxonomy, and validation-rules output is in docs-live/ diff --git a/delivery-process/specs/enhanced-index-generation.feature b/delivery-process/specs/enhanced-index-generation.feature new file mode 100644 index 00000000..dc344691 --- /dev/null +++ b/delivery-process/specs/enhanced-index-generation.feature @@ -0,0 +1,235 @@ +@libar-docs +@libar-docs-pattern:EnhancedIndexGeneration +@libar-docs-status:completed +@libar-docs-unlock-reason:WP-2-implementation-complete +@libar-docs-phase:35 +@libar-docs-effort:2w +@libar-docs-product-area:Generation +@libar-docs-depends-on:DocsConsolidationStrategy +@libar-docs-business-value:replaces-354-line-manual-INDEX-md-with-auto-generated-navigation-hub-combining-statistics-and-editorial-reading-paths +@libar-docs-priority:medium +Feature: Enhanced Index Generation + + **Problem:** + `docs/INDEX.md` (354 lines) is a manually maintained navigation hub with audience-based + reading orders, per-document detailed TOC, document roles matrix, quick navigation + table, and key concepts glossary. The auto-generated `docs-live/INDEX.md` (112 lines) + is a simple file listing with regeneration commands. It lacks audience navigation, + document role context, pattern statistics, and phase progress summaries. When documents + are added, renamed, or restructured, the manual index drifts from the actual doc set. + + **Solution:** + Create an `IndexCodec` that generates a comprehensive navigation hub by composing + auto-generated statistics from MasterDataset pre-computed views with editorial + navigation content via the preamble mechanism. The codec produces document listings, + pattern counts per product area, and phase progress from `byCategory`, `byPhase`, + `byProductArea`, and `byStatus` views. Audience reading paths, the document roles + matrix, and the quick finder table use `ReferenceDocConfig.preamble` as manually + authored `SectionBlock[]`. The generated output replaces both `docs/INDEX.md` and + `docs-live/INDEX.md` with a single unified navigation document. + + **Why It Matters:** + | Benefit | How | + | Single navigation hub | Unifies manual docs/ and generated docs-live/ listings in one document | + | Zero-drift statistics | Pattern counts, phase progress, product area coverage regenerated from MasterDataset | + | Audience paths preserved | Editorial reading orders carried via preamble, not duplicated manually | + | Document roles matrix | Audience-to-document mapping maintained in config, rendered in output | + | Closes Phase 6 | Completes DocsConsolidationStrategy Phase 6 (Index navigation update, pending) | + + **Scope:** + | Content Type | Auto-generatable? | Source | + | Product area and generated doc listing | Yes | Static documentEntries config plus MasterDataset views | + | Pattern statistics per area | Yes | dataset.byProductArea view | + | Phase progress summary | Yes | dataset.byStatus plus dataset.byPhase | + | Audience reading paths (New User, Developer, Team Lead) | No | Preamble SectionBlock[] | + | Document roles matrix (Audience x Document x Focus) | No | Preamble SectionBlock[] | + | Quick finder table (If you want X, read Y) | No | Preamble SectionBlock[] | + | Key concepts glossary | Partially | Could derive from pattern metadata or use preamble | + | Per-document section inventory with line ranges | Partially | Would need markdown AST parsing | + + **Design Questions (for design session):** + | Question | Options | Recommendation | + | Create new IndexCodec or extend existing index generator? | (A) New IndexCodec, (B) Extend docs-live/INDEX.md generator | (A) New codec -- current generator is a simple file lister with no MasterDataset access | + | How to merge manual and generated doc listings? | (A) Unified table, (B) Separate sections | (A) Unified -- users should not need to know which docs are manual vs generated | + | Should audience paths be preamble or a new annotation type? | (A) Preamble, (B) New annotation | (A) Preamble -- reading orders are editorial judgment, not code-derivable | + | Can key concepts be derived from pattern metadata? | (A) Yes from descriptions, (B) No, use preamble | (B) Preamble -- pattern descriptions are too granular for a glossary | + | How to handle hybrid docs/ and docs-live/ structure? | (A) Single merged listing, (B) Two sections with cross-links | (A) Merged -- audience sees one doc set, not two directories | + + **Design Session Findings (2026-03-06):** + | Finding | Impact | Resolution | + | DD-1: New IndexCodec registered in CodecRegistry as document type index | Enables MasterDataset access via standard codec.decode(dataset) pipeline and free integration with generateDocument, generateAllDocuments, CodecOptions | Create createIndexCodec() factory following OverviewCodec pattern, register in CodecRegistry and DOCUMENT_TYPES | + | DD-2: Document entries configured statically, not via filesystem discovery | Codec remains pure (no I/O), deterministic, testable. Config updated alongside document changes | IndexCodecOptions.documentEntries: readonly DocumentEntry[] with title, path, description, audience, topic | + | DD-3: Audience reading paths are full preamble SectionBlock arrays | Reading order is editorial judgment -- no annotation can express pedagogical sequencing. Most-cited navigation aid preserved | IndexCodecOptions.preamble contains READING_ORDER_SECTIONS with 3 audience profiles | + | DD-4: Key concepts glossary uses preamble, not annotation extraction | Pattern descriptions too granular for reader-friendly glossary. Future libar-docs-glossary annotation could replace this | KEY_CONCEPTS_SECTIONS in preamble with 6 core concept definitions | + | DD-5: Standalone IndexCodec, NOT a ReferenceDocConfig entry | ReferenceDocConfig 4-layer composition (conventions, diagrams, shapes, behaviors) does not apply to navigation documents. Index has no convention tags, scoped diagrams, shapes, or behavior categories | IndexCodec registered directly in CodecRegistry. Reuses preamble pattern from ReferenceDocConfig without type coupling | + | docs-live/INDEX.md is a static file, not code-generated | No existing generator to extend or replace. The current file was manually authored | New codec produces INDEX.md as its output, replacing the static file entirely | + | Section ordering: preamble first, statistics second | Reading paths and quick finder are highest-value navigation. Statistics are supplementary context | Matches existing manual INDEX.md structure. Preamble appears before auto-generated sections | + | computeStatusCounts and completionPercentage utilities already exist | No new utility code needed for statistics sections | Import from src/renderable/utils.ts, same as buildProductAreaIndex in reference-generators.ts | + + **Design Stubs:** + | Stub | Location | Purpose | + | index-codec-options.ts | delivery-process/stubs/enhanced-index-generation/index-codec-options.ts | IndexCodecOptions interface, DocumentEntry type, section visibility toggles, DD-1 and DD-5 rationale | + | index-codec.ts | delivery-process/stubs/enhanced-index-generation/index-codec.ts | createIndexCodec() factory, buildIndexDocument pipeline, section builder signatures, DD-1 rationale | + | index-preamble-config.ts | delivery-process/stubs/enhanced-index-generation/index-preamble-config.ts | Example preamble SectionBlock arrays, document entries, DD-2 DD-3 DD-4 rationale | + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | Create IndexCodec with MasterDataset-driven statistics | complete | src/renderable/codecs/index-codec.ts | Yes | unit | + | Register IndexCodec in codec registry and generator config | complete | src/renderable/generate.ts | Yes | integration | + | Preamble content for audience paths, document roles, quick finder | complete | docs-sources/index-navigation.md | No | n/a | + | CodecOptions entry for enhanced INDEX.md | complete | delivery-process.config.ts | Yes | integration | + | Replace docs/INDEX.md with pointer to generated output | complete | docs/INDEX.md | No | n/a | + | Behavior spec with scenarios for index generation | superseded | n/a | No | n/a | + + Rule: IndexCodec composes generated statistics with editorial navigation + + **Invariant:** The IndexCodec generates document listings and pattern statistics + from MasterDataset pre-computed views (`byCategory`, `byPhase`, `byProductArea`, + `byStatus`), while audience reading paths, the document roles matrix, and the + quick finder table use the `ReferenceDocConfig.preamble` mechanism as manually + authored `SectionBlock[]`. The codec does not hardcode document metadata -- all + statistics are derived from the dataset at generation time. Editorial content + changes at authorial cadence via config edits, not code changes. + + **Rationale:** Approximately 40% of INDEX.md content (product area lists, file + inventories, pattern statistics, phase progress) is directly derivable from + MasterDataset views and drifts when patterns change status or new patterns are + added. The remaining 60% (audience paths, document roles, quick finder) requires + human editorial judgment about which documents serve which readers. The preamble + mechanism cleanly separates these two content types within a single generated + output, as proven by CodecDrivenReferenceGeneration and DocsConsolidationStrategy + Phase 2. + + **Verified by:** Codec produces statistics from MasterDataset, + Preamble editorial content appears before generated sections + + @acceptance-criteria @happy-path + Scenario: IndexCodec generates pattern statistics from MasterDataset + Given a MasterDataset with patterns across 7 product areas + And patterns have statuses including roadmap, active, and completed + When the IndexCodec generates the index document + Then a product area statistics table shows pattern counts per area + And a phase progress summary shows counts by status + And all statistics match the MasterDataset view contents + + @acceptance-criteria @validation + Scenario: Statistics update when patterns change status + Given a MasterDataset where 3 patterns moved from roadmap to completed + When the IndexCodec regenerates the index document + Then the phase progress summary reflects the updated status counts + And product area statistics reflect the new completed count + + Rule: Audience reading paths are first-class sections + + **Invariant:** Three audience profiles exist in the generated index: New User, + Developer/AI, and Team Lead/CI. Each profile has a curated reading order that + lists documents in recommended sequence with a one-line description of what each + document provides for that audience. Reading paths appear prominently after the + quick navigation table and before the auto-generated statistics sections. The + reading paths are sourced from preamble, not derived from pattern metadata. + + **Rationale:** The manual INDEX.md reading orders are consistently cited as the + most useful navigation aid by developers onboarding to the project. A flat + alphabetical file listing (as in the current docs-live/INDEX.md) forces readers + to guess which documents are relevant to their role. Audience-specific paths + reduce time-to-relevance from minutes of scanning to seconds of following a + curated sequence. This content is inherently editorial -- no annotation can + express "read this third because it builds on concepts from document two." + + **Verified by:** Three audience reading paths appear in output, + Reading paths precede auto-generated statistics + + @acceptance-criteria @happy-path + Scenario: Generated index contains three audience reading paths + Given an IndexCodec with preamble containing three audience profiles + And the profiles are New User and Developer/AI and Team Lead/CI + When the IndexCodec generates the index document + Then three reading order sections appear with curated document sequences + And each reading order lists documents with one-line descriptions + And reading paths appear before auto-generated statistics sections + + @acceptance-criteria @validation + Scenario: Reading paths are not derived from pattern metadata + Given an IndexCodec with audience paths defined in preamble + When inspecting the codec source code + Then no audience path content is computed from MasterDataset + And all reading order content originates from the preamble SectionBlock array + + Rule: Index unifies manual and generated doc listings + + **Invariant:** The generated index covers both `docs/` (manual reference documents) + and `docs-live/` (generated reference documents) in a single unified navigation + structure. Documents are organized by topic or audience, not by source directory. + The reader does not need to know whether a document is manually authored or + auto-generated. Each document entry includes its title, a brief description, and + its primary audience. The directory source (docs/ or docs-live/) appears only in + the link path, not as a section heading or organizational axis. + + **Rationale:** The current documentation set splits across two directories for + implementation reasons (manual vs generated), but this split is meaningless to + readers. A developer looking for architecture documentation should find one entry, + not separate entries under "Manual Docs" and "Generated Docs" sections. The unified + listing follows the same principle as a library catalog -- books are organized by + subject, not by whether they were hand-typeset or digitally printed. + + **Verified by:** No section heading references docs/ or docs-live/ as category, + Documents from both directories appear in unified tables + + @acceptance-criteria @happy-path + Scenario: Documents from both directories appear in unified navigation + Given manual documents exist in docs/ including ARCHITECTURE.md and METHODOLOGY.md + And generated documents exist in docs-live/ including PRODUCT-AREAS.md and DECISIONS.md + When the IndexCodec generates the index document + Then all documents appear in topic-organized sections + And no section heading uses docs/ or docs-live/ as an organizational label + And each document entry includes title, description, and audience + + @acceptance-criteria @validation + Scenario: Quick navigation table includes both manual and generated documents + Given the preamble contains a quick finder table + When the IndexCodec generates the index document + Then the quick finder table maps goals to documents regardless of source directory + And links resolve correctly to both docs/ and docs-live/ paths + + Rule: Document metadata drives auto-generated sections + + **Invariant:** Pattern counts per product area, phase progress summaries, and + product area coverage percentages are derived from MasterDataset pre-computed views + at generation time. The IndexCodec accesses `dataset.byProductArea` for area + statistics, `dataset.byStatus` for status distribution, and `dataset.byPhase` for + phase ordering. No statistics are hardcoded in the codec or config. When a pattern + changes status or a new pattern is added, regenerating the index reflects the + change without any manual update. + + **Rationale:** The manual INDEX.md has no statistics section because maintaining + accurate counts manually is unsustainable across 196+ patterns. The MasterDataset + pre-computed views provide O(1) access to grouped pattern data. Surfacing these + statistics in the index gives readers an at-a-glance project health overview + (how many patterns per area, what percentage are completed, which phases are + active) that was previously only available via the Process Data API CLI. + + **Verified by:** Statistics section renders from MasterDataset views, + No hardcoded counts exist in codec or config + + @acceptance-criteria @happy-path + Scenario: Product area statistics render from MasterDataset + Given a MasterDataset with byProductArea containing 7 product areas + And each area has between 5 and 40 patterns + When the IndexCodec generates the auto-generated statistics section + Then a table shows each product area with its pattern count + And the total across all areas matches the dataset pattern count + + @acceptance-criteria @happy-path + Scenario: Phase progress summary shows status distribution + Given a MasterDataset with byStatus containing roadmap, active, and completed patterns + When the IndexCodec generates the phase progress section + Then a summary shows the count of patterns in each status + And a completion percentage is calculated from completed vs total + + @acceptance-criteria @validation + Scenario: Empty product area still appears in statistics + Given a MasterDataset where the CoreTypes product area has zero patterns + When the IndexCodec generates the statistics section + Then CoreTypes appears in the table with a count of zero + And no error occurs due to the empty area diff --git a/delivery-process/specs/error-guide-codec.feature b/delivery-process/specs/error-guide-codec.feature new file mode 100644 index 00000000..52c5898c --- /dev/null +++ b/delivery-process/specs/error-guide-codec.feature @@ -0,0 +1,224 @@ +@libar-docs +@libar-docs-pattern:ErrorGuideCodec +@libar-docs-status:completed +@libar-docs-unlock-reason:Initial-commit-with-all-deliverables-complete +@libar-docs-phase:35 +@libar-docs-effort:2w +@libar-docs-product-area:Generation +@libar-docs-depends-on:DocsConsolidationStrategy +@libar-docs-business-value:replaces-341-line-manual-PROCESS-GUARD-md-with-auto-generated-error-diagnosis-guides +@libar-docs-priority:medium +Feature: Error Guide Codec + + **Problem:** + `docs/PROCESS-GUARD.md` (341 lines) is manually maintained with per-error-code + diagnosis guides, escape hatch documentation, pre-commit setup instructions, and + programmatic API examples. When validation rules change in `src/lint/`, the manual + doc drifts. The existing `ValidationRulesCodec` generates `docs-live/validation/` + files (error-catalog.md, fsm-transitions.md, protection-levels.md) covering ~35% + of PROCESS-GUARD.md content, but these lack fix rationale ("why this rule exists"), + alternative approaches, integration recipes (Husky, CI), and the programmatic API. + + **Solution:** + Enhance the `ValidationRulesCodec` to generate error diagnosis guide content by: + (1) registering a `process-guard-errors` convention tag in `conventions.ts`, + (2) annotating error-handling source files in `src/lint/` with structured JSDoc + convention annotations, (3) adding new `ValidationRulesCodecOptions` toggles for + error guide sections, (4) adding a `ReferenceDocConfig` entry that composes + convention-tagged content with the existing error catalog, and (5) using preamble + for Husky/CI setup content that cannot come from source annotations. + + **Why It Matters:** + | Benefit | How | + | Zero-drift error docs | Error codes, causes, fixes, and rationale generated from annotated source | + | Fix rationale included | Each error code explains why the rule exists, not just how to fix it | + | Integration recipes | Husky pre-commit and CI pipeline setup carried via preamble | + | Progressive disclosure | Overview links to per-error detail pages with examples and alternatives | + | Replaces manual doc | PROCESS-GUARD.md sections replaced with pointers to generated output | + + **Scope:** + | Content Section | Source | Mechanism | + | Error codes with cause/fix | RULE_DEFINITIONS constant | Already generated (error-catalog.md) | + | Fix rationale per error | New convention annotations on src/lint/ | Convention tag extraction | + | Escape hatch alternatives | New convention annotations | Convention tag extraction | + | FSM transitions and protection levels | VALID_TRANSITIONS, PROTECTION_LEVELS | Already generated | + | Pre-commit setup (Husky) | Cannot come from annotations | Preamble SectionBlock[] | + | Programmatic API guide | Cannot come from annotations | Preamble SectionBlock[] | + | Architecture diagram (Decider pattern) | Cannot come from annotations | Preamble SectionBlock[] | + | CLI usage and options | Hardcoded in buildCLISection | Already generated | + + **Design Questions (for design session):** + | Question | Options | Recommendation | + | Enhance ValidationRulesCodec or create separate codec? | (A) Extend existing, (B) New ErrorGuideCodec | (A) Extend -- RULE_DEFINITIONS and section builders already exist | + | Convention tag approach? | (A) New process-guard-errors tag, (B) Reuse fsm-rules | (A) New tag -- error diagnosis content is distinct from FSM rule definitions | + | Where does rationale come from? | (A) Convention JSDoc on src/lint/, (B) Rule: blocks in ProcessGuardLinter spec | (A) Convention JSDoc -- rationale belongs near the error-handling code | + | How to handle Husky/CI content? | (A) Preamble, (B) New annotation type | (A) Preamble -- integration recipes are editorial, not code-derived | + + **Design Session Findings (2026-03-06):** + | Finding | Decision | Rationale | + | DD-1: Extend ValidationRulesCodec | Confirmed (A) Extend existing | ValidationRulesCodec owns RULE_DEFINITIONS, 4 boolean option toggles, buildDetailFiles(), and 6 section builders. A separate ErrorGuideCodec would duplicate all of these. New includeErrorGuide toggle follows established pattern. | + | DD-2: New process-guard-errors convention tag | Confirmed (A) New tag | fsm-rules covers FSM structure (transitions, states, protection). Error diagnosis (rationale, alternatives, debugging hints) is a distinct content domain. 13 existing convention values, this becomes the 14th. | + | DD-3: Convention JSDoc on decider.ts | Confirmed (A) Convention JSDoc | decider.ts already has 450-line JSDoc. Convention extractor decomposes by ## Heading sections into ConventionRuleContent entries. Each of 6 error rules gets a ## heading with Invariant/Rationale/table. Proven by orchestrator.ts and reference.ts convention annotations. | + | DD-4: Preamble for Husky/CI content | Confirmed (A) Preamble | ReferenceDocConfig.preamble is SectionBlock[] prepended before generated content. Already proven by product-area docs. Husky setup, programmatic API (6 functions), and Decider architecture diagram are editorial content at editorial cadence. | + | DD-5: Two-document composition strategy | ReferenceDocConfig entry creates unified PROCESS-GUARD.md | The reference codec composes preamble + convention content. The validation-rules generator continues producing error-catalog.md, fsm-transitions.md, protection-levels.md independently. The reference doc links to these detail files. | + | DD-6: Fallback strategy for missing annotations | description field as fallback rationale | composeRationaleIntoRules() enriches RULE_DEFINITIONS from convention bundles. If no convention annotation exists for a rule ID, rationale defaults to description. No empty rationale sections in output. | + + **Design Stubs:** + | Stub | Location | Purpose | + | enhanced-validation-options.ts | delivery-process/stubs/error-guide-codec/ | DD-1: Extended ValidationRulesCodecOptions with includeErrorGuide toggle and EnhancedRuleDefinition interface | + | error-guide-config.ts | delivery-process/stubs/error-guide-codec/ | DD-2/DD-4: ReferenceDocConfig entry with preamble SectionBlocks and convention tag registration | + | convention-annotation-example.ts | delivery-process/stubs/error-guide-codec/ | DD-3: Example convention annotation format for all 6 error rules on decider.ts | + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | Register process-guard-errors convention tag value | complete | src/taxonomy/conventions.ts | Yes | unit | + | Annotate error-handling source files with convention tags | complete | src/lint/process-guard/decider.ts | No | n/a | + | Add ValidationRulesCodecOptions toggles for error guide sections | complete | src/renderable/codecs/validation-rules.ts | Yes | unit | + | ReferenceDocConfig entry for PROCESS-GUARD generated reference | complete | delivery-process.config.ts | Yes | integration | + | Preamble content for Husky/CI setup and programmatic API | complete | delivery-process.config.ts | Yes | integration | + | Replace PROCESS-GUARD.md reference sections with pointer to generated output | complete | docs/PROCESS-GUARD.md | No | n/a | + | Behavior spec with scenarios for error guide generation | n/a | tests/features/generation/error-guide-codec.feature | Yes | acceptance | + + Rule: Error guide extends the existing ValidationRulesCodec + + **Invariant:** Error diagnosis guide content is produced by enhancing the existing + `ValidationRulesCodec` and its `RULE_DEFINITIONS` constant, not by creating a + parallel codec. The enhanced codec adds fix rationale, alternative approaches, and + integration context to the existing error catalog, FSM transitions, and protection + level detail files. A separate `ErrorGuideCodec` class is not created. + + **Rationale:** `ValidationRulesCodec` already owns `RULE_DEFINITIONS` with error + codes, causes, and fixes. It generates `error-catalog.md`, `fsm-transitions.md`, + and `protection-levels.md`. Creating a parallel codec would duplicate RULE_DEFINITIONS + access and fragment validation documentation across two codecs. Extending the existing + codec keeps all validation reference content in one place. + + **Verified by:** Enhanced codec produces error guide sections, + No parallel ErrorGuideCodec class exists + + @acceptance-criteria @happy-path + Scenario: Enhanced ValidationRulesCodec produces error guide content + Given the ValidationRulesCodec with error guide options enabled + And RULE_DEFINITIONS contains error codes with causes and fixes + And convention-tagged source files provide fix rationale + When the codec generates the validation rules document + Then error guide sections appear with rationale for each error code + And each error code entry includes cause, fix, and why-this-rule-exists + + @acceptance-criteria @validation + Scenario: Error guide options are independently toggleable + Given the ValidationRulesCodec with includeErrorGuide set to false + When the codec generates the validation rules document + Then no error guide rationale sections appear + And the existing error catalog, FSM, and protection level sections still render + + Rule: Each error code has fix rationale explaining why the rule exists + + **Invariant:** Every error code in the generated output includes not just a fix + command but a "why this rule exists" rationale. The rationale is sourced from + `@libar-docs-convention:process-guard-errors` JSDoc annotations on the error-handling + code in `src/lint/process-guard/`. The `RuleDefinition` interface is extended with + a `rationale` field, or rationale is composed from convention-extracted content. + + **Rationale:** The existing `error-catalog.md` tells developers what to do (fix + command) but not why the rule exists. Without rationale, developers reach for escape + hatches instead of understanding the workflow constraint. PROCESS-GUARD.md includes + rationale like "Prevents scope creep during implementation. Plan fully before + starting; implement what was planned." -- this must survive in the generated output. + + **Verified by:** All error codes have rationale in output, + Convention annotations are the rationale source + + @acceptance-criteria @happy-path + Scenario: Generated error catalog includes rationale for each rule + Given source files in src/lint/process-guard/ annotated with process-guard-errors convention + And each annotation includes a rationale section in its JSDoc + When the enhanced ValidationRulesCodec generates the error catalog detail file + Then each error code entry includes a "Why this rule exists" section + And the rationale text matches the convention annotation content + + @acceptance-criteria @validation + Scenario: Missing convention annotation falls back to description + Given a RULE_DEFINITIONS entry with no matching convention annotation + When the enhanced ValidationRulesCodec generates the error catalog + Then the error code entry uses the description field as fallback rationale + And no empty rationale section appears in the output + + Rule: Preamble carries integration content that cannot come from annotations + + **Invariant:** Pre-commit setup instructions (Husky configuration, package.json + scripts), CI pipeline patterns, programmatic API examples, and the Decider pattern + architecture diagram use the `ReferenceDocConfig.preamble` mechanism. These are + `SectionBlock[]` defined in the config entry, prepended before all generated content. + Preamble content is manually authored and changes at editorial cadence, not code cadence. + + **Rationale:** Integration recipes (Husky hook setup, CI YAML patterns, API usage + examples) are not extractable from source annotations because they describe how + external systems consume Process Guard, not how Process Guard is implemented. + The preamble mechanism exists precisely for this: editorial prose that lives in + the config, not in a separate manual file, and appears in the generated output. + + **Verified by:** Preamble includes Husky setup section, + Preamble includes programmatic API section + + @acceptance-criteria @happy-path + Scenario: Generated document includes Husky pre-commit setup from preamble + Given a ReferenceDocConfig with preamble containing Husky setup instructions + When the reference codec generates the PROCESS-GUARD reference document + Then the Husky setup section appears before generated validation rules content + And the section includes package.json script examples + + @acceptance-criteria @happy-path + Scenario: Generated document includes programmatic API guide from preamble + Given a ReferenceDocConfig with preamble containing programmatic API examples + When the reference codec generates the PROCESS-GUARD reference document + Then the API guide section appears in the preamble area + And the section includes import paths and function signatures + + @acceptance-criteria @validation + Scenario: Preamble content appears in both detail levels + Given a ReferenceDocConfig with preamble and convention tags + When the reference codec generates at detailed and summary levels + Then preamble sections appear in both outputs + And convention-derived content follows the preamble in both outputs + + Rule: Convention tags source error context from annotated lint code + + **Invariant:** Error-handling code in `src/lint/process-guard/` is annotated with + `@libar-docs-convention:process-guard-errors` using structured JSDoc that includes + rationale, alternative approaches, and common mistake patterns. The convention tag + value `process-guard-errors` is registered in `src/taxonomy/conventions.ts` in the + `CONVENTION_VALUES` array. The `createReferenceCodec` factory extracts this content + via the existing convention extractor pipeline. + + **Rationale:** Convention-tagged annotations on the error-handling code co-locate + rationale with implementation. When a developer changes an error rule in the decider, + the convention JSDoc is right there -- they update both in the same commit. This is + the same pattern used by `codec-registry`, `pipeline-architecture`, and + `taxonomy-rules` convention tags, all proven by CodecDrivenReferenceGeneration. + + **Verified by:** Convention tag is registered in CONVENTION_VALUES, + Convention extraction produces error context sections + + @acceptance-criteria @happy-path + Scenario: Convention tag value is registered and extractable + Given the CONVENTION_VALUES array in src/taxonomy/conventions.ts + When process-guard-errors is added to the array + Then the convention extractor recognizes the tag value + And source files tagged with process-guard-errors produce convention sections + + @acceptance-criteria @happy-path + Scenario: Convention-tagged decider code produces structured error context + Given the decider.ts file annotated with process-guard-errors convention + And the JSDoc includes rationale and alternative-approach sections + When the reference codec extracts convention content + Then each annotated block produces a section with rationale and alternatives + And sections are ordered by error code identifier + + @acceptance-criteria @validation + Scenario: Unannotated error-handling files produce no convention content + Given error-handling files in src/lint/ without convention tags + When the reference codec extracts convention content for process-guard-errors + Then no convention sections are produced for unannotated files + And the generated document still includes RULE_DEFINITIONS-based content diff --git a/delivery-process/specs/generated-doc-quality.feature b/delivery-process/specs/generated-doc-quality.feature new file mode 100644 index 00000000..c8219616 --- /dev/null +++ b/delivery-process/specs/generated-doc-quality.feature @@ -0,0 +1,123 @@ +@libar-docs +@libar-docs-pattern:GeneratedDocQuality +@libar-docs-status:completed +@libar-docs-phase:38 +@libar-docs-effort:2d +@libar-docs-product-area:Generation +@libar-docs-depends-on:DocsLiveConsolidation +@libar-docs-business-value:removes-500-lines-duplication-and-fixes-claude-context-coverage-for-generation-area +@libar-docs-priority:high +Feature: Generated Documentation Quality Improvements + + **Problem:** + Four quality issues reduce the usefulness of generated docs for both Claude agents + and human developers: (1) REFERENCE-SAMPLE.md re-renders canonical value tables + twice — 500+ duplicate lines with zero information gain; (2) the Generation product + area compact file is 1.4 KB for a 233 KB area — critically undersized; (3) + ARCHITECTURE-TYPES.md opens with orchestrator prose instead of type definitions, + burying the content Claude most needs; (4) product area docs (GENERATION.md 233 KB, + DATA-API.md 102 KB) have no navigation TOC, making browser traversal impractical. + + **Solution:** + Fix the reference codec's behavior-specs renderer to stop duplicating convention + tables. Enrich the Generation product area compact template. Reorder + ARCHITECTURE-TYPES.md to lead with type definitions. Add a generated TOC block + to product area doc headers. + + **Why It Matters:** + | Benefit | Audience | + | Removes ~200 wasted token-lines per REFERENCE-SAMPLE.md read | Claude | + | Generation compact usable as standalone context (1.4 KB → 4+ KB) | Claude | + | ARCHITECTURE-TYPES.md answers "what is MasterDataset?" immediately | Claude | + | 233 KB product area docs become navigable in a browser | Human devs | + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | Fix behavior-specs renderer: no duplicate convention tables | complete | src/renderable/codecs/reference.ts | Yes | unit | + | Enrich Generation _claude-md/ compact (target: 4+ KB) | complete | src/renderable/codecs/reference.ts | Yes | integration | + | Reorder ARCHITECTURE-TYPES.md: types first, convention content second | complete | delivery-process.config.ts, src/renderable/codecs/reference.ts | Yes | integration | + | Add generated TOC block to product area doc headers | complete | src/renderable/codecs/reference.ts | Yes | integration | + + Rule: Behavior-specs renderer does not duplicate convention table content + + **Invariant:** When the reference codec renders a convention rule that contains + a table, the table appears exactly once in the output: in the main convention + section. The behavior-specs (expanded rule detail) section shows only the + Invariant, Rationale, and Verified-by metadata — not the table body. A + convention section with N tables produces exactly N table instances in the + generated document, regardless of detail level. + + **Rationale:** DD-4: The current renderer re-includes the full convention + table when rendering the expanded rule detail section. For REFERENCE-SAMPLE.md + with 5 canonical value tables, this produces 500+ lines of exact duplication. + Agents consuming this file waste context on content they already parsed. + Human readers see the same table twice in the same scroll view. + + **Verified by:** Convention tables appear once in output, + Behavior-specs shows rule metadata only + + @acceptance-criteria @happy-path + Scenario: Convention rule table appears exactly once in generated output + Given a ReferenceDocConfig with a convention rule containing a markdown table + When the reference codec generates at detailed level + Then the table appears once in the convention section + And the behavior-specs expanded detail shows invariant and rationale only + And no duplicate table rows exist in the document + + @acceptance-criteria @validation + Scenario: REFERENCE-SAMPLE.md contains no duplicate table content after fix + Given the reference-sample config regenerated after codec fix + When the output is compared line by line + Then each canonical value table appears exactly once + And total document length is under 966 lines (down from 1166) + + Rule: Compact _claude-md/ files are self-sufficient for their product area + + **Invariant:** Each product area compact (`_claude-md//-overview.md`) + is self-sufficient as a standalone context file — an agent reading only the + compact can answer: what does this area do, what are its key patterns, what are + its invariants, and what files to read for details. Minimum target: 4 KB. + The Generation compact is a specific gap: 1.4 KB for an area with 20+ codecs + and the entire rendering pipeline. + + **Rationale:** DD-2: `_claude-md/` compacts are the Claude consumption contract. + A 1.4 KB compact for the largest product area (233 KB) means agents have no + usable summary context for Generation. They fall back to reading the full file + or hallucinating based on names alone. The contract requires each compact to be + a genuine summary, not a stub. + + **Verified by:** Generation compact >= 4 KB with codec list and pipeline summary, + All area compacts self-sufficient without full product area doc + + @acceptance-criteria @happy-path + Scenario: Generation compact contains codec inventory and pipeline summary + Given the Generation product area compact regenerated with enriched template + When its content is checked + Then it contains a list of all major codecs with one-line purposes + And it contains the four-stage pipeline summary (Scanner-Extractor-Transformer-Codec) + And its file size is at least 4 KB + + Rule: ARCHITECTURE-TYPES.md leads with type definitions, not convention content + + **Invariant:** ARCHITECTURE-TYPES.md opens with the MasterDataset type definitions + section before any pipeline-architecture convention content. An agent querying + "what is MasterDataset" finds the type definition within the first 30 lines. + The pipeline-architecture convention prose (orchestrator responsibilities, pipeline + steps) follows the type definitions section. + + **Rationale:** The file is named ARCHITECTURE-TYPES — type definitions are the + primary content. The pipeline-architecture convention content was added as a + secondary layer. Current output opens with orchestrator prose, burying the type + definitions that both Claude and human developers are most likely seeking. + Section ordering in ReferenceDocConfig determines render order. + + **Verified by:** Type definitions appear in first 30 lines, + Pipeline convention content follows types section + + @acceptance-criteria @happy-path + Scenario: MasterDataset type definition appears before orchestrator prose + Given ARCHITECTURE-TYPES.md generated with shapes section ordered before conventions + When the first 30 lines are read + Then MasterDataset or a related type definition appears + And no orchestrator responsibility prose appears before the first type definition diff --git a/delivery-process/specs/gherkin-patterns-restructure.feature b/delivery-process/specs/gherkin-patterns-restructure.feature new file mode 100644 index 00000000..832eedef --- /dev/null +++ b/delivery-process/specs/gherkin-patterns-restructure.feature @@ -0,0 +1,128 @@ +@libar-docs +@libar-docs-pattern:GherkinPatternsRestructure +@libar-docs-status:completed +@libar-docs-phase:41 +@libar-docs-effort:0.5d +@libar-docs-product-area:Generation +@libar-docs-depends-on:DocsConsolidationStrategy +@libar-docs-business-value:single-responsibility-per-doc +@libar-docs-priority:medium +Feature: Gherkin Patterns Guide Restructure + + **Problem:** + `docs/GHERKIN-PATTERNS.md` is 515 lines and mixes two distinct concerns: + (a) a writing guide for Gherkin authoring patterns (belongs here), and + (b) the Step Linting reference — 12 rules, 3 categories, examples, and CLI flags (lines 346–493, + ~148 lines) — which is quality tooling and belongs in VALIDATION.md alongside lint-patterns, + lint-process, and validate-patterns. + + The current cross-reference in VALIDATION.md (line 96) already says: "Detailed rules and examples: + See GHERKIN-PATTERNS.md — Step Linting". This is a forward-reference anti-pattern: the content + lives in the wrong file and requires a redirect to find it. + + **Solution:** + Move the Step Linting section (lines 346–493) into VALIDATION.md as a first-class section, + replacing the current redirect pointer (line 96) with the actual content. Trim GHERKIN-PATTERNS.md + from 515 lines to approximately 370 lines, retaining all authoring guide content. Update all + cross-references between the two files and in INDEX.md to reflect the new locations. + + **Design Finding — Revised Line Target (250 → ~370):** + + | Finding | Impact | Resolution | + | Original target was ~250 lines | Section audit shows only Step Linting (148 lines) is misplaced | Revised target to ~370 lines | + | Remaining 366 lines are ALL authoring content | Essential Patterns, Rich Content, Tag Conventions are referenced by CLAUDE.md and SESSION-GUIDES.md | No further trimming — removing would damage the guide | + | CLAUDE.md overlap is intentional | Testing section (274 lines) covers same rules but for AI debugging context, not tool reference | No CLAUDE.md trim in this phase | + + **Why It Matters:** + | Benefit | How | + | Single responsibility | Each doc covers one concern: writing vs. quality tooling | + | Reduced navigation | Developers find lint rules in VALIDATION.md, not GHERKIN-PATTERNS.md | + | Accurate cross-refs | VALIDATION.md becomes self-contained for all validation tooling | + | Smaller writing guide | 370-line doc is easier to scan during authoring sessions | + + **Section Disposition (from design session audit):** + + | Section | Lines | Line Range | Action | + | Header + intro | 7 | 1-7 | KEEP | + | Essential Patterns | 144 | 9-152 | KEEP | + | DataTable and DocString Usage | 50 | 154-203 | KEEP | + | Tag Conventions | 39 | 205-243 | KEEP | + | Feature File Rich Content | 99 | 246-344 | KEEP | + | Step Linting | 148 | 346-493 | MOVE to VALIDATION.md | + | Quick Reference | 12 | 495-506 | KEEP, remove lint-steps row | + | Related Documentation | 8 | 508-515 | KEEP, update descriptions | + + **VALIDATION.md Integration Point:** + + Current lint-steps section (lines 76-97) has a redirect pointer at line 96. + Replace lines 76-98 with: keep intro (76-95), delete redirect (96), insert + moved content (Feature File Rules, Step Definition Rules, Cross-File Rules, + CLI Reference from GHERKIN-PATTERNS.md lines 356-492). Result: ~430 lines. + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | Move Step Linting section (lines 346-493) to VALIDATION.md, replacing redirect at line 96 | complete | docs/VALIDATION.md | No | n/a | + | Remove Step Linting section from GHERKIN-PATTERNS.md (result: ~370 lines) | complete | docs/GHERKIN-PATTERNS.md | No | n/a | + | Update cross-references between the two docs | complete | docs/GHERKIN-PATTERNS.md, docs/VALIDATION.md | No | n/a | + | Verify related-documentation tables in both files | complete | docs/GHERKIN-PATTERNS.md, docs/VALIDATION.md | No | n/a | + | Update INDEX.md section tables and line counts for both docs | complete | docs/INDEX.md | No | n/a | + | Add lint-steps cross-reference row in GHERKIN-PATTERNS.md Quick Reference | complete | docs/GHERKIN-PATTERNS.md | No | n/a | + + Rule: Step Linting content belongs in VALIDATION.md + + **Invariant:** All validation tooling reference content lives in VALIDATION.md. + + **Rationale:** VALIDATION.md already documents lint-patterns, lint-process, and validate-patterns. + Step Linting is a fourth quality tool in the same family — it must follow the same pattern. + Redirecting from VALIDATION.md to GHERKIN-PATTERNS.md for lint rules breaks the principle that + VALIDATION.md is the single place to find quality tooling documentation. + + **Verified by:** Step Linting section appears in VALIDATION.md after restructure + + @acceptance-criteria @happy-path + Scenario: Step Linting section appears in VALIDATION.md after restructure + Given VALIDATION.md currently contains a redirect pointer to GHERKIN-PATTERNS.md for Step Linting rules + When the restructure is complete + Then VALIDATION.md contains the full Step Linting section including all 12 rules and the CLI reference + And the redirect pointer is removed from VALIDATION.md + And GHERKIN-PATTERNS.md no longer contains the Step Linting section + + Rule: GHERKIN-PATTERNS.md remains the authoring guide + + **Invariant:** GHERKIN-PATTERNS.md covers only Gherkin writing patterns, not tooling reference. + + **Rationale:** The writing guide is useful during spec authoring. Quality tool reference is + useful during CI setup and debugging. Mixing them forces authors to scroll past 148 lines of + tooling reference they do not need during writing, and forces CI engineers to look in the + wrong file for lint rule documentation. + + **Verified by:** Trimmed doc retains all authoring patterns, cross-references updated correctly + + @acceptance-criteria @happy-path + Scenario: Trimmed doc retains all authoring patterns and cross-references updated correctly + Given GHERKIN-PATTERNS.md is 515 lines containing authoring patterns and Step Linting content + When the Step Linting section is moved to VALIDATION.md + Then GHERKIN-PATTERNS.md is approximately 370 lines + And it retains Essential Patterns, DataTable and DocString usage, Tag Conventions, and Rich Content sections + And its Quick Reference table links to VALIDATION.md for lint-steps + And its Related Documentation table links to VALIDATION.md for the full lint tool suite + + Rule: INDEX.md reflects current document structure + + **Invariant:** INDEX.md section tables and line counts must be updated when content moves between docs. + + **Rationale:** INDEX.md serves as the navigation hub for all documentation. Stale line counts + and missing section entries cause developers to land in the wrong part of a document or miss + content entirely. Both GHERKIN-PATTERNS.md and VALIDATION.md entries must reflect the restructure. + + **Verified by:** INDEX.md entries match post-restructure line counts and sections + + @acceptance-criteria @validation + Scenario: INDEX.md entries match post-restructure line counts and sections + Given INDEX.md lists GHERKIN-PATTERNS.md at lines 1-515 and VALIDATION.md at lines 1-281 + When the restructure moves Step Linting content between the two docs + Then INDEX.md lists GHERKIN-PATTERNS.md at approximately 370 lines + And INDEX.md lists VALIDATION.md at approximately 430 lines + And the GHERKIN-PATTERNS.md section table no longer includes Step Linting + And the VALIDATION.md section table includes Step Linting with rules and examples diff --git a/delivery-process/specs/procedural-guide-codec.feature b/delivery-process/specs/procedural-guide-codec.feature new file mode 100644 index 00000000..bea062cd --- /dev/null +++ b/delivery-process/specs/procedural-guide-codec.feature @@ -0,0 +1,307 @@ +@libar-docs +@libar-docs-pattern:ProceduralGuideCodec +@libar-docs-status:completed +@libar-docs-unlock-reason:DD7-DD8-preamble-migration-complete +@libar-docs-phase:35 +@libar-docs-effort:3w +@libar-docs-product-area:Generation +@libar-docs-depends-on:DocsConsolidationStrategy +@libar-docs-business-value:replaces-757-lines-of-manual-SESSION-GUIDES-and-ANNOTATION-GUIDE-with-generated-procedural-guides-using-dual-source-codec +@libar-docs-priority:medium +Feature: Procedural Guide Codec + + **Problem:** + Two manual docs contain procedural content with no annotation source for generation: + `docs/SESSION-GUIDES.md` (389 lines) has session decision trees, per-session checklists, + prohibition lists, handoff templates, and discovery tag formats. `docs/ANNOTATION-GUIDE.md` + (268 lines) has a getting-started walkthrough, shape extraction mode explanations, the Zod + schema gotcha, file-type-specific annotation patterns, verification CLI recipes, and a + troubleshooting table. Gap analysis (WP-7) found only ~5% of this content is + auto-generatable from existing sources -- the remaining ~95% is procedural and editorial. + + The SessionGuidesModuleSource spec (Phase 39, completed) established 9 Rule: blocks with + session workflow invariants and generates compact AI context to `_claude-md/workflow/`. + However, these produce summary-level invariant statements for AI sessions, not the + developer-facing step-by-step checklists and decision trees that SESSION-GUIDES.md provides. + No generation path exists for the public-facing procedural guide content. + + **Solution:** + Create a `ProceduralGuideCodec` that uses a dual-source composition pattern: auto-generated + reference sections (tag reference tables, pattern statistics, session type contracts) are + derived from MasterDataset and taxonomy sources, while procedural content (checklists, + decision trees, getting-started walkthrough, troubleshooting tables) is authored as markdown + files in `docs-sources/` and parsed into `SectionBlock[]` at config load time by + `loadPreambleFromMarkdown()`. The codec produces two separate generated files -- one for + session workflow guides and one for annotation guides -- since these serve different + audiences (workflow practitioners vs annotation authors). + + Session workflow checklists are extracted from SessionGuidesModuleSource Rule: blocks and + rendered as developer-facing checklists at the detailed level. Decision trees render as + Mermaid flowchart diagrams, providing visual navigation that the manual docs express as + ASCII text trees. The generated output supersedes the manual files only after reaching + quality parity, respecting the SessionGuidesModuleSource invariant that SESSION-GUIDES.md + "is not deleted, shortened, or replaced with a redirect" during the transition period. + + **Why It Matters:** + | Benefit | How | + | Zero-drift session contracts | Session type table, FSM error reference, execution order regenerated from Rule: blocks | + | Dual audience from single source | SessionGuidesModuleSource Rule: blocks produce AI compact AND public checklists | + | Visual decision trees | Mermaid flowcharts replace ASCII art, render correctly in Starlight website | + | Separate guides for separate audiences | Session workflow guide and annotation guide are independent documents | + | Quality-gated transition | Manual files retained until generated equivalents match or exceed quality | + | Closes largest gap | WP-7 is the largest content gap (757 lines across 2 files with no generation source) | + + **Scope:** + | Content Section | Source | Mechanism | + | Session type decision tree | SessionGuidesModuleSource Rule 3 table | Auto-generated + Mermaid flowchart | + | Per-session checklists (Planning, Design, Implementation) | SessionGuidesModuleSource Rules 4-6 tables | Auto-generated from Rule: block tables | + | Session prohibition lists (Do NOT tables) | SessionGuidesModuleSource Rules 4, 6 tables | Auto-generated from Rule: block tables | + | FSM error reference and escape hatches | SessionGuidesModuleSource Rule 7 tables | Auto-generated from Rule: block tables | + | Handoff documentation template | SessionGuidesModuleSource Rule 8 | Auto-generated from Rule: block content | + | Context gathering CLI commands | Cannot derive from annotations | Markdown source -> loadPreambleFromMarkdown() | + | Getting-started annotation walkthrough | Cannot derive from annotations | Markdown source -> loadPreambleFromMarkdown() | + | Shape extraction mode explanations | Cannot derive from annotations | Markdown source -> loadPreambleFromMarkdown() | + | Zod schema gotcha and troubleshooting | Cannot derive from annotations | Markdown source -> loadPreambleFromMarkdown() | + | Tag reference summary table | Taxonomy registry data | Auto-generated from MasterDataset | + | Verification CLI recipes | Cannot derive from annotations | Markdown source -> loadPreambleFromMarkdown() | + + **Design Questions (for design session):** + | Question | Options | Recommendation | + | Should procedural content use new markers or preamble? | (A) New markers in Rule: blocks, (B) Preamble SectionBlock[] | (B) Preamble -- procedural content is editorial, not code-derivable | + | Can SessionGuidesModuleSource serve both AI and public output? | (A) Yes with detail levels, (B) No, separate sources | (A) Yes -- Rule: blocks have structured tables extractable at both levels | + | One combined codec or two separate codecs? | (A) One ProceduralGuideCodec with two configs, (B) Two separate codecs | (A) One codec -- same composition pattern, different ReferenceDocConfig entries | + | Should ANNOTATION-GUIDE content stay manual? | (A) Fully manual, (B) Hybrid with tag reference auto-generated | (B) Hybrid -- tag reference tables derive from taxonomy, walkthrough uses preamble | + | How to handle GHERKIN-PATTERNS.md overlap? | (A) Absorb into annotation guide, (B) Keep separate | (B) Keep separate -- GHERKIN-PATTERNS serves a different audience (spec authors vs annotation authors) | + | Should preamble be authored as markdown or inline SectionBlock[]? | (A) Markdown parsed at config time, (B) Inline SectionBlock[] in config | (A) Markdown -- natural authoring format, reduces config by ~540 lines, preserves codec purity | + + **Design Session Findings (2026-03-06):** + | Finding | Impact | Resolution | + | DD-1: No new codec class needed -- reuse createReferenceCodec() with two ReferenceDocConfig entries | Eliminates codec implementation deliverable; reduces to config-only work | Two ReferenceDocConfig entries in delivery-process.config.ts with different preamble, includeTags, and output paths | + | DD-2: SessionGuidesModuleSource Rules 3-8 tables already machine-extractable | buildBehaviorSectionsFromPatterns() + parseBusinessRuleAnnotations() + extractTablesFromDescription() handle all table formats | Use includeTags:session-workflows on SessionGuidesModuleSource to route behavior content to session guide | + | DD-3: Checklists and decision trees use existing SectionBlock types | No new ChecklistBlock or DecisionTreeBlock needed; ListBlock with [ ] prefix = checkbox syntax; MermaidBlock = flowchart. SectionBlock[] produced by parsing markdown via loadPreambleFromMarkdown() | Zero schema/renderer changes required | + | DD-4: Preamble is flat SectionBlock[] produced from markdown source files | No new named-section abstraction; heading blocks provide structure. Content authored as markdown in docs-sources/, parsed into SectionBlock[] at config import time -- not inline TypeScript object literals | Preserves same preamble composition pattern; authoring ergonomics improved | + | DD-5: Annotation guide hybrid -- 95% preamble + 5% auto-generated tag tables | Stable editorial content as preamble; only tag reference tables auto-generated from taxonomy | Avoids circular dependency (guide about annotations needing annotations to generate) | + | DD-6: Generated files in docs-live/reference/ alongside manual files in docs/ | No violation of SessionGuidesModuleSource Rule 1 invariant; side-by-side quality comparison possible | Manual files retained until quality audit confirms parity; then superseded with unlock-reason | + | DD-7: Editorial content authored as markdown in docs-sources/ | Preamble SectionBlock[] parsed from markdown files at config import time by loadPreambleFromMarkdown(). Codec purity preserved -- codecs still receive in-memory SectionBlock[]. Config file reduced from 853 to ~310 lines (63% reduction). Natural authoring format for checklists, code blocks, tables, Mermaid diagrams | Two markdown source files: docs-sources/session-workflow-guide.md and docs-sources/annotation-guide.md | + | DD-8: loadPreambleFromMarkdown() is a shared utility in src/renderable/ | Uses readFileSync (sync, runs at module import). Line-by-line state machine parses headings, paragraphs, code/mermaid blocks, tables, lists into SectionBlock[]. Available to all preamble consumers (ErrorGuideCodec, CliRecipeCodec) | Resolves path relative to project root. CollapsibleBlock and LinkOutBlock not parsed (no standard markdown syntax; current preamble content does not use them) | + + **Design Stubs:** + | Stub | Purpose | Target | + | delivery-process/stubs/procedural-guide-codec/procedural-codec-options.ts | Documents DD-1,DD-3,DD-4: no new options type, reuses ReferenceDocConfig | src/renderable/codecs/procedural-guide.ts | + | delivery-process/stubs/procedural-guide-codec/procedural-codec.ts | Documents DD-1,DD-2,DD-5,DD-6,DD-7,DD-8: config entries with loadPreambleFromMarkdown() | delivery-process.config.ts | + | delivery-process/stubs/procedural-guide-codec/session-guide-preamble.ts | DD-7: Markdown source file example + loadPreambleFromMarkdown() usage | delivery-process.config.ts | + | delivery-process/stubs/procedural-guide-codec/annotation-guide-preamble.ts | DD-7: Markdown source file example + loadPreambleFromMarkdown() usage | delivery-process.config.ts | + | delivery-process/stubs/procedural-guide-codec/load-preamble.ts | DD-8: loadPreambleFromMarkdown() utility interface and parsing spec | src/renderable/load-preamble.ts | + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | ReferenceDocConfig entry for session workflow guide (DD-1: reuses createReferenceCodec) | complete | delivery-process.config.ts | Yes | integration | + | ReferenceDocConfig entry for annotation guide (DD-1: reuses createReferenceCodec) | complete | delivery-process.config.ts | Yes | integration | + | Add libar-docs-include:session-workflows tag to SessionGuidesModuleSource (DD-2) | complete | delivery-process/specs/session-guides-module-source.feature | No | n/a | + | Create loadPreambleFromMarkdown() utility (DD-8) | complete | src/renderable/load-preamble.ts | Yes | unit | + | Create session workflow guide markdown source (DD-7) | complete | docs-sources/session-workflow-guide.md | No | n/a | + | Create annotation guide markdown source (DD-7) | complete | docs-sources/annotation-guide.md | No | n/a | + | Migrate session workflow preamble to loadPreambleFromMarkdown() call (DD-7) | complete | delivery-process.config.ts | Yes | integration | + | Migrate annotation guide preamble to loadPreambleFromMarkdown() call (DD-7) | complete | delivery-process.config.ts | Yes | integration | + | Behavior spec with scenarios for procedural guide generation | n/a | tests/features/generation/procedural-guide-codec.feature | Yes | acceptance | + | Quality comparison: generated vs manual content audit (DD-6) | n/a | docs/SESSION-GUIDES.md | No | n/a | + + Rule: Procedural guides use a dual-source codec + + **Invariant:** The ProceduralGuideCodec composes auto-generated reference sections + (from MasterDataset and taxonomy) with manually-authored procedural content (from + preamble `SectionBlock[]`). Auto-generated content covers ~5% of the output (tag + reference tables, pattern statistics, session type contract tables extracted from + Rule: blocks). The remaining ~95% is editorial preamble: checklists, decision trees, + getting-started walkthroughs, troubleshooting tables, and verification recipes -- + authored as markdown files in `docs-sources/` and parsed into `SectionBlock[]` by + `loadPreambleFromMarkdown()` at config load time. The codec does not attempt to + generate procedural prose from annotations -- it provides a structured delivery + vehicle that ensures preamble and reference content are composed in a consistent + order with consistent formatting across both guide documents. + + **Rationale:** Gap analysis found that SESSION-GUIDES.md and ANNOTATION-GUIDE.md + content is overwhelmingly procedural and editorial. Attempting to annotate checklists + and walkthroughs as source code would produce worse documentation than hand-authoring. + The dual-source pattern (proven by CodecDrivenReferenceGeneration, ErrorGuideCodec, + and CliRecipeCodec) composes preamble editorial content with auto-generated reference + sections. The codec's value is not in generating the procedural content but in + providing a single output pipeline that keeps reference tables current while carrying + editorial content in a consistent structure. + + **Verified by:** Codec output contains both preamble and generated sections, + Generated reference sections update when source data changes + + @acceptance-criteria @happy-path + Scenario: ProceduralGuideCodec composes preamble with generated reference + Given a ProceduralGuideCodec configured with preamble checklist content + And the MasterDataset contains session type metadata from SessionGuidesModuleSource + When the codec generates the session workflow guide + Then preamble checklist sections appear first in the output + And auto-generated session type contract tables follow the preamble + And tag reference tables from taxonomy data appear in the reference section + + @acceptance-criteria @validation + Scenario: Generated reference sections update when source data changes + Given the SessionGuidesModuleSource spec adds a new session type to Rule 3 + When the ProceduralGuideCodec regenerates the session workflow guide + Then the session type contract table includes the new session type + And preamble content is unchanged + + Rule: Session workflow checklists derive from annotated Rule: blocks + + **Invariant:** The SessionGuidesModuleSource spec's Rule: blocks (Rules 3-8) are the + canonical source for session workflow invariants. The ProceduralGuideCodec extracts + structured tables from these Rule: blocks and renders them as developer-facing + checklists at the detailed level. The same Rule: blocks produce compact invariant + statements for `_claude-md/workflow/` modules at the summary level. Two audiences + (public developers and AI sessions) are served from a single annotated source with + different rendering detail levels. The codec does not duplicate or re-derive Rule: + block content -- it reads from MasterDataset's behavior extraction views. + + **Rationale:** SessionGuidesModuleSource already captures session type contracts + (Rule 3), planning constraints (Rule 4), design constraints (Rule 5), implementation + execution order (Rule 6), FSM error reference (Rule 7), and handoff patterns (Rule 8) + as structured tables within Rule: block descriptions. These tables contain the same + information as the manual SESSION-GUIDES.md checklists, but in a machine-extractable + format. Rendering these as developer-facing checklists eliminates the maintenance + burden of keeping the manual file in sync with the spec, while the compact rendering + for AI context was already delivered by Phase 39. + + **Verified by:** Checklists render from SessionGuidesModuleSource Rule: blocks, + Both detail levels render from the same source + + @acceptance-criteria @happy-path + Scenario: Session checklists render from Rule: block extraction + Given SessionGuidesModuleSource contains Rule 4 with a planning Do/Do-NOT table + And Rule 6 with an implementation execution order list + When the ProceduralGuideCodec renders the session workflow guide at detailed level + Then a Planning Session section contains a checklist derived from Rule 4 + And an Implementation Session section contains a numbered execution order from Rule 6 + And the checklist items match the Rule: block table content + + @acceptance-criteria @validation + Scenario: Summary level produces compact invariants not full checklists + Given the ProceduralGuideCodec configured for summary detail level + When rendering the session workflow guide + Then session type contracts appear as a compact table + And full checklists are omitted in favor of invariant statements + And the summary output is suitable for AI context consumption + + Rule: Annotation guide content remains separate from session guides + + **Invariant:** The ProceduralGuideCodec produces two separate generated files via two + `ReferenceDocConfig` entries: one for session workflow guides (replacing SESSION-GUIDES.md) + and one for annotation guides (replacing ANNOTATION-GUIDE.md). The session workflow guide + targets workflow practitioners who need to know session type selection, execution order, + and FSM error recovery. The annotation guide targets annotation authors who need to know + opt-in markers, tag syntax, shape extraction modes, and verification steps. These + audiences overlap but have distinct primary needs. The codec class is shared; the config + entries and preamble content differ. + + **Rationale:** SESSION-GUIDES.md and ANNOTATION-GUIDE.md serve different audiences at + different points in the development lifecycle. Merging them into a single guide would + force annotation authors to navigate session workflow content and vice versa. The + existing DocsConsolidationStrategy Phase 5 (Guide trimming) already treats them as + separate documents. Using one codec class with two config entries follows the same + pattern as `createReferenceCodec` producing multiple documents from different configs. + + **Verified by:** Two separate generated files from two config entries, + Session guide has no annotation walkthrough content + + @acceptance-criteria @happy-path + Scenario: Two separate guide files are generated + Given the ProceduralGuideCodec with two ReferenceDocConfig entries + And one entry targets session workflow guide output + And the other entry targets annotation guide output + When the codec generates both documents + Then docs-live/reference/SESSION-WORKFLOW-GUIDE.md is created + And docs-live/reference/ANNOTATION-REFERENCE.md is created + And the two files have no duplicated sections + + @acceptance-criteria @validation + Scenario: Session guide contains no annotation walkthrough content + Given the generated session workflow guide + When inspecting its sections + Then no getting-started annotation walkthrough appears + And no shape extraction mode explanation appears + And the content focuses exclusively on session types, checklists, and FSM reference + + Rule: Decision trees render as Mermaid flowcharts + + **Invariant:** Session type decision trees and annotation workflow decision trees render + as Mermaid flowchart diagrams in the detailed output level. The session type decision + tree replaces the ASCII art tree in SESSION-GUIDES.md with a Mermaid `graph TD` diagram + that renders as an interactive flowchart on the Starlight website. Decision tree content + is authored as fenced mermaid code blocks in the markdown source file, parsed into + `MermaidBlock` entries by `loadPreambleFromMarkdown()` at config load time. At summary + level, decision trees render as compact text tables instead of diagrams. + + **Rationale:** The manual SESSION-GUIDES.md uses an ASCII art tree for the session + decision flow, which renders poorly on the website and cannot be interacted with. + Mermaid flowcharts are already supported by the Starlight website (proven by product + area docs with C4Context and graph LR diagrams). Converting decision trees to Mermaid + provides visual clarity, click-through navigation, and consistent rendering across + platforms. The content block type `mermaid` is already one of the 9 supported + SectionBlock types (proven by ReferenceDocShowcase). + + **Verified by:** Decision tree renders as Mermaid flowchart, + Summary level uses text table instead of diagram + + @acceptance-criteria @happy-path + Scenario: Session decision tree renders as Mermaid flowchart + Given the session workflow guide preamble contains a Mermaid graph TD diagram + And the diagram models the session type decision flow + When the ProceduralGuideCodec renders at detailed level + Then the output contains a Mermaid code block with the decision tree + And the diagram includes nodes for Planning, Design, Implementation, and Planning+Design + And decision edges use conditional labels + + @acceptance-criteria @validation + Scenario: Summary level renders decision tree as text table + Given the ProceduralGuideCodec configured for summary detail level + When rendering the session workflow guide + Then the decision tree appears as a compact text table mapping conditions to session types + And no Mermaid code block appears in the summary output + + Rule: Generated guide supersedes manual only at quality parity + + **Invariant:** The manual `docs/SESSION-GUIDES.md` is retained in the repository + until the generated equivalent matches or exceeds its quality across all content + dimensions: completeness (all checklists present), accuracy (all FSM states current), + visual clarity (decision trees render correctly), and usability (verified by comparison + audit). The SessionGuidesModuleSource invariant ("not deleted, shortened, or replaced + with a redirect") is respected during the transition period. The quality comparison + deliverable produces an explicit audit document recording which sections have parity + and which gaps remain. Only after the audit confirms full parity is the manual file + replaced with a pointer to the generated output. + + **Rationale:** SESSION-GUIDES.md is cited in the SessionGuidesModuleSource spec as + "the authoritative public human reference" serving developers on libar.dev. Replacing + it prematurely with a generated equivalent that lacks checklists, has formatting issues, + or omits edge cases would degrade the developer experience. The quality-gated approach + ensures the generated version earns its place as the replacement by demonstrating + equivalent or better quality, not merely by existing. This is the same principle applied + by DocsConsolidationStrategy: "Manual docs retain editorial and tutorial content" until + generation quality is sufficient. + + **Verified by:** Manual file retained during transition, + Quality audit produces explicit parity assessment + + @acceptance-criteria @happy-path + Scenario: Manual SESSION-GUIDES.md is retained during transition + Given the ProceduralGuideCodec has generated docs-live/reference/SESSION-WORKFLOW-GUIDE.md + And the quality audit has not yet confirmed parity + When inspecting the repository + Then docs/SESSION-GUIDES.md still exists with its original content + And docs/SESSION-GUIDES.md is not shortened or replaced with a redirect + And docs-live/reference/SESSION-WORKFLOW-GUIDE.md exists alongside it + + @acceptance-criteria @validation + Scenario: Quality audit produces explicit parity assessment + Given the generated session workflow guide and the manual SESSION-GUIDES.md + When performing the quality comparison audit + Then an audit record documents each section of SESSION-GUIDES.md + And each section is marked as parity-achieved or gap-remaining + And sections with gaps include a description of what is missing diff --git a/delivery-process/specs/process-api-hybrid-generation.feature b/delivery-process/specs/process-api-hybrid-generation.feature new file mode 100644 index 00000000..0eb51c60 --- /dev/null +++ b/delivery-process/specs/process-api-hybrid-generation.feature @@ -0,0 +1,157 @@ +@libar-docs +@libar-docs-pattern:ProcessApiHybridGeneration +@libar-docs-status:completed +@libar-docs-phase:43 +@libar-docs-effort:1d +@libar-docs-product-area:Generation +@libar-docs-depends-on:DocsConsolidationStrategy +@libar-docs-business-value:keeps-process-api-reference-tables-in-sync-with-cli-schema-automatically +@libar-docs-priority:low +Feature: PROCESS-API.md Hybrid Generation + + **Problem:** + `docs/PROCESS-API.md` (509 lines) contains three reference tables that manually + mirror CLI definitions in source code: Global Options (lines 382-389, 6 rows), + Output Modifiers (lines 397-403, 5 rows), and List Filters (lines 415-424, 8 rows). + These ~41 lines are pure data derived from code constants in `src/cli/process-api.ts` + and `src/cli/output-pipeline.ts`. When CLI options change, these tables require + manual updates and risk falling out of sync with the implementation. + + Additionally, the `showHelp()` function (lines 271-370 of `src/cli/process-api.ts`) + is a hardcoded third copy of the same information, creating three-way drift risk: + parser code, help text, and markdown tables. + + **Solution:** + Create a declarative CLI schema (`src/cli/cli-schema.ts`) as the single source of + truth. A standalone `ProcessApiReferenceGenerator` reads this schema and produces + a complete generated reference file at `docs-live/reference/PROCESS-API-REFERENCE.md`. + The "Output Reference" section in `docs/PROCESS-API.md` (lines 376-424) is replaced + with a heading and link to the generated file. The `showHelp()` function is refactored + to consume the same schema, eliminating three-way sync. + + **Why It Matters:** + | Benefit | How | + | Zero drift | Reference tables regenerate automatically from schema | + | Three-way sync eliminated | Schema drives both help text and generated docs | + | Consistent with existing pattern | Same OutputFile approach as ARCHITECTURE-CODECS.md | + + **Design Findings (2026-03-05):** + | Finding | Impact | Resolution | + | Original spec references src/cli/parser.ts | File does not exist | Fix to src/cli/process-api.ts + src/cli/output-pipeline.ts | + | Orchestrator only does full-file writes | Marker-based partial replacement not supported | Split Output Reference into separate generated file | + | ReferenceDocConfig is MasterDataset-sourced | CLI schema data is not annotation-derived | Standalone generator, not ReferenceDocConfig (ADR-006) | + | --format in Output Modifiers table but not in OutputModifiers interface | Would produce incomplete table | Schema includes --format alongside modifiers | + | --session parsed as global option but absent from Global Options table | Intentional, documented in Session Types | Schema captures in separate sessionOptions group | + | showHelp() lines 271-370 is third copy of same data | Three-way sync risk | Schema drives both help text and doc generation | + | Inter-table prose is only ~10 lines total | Must appear in generated file | Encode as description/postNote fields in schema | + + **Section Audit — docs/PROCESS-API.md (509 lines):** + | Section | Lines | Action | Rationale | + | Intro + Why Use This | 1-30 | KEEP | Editorial context | + | Quick Start | 31-62 | KEEP | Examples with output | + | Session Types | 65-76 | KEEP | Decision tree | + | Session Workflow Commands | 80-204 | KEEP | Narrative descriptions | + | Pattern Discovery | 207-301 | KEEP | Narrative descriptions | + | Architecture Queries | 305-332 | KEEP | Reference with examples | + | Metadata and Inventory | 336-374 | KEEP | Command descriptions | + | Output Reference heading | 376-378 | TRIM | Replace with link to generated file | + | Global Options table | 380-391 | EXTRACT | Generate from CLI schema | + | Output Modifiers table | 393-409 | EXTRACT | Generate from CLI schema | + | List Filters table | 411-424 | EXTRACT | Generate from CLI schema | + | JSON Envelope | 426-449 | KEEP | Operational reference | + | Exit Codes | 451-456 | KEEP | Operational reference | + | JSON Piping | 458-465 | KEEP | Operational tip | + | Common Recipes | 468-509 | KEEP | Editorial recipes | + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | Create declarative CLI schema with option groups | complete | src/cli/cli-schema.ts | Yes | unit | + | Sync test verifying schema entries match parseArgs behavior | complete | tests/features/behavior/cli/ | Yes | integration | + | ProcessApiReferenceGenerator producing complete reference file | complete | src/generators/built-in/process-api-reference-generator.ts | Yes | integration | + | Register generator in orchestrator config | complete | delivery-process.config.ts | Yes | integration | + | Trim PROCESS-API.md Output Reference to link to generated file | complete | docs/PROCESS-API.md | Yes | manual | + | Refactor showHelp to consume CLI schema | complete | src/cli/process-api.ts | Yes | integration | + | Behavior spec with scenarios for all 3 generated tables | complete | tests/features/behavior/cli/process-api-reference.feature | Yes | integration | + + Rule: CLI schema is single source of truth for reference tables + + **Invariant:** A declarative CLI schema in `src/cli/cli-schema.ts` defines all + global options, output modifiers, and list filters with their flags, descriptions, + defaults, and value types. The three reference tables in + `docs-live/reference/PROCESS-API-REFERENCE.md` are generated from this schema by + a standalone `ProcessApiReferenceGenerator`. The schema also drives `showHelp()`. + + **Rationale:** CLI options are defined imperatively in `parseArgs()` (lines 132-265 + of `src/cli/process-api.ts`) and `OutputModifiers`/`ListFilters` interfaces + (lines 43-83 of `src/cli/output-pipeline.ts`). A declarative schema extracts this + into a single structured definition that both documentation and help text consume. + The existing `ReferenceDocConfig` system cannot be used because it sources from + MasterDataset (annotation-derived data), not static constants (ADR-006). + + **Verified by:** Tables match parser definitions, showHelp output matches schema, + sync test catches drift + + @acceptance-criteria @happy-path + Scenario: Generated tables match CLI schema definitions + Given a CLI schema defining global options, output modifiers, and list filters + When the ProcessApiReferenceGenerator runs + Then PROCESS-API-REFERENCE.md contains a Global Options table with all defined flags + And the table includes flag name, short alias, description, and default columns + And PROCESS-API-REFERENCE.md contains an Output Modifiers table with all defined modifiers + And PROCESS-API-REFERENCE.md contains a List Filters table with all defined filter keys + + @acceptance-criteria @validation + Scenario: CLI schema stays in sync with parser + Given a CLI schema entry for each flag recognized by parseArgs + When a new flag is added to parseArgs without updating the schema + Then the sync test fails with a mismatch report + And when the schema is updated to include the new flag + Then the sync test passes + + Rule: Narrative prose sections remain manual + + **Invariant:** PROCESS-API.md sections covering "Why Use This", session type + decision tree, workflow recipes, worked examples with expected output, and + "Common Recipes" are not generated. They require editorial judgment and context + that cannot be extracted from code annotations. The document's value comes from + these sections — the generated reference tables are supporting material only. + + **Rationale:** Generated docs without prose context would be a bare options + table — usable as reference but not as a learning resource. The hybrid approach + gives both: accurate tables from code, readable narrative from editorial work. + + **Verified by:** Prose sections identical after regeneration, + Tables updated when CLI schema changes + + @acceptance-criteria @validation + Scenario: Prose sections unchanged after regeneration + Given PROCESS-API.md with narrative sections including "Why Use This" and "Common Recipes" + When the ProcessApiReferenceGenerator runs + Then PROCESS-API.md is not modified by the generator + And only PROCESS-API-REFERENCE.md is created or updated + And PROCESS-API.md contains a link to PROCESS-API-REFERENCE.md in the Output Reference section + + Rule: Standalone generator respects ADR-006 single read model + + **Invariant:** The `ProcessApiReferenceGenerator` imports CLI schema data directly + from `src/cli/cli-schema.ts`. It does NOT inject CLI data into MasterDataset or + consume MasterDataset for table generation. It implements `DocumentGenerator` and + returns `OutputFile[]` via the standard orchestrator write path. + + **Rationale:** ADR-006 establishes MasterDataset as the sole read model for + annotation-sourced data. CLI schema is a static TypeScript constant, not extracted + from annotations. Forcing it through MasterDataset would violate the "no parallel + pipeline" anti-pattern. A standalone generator with its own data source is + architecturally correct. + + **Verified by:** Generator has no MasterDataset import, output file written by orchestrator + + @acceptance-criteria @integration + Scenario: Generator produces complete reference file + Given the ProcessApiReferenceGenerator is registered in the orchestrator + When docs:all runs + Then docs-live/reference/PROCESS-API-REFERENCE.md is created + And the file contains three sections: Global Options, Output Modifiers, List Filters + And each section includes a markdown table with headers and data rows + And inter-table prose (config auto-detection, valid fields, precedence) is included diff --git a/delivery-process/specs/process-state-api-relationship-queries.feature b/delivery-process/specs/process-state-api-relationship-queries.feature index 4a20fc14..a03e7ad5 100644 --- a/delivery-process/specs/process-state-api-relationship-queries.feature +++ b/delivery-process/specs/process-state-api-relationship-queries.feature @@ -1,6 +1,6 @@ @libar-docs @libar-docs-pattern:ProcessStateAPIRelationshipQueries -@libar-docs-status:active +@libar-docs-status:completed @libar-docs-unlock-reason:Relationships-available-via-getPatternRelationships-superseded-by-DataAPIRelationshipGraph @libar-docs-phase:24 @libar-docs-product-area:DataAPI diff --git a/delivery-process/specs/publishing-relocation.feature b/delivery-process/specs/publishing-relocation.feature new file mode 100644 index 00000000..db419b4d --- /dev/null +++ b/delivery-process/specs/publishing-relocation.feature @@ -0,0 +1,154 @@ +@libar-docs +@libar-docs-pattern:PublishingRelocation +@libar-docs-status:completed +@libar-docs-phase:40 +@libar-docs-effort:0.25d +@libar-docs-product-area:Generation +@libar-docs-depends-on:DocsConsolidationStrategy +@libar-docs-business-value:move-maintainer-only-npm-and-ci-publishing-procedures-to-correct-repo-root-audience +@libar-docs-priority:medium +Feature: PUBLISHING.md Relocation to MAINTAINERS.md + + **Problem:** + `docs/PUBLISHING.md` (144 lines) is deployed to libar.dev as part of the `docs/` + directory, but its content is exclusively maintainer-only operational procedure: + npm authentication setup, 2FA workflow, version bump commands (pre-releases, + patch/minor/major), GitHub Actions release configuration, pre-commit and pre-push + hook descriptions, dry-run verification, and post-publish troubleshooting. A + developer or user browsing libar.dev has no use for these procedures — they are + targeted at the one or two people with npm publish access to the `@libar-dev` + organization. Placing maintainer procedures in the user-facing docs/ directory + creates audience misalignment and adds noise to the website. + + **Solution:** + Move the full content of `docs/PUBLISHING.md` into a new `MAINTAINERS.md` file + at the repository root. MAINTAINERS.md is a standard GitHub-visible location for + maintainer guidance — it appears in the repository root alongside CONTRIBUTING.md + and README.md, is findable by maintainers, and is not deployed to the website. + Delete `docs/PUBLISHING.md` after the content is moved. Update `docs/INDEX.md` + to remove all PUBLISHING.md references (3 locations). Update the website content + manifest to remove the dead sync target and add a link rewrite so any existing + cross-references resolve to the GitHub-hosted MAINTAINERS.md. + + **Why It Matters:** + | Benefit | How | + | Correct audience | Maintainers find procedures at the repo root, not buried in website docs | + | Cleaner website | docs/ contains only content useful to package users and developers | + | Standard convention | MAINTAINERS.md is a recognized GitHub repository metadata file | + | Zero information loss | All 144 lines move intact — no content is deleted, only relocated | + + **Design Session Findings (2026-03-05):** + | Finding | Impact | Resolution | + | PUBLISHING.md has zero relative links to other docs | No link rewriting needed in MAINTAINERS.md | Simplifies move to pure copy with header rename | + | Original spec references non-existent Phase 6 | False dependency for INDEX.md cleanup | INDEX.md update is now deliverable #3 of this phase | + | Website manifest maps PUBLISHING.md to /guides/publishing/ | Dead sync target after deletion | Deliverable #4 removes manifest entry | + | docs-live/GENERATION.md references PUBLISHING.md 4 times | Generated content, auto-updated by pnpm docs:all | No manual action needed | + | INDEX.md has 3 PUBLISHING.md references (lines 32, 260-272, 338) | Broken links and stale navigation after deletion | All 3 removed in deliverable #3 | + + **Section Audit (docs/PUBLISHING.md):** + | Section | Lines | Level | + | Publishing Guide (title) | 1 | H1 | + | Prerequisites | 5-9 | H2 | + | Version Strategy | 11-18 | H2 | + | Publishing Workflow | 20-67 | H2 | + | Pre-releases (Recommended for Initial Releases) | 22-36 | H3 | + | Subsequent Pre-releases | 38-44 | H3 | + | Stable Releases | 46-67 | H3 | + | Automated Publishing (GitHub Actions) | 69-85 | H2 | + | Pre-commit and Pre-push Hooks | 87-99 | H2 | + | Pre-commit | 91-95 | H3 | + | Pre-push | 98-99 | H3 | + | Dry Run | 101-109 | H2 | + | Verifying a Published Package | 111-126 | H2 | + | Troubleshooting | 128-144 | H2 | + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | Create MAINTAINERS.md at repo root with all PUBLISHING.md content | complete | MAINTAINERS.md | No | n/a | + | Delete docs/PUBLISHING.md | complete | docs/PUBLISHING.md | No | n/a | + | Remove PUBLISHING.md entries from docs/INDEX.md (lines 32, 260-272, 338) | complete | docs/INDEX.md | No | n/a | + | Remove PUBLISHING.md from website content-manifest.mjs guides array | complete | libar-dev-website/scripts/content-manifest.mjs | No | n/a | + | Add MAINTAINERS.md link rewrite to content-manifest.mjs | complete | libar-dev-website/scripts/content-manifest.mjs | No | n/a | + + Rule: All publishing content moves to MAINTAINERS.md intact + + **Invariant:** MAINTAINERS.md at the repository root contains all 8 H2 sections + previously in docs/PUBLISHING.md: Prerequisites, Version Strategy, Publishing + Workflow (with Pre-releases, Subsequent Pre-releases, and Stable Releases + subsections), Automated Publishing (GitHub Actions), Pre-commit and Pre-push + Hooks, Dry Run, Verifying a Published Package, and Troubleshooting. No content + is summarized, condensed, or omitted during the move. The H1 title changes from + "Publishing Guide" to "Maintainer Guide" to reflect the broader MAINTAINERS.md + convention. PUBLISHING.md contains zero relative links to other docs/ files, so + no link rewriting is required. + + **Rationale:** The relocation is a pure audience-alignment fix, not a content + review. Condensing content during the move would conflate two concerns. The + maintainer procedures are complete and accurate — they simply live in the wrong + location. A faithful copy ensures no institutional knowledge is lost in + translation. + + **Verified by:** MAINTAINERS.md contains all PUBLISHING.md sections, + No content omitted or summarized during relocation + + @acceptance-criteria @happy-path + Scenario: MAINTAINERS.md contains all publishing procedure sections + Given the content of docs/PUBLISHING.md before Phase 40 + When MAINTAINERS.md is created at the repository root + Then MAINTAINERS.md contains the Prerequisites section + And MAINTAINERS.md contains the Version Strategy table + And MAINTAINERS.md contains the Publishing Workflow section with pre-release and stable release commands + And MAINTAINERS.md contains the Automated Publishing section describing the GitHub Actions workflow + And MAINTAINERS.md contains the Dry Run section + And MAINTAINERS.md contains the Verifying a Published Package section + And MAINTAINERS.md contains the Troubleshooting section + + Rule: docs/PUBLISHING.md is deleted after relocation + + **Invariant:** After Phase 40 completes, `docs/PUBLISHING.md` does not exist. + The file is not kept as a redirect stub or summary pointer. MAINTAINERS.md at + the repo root is the sole location for publishing procedures. + + **Rationale:** A deleted file cannot serve the wrong audience. Keeping + docs/PUBLISHING.md as a stub pointing to MAINTAINERS.md would still deploy + a maintainer-only page to the website. The correct fix is deletion, not + redirection. Maintainers navigating to the repo root will find MAINTAINERS.md + via standard GitHub repository conventions. + + **Verified by:** File deleted from docs/, No broken links in retained docs + + @acceptance-criteria @validation + Scenario: docs/PUBLISHING.md is absent after Phase 40 completes + Given Phase 40 (PublishingRelocation) is complete + Then docs/PUBLISHING.md does not exist in the repository + And MAINTAINERS.md exists at the repository root + + Rule: Cross-references and website manifest are updated + + **Invariant:** After Phase 40 completes, docs/INDEX.md contains zero references + to PUBLISHING.md. The 3 locations that previously referenced it are removed: + the Quick Navigation table row (line 32), the Detailed Table of Contents + subsection (lines 260-272), and the Document Roles Summary row (line 338). + The website content manifest no longer includes PUBLISHING.md in the guides + array. A link rewrite entry maps "./PUBLISHING.md" to the GitHub blob URL for + MAINTAINERS.md so any remaining cross-references in other docs resolve correctly + after website deployment. + + **Rationale:** Deleting a file without updating its references creates broken + links in both the docs/ index and the website. The INDEX.md references are + removed entirely (not redirected) because the content is no longer in the docs/ + directory. The website manifest removal prevents a dead sync target. The link + rewrite handles any generated docs that reference PUBLISHING.md — they will + link to the GitHub-hosted MAINTAINERS.md instead of a 404. + + **Verified by:** INDEX.md has zero PUBLISHING.md references, + Website manifest guides array excludes PUBLISHING.md, + Link rewrite maps to MAINTAINERS.md GitHub URL + + @acceptance-criteria @validation + Scenario: INDEX.md and website manifest are updated + Given Phase 40 (PublishingRelocation) is complete + Then docs/INDEX.md Quick Navigation table has no PUBLISHING.md row + And docs/INDEX.md has no "PUBLISHING.md (Lines 1-144)" subsection + And docs/INDEX.md Document Roles Summary has no PUBLISHING.md row diff --git a/delivery-process/specs/readme-rationalization.feature b/delivery-process/specs/readme-rationalization.feature new file mode 100644 index 00000000..115bfdce --- /dev/null +++ b/delivery-process/specs/readme-rationalization.feature @@ -0,0 +1,158 @@ +@libar-docs +@libar-docs-pattern:ReadmeRationalization +@libar-docs-status:completed +@libar-docs-phase:42 +@libar-docs-effort:0.5d +@libar-docs-product-area:Generation +@libar-docs-depends-on:DocsConsolidationStrategy +@libar-docs-business-value:focused-npm-landing-page +@libar-docs-priority:medium +Feature: README Rationalization + + **Problem:** + `README.md` is 504 lines and serves three different audiences in one document: + (a) npm package consumers who need installation, quick start, and CLI commands (~150 lines -- keep), + (b) enterprise pitch content -- "Proven at Scale", comparison table, "How It Compares" -- better + suited for the libar.dev website where it can be formatted properly and kept up to date, + (c) configuration reference (lines 440-474) that duplicates docs/CONFIGURATION.md with identical + preset tables and code examples. + + Mixing these concerns produces a README that is too long for npm discovery, too shallow for + enterprise evaluation, and redundant with the configuration doc. npm consumers scanning the + package page are most impacted -- they hit 504 lines before finding the install command. + + **Solution:** + Trim README.md from 504 lines to approximately 150 lines, keeping only the npm-appropriate + content: badges, one-paragraph value proposition, install instructions, quick start (annotate, + generate, enforce), one annotated code example, content block summary table, CLI command table, + and a documentation index. Enterprise pitch sections are already fully covered by 9 website + landing page components (Metrics.astro, Pillars.astro, DataAPI.astro, Workflows.astro, + CodeExamples.astro, Pipeline.astro, Hero.astro, McpCallout.astro, FooterCta.astro). Remove the + Configuration section entirely -- it duplicates docs/CONFIGURATION.md. + + **Why It Matters:** + | Benefit | How | + | Faster npm discovery | 150-line README places install within first 20 lines | + | No configuration duplication | Single source of truth in docs/CONFIGURATION.md | + | Better getting-started page | Trimmed README aligns with /delivery-process/getting-started/ URL | + | Zero content loss | All enterprise pitch content already lives on the website | + + **Section Disposition (18 sections):** + | Section | Lines | Range | Action | Target | Rationale | + | Title + badges | 15 | 1-15 | KEEP | 12 | Essential npm identity | + | Why This Exists | 15 | 17-31 | TRIM | 6 | Keep thesis paragraph, remove comparison table | + | Built for AI-Assisted Development | 17 | 33-49 | REMOVE | 0 | Website DataAPI.astro + CodeExamples.astro | + | Quick Start | 57 | 52-108 | TRIM | 45 | Core npm content, trim tag prefix note | + | How It Works | 54 | 111-164 | TRIM | 20 | Keep one TS example + pipeline one-liner | + | What Gets Generated | 17 | 167-183 | TRIM | 10 | Keep content block table, remove prose | + | CLI Commands | 68 | 186-253 | TRIM | 25 | Keep command table, remove flags + deprecated | + | Proven at Scale | 47 | 256-302 | EXTRACT | 0 | Identical to Metrics.astro | + | FSM-Enforced Workflow | 32 | 305-336 | EXTRACT | 0 | Pillars.astro + Workflows.astro | + | Data API CLI | 26 | 339-364 | EXTRACT | 0 | DataAPI.astro (richer interactive demo) | + | Rich Relationship Model | 23 | 367-389 | EXTRACT | 0 | Pillars.astro pillar 04 | + | How It Compares | 21 | 392-412 | EXTRACT | 0 | No npm equivalent needed | + | Design-First Development | 4 | 416-419 | REMOVE | 0 | Pointer to METHODOLOGY.md already in doc index | + | Document Durability Model | 4 | 422-425 | REMOVE | 0 | Pointer to METHODOLOGY.md already in doc index | + | Use Cases | 11 | 428-438 | REMOVE | 0 | Covered by Quick Start + website | + | Configuration | 34 | 441-474 | REMOVE | 0 | Exact duplicate of docs/CONFIGURATION.md | + | Documentation | 23 | 477-499 | TRIM | 15 | Merge two tables into one, remove self-reference | + | License | 3 | 502-504 | KEEP | 3 | Required | + + Line count math: KEEP (15) + TRIM (121) + separators (6) = ~142 lines. + + **Design Findings:** + | Finding | Impact | Resolution | + | Website has 9 landing components, not only Hero | No content creation needed -- extraction is deletion | Deliverable 3 becomes mapping doc, not content brief | + | Metrics.astro has identical Proven at Scale claims | Section 8 (47 lines) is 100% redundant | Safe EXTRACT with zero information loss | + | Pillars.astro covers FSM, dual-source, relationships | Sections 9, 11, 12 redundant with website | Safe EXTRACT | + | generate-docs flags table duplicates --help output | CLI section is 68 lines but only command table is unique | Trim flags table, retain command summary only | + | INDEX.md line 22 references README as 1-504 | Stale line count after trim | Add deliverable 5 for INDEX.md update | + | README maps to /getting-started/ via content-manifest.mjs | Trimmed README is better getting-started page | No manifest change needed, add Rule 3 | + | Line 93 Configuration anchor breaks when section removed | Internal link to deleted section | Replace with docs/CONFIGURATION.md link | + + **README-to-Website Component Mapping:** + | README Section (EXTRACT) | Website Component | Coverage | + | Proven at Scale (S8, lines 256-302) | Metrics.astro | Identical: 5x throughput, 50-65% context, 0 ESLint | + | FSM-Enforced Workflow (S9, lines 305-336) | Pillars.astro pillar 02 + Workflows.astro | FSM concept + session patterns | + | Data API CLI (S10, lines 339-364) | DataAPI.astro | Three-tab interactive demo, richer than README | + | Rich Relationship Model (S11, lines 367-389) | Pillars.astro pillar 04 | Relationship tags + Mermaid diagrams | + | How It Compares (S12, lines 392-412) | Pillars.astro (implicit) | Four pillars position against competitors | + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | Trim README.md to ~150 lines per section disposition table | complete | README.md | No | n/a | + | Remove Configuration section (lines 441-474) duplicating docs/CONFIGURATION.md | complete | README.md | No | n/a | + | Document README-to-website component mapping for extracted enterprise sections | complete | delivery-process/specs/readme-rationalization.feature | No | n/a | + | Verify all retained links in trimmed README resolve to valid targets | complete | README.md | No | n/a | + | Update INDEX.md Quick Navigation line count for README (1-504 to ~1-150) | complete | docs/INDEX.md | No | n/a | + | Verify trimmed README serves as effective getting-started page at /getting-started/ | complete | README.md | No | n/a | + + Rule: README must be an npm package landing page + + **Invariant:** README.md content is scoped to what an npm package consumer needs: title and badges, + one-paragraph value proposition, install instructions, quick start (annotate, generate, enforce), + one annotated code example, content block summary table, CLI command table, and documentation index. + + **Rationale:** npm package pages are scanned by developers evaluating installation decisions. + Content above 150-200 lines increases time-to-value. Enterprise pitch content (benchmark tables, + methodology comparisons, session workflows, relationship models, comparison matrices) is not + actionable at install time and belongs on the project website where it receives proper formatting, + navigation, and updates without coupling to the package release cycle. The libar.dev website + already contains 9 landing page components covering all enterprise pitch content: Metrics.astro + (Proven at Scale), Pillars.astro (FSM, dual-source, relationships, codecs), DataAPI.astro + (Data API CLI), Workflows.astro (session types), CodeExamples.astro (annotation examples), + and Pipeline.astro (four-stage pipeline). + + **Verified by:** Trimmed README contains only npm-appropriate sections per disposition table + + @acceptance-criteria @happy-path + Scenario: Trimmed README contains only npm-appropriate sections per disposition table + Given README.md is 504 lines mixing npm content, enterprise pitch, and configuration reference + When the rationalization is complete + Then README.md is approximately 150 lines + And it contains these sections: Title, Why This Exists, Quick Start, How It Works, What Gets Generated, CLI Commands, Documentation, License + And it does not contain these sections: Built for AI-Assisted Development, Proven at Scale, FSM-Enforced Workflow, Data API CLI, Rich Relationship Model, How It Compares, Design-First Development, Document Durability Model, Use Cases, Configuration + + Rule: Configuration reference must not be duplicated in README + + **Invariant:** docs/CONFIGURATION.md is the single source of truth for preset and tag configuration. + + **Rationale:** README.md lines 441-474 reproduce the exact same preset table and config code + examples that appear in docs/CONFIGURATION.md. Duplicate reference content diverges over time + -- when a new preset is added, both files require updates. Removing the README copy and pointing + to CONFIGURATION.md eliminates the divergence risk and removes approximately 34 lines from the + README with no loss of information. + + **Verified by:** README references docs/CONFIGURATION.md instead of duplicating config content + + @acceptance-criteria @happy-path + Scenario: README references docs/CONFIGURATION.md instead of duplicating config content + Given README.md contains a Configuration section that duplicates docs/CONFIGURATION.md + When the rationalization is complete + Then README.md does not contain a Configuration code block or preset table + And README.md contains a link to docs/CONFIGURATION.md in the documentation index + And docs/CONFIGURATION.md remains unchanged as the authoritative configuration reference + + Rule: Trimmed README must serve as an effective getting-started page + + **Invariant:** The website publishes README.md as /delivery-process/getting-started/ via + content-manifest.mjs (line 57). After trimming, the remaining content must serve a first-time + visitor arriving at that URL: install instructions, a quick annotated code example, CLI commands + to run, and navigation links to deeper documentation. + + **Rationale:** The current 504-line README is a poor getting-started page because the install + command is buried after 50+ lines of marketing content. The trimmed 150-line version places + install instructions within the first 20 lines and follows with practical steps -- this is a + better getting-started experience than the current version. No manifest changes are needed; + the trim improves alignment with the URL. + + **Verified by:** Trimmed README has install instructions within first 20 lines and links to all guide documents + + @acceptance-criteria @happy-path + Scenario: Trimmed README has install instructions within first 20 lines and links to all guide documents + Given the website publishes README.md as /delivery-process/getting-started/ + When the rationalization is complete + Then install instructions appear within the first 20 lines of README.md + And Quick Start steps cover annotate, generate, and enforce + And the Documentation section links to CONFIGURATION.md, METHODOLOGY.md, ARCHITECTURE.md, SESSION-GUIDES.md, GHERKIN-PATTERNS.md, PROCESS-GUARD.md, VALIDATION.md, PROCESS-API.md, and TAXONOMY.md diff --git a/delivery-process/specs/reference-doc-showcase.feature b/delivery-process/specs/reference-doc-showcase.feature index 259edf63..4a4602d7 100644 --- a/delivery-process/specs/reference-doc-showcase.feature +++ b/delivery-process/specs/reference-doc-showcase.feature @@ -1,6 +1,6 @@ @libar-docs @libar-docs-pattern:ReferenceDocShowcase -@libar-docs-status:active +@libar-docs-status:completed @libar-docs-phase:30 @libar-docs-effort:13d @libar-docs-product-area:Generation diff --git a/delivery-process/specs/session-guides-module-source.feature b/delivery-process/specs/session-guides-module-source.feature new file mode 100644 index 00000000..34eaa8f7 --- /dev/null +++ b/delivery-process/specs/session-guides-module-source.feature @@ -0,0 +1,353 @@ +@libar-docs +@libar-docs-pattern:SessionGuidesModuleSource +@libar-docs-status:completed +@libar-docs-unlock-reason:Add-include-tag-for-ProceduralGuideCodec +@libar-docs-phase:39 +@libar-docs-effort:0.5d +@libar-docs-product-area:Generation +@libar-docs-depends-on:ClaudeModuleGeneration,DocsConsolidationStrategy +@libar-docs-business-value:session-workflow-CLAUDE-md-section-generated-from-annotated-specs +@libar-docs-priority:medium +@libar-docs-claude-module:session-workflows +@libar-docs-claude-section:workflow +@libar-docs-claude-tags:core +@libar-docs-include:session-workflows +Feature: Session Guides as Annotated Module Source + + **Problem:** + CLAUDE.md contains a "Session Workflows" section (~160 lines) that is hand-maintained + with no link to any annotated source. Three hand-written files in `_claude-md/workflow/` + (session-workflows.md, session-details.md, fsm-handoff.md) are equally opaque: no + machine-readable origin, no regeneration from source annotations. + + The prior plan proposed tagging ADR-001, ADR-003, and PDR-001 with `@libar-docs-claude-module` + to make them the source for generated workflow modules. Design analysis revealed this is + fundamentally flawed: `claude-module` is a file-level tag that pulls ALL Rules from a file, + but most Rules in those decision specs are irrelevant to session workflows (ADR-001 has 9 + Rules, only 2-3 are workflow-relevant; PDR-001 has 7 Rules about CLI implementation + decisions, not workflow guidance). + + **Solution:** + This spec file itself becomes the annotated source for session workflow content. + Session workflow invariants are captured as Rule: blocks here, covering session type + contracts, FSM protection, execution order, error recovery, and handoff patterns. + + Once ClaudeModuleGeneration (Phase 25) ships, adding `@libar-docs-claude-module` and + `@libar-docs-claude-section:workflow` tags to this spec will cause the codec to produce + `_claude-md/workflow/` modules automatically. The hand-written files are then deleted + and the CLAUDE.md section becomes a generated include. + + Retain `docs/SESSION-GUIDES.md` (389 lines) as the authoritative public human reference + deployed to libar.dev. It serves developers with comprehensive checklists and full CLI + examples — content that cannot be expressed as compact invariants. + + Three-layer architecture after Phase 39: + + | Layer | Location | Content | Maintenance | + | Public human reference | docs/SESSION-GUIDES.md | Full checklists, CLI examples, decision trees | Manual (editorial) | + | Compact AI context | _claude-md/workflow/ | Invariants, session contracts, FSM reference | Generated from this spec | + | Machine-queryable source | Process Data API | Rules from this spec via `rules` command | Derived from annotations | + + **Why It Matters:** + | Benefit | How | + | No CLAUDE.md drift | Session workflow section generated, not hand-authored | + | Single annotated source | This spec owns all session workflow invariants | + | Correct audience alignment | Public guide stays in docs/, AI context in _claude-md/ | + | Process API coverage | Session workflow content queryable via `pnpm process:query -- rules` | + | Immediately useful | Rule: blocks are queryable today, generation follows when Phase 25 ships | + + **Design Session Findings (2026-03-05):** + | Finding | Impact | + | claude-module is file-level, not Rule-level | Cannot selectively tag individual Rules in ADR/PDR files | + | ADR-001 has 9 Rules, only 2-3 workflow-relevant | Tagging ADR-001 would create noisy, diluted context | + | PDR-001 Rules are CLI implementation decisions | Not session workflow guidance, wrong audience | + | Phase 25 claude-section enum lacks workflow value | Must add workflow to enum before annotation | + | Self-referential spec is correct source | This spec captures invariants, SESSION-GUIDES.md has editorial content | + + Background: Deliverables + Given the following deliverables: + | Deliverable | Status | Location | Tests | Test Type | + | Session workflow behavior spec with Rule blocks (session types, FSM contracts, escape hatches, handoff) | complete | delivery-process/specs/session-guides-module-source.feature | No | n/a | + | Verify SESSION-GUIDES.md retained with correct INDEX.md links | complete | docs/SESSION-GUIDES.md | No | n/a | + | Add workflow to Phase 25 claude-section enum | complete | delivery-process/specs/claude-module-generation.feature | No | n/a | + | Add claude-module and claude-section:workflow tags to this spec | complete | delivery-process/specs/session-guides-module-source.feature | No | n/a | + | Generated _claude-md/workflow/session-workflows.md replaces hand-written version | complete | _claude-md/workflow/session-workflows.md | No | n/a | + | Generated _claude-md/workflow/fsm-handoff.md replaces hand-written version | complete | _claude-md/workflow/fsm-handoff.md | No | n/a | + | CLAUDE.md Session Workflows section replaced with modular-claude-md include | complete | CLAUDE.md | No | n/a | + + # =========================================================================== + # RULE 1: SESSION-GUIDES.MD IS THE PUBLIC HUMAN REFERENCE + # =========================================================================== + + Rule: SESSION-GUIDES.md is the authoritative public human reference + + **Invariant:** `docs/SESSION-GUIDES.md` exists and is not deleted, shortened, or + replaced with a redirect. Its comprehensive checklists, CLI command examples, and + session decision trees serve developers on libar.dev. + + **Rationale:** Session workflow guidance requires two formats for two audiences. + Public developers need comprehensive checklists with full examples. AI sessions + need compact invariants they can apply without reading 389 lines. + + **Verified by:** SESSION-GUIDES.md exists after Phase 39, + No broken links after Phase 39 + + @acceptance-criteria @happy-path + Scenario: SESSION-GUIDES.md exists after Phase 39 completes + Given Phase 39 (SessionGuidesModuleSource) is complete + Then docs/SESSION-GUIDES.md exists in the repository + And docs/INDEX.md contains a link to SESSION-GUIDES.md + And SESSION-GUIDES.md contains no fewer lines than it did before Phase 39 + + @acceptance-criteria @validation + Scenario: No broken links after Phase 39 + Given Phase 39 (SessionGuidesModuleSource) is complete + Then no retained file in docs/ contains a broken link to a deleted file + And docs/INDEX.md navigation is consistent with docs/ directory contents + + # =========================================================================== + # RULE 2: CLAUDE.MD SESSION CONTENT IS DERIVED + # =========================================================================== + + Rule: CLAUDE.md session workflow content is derived, not hand-authored + + **Invariant:** After Phase 39 generation deliverables complete, the "Session + Workflows" section in CLAUDE.md contains no manually-authored content. It is + composed from generated `_claude-md/workflow/` modules. + + **Rationale:** A hand-maintained CLAUDE.md session section creates two copies of + session workflow guidance with no synchronization mechanism. Regeneration from + annotated source eliminates drift. + + **Verified by:** CLAUDE.md session section is a generated module reference + + @acceptance-criteria @happy-path + Scenario: CLAUDE.md session section is a generated module reference + Given Phase 39 generation deliverables are complete + When inspecting CLAUDE.md under the Session Workflows heading + Then the section contains a modular-claude-md include reference to the generated module + And the section contains no manually-authored do/do-not tables or checklist steps + + # =========================================================================== + # RULE 3: SESSION TYPE DETERMINES ARTIFACTS AND FSM CHANGES + # =========================================================================== + + Rule: Session type determines artifacts and FSM changes + + **Invariant:** Four session types exist, each with defined input, output, and + FSM impact. Mixing outputs across session types (e.g., writing code in a planning + session) violates session discipline. + + **Rationale:** Session type confusion causes wasted work — a design mistake + discovered mid-implementation wastes the entire session. Clear contracts prevent + scope bleeding between session types. + + **Verified by:** Session type contracts are enforced + + | Session | Input | Output | FSM Change | + | Planning | Pattern brief | Roadmap spec (.feature) | Creates roadmap | + | Design | Complex requirement | Decision specs + code stubs | None | + | Implementation | Roadmap spec | Code + tests | roadmap to active to completed | + | Planning + Design | Pattern brief | Spec + stubs | Creates roadmap | + + @acceptance-criteria @happy-path + Scenario: Session type contracts are enforced + Given a planning session is active + Then the session produces only a roadmap spec + And no TypeScript implementation code is created + And the FSM status is set to roadmap + + # =========================================================================== + # RULE 4: PLANNING SESSIONS PRODUCE SPECS ONLY + # =========================================================================== + + Rule: Planning sessions produce roadmap specs only + + **Invariant:** A planning session creates a roadmap spec with metadata, deliverables + table, Rule: blocks with invariants, and scenarios. It must not produce implementation + code, transition to active, or prompt for implementation readiness. + + **Rationale:** Planning is the cheapest session type — it produces .feature file + edits, no compilation needed. Mixing implementation into planning defeats the cost + advantage and introduces untested code without a locked scope. + + **Verified by:** Planning session output constraints + + | Do | Do NOT | + | Extract metadata from pattern brief | Create .ts implementation | + | Create spec file with proper tags | Transition to active | + | Add deliverables table in Background | Ask Ready to implement | + | Convert constraints to Rule: blocks | Write full implementations | + | Add scenarios: 1 happy-path + 1 validation per Rule | | + + @acceptance-criteria @happy-path + Scenario: Planning session output constraints + Given a planning session for a new pattern + When the session completes + Then a .feature file exists with libar-docs-status:roadmap + And the file contains a Background with deliverables table + And no .ts files were created in src/ + + # =========================================================================== + # RULE 5: DESIGN SESSIONS PRODUCE DECISIONS AND STUBS + # =========================================================================== + + Rule: Design sessions produce decisions and stubs only + + **Invariant:** A design session makes architectural decisions and creates code stubs + with interfaces. It must not produce implementation code. Context gathering via the + Process Data API must precede any explore agent usage. + + **Rationale:** Design sessions resolve ambiguity before implementation begins. Code + stubs in delivery-process/stubs/ live outside src/ to avoid TypeScript compilation + and ESLint issues, making them zero-risk artifacts. + + **Verified by:** Design session output constraints + + | Use Design Session | Skip Design Session | + | Multiple valid approaches | Single obvious path | + | New patterns/capabilities | Bug fix | + | Cross-context coordination | Clear requirements | + + @acceptance-criteria @happy-path + Scenario: Design session output constraints + Given a design session for a pattern with multiple valid approaches + When the session completes + Then code stubs exist in delivery-process/stubs/ + And no implementation code was written in src/ + And decision rationale is captured in Rule: blocks + + # =========================================================================== + # RULE 6: IMPLEMENTATION FOLLOWS FSM-ENFORCED EXECUTION ORDER + # =========================================================================== + + Rule: Implementation sessions follow FSM-enforced execution order + + **Invariant:** Implementation sessions must follow a strict 5-step execution order. + Transition to active must happen before any code changes. Transition to completed + must happen only when ALL deliverables are done. Skipping steps causes Process Guard + rejection at commit time. + + **Rationale:** The execution order ensures FSM state accurately reflects work state + at every point. Writing code before transitioning to active means Process Guard + sees changes to a roadmap spec (no scope protection). Marking completed with + incomplete work creates a hard-locked state that requires unlock-reason to fix. + + **Verified by:** Implementation execution order is enforced + + Execution order: + 1. Transition to active FIRST (before any code changes) + 2. Create executable spec stubs (if libar-docs-executable-specs present) + 3. For each deliverable: implement, test, update status to complete + 4. Transition to completed (only when ALL deliverables done) + 5. Regenerate docs: pnpm docs:all + + | Do NOT | Why | + | Add new deliverables to active spec | Scope-locked state prevents scope creep | + | Mark completed with incomplete work | Hard-locked state cannot be undone | + | Skip FSM transitions | Process Guard will reject | + | Edit generated docs directly | Regenerate from source | + + @acceptance-criteria @happy-path + Scenario: Implementation execution order is enforced + Given an implementation session for a roadmap pattern + When the session begins + Then the first action is transitioning status to active + And code changes follow the FSM transition + And completed is only set after all deliverables are done + + # =========================================================================== + # RULE 7: FSM ERRORS HAVE DOCUMENTED FIXES + # =========================================================================== + + Rule: FSM errors have documented fixes + + **Invariant:** Every Process Guard error code has a defined cause and fix. The + error codes, causes, and fixes form a closed set — no undocumented error states + exist. + + **Rationale:** Undocumented FSM errors cause session-blocking confusion. A lookup + table from error code to fix eliminates guesswork and prevents workarounds that + bypass process integrity. + + **Verified by:** All FSM errors have documented recovery paths + + | Error | Cause | Fix | + | completed-protection | File has completed status but no unlock tag | Add libar-docs-unlock-reason tag | + | invalid-status-transition | Skipped FSM state (e.g., roadmap to completed) | Follow path: roadmap to active to completed | + | scope-creep | Added deliverable to active spec | Remove deliverable OR revert to roadmap | + | session-scope (warning) | Modified file outside session scope | Add to scope OR use --ignore-session | + | session-excluded | Modified excluded pattern during session | Remove from exclusion OR override | + + Escape hatches for exceptional situations: + + | Situation | Solution | Example | + | Fix bug in completed spec | Add unlock reason tag | libar-docs-unlock-reason:Fix-typo | + | Modify outside session scope | Use ignore flag | lint-process --staged --ignore-session | + | CI treats warnings as errors | Use strict flag | lint-process --all --strict | + + @acceptance-criteria @happy-path + Scenario: All FSM errors have documented recovery paths + Given Process Guard reports a validation error + Then the error code appears in the FSM error reference table + And the table entry includes both cause and fix + + # =========================================================================== + # RULE 8: HANDOFF CAPTURES SESSION-END STATE + # =========================================================================== + + Rule: Handoff captures session-end state for continuity + + **Invariant:** Multi-session work requires handoff documentation generated from + the Process Data API. Handoff output always reflects actual annotation state, + not manual notes. + + **Rationale:** Manual session notes drift from actual deliverable state. The + handoff command derives state from annotations, ensuring the next session starts + from ground truth rather than stale notes. + + **Verified by:** Handoff output reflects annotation state + + Generate handoff via: pnpm process:query -- handoff --pattern PatternName + Options: --git (include recent commits), --session (session identifier) + + Output includes: deliverable statuses, blockers, modification date, and next + steps — all derived from current annotation state. + + @acceptance-criteria @happy-path + Scenario: Handoff output reflects annotation state + Given a multi-session implementation with 3 deliverables + When running the handoff command after completing 2 deliverables + Then the output shows 2 complete and 1 pending + And the output reflects the current annotation state, not manual notes + + # =========================================================================== + # RULE 9: CLAUDE MODULE GENERATION IS THE MECHANISM (DEFERRED) + # =========================================================================== + + Rule: ClaudeModuleGeneration is the generation mechanism + + **Invariant:** Phase 39 depends on ClaudeModuleGeneration (Phase 25). Adding + `@libar-docs-claude-module` and `@libar-docs-claude-section:workflow` tags to + this spec will cause ClaudeModuleGeneration to produce `_claude-md/workflow/` + output files. The hand-written `_claude-md/workflow/` files are deleted after + successful verified generation. + + **Rationale:** The annotation work (Rule blocks in this spec) is immediately + useful — queryable via `pnpm process:query -- rules`. Generation deliverables + cannot complete until Phase 25 ships the ClaudeModuleCodec. This sequencing is + intentional: the annotation investment has standalone value regardless of + whether the codec exists yet. + + **Prerequisite:** Phase 25 must add `workflow` to the `claude-section` enum + values (currently: core, delivery-process, testing, infrastructure). + + **Verified by:** Generated modules replace hand-written workflow files + + @acceptance-criteria @happy-path + Scenario: Generated modules replace hand-written workflow files + Given ClaudeModuleGeneration (Phase 25) is complete + And this spec is annotated with claude-module and claude-section tags + When running pnpm docs:claude-modules + Then _claude-md/workflow/ contains generated files derived from this spec + And the generated files replace the prior hand-written versions diff --git a/delivery-process/specs/step-lint-vitest-cucumber.feature b/delivery-process/specs/step-lint-vitest-cucumber.feature index 020c2fc1..4f6f4177 100644 --- a/delivery-process/specs/step-lint-vitest-cucumber.feature +++ b/delivery-process/specs/step-lint-vitest-cucumber.feature @@ -1,6 +1,6 @@ @libar-docs @libar-docs-pattern:StepLintVitestCucumber -@libar-docs-status:active +@libar-docs-status:completed @libar-docs-phase:50 @libar-docs-effort:1d @libar-docs-product-area:Validation diff --git a/delivery-process/stubs/cli-recipe-codec/cli-recipe-generator.ts b/delivery-process/stubs/cli-recipe-codec/cli-recipe-generator.ts new file mode 100644 index 00000000..60d08505 --- /dev/null +++ b/delivery-process/stubs/cli-recipe-codec/cli-recipe-generator.ts @@ -0,0 +1,310 @@ +/** + * @libar-docs + * @libar-docs-status roadmap + * @libar-docs-implements CliRecipeCodec + * @libar-docs-target src/generators/built-in/cli-recipe-generator.ts + * + * ## CliRecipeGenerator — Standalone Generator for CLI Recipes and Narratives + * + * Produces `docs-live/reference/PROCESS-API-RECIPES.md` from the declarative + * CLI schema. Sibling to `ProcessApiReferenceGenerator` — both implement + * `DocumentGenerator`, both consume `CLI_SCHEMA` directly, neither depends + * on MasterDataset (ADR-006 compliant). + * + * **Design Decision DD-1 (Separate generator, not extension):** + * Reference tables and recipe guides serve different audiences and change at + * different cadences. Reference tables change when CLI flags are added or + * removed. Recipes change when workflow recommendations evolve. Coupling + * them in one generator would force both to change together. + * `ProcessApiReferenceGenerator` is already completed and tested (Phase 43) — + * extending it risks regressions. Two small standalone generators are easier + * to test and maintain than one large one. + * + * **Design Decision DD-2 (Schema-sourced content):** + * Recipe definitions and command narratives live in `CLI_SCHEMA` as structured + * data (see `recipe-schema.ts` for type definitions). The generator reads + * these fields and transforms them to `SectionBlock[]` using the renderable + * schema block builders. No domain knowledge is hardcoded in the generator. + * + * **Design Decision DD-3 (Preamble mechanism for editorial prose):** + * Editorial content ("Why Use This", Quick Start, session decision tree) is + * passed via a `preamble` field in the generator's config — an array of + * `SectionBlock[]` that is prepended before all generated content. This + * follows the proven pattern from `ReferenceDocConfig.preamble` and + * `ErrorGuideCodec` design. The preamble is configured in + * `delivery-process.config.ts`, not in the generator source. + * + * **Design Decision DD-5 (No claude-md output):** + * The generator produces only `docs-live/reference/PROCESS-API-RECIPES.md`. + * It does NOT produce `_claude-md/` output because CLAUDE.md already has + * a manually-authored "Data API CLI" section that serves the AI context use + * case. Adding generated claude-md modules would create duplicate content. + * + * ### Output File Structure + * + * The generated `PROCESS-API-RECIPES.md` has this structure: + * + * ``` + * # Process API CLI — Recipes & Workflow Guide + * > Auto-generated from CLI schema. + * + * [Preamble: Why Use This, Quick Start, Session Types] + * --- + * ## Session Workflow Commands ← from commandNarratives[0] + * ### overview ← from CommandNarrative entries + * ### scope-validate + * ... + * --- + * ## Pattern Discovery ← from commandNarratives[1] + * ### status + * ### list + * ... + * --- + * ## Common Recipes ← from recipes[0] + * ### Starting a Session ← from RecipeExample entries + * ### Finding What to Work On + * ... + * ``` + * + * ### Generator Architecture + * + * ``` + * CLI_SCHEMA.recipes → buildRecipeSections() → SectionBlock[] + * CLI_SCHEMA.commandNarratives → buildNarrativeSections() → SectionBlock[] + * config.preamble → prepended as-is → SectionBlock[] + * ↓ + * document() + renderToMarkdown() + * ↓ + * OutputFile { path, content } + * ``` + */ + +// Imports shown for design reference — actual paths resolve during implementation +// import type { DocumentGenerator, GeneratorContext, GeneratorOutput } from '../types.js'; +// import { CLI_SCHEMA } from '../../cli/cli-schema.js'; +// import type { RecipeGroup, CommandNarrativeGroup } from '../../cli/cli-schema.js'; +// import type { SectionBlock } from '../../renderable/schema.js'; +// import { heading, paragraph, code, separator, document } from '../../renderable/schema.js'; +// import { renderToMarkdown } from '../../renderable/render.js'; + +import type { RecipeGroup, CommandNarrativeGroup } from './recipe-schema.js'; + +// ============================================================================= +// Section Building — Recipes +// ============================================================================= + +/** + * Transform a RecipeGroup into SectionBlock[]. + * + * Each RecipeGroup becomes an H2 heading + optional description + recipe entries. + * Each RecipeExample becomes an H3 heading + purpose paragraph + code block. + * If expectedOutput is present, a separate "Example output" code block follows. + */ +function buildRecipeSections(_group: RecipeGroup): unknown[] { + // Implementation transforms RecipeGroup → SectionBlock[] using block builders: + // + // sections.push(heading(2, group.title)); + // if (group.description) sections.push(paragraph(group.description)); + // + // for (const recipe of group.recipes) { + // sections.push(heading(3, recipe.title)); + // sections.push(paragraph(recipe.purpose)); + // + // // Build code block from steps: + // // "pnpm process:query -- overview # project health" + // const codeContent = recipe.steps + // .map(s => s.comment ? `${s.command} # ${s.comment}` : s.command) + // .join('\n'); + // sections.push(code(codeContent, 'bash')); + // + // if (recipe.expectedOutput) { + // sections.push(paragraph('Example output:')); + // sections.push(code(recipe.expectedOutput)); + // } + // } + + throw new Error('CliRecipeCodec not yet implemented - roadmap pattern'); +} + +// ============================================================================= +// Section Building — Command Narratives +// ============================================================================= + +/** + * Transform a CommandNarrativeGroup into SectionBlock[]. + * + * Each group becomes an H2 heading + optional description. + * Each CommandNarrative becomes an H3 heading (command name) + description + * paragraph + usage example code block + optional details + optional output. + */ +function buildNarrativeSections(_group: CommandNarrativeGroup): unknown[] { + // Implementation transforms CommandNarrativeGroup → SectionBlock[] using block builders: + // + // sections.push(heading(2, group.title)); + // if (group.description) sections.push(paragraph(group.description)); + // + // for (const cmd of group.commands) { + // sections.push(heading(3, `\`${cmd.command}\``)); + // sections.push(paragraph(cmd.description)); + // sections.push(code(cmd.usageExample, 'bash')); + // if (cmd.details) sections.push(paragraph(cmd.details)); + // if (cmd.expectedOutput) { + // sections.push(paragraph('Example output:')); + // sections.push(code(cmd.expectedOutput)); + // } + // } + + throw new Error('CliRecipeCodec not yet implemented - roadmap pattern'); +} + +// ============================================================================= +// Document Assembly +// ============================================================================= + +/** + * Build the complete recipe document from CLI schema and preamble. + * + * Assembly order: + * 1. Auto-generation notice + * 2. Preamble sections (Why Use This, Quick Start, Session Types) + * 3. Command narrative sections (Session Workflow, Pattern Discovery, etc.) + * 4. Recipe sections (Common Recipes) + * + * @param _preamble - Editorial SectionBlock[] from generator config + */ +function buildRecipeDocument( + _preamble: readonly unknown[] +): string { + // Implementation: + // + // const sections: SectionBlock[] = []; + // + // // 1. Auto-generation notice + // sections.push(paragraph( + // '> Auto-generated from CLI schema. See [CLI Reference](./PROCESS-API-REFERENCE.md) for flag tables.' + // )); + // + // // 2. Preamble (editorial prose) + // if (preamble.length > 0) { + // sections.push(...preamble); + // sections.push(separator()); + // } + // + // // 3. Command narratives from schema + // if (CLI_SCHEMA.commandNarratives) { + // for (const group of CLI_SCHEMA.commandNarratives) { + // sections.push(...buildNarrativeSections(group)); + // sections.push(separator()); + // } + // } + // + // // 4. Recipes from schema + // if (CLI_SCHEMA.recipes) { + // for (const group of CLI_SCHEMA.recipes) { + // sections.push(...buildRecipeSections(group)); + // sections.push(separator()); + // } + // } + // + // const doc = document('Process API CLI - Recipes & Workflow Guide', sections); + // return renderToMarkdown(doc); + + throw new Error('CliRecipeCodec not yet implemented - roadmap pattern'); +} + +// ============================================================================= +// Generator Configuration +// ============================================================================= + +/** + * Configuration for the CliRecipeGenerator. + * + * This is NOT a ReferenceDocConfig — this generator is standalone and does + * not go through the reference codec pipeline. The config shape is minimal: + * just preamble content and output path. + */ +export interface CliRecipeGeneratorConfig { + /** + * Static editorial sections prepended before all generated content. + * Contains "Why Use This", Quick Start example, and session decision tree. + * Configured in delivery-process.config.ts. + */ + readonly preamble: readonly unknown[]; // SectionBlock[] — see src/renderable/schema.ts +} + +// ============================================================================= +// Generator Class +// ============================================================================= + +/** + * Standalone generator producing PROCESS-API-RECIPES.md from CLI schema. + * + * Follows the same pattern as ProcessApiReferenceGenerator: + * - Implements DocumentGenerator interface + * - Consumes CLI_SCHEMA directly (no MasterDataset dependency) + * - Returns OutputFile[] via standard orchestrator write path + * - Registered in delivery-process.config.ts generatorOverrides + * + * Key difference from ProcessApiReferenceGenerator: + * - ProcessApiReferenceGenerator reads CLIOptionGroup → produces flag tables + * - CliRecipeGenerator reads RecipeGroup[] + CommandNarrativeGroup[] → produces recipes + * - Both read from the same CLI_SCHEMA constant + */ +class CliRecipeGeneratorImpl { + readonly name = 'cli-recipe'; + readonly description = 'Generate CLI recipe guide and command narratives from schema'; + + private readonly config: CliRecipeGeneratorConfig; + + constructor(config: CliRecipeGeneratorConfig) { + this.config = config; + } + + generate( + _patterns: readonly unknown[], + _context: unknown + ): Promise<{ files: readonly { path: string; content: string }[] }> { + const content = buildRecipeDocument(this.config.preamble); + + return Promise.resolve({ + files: [ + { + path: 'reference/PROCESS-API-RECIPES.md', + content, + }, + ], + }); + } +} + +/** + * Factory function following the createXxxGenerator() convention. + * + * Called from delivery-process.config.ts or generator registration. + * Receives preamble content from config. + */ +export function createCliRecipeGenerator( + _config: CliRecipeGeneratorConfig +): unknown { + // Returns DocumentGenerator from src/generators/types.ts + throw new Error('CliRecipeCodec not yet implemented - roadmap pattern'); +} + +// ============================================================================= +// Config Registration Example +// ============================================================================= + +/** + * Registration follows the programmatic pattern from codec-generators.ts. + * The generator is registered similarly to createProcessApiReferenceGenerator(). + * + * Output directory override is set in delivery-process.config.ts: + * ```typescript + * generatorOverrides: { + * 'cli-recipe': { outputDirectory: 'docs-live' }, + * } + * ``` + */ + +// Exported only for design stub documentation purposes +export const _recipeExamples = { buildRecipeSections, buildNarrativeSections }; diff --git a/delivery-process/stubs/cli-recipe-codec/recipe-data.ts b/delivery-process/stubs/cli-recipe-codec/recipe-data.ts new file mode 100644 index 00000000..268049a4 --- /dev/null +++ b/delivery-process/stubs/cli-recipe-codec/recipe-data.ts @@ -0,0 +1,270 @@ +/** + * @libar-docs + * @libar-docs-status roadmap + * @libar-docs-implements CliRecipeCodec + * @libar-docs-target src/cli/cli-schema.ts + * + * ## Recipe Data — Example Definitions for CLI_SCHEMA Extension + * + * Demonstrates how recipe content from docs/PROCESS-API.md maps to the + * structured `RecipeGroup[]` and `CommandNarrativeGroup[]` schema types + * defined in `recipe-schema.ts`. + * + * **Content source:** All recipe and narrative content below is extracted from + * the manually-maintained `docs/PROCESS-API.md` (509 lines). During + * implementation, this content moves into `CLI_SCHEMA` in + * `src/cli/cli-schema.ts` and the manual prose sections in PROCESS-API.md + * are replaced with links to the generated file. + * + * **Coverage:** This stub shows 2 of 5 recipe groups and 2 of 6 command + * narratives to validate the schema design. The full implementation will + * include all content from PROCESS-API.md sections: + * + * | PROCESS-API.md Section | Schema Location | Content Type | + * |------------------------|-----------------|--------------| + * | Common Recipes (5 blocks, 42 lines) | `CLI_SCHEMA.recipes` | RecipeGroup[] | + * | Session Workflow Commands (6 cmds, 125 lines) | `CLI_SCHEMA.commandNarratives[0]` | CommandNarrativeGroup | + * | Pattern Discovery (8 cmds, 95 lines) | `CLI_SCHEMA.commandNarratives[1]` | CommandNarrativeGroup | + * | Architecture Queries (11 cmds, 28 lines) | `CLI_SCHEMA.commandNarratives[2]` | CommandNarrativeGroup | + * | Metadata and Inventory (4 cmds, 39 lines) | `CLI_SCHEMA.commandNarratives[3]` | CommandNarrativeGroup | + * | Why Use This (30 lines) | Generator preamble | SectionBlock[] | + * | Quick Start (32 lines) | Generator preamble | SectionBlock[] | + * | Session Types (12 lines) | Generator preamble | SectionBlock[] | + * + * **DD-4 validation:** Each command narrative below carries its description + * and usage example as structured data, not freeform prose. The generator + * renders these fields into markdown without any hardcoded command text. + */ + +import type { + RecipeGroup, + RecipeExample, + RecipeStep, + CommandNarrativeGroup, + CommandNarrative, +} from './recipe-schema.js'; + +// ============================================================================= +// Recipe Group Examples (2 of 5) +// ============================================================================= + +/** + * "Starting a Session" recipe — the recommended 3-command startup sequence. + * + * Source: docs/PROCESS-API.md lines 470-476 (Common Recipes section). + */ +const startingASessionRecipe: RecipeExample = { + title: 'Starting a Session', + purpose: 'The recommended session startup is three commands.', + steps: [ + { + command: 'pnpm process:query -- overview', + comment: 'project health', + }, + { + command: 'pnpm process:query -- scope-validate MyPattern implement', + comment: 'pre-flight', + }, + { + command: 'pnpm process:query -- context MyPattern --session implement', + comment: 'curated context', + }, + ] satisfies readonly RecipeStep[], +}; + +/** + * "Finding What to Work On" recipe — discover available work. + * + * Source: docs/PROCESS-API.md lines 478-484. + */ +const findingWorkRecipe: RecipeExample = { + title: 'Finding What to Work On', + purpose: 'Discover available patterns, blockers, and missing implementations.', + steps: [ + { + command: 'pnpm process:query -- list --status roadmap --names-only', + comment: 'available patterns', + }, + { + command: 'pnpm process:query -- arch blocking', + comment: 'stuck patterns', + }, + { + command: 'pnpm process:query -- stubs --unresolved', + comment: 'missing implementations', + }, + ] satisfies readonly RecipeStep[], +}; + +/** + * Example RecipeGroup composing the two recipe examples above. + * + * During implementation, all 5 recipe groups from PROCESS-API.md are defined: + * 1. Starting a Session + * 2. Finding What to Work On + * 3. Investigating a Pattern + * 4. Design Session Prep + * 5. Ending a Session + */ +const COMMON_RECIPES: RecipeGroup = { + title: 'Common Recipes', + description: 'Frequently-used command sequences for daily workflow.', + recipes: [startingASessionRecipe, findingWorkRecipe], +}; + +// ============================================================================= +// Command Narrative Examples (2 of 6 session workflow commands) +// ============================================================================= + +/** + * Narrative for the `overview` command. + * + * Source: docs/PROCESS-API.md lines 86-91. + */ +const overviewNarrative: CommandNarrative = { + command: 'overview', + description: + 'Executive summary: progress percentage, active phases, blocking patterns, and a CLI cheat sheet.', + usageExample: 'pnpm process:query -- overview', + expectedOutput: [ + '=== PROGRESS ===', + '318 patterns (224 completed, 47 active, 47 planned) = 70%', + '', + '=== ACTIVE PHASES ===', + 'Phase 24: ProcessStateAPIRelationshipQueries (1 active)', + 'Phase 25: DataAPIStubIntegration (1 active)', + '', + '=== BLOCKING ===', + 'StepLintExtendedRules blocked by: StepLintVitestCucumber', + '', + '=== DATA API ===', + 'pnpm process:query -- ', + ' overview, context, scope-validate, dep-tree, list, stubs, files, rules, arch blocking', + ].join('\n'), +}; + +/** + * Narrative for the `scope-validate` command. + * + * Source: docs/PROCESS-API.md lines 94-117. + */ +const scopeValidateNarrative: CommandNarrative = { + command: 'scope-validate', + description: + 'Highest-impact command. Pre-flight readiness check that prevents wasted sessions. Returns a PASS/BLOCKED/WARN verdict covering: dependency completion, deliverable definitions, FSM transition validity, and design decisions.', + usageExample: 'pnpm process:query -- scope-validate MyPattern implement', + details: + 'Checks: dependency completion, deliverable definitions, FSM transition validity, design decisions, executable spec location. Valid session types: `implement`, `design`.', + expectedOutput: [ + '=== SCOPE VALIDATION: DataAPIDesignSessionSupport (implement) ===', + '', + '=== CHECKLIST ===', + '[PASS] Dependencies completed: 2/2 completed', + '[PASS] Deliverables defined: 4 deliverable(s) found', + '[BLOCKED] FSM allows transition: completed -> active is not valid.', + '[WARN] Design decisions recorded: No PDR/AD references found in stubs', + '', + '=== VERDICT ===', + 'BLOCKED: 1 blocker(s) prevent implement session', + ].join('\n'), +}; + +/** + * Example CommandNarrativeGroup for Session Workflow Commands. + * + * During implementation, all 6 session workflow commands are included: + * overview, scope-validate, context, dep-tree, files, handoff. + * + * Additional CommandNarrativeGroups are created for: + * - Pattern Discovery (status, list, search, pattern, stubs, decisions, pdr, rules) + * - Architecture Queries (arch roles, context, layer, neighborhood, compare, coverage, dangling, orphans, blocking) + * - Metadata and Inventory (tags, sources, unannotated, query) + */ +const SESSION_WORKFLOW_NARRATIVES: CommandNarrativeGroup = { + title: 'Session Workflow Commands', + description: + 'These 6 commands output structured text (not JSON). They are designed for terminal reading and AI context consumption.', + commands: [overviewNarrative, scopeValidateNarrative], +}; + +// ============================================================================= +// Preamble Content Example (configured in delivery-process.config.ts) +// ============================================================================= + +/** + * Example preamble sections for the CliRecipeGenerator config. + * + * These are SectionBlock[] that get prepended before generated content. + * During implementation, the full preamble includes: + * + * 1. "Why Use This" — comparison table (CLI vs reading markdown) + * 2. Quick Start — 3-command sequence with example `overview` output + * 3. Session Types — table + decision tree sentence + * + * Source: docs/PROCESS-API.md lines 13-77. + * + * Note: The preamble is configured in delivery-process.config.ts, NOT in + * CLI_SCHEMA. This keeps editorial prose separate from structured command + * metadata and follows the proven pattern from ReferenceDocConfig.preamble. + */ +const EXAMPLE_PREAMBLE = [ + // --- Why Use This --- + { + type: 'heading' as const, + level: 2, + text: 'Why Use This', + }, + { + type: 'paragraph' as const, + text: 'Traditional approach: read generated Markdown, parse it mentally, hope it\'s current. This CLI queries the **same annotated sources** that generate those docs -- in real time, with typed output.', + }, + { + type: 'table' as const, + columns: ['Approach', 'Context Cost', 'Accuracy', 'Speed'], + rows: [ + ['Parse generated Markdown', 'High', 'Snapshot at gen time', 'Slow'], + ['**Data API CLI**', '**Low**', 'Real-time from source', 'Instant'], + ], + }, + { + type: 'paragraph' as const, + text: [ + 'The CLI has two output modes:', + '', + '- **Text commands** (6) -- formatted for terminal reading or AI context. Use `===` section markers for structure.', + '- **JSON commands** (12+) -- wrapped in a `QueryResult` envelope. Pipeable to `jq`.', + ].join('\n'), + }, + + // --- Session Types --- + { + type: 'heading' as const, + level: 2, + text: 'Session Types', + }, + { + type: 'paragraph' as const, + text: 'The `--session` flag tailors output to what you need right now:', + }, + { + type: 'table' as const, + columns: ['Type', 'Includes', 'When to Use'], + rows: [ + ['`planning`', 'Pattern metadata and spec file only', 'Creating a new roadmap spec'], + ['`design`', 'Full: metadata, stubs, deps, deliverables', 'Making architectural decisions'], + ['`implement`', 'Focused: deliverables, FSM state, test files', 'Writing code from an existing spec'], + ], + }, + { + type: 'paragraph' as const, + text: '**Decision tree:** Starting to code? `implement`. Complex decisions? `design`. New pattern? `planning`. Not sure? Run `overview` first.', + }, +] as const; + +// ============================================================================= +// Placeholder +// ============================================================================= + +export function _recipeDataPlaceholder(): never { + throw new Error('CliRecipeCodec not yet implemented - roadmap pattern'); +} diff --git a/delivery-process/stubs/cli-recipe-codec/recipe-schema.ts b/delivery-process/stubs/cli-recipe-codec/recipe-schema.ts new file mode 100644 index 00000000..8d22a524 --- /dev/null +++ b/delivery-process/stubs/cli-recipe-codec/recipe-schema.ts @@ -0,0 +1,219 @@ +/** + * @libar-docs + * @libar-docs-status roadmap + * @libar-docs-implements CliRecipeCodec + * @libar-docs-target src/cli/cli-schema.ts + * + * ## Recipe Schema — Structured Data Model for CLI Recipes + * + * Defines `RecipeGroup`, `RecipeExample`, and `RecipeStep` interfaces that + * extend `CLISchema` with multi-command recipe sequences. + * + * **Design Decision DD-1 (Separate schema extension, not inline per-option):** + * Recipes are multi-command sequences ("run these 3 commands in order") with + * explanatory context. They do not fit into `CLIOptionGroup` which models + * individual flags. A separate `RecipeGroup[]` field on `CLISchema` keeps + * the type system clean — existing `CLIOptionGroup` types are unchanged, + * and recipes are independently testable. + * + * Alternatives considered: + * - (A) Inline recipes in `CLIOptionGroup` — rejected because recipes span + * multiple option groups (e.g., "Starting a Session" uses `overview` + + * `scope-validate` + `context` which span session and global options). + * - (C) Feature file Rule: blocks — rejected because recipe content is + * procedural ("do X then Y"), not behavioral invariants. Feature files + * define what IS true; recipes define what to DO. + * + * **Design Decision DD-3 (Preamble for editorial prose):** + * The "Why Use This" motivation (~30 lines), Quick Start with example output + * (~32 lines), and session type decision tree (~12 lines) use the preamble + * mechanism in generator config, NOT fields in the recipe schema. These are + * editorial prose requiring human judgment, not structured data that can be + * derived from CLI metadata. The preamble mechanism is proven by + * DocsConsolidationStrategy Phase 2 and ErrorGuideCodec design stubs. + * + * **Design Decision DD-4 (Extended descriptions from schema):** + * Narrative command descriptions ("Highest-impact command. Pre-flight readiness + * check...") are sourced from `CommandNarrative` entries in the schema, not + * hardcoded in the generator. Each `CommandNarrative` carries a title, rich + * description, and usage example. This extends the existing `CLIOptionGroup` + * pattern: `CLIOptionGroup.description` carries per-group prose, and + * `CommandNarrative` carries per-command prose. + * + * We chose a separate `CommandNarrative` type rather than extending + * `CLIOptionGroup.description` because: + * - Command groups (Session Workflow, Pattern Discovery, Architecture) contain + * heterogeneous commands that each need their own narrative + * - `CLIOptionGroup` is designed for flag tables, not command catalogs + * - Narrative entries need usage examples (code blocks) which don't fit + * in a single description string + * + * **Design Decision DD-5 (Recipe organization and output format):** + * Recipes are grouped by task intent, not by session type or command name. + * Groups: "Starting a Session", "Finding What to Work On", "Investigating a + * Pattern", "Design Session Prep", "Ending a Session". Each `RecipeExample` + * has a title, purpose string, array of `RecipeStep` (command + comment), + * and optional expected output. This mirrors the existing Common Recipes + * section structure in PROCESS-API.md, ensuring zero information loss. + * + * ### Integration with CLISchema + * + * The existing `CLISchema` interface gains two new fields: + * + * | Field | Type | Purpose | + * |-------|------|---------| + * | `recipes` | `RecipeGroup[]` | Multi-command recipe sequences | + * | `commandNarratives` | `CommandNarrativeGroup[]` | Per-command narrative descriptions | + * + * Both are optional to preserve backward compatibility with existing consumers + * (ProcessApiReferenceGenerator, showHelp). + */ + +// ============================================================================= +// Recipe Schema Types +// ============================================================================= + +/** + * A single step in a recipe — one CLI command with an explanatory comment. + * + * @example + * ```typescript + * const step: RecipeStep = { + * command: 'pnpm process:query -- overview', + * comment: 'project health', + * }; + * ``` + */ +export interface RecipeStep { + /** The CLI command to run */ + readonly command: string; + + /** Short inline comment explaining what this step does */ + readonly comment?: string; +} + +/** + * A complete recipe example — a titled sequence of commands with context. + * + * @example + * ```typescript + * const recipe: RecipeExample = { + * title: 'Starting a Session', + * purpose: 'The recommended session startup is three commands.', + * steps: [ + * { command: 'pnpm process:query -- overview', comment: 'project health' }, + * { command: 'pnpm process:query -- scope-validate MyPattern implement', comment: 'pre-flight' }, + * { command: 'pnpm process:query -- context MyPattern --session implement', comment: 'curated context' }, + * ], + * }; + * ``` + */ +export interface RecipeExample { + /** Recipe title (becomes H3 or H4 heading) */ + readonly title: string; + + /** One-line purpose description rendered before the code block */ + readonly purpose: string; + + /** Ordered sequence of CLI commands */ + readonly steps: readonly RecipeStep[]; + + /** + * Optional expected output block rendered after the commands. + * Static string — no build-time CLI execution. + */ + readonly expectedOutput?: string; +} + +/** + * A group of related recipes under a shared heading. + * + * @example + * ```typescript + * const group: RecipeGroup = { + * title: 'Common Recipes', + * description: 'Frequently-used command sequences for daily workflow.', + * recipes: [startingASession, findingWork], + * }; + * ``` + */ +export interface RecipeGroup { + /** Group heading (becomes H2 heading) */ + readonly title: string; + + /** Optional intro prose rendered below the heading */ + readonly description?: string; + + /** Recipe examples in this group */ + readonly recipes: readonly RecipeExample[]; +} + +// ============================================================================= +// Command Narrative Types +// ============================================================================= + +/** + * Narrative metadata for a single CLI command. + * + * Carries the rich description and usage example that appears in the + * generated recipe file alongside the command. This replaces the manually + * maintained prose in docs/PROCESS-API.md sections like "Session Workflow + * Commands" and "Pattern Discovery". + * + * @example + * ```typescript + * const narrative: CommandNarrative = { + * command: 'scope-validate', + * description: 'Highest-impact command. Pre-flight readiness check that prevents wasted sessions.', + * usageExample: 'pnpm process:query -- scope-validate MyPattern implement', + * details: 'Checks: dependency completion, deliverable definitions, FSM transition validity, design decisions.', + * }; + * ``` + */ +export interface CommandNarrative { + /** Command name (e.g., 'overview', 'scope-validate', 'context') */ + readonly command: string; + + /** Rich narrative description of what this command does and why */ + readonly description: string; + + /** Primary usage example as a CLI command string */ + readonly usageExample: string; + + /** Additional detail text rendered below the usage example */ + readonly details?: string; + + /** Optional expected output block for this command */ + readonly expectedOutput?: string; +} + +/** + * A group of related command narratives under a shared section heading. + * + * Maps to sections like "Session Workflow Commands" (6 text commands) + * and "Pattern Discovery" (8 JSON commands) in docs/PROCESS-API.md. + */ +export interface CommandNarrativeGroup { + /** Section heading (e.g., 'Session Workflow Commands') */ + readonly title: string; + + /** Intro prose for the section */ + readonly description?: string; + + /** Individual command narratives */ + readonly commands: readonly CommandNarrative[]; +} + +// ============================================================================= +// CLISchema Extension +// ============================================================================= + +/** + * CLISchema already includes `recipes` and `commandNarratives` fields + * (added during Phase 43 implementation). See `src/cli/cli-schema.ts` + * for the canonical interface. No separate extended type needed. + */ + +export function _recipeSchemaPlaceholder(): never { + throw new Error('CliRecipeCodec not yet implemented - roadmap pattern'); +} diff --git a/delivery-process/stubs/enhanced-index-generation/index-codec-options.ts b/delivery-process/stubs/enhanced-index-generation/index-codec-options.ts new file mode 100644 index 00000000..6c6b427d --- /dev/null +++ b/delivery-process/stubs/enhanced-index-generation/index-codec-options.ts @@ -0,0 +1,175 @@ +/** + * @libar-docs + * @libar-docs-status completed + * @libar-docs-implements EnhancedIndexGeneration + * @libar-docs-target src/renderable/codecs/index-codec.ts + * + * ## IndexCodecOptions — DD-1, DD-5 Decisions + * + * **Decision DD-1 (New IndexCodec vs extend existing):** Create a new IndexCodec + * registered in CodecRegistry, NOT a standalone generator or extension of the + * current docs-live/INDEX.md (which is a static file, not generated by any code). + * + * **Rationale (DD-1):** The index needs MasterDataset pre-computed views + * (`byProductArea`, `byPhase`, `byStatus`, `byCategory`) to generate statistics. + * Only codecs registered in CodecRegistry receive MasterDataset via the + * `codec.decode(dataset)` pipeline. A standalone generator (like + * ProcessApiReferenceGenerator) would need to wire its own MasterDataset access, + * duplicating what CodecBasedGenerator already provides. The codec approach also + * gets free integration with `generateDocument('index', dataset)`, + * `generateAllDocuments()`, and the `CodecOptions` type-safe options pipeline. + * + * **Decision DD-5 (ReferenceDocConfig vs standalone codec):** Use a standalone + * IndexCodec rather than a ReferenceDocConfig entry. The IndexCodec is registered + * directly in CodecRegistry as document type `'index'`, not routed through the + * reference codec's 4-layer composition pipeline. + * + * **Rationale (DD-5):** ReferenceDocConfig's 4-layer composition (conventions, + * diagrams, shapes, behaviors) is designed for scoped reference documents that + * assemble content from annotated sources. The index document is fundamentally + * different — it is a NAVIGATION document that lists OTHER documents, computes + * cross-cutting statistics from MasterDataset views, and composes them with + * editorial preamble sections. None of the 4 layers apply: + * - No convention tags to extract (the index doesn't document conventions) + * - No scoped diagrams (the index doesn't visualize architecture) + * - No TypeScript shapes (the index doesn't expose API surfaces) + * - No behavior categories (the index doesn't describe behaviors) + * + * However, the IndexCodec DOES reuse the `preamble` concept from + * ReferenceDocConfig — editorial `SectionBlock[]` prepended before generated + * content. This is passed via `IndexCodecOptions.preamble`, not via + * ReferenceDocConfig. The preamble mechanism is a pattern, not a type coupling. + * + * ### Integration Points + * + * | Integration | How | + * |-------------|-----| + * | CodecRegistry | `CodecRegistry.register('index', IndexCodec)` | + * | DOCUMENT_TYPES | Add `index: { outputPath: 'INDEX.md', description: '...' }` | + * | CodecOptions | Add `index?: IndexCodecOptions` to CodecOptions interface | + * | delivery-process.config.ts | Add `generatorOverrides.index.outputDirectory: 'docs-live'` | + * | generateAllDocuments() | Automatically included via DOCUMENT_TYPES iteration | + */ + +import type { SectionBlock } from '../../src/renderable/schema.js'; +import type { BaseCodecOptions } from '../../src/renderable/codecs/types/base.js'; + +// --------------------------------------------------------------------------- +// IndexCodecOptions +// --------------------------------------------------------------------------- + +/** + * Options for the IndexCodec. + * + * Controls which sections appear in the generated index and provides + * the editorial preamble content (audience reading paths, document + * roles matrix, quick finder table). + * + * The codec composes two content types: + * 1. **Auto-generated** — Statistics and document listings from MasterDataset + * 2. **Editorial** — Preamble sections authored in config + * + * This separation follows the same principle as ReferenceDocConfig.preamble + * but is specific to the index document's navigation-focused structure. + */ +export interface IndexCodecOptions extends BaseCodecOptions { + // ─── Editorial Preamble ────────────────────────────────────────────────── + + /** + * Static preamble sections prepended before all generated content. + * + * Expected to contain: + * - Quick navigation table (If you want X, read Y) + * - Audience reading paths (New User, Developer/AI, Team Lead/CI) + * - Document roles matrix (Audience x Document x Focus) + * - Key concepts glossary + * + * These sections require editorial judgment and cannot be derived + * from MasterDataset metadata. + */ + readonly preamble?: readonly SectionBlock[]; + + // ─── Section Visibility Toggles ────────────────────────────────────────── + + /** Include product area statistics table (default: true) */ + readonly includeProductAreaStats?: boolean; + + /** Include phase progress summary with completion percentage (default: true) */ + readonly includePhaseProgress?: boolean; + + /** Include unified document inventory table (default: true) */ + readonly includeDocumentInventory?: boolean; + + /** Include package metadata header (default: true) */ + readonly includePackageMetadata?: boolean; + + // ─── Document Inventory Configuration ──────────────────────────────────── + + /** + * Document entries for the unified inventory. + * + * Each entry describes a document from either docs/ or docs-live/. + * The codec renders this static inventory and combines it with + * statistics derived from MasterDataset views. + * + * Documents are organized by topic, NOT by source directory. + * The reader should not need to know whether a document is manual + * or generated. + */ + readonly documentEntries?: readonly DocumentEntry[]; +} + +/** + * A document entry for the unified inventory. + * + * Describes a single document in the navigation index. + * Used for both manual docs/ and generated docs-live/ documents. + */ +export interface DocumentEntry { + /** Document title (e.g., "Architecture Overview") */ + readonly title: string; + + /** Relative path from project root (e.g., "docs/ARCHITECTURE.md" or "docs-live/PRODUCT-AREAS.md") */ + readonly path: string; + + /** Brief description of what the document covers */ + readonly description: string; + + /** Primary audience for this document */ + readonly audience: 'Everyone' | 'Developers' | 'AI/Devs' | 'Users' | 'Writers' | 'Team Leads' | 'CI/CD' | 'Maintainers' | 'Reference'; + + /** + * Topic category for grouping in the index. + * Documents with the same topic appear in the same section. + */ + readonly topic: string; +} + +// --------------------------------------------------------------------------- +// Default Options +// --------------------------------------------------------------------------- + +/** + * Default options for IndexCodec. + * + * All auto-generated sections are enabled by default. + * Preamble and document entries are empty by default — they must be + * provided via delivery-process.config.ts. + */ +export const DEFAULT_INDEX_OPTIONS: Required> & { + preamble: readonly SectionBlock[]; + documentEntries: readonly DocumentEntry[]; +} = { + generateDetailFiles: false, + detailLevel: 'detailed', + includeProductAreaStats: true, + includePhaseProgress: true, + includeDocumentInventory: true, + includePackageMetadata: true, + preamble: [], + documentEntries: [], +}; + +export function _indexCodecOptionsPlaceholder(): never { + throw new Error('EnhancedIndexGeneration not yet implemented - roadmap pattern'); +} diff --git a/delivery-process/stubs/enhanced-index-generation/index-codec.ts b/delivery-process/stubs/enhanced-index-generation/index-codec.ts new file mode 100644 index 00000000..14f94b9c --- /dev/null +++ b/delivery-process/stubs/enhanced-index-generation/index-codec.ts @@ -0,0 +1,210 @@ +/** + * @libar-docs + * @libar-docs-status completed + * @libar-docs-implements EnhancedIndexGeneration + * @libar-docs-target src/renderable/codecs/index-codec.ts + * + * ## IndexCodec Factory — DD-1 Implementation Stub + * + * Creates the IndexCodec as a Zod codec (MasterDataset -> RenderableDocument). + * Follows the same factory pattern as all other codecs in the system: + * `createIndexCodec(options?) -> DocumentCodec`. + * + * ### Codec Decode Pipeline + * + * ``` + * MasterDataset + * | + * +--> [Package Metadata Header] (optional, from options) + * | + * +--> [Preamble Sections] (editorial, from options.preamble) + * | - Quick Navigation Table + * | - Audience Reading Paths (3) + * | - Document Roles Matrix + * | - Key Concepts Glossary + * | + * +--> [Unified Document Inventory] (merged manual + generated) + * | - Organized by topic + * | - Each entry: title, description, audience, path + * | + * +--> [Product Area Statistics] (auto-generated from byProductArea) + * | - Per-area pattern counts + * | - Totals row + * | + * +--> [Phase Progress Summary] (auto-generated from byStatus) + * | - Status distribution counts + * | - Completion percentage + * | + * +--> [Regeneration Commands] (static footer) + * - pnpm docs:all + * - Individual generator commands + * ``` + * + * ### Key Design Choices + * + * 1. **Preamble first, statistics second.** Reading paths and the quick finder + * table are the most useful navigation aids (per spec Rule 2). Auto-generated + * statistics are supplementary context. This ordering matches how the manual + * INDEX.md is structured. + * + * 2. **Unified document inventory merges manual + generated.** The codec accepts + * `documentEntries` from config (covering both docs/ and docs-live/) and + * does NOT perform filesystem discovery at generation time (DD-2 decision). + * This keeps the codec pure (no I/O) and deterministic. + * + * 3. **Product area stats reuse `computeStatusCounts()`.** The same utility used + * by `buildProductAreaIndex()` in reference-generators.ts. No re-derivation + * from raw patterns (ADR-006). + * + * 4. **No detail files.** The index is a single-page navigation document. + * `generateDetailFiles` defaults to false. + */ + +import type { MasterDataset } from '../../src/validation-schemas/master-dataset.js'; +import type { RenderableDocument, SectionBlock } from '../../src/renderable/schema.js'; +import type { IndexCodecOptions, DocumentEntry } from './index-codec-options.js'; +import type { StatusCounts } from '../../src/api/types.js'; + +// --------------------------------------------------------------------------- +// Codec Factory +// --------------------------------------------------------------------------- + +/** + * Create an IndexCodec with custom options. + * + * The returned codec transforms MasterDataset into a RenderableDocument + * containing the enhanced index. Register in CodecRegistry as: + * + * ```typescript + * CodecRegistry.register('index', createIndexCodec()); + * CodecRegistry.registerFactory('index', createIndexCodec); + * ``` + * + * @param options - IndexCodecOptions with preamble and visibility toggles + * @returns A Zod codec (MasterDataset -> RenderableDocument) + */ +export function createIndexCodec( + _options?: IndexCodecOptions +): unknown { + // DD-1: Registered in CodecRegistry as document type 'index' + // Uses z.codec(MasterDatasetSchema, RenderableDocumentOutputSchema, { decode, encode }) + // pattern identical to OverviewCodec, BusinessRulesCodec, etc. + throw new Error('EnhancedIndexGeneration not yet implemented - roadmap pattern'); +} + +// The real implementation exports: export const IndexCodec = createIndexCodec(); +// See src/renderable/codecs/index-codec.ts for the actual codec. +// IndexCodec is created via createIndexCodec() — not eagerly instantiated in stubs + +// --------------------------------------------------------------------------- +// Document Builder (internal) +// --------------------------------------------------------------------------- + +/** + * Builds the enhanced index RenderableDocument from MasterDataset. + * + * Section ordering: + * 1. Package metadata header (if enabled) + * 2. Preamble sections (editorial: quick nav, reading paths, roles, glossary) + * 3. Unified document inventory (merged manual + generated) + * 4. Product area statistics (from byProductArea view) + * 5. Phase progress summary (from byStatus view) + * 6. Regeneration commands footer + * + * @param dataset - MasterDataset with pre-computed views + * @param options - Resolved IndexCodecOptions + * @returns RenderableDocument for the enhanced index + */ +function buildIndexDocument( + _dataset: MasterDataset, + _options: IndexCodecOptions +): RenderableDocument { + throw new Error('EnhancedIndexGeneration not yet implemented - roadmap pattern'); +} + +// --------------------------------------------------------------------------- +// Section Builders (internal) +// --------------------------------------------------------------------------- + +/** + * Build the unified document inventory section. + * + * Organizes documents by topic, NOT by source directory. + * Each topic becomes a heading with a table of documents. + * + * @param entries - Document entries from config (covers both docs/ and docs-live/) + * @returns SectionBlock[] for the document inventory + */ +function buildDocumentInventory( + _entries: readonly DocumentEntry[] +): SectionBlock[] { + // DD-2: Static config, not filesystem discovery. + // Groups entries by topic, renders each group as: + // ## {Topic} + // | Document | Description | Audience | + // | [title](path) | description | audience | + throw new Error('EnhancedIndexGeneration not yet implemented - roadmap pattern'); +} + +/** + * Build the product area statistics section. + * + * Uses dataset.byProductArea view and computeStatusCounts() to produce + * a table identical in structure to buildProductAreaIndex() in + * reference-generators.ts, but scoped to the index context. + * + * @param dataset - MasterDataset with byProductArea view + * @returns SectionBlock[] for the product area statistics + */ +function buildProductAreaStats( + _dataset: MasterDataset +): SectionBlock[] { + // Reuses computeStatusCounts() from src/renderable/utils.ts + // Produces table: | Area | Patterns | Completed | Active | Planned | + // Plus totals row. Same proven pattern as buildProductAreaIndex(). + throw new Error('EnhancedIndexGeneration not yet implemented - roadmap pattern'); +} + +/** + * Build the phase progress summary section. + * + * Uses dataset.byStatus view to show status distribution and + * completion percentage via completionPercentage() utility. + * + * @param dataset - MasterDataset with byStatus view + * @returns SectionBlock[] for the phase progress summary + */ +function buildPhaseProgress( + _dataset: MasterDataset +): SectionBlock[] { + // Uses dataset.byStatus (StatusGroupsSchema: { roadmap, active, completed, deferred }) + // Renders: "X patterns total: Y completed (Z%), A active, B planned" + // Plus per-phase breakdown from dataset.byPhase if available + throw new Error('EnhancedIndexGeneration not yet implemented - roadmap pattern'); +} + +/** + * Build the regeneration commands footer. + * + * Static section with pnpm commands for regenerating docs. + * + * @returns SectionBlock[] for the regeneration footer + */ +function buildRegenerationFooter(): SectionBlock[] { + // Static content: pnpm docs:all, individual generator commands + // Same content as current docs-live/INDEX.md "Regeneration" section + throw new Error('EnhancedIndexGeneration not yet implemented - roadmap pattern'); +} + +// Suppress unused variable warnings for internal functions +void buildIndexDocument; +void buildDocumentInventory; +void buildProductAreaStats; +void buildPhaseProgress; +void buildRegenerationFooter; + +// Suppress unused import warnings +void (undefined as unknown as MasterDataset); +void (undefined as unknown as SectionBlock); +void (undefined as unknown as DocumentEntry); +void (undefined as unknown as StatusCounts); diff --git a/delivery-process/stubs/enhanced-index-generation/index-preamble-config.ts b/delivery-process/stubs/enhanced-index-generation/index-preamble-config.ts new file mode 100644 index 00000000..c2867154 --- /dev/null +++ b/delivery-process/stubs/enhanced-index-generation/index-preamble-config.ts @@ -0,0 +1,403 @@ +/** + * @libar-docs + * @libar-docs-status completed + * @libar-docs-implements EnhancedIndexGeneration + * @libar-docs-target delivery-process.config.ts + * + * ## Index Preamble Configuration — DD-3, DD-4 Decisions + * + * **Decision DD-3 (Audience paths: preamble vs annotation-derived):** Use full + * preamble for audience reading paths. The reading order within each audience + * profile is editorial judgment — "read this third because it builds on concepts + * from document two" cannot be computed from pattern metadata. + * + * **Rationale (DD-3):** The three audience profiles (New User, Developer/AI, + * Team Lead/CI) and their curated reading sequences are the most-cited + * navigation aid in the existing manual INDEX.md. Each reading path is a + * deliberate pedagogical ordering: foundational concepts first, then + * architecture, then workflow, then enforcement. No annotation can express + * "this document builds on the mental model established by reading METHODOLOGY + * before ARCHITECTURE." The preamble mechanism is designed precisely for this + * case — editorial content that changes at authorial cadence, not code cadence. + * + * **Decision DD-4 (Key concepts: annotation-derived vs preamble):** Use preamble + * for the key concepts glossary. Pattern descriptions are too granular and + * technical to serve as glossary definitions for a navigation document. + * + * **Rationale (DD-4):** A glossary entry for "Delivery Workflow FSM" needs a + * reader-friendly 2-sentence explanation plus an ASCII state diagram. Pattern + * descriptions are structured for MasterDataset consumers (codecs, API queries), + * not for human onboarding. Attempting to derive glossary content from pattern + * metadata would produce entries like "FSM enforcement, pre-commit hooks" — + * accurate but unhelpful for someone encountering the concept for the first + * time. A future `@libar-docs-glossary` annotation type could solve this, but + * it would require a new scanner capability and extraction pipeline. The + * preamble approach works today with zero new infrastructure. + * + * **Decision DD-2 (Merge manual + generated listings):** Document entries are + * configured statically in `documentEntries`, not discovered at generation time. + * The codec is pure (no filesystem I/O) and deterministic. + * + * **Rationale (DD-2):** Filesystem discovery at generation time would couple + * the codec to the filesystem, break deterministic testing, and require + * heuristics to extract titles/descriptions from markdown files. The existing + * docs are a stable, slowly-changing set (~14 manual docs + ~30 generated). + * When a document is added or renamed, updating the config entry is trivial + * and happens at the same time as the document creation. This is the same + * pattern used by `PRODUCT_AREA_META` in reference.ts — manually curated + * metadata for a stable set of entities. + * + * ### Preamble Structure + * + * The preamble composes four editorial sections as `SectionBlock[]`: + * + * | Section | SectionBlock Types | Source | + * |---------|-------------------|--------| + * | Quick Navigation | heading + table | "If you want X, read Y" lookup | + * | Reading Order: New User | heading + paragraph + list | 3-step onboarding path | + * | Reading Order: Developer/AI | heading + paragraph + list | 5-step deep-dive path | + * | Reading Order: Team Lead/CI | heading + paragraph + list | 2-step governance path | + * | Document Roles Matrix | heading + table | Audience x Document x Focus | + * | Key Concepts | heading + paragraphs | Glossary definitions | + * + * ### Config Integration + * + * This preamble is provided via `CodecOptions` in delivery-process.config.ts: + * + * ```typescript + * // In delivery-process.config.ts (future) + * export default defineConfig({ + * // ... existing config ... + * codecOptions: { + * index: { + * preamble: INDEX_PREAMBLE_SECTIONS, + * documentEntries: INDEX_DOCUMENT_ENTRIES, + * }, + * }, + * }); + * ``` + * + * Alternatively, the preamble could be passed via generatorOverrides + * with a custom codec options mechanism, following the pattern used by + * `pr-changes` codec options (changedFiles passed at runtime). + */ + +import type { SectionBlock } from '../../src/renderable/schema.js'; +import type { DocumentEntry } from './index-codec-options.js'; + +// --------------------------------------------------------------------------- +// Example Preamble Sections +// --------------------------------------------------------------------------- + +/** + * Quick navigation table — "If you want X, read Y" lookup. + * + * This is the highest-value section of the index. Users scan this first + * to find the document relevant to their immediate need. + */ +export const QUICK_NAVIGATION_SECTIONS: readonly SectionBlock[] = [ + { + type: 'heading' as const, + level: 2, + text: 'Quick Navigation', + }, + { + type: 'table' as const, + columns: ['If you want to...', 'Read this'], + rows: [ + ['Get started quickly', '[README.md](../README.md)'], + ['Configure presets and tags', '[CONFIGURATION.md](docs/CONFIGURATION.md)'], + ['Understand the "why"', '[METHODOLOGY.md](docs/METHODOLOGY.md)'], + ['Learn the architecture', '[ARCHITECTURE.md](docs/ARCHITECTURE.md)'], + ['Run AI coding sessions', '[SESSION-GUIDES.md](docs/SESSION-GUIDES.md)'], + ['Write Gherkin specs', '[GHERKIN-PATTERNS.md](docs/GHERKIN-PATTERNS.md)'], + ['Enforce delivery process rules', '[PROCESS-GUARD.md](docs/PROCESS-GUARD.md)'], + ['Validate annotation quality', '[VALIDATION.md](docs/VALIDATION.md)'], + ['Query process state via CLI', '[PROCESS-API.md](docs/PROCESS-API.md)'], + ['Browse product area overviews', '[PRODUCT-AREAS.md](docs-live/PRODUCT-AREAS.md)'], + ['Review architecture decisions', '[DECISIONS.md](docs-live/DECISIONS.md)'], + ['Check business rules', '[BUSINESS-RULES.md](docs-live/BUSINESS-RULES.md)'], + ], + }, +]; + +/** + * Audience reading paths — curated sequences for three reader profiles. + * + * DD-3: These are full preamble sections because reading order is + * editorial judgment, not computable from metadata. + */ +export const READING_ORDER_SECTIONS: readonly SectionBlock[] = [ + { + type: 'heading' as const, + level: 2, + text: 'Reading Order', + }, + + // --- New User Path --- + { + type: 'heading' as const, + level: 3, + text: 'For New Users', + }, + { + type: 'paragraph' as const, + text: [ + '1. **[README.md](../README.md)** -- Installation, quick start, Data API CLI overview', + '2. **[CONFIGURATION.md](docs/CONFIGURATION.md)** -- Presets, tag prefixes, config files', + '3. **[METHODOLOGY.md](docs/METHODOLOGY.md)** -- Core thesis, dual-source architecture', + ].join('\n'), + }, + + // --- Developer / AI Path --- + { + type: 'heading' as const, + level: 3, + text: 'For Developers / AI', + }, + { + type: 'paragraph' as const, + text: [ + '4. **[ARCHITECTURE.md](docs/ARCHITECTURE.md)** -- Four-stage pipeline, codecs, MasterDataset', + '5. **[PROCESS-API.md](docs/PROCESS-API.md)** -- Data API CLI query interface', + '6. **[SESSION-GUIDES.md](docs/SESSION-GUIDES.md)** -- Planning/Design/Implementation workflows', + '7. **[GHERKIN-PATTERNS.md](docs/GHERKIN-PATTERNS.md)** -- Writing effective Gherkin specs', + '8. **[ANNOTATION-GUIDE.md](docs/ANNOTATION-GUIDE.md)** -- Annotation mechanics, shape extraction', + ].join('\n'), + }, + + // --- Team Lead / CI Path --- + { + type: 'heading' as const, + level: 3, + text: 'For Team Leads / CI', + }, + { + type: 'paragraph' as const, + text: [ + '9. **[PROCESS-GUARD.md](docs/PROCESS-GUARD.md)** -- FSM enforcement, pre-commit hooks', + '10. **[VALIDATION.md](docs/VALIDATION.md)** -- Lint rules, DoD checks, anti-patterns', + ].join('\n'), + }, +]; + +/** + * Document roles matrix — Audience x Document x Focus. + * + * Maps each document to its primary audience and focus area. + * This section helps readers who know their role find all relevant docs. + */ +export const DOCUMENT_ROLES_SECTIONS: readonly SectionBlock[] = [ + { + type: 'heading' as const, + level: 2, + text: 'Document Roles', + }, + { + type: 'table' as const, + columns: ['Document', 'Audience', 'Focus'], + rows: [ + ['README.md', 'Everyone', 'Quick start, value proposition'], + ['METHODOLOGY.md', 'Everyone', 'Why -- core thesis, principles'], + ['CONFIGURATION.md', 'Users', 'Setup -- presets, tags, config'], + ['ARCHITECTURE.md', 'Developers', 'How -- pipeline, codecs, schemas'], + ['PROCESS-API.md', 'AI/Devs', 'Data API CLI query interface'], + ['SESSION-GUIDES.md', 'AI/Devs', 'Workflow -- day-to-day usage'], + ['GHERKIN-PATTERNS.md', 'Writers', 'Specs -- writing effective Gherkin'], + ['PROCESS-GUARD.md', 'Team Leads', 'Governance -- enforcement rules'], + ['VALIDATION.md', 'CI/CD', 'Quality -- automated checks'], + ['TAXONOMY.md', 'Reference', 'Lookup -- tag taxonomy and API'], + ['ANNOTATION-GUIDE.md', 'Developers', 'Reference -- annotation mechanics'], + ['MAINTAINERS.md', 'Maintainers', 'Project maintenance and release workflow'], + ['PRODUCT-AREAS.md', 'Everyone', 'Generated -- product area overviews'], + ['DECISIONS.md', 'Developers', 'Generated -- architecture decisions'], + ['BUSINESS-RULES.md', 'Developers', 'Generated -- business rules and invariants'], + ], + }, +]; + +/** + * Key concepts glossary — reader-friendly definitions. + * + * DD-4: Full preamble, not annotation-derived. Pattern descriptions + * are too granular for glossary use. + */ +export const KEY_CONCEPTS_SECTIONS: readonly SectionBlock[] = [ + { + type: 'heading' as const, + level: 2, + text: 'Key Concepts', + }, + { + type: 'paragraph' as const, + text: [ + '**Delivery Process** -- A code-first documentation and workflow toolkit. Extracts patterns from annotated TypeScript and Gherkin sources, generates markdown documentation, and validates delivery workflow via pre-commit hooks.', + '', + '**Pattern** -- An annotated unit of work tracked by the delivery process. Each pattern has a status (roadmap, active, completed, deferred), belongs to a product area, and has deliverables. Patterns are the atomic unit of the MasterDataset.', + '', + '**MasterDataset** -- The single read model (ADR-006) containing all extracted patterns with pre-computed views (byProductArea, byPhase, byStatus, byCategory). All codecs and the Data API consume this dataset. No consumer re-derives data from raw scanner output.', + '', + '**Codec** -- A Zod-based transformer that decodes MasterDataset into a RenderableDocument. Each codec produces a specific document type (e.g., PatternsDocumentCodec produces PATTERNS.md). Codecs are pure functions with no I/O.', + '', + '**Dual-Source Architecture** -- Feature files own planning metadata (status, phase, dependencies). TypeScript files own implementation metadata (uses, used-by, category). This split prevents ownership conflicts and enables independent annotation cadences.', + '', + '**Delivery Workflow FSM** -- A finite state machine enforcing pattern lifecycle: roadmap -> active -> completed. Transitions are validated by Process Guard at commit time. The FSM prevents scope creep (no adding deliverables to active specs) and ensures completion integrity.', + ].join('\n'), + }, +]; + +/** + * Complete preamble for the IndexCodec. + * + * Composes all editorial sections in display order: + * 1. Quick Navigation (highest-value lookup table) + * 2. Reading Order (audience-specific paths) + * 3. Document Roles (audience x document matrix) + * 4. Key Concepts (glossary) + */ +export const INDEX_PREAMBLE_SECTIONS: readonly SectionBlock[] = [ + ...QUICK_NAVIGATION_SECTIONS, + { type: 'separator' as const }, + ...READING_ORDER_SECTIONS, + { type: 'separator' as const }, + ...DOCUMENT_ROLES_SECTIONS, + { type: 'separator' as const }, + ...KEY_CONCEPTS_SECTIONS, +]; + +// --------------------------------------------------------------------------- +// Example Document Entries (DD-2: static config, not filesystem discovery) +// --------------------------------------------------------------------------- + +/** + * Document entries for the unified inventory. + * + * DD-2: Configured statically. The codec does not discover files at + * generation time. When documents are added or renamed, this list + * is updated alongside the document change. + * + * Documents are organized by topic, not by source directory. + * The reader sees one unified set of documentation. + */ +export const INDEX_DOCUMENT_ENTRIES: readonly DocumentEntry[] = [ + // --- Getting Started --- + { + title: 'README', + path: 'README.md', + description: 'Installation, quick start, value proposition', + audience: 'Everyone', + topic: 'Getting Started', + }, + { + title: 'Configuration', + path: 'docs/CONFIGURATION.md', + description: 'Presets, tag prefixes, config files', + audience: 'Users', + topic: 'Getting Started', + }, + { + title: 'Methodology', + path: 'docs/METHODOLOGY.md', + description: 'Core thesis, dual-source architecture principles', + audience: 'Everyone', + topic: 'Getting Started', + }, + + // --- Architecture --- + { + title: 'Architecture', + path: 'docs/ARCHITECTURE.md', + description: 'Four-stage pipeline, codecs, MasterDataset, schemas', + audience: 'Developers', + topic: 'Architecture', + }, + { + title: 'Product Areas', + path: 'docs-live/PRODUCT-AREAS.md', + description: 'Product area overviews with live statistics and diagrams', + audience: 'Everyone', + topic: 'Architecture', + }, + { + title: 'Architecture Decisions', + path: 'docs-live/DECISIONS.md', + description: 'ADRs extracted from decision specs', + audience: 'Developers', + topic: 'Architecture', + }, + + // --- Development Workflow --- + { + title: 'Session Guides', + path: 'docs/SESSION-GUIDES.md', + description: 'Planning, Design, Implementation session workflows', + audience: 'AI/Devs', + topic: 'Development Workflow', + }, + { + title: 'Process API', + path: 'docs/PROCESS-API.md', + description: 'Data API CLI query interface for session context', + audience: 'AI/Devs', + topic: 'Development Workflow', + }, + + // --- Authoring --- + { + title: 'Gherkin Patterns', + path: 'docs/GHERKIN-PATTERNS.md', + description: 'Writing effective Gherkin specs, Rule blocks, DataTables', + audience: 'Writers', + topic: 'Authoring', + }, + { + title: 'Annotation Guide', + path: 'docs/ANNOTATION-GUIDE.md', + description: 'Annotation mechanics, shape extraction, tag reference', + audience: 'Developers', + topic: 'Authoring', + }, + { + title: 'Taxonomy', + path: 'docs/TAXONOMY.md', + description: 'Tag taxonomy structure and format types', + audience: 'Reference', + topic: 'Authoring', + }, + + // --- Governance --- + { + title: 'Process Guard', + path: 'docs/PROCESS-GUARD.md', + description: 'FSM enforcement, pre-commit hooks, error codes', + audience: 'Team Leads', + topic: 'Governance', + }, + { + title: 'Validation', + path: 'docs/VALIDATION.md', + description: 'Lint rules, DoD checks, anti-pattern detection', + audience: 'CI/CD', + topic: 'Governance', + }, + { + title: 'Business Rules', + path: 'docs-live/BUSINESS-RULES.md', + description: 'Business rules and invariants extracted from specs', + audience: 'Developers', + topic: 'Governance', + }, + + // --- Operations --- + { + title: 'Maintainers', + path: 'MAINTAINERS.md', + description: 'Project maintenance, release workflow, versioning, CI setup', + audience: 'Maintainers', + topic: 'Operations', + }, +]; + +export function _indexPreambleConfigPlaceholder(): never { + throw new Error('EnhancedIndexGeneration not yet implemented - roadmap pattern'); +} diff --git a/delivery-process/stubs/error-guide-codec/convention-annotation-example.ts b/delivery-process/stubs/error-guide-codec/convention-annotation-example.ts new file mode 100644 index 00000000..e0d28ea7 --- /dev/null +++ b/delivery-process/stubs/error-guide-codec/convention-annotation-example.ts @@ -0,0 +1,153 @@ +/** + * @libar-docs + * @libar-docs-status roadmap + * @libar-docs-implements ErrorGuideCodec + * @libar-docs-target src/lint/process-guard/decider.ts + * + * ## Convention Annotation Example — DD-3 Decision + * + * **Decision DD-3 (Rationale source):** Rationale comes from convention + * JSDoc annotations on `src/lint/process-guard/decider.ts`, not from + * `Rule:` blocks in the ProcessGuardLinter Gherkin spec. + * + * **Rationale (DD-3):** The rationale content belongs near the error-handling + * code, not in a planning spec. When a developer changes an error rule in + * the decider, the convention JSDoc is right there -- they update both in + * the same commit. This follows the proven pattern used by: + * - `src/generators/orchestrator.ts` with `@libar-docs-convention pipeline-architecture` + * - `src/renderable/codecs/reference.ts` with `@libar-docs-convention codec-registry` + * - `src/renderable/codecs/validation-rules.ts` with `@libar-docs-convention codec-registry` + * + * All three use TypeScript JSDoc convention annotations with `## Heading` + * decomposition. The convention extractor's `extractConventionRulesFromDescription()` + * splits by `## Heading` sections, parsing each for `**Invariant:**`, + * `**Rationale:**`, and tables -- exactly the structure needed for error guides. + * + * **Annotation format:** + * Each error rule gets a `## ` heading in the JSDoc with structured + * content below it. The convention extractor decomposes by heading and + * produces one `ConventionRuleContent` per error code. + * + * **Content structure per error code:** + * - `**Invariant:**` — The rule statement (maps to "Why this rule exists") + * - `**Rationale:**` — Why the constraint exists (detailed explanation) + * - Table with `| Situation | Solution | Example |` for alternatives + * + * ### Annotation Placement + * + * The convention annotation is added to the EXISTING JSDoc block on + * `src/lint/process-guard/decider.ts`. The file already has extensive + * JSDoc describing the decider's design principles and rules. The + * convention annotation extends this JSDoc, not replaces it. + * + * Specifically, `@libar-docs-convention process-guard-errors` is added + * to the file-level JSDoc alongside the existing annotations: + * - `@libar-docs-pattern ProcessGuardDecider` + * - `@libar-docs-arch-role decider` + * - etc. + * + * Then the `## ` headings for each error rule are added below the existing + * design documentation. + */ + +// --------------------------------------------------------------------------- +// Example: How decider.ts would be annotated (partial) +// --------------------------------------------------------------------------- + +/** + * This stub shows the PATTERN of convention annotation that would be + * added to `src/lint/process-guard/decider.ts`. The actual annotation + * content goes in the decider's file-level JSDoc block. + * + * Key insight: The convention extractor splits by `## Heading` and parses + * each section for `**Invariant:**`, `**Rationale:**`, and tables. So + * each error rule becomes a separate `ConventionRuleContent` entry in + * the extracted `ConventionBundle`. + * + * The annotation below demonstrates the format for all 6 error rules. + * In the actual decider.ts, these would follow the existing `### Rules + * Implemented` section. + * + * @libar-docs-convention process-guard-errors + * + * ## completed-protection + * + * **Invariant:** Completed specs are immutable without an explicit unlock + * reason. The unlock reason must be at least 10 characters and cannot be + * a placeholder. + * + * **Rationale:** The `completed` status represents verified, accepted work. + * Allowing silent modification undermines the terminal-state guarantee. + * Requiring an unlock reason creates an audit trail and forces the developer + * to justify why completed work needs revisiting. + * + * | Situation | Solution | Example | + * |-----------|----------|---------| + * | Fix typo in completed spec | Add unlock reason tag | `@libar-docs-unlock-reason:Fix-typo-in-FSM-diagram` | + * | Spec needs rework | Create new spec instead | New feature file with `roadmap` status | + * | Legacy import | Multiple transitions in one commit | Set `roadmap` then `completed` | + * + * ## invalid-status-transition + * + * **Invariant:** Status transitions must follow the PDR-005 FSM path. + * The only valid paths are: roadmap->active, roadmap->deferred, + * active->completed, active->roadmap, deferred->roadmap. + * + * **Rationale:** The FSM enforces a deliberate progression through + * planning, implementation, and completion. Skipping states (e.g., + * roadmap->completed) means work was never tracked as active, breaking + * session scoping and deliverable validation. + * + * | Attempted | Why Invalid | Valid Path | + * |-----------|-------------|------------| + * | roadmap->completed | Must go through active | roadmap->active->completed | + * | deferred->active | Must return to roadmap first | deferred->roadmap->active | + * | deferred->completed | Cannot skip two states | deferred->roadmap->active->completed | + * + * ## scope-creep + * + * **Invariant:** Active specs cannot add new deliverables. Scope is locked + * when status transitions to `active`. + * + * **Rationale:** Prevents scope creep during implementation. Plan fully + * before starting; implement what was planned. Adding deliverables mid- + * implementation signals inadequate planning and risks incomplete work. + * + * | Situation | Solution | Example | + * |-----------|----------|---------| + * | Need new deliverable | Revert to roadmap first | Change status to roadmap, add deliverable, then back to active | + * | Discovered work during implementation | Create new spec | New feature file for the discovered work | + * + * ## session-scope + * + * **Invariant:** Files outside the active session scope trigger warnings + * to prevent accidental cross-session modifications. + * + * **Rationale:** Session scoping ensures focused work. Modifying files + * outside the session scope often indicates scope creep or working on + * the wrong task. The warning is informational (not blocking) to allow + * intentional cross-scope changes with `--ignore-session`. + * + * ## session-excluded + * + * **Invariant:** Files explicitly excluded from a session cannot be + * modified in that session. This is a hard error, not a warning. + * + * **Rationale:** Explicit exclusion is a deliberate decision to protect + * certain files from modification during a session. Unlike session-scope + * (warning), exclusion represents a conscious boundary that should not + * be violated without changing the session configuration. + * + * ## deliverable-removed + * + * **Invariant:** Removing a deliverable from an active spec triggers a + * warning to ensure the removal is intentional and documented. + * + * **Rationale:** Deliverable removal during active implementation may + * indicate descoping or completion elsewhere. The warning ensures + * visibility -- the commit message should document why the deliverable + * was removed. + */ +export function _conventionAnnotationExample(): never { + throw new Error('ErrorGuideCodec not yet implemented - roadmap pattern'); +} diff --git a/delivery-process/stubs/error-guide-codec/enhanced-validation-options.ts b/delivery-process/stubs/error-guide-codec/enhanced-validation-options.ts new file mode 100644 index 00000000..c1059eeb --- /dev/null +++ b/delivery-process/stubs/error-guide-codec/enhanced-validation-options.ts @@ -0,0 +1,155 @@ +/** + * @libar-docs + * @libar-docs-status roadmap + * @libar-docs-implements ErrorGuideCodec + * @libar-docs-target src/renderable/codecs/validation-rules.ts + * + * ## Enhanced ValidationRulesCodecOptions — DD-1 Decision + * + * **Decision:** Extend the existing `ValidationRulesCodec` rather than creating + * a separate `ErrorGuideCodec`. The `ValidationRulesCodec` already owns + * `RULE_DEFINITIONS` with error codes, causes, and fixes, and generates + * `error-catalog.md`, `fsm-transitions.md`, and `protection-levels.md`. + * Creating a parallel codec would duplicate `RULE_DEFINITIONS` access and + * fragment validation documentation across two codecs. + * + * **Rationale (DD-1):** The existing ValidationRulesCodec has the right + * extension points: + * - `ValidationRulesCodecOptions` for feature toggles (pattern already + * established by `includeFSMDiagram`, `includeCLIUsage`, etc.) + * - `RULE_DEFINITIONS` constant for error code metadata + * - `buildDetailFiles()` for progressive disclosure + * - Section builder functions for composing document parts + * + * A new `ErrorGuideCodec` class would need to duplicate access to all of + * these, and consumers (orchestrator, config) would need to wire two codecs + * for what is logically one validation reference document. + * + * **What changes in validation-rules.ts:** + * 1. `RuleDefinition` interface gains optional `rationale` field + * 2. `ValidationRulesCodecOptions` gains `includeErrorGuide` toggle + * 3. `buildErrorCatalogDetailDocument()` conditionally renders rationale + * 4. New `buildErrorGuideSections()` builder for the rationale+alternatives layer + * + * **What does NOT change:** + * - No new class or codec file is created + * - Existing option defaults remain `true` (backward compatible) + * - `RULE_DEFINITIONS` entries without rationale fall back to `description` + */ + +import type { BaseCodecOptions } from '../../../src/renderable/codecs/types/base.js'; + +// --------------------------------------------------------------------------- +// DD-1: Extended RuleDefinition interface +// --------------------------------------------------------------------------- + +/** + * Extended rule definition for documentation, adding error guide fields. + * + * The `rationale` field is populated from convention-extracted content + * at generation time. If no convention annotation exists for a rule, + * the codec falls back to the `description` field. + * + * The `alternatives` field documents escape hatches and alternative + * approaches, also sourced from convention annotations. + */ +export interface EnhancedRuleDefinition { + /** Unique rule ID matching ProcessGuardRule union type */ + readonly id: string; + /** Default severity level */ + readonly severity: 'error' | 'warning'; + /** Human-readable rule description */ + readonly description: string; + /** What triggers this error */ + readonly cause: string; + /** How to fix this error */ + readonly fix: string; + /** + * Why this rule exists - sourced from convention annotation rationale. + * Falls back to `description` if no convention annotation exists. + */ + readonly rationale?: string; + /** + * Alternative approaches / escape hatches for this rule. + * Sourced from convention annotation alternatives section. + */ + readonly alternatives?: readonly string[]; +} + +// --------------------------------------------------------------------------- +// DD-1: Extended ValidationRulesCodecOptions +// --------------------------------------------------------------------------- + +/** + * Enhanced options for ValidationRulesCodec with error guide toggles. + * + * New toggles follow the established pattern: boolean flags with `true` + * defaults, independently toggleable. The `includeErrorGuide` flag + * controls whether rationale and alternative-approach content from + * convention annotations is merged into the error catalog detail file. + * + * When `includeErrorGuide` is `false`, the codec produces the same + * output as before this enhancement (backward compatible). + */ +export interface EnhancedValidationRulesCodecOptions extends BaseCodecOptions { + /** Include FSM state diagram (default: true) */ + readonly includeFSMDiagram?: boolean; + /** Include CLI usage section (default: true) */ + readonly includeCLIUsage?: boolean; + /** Include escape hatches section (default: true) */ + readonly includeEscapeHatches?: boolean; + /** Include protection levels matrix (default: true) */ + readonly includeProtectionMatrix?: boolean; + + /** + * DD-1: Include error guide rationale and alternatives in the error + * catalog detail file. When enabled, each error code entry in + * `validation/error-catalog.md` gains "Why this rule exists" and + * "Alternative approaches" sections sourced from convention annotations. + * + * Default: true + */ + readonly includeErrorGuide?: boolean; +} + +/** + * Default options with error guide enabled. + */ +export const ENHANCED_DEFAULT_OPTIONS: EnhancedValidationRulesCodecOptions = { + detailLevel: 'detailed', + generateDetailFiles: true, + includeFSMDiagram: true, + includeCLIUsage: true, + includeEscapeHatches: true, + includeProtectionMatrix: true, + includeErrorGuide: true, +}; + +// --------------------------------------------------------------------------- +// DD-3: Rationale composition from convention bundles +// --------------------------------------------------------------------------- + +/** + * Compose rationale into RuleDefinition entries from convention-extracted content. + * + * This function takes the static `RULE_DEFINITIONS` array and enriches each + * entry with rationale and alternatives from convention bundles extracted by + * the convention extractor pipeline. + * + * Matching strategy: Convention rule names are matched to RULE_DEFINITIONS + * entries by normalizing to the `id` field (e.g., convention rule name + * "completed-protection" matches `RULE_DEFINITIONS[0].id`). + * + * Fallback: If no convention content exists for a rule, `rationale` defaults + * to the `description` field. No empty rationale sections appear in output. + * + * @param rules - Static RULE_DEFINITIONS array + * @param conventionRationale - Map of rule ID to convention-extracted rationale + * @returns Enhanced rule definitions with rationale populated + */ +export function composeRationaleIntoRules( + _rules: readonly EnhancedRuleDefinition[], + _conventionRationale: ReadonlyMap +): EnhancedRuleDefinition[] { + throw new Error('ErrorGuideCodec not yet implemented - roadmap pattern'); +} diff --git a/delivery-process/stubs/error-guide-codec/error-guide-config.ts b/delivery-process/stubs/error-guide-codec/error-guide-config.ts new file mode 100644 index 00000000..55848af8 --- /dev/null +++ b/delivery-process/stubs/error-guide-codec/error-guide-config.ts @@ -0,0 +1,222 @@ +/** + * @libar-docs + * @libar-docs-status roadmap + * @libar-docs-implements ErrorGuideCodec + * @libar-docs-target delivery-process.config.ts + * + * ## ReferenceDocConfig Entry for Process Guard Error Guide — DD-2, DD-4 Decisions + * + * **Decision DD-2 (Convention tag approach):** Register a new `process-guard-errors` + * convention tag value in `CONVENTION_VALUES` rather than reusing `fsm-rules`. + * + * **Rationale (DD-2):** The `fsm-rules` tag covers FSM state definitions, + * transition matrices, and protection levels — structural FSM documentation. + * Error diagnosis content (rationale for why a rule exists, alternative + * approaches, common mistake patterns) is a distinct concern. Co-locating + * both under `fsm-rules` would conflate "how the FSM works" with "how to + * debug Process Guard errors". A dedicated tag keeps convention bundles + * focused and enables independent content routing. + * + * Existing convention tags for reference: + * - `fsm-rules` — FSM structure (transitions, states, protection levels) + * - `cli-patterns` — CLI argument parsing conventions + * - `codec-registry` — Codec catalog and factory patterns + * - `pipeline-architecture` — Pipeline stage responsibilities + * + * The new `process-guard-errors` tag covers: + * - Per-error-code rationale ("why this rule exists") + * - Alternative approaches and escape hatches + * - Common mistake patterns and debugging hints + * + * **Decision DD-4 (Husky/CI content):** Use the `ReferenceDocConfig.preamble` + * mechanism for integration recipes. Preamble is `SectionBlock[]` prepended + * before all generated content. This is the established pattern — no new + * annotation type is needed. + * + * **Rationale (DD-4):** Integration recipes (Husky hook setup, CI YAML + * patterns, programmatic API examples, architecture diagrams) describe how + * external systems consume Process Guard, not how Process Guard is + * implemented. This content cannot come from `@libar-docs-convention` + * annotations because it is not attached to any source code entity. + * The preamble mechanism was designed precisely for this case: + * - Already proven by product-area docs (e.g., `PRODUCT_AREA_META` preamble) + * - Appears in both detailed and summary outputs + * - Lives in the config, not in a separate manual file + * - Changes at editorial cadence, not code cadence + * + * ### Config Structure + * + * The `ReferenceDocConfig` entry composes three content layers: + * + * | Layer | Source | Content | + * |-------|--------|---------| + * | Preamble | Config `preamble: SectionBlock[]` | Husky setup, CI recipes, programmatic API, architecture diagram | + * | Conventions | `conventionTags: ['process-guard-errors']` | Per-error rationale, alternatives, debugging hints | + * | Existing codec | `validation-rules` generator override | Error catalog, FSM transitions, protection levels | + * + * **Integration with ValidationRulesCodec:** + * The ReferenceDocConfig uses `conventionTags: ['process-guard-errors']` to + * pull rationale content through the reference codec's convention extraction + * pipeline. The `validation-rules` generator continues to produce its + * existing detail files (`error-catalog.md`, `fsm-transitions.md`, + * `protection-levels.md`) independently. The reference doc entry creates + * a unified PROCESS-GUARD.md that composes preamble + convention content + + * links to the validation-rules detail files. + */ + +// --------------------------------------------------------------------------- +// Example ReferenceDocConfig entry (would be added to delivery-process.config.ts) +// --------------------------------------------------------------------------- + +/** + * This stub demonstrates the config entry shape. The actual entry goes in + * `delivery-process.config.ts` under the `referenceDocConfigs` array. + * + * The preamble sections below show the editorial content structure for + * Husky setup, programmatic API, and architecture diagram. Each preamble + * entry is a SectionBlock (heading, paragraph, code, table, or mermaid). + */ +export const ERROR_GUIDE_REFERENCE_CONFIG = { + title: 'Process Guard Reference', + conventionTags: ['process-guard-errors'], + shapeSources: [], + behaviorCategories: [], + claudeMdSection: 'validation', + docsFilename: 'PROCESS-GUARD.md', + claudeMdFilename: 'process-guard.md', + preamble: [ + // --- Husky Pre-commit Setup --- + { + type: 'heading' as const, + level: 2, + text: 'Pre-commit Setup', + }, + { + type: 'paragraph' as const, + text: 'Configure Process Guard as a pre-commit hook using Husky.', + }, + { + type: 'code' as const, + language: 'bash', + content: [ + '# .husky/pre-commit', + '#!/usr/bin/env sh', + '. "$(dirname -- "$0")/_/husky.sh"', + '', + 'npx lint-process --staged', + ].join('\n'), + }, + { + type: 'heading' as const, + level: 3, + text: 'package.json Scripts', + }, + { + type: 'code' as const, + language: 'json', + content: JSON.stringify( + { + scripts: { + 'lint:process': 'lint-process --staged', + 'lint:process:ci': 'lint-process --all --strict', + }, + }, + null, + 2 + ), + }, + + // --- Programmatic API --- + { + type: 'heading' as const, + level: 2, + text: 'Programmatic API', + }, + { + type: 'paragraph' as const, + text: 'Use Process Guard programmatically for custom validation workflows.', + }, + { + type: 'code' as const, + language: 'typescript', + content: [ + "import {", + " deriveProcessState,", + " detectStagedChanges,", + " validateChanges,", + " hasErrors,", + " summarizeResult,", + "} from '@libar-dev/delivery-process/lint';", + "", + "// 1. Derive state from annotations", + "const state = (await deriveProcessState({ baseDir: '.' })).value;", + "", + "// 2. Detect changes", + "const changes = detectStagedChanges('.').value;", + "", + "// 3. Validate", + "const { result } = validateChanges({", + " state,", + " changes,", + " options: { strict: false, ignoreSession: false },", + "});", + "", + "// 4. Handle results", + "if (hasErrors(result)) {", + " console.log(summarizeResult(result));", + " process.exit(1);", + "}", + ].join('\n'), + }, + { + type: 'heading' as const, + level: 3, + text: 'API Functions', + }, + { + type: 'table' as const, + headers: ['Category', 'Function', 'Description'], + rows: [ + ['State', 'deriveProcessState(cfg)', 'Build state from file annotations'], + ['Changes', 'detectStagedChanges(dir)', 'Parse staged git diff'], + ['Changes', 'detectBranchChanges(dir)', 'Parse all changes vs main'], + ['Validate', 'validateChanges(input)', 'Run all validation rules'], + ['Results', 'hasErrors(result)', 'Check for blocking errors'], + ['Results', 'summarizeResult(result)', 'Human-readable summary'], + ], + }, + + // --- Architecture Diagram --- + { + type: 'heading' as const, + level: 2, + text: 'Architecture', + }, + { + type: 'paragraph' as const, + text: 'Process Guard uses the Decider pattern: pure functions with no I/O.', + }, + { + type: 'mermaid' as const, + content: [ + 'graph LR', + ' A[deriveProcessState] --> C[validateChanges]', + ' B[detectStagedChanges / detectBranchChanges] --> C', + ' C --> D[ValidationResult]', + ].join('\n'), + }, + ], +} as const; + +// --------------------------------------------------------------------------- +// Convention tag registration (goes in src/taxonomy/conventions.ts) +// --------------------------------------------------------------------------- + +/** + * DD-2: 'process-guard-errors' is already registered in + * `src/taxonomy/conventions.ts` CONVENTION_VALUES. + * No additional registration needed. + */ +export function _conventionTagRegistrationPlaceholder(): never { + throw new Error('ErrorGuideCodec not yet implemented - roadmap pattern'); +} diff --git a/delivery-process/stubs/procedural-guide-codec/annotation-guide-preamble.ts b/delivery-process/stubs/procedural-guide-codec/annotation-guide-preamble.ts new file mode 100644 index 00000000..403285a8 --- /dev/null +++ b/delivery-process/stubs/procedural-guide-codec/annotation-guide-preamble.ts @@ -0,0 +1,126 @@ +/** + * @libar-docs + * @libar-docs-status roadmap + * @libar-docs-implements ProceduralGuideCodec + * @libar-docs-target delivery-process.config.ts + * + * ## Annotation Guide — Markdown Source File Example + * + * **Design Decision DD-7 (Markdown source files):** + * The annotation guide preamble content (~265 lines of inline `SectionBlock[]` + * TypeScript) is replaced by a plain markdown file at + * `docs-sources/annotation-guide.md`. This file is read and parsed into + * `SectionBlock[]` at config import time by `loadPreambleFromMarkdown()`. + * + * **Design Decision DD-5 (Hybrid approach):** + * The annotation guide uses a hybrid approach. Most content (getting-started + * walkthrough, shape extraction modes, Zod gotcha, file-type annotation + * patterns, verification CLI recipes, troubleshooting table) is stable + * editorial content that changes at editorial cadence, not code cadence. + * This content is authored as markdown. The tag reference summary table is + * the one section that changes when tags are added or modified -- it is + * auto-generated from taxonomy data. + * + * **Rationale (DD-5):** Attempting to annotate "how to annotate" as source + * code creates a circular dependency -- the guide that teaches annotation + * would need annotations to generate itself. The markdown source file + * breaks this circularity: the walkthrough is editorial content authored + * once and maintained manually. The tag reference table IS derivable + * from the taxonomy registry (tag names, format types, enum values) and + * should be auto-generated to stay current. + * + * ### Content Mapping from ANNOTATION-GUIDE.md + * + * | Manual Section (ANNOTATION-GUIDE.md) | Markdown Element | Lines | + * |--------------------------------------|------------------|-------| + * | Getting Started: File-Level Opt-In | Code fences + paragraphs | 9-42 | + * | Tag Prefix by Preset | Markdown table | 44-54 | + * | Dual-Source Ownership | Markdown table | 56-65 | + * | Shape Extraction: Mode 1 (Explicit) | Code fence | 71-82 | + * | Shape Extraction: Mode 2 (Wildcard) | Code fence | 84-98 | + * | Shape Extraction: Mode 3 (Declaration) | Code fence | 99-114 | + * | Critical Gotcha: Zod Schemas | Markdown table | 116-124 | + * | Verification CLI Commands | Bash code fence | 229-246 | + * | Common Issues / Troubleshooting | Markdown table | 250-257 | + * + * Content NOT in preamble (auto-generated from taxonomy): + * - Tag Groups Quick Reference table (lines 196-212) + * - Format Types table (lines 214-224) + * + * ### Config Usage Example + * + * ```typescript + * // In delivery-process.config.ts: + * import { loadPreambleFromMarkdown } from './src/renderable/load-preamble.js'; + * + * const annotationPreamble = loadPreambleFromMarkdown( + * 'docs-sources/annotation-guide.md' + * ); + * + * // In referenceDocConfigs: + * { + * title: 'Annotation Reference Guide', + * conventionTags: ['annotation-system'], + * preamble: [...annotationPreamble], + * docsFilename: 'ANNOTATION-REFERENCE.md', + * // ... + * } + * ``` + * + * ### Example Markdown Source File (abbreviated) + * + * The full file at `docs-sources/annotation-guide.md` contains all sections + * from the content mapping table above. This example shows a representative + * section to illustrate the authoring format: + * + * ```markdown + * ## Getting Started + * + * Every file that participates in the annotation system must have a + * `@libar-docs` opt-in marker. Files without this marker are invisible + * to the scanner. + * + * ### File-Level Opt-In + * + * **TypeScript** -- file-level JSDoc block: + * + * \`\`\`typescript + * /** + * * @libar-docs + * * @libar-docs-pattern MyPattern + * * @libar-docs-status roadmap + * * / + * \`\`\` + * + * ### Tag Prefix by Preset + * + * | Preset | Prefix | Categories | Use Case | + * |--------|--------|------------|----------| + * | `libar-generic` (default) | `@libar-docs-` | 3 | Simple projects | + * | `ddd-es-cqrs` | `@libar-docs-` | 21 | DDD/Event Sourcing monorepos | + * + * --- + * + * ## Critical Gotcha: Zod Schemas + * + * For Zod files, extract the **schema constant** (with `Schema` suffix), + * not the inferred type alias: + * + * | Wrong (type alias) | Correct (schema constant) | + * |--------------------|---------------------------| + * | `@extract-shapes MasterDataset` | `@extract-shapes MasterDatasetSchema` | + * + * --- + * + * ## Common Issues + * + * | Symptom | Cause | Fix | + * |---------|-------|-----| + * | Pattern not in scanner output | Missing `@libar-docs` opt-in | Add file-level `@libar-docs` JSDoc/tag | + * | Shape shows `z.infer<>` wrapper | Extracted type alias, not schema | Use schema constant name | + * ``` + */ + +export function _annotationGuidePreambleDesignStub(): never { + throw new Error('ProceduralGuideCodec not yet implemented - roadmap pattern'); +} diff --git a/delivery-process/stubs/procedural-guide-codec/load-preamble.ts b/delivery-process/stubs/procedural-guide-codec/load-preamble.ts new file mode 100644 index 00000000..a073bb56 --- /dev/null +++ b/delivery-process/stubs/procedural-guide-codec/load-preamble.ts @@ -0,0 +1,133 @@ +/** + * @libar-docs + * @libar-docs-status roadmap + * @libar-docs-implements ProceduralGuideCodec + * @libar-docs-target src/renderable/load-preamble.ts + * + * ## loadPreambleFromMarkdown() — Shared Utility Stub + * + * **Design Decision DD-8 (Shared markdown-to-SectionBlock parser):** + * A `loadPreambleFromMarkdown()` function in `src/renderable/load-preamble.ts` + * reads a markdown file via `readFileSync` (synchronous, runs at module import + * time) and parses it into a `readonly SectionBlock[]` array using a line-by-line + * state machine. This utility is available to all preamble consumers: + * ProceduralGuideCodec, ErrorGuideCodec, CliRecipeCodec. + * + * **Rationale (DD-8):** Preamble content is naturally authored as markdown — + * headings, tables, code fences, lists, and Mermaid diagrams all have standard + * markdown syntax. Converting this to inline TypeScript `SectionBlock[]` object + * literals (e.g., `{ type: 'heading', level: 2, text: '...' }`) is verbose + * and harder to review. A shared parser eliminates 540+ lines of inline + * TypeScript per codec config while preserving the same `SectionBlock[]` + * shape that codecs receive in memory. + * + * **Codec purity preserved:** The parser runs at config import time (before + * any codec `decode()` call). Codecs receive `SectionBlock[]` in memory via + * `ReferenceDocConfig.preamble` — they never know whether the preamble came + * from inline TypeScript or a parsed markdown file. No filesystem I/O occurs + * during codec execution. + * + * ### Parsing Rules (Line-by-Line State Machine) + * + * The parser processes the markdown file line by line, maintaining a state + * that tracks whether it is inside a code fence, accumulating a table, or + * collecting paragraph text. + * + * | Markdown Construct | SectionBlock Type | Detection Rule | + * |--------------------|-------------------|----------------| + * | `# Heading` through `###### Heading` | HeadingBlock | Line starts with 1-6 `#` chars followed by space | + * | Plain text paragraphs | ParagraphBlock | Consecutive non-empty lines separated by blank lines | + * | `---` (horizontal rule) | SeparatorBlock | Line is exactly `---`, `***`, or `___` | + * | `\| col \| col \|` with separator row | TableBlock | Line starts with `\|`, second line has `\|---` pattern | + * | `- item` or `* item` | ListBlock (unordered) | Line starts with `- ` or `* ` | + * | `1. item` | ListBlock (ordered) | Line starts with `\d+. ` | + * | ` ```language ` ... ` ``` ` | CodeBlock | Fenced code block with language info string | + * | ` ```mermaid ` ... ` ``` ` | MermaidBlock | Special case: code fence with `mermaid` info string | + * + * ### State Machine States + * + * | State | Entered When | Exited When | + * |-------|-------------|-------------| + * | `idle` | Start, after emitting a block | Any non-blank line | + * | `in-code-fence` | Line matches ` ``` ` with optional info string | Line matches closing ` ``` ` | + * | `in-table` | Line starts with `\|` and next line is separator | Line does not start with `\|` | + * | `in-paragraph` | Non-blank line that doesn't match other patterns | Blank line encountered | + * | `in-list` | Line starts with `- `, `* `, or `\d+. ` | Line does not match list pattern | + * + * ### Edge Cases + * + * | Case | Behavior | + * |------|----------| + * | `- [ ] Step text` | Parsed as ListBlock item with `[ ] ` prefix preserved (GFM checkbox) | + * | Nested lists | Not supported — flattened to single-level list | + * | `**bold**` in paragraphs | Preserved as-is in ParagraphBlock text (markdown inline formatting) | + * | Empty code fence | Produces CodeBlock with empty content string | + * | Table alignment (`:---:`) | Alignment markers stripped, columns extracted from header row | + * | Consecutive headings | Each produces a separate HeadingBlock | + * | YAML frontmatter (`---` ... `---`) | Not parsed — not needed for preamble content | + * + * ### Blocks NOT Produced + * + * | SectionBlock Type | Why Not Parsed | + * |-------------------|---------------| + * | CollapsibleBlock | No standard markdown syntax; codec adds these for progressive disclosure | + * | LinkOutBlock | No standard markdown syntax; codec adds cross-reference links | + * + * ### Usage + * + * ```typescript + * // In delivery-process.config.ts: + * import { loadPreambleFromMarkdown } from './src/renderable/load-preamble.js'; + * + * const sessionWorkflowPreamble = loadPreambleFromMarkdown( + * 'docs-sources/session-workflow-guide.md' + * ); + * + * const annotationPreamble = loadPreambleFromMarkdown( + * 'docs-sources/annotation-guide.md' + * ); + * + * // In referenceDocConfigs: + * { + * title: 'Session Workflow Guide', + * preamble: [...sessionWorkflowPreamble], + * // ... + * } + * ``` + * + * ### File Resolution + * + * The `filePath` argument is resolved relative to the project root directory + * (the directory containing `package.json`). This matches how other config + * file paths are resolved in `delivery-process.config.ts`. + * + * ```typescript + * // These are equivalent: + * loadPreambleFromMarkdown('docs-sources/session-workflow-guide.md') + * // Resolves to: /absolute/path/to/project/docs-sources/session-workflow-guide.md + * ``` + */ + +import type { SectionBlock } from '../../../src/renderable/schema.js'; + +/** + * Reads a markdown file and parses it into a `readonly SectionBlock[]` array. + * + * Uses `readFileSync` (synchronous) — intended to run at config import time, + * not during codec decode. Resolves `filePath` relative to project root. + * + * @param _filePath - Path to markdown file, relative to project root + * @returns Parsed SectionBlock array suitable for ReferenceDocConfig.preamble + * + * @example + * ```typescript + * const preamble = loadPreambleFromMarkdown('docs-sources/session-workflow-guide.md'); + * // Returns: readonly SectionBlock[] with HeadingBlock, ParagraphBlock, + * // CodeBlock, MermaidBlock, TableBlock, ListBlock, SeparatorBlock + * ``` + */ +export function loadPreambleFromMarkdown( + _filePath: string +): readonly SectionBlock[] { + throw new Error('ProceduralGuideCodec not yet implemented - roadmap pattern'); +} diff --git a/delivery-process/stubs/procedural-guide-codec/procedural-codec-options.ts b/delivery-process/stubs/procedural-guide-codec/procedural-codec-options.ts new file mode 100644 index 00000000..8f28432b --- /dev/null +++ b/delivery-process/stubs/procedural-guide-codec/procedural-codec-options.ts @@ -0,0 +1,135 @@ +/** + * @libar-docs + * @libar-docs-status roadmap + * @libar-docs-implements ProceduralGuideCodec + * @libar-docs-target src/renderable/codecs/procedural-guide.ts + * + * ## ProceduralGuideCodecOptions -- Configuration Interface + * + * **Design Decision DD-1 (One codec, two configs):** + * A single `createProceduralGuideCodec()` factory produces both the session + * workflow guide and the annotation guide. The two documents share the same + * dual-source composition pattern (preamble editorial + auto-generated + * reference), but differ in their `ReferenceDocConfig` entries: different + * titles, different preamble content, different behavior source patterns, + * and different output paths. + * + * **Rationale (DD-1):** The codec class contains zero document-specific + * logic. All document-specific content is in the config: the preamble + * `SectionBlock[]` array carries editorial content, while + * `behaviorCategories` and the SessionGuidesModuleSource pattern name + * control which Rule: blocks are extracted. Creating two separate codec + * classes would duplicate the identical composition logic. This follows + * the precedent set by `createReferenceCodec()`, which produces 10+ + * different reference documents from different `ReferenceDocConfig` entries. + * + * **Design Decision DD-4 (Preamble from parsed markdown):** + * The preamble is a flat `SectionBlock[]` array produced by parsing a + * markdown source file via `loadPreambleFromMarkdown()` at config import + * time. Editorial content is organized by section headings in the markdown + * file (e.g., `## Session Decision Tree`, `## Getting Started`). This + * avoids introducing a new "named template section" abstraction -- the + * existing `SectionBlock` types (`heading`, `paragraph`, `table`, + * `mermaid`, `code`, `list`) are sufficient to express all procedural + * content, and standard markdown maps directly to these types. + * + * **Rationale (DD-4):** The preamble IS ~95% of the document, which is + * unusual but not architecturally different from a 10% preamble. The + * `SectionBlock[]` array is already the universal composition unit for + * all reference docs. Authoring this content as markdown (DD-7) instead + * of inline TypeScript object literals reduces config file size by ~540 + * lines while preserving the same `SectionBlock[]` shape that the codec + * receives. + * + * **Design Decision DD-3 (Checklists and decision trees via existing blocks):** + * Checklists use `ListBlock` with `- [ ] Step 1` text items (rendered + * as markdown checkbox syntax). Decision trees use `MermaidBlock` with + * `graph TD` diagrams. No new `ChecklistBlock` or `DecisionTreeBlock` + * types are introduced. + * + * **Rationale (DD-3):** The markdown renderer already emits `ListBlock` + * items as `- item` lines. Prefixing list items with `[ ] ` produces + * valid GitHub/Starlight checkbox syntax without any renderer changes. + * Mermaid `graph TD` diagrams are already a supported `SectionBlock` + * type (proven by product area docs and ReferenceDocShowcase). Adding + * new block types would require schema changes, renderer changes, and + * test updates -- all for rendering that existing types already handle. + * + * ### Integration with ReferenceDocConfig + * + * The ProceduralGuideCodec does NOT introduce a new config type. It + * reuses `ReferenceDocConfig` directly, with these fields populated: + * + * | Field | Session Workflow Guide | Annotation Guide | + * |-------|----------------------|------------------| + * | title | "Session Workflow Guide" | "Annotation Reference Guide" | + * | preamble | Checklists, Mermaid decision tree, Do-NOT tables | Getting-started, shape modes, troubleshooting | + * | behaviorCategories | [] (empty -- uses includeTags instead) | [] | + * | includeTags | ['session-workflows'] | [] | + * | conventionTags | [] | ['annotation-system'] | + * | shapeSources | [] | [] | + * | claudeMdSection | 'workflow' | 'annotation' | + * | docsFilename | 'SESSION-WORKFLOW-GUIDE.md' | 'ANNOTATION-REFERENCE.md' | + * | claudeMdFilename | 'session-workflow-guide.md' | 'annotation-reference.md' | + * + * The `includeTags` mechanism is preferred over `behaviorCategories` + * because SessionGuidesModuleSource needs to be explicitly opted-in + * via `@libar-docs-include:session-workflows` rather than category-matched. + * This allows precise control over which patterns contribute behavior + * content to each guide document. + */ + +import type { SectionBlock } from '../../../src/renderable/schema.js'; + +// --------------------------------------------------------------------------- +// No new options type needed -- ProceduralGuideCodec uses ReferenceDocConfig +// --------------------------------------------------------------------------- + +/** + * Type alias documenting the preamble content structure for session guides. + * The actual type is `readonly SectionBlock[]` from ReferenceDocConfig.preamble. + * + * Content organization within the flat SectionBlock[] array: + * + * Session Workflow Guide preamble sections (in order): + * 1. heading(2, 'Session Decision Tree') + MermaidBlock (graph TD) + * 2. heading(2, 'Planning Session') + checklist ListBlocks + Do-NOT table + * 3. heading(2, 'Design Session') + checklist ListBlocks + Do-NOT table + * 4. heading(2, 'Implementation Session') + execution order ListBlock + Do-NOT table + * 5. heading(2, 'Planning + Design Session') + combined checklist + * 6. heading(2, 'Handoff Documentation') + template CodeBlock + * 7. heading(2, 'FSM Protection Quick Reference') + FSM table + * + * Annotation Guide preamble sections (in order): + * 1. heading(2, 'Getting Started') + opt-in examples + prefix table + * 2. heading(2, 'Shape Extraction') + mode explanations + Zod gotcha + * 3. heading(2, 'Annotation Patterns by File Type') + per-type examples + * 4. heading(2, 'Verification') + CLI recipes + troubleshooting table + */ +export type ProceduralGuidePreamble = readonly SectionBlock[]; + +/** + * Validates that a preamble array contains the expected section structure + * for a session workflow guide. Used in tests to verify preamble completeness. + * + * @param _preamble - The preamble SectionBlock[] to validate + * @returns true if all expected sections are present + */ +export function validateSessionGuidePreamble( + _preamble: ProceduralGuidePreamble +): boolean { + throw new Error('ProceduralGuideCodec not yet implemented - roadmap pattern'); +} + +/** + * Validates that a preamble array contains the expected section structure + * for an annotation guide. Used in tests to verify preamble completeness. + * + * @param _preamble - The preamble SectionBlock[] to validate + * @returns true if all expected sections are present + */ +export function validateAnnotationGuidePreamble( + _preamble: ProceduralGuidePreamble +): boolean { + throw new Error('ProceduralGuideCodec not yet implemented - roadmap pattern'); +} diff --git a/delivery-process/stubs/procedural-guide-codec/procedural-codec.ts b/delivery-process/stubs/procedural-guide-codec/procedural-codec.ts new file mode 100644 index 00000000..e57f0203 --- /dev/null +++ b/delivery-process/stubs/procedural-guide-codec/procedural-codec.ts @@ -0,0 +1,209 @@ +/** + * @libar-docs + * @libar-docs-status roadmap + * @libar-docs-implements ProceduralGuideCodec + * @libar-docs-target src/renderable/codecs/procedural-guide.ts + * + * ## ProceduralGuideCodec -- Factory Stub for Dual-Source Procedural Guides + * + * **Design Decision DD-1 (One codec, two configs):** + * This codec IS `createReferenceCodec()`. The ProceduralGuideCodec does not + * introduce a new codec class. Instead, it adds two new `ReferenceDocConfig` + * entries to the `referenceDocConfigs` array in `delivery-process.config.ts`. + * Each entry configures `createReferenceCodec()` with document-specific + * preamble content and behavior extraction settings. + * + * **Why no new codec class is needed:** + * The existing `createReferenceCodec()` already supports all required + * composition: + * - `preamble: SectionBlock[]` -- carries ~95% editorial content + * - `includeTags: string[]` -- pulls Rule: blocks from SessionGuidesModuleSource + * - `behaviorCategories: string[]` -- category-based behavior extraction + * - `conventionTags: string[]` -- convention content extraction + * - Detail level rendering (summary vs detailed) -- already built + * + * The ProceduralGuideCodec "pattern" is therefore a configuration pattern, + * not a code pattern. The implementation deliverables are: + * 1. `loadPreambleFromMarkdown()` utility in `src/renderable/load-preamble.ts` + * 2. Two markdown source files in `docs-sources/` + * 3. Two `ReferenceDocConfig` entries in `delivery-process.config.ts` + * 4. `@libar-docs-include:session-workflows` tag on SessionGuidesModuleSource + * + * **Design Decision DD-2 (SessionGuidesModuleSource as behavior source):** + * The SessionGuidesModuleSource spec's Rule: blocks (Rules 3-8) are extracted + * via the existing `buildBehaviorSectionsFromPatterns()` function. This + * function already: + * - Extracts Invariant/Rationale via `parseBusinessRuleAnnotations()` + * - Extracts tables via `extractTablesFromDescription()` + * - Renders at two detail levels (summary: compact table, detailed: full rules) + * - Wraps 3+ rules in collapsible blocks for progressive disclosure + * + * The Rule: block tables in SessionGuidesModuleSource (session type contracts, + * Do/Do-NOT tables, FSM error reference, escape hatches) are ALREADY + * machine-extractable. The existing behavior extraction pipeline handles them + * without modification. + * + * **What the detailed level adds over the existing AI summary:** + * - Full Invariant + Rationale text (summary truncates to 120 chars) + * - Tables rendered as full markdown tables (summary omits tables) + * - Code examples from DocStrings (summary omits code) + * - Scenario names as "Verified by" lists (summary omits) + * + * The preamble content adds what Rule: blocks cannot express: + * - Step-by-step numbered checklists with checkbox syntax + * - Mermaid flowchart decision trees + * - CLI command examples with full bash code blocks + * - Cross-references to other docs + * + * **Design Decision DD-5 (Annotation guide: hybrid approach):** + * The annotation guide uses a hybrid approach: + * - ~95% preamble: getting-started walkthrough, shape extraction mode + * explanations, Zod gotcha, file-type annotation examples, verification + * CLI recipes, troubleshooting table + * - ~5% auto-generated: Tag reference summary table derived from taxonomy + * registry data via `createReferenceCodec()`'s existing convention or + * shape extraction. Tag groups, format types, and example values are + * already in MasterDataset. + * + * **Rationale (DD-5):** The annotation guide content is highly stable -- + * the getting-started walkthrough, shape extraction modes, and Zod gotcha + * have not changed since initial authoring. Making them preamble avoids + * the annotation overhead for content that changes at editorial cadence. + * The tag reference table is the one section that DOES change when tags + * are added -- auto-generating it eliminates a maintenance burden. + * + * **Design Decision DD-6 (Transition strategy):** + * The generated files output to `docs-live/reference/` (not `docs/`). + * The manual files (`docs/SESSION-GUIDES.md`, `docs/ANNOTATION-GUIDE.md`) + * are retained alongside the generated files during the transition period. + * The quality comparison deliverable produces an audit document recording + * section-by-section parity. Only after the audit confirms full parity + * are the manual files replaced with redirects to the generated output. + * + * **Rationale (DD-6):** The SessionGuidesModuleSource invariant (Rule 1) + * explicitly states SESSION-GUIDES.md "is not deleted, shortened, or + * replaced with a redirect." The generated file lives in a DIFFERENT + * directory (`docs-live/reference/`) and has a DIFFERENT name + * (`SESSION-WORKFLOW-GUIDE.md`). This means: + * - No violation of the Rule 1 invariant during transition + * - Both files can be compared side-by-side for quality audit + * - The manual file continues serving developers until parity is confirmed + * - After parity, Rule 1 can be explicitly superseded with an unlock-reason + * + * **Design Decision DD-7 (Markdown source files for editorial content):** + * Preamble content is authored as plain markdown files in `docs-sources/` + * and parsed into `SectionBlock[]` at config import time by + * `loadPreambleFromMarkdown()`. This replaces inline `SectionBlock[]` + * TypeScript object literals in the config file, reducing it from 853 + * to ~310 lines (63% reduction). Markdown is the natural authoring format + * for checklists, code blocks, tables, and Mermaid diagrams. + * + * **Rationale (DD-7):** The previous approach required ~541 lines of nested + * TypeScript object literals (`{ type: 'heading', level: 2, text: '...' }`) + * to express content that is more naturally written as markdown. The codec + * still receives `SectionBlock[]` in memory -- it never knows whether + * the preamble came from inline TypeScript or a parsed markdown file. + * Codec purity is preserved. + * + * **Design Decision DD-8 (loadPreambleFromMarkdown() shared utility):** + * A `loadPreambleFromMarkdown()` function in `src/renderable/load-preamble.ts` + * uses `readFileSync` (synchronous, runs at module import time) and a + * line-by-line state machine to parse markdown into `SectionBlock[]`. + * Available to all preamble consumers (ErrorGuideCodec, CliRecipeCodec). + * + * ### Implementation Plan + * + * Step 1: Create `loadPreambleFromMarkdown()` in `src/renderable/load-preamble.ts` + * Step 2: Create `docs-sources/session-workflow-guide.md` (content from current inline preamble) + * Step 3: Create `docs-sources/annotation-guide.md` (content from current inline preamble) + * Step 4: Update `delivery-process.config.ts` to use `loadPreambleFromMarkdown()` calls + * Step 5: Verify generated output matches current output (regression test) + * Step 6: Quality audit document comparing generated vs manual + */ + +// --------------------------------------------------------------------------- +// Example ReferenceDocConfig entries for delivery-process.config.ts +// --------------------------------------------------------------------------- + +import type { SectionBlock } from '../../../src/renderable/schema.js'; + +/** + * Placeholder interface showing the shape of a ReferenceDocConfig entry. + * The actual type is imported from `src/renderable/codecs/reference.ts`. + * This stub exists to document the design -- the real implementation adds + * entries directly to the `referenceDocConfigs` array. + */ +interface ReferenceDocConfigEntry { + readonly title: string; + readonly conventionTags: readonly string[]; + readonly shapeSources: readonly string[]; + readonly behaviorCategories: readonly string[]; + readonly includeTags?: readonly string[]; + readonly preamble?: readonly SectionBlock[]; + readonly claudeMdSection: string; + readonly docsFilename: string; + readonly claudeMdFilename: string; + readonly excludeSourcePaths?: readonly string[]; +} + +/** + * ReferenceDocConfig entry for the Session Workflow Guide. + * + * DD-7: Preamble loaded from markdown source file, not inline SectionBlock[]. + * + * ```typescript + * // In delivery-process.config.ts: + * import { loadPreambleFromMarkdown } from './src/renderable/load-preamble.js'; + * + * const sessionWorkflowPreamble = loadPreambleFromMarkdown( + * 'docs-sources/session-workflow-guide.md' + * ); + * + * // In referenceDocConfigs array: + * { + * title: 'Session Workflow Guide', + * conventionTags: [], + * shapeSources: [], + * behaviorCategories: [], + * includeTags: ['session-workflows'], + * claudeMdSection: 'workflow', + * docsFilename: 'SESSION-WORKFLOW-GUIDE.md', + * claudeMdFilename: 'session-workflow-guide.md', + * preamble: [...sessionWorkflowPreamble], + * } + * ``` + * + * Output: docs-live/reference/SESSION-WORKFLOW-GUIDE.md + */ +export function createSessionWorkflowGuideConfig( + _preamble: readonly SectionBlock[] +): ReferenceDocConfigEntry { + throw new Error('ProceduralGuideCodec not yet implemented - roadmap pattern'); +} + +/** + * ReferenceDocConfig entry for the Annotation Guide. + * + * DD-7: Preamble loaded from markdown source file. + * + * ```typescript + * const annotationPreamble = loadPreambleFromMarkdown( + * 'docs-sources/annotation-guide.md' + * ); + * + * // In referenceDocConfigs array: + * { + * title: 'Annotation Reference Guide', + * conventionTags: ['annotation-system'], + * preamble: [...annotationPreamble], + * // ... + * } + * ``` + * + * Output: docs-live/reference/ANNOTATION-REFERENCE.md + */ +export function createAnnotationGuideConfig( + _preamble: readonly SectionBlock[] +): ReferenceDocConfigEntry { + throw new Error('ProceduralGuideCodec not yet implemented - roadmap pattern'); +} diff --git a/delivery-process/stubs/procedural-guide-codec/session-guide-preamble.ts b/delivery-process/stubs/procedural-guide-codec/session-guide-preamble.ts new file mode 100644 index 00000000..879b48ac --- /dev/null +++ b/delivery-process/stubs/procedural-guide-codec/session-guide-preamble.ts @@ -0,0 +1,146 @@ +/** + * @libar-docs + * @libar-docs-status roadmap + * @libar-docs-implements ProceduralGuideCodec + * @libar-docs-target delivery-process.config.ts + * + * ## Session Workflow Guide — Markdown Source File Example + * + * **Design Decision DD-7 (Markdown source files):** + * The session workflow guide preamble content (~276 lines of inline + * `SectionBlock[]` TypeScript) is replaced by a plain markdown file at + * `docs-sources/session-workflow-guide.md`. This file is read and parsed + * into `SectionBlock[]` at config import time by `loadPreambleFromMarkdown()`. + * + * **Design Decision DD-3 (Checklists as ListBlock items):** + * Checklist items written as `- [ ] Step description` in markdown are parsed + * into `ListBlock` items with the `[ ] ` prefix preserved. The markdown + * renderer emits `- [ ] Step description` -- valid GitHub Flavored Markdown + * checkbox syntax rendered by Starlight as interactive checkboxes. + * + * **Design Decision DD-3 (Decision trees as MermaidBlock):** + * Mermaid code fences in the markdown source file are parsed into + * `MermaidBlock` entries (not `CodeBlock`). The session type decision tree + * renders as an interactive flowchart on the Starlight website. + * + * ### Content Mapping from SESSION-GUIDES.md + * + * | Manual Section (SESSION-GUIDES.md) | Markdown Element | Lines | + * |-----------------------------------|--------------------|-------| + * | Session Decision Tree (ASCII art) | Mermaid code fence (graph TD) | 9-16 | + * | Session type table | Markdown table | 18-23 | + * | Planning Session checklist | Unordered list with [ ] prefix | 40-79 | + * | Planning Do NOT list | Unordered list | 82-85 | + * | Design Session checklist | Unordered list with [ ] prefix | 117-153 | + * | Design Do NOT list | Unordered list | 154-159 | + * | Implementation execution order | Ordered list | 186-226 | + * | Implementation Do NOT table | Markdown table | 230-233 | + * | Planning+Design checklist | Unordered list | 249-276 | + * | Handoff template | Bash code fence | 333-350 | + * | FSM Protection table | Markdown table | 369-374 | + * + * Content NOT in preamble (auto-generated from SessionGuidesModuleSource): + * - Session type contract invariants (Rule 3) + * - FSM error reference table (Rule 7) + * - Escape hatches table (Rule 7) + * + * ### Config Usage Example + * + * ```typescript + * // In delivery-process.config.ts: + * import { loadPreambleFromMarkdown } from './src/renderable/load-preamble.js'; + * + * const sessionWorkflowPreamble = loadPreambleFromMarkdown( + * 'docs-sources/session-workflow-guide.md' + * ); + * + * // In referenceDocConfigs: + * { + * title: 'Session Workflow Guide', + * includeTags: ['session-workflows'], + * preamble: [...sessionWorkflowPreamble], + * docsFilename: 'SESSION-WORKFLOW-GUIDE.md', + * // ... + * } + * ``` + * + * ### Example Markdown Source File (abbreviated) + * + * The full file at `docs-sources/session-workflow-guide.md` contains all + * sections from the content mapping table above. This example shows the + * first few sections to illustrate the authoring format: + * + * ```markdown + * ## Session Decision Tree + * + * Use this flowchart to determine which session type to run. + * + * \`\`\`mermaid + * graph TD + * A[Starting from pattern brief?] -->|Yes| B[Need code stubs now?] + * A -->|No| C[Ready to code?] + * B -->|Yes| D[Planning + Design Session] + * B -->|No| E[Planning Session] + * C -->|Yes| F[Complex decisions?] + * C -->|No| E + * F -->|Yes| G[Design Session] + * F -->|No| H[Implementation Session] + * + * style D fill:#e1f5fe + * style E fill:#e8f5e9 + * style G fill:#fff3e0 + * style H fill:#fce4ec + * \`\`\` + * + * ## Session Type Contracts + * + * | Session | Input | Output | FSM Change | + * |---------|-------|--------|------------| + * | Planning | Pattern brief | Roadmap spec (`.feature`) | Creates `roadmap` | + * | Design | Complex requirement | Decision specs + code stubs | None | + * | Implementation | Roadmap spec | Code + tests | `roadmap` -> `active` -> `completed` | + * | Planning + Design | Pattern brief | Spec + stubs | Creates `roadmap` | + * + * --- + * + * ## Planning Session + * + * **Goal:** Create a roadmap spec. Do not write implementation code. + * + * ### Context Gathering + * + * \`\`\`bash + * pnpm process:query -- overview # Project health + * pnpm process:query -- list --status roadmap --names-only # Available patterns + * \`\`\` + * + * ### Planning Checklist + * + * - [ ] **Extract metadata** from pattern brief: phase, dependencies, status + * - [ ] **Create spec file** at `{specs-directory}/{product-area}/{pattern}.feature` + * - [ ] **Convert constraints to Rule: blocks** with Invariant/Rationale + * - [ ] **Add scenarios** per Rule: 1 happy-path + 1 validation minimum + * + * ### Planning Do NOT + * + * - Create `.ts` implementation files + * - Transition to `active` + * - Ask "Ready to implement?" + * + * --- + * ``` + * + * The `loadPreambleFromMarkdown()` parser converts this markdown into the + * same `SectionBlock[]` array that was previously authored inline: + * - `## Heading` -> `HeadingBlock { level: 2, text: '...' }` + * - Paragraphs -> `ParagraphBlock { text: '...' }` + * - `\`\`\`mermaid ... \`\`\`` -> `MermaidBlock { content: '...' }` + * - `\`\`\`bash ... \`\`\`` -> `CodeBlock { language: 'bash', content: '...' }` + * - `| col | col |` tables -> `TableBlock { columns: [...], rows: [...] }` + * - `- [ ] item` -> `ListBlock { items: ['[ ] item', ...] }` + * - `---` -> `SeparatorBlock` + */ + +export function _sessionGuidePreambleDesignStub(): never { + throw new Error('ProceduralGuideCodec not yet implemented - roadmap pattern'); +} diff --git a/docs-generated/BUSINESS-RULES.md b/docs-generated/BUSINESS-RULES.md deleted file mode 100644 index 99d05718..00000000 --- a/docs-generated/BUSINESS-RULES.md +++ /dev/null @@ -1,24 +0,0 @@ -# Business Rules - -**Purpose:** Domain constraints and invariants extracted from feature files -**Detail Level:** Overview with links to detailed business rules by product area - ---- - -**Domain constraints and invariants extracted from feature specifications. 554 rules from 120 features across 7 product areas.** - ---- - -## Product Areas - -| Product Area | Features | Rules | With Invariants | -| --- | --- | --- | --- | -| [Annotation](business-rules/annotation.md) | 20 | 88 | 88 | -| [Configuration](business-rules/configuration.md) | 7 | 32 | 32 | -| [CoreTypes](business-rules/core-types.md) | 5 | 22 | 22 | -| [DataAPI](business-rules/data-api.md) | 20 | 86 | 86 | -| [Generation](business-rules/generation.md) | 55 | 265 | 265 | -| [Process](business-rules/process.md) | 2 | 7 | 7 | -| [Validation](business-rules/validation.md) | 11 | 54 | 54 | - ---- diff --git a/docs-generated/TAXONOMY.md b/docs-generated/TAXONOMY.md deleted file mode 100644 index 05076ba2..00000000 --- a/docs-generated/TAXONOMY.md +++ /dev/null @@ -1,196 +0,0 @@ -# Taxonomy Reference - -**Purpose:** Tag taxonomy configuration for code-first documentation -**Detail Level:** Overview with links to details - ---- - -## Overview - -**3 categories** | **53 metadata tags** | **3 aggregation tags** - -Current configuration uses `@libar-docs-` prefix with `@libar-docs` file opt-in. - -| Component | Count | Description | -| --- | --- | --- | -| Categories | 3 | Pattern classification by domain | -| Metadata Tags | 53 | Pattern enrichment and relationships | -| Aggregation Tags | 3 | Document routing | - ---- - -## Categories - -Domain classifications for organizing patterns by priority. - -| Tag | Domain | Priority | Description | -| --- | --- | --- | --- | -| `core` | Core | 1 | Core patterns | -| `api` | API | 2 | Public APIs | -| `infra` | Infrastructure | 3 | Infrastructure | - -[Full category reference](taxonomy/categories.md) - ---- - -## Metadata Tags - -Tags for enriching patterns with additional metadata. - -### Core Tags - -| Tag | Format | Purpose | Required | Example | -| --- | --- | --- | --- | --- | -| `pattern` | value | Explicit pattern name | Yes | `@libar-docs-pattern CommandOrchestrator` | -| `status` | enum | Work item lifecycle status (per PDR-005 FSM) | No | `@libar-docs-status roadmap` | -| `core` | flag | Marks as essential/must-know pattern | No | `@libar-docs-core` | -| `usecase` | quoted-value | Use case association | No | `@libar-docs-usecase "When handling command failures"` | - -### Relationship Tags - -| Tag | Format | Purpose | Required | Example | -| --- | --- | --- | --- | --- | -| `uses` | csv | Patterns this depends on | No | `@libar-docs-uses CommandBus, EventStore` | -| `used-by` | csv | Patterns that depend on this | No | `@libar-docs-used-by SagaOrchestrator` | -| `depends-on` | csv | Roadmap dependencies (pattern or phase names) | No | `@libar-docs-depends-on EventStore, CommandBus` | -| `enables` | csv | Patterns this enables | No | `@libar-docs-enables SagaOrchestrator, ProjectionBuilder` | -| `implements` | csv | Patterns this code file realizes (realization relationship) | No | `@libar-docs-implements EventStoreDurability, IdempotentAppend` | -| `extends` | value | Base pattern this pattern extends (generalization relationship) | No | `@libar-docs-extends ProjectionCategories` | -| `see-also` | csv | Related patterns for cross-reference without dependency implication | No | `@libar-docs-see-also AgentAsBoundedContext, CrossContextIntegration` | -| `api-ref` | csv | File paths to implementation APIs (replaces 'See:' Markdown text in Rules) | No | `@libar-docs-api-ref @libar-dev/platform-core/src/durability/outbox.ts` | - -### Timeline Tags - -| Tag | Format | Purpose | Required | Example | -| --- | --- | --- | --- | --- | -| `phase` | number | Roadmap phase number (unified across monorepo) | No | `@libar-docs-phase 14` | -| `release` | value | Target release version (semver or vNEXT for unreleased work) | No | `@libar-docs-release v0.1.0` | -| `quarter` | value | Delivery quarter for timeline tracking | No | `@libar-docs-quarter Q1-2026` | -| `completed` | value | Completion date (YYYY-MM-DD format) | No | `@libar-docs-completed 2026-01-08` | -| `effort` | value | Estimated effort (4h, 2d, 1w format) | No | `@libar-docs-effort 2d` | -| `effort-actual` | value | Actual effort spent (4h, 2d, 1w format) | No | `@libar-docs-effort-actual 3d` | -| `team` | value | Responsible team assignment | No | `@libar-docs-team platform` | -| `workflow` | enum | Workflow discipline for process tracking | No | `@libar-docs-workflow implementation` | -| `risk` | enum | Risk level for planning | No | `@libar-docs-risk medium` | -| `priority` | enum | Priority level for roadmap ordering | No | `@libar-docs-priority high` | - -### ADR Tags - -| Tag | Format | Purpose | Required | Example | -| --- | --- | --- | --- | --- | -| `adr` | value | ADR/PDR number for decision tracking | No | `@libar-docs-adr 015` | -| `adr-status` | enum | ADR/PDR decision status | No | `@libar-docs-adr-status accepted` | -| `adr-category` | value | ADR/PDR category (architecture, process, tooling) | No | `@libar-docs-adr-category architecture` | -| `adr-supersedes` | value | ADR/PDR number this decision supersedes | No | `@libar-docs-adr-supersedes 012` | -| `adr-superseded-by` | value | ADR/PDR number that supersedes this decision | No | `@libar-docs-adr-superseded-by 020` | -| `adr-theme` | enum | Theme grouping for related decisions (from synthesis) | No | `@libar-docs-adr-theme persistence` | -| `adr-layer` | enum | Evolutionary layer of the decision | No | `@libar-docs-adr-layer foundation` | - -### Architecture Tags - -| Tag | Format | Purpose | Required | Example | -| --- | --- | --- | --- | --- | -| `arch-role` | enum | Architectural role for diagram generation (component type) | No | `@libar-docs-arch-role projection` | -| `arch-context` | value | Bounded context this component belongs to (for subgraph grouping) | No | `@libar-docs-arch-context orders` | -| `arch-layer` | enum | Architectural layer for layered diagrams | No | `@libar-docs-arch-layer application` | - -### Other Tags - -| Tag | Format | Purpose | Required | Example | -| --- | --- | --- | --- | --- | -| `brief` | value | Path to pattern brief markdown | No | `@libar-docs-brief docs/briefs/decider-pattern.md` | -| `product-area` | value | Product area for PRD grouping | No | `@libar-docs-product-area PlatformCore` | -| `user-role` | value | Target user persona for this feature | No | `@libar-docs-user-role Developer` | -| `business-value` | value | Business value statement (hyphenated for tag format) | No | `@libar-docs-business-value eliminates-event-replay-complexity` | -| `constraint` | value | Technical constraint affecting feature implementation | No | `@libar-docs-constraint requires-convex-backend` | -| `level` | enum | Hierarchy level for epic->phase->task breakdown | No | `@libar-docs-level epic` | -| `parent` | value | Parent pattern name in hierarchy (links tasks to phases, phases to epics) | No | `@libar-docs-parent AggregateArchitecture` | -| `title` | quoted-value | Human-readable display title (supports quoted values with spaces) | No | `@libar-docs-title:"Process Guard Linter"` | -| `executable-specs` | csv | Links roadmap spec to package executable spec locations (PDR-007) | No | `@libar-docs-executable-specs platform-decider/tests/features/behavior` | -| `roadmap-spec` | value | Links package spec back to roadmap pattern for traceability (PDR-007) | No | `@libar-docs-roadmap-spec DeciderPattern` | -| `behavior-file` | value | Path to behavior test feature file for traceability | No | `@libar-docs-behavior-file behavior/my-pattern.feature` | -| `discovered-gap` | value | Gap identified during session retrospective | No | `@libar-docs-discovered-gap missing-error-handling` | -| `discovered-improvement` | value | Improvement identified during session retrospective | No | `@libar-docs-discovered-improvement cache-invalidation` | -| `discovered-risk` | value | Risk identified during session retrospective | No | `@libar-docs-discovered-risk data-loss-on-migration` | -| `discovered-learning` | value | Learning captured during session retrospective | No | `@libar-docs-discovered-learning convex-mutation-limits` | -| `extract-shapes` | csv | TypeScript type names to extract from this file for documentation | No | `@libar-docs-extract-shapes DeciderInput, ValidationResult, ProcessViolation` | -| `shape` | value | Marks declaration as documentable shape, optionally with group name | No | `@libar-docs-shape api-types` | -| `include` | csv | Cross-cutting document inclusion for content routing and diagram scoping | No | `@libar-docs-include reference-sample,codec-system` | -| `target` | value | Target implementation path for stub files | No | `@libar-docs-target src/api/stub-resolver.ts` | -| `since` | value | Design session that created this pattern | No | `@libar-docs-since DS-A` | -| `convention` | csv | Convention domains for reference document generation from decision records | No | `@libar-docs-convention fsm-rules, testing-policy` | - -[Full metadata tag reference](taxonomy/metadata-tags.md) - ---- - -## Aggregation Tags - -Tags that route patterns to specific aggregated documents. - -| Tag | Target Document | Purpose | -| --- | --- | --- | -| `overview` | OVERVIEW.md | Architecture overview patterns | -| `decision` | DECISIONS.md | ADR-style decisions (auto-numbered) | -| `intro` | None | Package introduction (template placeholder) | - ---- - -## Format Types - -How tag values are parsed and validated. - -| Format | Description | Example | -| --- | --- | --- | -| `value` | Simple string value | `@libar-docs-pattern MyPattern` | -| `enum` | Constrained to predefined values | `@libar-docs-status roadmap` | -| `quoted-value` | String in quotes (preserves spaces) | `@libar-docs-usecase "When X happens"` | -| `csv` | Comma-separated values | `@libar-docs-uses A, B, C` | -| `number` | Numeric value | `@libar-docs-phase 14` | -| `flag` | Boolean presence (no value) | `@libar-docs-core` | - -[Format type details](taxonomy/format-types.md) - ---- - -## Presets - -Available configuration presets. - -| Preset | Tag Prefix | Categories | Use Case | -| --- | --- | --- | --- | -| `generic` | `@docs-` | 3 | Simple projects with @docs- prefix | -| `libar-generic` | `@libar-docs-` | 3 | Default preset with @libar-docs- prefix | -| `ddd-es-cqrs` | `@libar-docs-` | 21 | Full DDD/ES/CQRS taxonomy | - ---- - -## Architecture - -Taxonomy source files and pipeline flow. - -```plaintext -src/taxonomy/ -├── categories.ts # Category definitions (21 DDD-ES-CQRS) -├── format-types.ts # Format type constants -├── registry-builder.ts # Single source of truth builder -├── status-values.ts # Status FSM values -├── generator-options.ts # Generator option values -├── hierarchy-levels.ts # Hierarchy level values -├── risk-levels.ts # Risk level values -└── index.ts # Barrel export -``` - -```mermaid -graph LR - Config[Configuration] --> Scanner[Scanner] - Scanner --> Extractor[Extractor] - Extractor --> Transformer[Transformer] - Transformer --> Codec[Codec] - Codec --> Markdown[Markdown] - - Registry[TagRegistry] --> Scanner - Registry --> Extractor -``` - ---- diff --git a/docs-generated/_claude-md/architecture/reference-sample.md b/docs-generated/_claude-md/architecture/reference-sample.md deleted file mode 100644 index 54a3f70f..00000000 --- a/docs-generated/_claude-md/architecture/reference-sample.md +++ /dev/null @@ -1,172 +0,0 @@ -### Reference Generation Sample - -#### Product area canonical values - -**Invariant:** The product-area tag uses one of 7 canonical values. Each value represents a reader-facing documentation section, not a source module. - -| Value | Reader Question | Covers | -| --- | --- | --- | -| Annotation | How do I annotate code? | Scanning, extraction, tag parsing, dual-source | -| Configuration | How do I configure the tool? | Config loading, presets, resolution | -| Generation | How does code become docs? | Codecs, generators, rendering, diagrams | -| Validation | How is the workflow enforced? | FSM, DoD, anti-patterns, process guard, lint | -| DataAPI | How do I query process state? | Process state API, stubs, context assembly, CLI | -| CoreTypes | What foundational types exist? | Result monad, error factories, string utils | -| Process | How does the session workflow work? | Session lifecycle, handoffs, conventions | - - -#### ADR category canonical values - -**Invariant:** The adr-category tag uses one of 4 values. - -| Value | Purpose | -| --- | --- | -| architecture | System structure, component design, data flow | -| process | Workflow, conventions, annotation rules | -| testing | Test strategy, verification approach | -| documentation | Documentation generation, content structure | - - -#### FSM status values and protection levels - -**Invariant:** Pattern status uses exactly 4 values with defined protection levels. These are enforced by Process Guard at commit time. - -| Status | Protection | Can Add Deliverables | Allowed Actions | -| --- | --- | --- | --- | -| roadmap | None | Yes | Full editing | -| active | Scope-locked | No | Edit existing deliverables only | -| completed | Hard-locked | No | Requires unlock-reason tag | -| deferred | None | Yes | Full editing | - - -#### Valid FSM transitions - -**Invariant:** Only these transitions are valid. All others are rejected by Process Guard. - -| From | To | Trigger | -| --- | --- | --- | -| roadmap | active | Start work | -| roadmap | deferred | Postpone | -| active | completed | All deliverables done | -| active | roadmap | Blocked/regressed | -| deferred | roadmap | Resume planning | - - -#### Tag format types - -**Invariant:** Every tag has one of 6 format types that determines how its value is parsed. - -| Format | Parsing | Example | -| --- | --- | --- | -| flag | Boolean presence, no value | @libar-docs-core | -| value | Simple string | @libar-docs-pattern MyPattern | -| enum | Constrained to predefined list | @libar-docs-status completed | -| csv | Comma-separated values | @libar-docs-uses A, B, C | -| number | Numeric value | @libar-docs-phase 15 | -| quoted-value | Preserves spaces | @libar-docs-brief:'Multi word' | - - -#### Source ownership - -**Invariant:** Relationship tags have defined ownership by source type. Anti-pattern detection enforces these boundaries. - -| Tag | Correct Source | Wrong Source | Rationale | -| --- | --- | --- | --- | -| uses | TypeScript | Feature files | TS owns runtime dependencies | -| depends-on | Feature files | TypeScript | Gherkin owns planning dependencies | -| quarter | Feature files | TypeScript | Gherkin owns timeline metadata | -| team | Feature files | TypeScript | Gherkin owns ownership metadata | - - -#### Quarter format convention - -**Invariant:** The quarter tag uses `YYYY-QN` format (e.g., `2026-Q1`). ISO-year-first sorting works lexicographically. - - -#### Canonical phase definitions (6-phase USDP standard) - -**Invariant:** The default workflow defines exactly 6 phases in fixed order. These are the canonical phase names and ordinals used by all generated documentation. - -| Order | Phase | Purpose | -| --- | --- | --- | -| 1 | Inception | Problem framing, scope definition | -| 2 | Elaboration | Design decisions, architecture exploration | -| 3 | Session | Planning and design session work | -| 4 | Construction | Implementation, testing, integration | -| 5 | Validation | Verification, acceptance criteria confirmation | -| 6 | Retrospective | Review, lessons learned, documentation | - - -#### Deliverable status canonical values - -**Invariant:** Deliverable status (distinct from pattern FSM status) uses exactly 6 values, enforced by Zod schema at parse time. - -| Value | Meaning | -| --- | --- | -| complete | Work is done | -| in-progress | Work is ongoing | -| pending | Work has not started | -| deferred | Work postponed | -| superseded | Replaced by another | -| n/a | Not applicable | - - -#### API Types - -| Type | Kind | -| --- | --- | -| SectionBlock | type | -| normalizeStatus | function | -| DELIVERABLE_STATUS_VALUES | const | -| CategoryDefinition | interface | - - -#### Behavior Specifications - -##### DeliveryProcessFactory - -##### DefineConfig - -##### ADR005CodecBasedMarkdownRendering - -| Rule | Description | -| --- | --- | -| Codecs implement a decode-only contract | **Invariant:** Every codec is a pure function that accepts a MasterDataset
and returns a RenderableDocument.... | -| RenderableDocument is a typed intermediate representation | **Invariant:** RenderableDocument contains a title, an ordered array of
SectionBlock elements, and an optional... | -| CompositeCodec assembles documents from child codecs | **Invariant:** CompositeCodec accepts an array of child codecs and
produces a single RenderableDocument by... | -| ADR content comes from both Feature description and Rule prefixes | **Invariant:** ADR structured content (Context, Decision, Consequences)
can appear in two locations within a... | -| The markdown renderer is codec-agnostic | **Invariant:** The renderer accepts any RenderableDocument regardless of
which codec produced it. Rendering... | - -##### ADR001TaxonomyCanonicalValues - -| Rule | Description | -| --- | --- | -| Product area canonical values | **Invariant:** The product-area tag uses one of 7 canonical values.
Each value represents a reader-facing... | -| ADR category canonical values | **Invariant:** The adr-category tag uses one of 4 values.
**Rationale:** Unbounded category values prevent... | -| FSM status values and protection levels | **Invariant:** Pattern status uses exactly 4 values with defined
protection levels. These are enforced by Process... | -| Valid FSM transitions | **Invariant:** Only these transitions are valid. All others are
rejected by Process Guard.
**Rationale:**... | -| Tag format types | **Invariant:** Every tag has one of 6 format types that determines
how its value is parsed.
**Rationale:**... | -| Source ownership | **Invariant:** Relationship tags have defined ownership by source type.
Anti-pattern detection enforces these... | -| Quarter format convention | **Invariant:** The quarter tag uses `YYYY-QN` format (e.g., `2026-Q1`).
ISO-year-first sorting works... | -| Canonical phase definitions (6-phase USDP standard) | **Invariant:** The default workflow defines exactly 6 phases in fixed
order. These are the canonical phase names... | -| Deliverable status canonical values | **Invariant:** Deliverable status (distinct from pattern FSM status)
uses exactly 6 values, enforced by Zod... | - -##### ConfigBasedWorkflowDefinition - -| Rule | Description | -| --- | --- | -| Default workflow is built from an inline constant | **Invariant:** `loadDefaultWorkflow()` returns a `LoadedWorkflow` without
file system access. It cannot fail. The... | -| Custom workflow files still work via --workflow flag | **Invariant:** `loadWorkflowFromPath()` remains available for projects
that need custom workflow definitions. The... | -| FSM validation and Process Guard are not affected | **Invariant:** The FSM transition matrix, protection levels, and Process
Guard rules remain hardcoded in... | -| Workflow as a configurable preset field is deferred | **Invariant:** The inline default workflow constant is the only workflow source until preset integration is... | - -##### ProcessGuardTesting - -| Rule | Description | -| --- | --- | -| Completed files require unlock-reason to modify | **Invariant:** A completed spec file cannot be modified unless it carries an @libar-docs-unlock-reason tag.... | -| Status transitions must follow PDR-005 FSM | **Invariant:** Status changes must follow the directed graph: roadmap->active->completed, roadmap<->deferred,... | -| Active specs cannot add new deliverables | **Invariant:** A spec in active status cannot have deliverables added that were not present when it entered active.... | -| Files outside active session scope trigger warnings | **Invariant:** Files modified outside the active session's declared scope produce a session-scope warning.... | -| Explicitly excluded files trigger errors | **Invariant:** Files explicitly excluded from a session cannot be modified, producing a session-excluded error.... | -| Multiple rules validate independently | **Invariant:** Each validation rule evaluates independently — a single file can produce violations from multiple... | diff --git a/docs-generated/taxonomy/categories.md b/docs-generated/taxonomy/categories.md deleted file mode 100644 index 0c75488f..00000000 --- a/docs-generated/taxonomy/categories.md +++ /dev/null @@ -1,33 +0,0 @@ -# Category Reference - -**Purpose:** Complete category definitions with aliases and domain groupings - ---- - -## Category Definitions - -3 categories sorted by priority. - -| Tag | Domain | Priority | Description | Aliases | -| --- | --- | --- | --- | --- | -| `core` | Core | 1 | Core patterns | - | -| `api` | API | 2 | Public APIs | - | -| `infra` | Infrastructure | 3 | Infrastructure | `infrastructure` | - -## Categories by Domain - -### Core - -`core` - -### API - -`api` - -### Infrastructure - -`infra` - ---- - -[Back to Taxonomy Reference](../TAXONOMY.md) diff --git a/docs-generated/taxonomy/format-types.md b/docs-generated/taxonomy/format-types.md deleted file mode 100644 index 6fab3817..00000000 --- a/docs-generated/taxonomy/format-types.md +++ /dev/null @@ -1,67 +0,0 @@ -# Format Type Reference - -**Purpose:** Detailed format type parsing behavior and examples - ---- - -## Format Type Reference - -Detailed parsing behavior for each format type. - -### `value` - -| Property | Value | -| --- | --- | -| Description | Simple string value | -| Parsing Behavior | Captures everything after the tag name as the value | -| Example | `@libar-docs-pattern CommandOrchestrator` | -| Notes | Most common format for single-value tags | - -### `enum` - -| Property | Value | -| --- | --- | -| Description | Constrained to predefined values | -| Parsing Behavior | Validates value against allowed list; rejects invalid values | -| Example | `@libar-docs-status roadmap` | -| Notes | Used for FSM states, priority levels, risk levels | - -### `quoted-value` - -| Property | Value | -| --- | --- | -| Description | String in quotes (preserves spaces) | -| Parsing Behavior | Extracts content between quotes; preserves internal whitespace | -| Example | `@libar-docs-usecase "When a user submits a form"` | -| Notes | Use for human-readable text with spaces | - -### `csv` - -| Property | Value | -| --- | --- | -| Description | Comma-separated values | -| Parsing Behavior | Splits on commas; trims whitespace from each value | -| Example | `@libar-docs-uses CommandBus, EventStore, Projection` | -| Notes | Used for relationship tags and multi-value references | - -### `number` - -| Property | Value | -| --- | --- | -| Description | Numeric value | -| Parsing Behavior | Parses as integer; NaN if invalid | -| Example | `@libar-docs-phase 14` | -| Notes | Used for phase numbers and ordering | - -### `flag` - -| Property | Value | -| --- | --- | -| Description | Boolean presence (no value needed) | -| Parsing Behavior | Presence of tag indicates true; absence indicates false | -| Example | `@libar-docs-core` | -| Notes | Used for boolean markers like core, overview, decision | - ---- - -[Back to Taxonomy Reference](../TAXONOMY.md) diff --git a/docs-generated/taxonomy/metadata-tags.md b/docs-generated/taxonomy/metadata-tags.md deleted file mode 100644 index cf187640..00000000 --- a/docs-generated/taxonomy/metadata-tags.md +++ /dev/null @@ -1,615 +0,0 @@ -# Metadata Tag Reference - -**Purpose:** Complete metadata tag definitions with all fields - ---- - -## Metadata Tag Definitions - -53 metadata tags with full details. - -| Tag | Format | Purpose | Required | Repeatable | Values | Default | -| --- | --- | --- | --- | --- | --- | --- | -| `pattern` | value | Explicit pattern name | Yes | No | - | - | -| `status` | enum | Work item lifecycle status (per PDR-005 FSM) | No | No | roadmap, active, completed, deferred | roadmap | -| `core` | flag | Marks as essential/must-know pattern | No | No | - | - | -| `usecase` | quoted-value | Use case association | No | Yes | - | - | -| `uses` | csv | Patterns this depends on | No | No | - | - | -| `used-by` | csv | Patterns that depend on this | No | No | - | - | -| `phase` | number | Roadmap phase number (unified across monorepo) | No | No | - | - | -| `release` | value | Target release version (semver or vNEXT for unreleased work) | No | No | - | - | -| `brief` | value | Path to pattern brief markdown | No | No | - | - | -| `depends-on` | csv | Roadmap dependencies (pattern or phase names) | No | No | - | - | -| `enables` | csv | Patterns this enables | No | No | - | - | -| `implements` | csv | Patterns this code file realizes (realization relationship) | No | No | - | - | -| `extends` | value | Base pattern this pattern extends (generalization relationship) | No | No | - | - | -| `quarter` | value | Delivery quarter for timeline tracking | No | No | - | - | -| `completed` | value | Completion date (YYYY-MM-DD format) | No | No | - | - | -| `effort` | value | Estimated effort (4h, 2d, 1w format) | No | No | - | - | -| `effort-actual` | value | Actual effort spent (4h, 2d, 1w format) | No | No | - | - | -| `team` | value | Responsible team assignment | No | No | - | - | -| `workflow` | enum | Workflow discipline for process tracking | No | No | implementation, planning, validation, documentation | - | -| `risk` | enum | Risk level for planning | No | No | low, medium, high | - | -| `priority` | enum | Priority level for roadmap ordering | No | No | critical, high, medium, low | - | -| `product-area` | value | Product area for PRD grouping | No | No | - | - | -| `user-role` | value | Target user persona for this feature | No | No | - | - | -| `business-value` | value | Business value statement (hyphenated for tag format) | No | No | - | - | -| `constraint` | value | Technical constraint affecting feature implementation | No | Yes | - | - | -| `adr` | value | ADR/PDR number for decision tracking | No | No | - | - | -| `adr-status` | enum | ADR/PDR decision status | No | No | proposed, accepted, deprecated, superseded | proposed | -| `adr-category` | value | ADR/PDR category (architecture, process, tooling) | No | No | - | - | -| `adr-supersedes` | value | ADR/PDR number this decision supersedes | No | No | - | - | -| `adr-superseded-by` | value | ADR/PDR number that supersedes this decision | No | No | - | - | -| `adr-theme` | enum | Theme grouping for related decisions (from synthesis) | No | No | persistence, isolation, commands, projections, coordination, taxonomy, testing | - | -| `adr-layer` | enum | Evolutionary layer of the decision | No | No | foundation, infrastructure, refinement | - | -| `level` | enum | Hierarchy level for epic->phase->task breakdown | No | No | epic, phase, task | phase | -| `parent` | value | Parent pattern name in hierarchy (links tasks to phases, phases to epics) | No | No | - | - | -| `title` | quoted-value | Human-readable display title (supports quoted values with spaces) | No | No | - | - | -| `executable-specs` | csv | Links roadmap spec to package executable spec locations (PDR-007) | No | No | - | - | -| `roadmap-spec` | value | Links package spec back to roadmap pattern for traceability (PDR-007) | No | No | - | - | -| `behavior-file` | value | Path to behavior test feature file for traceability | No | No | - | - | -| `discovered-gap` | value | Gap identified during session retrospective | No | Yes | - | - | -| `discovered-improvement` | value | Improvement identified during session retrospective | No | Yes | - | - | -| `discovered-risk` | value | Risk identified during session retrospective | No | Yes | - | - | -| `discovered-learning` | value | Learning captured during session retrospective | No | Yes | - | - | -| `see-also` | csv | Related patterns for cross-reference without dependency implication | No | No | - | - | -| `api-ref` | csv | File paths to implementation APIs (replaces 'See:' Markdown text in Rules) | No | No | - | - | -| `extract-shapes` | csv | TypeScript type names to extract from this file for documentation | No | No | - | - | -| `shape` | value | Marks declaration as documentable shape, optionally with group name | No | No | - | - | -| `arch-role` | enum | Architectural role for diagram generation (component type) | No | No | bounded-context, command-handler, projection, saga, process-manager, infrastructure, repository, decider, read-model, service | - | -| `arch-context` | value | Bounded context this component belongs to (for subgraph grouping) | No | No | - | - | -| `arch-layer` | enum | Architectural layer for layered diagrams | No | No | domain, application, infrastructure | - | -| `include` | csv | Cross-cutting document inclusion for content routing and diagram scoping | No | No | - | - | -| `target` | value | Target implementation path for stub files | No | No | - | - | -| `since` | value | Design session that created this pattern | No | No | - | - | -| `convention` | csv | Convention domains for reference document generation from decision records | No | No | testing-policy, fsm-rules, cli-patterns, output-format, pattern-naming, session-workflow, config-presets, annotation-system, pipeline-architecture, publishing, doc-generation, taxonomy-rules | - | - -## Tag Details - -### `pattern` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Explicit pattern name | -| Required | Yes | -| Repeatable | No | -| Example | `@libar-docs-pattern CommandOrchestrator` | - -### `status` - -| Property | Value | -| --- | --- | -| Format | enum | -| Purpose | Work item lifecycle status (per PDR-005 FSM) | -| Required | No | -| Repeatable | No | -| Valid Values | roadmap, active, completed, deferred | -| Default | roadmap | -| Example | `@libar-docs-status roadmap` | - -### `core` - -| Property | Value | -| --- | --- | -| Format | flag | -| Purpose | Marks as essential/must-know pattern | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-core` | - -### `usecase` - -| Property | Value | -| --- | --- | -| Format | quoted-value | -| Purpose | Use case association | -| Required | No | -| Repeatable | Yes | -| Example | `@libar-docs-usecase "When handling command failures"` | - -### `uses` - -| Property | Value | -| --- | --- | -| Format | csv | -| Purpose | Patterns this depends on | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-uses CommandBus, EventStore` | - -### `used-by` - -| Property | Value | -| --- | --- | -| Format | csv | -| Purpose | Patterns that depend on this | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-used-by SagaOrchestrator` | - -### `phase` - -| Property | Value | -| --- | --- | -| Format | number | -| Purpose | Roadmap phase number (unified across monorepo) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-phase 14` | - -### `release` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Target release version (semver or vNEXT for unreleased work) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-release v0.1.0` | - -### `brief` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Path to pattern brief markdown | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-brief docs/briefs/decider-pattern.md` | - -### `depends-on` - -| Property | Value | -| --- | --- | -| Format | csv | -| Purpose | Roadmap dependencies (pattern or phase names) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-depends-on EventStore, CommandBus` | - -### `enables` - -| Property | Value | -| --- | --- | -| Format | csv | -| Purpose | Patterns this enables | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-enables SagaOrchestrator, ProjectionBuilder` | - -### `implements` - -| Property | Value | -| --- | --- | -| Format | csv | -| Purpose | Patterns this code file realizes (realization relationship) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-implements EventStoreDurability, IdempotentAppend` | - -### `extends` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Base pattern this pattern extends (generalization relationship) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-extends ProjectionCategories` | - -### `quarter` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Delivery quarter for timeline tracking | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-quarter Q1-2026` | - -### `completed` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Completion date (YYYY-MM-DD format) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-completed 2026-01-08` | - -### `effort` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Estimated effort (4h, 2d, 1w format) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-effort 2d` | - -### `effort-actual` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Actual effort spent (4h, 2d, 1w format) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-effort-actual 3d` | - -### `team` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Responsible team assignment | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-team platform` | - -### `workflow` - -| Property | Value | -| --- | --- | -| Format | enum | -| Purpose | Workflow discipline for process tracking | -| Required | No | -| Repeatable | No | -| Valid Values | implementation, planning, validation, documentation | -| Example | `@libar-docs-workflow implementation` | - -### `risk` - -| Property | Value | -| --- | --- | -| Format | enum | -| Purpose | Risk level for planning | -| Required | No | -| Repeatable | No | -| Valid Values | low, medium, high | -| Example | `@libar-docs-risk medium` | - -### `priority` - -| Property | Value | -| --- | --- | -| Format | enum | -| Purpose | Priority level for roadmap ordering | -| Required | No | -| Repeatable | No | -| Valid Values | critical, high, medium, low | -| Example | `@libar-docs-priority high` | - -### `product-area` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Product area for PRD grouping | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-product-area PlatformCore` | - -### `user-role` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Target user persona for this feature | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-user-role Developer` | - -### `business-value` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Business value statement (hyphenated for tag format) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-business-value eliminates-event-replay-complexity` | - -### `constraint` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Technical constraint affecting feature implementation | -| Required | No | -| Repeatable | Yes | -| Example | `@libar-docs-constraint requires-convex-backend` | - -### `adr` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | ADR/PDR number for decision tracking | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-adr 015` | - -### `adr-status` - -| Property | Value | -| --- | --- | -| Format | enum | -| Purpose | ADR/PDR decision status | -| Required | No | -| Repeatable | No | -| Valid Values | proposed, accepted, deprecated, superseded | -| Default | proposed | -| Example | `@libar-docs-adr-status accepted` | - -### `adr-category` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | ADR/PDR category (architecture, process, tooling) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-adr-category architecture` | - -### `adr-supersedes` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | ADR/PDR number this decision supersedes | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-adr-supersedes 012` | - -### `adr-superseded-by` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | ADR/PDR number that supersedes this decision | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-adr-superseded-by 020` | - -### `adr-theme` - -| Property | Value | -| --- | --- | -| Format | enum | -| Purpose | Theme grouping for related decisions (from synthesis) | -| Required | No | -| Repeatable | No | -| Valid Values | persistence, isolation, commands, projections, coordination, taxonomy, testing | -| Example | `@libar-docs-adr-theme persistence` | - -### `adr-layer` - -| Property | Value | -| --- | --- | -| Format | enum | -| Purpose | Evolutionary layer of the decision | -| Required | No | -| Repeatable | No | -| Valid Values | foundation, infrastructure, refinement | -| Example | `@libar-docs-adr-layer foundation` | - -### `level` - -| Property | Value | -| --- | --- | -| Format | enum | -| Purpose | Hierarchy level for epic->phase->task breakdown | -| Required | No | -| Repeatable | No | -| Valid Values | epic, phase, task | -| Default | phase | -| Example | `@libar-docs-level epic` | - -### `parent` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Parent pattern name in hierarchy (links tasks to phases, phases to epics) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-parent AggregateArchitecture` | - -### `title` - -| Property | Value | -| --- | --- | -| Format | quoted-value | -| Purpose | Human-readable display title (supports quoted values with spaces) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-title:"Process Guard Linter"` | - -### `executable-specs` - -| Property | Value | -| --- | --- | -| Format | csv | -| Purpose | Links roadmap spec to package executable spec locations (PDR-007) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-executable-specs platform-decider/tests/features/behavior` | - -### `roadmap-spec` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Links package spec back to roadmap pattern for traceability (PDR-007) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-roadmap-spec DeciderPattern` | - -### `behavior-file` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Path to behavior test feature file for traceability | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-behavior-file behavior/my-pattern.feature` | - -### `discovered-gap` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Gap identified during session retrospective | -| Required | No | -| Repeatable | Yes | -| Example | `@libar-docs-discovered-gap missing-error-handling` | - -### `discovered-improvement` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Improvement identified during session retrospective | -| Required | No | -| Repeatable | Yes | -| Example | `@libar-docs-discovered-improvement cache-invalidation` | - -### `discovered-risk` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Risk identified during session retrospective | -| Required | No | -| Repeatable | Yes | -| Example | `@libar-docs-discovered-risk data-loss-on-migration` | - -### `discovered-learning` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Learning captured during session retrospective | -| Required | No | -| Repeatable | Yes | -| Example | `@libar-docs-discovered-learning convex-mutation-limits` | - -### `see-also` - -| Property | Value | -| --- | --- | -| Format | csv | -| Purpose | Related patterns for cross-reference without dependency implication | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-see-also AgentAsBoundedContext, CrossContextIntegration` | - -### `api-ref` - -| Property | Value | -| --- | --- | -| Format | csv | -| Purpose | File paths to implementation APIs (replaces 'See:' Markdown text in Rules) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-api-ref @libar-dev/platform-core/src/durability/outbox.ts` | - -### `extract-shapes` - -| Property | Value | -| --- | --- | -| Format | csv | -| Purpose | TypeScript type names to extract from this file for documentation | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-extract-shapes DeciderInput, ValidationResult, ProcessViolation` | - -### `shape` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Marks declaration as documentable shape, optionally with group name | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-shape api-types` | - -### `arch-role` - -| Property | Value | -| --- | --- | -| Format | enum | -| Purpose | Architectural role for diagram generation (component type) | -| Required | No | -| Repeatable | No | -| Valid Values | bounded-context, command-handler, projection, saga, process-manager, infrastructure, repository, decider, read-model, service | -| Example | `@libar-docs-arch-role projection` | - -### `arch-context` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Bounded context this component belongs to (for subgraph grouping) | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-arch-context orders` | - -### `arch-layer` - -| Property | Value | -| --- | --- | -| Format | enum | -| Purpose | Architectural layer for layered diagrams | -| Required | No | -| Repeatable | No | -| Valid Values | domain, application, infrastructure | -| Example | `@libar-docs-arch-layer application` | - -### `include` - -| Property | Value | -| --- | --- | -| Format | csv | -| Purpose | Cross-cutting document inclusion for content routing and diagram scoping | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-include reference-sample,codec-system` | - -### `target` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Target implementation path for stub files | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-target src/api/stub-resolver.ts` | - -### `since` - -| Property | Value | -| --- | --- | -| Format | value | -| Purpose | Design session that created this pattern | -| Required | No | -| Repeatable | No | -| Example | `@libar-docs-since DS-A` | - -### `convention` - -| Property | Value | -| --- | --- | -| Format | csv | -| Purpose | Convention domains for reference document generation from decision records | -| Required | No | -| Repeatable | No | -| Valid Values | testing-policy, fsm-rules, cli-patterns, output-format, pattern-naming, session-workflow, config-presets, annotation-system, pipeline-architecture, publishing, doc-generation, taxonomy-rules | -| Example | `@libar-docs-convention fsm-rules, testing-policy` | - ---- - -[Back to Taxonomy Reference](../TAXONOMY.md) diff --git a/docs-live/ARCHITECTURE.md b/docs-live/ARCHITECTURE.md new file mode 100644 index 00000000..d07a7e25 --- /dev/null +++ b/docs-live/ARCHITECTURE.md @@ -0,0 +1,564 @@ +# Architecture + +**Purpose:** Auto-generated architecture diagram from source annotations +**Detail Level:** Component diagram with bounded context subgraphs + +--- + +## Overview + +This diagram was auto-generated from 155 annotated source files across 11 bounded contexts. + +| Metric | Count | +| ---------------- | ----- | +| Total Components | 155 | +| Bounded Contexts | 11 | +| Component Roles | 5 | + +--- + +## System Overview + +Component architecture with bounded context isolation: + +```mermaid +graph TB + subgraph api["Api BC"] + MasterDataset["MasterDataset[read-model]"] + ProcessStateTypes["ProcessStateTypes"] + PatternSummarizerImpl["PatternSummarizerImpl[service]"] + StubResolverImpl["StubResolverImpl"] + ScopeValidatorImpl["ScopeValidatorImpl[service]"] + RulesQueryModule["RulesQueryModule"] + ProcessStateAPI["ProcessStateAPI[service]"] + PatternHelpers["PatternHelpers"] + APIModule["APIModule"] + HandoffGeneratorImpl["HandoffGeneratorImpl[service]"] + FuzzyMatcherImpl["FuzzyMatcherImpl[service]"] + CoverageAnalyzerImpl["CoverageAnalyzerImpl[service]"] + ContextFormatterImpl["ContextFormatterImpl[service]"] + ContextAssemblerImpl["ContextAssemblerImpl[service]"] + ArchQueriesImpl["ArchQueriesImpl[service]"] + end + subgraph cli["Cli BC"] + CLIVersionHelper["CLIVersionHelper"] + ValidatePatternsCLI["ValidatePatternsCLI"] + ProcessAPICLIImpl["ProcessAPICLIImpl[service]"] + OutputPipelineImpl["OutputPipelineImpl[service]"] + LintProcessCLI["LintProcessCLI"] + LintPatternsCLI["LintPatternsCLI"] + TagTaxonomyCLI["TagTaxonomyCLI"] + Documentation_Generator_CLI["Documentation Generator CLI"] + CLIErrorHandler["CLIErrorHandler"] + CLISchema["CLISchema"] + end + subgraph config["Config BC"] + WorkflowLoader["WorkflowLoader[infrastructure]"] + ConfigurationTypes["ConfigurationTypes"] + ConfigResolver["ConfigResolver[service]"] + RegexBuilders["RegexBuilders[infrastructure]"] + ProjectConfigTypes["ProjectConfigTypes"] + ProjectConfigSchema["ProjectConfigSchema[infrastructure]"] + ConfigurationPresets["ConfigurationPresets"] + SourceMerger["SourceMerger[service]"] + DeliveryProcessFactory["DeliveryProcessFactory[service]"] + DefineConfig["DefineConfig[infrastructure]"] + ConfigurationDefaults["ConfigurationDefaults"] + ConfigLoader["ConfigLoader[infrastructure]"] + end + subgraph extractor["Extractor BC"] + ShapeExtractor["ShapeExtractor"] + LayerInference["LayerInference"] + GherkinExtractor["GherkinExtractor[service]"] + DualSourceExtractor["DualSourceExtractor[service]"] + Document_Extractor["Document Extractor[service]"] + end + subgraph generator["Generator BC"] + FileCache["FileCache[infrastructure]"] + WarningCollector["WarningCollector"] + GeneratorTypes["GeneratorTypes"] + SourceMappingValidator["SourceMappingValidator"] + SourceMapper["SourceMapper[infrastructure]"] + GeneratorRegistry["GeneratorRegistry"] + Documentation_Generation_Orchestrator["Documentation Generation Orchestrator[service]"] + ContentDeduplicator["ContentDeduplicator[infrastructure]"] + CodecBasedGenerator["CodecBasedGenerator[service]"] + TransformDataset["TransformDataset[service]"] + MergePatterns["MergePatterns"] + PipelineModule["PipelineModule"] + PipelineFactory["PipelineFactory"] + ReferenceGeneratorRegistration["ReferenceGeneratorRegistration"] + ProcessApiReferenceGenerator["ProcessApiReferenceGenerator"] + BuiltInGenerators["BuiltInGenerators"] + DecisionDocGenerator["DecisionDocGenerator[service]"] + CodecGeneratorRegistration["CodecGeneratorRegistration"] + CliRecipeGenerator["CliRecipeGenerator"] + end + subgraph lint["Lint BC"] + LintRules["LintRules[service]"] + LintModule["LintModule"] + LintEngine["LintEngine[service]"] + ProcessGuardTypes["ProcessGuardTypes"] + ProcessGuardModule["ProcessGuardModule"] + DetectChanges["DetectChanges"] + DeriveProcessState["DeriveProcessState"] + ProcessGuardDecider["ProcessGuardDecider[decider]"] + end + subgraph renderer["Renderer BC"] + RenderableUtils["RenderableUtils"] + RenderableDocument["RenderableDocument[read-model]"] + SectionBlock["SectionBlock"] + UniversalRenderer["UniversalRenderer[service]"] + loadPreambleFromMarkdown___Shared_Markdown_to_SectionBlock_Parser["loadPreambleFromMarkdown — Shared Markdown-to-SectionBlock Parser"] + RenderableDocumentModel_RDM_["RenderableDocumentModel(RDM)"] + DocumentGenerator["DocumentGenerator[service]"] + ValidationRulesCodec["ValidationRulesCodec"] + TimelineCodec["TimelineCodec"] + TaxonomyCodec["TaxonomyCodec"] + SharedCodecSchema["SharedCodecSchema"] + SessionCodec["SessionCodec[projection]"] + RequirementsCodec["RequirementsCodec"] + ReportingCodecs["ReportingCodecs"] + ReferenceDocumentCodec["ReferenceDocumentCodec"] + PrChangesCodec["PrChangesCodec"] + PlanningCodecs["PlanningCodecs"] + PatternsCodec["PatternsCodec[projection]"] + DocumentCodecs["DocumentCodecs"] + IndexCodec["IndexCodec"] + RichContentHelpers["RichContentHelpers"] + MermaidDiagramUtils["MermaidDiagramUtils"] + DecisionDocCodec["DecisionDocCodec[projection]"] + CompositeCodec["CompositeCodec[projection]"] + ClaudeModuleCodec["ClaudeModuleCodec"] + BusinessRulesCodec["BusinessRulesCodec"] + ArchitectureCodec["ArchitectureCodec[projection]"] + AdrDocumentCodec["AdrDocumentCodec"] + CodecBaseOptions["CodecBaseOptions"] + end + subgraph scanner["Scanner BC"] + Pattern_Scanner["Pattern Scanner[infrastructure]"] + GherkinScanner["GherkinScanner[infrastructure]"] + GherkinASTParser["GherkinASTParser[infrastructure]"] + TypeScript_AST_Parser["TypeScript AST Parser[infrastructure]"] + end + subgraph taxonomy["Taxonomy BC"] + StatusValues["StatusValues"] + RiskLevels["RiskLevels"] + TagRegistryBuilder["TagRegistryBuilder[service]"] + NormalizedStatus["NormalizedStatus"] + LayerTypes["LayerTypes"] + HierarchyLevels["HierarchyLevels"] + FormatTypes["FormatTypes"] + DeliverableStatusTaxonomy["DeliverableStatusTaxonomy"] + CategoryDefinitions["CategoryDefinitions[read-model]"] + CategoryDefinition["CategoryDefinition"] + end + subgraph types["Types BC"] + ResultMonadTypes["ResultMonadTypes"] + ErrorFactoryTypes["ErrorFactoryTypes"] + end + subgraph validation["Validation BC"] + WorkflowConfigSchema["WorkflowConfigSchema"] + Tag_Registry_Configuration["Tag Registry Configuration"] + OutputSchemas["OutputSchemas"] + ExtractedShapeSchema["ExtractedShapeSchema"] + ExtractedPatternSchema["ExtractedPatternSchema"] + DualSourceSchemas["DualSourceSchemas"] + DocDirectiveSchema["DocDirectiveSchema"] + CodecUtils["CodecUtils"] + DoDValidationTypes["DoDValidationTypes"] + ValidationModule["ValidationModule"] + DoDValidator["DoDValidator[service]"] + AntiPatternDetector["AntiPatternDetector[service]"] + FSMValidator["FSMValidator[decider]"] + FSMTransitions["FSMTransitions[read-model]"] + FSMStates["FSMStates[read-model]"] + FSMModule["FSMModule"] + end + subgraph shared["Shared Infrastructure"] + WorkflowConfigSchema["WorkflowConfigSchema"] + Tag_Registry_Configuration["Tag Registry Configuration"] + OutputSchemas["OutputSchemas"] + ExtractedShapeSchema["ExtractedShapeSchema"] + ExtractedPatternSchema["ExtractedPatternSchema"] + DualSourceSchemas["DualSourceSchemas"] + DocDirectiveSchema["DocDirectiveSchema"] + CodecUtils["CodecUtils"] + ResultMonadTypes["ResultMonadTypes"] + ErrorFactoryTypes["ErrorFactoryTypes"] + StatusValues["StatusValues"] + RiskLevels["RiskLevels"] + NormalizedStatus["NormalizedStatus"] + LayerTypes["LayerTypes"] + HierarchyLevels["HierarchyLevels"] + FormatTypes["FormatTypes"] + DeliverableStatusTaxonomy["DeliverableStatusTaxonomy"] + CategoryDefinition["CategoryDefinition"] + DoDValidationTypes["DoDValidationTypes"] + ValidationModule["ValidationModule"] + RenderableUtils["RenderableUtils"] + SectionBlock["SectionBlock"] + RenderableDocumentModel_RDM_["RenderableDocumentModel(RDM)"] + ShapeExtractor["ShapeExtractor"] + LayerInference["LayerInference"] + CLIVersionHelper["CLIVersionHelper"] + ValidatePatternsCLI["ValidatePatternsCLI"] + LintProcessCLI["LintProcessCLI"] + LintPatternsCLI["LintPatternsCLI"] + TagTaxonomyCLI["TagTaxonomyCLI"] + Documentation_Generator_CLI["Documentation Generator CLI"] + CLIErrorHandler["CLIErrorHandler"] + WarningCollector["WarningCollector"] + GeneratorTypes["GeneratorTypes"] + SourceMappingValidator["SourceMappingValidator"] + GeneratorRegistry["GeneratorRegistry"] + ProcessStateTypes["ProcessStateTypes"] + StubResolverImpl["StubResolverImpl"] + RulesQueryModule["RulesQueryModule"] + APIModule["APIModule"] + LintModule["LintModule"] + Convention_Annotation_Example___DD_3_Decision["Convention Annotation Example — DD-3 Decision[decider]"] + FSMModule["FSMModule"] + ValidationRulesCodec["ValidationRulesCodec"] + TimelineCodec["TimelineCodec"] + TaxonomyCodec["TaxonomyCodec"] + SharedCodecSchema["SharedCodecSchema"] + RequirementsCodec["RequirementsCodec"] + ReportingCodecs["ReportingCodecs"] + ReferenceDocumentCodec["ReferenceDocumentCodec"] + PrChangesCodec["PrChangesCodec"] + PlanningCodecs["PlanningCodecs"] + DocumentCodecs["DocumentCodecs"] + IndexCodec["IndexCodec"] + RichContentHelpers["RichContentHelpers"] + ClaudeModuleCodec["ClaudeModuleCodec"] + BusinessRulesCodec["BusinessRulesCodec"] + AdrDocumentCodec["AdrDocumentCodec"] + MergePatterns["MergePatterns"] + PipelineModule["PipelineModule"] + PipelineFactory["PipelineFactory"] + ReferenceGeneratorRegistration["ReferenceGeneratorRegistration"] + BuiltInGenerators["BuiltInGenerators"] + CodecGeneratorRegistration["CodecGeneratorRegistration"] + ProcessGuardTypes["ProcessGuardTypes"] + ProcessGuardModule["ProcessGuardModule"] + DetectChanges["DetectChanges"] + DeriveProcessState["DeriveProcessState"] + CodecBaseOptions["CodecBaseOptions"] + ValidatorReadModelConsolidation["ValidatorReadModelConsolidation"] + StepDefinitionCompletion["StepDefinitionCompletion"] + SessionGuidesModuleSource["SessionGuidesModuleSource"] + SessionFileCleanup["SessionFileCleanup"] + ProcessAPILayeredExtraction["ProcessAPILayeredExtraction"] + OrchestratorPipelineFactoryMigration["OrchestratorPipelineFactoryMigration"] + MvpWorkflowImplementation["MvpWorkflowImplementation"] + LivingRoadmapCLI["LivingRoadmapCLI"] + EffortVarianceTracking["EffortVarianceTracking"] + ConfigBasedWorkflowDefinition["ConfigBasedWorkflowDefinition"] + CliBehaviorTesting["CliBehaviorTesting"] + ADR006SingleReadModelArchitecture["ADR006SingleReadModelArchitecture"] + ADR005CodecBasedMarkdownRendering["ADR005CodecBasedMarkdownRendering"] + ADR003SourceFirstPatternArchitecture["ADR003SourceFirstPatternArchitecture"] + ADR002GherkinOnlyTesting["ADR002GherkinOnlyTesting"] + ADR001TaxonomyCanonicalValues["ADR001TaxonomyCanonicalValues"] + StringUtils["StringUtils"] + ProcessGuardTesting["ProcessGuardTesting"] + SessionHandoffs["SessionHandoffs"] + SessionFileLifecycle["SessionFileLifecycle"] + KebabCaseSlugs["KebabCaseSlugs"] + ErrorHandlingUnification["ErrorHandlingUnification"] + ResultMonad["ResultMonad"] + ErrorFactories["ErrorFactories"] + end + ExtractedPatternSchema --> DocDirectiveSchema + DualSourceSchemas ..-> MvpWorkflowImplementation + DocDirectiveSchema ..-> MvpWorkflowImplementation + ResultMonadTypes ..-> ResultMonad + ErrorFactoryTypes ..-> ErrorFactories + CategoryDefinition ..-> CategoryDefinitions + GherkinScanner --> GherkinASTParser + TypeScript_AST_Parser --> DocDirectiveSchema + DoDValidator --> DoDValidationTypes + DoDValidator --> DualSourceExtractor + AntiPatternDetector --> DoDValidationTypes + SectionBlock ..-> RenderableDocument + WorkflowLoader --> WorkflowConfigSchema + WorkflowLoader --> CodecUtils + ConfigResolver --> ProjectConfigTypes + ConfigResolver --> DeliveryProcessFactory + ConfigResolver --> ConfigurationDefaults + RegexBuilders --> ConfigurationTypes + ProjectConfigTypes --> ConfigurationTypes + ProjectConfigTypes --> ConfigurationPresets + ProjectConfigSchema --> ProjectConfigTypes + ConfigurationPresets --> ConfigurationTypes + SourceMerger --> ProjectConfigTypes + DeliveryProcessFactory --> ConfigurationTypes + DeliveryProcessFactory --> ConfigurationPresets + DeliveryProcessFactory --> RegexBuilders + DefineConfig --> ProjectConfigTypes + ConfigLoader --> DeliveryProcessFactory + ConfigLoader --> ConfigurationTypes + GherkinExtractor --> GherkinASTParser + DualSourceExtractor --> GherkinExtractor + DualSourceExtractor --> GherkinScanner + Document_Extractor --> Pattern_Scanner + ValidatePatternsCLI --> GherkinScanner + ValidatePatternsCLI --> GherkinExtractor + ValidatePatternsCLI --> MasterDataset + ValidatePatternsCLI --> CodecUtils + ProcessAPICLIImpl --> ProcessStateAPI + ProcessAPICLIImpl --> MasterDataset + ProcessAPICLIImpl --> PipelineFactory + ProcessAPICLIImpl --> RulesQueryModule + ProcessAPICLIImpl --> PatternSummarizerImpl + ProcessAPICLIImpl --> FuzzyMatcherImpl + ProcessAPICLIImpl --> OutputPipelineImpl + OutputPipelineImpl --> PatternSummarizerImpl + LintProcessCLI --> ProcessGuardModule + LintPatternsCLI --> LintEngine + LintPatternsCLI --> LintRules + TagTaxonomyCLI --> ConfigLoader + SourceMapper -.-> DecisionDocCodec + SourceMapper -.-> ShapeExtractor + SourceMapper -.-> GherkinASTParser + GeneratorRegistry --> GeneratorTypes + Documentation_Generation_Orchestrator --> Pattern_Scanner + PatternSummarizerImpl --> ProcessStateAPI + StubResolverImpl --> ProcessStateAPI + ScopeValidatorImpl --> ProcessStateAPI + ScopeValidatorImpl --> MasterDataset + ScopeValidatorImpl --> StubResolverImpl + RulesQueryModule --> BusinessRulesCodec + RulesQueryModule ..-> ProcessAPILayeredExtraction + ProcessStateAPI --> MasterDataset + ProcessStateAPI --> FSMValidator + HandoffGeneratorImpl --> ProcessStateAPI + HandoffGeneratorImpl --> MasterDataset + HandoffGeneratorImpl --> ContextFormatterImpl + CoverageAnalyzerImpl --> Pattern_Scanner + CoverageAnalyzerImpl --> MasterDataset + ContextFormatterImpl --> ContextAssemblerImpl + ContextAssemblerImpl --> ProcessStateAPI + ContextAssemblerImpl --> MasterDataset + ContextAssemblerImpl --> PatternSummarizerImpl + ContextAssemblerImpl --> FuzzyMatcherImpl + ContextAssemblerImpl --> StubResolverImpl + ArchQueriesImpl --> ProcessStateAPI + ArchQueriesImpl --> MasterDataset + LintModule --> LintRules + LintModule --> LintEngine + LintEngine --> LintRules + LintEngine --> CodecUtils + FSMValidator --> FSMTransitions + FSMValidator --> FSMStates + ArchitectureCodec --> MasterDataset + TransformDataset --> MasterDataset + MergePatterns --> PatternHelpers + MergePatterns ..-> OrchestratorPipelineFactoryMigration + PipelineModule --> TransformDataset + PipelineFactory --> GherkinScanner + PipelineFactory --> GherkinExtractor + PipelineFactory --> MasterDataset + PipelineFactory ..-> ProcessAPILayeredExtraction + BuiltInGenerators --> GeneratorRegistry + BuiltInGenerators --> CodecBasedGenerator + DecisionDocGenerator -.-> DecisionDocCodec + DecisionDocGenerator -.-> SourceMapper + DetectChanges --> DeriveProcessState + DeriveProcessState --> GherkinScanner + DeriveProcessState --> FSMValidator + ProcessGuardDecider --> FSMValidator + ProcessGuardDecider --> DeriveProcessState + ProcessGuardDecider --> DetectChanges + ValidatorReadModelConsolidation -.-> ADR006SingleReadModelArchitecture + StepDefinitionCompletion -.-> ADR002GherkinOnlyTesting + SessionFileCleanup -.-> SessionFileLifecycle + ProcessAPILayeredExtraction -.-> ValidatorReadModelConsolidation + OrchestratorPipelineFactoryMigration -.-> ProcessAPILayeredExtraction + LivingRoadmapCLI -.-> MvpWorkflowImplementation + EffortVarianceTracking -.-> MvpWorkflowImplementation + ConfigBasedWorkflowDefinition -.-> MvpWorkflowImplementation + CliBehaviorTesting -.-> ADR002GherkinOnlyTesting + ADR006SingleReadModelArchitecture -.-> ADR005CodecBasedMarkdownRendering + ADR003SourceFirstPatternArchitecture -.-> ADR001TaxonomyCanonicalValues + ProcessGuardTesting -.-> AntiPatternDetector + KebabCaseSlugs -.-> StringUtils + ErrorHandlingUnification -.-> ResultMonad + ErrorHandlingUnification -.-> ErrorFactories +``` + +--- + +## Legend + +| Arrow Style | Relationship | Description | +| ----------- | ------------ | ---------------------------------------- | +| `-->` | uses | Direct dependency (solid arrow) | +| `-.->` | depends-on | Weak dependency (dashed arrow) | +| `..->` | implements | Realization relationship (dotted arrow) | +| `-->>` | extends | Generalization relationship (open arrow) | + +--- + +## Component Inventory + +All components with architecture annotations: + +| Component | Context | Role | Layer | Source File | +| ----------------------------------------------------------------- | ---------- | -------------- | -------------- | ---------------------------------------------------------------------------- | +| 🚧 Pattern Helpers | api | - | domain | src/api/pattern-helpers.ts | +| ✅ Master Dataset | api | read-model | domain | src/validation-schemas/master-dataset.ts | +| 🚧 Arch Queries Impl | api | service | domain | src/api/arch-queries.ts | +| 🚧 Context Assembler Impl | api | service | application | src/api/context-assembler.ts | +| 🚧 Context Formatter Impl | api | service | application | src/api/context-formatter.ts | +| 🚧 Coverage Analyzer Impl | api | service | application | src/api/coverage-analyzer.ts | +| 🚧 Fuzzy Matcher Impl | api | service | application | src/api/fuzzy-match.ts | +| ✅ Handoff Generator Impl | api | service | application | src/api/handoff-generator.ts | +| 🚧 Pattern Summarizer Impl | api | service | application | src/api/summarize.ts | +| 🚧 Process State API | api | service | application | src/api/process-state.ts | +| ✅ Scope Validator Impl | api | service | application | src/api/scope-validator.ts | +| ✅ CLI Schema | cli | - | domain | src/cli/cli-schema.ts | +| 🚧 Output Pipeline Impl | cli | service | application | src/cli/output-pipeline.ts | +| 🚧 Process API CLI Impl | cli | service | application | src/cli/process-api.ts | +| ✅ Configuration Defaults | config | - | domain | src/config/defaults.ts | +| ✅ Configuration Presets | config | - | domain | src/config/presets.ts | +| ✅ Configuration Types | config | - | domain | src/config/types.ts | +| 🚧 Project Config Types | config | - | domain | src/config/project-config.ts | +| ✅ Config Loader | config | infrastructure | infrastructure | src/config/config-loader.ts | +| 🚧 Define Config | config | infrastructure | infrastructure | src/config/define-config.ts | +| 🚧 Project Config Schema | config | infrastructure | infrastructure | src/config/project-config-schema.ts | +| ✅ Regex Builders | config | infrastructure | infrastructure | src/config/regex-builders.ts | +| ✅ Workflow Loader | config | infrastructure | infrastructure | src/config/workflow-loader.ts | +| 🚧 Config Resolver | config | service | application | src/config/resolve-config.ts | +| ✅ Delivery Process Factory | config | service | application | src/config/factory.ts | +| 🚧 Source Merger | config | service | application | src/config/merge-sources.ts | +| ✅ Document Extractor | extractor | service | application | src/extractor/doc-extractor.ts | +| ✅ Dual Source Extractor | extractor | service | application | src/extractor/dual-source-extractor.ts | +| ✅ Gherkin Extractor | extractor | service | application | src/extractor/gherkin-extractor.ts | +| Cli Recipe Generator | generator | - | application | src/generators/built-in/cli-recipe-generator.ts | +| ✅ Process Api Reference Generator | generator | - | application | src/generators/built-in/process-api-reference-generator.ts | +| ✅ Content Deduplicator | generator | infrastructure | infrastructure | src/generators/content-deduplicator.ts | +| 🚧 File Cache | generator | infrastructure | infrastructure | src/cache/file-cache.ts | +| ✅ Source Mapper | generator | infrastructure | infrastructure | src/generators/source-mapper.ts | +| ✅ Codec Based Generator | generator | service | application | src/generators/codec-based.ts | +| ✅ Decision Doc Generator | generator | service | application | src/generators/built-in/decision-doc-generator.ts | +| ✅ Documentation Generation Orchestrator | generator | service | application | src/generators/orchestrator.ts | +| ✅ Transform Dataset | generator | service | application | src/generators/pipeline/transform-dataset.ts | +| 🚧 Process Guard Decider | lint | decider | application | src/lint/process-guard/decider.ts | +| ✅ Lint Engine | lint | service | application | src/lint/engine.ts | +| ✅ Lint Rules | lint | service | application | src/lint/rules.ts | +| loadPreambleFromMarkdown — Shared Markdown-to-SectionBlock Parser | renderer | - | domain | src/renderable/load-preamble.ts | +| ✅ Mermaid Diagram Utils | renderer | - | - | src/renderable/codecs/diagram-utils.ts | +| ✅ Architecture Codec | renderer | projection | application | src/renderable/codecs/architecture.ts | +| 🚧 Composite Codec | renderer | projection | application | src/renderable/codecs/composite.ts | +| ✅ Decision Doc Codec | renderer | projection | application | src/renderable/codecs/decision-doc.ts | +| ✅ Patterns Codec | renderer | projection | application | src/renderable/codecs/patterns.ts | +| ✅ Session Codec | renderer | projection | application | src/renderable/codecs/session.ts | +| ✅ Renderable Document | renderer | read-model | domain | src/renderable/schema.ts | +| ✅ Document Generator | renderer | service | application | src/renderable/generate.ts | +| ✅ Universal Renderer | renderer | service | application | src/renderable/render.ts | +| ✅ Gherkin AST Parser | scanner | infrastructure | infrastructure | src/scanner/gherkin-ast-parser.ts | +| ✅ Gherkin Scanner | scanner | infrastructure | infrastructure | src/scanner/gherkin-scanner.ts | +| ✅ Pattern Scanner | scanner | infrastructure | infrastructure | src/scanner/pattern-scanner.ts | +| ✅ TypeScript AST Parser | scanner | infrastructure | infrastructure | src/scanner/ast-parser.ts | +| ✅ Category Definitions | taxonomy | read-model | domain | src/taxonomy/categories.ts | +| ✅ Tag Registry Builder | taxonomy | service | domain | src/taxonomy/registry-builder.ts | +| 🚧 FSM Validator | validation | decider | application | src/validation/fsm/validator.ts | +| 🚧 FSM States | validation | read-model | domain | src/validation/fsm/states.ts | +| 🚧 FSM Transitions | validation | read-model | domain | src/validation/fsm/transitions.ts | +| ✅ Anti Pattern Detector | validation | service | application | src/validation/anti-patterns.ts | +| ✅ DoD Validator | validation | service | application | src/validation/dod-validator.ts | +| 📋 ADR 001 Taxonomy Canonical Values | - | - | - | delivery-process/decisions/adr-001-taxonomy-canonical-values.feature | +| ✅ ADR 002 Gherkin Only Testing | - | - | - | delivery-process/decisions/adr-002-gherkin-only-testing.feature | +| 📋 ADR 003 Source First Pattern Architecture | - | - | - | delivery-process/decisions/adr-003-source-first-pattern-architecture.feature | +| ✅ ADR 005 Codec Based Markdown Rendering | - | - | - | delivery-process/decisions/adr-005-codec-based-markdown-rendering.feature | +| ✅ ADR 006 Single Read Model Architecture | - | - | - | delivery-process/decisions/adr-006-single-read-model-architecture.feature | +| ✅ Adr Document Codec | - | - | - | src/renderable/codecs/adr.ts | +| 🚧 API Module | - | - | - | src/api/index.ts | +| ✅ Built In Generators | - | - | - | src/generators/built-in/index.ts | +| ✅ Business Rules Codec | - | - | - | src/renderable/codecs/business-rules.ts | +| CategoryDefinition | - | - | - | src/taxonomy/categories.ts | +| 🚧 Claude Module Codec | - | - | - | src/renderable/codecs/claude-module.ts | +| 📋 Cli Behavior Testing | - | - | - | delivery-process/specs/cli-behavior-testing.feature | +| ✅ CLI Error Handler | - | - | - | src/cli/error-handler.ts | +| ✅ CLI Version Helper | - | - | - | src/cli/version.ts | +| ✅ Codec Base Options | - | - | - | src/renderable/codecs/types/base.ts | +| ✅ Codec Generator Registration | - | - | - | src/generators/built-in/codec-generators.ts | +| ✅ Codec Utils | - | - | - | src/validation-schemas/codec-utils.ts | +| ✅ Config Based Workflow Definition | - | - | - | delivery-process/specs/config-based-workflow-definition.feature | +| 🚧 Deliverable Status Taxonomy | - | - | - | src/taxonomy/deliverable-status.ts | +| 🚧 Derive Process State | - | - | - | src/lint/process-guard/derive-state.ts | +| 🚧 Detect Changes | - | - | - | src/lint/process-guard/detect-changes.ts | +| ✅ Doc Directive Schema | - | - | - | src/validation-schemas/doc-directive.ts | +| ✅ Documentation Generator CLI | - | - | - | src/cli/generate-docs.ts | +| ✅ Document Codecs | - | - | - | src/renderable/codecs/index.ts | +| ✅ DoD Validation Types | - | - | - | src/validation/types.ts | +| ✅ Dual Source Schemas | - | - | - | src/validation-schemas/dual-source.ts | +| 📋 Effort Variance Tracking | - | - | - | delivery-process/specs/effort-variance-tracking.feature | +| ✅ Error Factories | - | - | - | tests/features/types/error-factories.feature | +| ✅ Error Factory Types | - | - | - | src/types/errors.ts | +| ✅ Error Handling Unification | - | - | - | tests/features/behavior/error-handling.feature | +| ✅ Extracted Pattern Schema | - | - | - | src/validation-schemas/extracted-pattern.ts | +| ✅ Extracted Shape Schema | - | - | - | src/validation-schemas/extracted-shape.ts | +| ✅ Format Types | - | - | - | src/taxonomy/format-types.ts | +| 🚧 FSM Module | - | - | - | src/validation/fsm/index.ts | +| ✅ Generator Registry | - | - | - | src/generators/registry.ts | +| ✅ Generator Types | - | - | - | src/generators/types.ts | +| ✅ Hierarchy Levels | - | - | - | src/taxonomy/hierarchy-levels.ts | +| ✅ Index Codec | - | - | - | src/renderable/codecs/index-codec.ts | +| 📋 Kebab Case Slugs | - | - | - | tests/features/behavior/kebab-case-slugs.feature | +| ✅ Layer Inference | - | - | - | src/extractor/layer-inference.ts | +| ✅ Layer Types | - | - | - | src/taxonomy/layer-types.ts | +| ✅ Lint Module | - | - | - | src/lint/index.ts | +| ✅ Lint Patterns CLI | - | - | - | src/cli/lint-patterns.ts | +| 🚧 Lint Process CLI | - | - | - | src/cli/lint-process.ts | +| 📋 Living Roadmap CLI | - | - | - | delivery-process/specs/living-roadmap-cli.feature | +| ✅ Merge Patterns | - | - | - | src/generators/pipeline/merge-patterns.ts | +| ✅ Mvp Workflow Implementation | - | - | - | delivery-process/specs/mvp-workflow-implementation.feature | +| ✅ Normalized Status | - | - | - | src/taxonomy/normalized-status.ts | +| ✅ Orchestrator Pipeline Factory Migration | - | - | - | delivery-process/specs/orchestrator-pipeline-factory-migration.feature | +| ✅ Output Schemas | - | - | - | src/validation-schemas/output-schemas.ts | +| ✅ Pipeline Factory | - | - | - | src/generators/pipeline/build-pipeline.ts | +| ✅ Pipeline Module | - | - | - | src/generators/pipeline/index.ts | +| ✅ Planning Codecs | - | - | - | src/renderable/codecs/planning.ts | +| ✅ Pr Changes Codec | - | - | - | src/renderable/codecs/pr-changes.ts | +| ✅ Process API Layered Extraction | - | - | - | delivery-process/specs/process-api-layered-extraction.feature | +| 🚧 Process Guard Module | - | - | - | src/lint/process-guard/index.ts | +| ✅ Process Guard Testing | - | - | - | tests/features/validation/process-guard.feature | +| 🚧 Process Guard Types | - | - | - | src/lint/process-guard/types.ts | +| 🚧 Process State Types | - | - | - | src/api/types.ts | +| 🚧 Reference Document Codec | - | - | - | src/renderable/codecs/reference.ts | +| 🚧 Reference Generator Registration | - | - | - | src/generators/built-in/reference-generators.ts | +| ✅ Renderable Document Model(RDM) | - | - | - | src/renderable/index.ts | +| ✅ Renderable Utils | - | - | - | src/renderable/utils.ts | +| ✅ Reporting Codecs | - | - | - | src/renderable/codecs/reporting.ts | +| ✅ Requirements Codec | - | - | - | src/renderable/codecs/requirements.ts | +| ✅ Result Monad | - | - | - | tests/features/types/result-monad.feature | +| ✅ Result Monad Types | - | - | - | src/types/result.ts | +| ✅ Rich Content Helpers | - | - | - | src/renderable/codecs/helpers.ts | +| ✅ Risk Levels | - | - | - | src/taxonomy/risk-levels.ts | +| ✅ Rules Query Module | - | - | - | src/api/rules-query.ts | +| SectionBlock | - | - | - | src/renderable/schema.ts | +| 📋 Session File Cleanup | - | - | - | delivery-process/specs/session-file-cleanup.feature | +| ✅ Session File Lifecycle | - | - | - | tests/features/behavior/session-file-lifecycle.feature | +| ✅ Session Guides Module Source | - | - | - | delivery-process/specs/session-guides-module-source.feature | +| ✅ Session Handoffs | - | - | - | tests/features/behavior/session-handoffs.feature | +| ✅ Shape Extractor | - | - | - | src/extractor/shape-extractor.ts | +| ✅ Shared Codec Schema | - | - | - | src/renderable/codecs/shared-schema.ts | +| ✅ Source Mapping Validator | - | - | - | src/generators/source-mapping-validator.ts | +| ✅ Status Values | - | - | - | src/taxonomy/status-values.ts | +| 📋 Step Definition Completion | - | - | - | delivery-process/specs/step-definition-completion.feature | +| ✅ String Utils | - | - | - | tests/features/utils/string-utils.feature | +| 🚧 Stub Resolver Impl | - | - | - | src/api/stub-resolver.ts | +| ✅ Tag Registry Configuration | - | - | - | src/validation-schemas/tag-registry.ts | +| ⏸️ Tag Taxonomy CLI | - | - | - | src/cli/generate-tag-taxonomy.ts | +| ✅ Taxonomy Codec | - | - | - | src/renderable/codecs/taxonomy.ts | +| ✅ Timeline Codec | - | - | - | src/renderable/codecs/timeline.ts | +| ✅ Validate Patterns CLI | - | - | - | src/cli/validate-patterns.ts | +| ✅ Validation Module | - | - | - | src/validation/index.ts | +| ✅ Validation Rules Codec | - | - | - | src/renderable/codecs/validation-rules.ts | +| ✅ Validator Read Model Consolidation | - | - | - | delivery-process/specs/validator-read-model-consolidation.feature | +| ✅ Warning Collector | - | - | - | src/generators/warning-collector.ts | +| ✅ Workflow Config Schema | - | - | - | src/validation-schemas/workflow-config.ts | +| 📋 Convention Annotation Example — DD-3 Decision | - | decider | - | delivery-process/stubs/error-guide-codec/convention-annotation-example.ts | diff --git a/docs-live/BUSINESS-RULES.md b/docs-live/BUSINESS-RULES.md new file mode 100644 index 00000000..87440f51 --- /dev/null +++ b/docs-live/BUSINESS-RULES.md @@ -0,0 +1,24 @@ +# Business Rules + +**Purpose:** Domain constraints and invariants extracted from feature files +**Detail Level:** Overview with links to detailed business rules by product area + +--- + +**Domain constraints and invariants extracted from feature specifications. 579 rules from 124 features across 7 product areas.** + +--- + +## Product Areas + +| Product Area | Features | Rules | With Invariants | +| ------------------------------------------------ | -------- | ----- | --------------- | +| [Annotation](business-rules/annotation.md) | 20 | 88 | 88 | +| [Configuration](business-rules/configuration.md) | 7 | 32 | 32 | +| [Core Types](business-rules/core-types.md) | 5 | 22 | 22 | +| [Data API](business-rules/data-api.md) | 21 | 89 | 89 | +| [Generation](business-rules/generation.md) | 58 | 287 | 287 | +| [Process](business-rules/process.md) | 2 | 7 | 7 | +| [Validation](business-rules/validation.md) | 11 | 54 | 54 | + +--- diff --git a/docs-live/CHANGELOG-GENERATED.md b/docs-live/CHANGELOG-GENERATED.md new file mode 100644 index 00000000..a894815e --- /dev/null +++ b/docs-live/CHANGELOG-GENERATED.md @@ -0,0 +1,328 @@ +# Changelog + +**Purpose:** Project changelog in Keep a Changelog format + +--- + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +--- + +## [Unreleased] + +### Added + +- **Deliverable Status Taxonomy**: Canonical status values for deliverables in Gherkin Background tables. +- **Config Resolver**: Resolves a raw `DeliveryProcessProjectConfig` into a fully-resolved `ResolvedConfig` with all defaults applied, stubs... +- **Project Config Types**: Unified project configuration for the delivery-process package. +- **Project Config Schema**: Zod validation schema for `DeliveryProcessProjectConfig`. +- **Source Merger**: Computes effective sources for a specific generator by applying per-generator overrides to the base resolved sources. +- **Define Config**: Identity function for type-safe project configuration. +- **Process API CLI Impl**: Exposes ProcessStateAPI methods as CLI subcommands with JSON output. +- **Output Pipeline Impl**: Post-processing pipeline that transforms raw API results into shaped CLI output. +- **Lint Process CLI**: Validates git changes against delivery process rules. +- **File Cache**: Simple Map-based cache for file contents during a single generation run. +- **Process State Types**: :MasterDataset Type definitions for the ProcessStateAPI query interface. +- **Pattern Summarizer Impl**: Projects the full ExtractedPattern (~3.5KB per pattern) down to a PatternSummary (~100 bytes) for list queries. +- **Stub Resolver Impl**: Identifies design session stubs in the MasterDataset and resolves them against the filesystem to determine... +- **Process State API**: TypeScript interface for querying delivery process state. +- **Pattern Helpers**: Common helper functions used by context-assembler, arch-queries, and other API modules that need pattern name... +- **API Module**: Central export for the Process State API, providing a TypeScript interface for querying delivery process state. +- **Fuzzy Matcher Impl**: Provides fuzzy matching for pattern names with tiered scoring: exact (1.0) > prefix (0.9) > substring (0.7) >... +- **Coverage Analyzer Impl**: Reports annotation completeness by comparing scannable files (from glob) against annotated patterns in MasterDataset. +- **Context Formatter Impl**: First plain-text formatter in the codebase. +- **Context Assembler Impl**: Pure function composition over MasterDataset. +- **Arch Queries Impl**: Pure functions over MasterDataset for deep architecture exploration. +- **FSM Validator**: :PDR005MvpWorkflow Pure validation functions following the Decider pattern: - No I/O, no side effects - Return... +- **FSM Transitions**: :PDR005MvpWorkflow Defines valid transitions between FSM states per PDR-005: ``` roadmap ──→ active ──→ completed │ ... +- **FSM States**: :PDR005MvpWorkflow Defines the 4-state FSM from PDR-005 MVP Workflow: - roadmap: Planned work (fully editable) -... +- **FSM Module**: :PDR005MvpWorkflow Central export for the 4-state FSM defined in PDR-005: ``` roadmap ──→ active ──→ completed │ ... +- **Reference Document Codec**: :Generation A single codec factory that creates reference document codecs from configuration objects. +- **Composite Codec**: :Generation Assembles reference documents from multiple codec outputs by concatenating RenderableDocument sections. +- **Claude Module Codec**: :Generation Transforms MasterDataset into RenderableDocuments for CLAUDE.md module generation. +- **Process Guard Types**: :FSMValidator Defines types for the process guard linter including: - Process state derived from file annotations -... +- **Process Guard Module**: :FSMValidator,DeriveProcessState,DetectChanges,ProcessGuardDecider Enforces delivery process rules by validating... +- **Detect Changes**: Detects changes from git diff including: - Modified, added, deleted files - Status transitions (@libar-docs-status... +- **Derive Process State**: :GherkinScanner,FSMValidator Derives process state from @libar-docs-\* annotations in files. +- **Process Guard Decider**: :FSMValidator,DeriveProcessState,DetectChanges Pure function that validates changes against process rules. +- **Reference Generator Registration**: Registers all reference document generators. +- **Load Preamble Parser**: The parseMarkdownToBlocks function converts raw markdown content into a readonly SectionBlock[] array using a 5-state... +- **Architecture Doc Refactoring Testing**: Validates that ARCHITECTURE.md retains its full reference content and that generated documents in docs-live/ coexist... +- **Uses Tag Testing**: Tests extraction and processing of @libar-docs-uses and @libar-docs-used-by relationship tags from TypeScript files. +- **Depends On Tag Testing**: Tests extraction of @libar-docs-depends-on and @libar-docs-enables relationship tags from Gherkin files. +- **Stub Taxonomy Tag Tests**: Stub metadata (target path, design session) was stored as plain text in JSDoc descriptions, invisible to structured... +- **Stub Resolver Tests**: Design session stubs need structured discovery and resolution to determine which stubs have been implemented and... +- **Pattern Summarize Tests**: Validates that summarizePattern() projects ExtractedPattern (~3.5KB) to PatternSummary (~100 bytes) with the correct... +- **Pattern Helpers Tests** +- **Output Pipeline Tests**: Validates the output pipeline transforms: summarization, modifiers, list filters, empty stripping, and format output. +- **Fuzzy Match Tests**: Validates tiered fuzzy matching: exact > prefix > substring > Levenshtein. +- **Arch Queries Test** +- **Context Formatter Tests**: Tests for formatContextBundle(), formatDepTree(), formatFileReadingList(), and formatOverview() plain text rendering... +- **Context Assembler Tests**: Tests for assembleContext(), buildDepTree(), buildFileReadingList(), and buildOverview() pure functions that operate... + +--- + +## [v1.0.0] + +### Added + +- **TypeScript Taxonomy Implementation**: As a delivery-process developer I want taxonomy defined in TypeScript with Zod integration So that I get compile-time... +- **Process Guard Linter**: During planning and implementation sessions, accidental modifications occur: - Specs outside the intended scope get... +- **Phase State Machine Validation**: Phase lifecycle state transitions are not enforced programmatically despite being documented in PROCESS_SETUP.md. +- **Pattern Relationship Model**: Problem: The delivery process lacks a comprehensive relationship model between artifacts. +- **Mvp Workflow Implementation**: PDR-005 defines a 4-state workflow FSM (`roadmap, active, completed, deferred`) but the delivery-process package... +- **Gherkin Rules Support**: Feature files were limited to flat scenario lists. + +--- + +## [Earlier] + +### Added + +- **Public API**: Main entry point for the @libar-dev/delivery-process package. +- **Index Preamble Configuration — DD-3, DD-4 Decisions**: Decision DD-3 (Audience paths: preamble vs annotation-derived): Use full preamble for audience reading paths. +- **IndexCodec Factory — DD-1 Implementation Stub**: Creates the IndexCodec as a Zod codec (MasterDataset -> RenderableDocument). +- **IndexCodecOptions — DD-1, DD-5 Decisions**: Decision DD-1 (New IndexCodec vs extend existing): Create a new IndexCodec registered in CodecRegistry, NOT a... +- **DoD Validation Types**: Types and schemas for Definition of Done (DoD) validation and anti-pattern detection. +- **Validation Module**: Barrel export for validation module providing: - Definition of Done (DoD) validation for completed phases -... +- **DoD Validator**: Validates that completed phases meet Definition of Done criteria: 1. +- **Anti Pattern Detector**: Detects violations of the dual-source documentation architecture and process hygiene issues that lead to... +- **Workflow Config Schema**: Zod schemas for validating workflow configuration files that define status models, phase definitions, and artifact... +- **Tag Registry Configuration**: Defines the structure and validation for tag taxonomy configuration. +- **Output Schemas**: Zod schemas for JSON output formats used by CLI tools. +- **Master Dataset**: Defines the schema for a pre-computed dataset that holds all extracted patterns along with derived views (by status,... +- **Extracted Shape Schema**: Zod schema for TypeScript type definitions extracted from source files via the @libar-docs-extract-shapes tag. +- **Extracted Pattern Schema**: Zod schema for validating complete extracted patterns with code, metadata, relationships, and source information. +- **Dual Source Schemas**: Zod schemas for dual-source extraction types. +- **Doc Directive Schema**: Zod schemas for validating parsed @libar-docs-\* directives from JSDoc comments. +- **Codec Utils**: Provides factory functions for creating type-safe JSON parsing and serialization pipelines using Zod schemas. +- **Result Monad Types**: Explicit error handling via discriminated union. +- **Error Factory Types**: Structured, discriminated error types with factory functions. +- **Status Values**: THE single source of truth for FSM state values in the monorepo (per PDR-005 FSM). +- **Risk Levels**: Three-tier risk classification for roadmap planning. +- **Tag Registry Builder**: Constructs a complete TagRegistry from TypeScript constants. +- **Normalized Status**: The delivery-process system uses a two-level status taxonomy: 1. +- **Layer Types**: Inferred from feature file directory paths: - timeline: Process/workflow features (delivery-process) - domain:... +- **Hierarchy Levels**: Three-level hierarchy for organizing work: - epic: Multi-quarter strategic initiatives - phase: Standard work units... +- **Format Types**: Defines how tag values are parsed and validated. +- **Category Definitions**: Categories are used to classify patterns and organize documentation. +- **Renderable Utils**: Utility functions for document codecs. +- **Renderable Document**: Universal intermediate format for all generated documentation. +- **Universal Renderer**: Converts RenderableDocument to output strings. +- **Renderable Document Model(RDM)**: Unified document generation using codecs and a universal renderer. +- **Document Generator**: Simplified document generation using codecs. +- **Lint Rules**: Defines lint rules that check @libar-docs-\* directives for completeness and quality. +- **Lint Module**: Provides lint rules and engine for pattern annotation quality checking. +- **Lint Engine**: Orchestrates lint rule execution against parsed directives. +- **Warning Collector**: Provides a unified system for capturing, categorizing, and reporting non-fatal issues during document generation. +- **Generator Types**: Minimal interface for pluggable generators that produce documentation from patterns. +- **Source Mapping Validator**: Performs pre-flight checks on source mapping tables before extraction begins. +- **Source Mapper**: Aggregates content from multiple source files based on source mapping tables parsed from decision documents. +- **Generator Registry**: Manages registration and lookup of document generators (both built-in and custom). +- **Documentation Generation Orchestrator**: Invariant: The orchestrator is the integration boundary for full docs generation: it delegates dataset construction... +- **Content Deduplicator**: Identifies and merges duplicate sections extracted from multiple sources. +- **Codec Based Generator**: Adapts the new RenderableDocument Model (RDM) codec system to the existing DocumentGenerator interface. +- **Shape Extractor**: Extracts TypeScript type definitions (interfaces, type aliases, enums, function signatures) from source files for... +- **Layer Inference**: Infers feature file layer (timeline, domain, integration, e2e, component) from directory path patterns. +- **Gherkin Extractor**: Transforms scanned Gherkin feature files into ExtractedPattern objects for inclusion in generated documentation. +- **Dual Source Extractor**: Extracts pattern metadata from both TypeScript code stubs (@libar-docs-_) and Gherkin feature files (@libar-docs-_),... +- **Document Extractor**: Converts scanned file data into complete ExtractedPattern objects with unique IDs, inferred names, categories, and... +- **Workflow Loader**: Provides the default 6-phase workflow as an inline constant and loads custom workflow overrides from JSON files via... +- **Configuration Types**: Type definitions for the delivery process configuration system. +- **Regex Builders**: Type-safe regex factory functions for tag detection and normalization. +- **Configuration Presets**: Predefined configuration presets for common use cases. +- **Delivery Process Factory**: Main factory function for creating configured delivery process instances. +- **Configuration Defaults**: Centralized default constants for the delivery-process package. +- **Config Loader**: Discovers and loads `delivery-process.config.ts` files for hierarchical configuration. +- **CLI Version Helper**: Reads package version from package.json for CLI --version flag. +- **Validate Patterns CLI**: Cross-validates TypeScript patterns vs Gherkin feature files. +- **Lint Patterns CLI**: Validates pattern annotations for quality and completeness. +- **Documentation Generator CLI**: Replaces multiple specialized CLIs with one unified interface that supports multiple generators in a single run. +- **CLI Error Handler**: Provides type-safe error handling for all CLI commands using the DocError discriminated union pattern. +- **CLI Schema**: :DataAPI Declarative schema defining all CLI options for the process-api command. +- **String Utilities**: Provides shared utilities for string manipulation used across the delivery-process package, including slugification... +- **Utils Module**: Common helper functions used across the delivery-process package. +- **Pattern Id Generator**: Generates unique, deterministic pattern IDs based on file path and line number. +- **Collection Utilities**: Provides shared utilities for working with arrays and collections, such as grouping items by a key function. +- **Scope Validator Impl**: Pure function composition over ProcessStateAPI and MasterDataset. +- **Rules Query Module**: Pure query function for business rules extracted from Gherkin Rule: blocks. +- **Handoff Generator Impl**: Pure function that assembles a handoff document from ProcessStateAPI and MasterDataset. +- **Pattern Scanner**: Discovers TypeScript files matching glob patterns and filters to only those with `@libar-docs` opt-in. +- **Gherkin Scanner**: Scans .feature files for pattern metadata encoded in Gherkin tags. +- **Gherkin AST Parser**: Parses Gherkin feature files using @cucumber/gherkin and extracts structured data including feature metadata, tags,... +- **TypeScript AST Parser**: Parses TypeScript source files using @typescript-eslint/typescript-estree to extract @libar-docs-\* directives with... +- **Validation Rules Codec**: :Generation Transforms MasterDataset into a RenderableDocument for Process Guard validation rules reference. +- **Timeline Codec**: :Generation Purpose: Development roadmap organized by phase with progress tracking. +- **Taxonomy Codec**: :Generation Transforms MasterDataset into a RenderableDocument for taxonomy reference output. +- **Shared Codec Schema**: Provides a simplified RenderableDocument output schema for use with Zod 4 codecs. +- **Session Codec**: :Generation Purpose: Current session context for AI agents and developers. +- **Requirements Codec**: :Generation Transforms MasterDataset into RenderableDocument for PRD/requirements output. +- **Reporting Codecs**: :Generation Purpose: Keep a Changelog format changelog grouped by release version. +- **Pr Changes Codec**: :Generation Transforms MasterDataset into RenderableDocument for PR-scoped output. +- **Planning Codecs**: :Generation Purpose: Pre-planning questions and Definition of Done validation. +- **Patterns Codec**: :Generation Transforms MasterDataset into a RenderableDocument for pattern registry output. +- **Document Codecs**: Barrel export for all document codecs. +- **Index Codec**: :Generation Purpose: Navigation hub composing editorial preamble with MasterDataset statistics. +- **Rich Content Helpers**: Shared helper functions for rendering Gherkin rich content in document codecs. +- **Mermaid Diagram Utils**: Sanitization and formatting helpers shared across architecture.ts and reference.ts diagram builders. +- **Decision Doc Codec**: Parses decision documents (ADR/PDR in .feature format) and extracts content for documentation generation. +- **Business Rules Codec**: :Generation Transforms MasterDataset into a RenderableDocument for business rules output. +- **Architecture Codec**: :Generation Transforms MasterDataset into a RenderableDocument containing architecture diagrams (Mermaid) generated... +- **Adr Document Codec**: :Generation Transforms MasterDataset into RenderableDocument for Architecture Decision Records. +- **Transform Dataset**: Transforms raw extracted patterns into a MasterDataset with all pre-computed views. +- **Merge Patterns**: Merges patterns from TypeScript and Gherkin sources with conflict detection. +- **Pipeline Module**: Barrel export for the unified transformation pipeline components. +- **Pipeline Factory**: Invariant: `buildMasterDataset()` is the shared factory for Steps 1-8 of the architecture pipeline and returns... +- **Process Api Reference Generator**: :Generation Generates `PROCESS-API-REFERENCE.md` from the declarative CLI schema. +- **Built In Generators**: Registers all codec-based generators on import using the RDM (RenderableDocument Model) architecture. +- **Decision Doc Generator**: Orchestrates the full pipeline for generating documentation from decision documents (ADR/PDR in .feature format): 1. +- **Codec Generator Registration**: Registers codec-based generators for the RenderableDocument Model (RDM) system. +- **Codec Base Options**: Shared types, interfaces, and utilities for all document codecs. +- **ADR 006 Single Read Model Architecture**: The delivery-process package applies event sourcing to itself: git is the event store, annotated source files are... +- **ADR 005 Codec Based Markdown Rendering**: The documentation generator needs to transform structured pattern data (MasterDataset) into markdown files. +- **ADR 002 Gherkin Only Testing**: A package that generates documentation from `.feature` files had dual test approaches: 97 legacy `.test.ts` files... +- **Validator Read Model Consolidation**: `validate-patterns.ts` is the only feature consumer that bypasses the MasterDataset. +- **Universal Doc Generator Robustness**: This feature transforms the PoC document generator into a production-ready universal generator capable of operating... +- **Step Lint Vitest Cucumber**: Hours are lost debugging vitest-cucumber-specific issues that only surface at test runtime. +- **Shape Extraction**: Documentation comments duplicate type definitions that exist in the same file. +- **Session Guides Module Source**: CLAUDE.md contains a "Session Workflows" section (~160 lines) that is hand-maintained with no link to any annotated... +- **Scoped Architectural View**: Full architecture diagrams show every annotated pattern in the project. +- **Reference Doc Showcase**: The Reference Generation Sample document exercises a small fraction of the reference codec's capabilities: 2... +- **Readme Rationalization**: `README.md` is 504 lines and serves three different audiences in one document: (a) npm package consumers who need... +- **Publishing Relocation**: `docs/PUBLISHING.md` (144 lines) is deployed to libar.dev as part of the `docs/` directory, but its content is... +- **Process State API Relationship Queries**: Problem: ProcessStateAPI currently supports dependency queries (`uses`, `usedBy`, `dependsOn`, `enables`) but lacks... +- **Process State API CLI**: The ProcessStateAPI provides 27 typed query methods for efficient state queries, but Claude Code sessions cannot use... +- **Process API Layered Extraction**: `process-api.ts` is 1,700 lines containing two remaining architectural violations of ADR-006: 1. +- **Process Api Hybrid Generation**: `docs/PROCESS-API.md` (509 lines) contains three reference tables that manually mirror CLI definitions in source... +- **Procedural Guide Codec**: Two manual docs contain procedural content with no annotation source for generation: `docs/SESSION-GUIDES.md` (389... +- **Orchestrator Pipeline Factory Migration**: `orchestrator.ts` is the last feature consumer that wires the 8-step scan-extract-merge-transform pipeline inline... +- **Gherkin Patterns Restructure**: `docs/GHERKIN-PATTERNS.md` is 515 lines and mixes two distinct concerns: (a) a writing guide for Gherkin authoring... +- **Generated Doc Quality**: Four quality issues reduce the usefulness of generated docs for both Claude agents and human developers: (1)... +- **Error Guide Codec**: `docs/PROCESS-GUARD.md` (341 lines) is manually maintained with per-error-code diagnosis guides, escape hatch... +- **Enhanced Index Generation**: `docs/INDEX.md` (354 lines) is a manually maintained navigation hub with audience-based reading orders, per-document... +- **Docs Live Consolidation**: `docs-generated/` mixes production reference documents (ARCHITECTURE-CODECS.md, ARCHITECTURE-TYPES.md at 19 KB and 14... +- **Doc Generation Proof Of Concept**: Status: SUPERSEDED - This POC has been implemented. +- **Declaration Level Shape Tagging**: The current shape extraction system operates at file granularity. +- **Data API Stub Integration**: Design sessions produce code stubs in `delivery-process/stubs/` with rich metadata: `@target` (destination file... +- **Data API Design Session Support**: Starting a design or implementation session requires manually compiling elaborate context prompts. +- **Data API Output Shaping**: The ProcessStateAPI CLI returns raw `ExtractedPattern` objects via `JSON.stringify`. +- **Data API Context Assembly**: Starting a Claude Code design or implementation session requires assembling 30-100KB of curated, multi-source context... +- **Data API Architecture Queries**: The current `arch` subcommand provides basic queries (roles, context, layer, graph) but lacks deeper analysis needed... +- **Cross Cutting Document Inclusion**: The reference doc codec assembles content from four sources, each with its own selection mechanism: conventionTags... +- **Config Based Workflow Definition**: Every `pnpm process:query` and `pnpm docs:*` invocation prints: `Failed to load default workflow (6-phase-standard):... +- **Codec Driven Reference Generation**: Each reference document (Process Guard, Taxonomy, Validation, etc.) required a hand-coded recipe feature that... +- **Cli Recipe Codec**: `docs/PROCESS-API.md` (~509 lines) retains ~460 lines of editorial prose after Phase 43 (ProcessApiHybridGeneration)... +- **Claude Module Generation**: Problem: CLAUDE.md modules are hand-written markdown files that drift from source code over time. +- **Architecture Doc Refactoring**: ARCHITECTURE.md is 1,287 lines of manually-maintained documentation covering 14 sections. +- **Status Transition Detection Testing**: Tests for the detectStatusTransitions function that parses git diff output. +- **Process Guard Testing**: Pure validation functions for enforcing delivery process rules per PDR-005. +- **FSM Validator Testing**: Pure validation functions for the 4-state FSM defined in PDR-005. +- **DoD Validator Testing**: Validates that completed phases meet Definition of Done criteria: 1. +- **Detect Changes Testing**: Tests for the detectDeliverableChanges function that parses git diff output. +- **Config Schema Validation**: Configuration schemas validate scanner and generator inputs with security constraints to prevent path traversal... +- **Anti Pattern Detector Testing**: Detects violations of the dual-source documentation architecture and process hygiene issues that lead to... +- **Result Monad**: The Result type provides explicit error handling via a discriminated union. +- **Error Factories**: Error factories create structured, discriminated error types with consistent message formatting. +- **Gherkin Ast Parser**: The Gherkin AST parser extracts feature metadata, scenarios, and steps from .feature files for timeline generation... +- **File Discovery**: The file discovery system uses glob patterns to find TypeScript files for documentation extraction. +- **Doc String Media Type**: DocString language hints (mediaType) should be preserved through the parsing pipeline from feature files to rendered... +- **Ast Parser Relationships Edges**: The AST Parser extracts @libar-docs-\* directives from TypeScript source files using the TypeScript compiler API. +- **Ast Parser Metadata**: The AST Parser extracts @libar-docs-\* directives from TypeScript source files using the TypeScript compiler API. +- **Ast Parser Exports**: The AST Parser extracts @libar-docs-\* directives from TypeScript source files using the TypeScript compiler API. +- **Rule Keyword Po C**: This feature tests whether vitest-cucumber supports the Rule keyword for organizing scenarios under business rules. +- **Lint Rule Individual Testing**: Individual lint rules that check parsed directives for completeness. +- **Lint Rule Advanced Testing**: Complex lint rule logic and collection-level behavior. +- **Lint Engine Testing**: The lint engine orchestrates rule execution, aggregates violations, and formats output for human and machine... +- **Table Extraction**: Tables in business rule descriptions should appear exactly once in output. +- **Generator Registry Testing**: Tests the GeneratorRegistry registration, lookup, and listing capabilities. +- **Prd Implementation Section Testing**: Tests the Implementations section rendering in pattern documents. +- **Pr Changes Options**: Tests the PrChangesCodec filtering capabilities for generating PR-scoped documentation. +- **Documentation Orchestrator**: Tests the orchestrator's pattern merging, conflict detection, and generator coordination capabilities. +- **Codec Based Generator Testing**: Tests the CodecBasedGenerator which adapts the RenderableDocument Model (RDM) codec system to the DocumentGenerator... +- **Business Rules Document Codec**: Tests the BusinessRulesCodec transformation from MasterDataset to RenderableDocument. +- **Shape Extraction Types Testing**: Validates the shape extraction system that extracts TypeScript type definitions (interfaces, type aliases, enums,... +- **Shape Extraction Rendering Testing**: Validates the shape extraction system that extracts TypeScript type definitions (interfaces, type aliases, enums,... +- **Extraction Pipeline Enhancements Testing**: Validates extraction pipeline capabilities for ReferenceDocShowcase: function signature surfacing, full... +- **Dual Source Extractor Testing**: Extracts and combines pattern metadata from both TypeScript code stubs (@libar-docs-) and Gherkin feature files... +- **Declaration Level Shape Tagging Testing**: Tests the discoverTaggedShapes function that scans TypeScript source code for declarations annotated with the... +- **Source Merging**: mergeSourcesForGenerator computes effective sources for a specific generator by applying per-generator overrides to... +- **Project Config Loader**: loadProjectConfig loads and resolves configuration from file, supporting both new-style defineConfig and legacy... +- **Preset System**: Presets provide pre-configured taxonomies for different project types. +- **Define Config Testing**: The defineConfig identity function and DeliveryProcessProjectConfigSchema provide type-safe configuration authoring... +- **Configuration API**: The createDeliveryProcess factory provides a type-safe way to configure the delivery process with custom tag prefixes... +- **Config Resolution**: resolveProjectConfig transforms a raw DeliveryProcessProjectConfig into a fully resolved ResolvedConfig with all... +- **Config Loader Testing**: The config loader discovers and loads `delivery-process.config.ts` files for hierarchical configuration, enabling... +- **Validate Patterns Cli**: Command-line interface for cross-validating TypeScript patterns vs Gherkin feature files. +- **Process Api Cli Subcommands**: Discovery subcommands: list, search, context assembly, tags/sources, extended arch, unannotated. +- **Process Api Cli Modifiers And Rules**: Output modifiers, arch health, and rules subcommand. +- **Process Api Cli Core**: Core CLI infrastructure: help, version, input validation, status, query, pattern, arch basics, missing args, edge cases. +- **Lint Process Cli**: Command-line interface for validating changes against delivery process rules. +- **Lint Patterns Cli**: Command-line interface for validating pattern annotation quality. +- **Generate Tag Taxonomy Cli**: Command-line interface for generating TAG_TAXONOMY.md from tag registry configuration. +- **Generate Docs Cli**: Command-line interface for generating documentation from annotated TypeScript. +- **Transform Dataset Testing**: The transformToMasterDataset function transforms raw extracted patterns into a MasterDataset with all pre-computed... +- **Session Handoffs**: The delivery process supports mid-phase handoffs between sessions and coordination across multiple developers through... +- **Session File Lifecycle**: Orphaned session files are automatically cleaned up during generation, maintaining a clean docs-living/sessions/... +- **Scanner Core**: The scanPatterns function orchestrates file discovery, directive detection, and AST parsing to extract documentation... +- **Renderer Output Formats**: The universal renderer converts RenderableDocument to markdown. +- **Renderer Block Types**: The universal renderer converts RenderableDocument to markdown. +- **Remaining Work Summary Accuracy**: Summary totals in REMAINING-WORK.md must match the sum of phase table rows. +- **Remaining Work Enhancement**: Enhanced REMAINING-WORK.md generation with priority-based sorting, quarter grouping, and progressive disclosure for... +- **Pr Changes Generation**: The delivery process generates PR-CHANGES.md from active or completed phases, formatted for PR descriptions, code... +- **Patterns Codec Testing**: The PatternsDocumentCodec transforms MasterDataset into a RenderableDocument for generating PATTERNS.md and category... +- **Pattern Tag Extraction**: The extractPatternTags function parses Gherkin feature tags into structured metadata objects for pattern processing. +- **Layer Inference Testing**: The layer inference module classifies feature files into testing layers (timeline, domain, integration, e2e,... +- **Implementation Link Path Normalization**: Links to implementation files in generated pattern documents should have correct relative paths. +- **Extract Summary**: The extractSummary function transforms multi-line pattern descriptions into concise, single-line summaries suitable... +- **Error Handling Unification**: All CLI commands and extractors should use the DocError discriminated union pattern for consistent, structured error... +- **Directive Detection**: Pure functions that detect @libar-docs directives in TypeScript source code. +- **Description Quality Foundation**: Enhanced documentation generation with human-readable names, behavior file verification, and numbered acceptance... +- **Description Header Normalization**: Pattern descriptions should not create duplicate headers when rendered. +- **Context Inference**: Patterns in standard directories (src/validation/, src/scanner/) should automatically receive architecture context... +- **Zod Codec Migration**: All JSON parsing and serialization uses type-safe Zod codec pattern, replacing raw JSON.parse/stringify with... +- **Process State API Testing**: Programmatic interface for querying delivery process state. +- **Warning Collector Testing**: The warning collector provides a unified system for capturing, categorizing, and reporting non-fatal issues during... +- **Validation Rules Codec Testing**: Validates the Validation Rules Codec that transforms MasterDataset into a RenderableDocument for Process Guard... +- **Taxonomy Codec Testing**: Validates the Taxonomy Codec that transforms MasterDataset into a RenderableDocument for tag taxonomy reference... +- **Source Mapping Validator Testing**: Context: Source mappings reference files that may not exist, use invalid extraction methods, or have incompatible... +- **Source Mapper Testing**: The Source Mapper aggregates content from multiple source files based on source mapping tables parsed from decision... +- **Robustness Integration**: Context: Document generation pipeline needs validation, deduplication, and warning collection to work together... +- **Poc Integration**: End-to-end integration tests that exercise the full documentation generation pipeline using the actual POC decision... +- **Decision Doc Generator Testing**: The Decision Doc Generator orchestrates the full documentation generation pipeline from decision documents (ADR/PDR in . +- **Decision Doc Codec Testing**: Validates the Decision Doc Codec that parses decision documents (ADR/PDR in .feature format) and extracts content for... +- **Content Deduplication**: Context: Multiple sources may extract identical content, leading to duplicate sections in generated documentation. +- **String Utils**: String utilities provide consistent text transformations across the codebase. +- **Mermaid Relationship Rendering**: Tests for rendering all relationship types in Mermaid dependency graphs with distinct visual styles per relationship... +- **Linter Validation Testing**: Tests for lint rules that validate relationship integrity, detect conflicts, and ensure bidirectional traceability... +- **Implements Tag Processing**: Tests for the @libar-docs-implements tag which links implementation files to their corresponding roadmap pattern... +- **Extends Tag Testing**: Tests for the @libar-docs-extends tag which establishes generalization relationships between patterns (pattern... +- **Process Api Reference Tests**: Verifies that the declarative CLI schema drives reference table generation and stays in sync with the parser... +- **Timeline Codec Testing**: The timeline codecs (RoadmapDocumentCodec, CompletedMilestonesCodec, CurrentWorkCodec) transform MasterDataset into... +- **Shape Selector Testing**: Tests the filterShapesBySelectors function that provides fine-grained shape selection via structural discriminated... +- **Shape Matcher Testing**: Matches file paths against glob patterns for TypeScript shape extraction. +- **Session Codec Testing**: The session codecs (SessionContextCodec, RemainingWorkCodec) transform MasterDataset into RenderableDocuments for AI... +- **Requirements Adr Codec Testing**: The RequirementsDocumentCodec and AdrDocumentCodec transform MasterDataset into RenderableDocuments for PRD-style and... +- **Reporting Codec Testing**: The reporting codecs (ChangelogCodec, TraceabilityCodec, OverviewCodec) transform MasterDataset into... +- **Reference Generator Testing**: Registers reference document generators from project config. +- **Reference Codec Diagram Testing**: Scoped diagram generation from diagramScope and diagramScopes config, including archContext, include, archLayer,... +- **Reference Codec Diagram Type Testing**: Diagram type controls Mermaid output format including flowchart, sequenceDiagram, stateDiagram-v2, C4Context, and... +- **Reference Codec Detail Rendering**: Standard detail level behavior, deep behavior rendering with structured annotations, shape JSDoc prose,... +- **Reference Codec Core Testing**: Parameterized codec factory that creates reference document codecs from configuration objects. +- **Pr Changes Codec Rendering Testing**: The PrChangesCodec transforms MasterDataset into RenderableDocument for PR-scoped documentation. +- **Pr Changes Codec Options Testing**: The PrChangesCodec transforms MasterDataset into RenderableDocument for PR-scoped documentation. +- **Planning Codec Testing**: The planning codecs (PlanningChecklistCodec, SessionPlanCodec, SessionFindingsCodec) transform MasterDataset into... +- **Generated Doc Quality Tests**: Tests for the four quality fixes in GeneratedDocQuality (Phase 38): duplicate table removal, Generation compact... +- **Dedent Helper**: The dedent helper function normalizes indentation in code blocks extracted from DocStrings. +- **Convention Extractor Testing**: Extracts convention content from MasterDataset decision records tagged with @libar-docs-convention. +- **Composite Codec Testing**: Assembles reference documents from multiple codec outputs by concatenating RenderableDocument sections. +- **Scope Validator Tests**: Starting an implementation or design session without checking prerequisites wastes time when blockers are discovered... +- **Handoff Generator Tests**: Multi-session work loses critical state between sessions when handoff documentation is manual or forgotten. +- **Layered Diagram Generation**: As a documentation generator I want to generate layered architecture diagrams from metadata So that system... +- **Arch Generator Registration**: As a CLI user I want an architecture generator registered in the generator registry So that I can run pnpm... +- **Component Diagram Generation**: As a documentation generator I want to generate component diagrams from architecture metadata So that system... +- **Arch Tag Extraction**: As a documentation generator I want architecture tags extracted from source code So that I can generate accurate... +- **Arch Index Dataset**: As a documentation generator I want an archIndex built during dataset transformation So that I can efficiently look... + +--- diff --git a/docs-live/DECISIONS.md b/docs-live/DECISIONS.md index adf543f9..08f6c4c9 100644 --- a/docs-live/DECISIONS.md +++ b/docs-live/DECISIONS.md @@ -7,14 +7,14 @@ ## Summary -| Metric | Value | -| ---------- | ----- | -| Total ADRs | 7 | -| Accepted | 5 | -| Proposed | 0 | -| Deprecated | 0 | -| Superseded | 1 | -| Categories | 4 | +| Metric | Value | +| --- | --- | +| Total ADRs | 7 | +| Accepted | 5 | +| Proposed | 0 | +| Deprecated | 0 | +| Superseded | 1 | +| Categories | 4 | --- @@ -24,9 +24,9 @@ 3 decisions -| ADR | Title | Status | -| -------------------------------------------------------------- | -------------------------------------- | -------- | -| [ADR-004](decisions/adr-004-session-workflow-commands.md) | PDR 001 Session Workflow Commands | accepted | +| ADR | Title | Status | +| --- | --- | --- | +| [ADR-004](decisions/adr-004-session-workflow-commands.md) | PDR 001 Session Workflow Commands | accepted | | [ADR-005](decisions/adr-005-codec-based-markdown-rendering.md) | ADR 005 Codec Based Markdown Rendering | accepted | | [ADR-006](decisions/adr-006-single-read-model-architecture.md) | ADR 006 Single Read Model Architecture | proposed | @@ -36,8 +36,8 @@ 1 decisions -| ADR | Title | Status | -| --------------------------------------------------------------- | ------------------------------- | ---------- | +| ADR | Title | Status | +| --- | --- | --- | | [ADR-021](decisions/adr-021-doc-generation-proof-of-concept.md) | Doc Generation Proof Of Concept | superseded | --- @@ -46,9 +46,9 @@ 2 decisions -| ADR | Title | Status | -| ----------------------------------------------------------------- | ----------------------------------------- | -------- | -| [ADR-001](decisions/adr-001-taxonomy-canonical-values.md) | ADR 001 Taxonomy Canonical Values | accepted | +| ADR | Title | Status | +| --- | --- | --- | +| [ADR-001](decisions/adr-001-taxonomy-canonical-values.md) | ADR 001 Taxonomy Canonical Values | accepted | | [ADR-003](decisions/adr-003-source-first-pattern-architecture.md) | ADR 003 Source First Pattern Architecture | accepted | --- @@ -57,22 +57,22 @@ 1 decisions -| ADR | Title | Status | -| ---------------------------------------------------- | ---------------------------- | -------- | +| ADR | Title | Status | +| --- | --- | --- | | [ADR-002](decisions/adr-002-gherkin-only-testing.md) | ADR 002 Gherkin Only Testing | accepted | --- ## ADR Index -| ADR | Title | Status | Category | -| ----------------------------------------------------------------- | ----------------------------------------- | ---------- | ------------- | -| [ADR-001](decisions/adr-001-taxonomy-canonical-values.md) | ADR 001 Taxonomy Canonical Values | accepted | process | -| [ADR-002](decisions/adr-002-gherkin-only-testing.md) | ADR 002 Gherkin Only Testing | accepted | testing | -| [ADR-003](decisions/adr-003-source-first-pattern-architecture.md) | ADR 003 Source First Pattern Architecture | accepted | process | -| [ADR-004](decisions/adr-004-session-workflow-commands.md) | PDR 001 Session Workflow Commands | accepted | architecture | -| [ADR-005](decisions/adr-005-codec-based-markdown-rendering.md) | ADR 005 Codec Based Markdown Rendering | accepted | architecture | -| [ADR-006](decisions/adr-006-single-read-model-architecture.md) | ADR 006 Single Read Model Architecture | proposed | architecture | -| [ADR-021](decisions/adr-021-doc-generation-proof-of-concept.md) | Doc Generation Proof Of Concept | superseded | documentation | +| ADR | Title | Status | Category | +| --- | --- | --- | --- | +| [ADR-001](decisions/adr-001-taxonomy-canonical-values.md) | ADR 001 Taxonomy Canonical Values | accepted | process | +| [ADR-002](decisions/adr-002-gherkin-only-testing.md) | ADR 002 Gherkin Only Testing | accepted | testing | +| [ADR-003](decisions/adr-003-source-first-pattern-architecture.md) | ADR 003 Source First Pattern Architecture | accepted | process | +| [ADR-004](decisions/adr-004-session-workflow-commands.md) | PDR 001 Session Workflow Commands | accepted | architecture | +| [ADR-005](decisions/adr-005-codec-based-markdown-rendering.md) | ADR 005 Codec Based Markdown Rendering | accepted | architecture | +| [ADR-006](decisions/adr-006-single-read-model-architecture.md) | ADR 006 Single Read Model Architecture | proposed | architecture | +| [ADR-021](decisions/adr-021-doc-generation-proof-of-concept.md) | Doc Generation Proof Of Concept | superseded | documentation | --- diff --git a/docs-live/INDEX.md b/docs-live/INDEX.md new file mode 100644 index 00000000..52edff89 --- /dev/null +++ b/docs-live/INDEX.md @@ -0,0 +1,226 @@ +# Documentation Index + +**Purpose:** Navigate the full documentation set for @libar-dev/delivery-process. Use section links for targeted reading. + +--- + +## Package Metadata + +| Field | Value | +| ----------------- | ----------------------------------------------------- | +| **Package** | @libar-dev/delivery-process | +| **Purpose** | Code-first documentation and delivery process toolkit | +| **Patterns** | 355 tracked (249 completed, 47 active, 59 planned) | +| **Product Areas** | 7 | +| **License** | MIT | + +--- + +## Quick Navigation + +| If you want to... | Read this | +| ------------------------------ | --------------------------------------------------------------- | +| Learn the architecture | [ARCHITECTURE.md](ARCHITECTURE.md) | +| Browse product area overviews | [PRODUCT-AREAS.md](PRODUCT-AREAS.md) | +| Review architecture decisions | [DECISIONS.md](DECISIONS.md) | +| Check business rules | [BUSINESS-RULES.md](BUSINESS-RULES.md) | +| Understand the tag taxonomy | [TAXONOMY.md](TAXONOMY.md) | +| Check validation rules | [VALIDATION-RULES.md](VALIDATION-RULES.md) | +| Browse the changelog | [CHANGELOG-GENERATED.md](CHANGELOG-GENERATED.md) | +| Query process state via CLI | [Process API Reference](reference/PROCESS-API-REFERENCE.md) | +| Find CLI workflow recipes | [Process API Recipes](reference/PROCESS-API-RECIPES.md) | +| Run AI coding sessions | [Session Workflow Guide](reference/SESSION-WORKFLOW-GUIDE.md) | +| Enforce delivery process rules | [Process Guard Reference](reference/PROCESS-GUARD-REFERENCE.md) | +| Learn annotation mechanics | [Annotation Reference](reference/ANNOTATION-REFERENCE.md) | +| See codec patterns and options | [Architecture Codecs](reference/ARCHITECTURE-CODECS.md) | +| Understand MasterDataset types | [Architecture Types](reference/ARCHITECTURE-TYPES.md) | + +--- + +## Reading Order + +### Overview + +1. **[ARCHITECTURE.md](ARCHITECTURE.md)** -- Architecture diagram from source annotations +2. **[PRODUCT-AREAS.md](PRODUCT-AREAS.md)** -- Product area overviews with live statistics and diagrams +3. **[TAXONOMY.md](TAXONOMY.md)** -- Tag taxonomy configuration and format types + +### Deep Dive + +1. **[DECISIONS.md](DECISIONS.md)** -- Architecture Decision Records extracted from specs +2. **[BUSINESS-RULES.md](BUSINESS-RULES.md)** -- Domain constraints and invariants from feature files +3. **[VALIDATION-RULES.md](VALIDATION-RULES.md)** -- Process Guard validation rules and FSM reference + +### Reference Guides + +1. **[Annotation Reference](reference/ANNOTATION-REFERENCE.md)** -- Annotation mechanics and tag reference +2. **[Session Workflow Guide](reference/SESSION-WORKFLOW-GUIDE.md)** -- Planning, Design, Implementation workflows +3. **[Process API Reference](reference/PROCESS-API-REFERENCE.md)** -- CLI command reference with flags and examples +4. **[Process Guard Reference](reference/PROCESS-GUARD-REFERENCE.md)** -- Pre-commit hooks, error codes, programmatic API + +--- + +## Document Roles + +| Document | Audience | Focus | +| ----------------------- | ---------- | ------------------------------------------------ | +| ARCHITECTURE.md | Developers | Architecture diagram from source annotations | +| PRODUCT-AREAS.md | Everyone | Product area overviews with live statistics | +| DECISIONS.md | Developers | Architecture Decision Records | +| BUSINESS-RULES.md | Developers | Domain constraints and invariants | +| TAXONOMY.md | Reference | Tag taxonomy structure and format types | +| VALIDATION-RULES.md | CI/CD | Process Guard validation rules and FSM reference | +| CHANGELOG-GENERATED.md | Everyone | Project changelog from release specs | +| Annotation Reference | Developers | Annotation mechanics, shape extraction | +| Session Workflow Guide | AI/Devs | Session decision trees and workflow checklists | +| Process API Reference | AI/Devs | CLI command reference with flags and examples | +| Process API Recipes | AI/Devs | CLI workflow recipes and session guides | +| Process Guard Reference | Team Leads | Pre-commit hooks, error codes, programmatic API | +| Architecture Codecs | Developers | All codecs with factory patterns and options | +| Architecture Types | Developers | MasterDataset interface and type shapes | + +--- + +## Key Concepts + +**Delivery Process** -- A code-first documentation and workflow toolkit. Extracts patterns from annotated TypeScript and Gherkin sources, generates markdown documentation, and validates delivery workflow via pre-commit hooks. + +**Pattern** -- An annotated unit of work tracked by the delivery process. Each pattern has a status (roadmap, active, completed, deferred), belongs to a product area, and has deliverables. Patterns are the atomic unit of the MasterDataset. + +**MasterDataset** -- The single read model (ADR-006) containing all extracted patterns with pre-computed views (byProductArea, byPhase, byStatus, byCategory). All codecs and the Data API consume this dataset. + +**Codec** -- A Zod-based transformer that decodes MasterDataset into a RenderableDocument. Each codec produces a specific document type. Codecs are pure functions with no I/O. + +**Dual-Source Architecture** -- Feature files own planning metadata (status, phase, dependencies). TypeScript files own implementation metadata (uses, used-by, category). This split prevents ownership conflicts. + +**Delivery Workflow FSM** -- A finite state machine enforcing pattern lifecycle: roadmap -> active -> completed. Transitions are validated by Process Guard at commit time. + +--- + +## Document Inventory + +### Overview + +| Document | Description | Audience | +| ----------------------------------- | -------------------------------------------------------- | ---------- | +| [Architecture](ARCHITECTURE.md) | Architecture diagram from source annotations | Developers | +| [Product Areas](PRODUCT-AREAS.md) | Product area overviews with live statistics and diagrams | Everyone | +| [Taxonomy](TAXONOMY.md) | Tag taxonomy configuration and format types | Reference | +| [Changelog](CHANGELOG-GENERATED.md) | Project changelog from release specs | Everyone | + +### Governance + +| Document | Description | Audience | +| --------------------------------------- | ---------------------------------------------------- | ---------- | +| [Decisions](DECISIONS.md) | Architecture Decision Records extracted from specs | Developers | +| [Business Rules](BUSINESS-RULES.md) | Domain constraints and invariants from feature files | Developers | +| [Validation Rules](VALIDATION-RULES.md) | Process Guard validation rules and FSM reference | CI/CD | + +### Reference Guides + +| Document | Description | Audience | +| --------------------------------------------------------------- | ----------------------------------------------------- | ---------- | +| [Annotation Reference](reference/ANNOTATION-REFERENCE.md) | Annotation mechanics, shape extraction, tag reference | Developers | +| [Session Workflow Guide](reference/SESSION-WORKFLOW-GUIDE.md) | Planning, Design, Implementation session workflows | AI/Devs | +| [Process API Reference](reference/PROCESS-API-REFERENCE.md) | CLI command reference with flags and examples | AI/Devs | +| [Process API Recipes](reference/PROCESS-API-RECIPES.md) | CLI workflow recipes and session guides | AI/Devs | +| [Process Guard Reference](reference/PROCESS-GUARD-REFERENCE.md) | Pre-commit hooks, error codes, programmatic API | Team Leads | +| [Architecture Codecs](reference/ARCHITECTURE-CODECS.md) | All codecs with factory patterns and options | Developers | +| [Architecture Types](reference/ARCHITECTURE-TYPES.md) | MasterDataset interface and type shapes | Developers | + +### Product Area Details + +| Document | Description | Audience | +| ----------------------------------------------- | -------------------------------------------------- | ---------- | +| [Annotation](product-areas/ANNOTATION.md) | Annotation product area patterns and statistics | Developers | +| [Configuration](product-areas/CONFIGURATION.md) | Configuration product area patterns and statistics | Users | +| [Core Types](product-areas/CORE-TYPES.md) | Core types product area patterns and statistics | Developers | +| [Data API](product-areas/DATA-API.md) | Data API product area patterns and statistics | AI/Devs | +| [Generation](product-areas/GENERATION.md) | Generation product area patterns and statistics | Developers | +| [Process](product-areas/PROCESS.md) | Process product area patterns and statistics | Team Leads | +| [Validation](product-areas/VALIDATION.md) | Validation product area patterns and statistics | CI/CD | + +--- + +## Product Area Statistics + +| Area | Patterns | Completed | Active | Planned | Progress | +| ------------- | -------- | --------- | ------ | ------- | -------------------------- | +| Annotation | 26 | 23 | 2 | 1 | [███████░] 23/26 88% | +| Configuration | 9 | 8 | 0 | 1 | [███████░] 8/9 89% | +| CoreTypes | 7 | 6 | 0 | 1 | [███████░] 6/7 86% | +| DataAPI | 35 | 22 | 9 | 4 | [█████░░░] 22/35 63% | +| Generation | 91 | 77 | 2 | 12 | [███████░] 77/91 85% | +| Process | 11 | 4 | 0 | 7 | [███░░░░░] 4/11 36% | +| Validation | 22 | 15 | 0 | 7 | [█████░░░] 15/22 68% | +| **Total** | **201** | **155** | **13** | **33** | **[██████░░] 155/201 77%** | + +--- + +## Phase Progress + +**355** patterns total: **249** completed (70%), **47** active, **59** planned. [██████████████░░░░░░] 249/355 + +| Status | Count | Percentage | +| --------- | ----- | ---------- | +| Completed | 249 | 70% | +| Active | 47 | 13% | +| Planned | 59 | 17% | + +### By Phase + +| Phase | Patterns | Completed | Progress | +| --------- | -------- | --------- | -------- | +| Phase 18 | 1 | 0 | 0% | +| Phase 23 | 2 | 0 | 0% | +| Phase 24 | 2 | 2 | 100% | +| Phase 25 | 10 | 6 | 60% | +| Phase 26 | 2 | 2 | 100% | +| Phase 27 | 3 | 3 | 100% | +| Phase 28 | 2 | 2 | 100% | +| Phase 30 | 1 | 1 | 100% | +| Phase 31 | 1 | 1 | 100% | +| Phase 32 | 1 | 1 | 100% | +| Phase 35 | 5 | 4 | 80% | +| Phase 36 | 1 | 1 | 100% | +| Phase 37 | 1 | 1 | 100% | +| Phase 38 | 1 | 1 | 100% | +| Phase 39 | 1 | 1 | 100% | +| Phase 40 | 1 | 1 | 100% | +| Phase 41 | 1 | 1 | 100% | +| Phase 42 | 1 | 1 | 100% | +| Phase 43 | 1 | 1 | 100% | +| Phase 44 | 2 | 0 | 0% | +| Phase 50 | 1 | 1 | 100% | +| Phase 51 | 1 | 0 | 0% | +| Phase 99 | 9 | 5 | 56% | +| Phase 100 | 15 | 4 | 27% | +| Phase 101 | 2 | 1 | 50% | +| Phase 102 | 1 | 0 | 0% | +| Phase 103 | 1 | 0 | 0% | +| Phase 104 | 1 | 0 | 0% | + +--- + +## Regeneration + +Regenerate all documentation from annotated sources: + +```bash +pnpm docs:all # Regenerate all generated docs +pnpm docs:all-preview # Also generate ephemeral workflow docs +``` + +Individual generators: + +```bash +pnpm docs:product-areas # Product area docs +pnpm docs:decisions # Architecture decisions +pnpm docs:reference # Reference documents +pnpm docs:business-rules # Business rules +pnpm docs:taxonomy # Taxonomy reference +pnpm docs:validation # Validation rules +pnpm docs:claude-modules # Claude context modules +pnpm docs:process-api-reference # Process API CLI reference +pnpm docs:cli-recipe # CLI recipes & workflow guide +``` diff --git a/docs-live/PRODUCT-AREAS.md b/docs-live/PRODUCT-AREAS.md index 77254d06..bd68135f 100644 --- a/docs-live/PRODUCT-AREAS.md +++ b/docs-live/PRODUCT-AREAS.md @@ -29,11 +29,11 @@ Configuration is the entry boundary — it transforms a user-authored `delivery- > **How does code become docs?** -The generation pipeline transforms annotated source code into markdown documents. It follows a four-stage architecture: Scanner → Extractor → Transformer → Codec. Codecs are pure functions — given a MasterDataset, they produce a RenderableDocument without side effects. CompositeCodec composes multiple codecs into a single document. +The generation pipeline transforms annotated source code into markdown documents through a four-stage architecture: Scanner discovers files, Extractor produces `ExtractedPattern` objects, Transformer builds MasterDataset with pre-computed views, and Codecs render to markdown via RenderableDocument IR. Nine specialized codecs handle reference docs, planning, session, reporting, timeline, ADRs, business rules, taxonomy, and composite output — each supporting three detail levels (detailed, standard, summary). The Orchestrator runs generators in registration order, producing both detailed `docs-live/` references and compact `_claude-md/` summaries. -**75 patterns** — 62 completed, 1 active, 12 planned +**91 patterns** — 77 completed, 2 active, 12 planned -**Key patterns:** ADR005CodecBasedMarkdownRendering, CodecDrivenReferenceGeneration, CrossCuttingDocumentInclusion, ArchitectureDiagramGeneration, ScopedArchitecturalView +**Key patterns:** ADR005CodecBasedMarkdownRendering, CodecDrivenReferenceGeneration, CrossCuttingDocumentInclusion, ArchitectureDiagramGeneration, ScopedArchitecturalView, CompositeCodec, RenderableDocument, ProductAreaOverview ## [Validation](product-areas/VALIDATION.md) @@ -41,7 +41,7 @@ The generation pipeline transforms annotated source code into markdown documents Validation is the enforcement boundary — it ensures that every change to annotated source files respects the delivery lifecycle rules defined by the FSM, protection levels, and scope constraints. The system operates in three layers: the FSM validator checks status transitions against a 4-state directed graph, the Process Guard orchestrates commit-time validation using a Decider pattern (state derived from annotations, not stored separately), and the lint engine provides pluggable rule execution with pretty and JSON output. Anti-pattern detection enforces dual-source ownership boundaries — `@libar-docs-uses` belongs on TypeScript, `@libar-docs-depends-on` belongs on Gherkin — preventing cross-domain tag confusion that causes documentation drift. Definition of Done validation ensures completed patterns have all deliverables marked done and at least one acceptance-criteria scenario. -**22 patterns** — 14 completed, 1 active, 7 planned +**22 patterns** — 15 completed, 0 active, 7 planned **Key patterns:** ProcessGuardLinter, PhaseStateMachineValidation, DoDValidation, StepLintVitestCucumber, ProgressiveGovernance @@ -51,7 +51,7 @@ Validation is the enforcement boundary — it ensures that every change to annot The Data API provides direct terminal access to delivery process state. It replaces reading generated markdown or launching explore agents — targeted queries use 5-10x less context. The `context` command assembles curated bundles tailored to session type (planning, design, implement). -**34 patterns** — 20 completed, 10 active, 4 planned +**35 patterns** — 22 completed, 9 active, 4 planned **Key patterns:** DataAPIContextAssembly, ProcessStateAPICLI, DataAPIDesignSessionSupport, DataAPIRelationshipGraph, DataAPIOutputShaping @@ -83,12 +83,12 @@ Process defines the USDP-inspired session workflow that governs how work moves t | ----------------------------------------------- | -------- | --------- | ------ | ------- | | [Annotation](product-areas/ANNOTATION.md) | 26 | 23 | 2 | 1 | | [Configuration](product-areas/CONFIGURATION.md) | 9 | 8 | 0 | 1 | -| [Generation](product-areas/GENERATION.md) | 75 | 62 | 1 | 12 | -| [Validation](product-areas/VALIDATION.md) | 22 | 14 | 1 | 7 | -| [DataAPI](product-areas/DATA-API.md) | 34 | 20 | 10 | 4 | +| [Generation](product-areas/GENERATION.md) | 91 | 77 | 2 | 12 | +| [Validation](product-areas/VALIDATION.md) | 22 | 15 | 0 | 7 | +| [DataAPI](product-areas/DATA-API.md) | 35 | 22 | 9 | 4 | | [CoreTypes](product-areas/CORE-TYPES.md) | 7 | 6 | 0 | 1 | | [Process](product-areas/PROCESS.md) | 11 | 4 | 0 | 7 | -| **Total** | **184** | **137** | **14** | **33** | +| **Total** | **201** | **155** | **13** | **33** | --- @@ -107,6 +107,11 @@ C4Context System(DefineConfig, "DefineConfig") System(ConfigLoader, "ConfigLoader") } + Boundary(renderer, "Renderer") { + System(CompositeCodec, "CompositeCodec") + } + System(ADR003SourceFirstPatternArchitecture, "ADR003SourceFirstPatternArchitecture") + System(ADR001TaxonomyCanonicalValues, "ADR001TaxonomyCanonicalValues") System(ShapeExtraction, "ShapeExtraction") System(ScopedArchitecturalView, "ScopedArchitecturalView") System(DeclarationLevelShapeTagging, "DeclarationLevelShapeTagging") @@ -115,8 +120,6 @@ C4Context System(DataAPIContextAssembly, "DataAPIContextAssembly") System(CrossCuttingDocumentInclusion, "CrossCuttingDocumentInclusion") System(CodecDrivenReferenceGeneration, "CodecDrivenReferenceGeneration") - System(ADR003SourceFirstPatternArchitecture, "ADR003SourceFirstPatternArchitecture") - System(ADR001TaxonomyCanonicalValues, "ADR001TaxonomyCanonicalValues") System(ResultMonad, "ResultMonad") System(ErrorFactories, "ErrorFactories") System(StringUtils, "StringUtils") @@ -141,6 +144,8 @@ C4Context Rel(DefineConfig, ProjectConfigTypes, "uses") Rel(ConfigLoader, DeliveryProcessFactory, "uses") Rel(ConfigLoader, ConfigurationTypes, "uses") + Rel(CompositeCodec, ReferenceDocShowcase, "implements") + Rel(ADR003SourceFirstPatternArchitecture, ADR001TaxonomyCanonicalValues, "depends on") Rel(ScopedArchitecturalView, ShapeExtraction, "depends on") Rel(DeclarationLevelShapeTagging, ShapeExtraction, "depends on") Rel(DeclarationLevelShapeTagging, ReferenceDocShowcase, "depends on") @@ -152,7 +157,6 @@ C4Context Rel(CrossCuttingDocumentInclusion, ReferenceDocShowcase, "depends on") Rel(CodecDrivenReferenceGeneration, DocGenerationProofOfConcept, "depends on") Rel(CodecDrivenReferenceGeneration, ScopedArchitecturalView, "depends on") - Rel(ADR003SourceFirstPatternArchitecture, ADR001TaxonomyCanonicalValues, "depends on") Rel(ExtractionPipelineEnhancementsTesting, ReferenceDocShowcase, "implements") Rel(KebabCaseSlugs, StringUtils, "depends on") Rel(ErrorHandlingUnification, ResultMonad, "depends on") @@ -182,6 +186,11 @@ graph LR DefineConfig[/"DefineConfig"/] ConfigLoader[/"ConfigLoader"/] end + subgraph renderer["Renderer"] + CompositeCodec[("CompositeCodec")] + end + ADR003SourceFirstPatternArchitecture["ADR003SourceFirstPatternArchitecture"] + ADR001TaxonomyCanonicalValues["ADR001TaxonomyCanonicalValues"] ShapeExtraction["ShapeExtraction"] ScopedArchitecturalView["ScopedArchitecturalView"] DeclarationLevelShapeTagging["DeclarationLevelShapeTagging"] @@ -190,8 +199,6 @@ graph LR DataAPIContextAssembly["DataAPIContextAssembly"] CrossCuttingDocumentInclusion["CrossCuttingDocumentInclusion"] CodecDrivenReferenceGeneration["CodecDrivenReferenceGeneration"] - ADR003SourceFirstPatternArchitecture["ADR003SourceFirstPatternArchitecture"] - ADR001TaxonomyCanonicalValues["ADR001TaxonomyCanonicalValues"] ResultMonad["ResultMonad"] ErrorFactories["ErrorFactories"] StringUtils["StringUtils"] @@ -218,6 +225,8 @@ graph LR DefineConfig -->|uses| ProjectConfigTypes ConfigLoader -->|uses| DeliveryProcessFactory ConfigLoader -->|uses| ConfigurationTypes + CompositeCodec ..->|implements| ReferenceDocShowcase + ADR003SourceFirstPatternArchitecture -.->|depends on| ADR001TaxonomyCanonicalValues ScopedArchitecturalView -.->|depends on| ShapeExtraction DeclarationLevelShapeTagging -.->|depends on| ShapeExtraction DeclarationLevelShapeTagging -.->|depends on| ReferenceDocShowcase @@ -229,7 +238,6 @@ graph LR CrossCuttingDocumentInclusion -.->|depends on| ReferenceDocShowcase CodecDrivenReferenceGeneration -.->|depends on| DocGenerationProofOfConcept CodecDrivenReferenceGeneration -.->|depends on| ScopedArchitecturalView - ADR003SourceFirstPatternArchitecture -.->|depends on| ADR001TaxonomyCanonicalValues ExtractionPipelineEnhancementsTesting ..->|implements| ReferenceDocShowcase KebabCaseSlugs -.->|depends on| StringUtils ErrorHandlingUnification -.->|depends on| ResultMonad diff --git a/docs-live/TAXONOMY.md b/docs-live/TAXONOMY.md new file mode 100644 index 00000000..bb0413d8 --- /dev/null +++ b/docs-live/TAXONOMY.md @@ -0,0 +1,199 @@ +# Taxonomy Reference + +**Purpose:** Tag taxonomy configuration for code-first documentation +**Detail Level:** Overview with links to details + +--- + +## Overview + +**3 categories** | **56 metadata tags** | **3 aggregation tags** + +Current configuration uses `@libar-docs-` prefix with `@libar-docs` file opt-in. + +| Component | Count | Description | +| ---------------- | ----- | ------------------------------------ | +| Categories | 3 | Pattern classification by domain | +| Metadata Tags | 56 | Pattern enrichment and relationships | +| Aggregation Tags | 3 | Document routing | + +--- + +## Categories + +Domain classifications for organizing patterns by priority. + +| Tag | Domain | Priority | Description | +| ------- | -------------- | -------- | -------------- | +| `core` | Core | 1 | Core patterns | +| `api` | API | 2 | Public APIs | +| `infra` | Infrastructure | 3 | Infrastructure | + +[Full category reference](taxonomy/categories.md) + +--- + +## Metadata Tags + +Tags for enriching patterns with additional metadata. + +### Core Tags + +| Tag | Format | Purpose | Required | Example | +| --------- | ------------ | -------------------------------------------- | -------- | ------------------------------------------------------ | +| `pattern` | value | Explicit pattern name | Yes | `@libar-docs-pattern CommandOrchestrator` | +| `status` | enum | Work item lifecycle status (per PDR-005 FSM) | No | `@libar-docs-status roadmap` | +| `core` | flag | Marks as essential/must-know pattern | No | `@libar-docs-core` | +| `usecase` | quoted-value | Use case association | No | `@libar-docs-usecase "When handling command failures"` | + +### Relationship Tags + +| Tag | Format | Purpose | Required | Example | +| ------------ | ------ | -------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------- | +| `uses` | csv | Patterns this depends on | No | `@libar-docs-uses CommandBus, EventStore` | +| `used-by` | csv | Patterns that depend on this | No | `@libar-docs-used-by SagaOrchestrator` | +| `depends-on` | csv | Roadmap dependencies (pattern or phase names) | No | `@libar-docs-depends-on EventStore, CommandBus` | +| `enables` | csv | Patterns this enables | No | `@libar-docs-enables SagaOrchestrator, ProjectionBuilder` | +| `implements` | csv | Patterns this code file realizes (realization relationship) | No | `@libar-docs-implements EventStoreDurability, IdempotentAppend` | +| `extends` | value | Base pattern this pattern extends (generalization relationship) | No | `@libar-docs-extends ProjectionCategories` | +| `see-also` | csv | Related patterns for cross-reference without dependency implication | No | `@libar-docs-see-also AgentAsBoundedContext, CrossContextIntegration` | +| `api-ref` | csv | File paths to implementation APIs (replaces 'See:' Markdown text in Rules) | No | `@libar-docs-api-ref @libar-dev/platform-core/src/durability/outbox.ts` | + +### Timeline Tags + +| Tag | Format | Purpose | Required | Example | +| --------------- | ------ | ------------------------------------------------------------ | -------- | ------------------------------------- | +| `phase` | number | Roadmap phase number (unified across monorepo) | No | `@libar-docs-phase 14` | +| `release` | value | Target release version (semver or vNEXT for unreleased work) | No | `@libar-docs-release v0.1.0` | +| `quarter` | value | Delivery quarter for timeline tracking | No | `@libar-docs-quarter Q1-2026` | +| `completed` | value | Completion date (YYYY-MM-DD format) | No | `@libar-docs-completed 2026-01-08` | +| `effort` | value | Estimated effort (4h, 2d, 1w format) | No | `@libar-docs-effort 2d` | +| `effort-actual` | value | Actual effort spent (4h, 2d, 1w format) | No | `@libar-docs-effort-actual 3d` | +| `team` | value | Responsible team assignment | No | `@libar-docs-team platform` | +| `workflow` | enum | Workflow discipline for process tracking | No | `@libar-docs-workflow implementation` | +| `risk` | enum | Risk level for planning | No | `@libar-docs-risk medium` | +| `priority` | enum | Priority level for roadmap ordering | No | `@libar-docs-priority high` | + +### ADR Tags + +| Tag | Format | Purpose | Required | Example | +| ------------------- | ------ | ----------------------------------------------------- | -------- | --------------------------------------- | +| `adr` | value | ADR/PDR number for decision tracking | No | `@libar-docs-adr 015` | +| `adr-status` | enum | ADR/PDR decision status | No | `@libar-docs-adr-status accepted` | +| `adr-category` | value | ADR/PDR category (architecture, process, tooling) | No | `@libar-docs-adr-category architecture` | +| `adr-supersedes` | value | ADR/PDR number this decision supersedes | No | `@libar-docs-adr-supersedes 012` | +| `adr-superseded-by` | value | ADR/PDR number that supersedes this decision | No | `@libar-docs-adr-superseded-by 020` | +| `adr-theme` | enum | Theme grouping for related decisions (from synthesis) | No | `@libar-docs-adr-theme persistence` | +| `adr-layer` | enum | Evolutionary layer of the decision | No | `@libar-docs-adr-layer foundation` | + +### Architecture Tags + +| Tag | Format | Purpose | Required | Example | +| -------------- | ------ | ----------------------------------------------------------------- | -------- | ------------------------------------ | +| `arch-role` | enum | Architectural role for diagram generation (component type) | No | `@libar-docs-arch-role projection` | +| `arch-context` | value | Bounded context this component belongs to (for subgraph grouping) | No | `@libar-docs-arch-context orders` | +| `arch-layer` | enum | Architectural layer for layered diagrams | No | `@libar-docs-arch-layer application` | + +### Other Tags + +| Tag | Format | Purpose | Required | Example | +| ------------------------ | ------------ | -------------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------- | +| `brief` | value | Path to pattern brief markdown | No | `@libar-docs-brief docs/briefs/decider-pattern.md` | +| `product-area` | value | Product area for PRD grouping | No | `@libar-docs-product-area PlatformCore` | +| `user-role` | value | Target user persona for this feature | No | `@libar-docs-user-role Developer` | +| `business-value` | value | Business value statement (hyphenated for tag format) | No | `@libar-docs-business-value eliminates-event-replay-complexity` | +| `constraint` | value | Technical constraint affecting feature implementation | No | `@libar-docs-constraint requires-convex-backend` | +| `level` | enum | Hierarchy level for epic->phase->task breakdown | No | `@libar-docs-level epic` | +| `parent` | value | Parent pattern name in hierarchy (links tasks to phases, phases to epics) | No | `@libar-docs-parent AggregateArchitecture` | +| `title` | quoted-value | Human-readable display title (supports quoted values with spaces) | No | `@libar-docs-title:"Process Guard Linter"` | +| `executable-specs` | csv | Links roadmap spec to package executable spec locations (PDR-007) | No | `@libar-docs-executable-specs platform-decider/tests/features/behavior` | +| `roadmap-spec` | value | Links package spec back to roadmap pattern for traceability (PDR-007) | No | `@libar-docs-roadmap-spec DeciderPattern` | +| `behavior-file` | value | Path to behavior test feature file for traceability | No | `@libar-docs-behavior-file behavior/my-pattern.feature` | +| `discovered-gap` | value | Gap identified during session retrospective | No | `@libar-docs-discovered-gap missing-error-handling` | +| `discovered-improvement` | value | Improvement identified during session retrospective | No | `@libar-docs-discovered-improvement cache-invalidation` | +| `discovered-risk` | value | Risk identified during session retrospective | No | `@libar-docs-discovered-risk data-loss-on-migration` | +| `discovered-learning` | value | Learning captured during session retrospective | No | `@libar-docs-discovered-learning convex-mutation-limits` | +| `extract-shapes` | csv | TypeScript type names to extract from this file for documentation | No | `@libar-docs-extract-shapes DeciderInput, ValidationResult, ProcessViolation` | +| `shape` | value | Marks declaration as documentable shape, optionally with group name | No | `@libar-docs-shape api-types` | +| `include` | csv | Cross-cutting document inclusion for content routing and diagram scoping | No | `@libar-docs-include reference-sample,codec-system` | +| `target` | value | Target implementation path for stub files | No | `@libar-docs-target src/api/stub-resolver.ts` | +| `since` | value | Design session that created this pattern | No | `@libar-docs-since DS-A` | +| `convention` | csv | Convention domains for reference document generation from decision records | No | `@libar-docs-convention fsm-rules, testing-policy` | +| `claude-module` | value | Module identifier for CLAUDE.md module generation (becomes filename) | No | `@libar-docs-claude-module process-guard` | +| `claude-section` | enum | Target section directory in \_claude-md/ for module output | No | `@libar-docs-claude-section delivery-process` | +| `claude-tags` | csv | Variation filtering tags for modular-claude-md inclusion | No | `@libar-docs-claude-tags core-mandatory, delivery-process` | + +[Full metadata tag reference](taxonomy/metadata-tags.md) + +--- + +## Aggregation Tags + +Tags that route patterns to specific aggregated documents. + +| Tag | Target Document | Purpose | +| ---------- | --------------- | ------------------------------------------- | +| `overview` | OVERVIEW.md | Architecture overview patterns | +| `decision` | DECISIONS.md | ADR-style decisions (auto-numbered) | +| `intro` | None | Package introduction (template placeholder) | + +--- + +## Format Types + +How tag values are parsed and validated. + +| Format | Description | Example | +| -------------- | ----------------------------------- | -------------------------------------- | +| `value` | Simple string value | `@libar-docs-pattern MyPattern` | +| `enum` | Constrained to predefined values | `@libar-docs-status roadmap` | +| `quoted-value` | String in quotes (preserves spaces) | `@libar-docs-usecase "When X happens"` | +| `csv` | Comma-separated values | `@libar-docs-uses A, B, C` | +| `number` | Numeric value | `@libar-docs-phase 14` | +| `flag` | Boolean presence (no value) | `@libar-docs-core` | + +[Format type details](taxonomy/format-types.md) + +--- + +## Presets + +Available configuration presets. + +| Preset | Tag Prefix | Categories | Use Case | +| --------------- | -------------- | ---------- | --------------------------------------- | +| `generic` | `@docs-` | 3 | Simple projects with @docs- prefix | +| `libar-generic` | `@libar-docs-` | 3 | Default preset with @libar-docs- prefix | +| `ddd-es-cqrs` | `@libar-docs-` | 21 | Full DDD/ES/CQRS taxonomy | + +--- + +## Architecture + +Taxonomy source files and pipeline flow. + +```plaintext +src/taxonomy/ +├── categories.ts # Category definitions (21 DDD-ES-CQRS) +├── format-types.ts # Format type constants +├── registry-builder.ts # Single source of truth builder +├── status-values.ts # Status FSM values +├── generator-options.ts # Generator option values +├── hierarchy-levels.ts # Hierarchy level values +├── risk-levels.ts # Risk level values +└── index.ts # Barrel export +``` + +```mermaid +graph LR + Config[Configuration] --> Scanner[Scanner] + Scanner --> Extractor[Extractor] + Extractor --> Transformer[Transformer] + Transformer --> Codec[Codec] + Codec --> Markdown[Markdown] + + Registry[TagRegistry] --> Scanner + Registry --> Extractor +``` + +--- diff --git a/docs-live/VALIDATION-RULES.md b/docs-live/VALIDATION-RULES.md new file mode 100644 index 00000000..ed2a67fc --- /dev/null +++ b/docs-live/VALIDATION-RULES.md @@ -0,0 +1,119 @@ +# Validation Rules + +**Purpose:** Process Guard validation rules and FSM reference +**Detail Level:** Overview with links to details + +--- + +## Overview + +Process Guard validates delivery workflow changes at commit time using a Decider pattern. It enforces the 4-state FSM defined in PDR-005 and prevents common workflow violations. + +**6 validation rules** | **4 FSM states** | **3 protection levels** + +--- + +## Validation Rules + +Rules are checked in order. Errors block commit; warnings are informational. + +| Rule ID | Severity | Description | +| --------------------------- | -------- | --------------------------------------------------- | +| `completed-protection` | error | Completed specs require unlock-reason tag to modify | +| `invalid-status-transition` | error | Status transitions must follow FSM path | +| `scope-creep` | error | Active specs cannot add new deliverables | +| `session-scope` | warning | File outside session scope | +| `session-excluded` | error | File explicitly excluded from session | +| `deliverable-removed` | warning | Deliverable was removed from spec | + +[Full error catalog with fix instructions](validation/error-catalog.md) + +--- + +## FSM State Diagram + +Valid transitions per PDR-005 MVP Workflow: + +```mermaid +stateDiagram-v2 + [*] --> roadmap: new pattern + roadmap --> active + roadmap --> deferred + active --> completed + active --> roadmap: blocked/regressed + deferred --> roadmap + completed --> [*]: terminal +``` + +**Valid Transitions:** + +- `roadmap` -> `active` -> `completed` (normal flow) +- `active` -> `roadmap` (blocked/regressed) +- `roadmap` <-> `deferred` (parking) + +[Detailed transition matrix](validation/fsm-transitions.md) + +--- + +## Protection Levels + +Protection levels determine what modifications are allowed per status. + +| Status | Protection | Can Add Deliverables | Needs Unlock | +| ----------- | ---------- | -------------------- | ------------ | +| `roadmap` | none | Yes | No | +| `active` | scope | No | No | +| `completed` | hard | No | Yes | +| `deferred` | none | Yes | No | + +[Protection level details](validation/protection-levels.md) + +--- + +## CLI Usage + +```bash +# Pre-commit (default mode) +lint-process --staged + +# CI pipeline with strict mode +lint-process --all --strict + +# Override session scope checking +lint-process --staged --ignore-session + +# Debug: show derived process state +lint-process --staged --show-state +``` + +### Options + +| Flag | Description | +| ------------------ | --------------------------------------- | +| `--staged` | Validate staged files only (pre-commit) | +| `--all` | Validate all tracked files (CI) | +| `--strict` | Treat warnings as errors (exit 1) | +| `--ignore-session` | Skip session scope validation | +| `--show-state` | Debug: show derived process state | +| `--format json` | Machine-readable JSON output | + +### Exit Codes + +| Code | Meaning | +| ---- | ---------------------------------------------- | +| `0` | No errors (warnings allowed unless `--strict`) | +| `1` | Errors found or warnings with `--strict` | + +--- + +## Escape Hatches + +Override mechanisms for exceptional situations. + +| Situation | Solution | Example | +| ---------------------------- | --------------------- | ---------------------------------------- | +| Fix bug in completed spec | Add unlock reason tag | `@libar-docs-unlock-reason:'Fix-typo'` | +| Modify outside session scope | Use ignore flag | `lint-process --staged --ignore-session` | +| CI treats warnings as errors | Use strict flag | `lint-process --all --strict` | + +--- diff --git a/docs-live/_claude-md/annotation/annotation-overview.md b/docs-live/_claude-md/annotation/annotation-overview.md index 2acd5259..830e8f08 100644 --- a/docs-live/_claude-md/annotation/annotation-overview.md +++ b/docs-live/_claude-md/annotation/annotation-overview.md @@ -9,18 +9,19 @@ - Pipeline data preservation: Gherkin `Rule:` blocks, deliverables, scenarios, and all metadata flow through scanner → extractor → `ExtractedPattern` → generators without data loss - Dual-source merge with conflict detection: Same pattern name in both TypeScript and Gherkin produces a merge conflict error. Phase mismatches between sources produce validation errors + **Components:** Extractor (GherkinExtractor, DualSourceExtractor, Document Extractor), Scanner (Pattern Scanner, GherkinScanner, GherkinASTParser, TypeScript AST Parser) #### API Types -| Type | Kind | -| -------------------------------- | --------- | -| TagRegistry | interface | +| Type | Kind | +| --- | --- | +| TagRegistry | interface | | MetadataTagDefinitionForRegistry | interface | -| CategoryDefinition | interface | -| TagDefinition | type | -| CategoryTag | type | -| buildRegistry | function | -| METADATA_TAGS_BY_GROUP | const | -| CATEGORIES | const | -| CATEGORY_TAGS | const | +| CategoryDefinition | interface | +| TagDefinition | type | +| CategoryTag | type | +| buildRegistry | function | +| METADATA_TAGS_BY_GROUP | const | +| CATEGORIES | const | +| CATEGORY_TAGS | const | diff --git a/docs-live/_claude-md/annotation/annotation-reference.md b/docs-live/_claude-md/annotation/annotation-reference.md new file mode 100644 index 00000000..405eccaf --- /dev/null +++ b/docs-live/_claude-md/annotation/annotation-reference.md @@ -0,0 +1,131 @@ +### Annotation Reference Guide + +#### Getting Started + +Every file that participates in the annotation system must have a `@libar-docs` opt-in marker. Files without this marker are invisible to the scanner. + +##### File-Level Opt-In + +**TypeScript** -- file-level JSDoc block: + +```typescript +/** + * @libar-docs + * @libar-docs-pattern MyPattern + * @libar-docs-status roadmap + * @libar-docs-uses EventStore, CommandBus + * + * ## My Pattern - Description + */ +``` + +**Gherkin** -- file-level tags before `Feature:`: + +```gherkin +@libar-docs +@libar-docs-pattern:MyPattern +@libar-docs-status:roadmap +@libar-docs-phase:14 +Feature: My Pattern + + **Problem:** + Description of the problem. +``` + +##### Tag Prefix by Preset + +| Preset | Prefix | Categories | Use Case | +| ------------------------- | -------------- | ---------- | ----------------------------- | +| `libar-generic` (default) | `@libar-docs-` | 3 | Simple projects | +| `ddd-es-cqrs` | `@libar-docs-` | 21 | DDD/Event Sourcing monorepos | +| `generic` | `@docs-` | 3 | Simple projects, short prefix | + +##### Dual-Source Ownership + +| Source | Owns | Example Tags | +| -------------- | ----------------------------------------------- | -------------------------------------------- | +| **TypeScript** | Implementation: runtime deps, category, shapes | `uses`, `used-by`, `extract-shapes`, `shape` | +| **Gherkin** | Planning: status, phase, timeline, dependencies | `status`, `phase`, `depends-on`, `quarter` | + +#### Shape Extraction + +Shape extraction pulls TypeScript type definitions (interfaces, type aliases, enums, functions, consts) into generated documentation. There are three modes: + +##### Mode 1: File-Level Explicit Names + +List specific declaration names in the file-level JSDoc: + +```typescript +/** + * @libar-docs + * @libar-docs-extract-shapes MasterDatasetSchema, StatusGroupsSchema + */ +``` + +Names appear in the generated output in the order listed. + +##### Mode 2: File-Level Wildcard + +```typescript +/** + * @libar-docs + * @libar-docs-extract-shapes * + */ +``` + +Wildcard must be the sole value -- `*, Foo` is invalid. + +##### Mode 3: Declaration-Level Tagging + +Tag individual declarations with `@libar-docs-shape`, optionally with a group name: + +```typescript +/** @libar-docs-shape api-types */ +export interface CommandInput { + readonly aggregateId: string; + readonly payload: unknown; +} +``` + +The optional group name (`api-types`) enables filtering in diagram scopes and product area documents via `@libar-docs-include`. + +#### Critical Gotcha: Zod Schemas + +For Zod files, extract the **schema constant** (with `Schema` suffix), not the inferred type alias: + +| Wrong (type alias) | Correct (schema constant) | +| ---------------------------------------- | ----------------------------------------- | +| `@extract-shapes MasterDataset` | `@extract-shapes MasterDatasetSchema` | +| Shows: `z.infer` (unhelpful) | Shows: `z.object({...})` (full structure) | + +#### Verification + +##### CLI Commands + +```bash +# Tag usage inventory (counts per tag and value) +pnpm process:query -- tags + +# Find files missing @libar-docs opt-in marker +pnpm process:query -- unannotated --path src/types + +# File inventory by type (TS, Gherkin, Stubs) +pnpm process:query -- sources + +# Full pattern JSON including extractedShapes +pnpm process:query -- query getPattern MyPattern + +# Generate complete tag reference +npx generate-tag-taxonomy -o TAG_TAXONOMY.md -f +``` + +#### Common Issues + +| Symptom | Cause | Fix | +| ------------------------------- | ----------------------------------- | ------------------------------------------------ | +| Pattern not in scanner output | Missing `@libar-docs` opt-in marker | Add file-level `@libar-docs` JSDoc/tag | +| Shape shows `z.infer<>` wrapper | Extracted type alias, not schema | Use schema constant name (e.g., `FooSchema`) | +| Shape not in product area doc | Missing `@libar-docs-product-area` | Add product-area tag to file-level annotation | +| Declaration-level shape missing | No `@libar-docs-shape` on decl | Add `@libar-docs-shape` JSDoc to the declaration | +| Tag value rejected | Wrong format or invalid enum value | Check format type in taxonomy reference | +| Anti-pattern validation error | Tag on wrong source type | Move tag to correct source (TS vs Gherkin) | diff --git a/docs-live/_claude-md/architecture/architecture-codecs.md b/docs-live/_claude-md/architecture/architecture-codecs.md new file mode 100644 index 00000000..e7dbc399 --- /dev/null +++ b/docs-live/_claude-md/architecture/architecture-codecs.md @@ -0,0 +1,159 @@ +### Available Codecs Reference + +#### ValidationRulesCodec + +| Option | Type | Default | Description | +| ----------------------- | ------- | ------- | --------------------------------------------------- | +| includeFSMDiagram | boolean | true | Include FSM state diagram | +| includeCLIUsage | boolean | true | Include CLI usage section | +| includeEscapeHatches | boolean | true | Include escape hatches section | +| includeProtectionMatrix | boolean | true | Include protection levels matrix | +| includeErrorGuide | boolean | true | Include error guide with rationale and alternatives | + +#### RoadmapDocumentCodec + +| Option | Type | Default | Description | +| ------------------- | ------------------------ | ------- | ----------------------------------- | +| generateDetailFiles | boolean | true | Create phase detail files | +| filterStatus | NormalizedStatusFilter[] | [] | Filter by status | +| includeProcess | boolean | true | Show quarter, effort, team metadata | +| includeDeliverables | boolean | true | List deliverables per phase | +| filterPhases | number[] | [] | Filter to specific phases | + +#### CompletedMilestonesCodec + +#### CurrentWorkCodec + +#### TaxonomyDocumentCodec + +| Option | Type | Default | Description | +| ------------------ | ------- | ------- | ------------------------------- | +| includePresets | boolean | true | Include preset comparison table | +| includeFormatTypes | boolean | true | Include format type reference | +| includeArchDiagram | boolean | true | Include architecture diagram | +| groupByDomain | boolean | true | Group metadata tags by domain | + +#### SessionContextCodec + +#### RemainingWorkCodec + +| Option | Type | Default | Description | +| --------------------- | ---------------------------------------------- | ------- | ----------------------------- | +| includeIncomplete | boolean | true | Include planned items | +| includeBlocked | boolean | true | Show blocked items analysis | +| includeNextActionable | boolean | true | Next actionable items section | +| maxNextActionable | number | 5 | Max items in next actionable | +| sortBy | "phase" \| "priority" \| "effort" \| "quarter" | "phase" | Sort order | +| groupPlannedBy | "quarter" \| "priority" \| "level" \| "none" | "none" | Group planned items | + +#### RequirementsDocumentCodec + +| Option | Type | Default | Description | +| -------------------- | ---------------------------------------- | -------------- | -------------------------------- | +| generateDetailFiles | boolean | true | Create product area detail files | +| groupBy | "product-area" \| "user-role" \| "phase" | "product-area" | Primary grouping | +| filterStatus | NormalizedStatusFilter[] | [] | Filter by status (empty = all) | +| includeScenarioSteps | boolean | true | Show Given/When/Then steps | +| includeBusinessValue | boolean | true | Display business value metadata | +| includeBusinessRules | boolean | true | Show Gherkin Rule: sections | + +#### ChangelogCodec + +| Option | Type | Default | Description | +| ----------------- | ---------------------- | ------- | --------------------------------- | +| includeUnreleased | boolean | true | Include unreleased section | +| includeLinks | boolean | true | Include links | +| categoryMapping | Record | {} | Map categories to changelog types | + +#### TraceabilityCodec + +#### OverviewCodec + +#### ReferenceDocumentCodec + +| Option | Type | Description | +| ------------------ | --------------- | ------------------------------------------------------------ | +| conventionTags | string[] | Convention tag values to extract from decision records | +| diagramScope | DiagramScope | Single diagram configuration | +| diagramScopes | DiagramScope[] | Multiple diagrams (takes precedence over diagramScope) | +| shapeSources | string[] | Glob patterns for TypeScript shape extraction | +| shapeSelectors | ShapeSelector[] | Fine-grained declaration-level shape filtering | +| behaviorCategories | string[] | Category tags for behavior pattern content | +| includeTags | string[] | Cross-cutting content routing via include tags | +| preamble | SectionBlock[] | Static editorial sections prepended before generated content | +| productArea | string | Pre-filter all content sources to matching product area | +| excludeSourcePaths | string[] | Exclude patterns by source path prefix | + +| Type | Description | +| --------------- | -------------------------------------------------------------- | +| graph (default) | Flowchart with subgraphs by archContext, custom node shapes | +| sequenceDiagram | Sequence diagram with typed messages between participants | +| stateDiagram-v2 | State diagram with transitions from dependsOn relationships | +| C4Context | C4 context diagram with boundaries, systems, and relationships | +| classDiagram | Class diagram with archRole stereotypes and typed arrows | + +| Variant | Example | Behavior | +| -------------- | ----------------------------------------------- | --------------------------- | +| group only | `{ group: "api-types" }` | Match shapes by group tag | +| source + names | `{ source: "src/types.ts", names: ["Config"] }` | Named shapes from file | +| source only | `{ source: "src/path/*.ts" }` | All tagged shapes from glob | + +#### PrChangesCodec + +#### PlanningChecklistCodec + +#### SessionPlanCodec + +#### SessionFindingsCodec + +#### PatternsDocumentCodec + +| Option | Type | Default | Description | +| ---------------------- | ------------------------------------- | ---------- | ------------------------------------------- | +| generateDetailFiles | boolean | true | Create category detail files | +| detailLevel | "summary" \| "standard" \| "detailed" | "standard" | Output verbosity | +| includeDependencyGraph | boolean | true | Render Mermaid dependency graph | +| includeUseCases | boolean | true | Show use cases section | +| filterCategories | string[] | [] | Filter to specific categories (empty = all) | + +#### IndexCodec + +| Option | Type | Default | Description | +| ------------------------ | --------------- | ------- | ---------------------------------------------------------------- | +| preamble | SectionBlock[] | [] | Editorial sections (reading paths, document roles, key concepts) | +| documentEntries | DocumentEntry[] | [] | Static document inventory entries | +| includeProductAreaStats | boolean | true | Product area statistics table | +| includePhaseProgress | boolean | true | Phase progress summary | +| includeDocumentInventory | boolean | true | Unified document inventory | +| includePackageMetadata | boolean | true | Package metadata header | + +#### CompositeCodec + +#### ClaudeModuleCodec + +#### BusinessRulesCodec + +| Option | Type | Default | Description | +| -------------------- | ------------------------------------------ | ------------------- | ----------------------------------------- | +| groupBy | "domain" \| "phase" \| "domain-then-phase" | "domain-then-phase" | Primary grouping strategy | +| includeCodeExamples | boolean | false | Include code examples from DocStrings | +| includeTables | boolean | true | Include markdown tables from descriptions | +| includeRationale | boolean | true | Include rationale section per rule | +| filterDomains | string[] | [] | Filter by domain categories (empty = all) | +| filterPhases | number[] | [] | Filter by phases (empty = all) | +| onlyWithInvariants | boolean | false | Show only rules with explicit invariants | +| includeSource | boolean | true | Include source feature file link | +| includeVerifiedBy | boolean | true | Include Verified by scenario links | +| maxDescriptionLength | number | 150 | Max description length in standard mode | +| excludeSourcePaths | string[] | [] | Exclude patterns by source path prefix | + +#### ArchitectureDocumentCodec + +| Option | Type | Default | Description | +| ---------------- | ------------------------ | ----------- | ----------------------------------------- | +| diagramType | "component" \| "layered" | "component" | Type of diagram to generate | +| includeInventory | boolean | true | Include component inventory table | +| includeLegend | boolean | true | Include legend for arrow styles | +| filterContexts | string[] | [] | Filter to specific contexts (empty = all) | + +#### AdrDocumentCodec diff --git a/docs-live/_claude-md/architecture/architecture-types.md b/docs-live/_claude-md/architecture/architecture-types.md new file mode 100644 index 00000000..1f7a468a --- /dev/null +++ b/docs-live/_claude-md/architecture/architecture-types.md @@ -0,0 +1,38 @@ +### Architecture Types Reference + +#### API Types + +| Type | Kind | +| --- | --- | +| MasterDatasetSchema | const | +| StatusGroupsSchema | const | +| StatusCountsSchema | const | +| PhaseGroupSchema | const | +| SourceViewsSchema | const | +| RelationshipEntrySchema | const | +| RuntimeMasterDataset | interface | +| RawDataset | interface | +| PipelineOptions | interface | +| PipelineResult | interface | + + +#### Orchestrator Pipeline Responsibilities + +**Invariant:** The orchestrator is the integration boundary for full docs generation: it delegates dataset construction to the shared pipeline, then executes codecs and writes files. + + +#### Steps 1-8 via buildMasterDataset() + + +#### Steps 9-10: Codec Execution and File Writing + + +#### Shared Pipeline Factory Responsibilities + +**Invariant:** `buildMasterDataset()` is the shared factory for Steps 1-8 of the architecture pipeline and returns `Result` without process-level side effects. + + +#### 8-Step Dataset Build Flow + + +#### Consumer Architecture and PipelineOptions Differentiation diff --git a/docs-live/_claude-md/architecture/reference-sample.md b/docs-live/_claude-md/architecture/reference-sample.md new file mode 100644 index 00000000..fedf0005 --- /dev/null +++ b/docs-live/_claude-md/architecture/reference-sample.md @@ -0,0 +1,162 @@ +### Reference Generation Sample + +#### Product area canonical values + +**Invariant:** The product-area tag uses one of 7 canonical values. Each value represents a reader-facing documentation section, not a source module. + +| Value | Reader Question | Covers | +| ------------- | ----------------------------------- | ----------------------------------------------- | +| Annotation | How do I annotate code? | Scanning, extraction, tag parsing, dual-source | +| Configuration | How do I configure the tool? | Config loading, presets, resolution | +| Generation | How does code become docs? | Codecs, generators, rendering, diagrams | +| Validation | How is the workflow enforced? | FSM, DoD, anti-patterns, process guard, lint | +| DataAPI | How do I query process state? | Process state API, stubs, context assembly, CLI | +| CoreTypes | What foundational types exist? | Result monad, error factories, string utils | +| Process | How does the session workflow work? | Session lifecycle, handoffs, conventions | + +#### ADR category canonical values + +**Invariant:** The adr-category tag uses one of 4 values. + +| Value | Purpose | +| ------------- | --------------------------------------------- | +| architecture | System structure, component design, data flow | +| process | Workflow, conventions, annotation rules | +| testing | Test strategy, verification approach | +| documentation | Documentation generation, content structure | + +#### FSM status values and protection levels + +**Invariant:** Pattern status uses exactly 4 values with defined protection levels. These are enforced by Process Guard at commit time. + +| Status | Protection | Can Add Deliverables | Allowed Actions | +| --------- | ------------ | -------------------- | ------------------------------- | +| roadmap | None | Yes | Full editing | +| active | Scope-locked | No | Edit existing deliverables only | +| completed | Hard-locked | No | Requires unlock-reason tag | +| deferred | None | Yes | Full editing | + +#### Valid FSM transitions + +**Invariant:** Only these transitions are valid. All others are rejected by Process Guard. + +| From | To | Trigger | +| -------- | --------- | --------------------- | +| roadmap | active | Start work | +| roadmap | deferred | Postpone | +| active | completed | All deliverables done | +| active | roadmap | Blocked/regressed | +| deferred | roadmap | Resume planning | + +#### Tag format types + +**Invariant:** Every tag has one of 6 format types that determines how its value is parsed. + +| Format | Parsing | Example | +| ------------ | ------------------------------ | ------------------------------ | +| flag | Boolean presence, no value | @libar-docs-core | +| value | Simple string | @libar-docs-pattern MyPattern | +| enum | Constrained to predefined list | @libar-docs-status completed | +| csv | Comma-separated values | @libar-docs-uses A, B, C | +| number | Numeric value | @libar-docs-phase 15 | +| quoted-value | Preserves spaces | @libar-docs-brief:'Multi word' | + +#### Source ownership + +**Invariant:** Relationship tags have defined ownership by source type. Anti-pattern detection enforces these boundaries. + +| Tag | Correct Source | Wrong Source | Rationale | +| ---------- | -------------- | ------------- | ---------------------------------- | +| uses | TypeScript | Feature files | TS owns runtime dependencies | +| depends-on | Feature files | TypeScript | Gherkin owns planning dependencies | +| quarter | Feature files | TypeScript | Gherkin owns timeline metadata | +| team | Feature files | TypeScript | Gherkin owns ownership metadata | + +#### Quarter format convention + +**Invariant:** The quarter tag uses `YYYY-QN` format (e.g., `2026-Q1`). ISO-year-first sorting works lexicographically. + +#### Canonical phase definitions (6-phase USDP standard) + +**Invariant:** The default workflow defines exactly 6 phases in fixed order. These are the canonical phase names and ordinals used by all generated documentation. + +| Order | Phase | Purpose | +| ----- | ------------- | ---------------------------------------------- | +| 1 | Inception | Problem framing, scope definition | +| 2 | Elaboration | Design decisions, architecture exploration | +| 3 | Session | Planning and design session work | +| 4 | Construction | Implementation, testing, integration | +| 5 | Validation | Verification, acceptance criteria confirmation | +| 6 | Retrospective | Review, lessons learned, documentation | + +#### Deliverable status canonical values + +**Invariant:** Deliverable status (distinct from pattern FSM status) uses exactly 6 values, enforced by Zod schema at parse time. + +| Value | Meaning | +| ----------- | -------------------- | +| complete | Work is done | +| in-progress | Work is ongoing | +| pending | Work has not started | +| deferred | Work postponed | +| superseded | Replaced by another | +| n/a | Not applicable | + +#### API Types + +| Type | Kind | +| ------------------------- | --------- | +| normalizeStatus | function | +| DELIVERABLE_STATUS_VALUES | const | +| CategoryDefinition | interface | +| SectionBlock | type | + +#### Behavior Specifications + +##### DeliveryProcessFactory + +##### DefineConfig + +##### ConfigBasedWorkflowDefinition + +| Rule | Description | +| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | +| Default workflow is built from an inline constant | **Invariant:** `loadDefaultWorkflow()` returns a `LoadedWorkflow` without
file system access. It cannot fail. The... | +| Custom workflow files still work via --workflow flag | **Invariant:** `loadWorkflowFromPath()` remains available for projects
that need custom workflow definitions. The... | +| FSM validation and Process Guard are not affected | **Invariant:** The FSM transition matrix, protection levels, and Process
Guard rules remain hardcoded in... | +| Workflow as a configurable preset field is deferred | **Invariant:** The inline default workflow constant is the only workflow source until preset integration is... | + +##### ADR005CodecBasedMarkdownRendering + +| Rule | Description | +| ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| Codecs implement a decode-only contract | **Invariant:** Every codec is a pure function that accepts a MasterDataset
and returns a RenderableDocument.... | +| RenderableDocument is a typed intermediate representation | **Invariant:** RenderableDocument contains a title, an ordered array of
SectionBlock elements, and an optional... | +| CompositeCodec assembles documents from child codecs | **Invariant:** CompositeCodec accepts an array of child codecs and
produces a single RenderableDocument by... | +| ADR content comes from both Feature description and Rule prefixes | **Invariant:** ADR structured content (Context, Decision, Consequences)
can appear in two locations within a... | +| The markdown renderer is codec-agnostic | **Invariant:** The renderer accepts any RenderableDocument regardless of
which codec produced it. Rendering... | + +##### ADR001TaxonomyCanonicalValues + +| Rule | Description | +| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | +| Product area canonical values | **Invariant:** The product-area tag uses one of 7 canonical values.
Each value represents a reader-facing... | +| ADR category canonical values | **Invariant:** The adr-category tag uses one of 4 values.
**Rationale:** Unbounded category values prevent... | +| FSM status values and protection levels | **Invariant:** Pattern status uses exactly 4 values with defined
protection levels. These are enforced by Process... | +| Valid FSM transitions | **Invariant:** Only these transitions are valid. All others are
rejected by Process Guard.
**Rationale:**... | +| Tag format types | **Invariant:** Every tag has one of 6 format types that determines
how its value is parsed.
**Rationale:**... | +| Source ownership | **Invariant:** Relationship tags have defined ownership by source type.
Anti-pattern detection enforces these... | +| Quarter format convention | **Invariant:** The quarter tag uses `YYYY-QN` format (e.g., `2026-Q1`).
ISO-year-first sorting works... | +| Canonical phase definitions (6-phase USDP standard) | **Invariant:** The default workflow defines exactly 6 phases in fixed
order. These are the canonical phase names... | +| Deliverable status canonical values | **Invariant:** Deliverable status (distinct from pattern FSM status)
uses exactly 6 values, enforced by Zod... | + +##### ProcessGuardTesting + +| Rule | Description | +| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | +| Completed files require unlock-reason to modify | **Invariant:** A completed spec file cannot be modified unless it carries an @libar-docs-unlock-reason tag.... | +| Status transitions must follow PDR-005 FSM | **Invariant:** Status changes must follow the directed graph: roadmap->active->completed, roadmap<->deferred,... | +| Active specs cannot add new deliverables | **Invariant:** A spec in active status cannot have deliverables added that were not present when it entered active.... | +| Files outside active session scope trigger warnings | **Invariant:** Files modified outside the active session's declared scope produce a session-scope warning.... | +| Explicitly excluded files trigger errors | **Invariant:** Files explicitly excluded from a session cannot be modified, producing a session-excluded error.... | +| Multiple rules validate independently | **Invariant:** Each validation rule evaluates independently — a single file can produce violations from multiple... | diff --git a/docs-live/_claude-md/configuration/configuration-overview.md b/docs-live/_claude-md/configuration/configuration-overview.md index 3c573a63..4a8fd860 100644 --- a/docs-live/_claude-md/configuration/configuration-overview.md +++ b/docs-live/_claude-md/configuration/configuration-overview.md @@ -9,29 +9,30 @@ - Stubs merged at resolution time: Stub directory globs are appended to typescript sources, making stubs transparent to the downstream pipeline - Source override composition: SourceMerger applies per-generator overrides (`replaceFeatures`, `additionalFeatures`, `additionalInput`) to base sources. Exclude is always inherited from base + **Components:** Config (WorkflowLoader, ConfigurationTypes, ConfigResolver, RegexBuilders, ProjectConfigTypes, ProjectConfigSchema, ConfigurationPresets, SourceMerger, DeliveryProcessFactory, DefineConfig, ConfigurationDefaults, ConfigLoader) #### API Types -| Type | Kind | -| ---------------------------- | --------- | -| DeliveryProcessConfig | interface | -| DeliveryProcessInstance | interface | -| RegexBuilders | interface | +| Type | Kind | +| --- | --- | +| DeliveryProcessConfig | interface | +| DeliveryProcessInstance | interface | +| RegexBuilders | interface | | DeliveryProcessProjectConfig | interface | -| SourcesConfig | interface | -| OutputConfig | interface | -| GeneratorSourceOverride | interface | -| ResolvedProjectConfig | interface | -| ResolvedSourcesConfig | interface | +| SourcesConfig | interface | +| OutputConfig | interface | +| GeneratorSourceOverride | interface | +| ResolvedProjectConfig | interface | +| ResolvedSourcesConfig | interface | | CreateDeliveryProcessOptions | interface | -| ConfigDiscoveryResult | interface | -| ConfigLoadError | interface | -| ResolvedConfig | type | -| PresetName | type | -| ConfigLoadResult | type | -| createRegexBuilders | function | -| createDeliveryProcess | function | -| findConfigFile | function | -| loadConfig | function | -| formatConfigError | function | +| ConfigDiscoveryResult | interface | +| ConfigLoadError | interface | +| ResolvedConfig | type | +| PresetName | type | +| ConfigLoadResult | type | +| createRegexBuilders | function | +| createDeliveryProcess | function | +| findConfigFile | function | +| loadConfig | function | +| formatConfigError | function | diff --git a/docs-live/_claude-md/data-api/data-api-overview.md b/docs-live/_claude-md/data-api/data-api-overview.md index 31aaaf67..35e48cff 100644 --- a/docs-live/_claude-md/data-api/data-api-overview.md +++ b/docs-live/_claude-md/data-api/data-api-overview.md @@ -8,14 +8,37 @@ - Session type tailoring: `planning` (~500B, brief + deps), `design` (~1.5KB, spec + stubs + deps), `implement` (deliverables + FSM + tests) - Direct API queries replace doc reading: JSON output is 5-10x smaller than generated docs + +#### Contents + +- [Key Invariants](#key-invariants) +- [Shared Pipeline Factory Responsibilities](#shared-pipeline-factory-responsibilities) +- [8-Step Dataset Build Flow](#8-step-dataset-build-flow) +- [Consumer Architecture and PipelineOptions Differentiation](#consumer-architecture-and-pipelineoptions-differentiation) +- [API Types](#api-types) + + +#### Shared Pipeline Factory Responsibilities + +**Invariant:** `buildMasterDataset()` is the shared factory for Steps 1-8 of the architecture pipeline and returns `Result` without process-level side effects. + + +#### 8-Step Dataset Build Flow + + +#### Consumer Architecture and PipelineOptions Differentiation + + #### API Types -| Type | Kind | -| ----------------------- | ----- | -| MasterDatasetSchema | const | -| StatusGroupsSchema | const | -| StatusCountsSchema | const | -| PhaseGroupSchema | const | -| SourceViewsSchema | const | +| Type | Kind | +| --- | --- | +| PipelineOptions | interface | +| PipelineResult | interface | +| MasterDatasetSchema | const | +| StatusGroupsSchema | const | +| StatusCountsSchema | const | +| PhaseGroupSchema | const | +| SourceViewsSchema | const | | RelationshipEntrySchema | const | -| ArchIndexSchema | const | +| ArchIndexSchema | const | diff --git a/docs-live/_claude-md/generation/generation-overview.md b/docs-live/_claude-md/generation/generation-overview.md index 0ae14ff3..b24bd8f6 100644 --- a/docs-live/_claude-md/generation/generation-overview.md +++ b/docs-live/_claude-md/generation/generation-overview.md @@ -1,12 +1,17 @@ ### Generation Overview -**How does code become docs?** The generation pipeline transforms annotated source code into markdown documents. It follows a four-stage architecture: Scanner → Extractor → Transformer → Codec. Codecs are pure functions — given a MasterDataset, they produce a RenderableDocument without side effects. CompositeCodec composes multiple codecs into a single document. +**How does code become docs?** The generation pipeline transforms annotated source code into markdown documents through a four-stage architecture: Scanner discovers files, Extractor produces `ExtractedPattern` objects, Transformer builds MasterDataset with pre-computed views, and Codecs render to markdown via RenderableDocument IR. Nine specialized codecs handle reference docs, planning, session, reporting, timeline, ADRs, business rules, taxonomy, and composite output — each supporting three detail levels (detailed, standard, summary). The Orchestrator runs generators in registration order, producing both detailed `docs-live/` references and compact `_claude-md/` summaries. #### Key Invariants - Codec purity: Every codec is a pure function (dataset in, document out). No side effects, no filesystem access. Same input always produces same output +- Single read model (ADR-006): All codecs consume MasterDataset. No codec reads raw scanner/extractor output. Anti-patterns: Parallel Pipeline, Lossy Local Type, Re-derived Relationship +- Progressive disclosure: Every document renders at three detail levels (detailed, standard, summary) from the same codec. Summary feeds `_claude-md/` modules; detailed feeds `docs-live/reference/` - Config-driven generation: A single `ReferenceDocConfig` produces a complete document. Content sources compose in fixed order: conventions, diagrams, shapes, behaviors - RenderableDocument IR: Codecs express intent ("this is a table"), the renderer handles syntax ("pipe-delimited markdown"). Switching output format requires only a new renderer +- Composition order: Reference docs compose four content layers in fixed order. Product area docs compose five layers: intro, conventions, diagrams, shapes, business rules +- Shape extraction: TypeScript shapes (`interface`, `type`, `enum`, `function`, `const`) are extracted by declaration-level `@libar-docs-shape` tags. Shapes include source text, JSDoc, type parameters, and property documentation +- Generator registration: Generators self-register via `registerGenerator()`. The orchestrator runs them in registration order. Each generator owns its output files and codec configuration #### API Types diff --git a/docs-live/_claude-md/process/process-overview.md b/docs-live/_claude-md/process/process-overview.md index a32dd1f1..68d95e25 100644 --- a/docs-live/_claude-md/process/process-overview.md +++ b/docs-live/_claude-md/process/process-overview.md @@ -9,6 +9,19 @@ - Two distinct status domains: Pattern FSM status (4 values) vs. deliverable status (6 values). Never cross domains - Session types define capabilities: planning creates specs, design creates stubs, implementation writes code. Each session type has a fixed input/output contract enforced by convention +#### Contents + +- [Key Invariants](#key-invariants) +- [Product area canonical values](#product-area-canonical-values) +- [ADR category canonical values](#adr-category-canonical-values) +- [FSM status values and protection levels](#fsm-status-values-and-protection-levels) +- [Valid FSM transitions](#valid-fsm-transitions) +- [Tag format types](#tag-format-types) +- [Source ownership](#source-ownership) +- [Quarter format convention](#quarter-format-convention) +- [Canonical phase definitions (6-phase USDP standard)](#canonical-phase-definitions-6-phase-usdp-standard) +- [Deliverable status canonical values](#deliverable-status-canonical-values) + #### Product area canonical values **Invariant:** The product-area tag uses one of 7 canonical values. Each value represents a reader-facing documentation section, not a source module. @@ -111,4 +124,4 @@ | superseded | Replaced by another | | n/a | Not applicable | -**Components:** Other (ValidatorReadModelConsolidation, StepDefinitionCompletion, SessionFileCleanup, ProcessAPILayeredExtraction, OrchestratorPipelineFactoryMigration, MvpWorkflowImplementation, LivingRoadmapCLI, EffortVarianceTracking, ConfigBasedWorkflowDefinition, CliBehaviorTesting, ADR006SingleReadModelArchitecture, ADR003SourceFirstPatternArchitecture, ADR002GherkinOnlyTesting, ADR001TaxonomyCanonicalValues, SessionHandoffs, SessionFileLifecycle) +**Components:** Other (ADR006SingleReadModelArchitecture, ADR003SourceFirstPatternArchitecture, ADR002GherkinOnlyTesting, ADR001TaxonomyCanonicalValues, ValidatorReadModelConsolidation, StepDefinitionCompletion, SessionFileCleanup, ProcessAPILayeredExtraction, OrchestratorPipelineFactoryMigration, MvpWorkflowImplementation, LivingRoadmapCLI, EffortVarianceTracking, ConfigBasedWorkflowDefinition, CliBehaviorTesting, SessionHandoffs, SessionFileLifecycle) diff --git a/docs-live/_claude-md/validation/process-guard.md b/docs-live/_claude-md/validation/process-guard.md new file mode 100644 index 00000000..171ff143 --- /dev/null +++ b/docs-live/_claude-md/validation/process-guard.md @@ -0,0 +1,114 @@ +### Process Guard Reference + +#### Pre-commit Setup + +Configure Process Guard as a pre-commit hook using Husky. + +```bash +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx lint-process --staged +``` + +##### package.json Scripts + +```json +{ + "scripts": { + "lint:process": "lint-process --staged", + "lint:process:ci": "lint-process --all --strict" + } +} +``` + +#### Programmatic API + +Use Process Guard programmatically for custom validation workflows. + +```typescript +import { + deriveProcessState, + detectStagedChanges, + validateChanges, + hasErrors, + summarizeResult, +} from '@libar-dev/delivery-process/lint'; + +// 1. Derive state from annotations +const state = (await deriveProcessState({ baseDir: '.' })).value; + +// 2. Detect changes +const changes = detectStagedChanges('.').value; + +// 3. Validate +const { result } = validateChanges({ + state, + changes, + options: { strict: false, ignoreSession: false }, +}); + +// 4. Handle results +if (hasErrors(result)) { + console.log(summarizeResult(result)); + process.exit(1); +} +``` + +##### API Functions + +| Category | Function | Description | +| -------- | ------------------------ | --------------------------------- | +| State | deriveProcessState(cfg) | Build state from file annotations | +| Changes | detectStagedChanges(dir) | Parse staged git diff | +| Changes | detectBranchChanges(dir) | Parse all changes vs main | +| Validate | validateChanges(input) | Run all validation rules | +| Results | hasErrors(result) | Check for blocking errors | +| Results | summarizeResult(result) | Human-readable summary | + +#### Architecture + +Process Guard uses the Decider pattern: pure functions with no I/O. + +#### ProcessGuardDecider - Pure Validation Logic + +#### completed-protection + +**Invariant:** Completed specs are immutable without an explicit unlock reason. The unlock reason must be at least 10 characters and cannot be a placeholder. + +| Situation | Solution | Example | +| -------------------------- | ---------------------------------- | --------------------------------------------------- | +| Fix typo in completed spec | Add unlock reason tag | `@libar-docs-unlock-reason:Fix-typo-in-FSM-diagram` | +| Spec needs rework | Create new spec instead | New feature file with `roadmap` status | +| Legacy import | Multiple transitions in one commit | Set `roadmap` then `completed` | + +#### invalid-status-transition + +**Invariant:** Status transitions must follow the PDR-005 FSM path. The only valid paths are: roadmap to active, roadmap to deferred, active to completed, active to roadmap, deferred to roadmap. + +| Attempted | Why Invalid | Valid Path | +| --------------------- | ---------------------------- | ------------------------------------------ | +| roadmap to completed | Must go through active | roadmap to active to completed | +| deferred to active | Must return to roadmap first | deferred to roadmap to active | +| deferred to completed | Cannot skip two states | deferred to roadmap to active to completed | + +#### scope-creep + +**Invariant:** Active specs cannot add new deliverables. Scope is locked when status transitions to `active`. + +| Situation | Solution | Example | +| ------------------------------------- | ----------------------- | -------------------------------------------------------------- | +| Need new deliverable | Revert to roadmap first | Change status to roadmap, add deliverable, then back to active | +| Discovered work during implementation | Create new spec | New feature file for the discovered work | + +#### session-scope + +**Invariant:** Files outside the active session scope trigger warnings to prevent accidental cross-session modifications. + +#### session-excluded + +**Invariant:** Files explicitly excluded from a session cannot be modified in that session. This is a hard error, not a warning. + +#### deliverable-removed + +**Invariant:** Removing a deliverable from an active spec triggers a warning to ensure the removal is intentional and documented. diff --git a/docs-live/_claude-md/validation/validation-overview.md b/docs-live/_claude-md/validation/validation-overview.md index b927aa87..b24b3404 100644 --- a/docs-live/_claude-md/validation/validation-overview.md +++ b/docs-live/_claude-md/validation/validation-overview.md @@ -9,29 +9,30 @@ - Decider pattern: All validation is (state, changes, options) → result. State is derived from annotations, not maintained separately - Dual-source ownership: Anti-pattern detection enforces tag boundaries — `uses` on TypeScript (runtime deps), `depends-on`/`quarter`/`team` on Gherkin (planning metadata). Violations are flagged before they cause documentation drift + **Components:** Lint (LintRules, LintEngine, ProcessGuardDecider), Validation (DoDValidator, AntiPatternDetector, FSMValidator, FSMTransitions, FSMStates) #### API Types -| Type | Kind | -| ---------------------------------- | --------- | -| AntiPatternDetectionOptions | interface | -| LintRule | interface | -| LintContext | interface | -| ProtectionLevel | type | -| isDeliverableComplete | function | -| hasAcceptanceCriteria | function | -| extractAcceptanceCriteriaScenarios | function | -| validateDoDForPhase | function | -| validateDoD | function | -| formatDoDSummary | function | -| detectAntiPatterns | function | -| detectProcessInCode | function | -| detectMagicComments | function | -| detectScenarioBloat | function | -| detectMegaFeature | function | -| formatAntiPatternReport | function | -| toValidationIssues | function | -| filterRulesBySeverity | function | -| isValidTransition | function | -| getValidTransitionsFrom | function | +| Type | Kind | +| --- | --- | +| AntiPatternDetectionOptions | interface | +| LintRule | interface | +| LintContext | interface | +| ProtectionLevel | type | +| isDeliverableComplete | function | +| hasAcceptanceCriteria | function | +| extractAcceptanceCriteriaScenarios | function | +| validateDoDForPhase | function | +| validateDoD | function | +| formatDoDSummary | function | +| detectAntiPatterns | function | +| detectProcessInCode | function | +| detectMagicComments | function | +| detectScenarioBloat | function | +| detectMegaFeature | function | +| formatAntiPatternReport | function | +| toValidationIssues | function | +| filterRulesBySeverity | function | +| isValidTransition | function | +| getValidTransitionsFrom | function | diff --git a/docs-live/_claude-md/workflow/session-workflow-guide.md b/docs-live/_claude-md/workflow/session-workflow-guide.md new file mode 100644 index 00000000..7eac2d4b --- /dev/null +++ b/docs-live/_claude-md/workflow/session-workflow-guide.md @@ -0,0 +1,141 @@ +### Session Workflow Guide + +#### Session Decision Tree + +Use this flowchart to determine which session type to run. + +#### Session Type Contracts + +| Session | Input | Output | FSM Change | +| ----------------- | ------------------- | --------------------------- | ------------------------------------ | +| Planning | Pattern brief | Roadmap spec (`.feature`) | Creates `roadmap` | +| Design | Complex requirement | Decision specs + code stubs | None | +| Implementation | Roadmap spec | Code + tests | `roadmap` -> `active` -> `completed` | +| Planning + Design | Pattern brief | Spec + stubs | Creates `roadmap` | + +#### Implementation Execution Order + +Implementation sessions MUST follow this strict 5-step sequence. Skipping steps causes Process Guard rejection at commit time. + +1. **Transition to `active` FIRST** (before any code changes) +2. **Create executable spec stubs** (if `@libar-docs-executable-specs` present) +3. **For each deliverable:** implement, test, update status to `complete` +4. **Transition to `completed`** (only when ALL deliverables done) +5. **Regenerate docs:** `pnpm docs:all` + +##### Implementation Do NOT + +| Do NOT | Why | +| ----------------------------------- | --------------------------------------- | +| Add new deliverables to active spec | Scope-locked state prevents scope creep | +| Mark completed with incomplete work | Hard-locked state cannot be undone | +| Skip FSM transitions | Process Guard will reject | +| Edit generated docs directly | Regenerate from source | + +#### Planning Session + +**Goal:** Create a roadmap spec. Do not write implementation code. + +##### Context Gathering + +```bash +pnpm process:query -- overview # Project health +pnpm process:query -- list --status roadmap --names-only # Available patterns +``` + +##### Planning Checklist + +- [ ] **Extract metadata** from pattern brief: phase, dependencies, status +- [ ] **Create spec file** at `{specs-directory}/{product-area}/{pattern}.feature` +- [ ] **Structure the feature** with Problem/Solution, tags, deliverables table +- [ ] **Convert constraints to Rule: blocks** with Invariant/Rationale +- [ ] **Add scenarios** per Rule: 1 happy-path + 1 validation minimum +- [ ] **Set executable specs location** via `@libar-docs-executable-specs` tag + +##### Planning Do NOT + +- Create `.ts` implementation files +- Transition to `active` +- Ask "Ready to implement?" + +#### Design Session + +**Goal:** Make architectural decisions. Create code stubs with interfaces. Do not implement. + +##### Context Gathering + +```bash +pnpm process:query -- context --session design # Full context bundle +pnpm process:query -- dep-tree # Dependency chain +pnpm process:query -- stubs # Existing design stubs +``` + +##### When to Use Design Sessions + +| Use Design Session | Skip Design Session | +| -------------------------- | ------------------- | +| Multiple valid approaches | Single obvious path | +| New patterns/capabilities | Bug fix | +| Cross-context coordination | Clear requirements | + +##### Design Checklist + +- [ ] **Record decisions** as PDR `.feature` files in `delivery-process/decisions/` +- [ ] **Document options** with at least 2-3 approaches and pros/cons +- [ ] **Get approval** from user on recommended approach +- [ ] **Create code stubs** in `delivery-process/stubs/{pattern-name}/` +- [ ] **Verify stub identifier spelling** before committing +- [ ] **List canonical helpers** in `@libar-docs-uses` tags + +##### Design Do NOT + +- Create markdown design documents (use decision specs instead) +- Create implementation plans +- Transition spec to `active` +- Write full implementations (stubs only) + +#### Planning + Design Session + +**Goal:** Create spec AND code stubs in one session. For immediate implementation handoff. + +##### When to Use + +| Use Planning + Design | Use Planning Only | +| ----------------------------------- | ---------------------------- | +| Need stubs for implementation | Only enhancing spec | +| Preparing for immediate handoff | Still exploring requirements | +| Want complete two-tier architecture | Don't need Tier 2 yet | + +#### Handoff Documentation + +For multi-session work, capture state at session boundaries using the Process Data API. + +```bash +pnpm process:query -- handoff --pattern +pnpm process:query -- handoff --pattern --git # include recent commits +``` + +#### Quick Reference: FSM Protection + +| State | Protection | Can Add Deliverables | Needs Unlock | +| ----------- | ------------ | -------------------- | ------------ | +| `roadmap` | None | Yes | No | +| `active` | Scope-locked | No | No | +| `completed` | Hard-locked | No | Yes | +| `deferred` | None | Yes | No | + +#### Behavior Specifications + +##### SessionGuidesModuleSource + +| Rule | Description | +| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | +| SESSION-GUIDES.md is the authoritative public human reference | **Invariant:** `docs/SESSION-GUIDES.md` exists and is not deleted, shortened, or
replaced with a redirect. Its... | +| CLAUDE.md session workflow content is derived, not hand-authored | **Invariant:** After Phase 39 generation deliverables complete, the "Session
Workflows" section in CLAUDE.md... | +| Session type determines artifacts and FSM changes | **Invariant:** Four session types exist, each with defined input, output, and
FSM impact. Mixing outputs across... | +| Planning sessions produce roadmap specs only | **Invariant:** A planning session creates a roadmap spec with metadata, deliverables
table, Rule: blocks with... | +| Design sessions produce decisions and stubs only | **Invariant:** A design session makes architectural decisions and creates code stubs
with interfaces. It must not... | +| Implementation sessions follow FSM-enforced execution order | **Invariant:** Implementation sessions must follow a strict 5-step execution order.
Transition to active must... | +| FSM errors have documented fixes | **Invariant:** Every Process Guard error code has a defined cause and fix. The
error codes, causes, and fixes... | +| Handoff captures session-end state for continuity | **Invariant:** Multi-session work requires handoff documentation generated from
the Process Data API. Handoff... | +| ClaudeModuleGeneration is the generation mechanism | **Invariant:** Phase 39 depends on ClaudeModuleGeneration (Phase 25). Adding
`@libar-docs-claude-module` and... | diff --git a/docs-generated/business-rules/annotation.md b/docs-live/business-rules/annotation.md similarity index 93% rename from docs-generated/business-rules/annotation.md rename to docs-live/business-rules/annotation.md index d9d0d919..54a75a2d 100644 --- a/docs-generated/business-rules/annotation.md +++ b/docs-live/business-rules/annotation.md @@ -12,7 +12,7 @@ ### Ast Parser Exports -*The AST Parser extracts @libar-docs-* directives from TypeScript source files* +_The AST Parser extracts @libar-docs-_ directives from TypeScript source files\* --- @@ -23,6 +23,7 @@ > **Rationale:** Export type classification drives how codecs render API documentation — misclassifying a function as a const (or vice versa) produces incorrect signatures and misleading docs. **Verified by:** + - Parse function export with directive - Parse type export with directive - Parse interface export with directive @@ -39,11 +40,11 @@ - Parse multiple exports in single statement - Parse multiple directives in same file -*ast-parser-exports.feature* +_ast-parser-exports.feature_ ### Ast Parser Metadata -*The AST Parser extracts @libar-docs-* directives from TypeScript source files* +_The AST Parser extracts @libar-docs-_ directives from TypeScript source files\* --- @@ -54,6 +55,7 @@ > **Rationale:** Downstream codecs render each metadata field independently — incorrect parsing causes examples to leak into descriptions or signatures to be lost in generated documentation. **Verified by:** + - Extract examples from directive - Extract multi-line description - Track line numbers correctly @@ -69,6 +71,7 @@ > **Rationale:** Tags control taxonomy classification and pattern routing — extracting them from prose or examples would create phantom patterns and corrupt the registry. **Verified by:** + - Extract multiple tags from directive section - Extract tag with description on same line - NOT extract tags mentioned in description @@ -83,16 +86,17 @@ > **Rationale:** Generated pattern documentation includes a When to Use section — failing to recognize any supported format means valid guidance silently disappears from output. **Verified by:** + - Extract When to Use heading format with bullet points - Extract When to use inline format - Extract asterisk bullets in When to Use section - Not set whenToUse when section is missing -*ast-parser-metadata.feature* +_ast-parser-metadata.feature_ ### Ast Parser Relationships Edges -*The AST Parser extracts @libar-docs-* directives from TypeScript source files* +_The AST Parser extracts @libar-docs-_ directives from TypeScript source files\* --- @@ -103,6 +107,7 @@ > **Rationale:** Relationship data drives dependency diagrams and impact analysis — extracting from prose would produce false edges from incidental mentions. **Verified by:** + - Extract @libar-docs-uses with single value - Extract @libar-docs-uses with comma-separated values - Extract @libar-docs-used-by with single value @@ -120,7 +125,8 @@ > **Rationale:** The scanner processes hundreds of files in bulk — a single malformed file must not abort the entire pipeline or produce an undiagnosable crash. **Verified by:** -- Skip comments without @libar-docs-* tags + +- Skip comments without @libar-docs-\* tags - Skip invalid directive with incomplete tag - Handle malformed TypeScript gracefully - Handle empty file gracefully @@ -129,32 +135,34 @@ - Skip inline comments (non-block) - Handle unicode characters in descriptions -*ast-parser-relationships-edges.feature* +_ast-parser-relationships-edges.feature_ ### Context Inference -*Patterns in standard directories (src/validation/, src/scanner/) should* +_Patterns in standard directories (src/validation/, src/scanner/) should_ --- -#### matchPattern supports recursive wildcard ** +#### matchPattern supports recursive wildcard \*\* > **Invariant:** The `**` wildcard matches files at any nesting depth below the specified directory prefix. > > **Rationale:** Directory hierarchies vary in depth; recursive matching ensures all nested files inherit context. **Verified by:** + - Recursive wildcard matches nested paths --- -#### matchPattern supports single-level wildcard /* +#### matchPattern supports single-level wildcard /\* > **Invariant:** The `/*` wildcard matches only direct children of the specified directory, not deeper nested files. > > **Rationale:** Some contexts apply only to a specific directory level, not its entire subtree. **Verified by:** + - Single-level wildcard matches direct children only --- @@ -166,6 +174,7 @@ > **Rationale:** Without prefix matching, users would need separate wildcard patterns for each nesting depth, making rule configuration verbose and error-prone. **Verified by:** + - Prefix matching behavior --- @@ -177,6 +186,7 @@ > **Rationale:** Unmatched files must not receive a spurious context assignment; absence of context is a valid state. **Verified by:** + - Empty rules array returns undefined - File path does not match any rule @@ -189,6 +199,7 @@ > **Rationale:** Deterministic ordering prevents ambiguous context assignment when rules overlap. **Verified by:** + - Single matching rule infers context - First matching rule wins when multiple could match @@ -201,6 +212,7 @@ > **Rationale:** Explicit annotations represent intentional developer decisions that must not be silently overwritten by automation. **Verified by:** + - Explicit context takes precedence over inference --- @@ -212,6 +224,7 @@ > **Rationale:** Coupling context inference to archLayer would prevent context-based queries from finding patterns that lack explicit layer annotations. **Verified by:** + - Pattern without archLayer is still added to byContext if context is inferred --- @@ -223,13 +236,14 @@ > **Rationale:** Convention-based mapping eliminates the need for explicit context annotations on every file in standard directories. **Verified by:** + - Default directory mappings -*context-inference.feature* +_context-inference.feature_ ### Declaration Level Shape Tagging -*Tests the discoverTaggedShapes function that scans TypeScript source* +_Tests the discoverTaggedShapes function that scans TypeScript source_ --- @@ -240,6 +254,7 @@ > **Rationale:** Extracting shapes without an explicit opt-in tag would surface internal implementation details in generated API documentation, violating information hiding. **Verified by:** + - Tagged declaration is extracted as shape - Untagged exported declaration is not extracted - Group name is captured from tag value @@ -260,6 +275,7 @@ > **Rationale:** Introducing a second parser would create divergent AST behavior — reusing the established parser ensures consistent JSDoc handling and avoids subtle extraction differences. **Verified by:** + - All five declaration kinds are discoverable - JSDoc with gap larger than MAX_JSDOC_LINE_DISTANCE is not matched - Tag as last line before closing JSDoc delimiter @@ -270,11 +286,11 @@ - JSDoc gap enforcement - Tag with other JSDoc content -*declaration-level-shape-tagging.feature* +_declaration-level-shape-tagging.feature_ ### Depends On Tag -*Tests extraction of @libar-docs-depends-on and @libar-docs-enables* +_Tests extraction of @libar-docs-depends-on and @libar-docs-enables_ --- @@ -285,6 +301,7 @@ > **Rationale:** Without registry definitions, the data-driven AST parser cannot discover or extract these planning dependency tags from source files. **Verified by:** + - Depends-on tag exists in registry - Enables tag exists in registry @@ -297,6 +314,7 @@ > **Rationale:** Missing dependency extraction causes the dependency tree and blocking-pattern queries to return incomplete results. **Verified by:** + - Depends-on extracted from feature file - Multiple depends-on values extracted as CSV @@ -309,13 +327,15 @@ > **Rationale:** Depends-on represents planning dependencies owned by Gherkin specs, not runtime dependencies owned by TypeScript. **Verified by:** + - Depends-on in TypeScript is detected by lint rule - Depends-on in TypeScript is detected by lint rule - The depends-on tag is for planning dependencies and belongs in feature - files + The depends-on tag is for planning dependencies and belongs in feature + files + - not TypeScript code. TypeScript files should use "uses" for - runtime dependencies. + runtime dependencies. --- @@ -326,6 +346,7 @@ > **Rationale:** Missing enables extraction breaks forward-looking dependency queries, hiding which patterns are unblocked when a prerequisite completes. **Verified by:** + - Enables extracted from feature file - Multiple enables values extracted as CSV @@ -338,30 +359,32 @@ > **Rationale:** Omitting planning dependencies from the index causes blocking-pattern and critical-path queries to return incomplete results. **Verified by:** + - DependsOn relationships stored in relationship index - Enables relationships stored explicitly - Enables relationships stored explicitly - The relationship index stores dependsOn and enables relationships - directly from pattern metadata. These are explicit declarations. + The relationship index stores dependsOn and enables relationships + directly from pattern metadata. These are explicit declarations. -*depends-on-tag.feature* +_depends-on-tag.feature_ ### Directive Detection -*- Full AST parsing of every TypeScript file is expensive and slow* +_- Full AST parsing of every TypeScript file is expensive and slow_ --- -#### hasDocDirectives detects @libar-docs-* section directives +#### hasDocDirectives detects @libar-docs-\* section directives > **Invariant:** hasDocDirectives must return true if and only if the source contains at least one @libar-docs-{suffix} directive (case-sensitive, @ required, suffix required). > > **Rationale:** This is the first-pass filter in the scanner pipeline; false negatives cause patterns to be silently missed, while false positives only waste AST parsing time. **Verified by:** + - Detect @libar-docs-core directive in JSDoc block -- Detect various @libar-docs-* directives +- Detect various @libar-docs-\* directives - Detect directive anywhere in file content - Detect multiple directives on same line - Detect directive in inline comment @@ -373,11 +396,12 @@ #### hasFileOptIn detects file-level @libar-docs marker -> **Invariant:** hasFileOptIn must return true if and only if the source contains a bare @libar-docs tag (not followed by a hyphen) inside a JSDoc block comment; line comments and @libar-docs-* suffixed tags must not match. +> **Invariant:** hasFileOptIn must return true if and only if the source contains a bare @libar-docs tag (not followed by a hyphen) inside a JSDoc block comment; line comments and @libar-docs-\* suffixed tags must not match. > > **Rationale:** File-level opt-in is the gate for including a file in the scanner pipeline; confusing @libar-docs-core (a section tag) with @libar-docs (file opt-in) would either miss files or over-include them. **Verified by:** + - Detect @libar-docs in JSDoc block comment - Detect @libar-docs with description on same line - Detect @libar-docs in multi-line JSDoc @@ -387,13 +411,13 @@ - Return false for multiple section tags without opt-in - Return false for empty content in hasFileOptIn - Return false for @libar-docs in line comment -- Not confuse @libar-docs-* with @libar-docs opt-in +- Not confuse @libar-docs-\* with @libar-docs opt-in -*directive-detection.feature* +_directive-detection.feature_ ### Doc String Media Type -*DocString language hints (mediaType) should be preserved through the parsing* +_DocString language hints (mediaType) should be preserved through the parsing_ --- @@ -404,6 +428,7 @@ > **Rationale:** Losing the mediaType causes downstream renderers to apply incorrect escaping or default language hints, corrupting code block output. **Verified by:** + - Parse DocString with typescript mediaType - Parse DocString with json mediaType - Parse DocString with jsdoc mediaType @@ -418,6 +443,7 @@ > **Rationale:** Using the wrong language hint causes syntax highlighters to misrender code blocks, and losing mediaType entirely can trigger incorrect escaping (e.g., asterisks in JSDoc). **Verified by:** + - TypeScript mediaType renders as typescript code block - JSDoc mediaType prevents asterisk escaping - Missing mediaType falls back to default language @@ -431,14 +457,15 @@ > **Rationale:** Legacy callers pass raw strings while newer code passes structured objects — the renderer must handle both without breaking existing usage. **Verified by:** + - String docString renders correctly (legacy format) - Object docString with mediaType takes precedence -*docstring-mediatype.feature* +_docstring-mediatype.feature_ ### Dual Source Extractor -*- Pattern data split across code stubs and feature files* +_- Pattern data split across code stubs and feature files_ --- @@ -449,6 +476,7 @@ > **Rationale:** Pattern name and phase are the minimum identifiers for placing a pattern in the roadmap — without both, the pattern cannot be tracked. **Verified by:** + - Complete process metadata extraction - Minimal required tags extraction - Missing pattern tag returns null @@ -463,6 +491,7 @@ > **Rationale:** The Background table is the single source of truth for deliverable tracking — extracting from other locations would create ambiguity. **Verified by:** + - Standard deliverables table extraction - Extended deliverables with Finding and Release - Feature without background returns empty @@ -477,6 +506,7 @@ > **Rationale:** Dual-source combination ensures documentation reflects both implementation intent (code) and specification (Gherkin) — mismatches signal inconsistency. **Verified by:** + - Matching code and feature are combined - Code-only pattern has no matching feature - Feature-only pattern has no matching code @@ -492,6 +522,7 @@ > **Rationale:** Inconsistencies between code stubs and feature files indicate drift — errors catch conflicts while warnings surface missing counterparts that may be intentional. **Verified by:** + - Clean results have no errors - Cross-validation errors are reported - Orphaned roadmap code stubs produce warnings @@ -506,15 +537,16 @@ > **Rationale:** Include tags control which patterns appear in scoped diagrams — incorrect parsing drops patterns from diagrams or includes unrelated ones. **Verified by:** + - Single include tag is extracted - CSV include tag produces multiple values - Feature without include tag has no include field -*dual-source-extraction.feature* +_dual-source-extraction.feature_ ### Extends Tag -*Tests for the @libar-docs-extends tag which establishes generalization* +_Tests for the @libar-docs-extends tag which establishes generalization_ --- @@ -525,6 +557,7 @@ > **Rationale:** Without a registry definition, the data-driven AST parser cannot discover or extract the extends tag from source files. **Verified by:** + - Extends tag exists in registry --- @@ -536,12 +569,13 @@ > **Rationale:** Single inheritance avoids diamond-problem ambiguity in pattern generalization hierarchies. **Verified by:** + - Parse extends from feature file - Extends preserved through extraction pipeline - Extends preserved through extraction pipeline - Extends uses single-value format because pattern inheritance should be - single-inheritance to avoid diamond problems. + Extends uses single-value format because pattern inheritance should be + single-inheritance to avoid diamond problems. --- @@ -552,6 +586,7 @@ > **Rationale:** Without the reverse index, base patterns cannot discover their extensions, breaking generalization hierarchy navigation in generated docs. **Verified by:** + - Extended pattern knows its extensions --- @@ -563,14 +598,15 @@ > **Rationale:** Circular extends relationships create infinite resolution loops and undefined behavior. **Verified by:** + - Direct circular inheritance detected - Transitive circular inheritance detected -*extends-tag.feature* +_extends-tag.feature_ ### Extraction Pipeline Enhancements -*Validates extraction pipeline capabilities for ReferenceDocShowcase:* +_Validates extraction pipeline capabilities for ReferenceDocShowcase:_ --- @@ -581,6 +617,7 @@ > **Rationale:** Reference documentation renders signatures verbatim — placeholder values instead of real types make the API docs unusable for consumers. **Verified by:** + - Simple function signature is extracted with full types - Async function keeps async prefix in signature - Multi-parameter function has all types in signature @@ -599,6 +636,7 @@ > **Rationale:** Truncated property descriptions lose important behavioral details (defaults, units, constraints) that consumers rely on when integrating with the API. **Verified by:** + - Multi-line property JSDoc is fully preserved - Single-line property JSDoc still works - Multi-line property JSDoc preserved @@ -613,6 +651,7 @@ > **Rationale:** Function reference docs require parameter, return, and exception documentation — missing extraction means consumers must read source code instead of generated docs. **Verified by:** + - Param tags are extracted from function JSDoc - Returns tag is extracted from function JSDoc - Throws tags are extracted from function JSDoc @@ -631,6 +670,7 @@ > **Rationale:** Requiring explicit names for every export creates maintenance burden and stale annotations — wildcard discovery keeps shape docs in sync as exports are added or removed. **Verified by:** + - Wildcard extracts all exported declarations - Mixed wildcard and names produces warning - Same-name type and const exports produce one shape @@ -638,11 +678,11 @@ - Non-exported declarations excluded - Mixed wildcard and names rejected -*extraction-pipeline-enhancements.feature* +_extraction-pipeline-enhancements.feature_ ### File Discovery -*The file discovery system uses glob patterns to find TypeScript files* +_The file discovery system uses glob patterns to find TypeScript files_ --- @@ -653,6 +693,7 @@ > **Rationale:** Downstream pipeline stages (AST parser, extractor) require absolute paths to read file contents; relative paths would break when baseDir differs from cwd. **Verified by:** + - Find TypeScript files matching glob patterns - Return absolute paths - Support multiple glob patterns @@ -666,6 +707,7 @@ > **Rationale:** Scanning generated output (dist), third-party code (node_modules), or test files would produce false positives in the pattern registry and waste processing time. **Verified by:** + - Exclude node_modules by default - Exclude dist directory by default - Exclude test files by default @@ -680,15 +722,16 @@ > **Rationale:** Replacing defaults with custom patterns would silently re-include node_modules and dist, causing false positives in the pattern registry. **Verified by:** + - Respect custom exclude patterns - Return empty array when no files match - Handle nested directory structures -*file-discovery.feature* +_file-discovery.feature_ ### Gherkin Ast Parser -*The Gherkin AST parser extracts feature metadata, scenarios, and steps* +_The Gherkin AST parser extracts feature metadata, scenarios, and steps_ --- @@ -699,6 +742,7 @@ > **Rationale:** Downstream generators (timeline, business rules) depend on complete AST extraction; missing fields cause silent gaps in generated documentation. **Verified by:** + - Parse valid feature file with pattern metadata - Parse multiple scenarios - Handle feature without tags @@ -712,14 +756,15 @@ > **Rationale:** The scanner processes many feature files in batch; structured errors allow graceful degradation and per-file error reporting rather than aborting the entire scan. **Verified by:** + - Return error for malformed Gherkin - Return error for file without feature -*gherkin-parser.feature* +_gherkin-parser.feature_ ### Implements Tag Processing -*Tests for the @libar-docs-implements tag which links implementation files* +_Tests for the @libar-docs-implements tag which links implementation files_ --- @@ -730,12 +775,14 @@ > **Rationale:** Without a registry definition, the data-driven AST parser cannot discover or extract the implements tag from source files. **Verified by:** + - Implements tag exists in registry - Implements tag exists in registry - The tag registry defines `implements` with CSV format + The tag registry defines `implements` with CSV format + - enabling the - data-driven AST parser to automatically extract it. + data-driven AST parser to automatically extract it. --- @@ -746,6 +793,7 @@ > **Rationale:** Lost implements values sever the link between implementation files and their roadmap specs, breaking traceability. **Verified by:** + - Parse implements with single pattern - Implements preserved through extraction pipeline @@ -758,6 +806,7 @@ > **Rationale:** Unsplit or untrimmed CSV values produce invalid pattern references that fail relationship index lookups. **Verified by:** + - Parse implements with multiple patterns - CSV values are trimmed @@ -770,6 +819,7 @@ > **Rationale:** Without the reverse index, roadmap specs cannot discover their implementation files, breaking traceability and DoD validation. **Verified by:** + - Single implementation creates reverse lookup - Multiple implementations aggregate @@ -782,14 +832,15 @@ > **Rationale:** Schema rejection of valid implements/implementedBy values causes runtime parse failures that silently drop traceability links. **Verified by:** + - DocDirective schema accepts implements - RelationshipEntry schema accepts implementedBy -*implements-tag.feature* +_implements-tag.feature_ ### Layer Inference -*- Manual layer annotation in every feature file is tedious and error-prone* +_- Manual layer annotation in every feature file is tedious and error-prone_ --- @@ -800,6 +851,7 @@ > **Rationale:** Timeline features track phased delivery progress and must be grouped separately for roadmap generation and phase filtering. **Verified by:** + - Detect timeline features from /timeline/ path - Detect timeline features regardless of parent directories - Detect timeline features in delivery-process package @@ -813,6 +865,7 @@ > **Rationale:** Domain features define core business rules and must be distinguished from infrastructure tests for accurate coverage reporting. **Verified by:** + - Detect decider features as domain - Detect orders features as domain - Detect inventory features as domain @@ -826,6 +879,7 @@ > **Rationale:** Integration tests nested under domain directories (e.g., /integration/orders/) would be misclassified as domain without explicit priority, skewing layer coverage metrics. **Verified by:** + - Detect integration-features directory as integration - Detect /integration/ directory as integration - Integration takes priority over orders subdirectory @@ -840,6 +894,7 @@ > **Rationale:** E2E tests require separate execution infrastructure and longer timeouts; misclassification would mix them into faster test suites. **Verified by:** + - Detect e2e features from /e2e/ path - Detect e2e features in frontend app - Detect e2e-journeys as e2e @@ -853,6 +908,7 @@ > **Rationale:** Tool-specific features test internal pipeline stages and must be isolated from business domain and integration layers in documentation grouping. **Verified by:** + - Detect scanner features as component - Detect lint features as component @@ -865,6 +921,7 @@ > **Rationale:** Silently dropping unclassified features would create invisible gaps in test coverage; the unknown fallback ensures every feature is accounted for. **Verified by:** + - Return unknown for unclassified paths - Return unknown for root-level features - Return unknown for generic test paths @@ -878,6 +935,7 @@ > **Rationale:** The consumer monorepo runs on multiple platforms; platform-dependent classification would produce inconsistent documentation across developer machines and CI. **Verified by:** + - Handle Windows-style paths with backslashes - Be case-insensitive - Handle mixed path separators @@ -895,15 +953,16 @@ > **Rationale:** Consumers iterate over FEATURE_LAYERS for exhaustive layer handling; a mutable or incomplete array would cause missed layers at runtime. **Verified by:** + - FEATURE_LAYERS contains all valid layer values - FEATURE_LAYERS has exactly 6 layers - FEATURE_LAYERS is a readonly array -*layer-inference.feature* +_layer-inference.feature_ ### Pattern Tag Extraction -*- Gherkin tags are flat strings needing semantic interpretation* +_- Gherkin tags are flat strings needing semantic interpretation_ --- @@ -914,6 +973,7 @@ > **Rationale:** Incorrect type coercion (e.g., phase as string instead of number) causes downstream pipeline failures in filtering and sorting. **Verified by:** + - Extract pattern name tag - Extract phase number tag - Extract status roadmap tag @@ -931,6 +991,7 @@ > **Rationale:** Missing a dependency value silently breaks the dependency graph, causing incorrect build ordering and orphaned pattern references. **Verified by:** + - Extract single dependency - Extract comma-separated dependencies - Extract comma-separated enables @@ -944,6 +1005,7 @@ > **Rationale:** Including test-control tags (acceptance-criteria, happy-path) as categories pollutes the pattern taxonomy with non-semantic values. **Verified by:** + - Extract category tags (no colon) - libar-docs opt-in marker is NOT a category @@ -956,6 +1018,7 @@ > **Rationale:** Real feature files combine many tag types; extraction must handle all types simultaneously without interference between parsers. **Verified by:** + - Extract all metadata from complex tag list --- @@ -967,6 +1030,7 @@ > **Rationale:** Throwing on malformed tags would abort extraction for the entire file, losing valid metadata from well-formed tags. **Verified by:** + - Empty tag list returns empty metadata - Invalid phase number is ignored @@ -979,6 +1043,7 @@ > **Rationale:** Untrimmed whitespace creates distinct values for the same convention, causing false negatives in convention-based filtering and validation. **Verified by:** + - Extract single convention tag - Extract CSV convention tags - Convention tag trims whitespace in CSV values @@ -992,6 +1057,7 @@ > **Rationale:** Hard-coded if/else branches for each tag type cannot scale; registry-driven extraction ensures new tags are supported by configuration, not code changes. **Verified by:** + - Registry-driven enum tag without prior if/else branch - Registry-driven enum rejects invalid value - Registry-driven CSV tag accumulates values @@ -1001,11 +1067,11 @@ - Repeatable value tag accumulates multiple occurrences - CSV with values constraint rejects invalid values -*pattern-tag-extraction.feature* +_pattern-tag-extraction.feature_ ### Scanner Core -*- Need to scan entire codebases for documentation directives efficiently* +_- Need to scan entire codebases for documentation directives efficiently_ --- @@ -1016,6 +1082,7 @@ > **Rationale:** Downstream generators depend on complete directive data; partial extraction causes silent documentation gaps across the monorepo. **Verified by:** + - Scan files and extract directives - Skip files without directives - Extract complete directive information @@ -1029,6 +1096,7 @@ > **Rationale:** In a monorepo with hundreds of files, a single syntax error must not block the entire documentation pipeline. **Verified by:** + - Collect errors for files that fail to parse - Always return Ok result even with broken files @@ -1041,6 +1109,7 @@ > **Rationale:** Without exclusion filtering, internal directories and generated files would pollute the pattern registry with false positives and slow down scanning. **Verified by:** + - Return empty results when no patterns match - Respect exclusion patterns - Handle multiple files with multiple directives each @@ -1049,21 +1118,22 @@ #### File opt-in requirement gates scanning -> **Invariant:** Only files containing a standalone @libar-docs marker (not @libar-docs-*) are eligible for directive extraction. +> **Invariant:** Only files containing a standalone @libar-docs marker (not @libar-docs-\*) are eligible for directive extraction. > > **Rationale:** Without opt-in gating, every TypeScript file in the monorepo would be parsed, wasting processing time on files that have no documentation directives. **Verified by:** + - Handle files with quick directive check optimization - Skip files without @libar-docs file-level opt-in -- Not confuse @libar-docs-* with @libar-docs opt-in +- Not confuse @libar-docs-\* with @libar-docs opt-in - Detect @libar-docs opt-in combined with section tags -*scanner-core.feature* +_scanner-core.feature_ ### Shape Extraction Rendering -*Validates the shape extraction system that extracts TypeScript type* +_Validates the shape extraction system that extracts TypeScript type_ --- @@ -1074,6 +1144,7 @@ > **Rationale:** Documentation consumers rely on tag-specified ordering for consistent, predictable layout regardless of how source files are organized. **Verified by:** + - Shapes appear in tag order not source order - Mixed shape types in specified order @@ -1086,6 +1157,7 @@ > **Rationale:** Fenced code blocks provide syntax highlighting and preserve type definition formatting, which is essential for readable API documentation. **Verified by:** + - Render shapes as markdown --- @@ -1097,6 +1169,7 @@ > **Rationale:** Silently extracting imported types as if they were local declarations would produce duplicate or misleading documentation, since the canonical definition lives in another file. **Verified by:** + - Imported shape produces warning - Re-exported shape produces re-export entry @@ -1109,6 +1182,7 @@ > **Rationale:** Unhandled parse exceptions would crash the pipeline mid-run, preventing all subsequent files from being processed. **Verified by:** + - Malformed TypeScript returns error --- @@ -1120,6 +1194,7 @@ > **Rationale:** Different documentation layouts require different grouping strategies; a single block provides compact overviews while separate blocks allow per-type commentary. **Verified by:** + - Grouped rendering in single code block - Separate rendering with multiple code blocks @@ -1127,11 +1202,12 @@ #### Annotation tags are stripped from extracted JSDoc while preserving standard tags -> **Invariant:** Extracted shapes never contain @libar-docs-* annotation lines in their jsDoc field. +> **Invariant:** Extracted shapes never contain @libar-docs-\* annotation lines in their jsDoc field. > > **Rationale:** Shape JSDoc is rendered in documentation output. Annotation tags are metadata for the extraction pipeline, not user-visible documentation content. **Verified by:** + - JSDoc with only annotation tags produces no jsDoc - Mixed JSDoc preserves standard tags and strips annotation tags - Single-line annotation-only JSDoc produces no jsDoc @@ -1146,13 +1222,14 @@ > **Rationale:** Feeding unbounded input to the TypeScript parser risks out-of-memory crashes that would halt the entire extraction pipeline. **Verified by:** + - Source code exceeding 5MB limit returns error -*shape-extraction-rendering.feature* +_shape-extraction-rendering.feature_ ### Shape Extraction Types -*Validates the shape extraction system that extracts TypeScript type* +_Validates the shape extraction system that extracts TypeScript type_ --- @@ -1163,6 +1240,7 @@ > **Rationale:** Without CSV format registration, the tag parser cannot split comma-separated shape lists, causing only the first shape to be extracted. **Verified by:** + - Tag registry contains extract-shapes with correct format --- @@ -1174,6 +1252,7 @@ > **Rationale:** Interfaces are the primary API surface for TypeScript libraries; failing to extract them leaves the most important type contracts undocumented. **Verified by:** + - Extract simple interface - Extract interface with JSDoc - Extract interface with generics @@ -1189,6 +1268,7 @@ > **Rationale:** Misattributing interface-level JSDoc to the first property produces incorrect per-field documentation and misleads consumers about individual property semantics. The extractor uses strict adjacency (gap = 1 line) to prevent interface-level JSDoc from being misattributed to the first property. **Verified by:** + - Extract properties with adjacent JSDoc - Interface JSDoc not attributed to first property - Mixed documented and undocumented properties @@ -1202,6 +1282,7 @@ > **Rationale:** Type aliases encode domain constraints (e.g., discriminated unions, mapped utilities) that are essential for API documentation; omitting them hides the type-level design. **Verified by:** + - Extract union type alias - Extract mapped type - Extract conditional type @@ -1215,6 +1296,7 @@ > **Rationale:** Enums define finite value sets used in validation and serialization; missing them from documentation forces consumers to read source code to discover valid values. **Verified by:** + - Extract string enum - Extract const enum @@ -1227,6 +1309,7 @@ > **Rationale:** Including function bodies in documentation exposes implementation details, inflates output size, and creates a maintenance burden when internals change without signature changes. **Verified by:** + - Extract function signature - Extract async function signature @@ -1239,6 +1322,7 @@ > **Rationale:** Constants define configuration defaults, version strings, and sentinel values that consumers depend on; excluding them creates documentation gaps for public API surface. **Verified by:** + - Extract const with type annotation - Extract const without type annotation @@ -1251,14 +1335,15 @@ > **Rationale:** Internal types often define the core domain model; restricting extraction to exports only would omit types that are essential for understanding module internals. **Verified by:** + - Extract non-exported interface - Re-export marks internal shape as exported -*shape-extraction-types.feature* +_shape-extraction-types.feature_ ### Uses Tag -*Tests extraction and processing of @libar-docs-uses and @libar-docs-used-by* +_Tests extraction and processing of @libar-docs-uses and @libar-docs-used-by_ --- @@ -1269,6 +1354,7 @@ > **Rationale:** Without registry definitions, the data-driven AST parser cannot discover or extract these tags from source files. **Verified by:** + - Uses tag exists in registry - Used-by tag exists in registry @@ -1281,6 +1367,7 @@ > **Rationale:** Missing or malformed uses extraction breaks runtime dependency tracking and produces incomplete relationship diagrams. **Verified by:** + - Single uses value extracted - Multiple uses values extracted as CSV @@ -1293,6 +1380,7 @@ > **Rationale:** Missing used-by extraction prevents reverse dependency lookups, leaving consumers unable to discover which patterns depend on them. **Verified by:** + - Single used-by value extracted - Multiple used-by values extracted as CSV @@ -1305,12 +1393,14 @@ > **Rationale:** Omitting relationships from the index causes dependency diagrams and impact-analysis queries to silently miss connections. **Verified by:** + - Uses relationships stored in relationship index - UsedBy relationships stored explicitly - UsedBy relationships stored explicitly - The relationship index stores uses and usedBy relationships directly - from pattern metadata. Unlike implements + The relationship index stores uses and usedBy relationships directly + from pattern metadata. Unlike implements + - these are explicit declarations. --- @@ -1322,10 +1412,11 @@ > **Rationale:** Schema rejection of valid uses/usedBy values causes runtime parse failures that silently drop relationship data. **Verified by:** + - DocDirective schema accepts uses - RelationshipEntry schema accepts usedBy -*uses-tag.feature* +_uses-tag.feature_ --- diff --git a/docs-generated/business-rules/configuration.md b/docs-live/business-rules/configuration.md similarity index 95% rename from docs-generated/business-rules/configuration.md rename to docs-live/business-rules/configuration.md index a8ccf875..99898fe6 100644 --- a/docs-generated/business-rules/configuration.md +++ b/docs-live/business-rules/configuration.md @@ -12,7 +12,7 @@ ### Config Loader -*- Different directories need different taxonomies* +_- Different directories need different taxonomies_ --- @@ -23,6 +23,7 @@ > **Rationale:** Projects may run CLI commands from subdirectories — upward traversal ensures the nearest config file is always found regardless of working directory. **Verified by:** + - Find config file in current directory - Find config file in parent directory - Prefer TypeScript config over JavaScript @@ -37,6 +38,7 @@ > **Rationale:** Searching beyond the repo root could find unrelated config files from parent projects, producing confusing cross-project behavior. **Verified by:** + - Stop at .git directory marker --- @@ -48,6 +50,7 @@ > **Rationale:** Invalid configurations produce cryptic downstream errors — early validation with clear messages prevents debugging wasted on malformed config. **Verified by:** + - Load valid config with default fallback - Load valid config file - Error on config without default export @@ -62,13 +65,14 @@ > **Rationale:** Raw error objects are not actionable — developers need the config file path and a clear description to diagnose and fix configuration issues. **Verified by:** + - Format error with path and message -*config-loader.feature* +_config-loader.feature_ ### Config Resolution -*- Raw user config is partial with many optional fields* +_- Raw user config is partial with many optional fields_ --- @@ -79,6 +83,7 @@ > **Rationale:** Downstream consumers need a safe starting point when no config file exists. **Verified by:** + - Default config has empty sources and isDefault flag --- @@ -90,6 +95,7 @@ > **Rationale:** Presets are the primary user-facing configuration — wrong category counts break downstream scanning. **Verified by:** + - libar-generic preset creates 3 categories --- @@ -101,6 +107,7 @@ > **Rationale:** Stubs extend the scanner's source set without requiring users to manually list them. **Verified by:** + - Stubs appended to typescript sources --- @@ -112,6 +119,7 @@ > **Rationale:** Consistent defaults prevent accidental overwrites and establish a predictable output location. **Verified by:** + - Default output directory and overwrite - Explicit output overrides defaults @@ -124,6 +132,7 @@ > **Rationale:** Patterns is the most commonly needed output — defaulting to it reduces boilerplate. **Verified by:** + - Generators default to patterns --- @@ -135,6 +144,7 @@ > **Rationale:** Prepending gives user rules priority during context matching without losing defaults. **Verified by:** + - User rules prepended to defaults --- @@ -146,13 +156,14 @@ > **Rationale:** Downstream tools need the original config file location for error reporting and relative path resolution. **Verified by:** + - configPath carried from resolution options -*config-resolution.feature* +_config-resolution.feature_ ### Configuration API -*- Different projects need different tag prefixes* +_- Different projects need different tag prefixes_ --- @@ -163,6 +174,7 @@ > **Rationale:** A sensible default preset eliminates boilerplate for the common case while still supporting specialized presets (ddd-es-cqrs) for advanced monorepo configurations. **Verified by:** + - Create with no arguments uses libar-generic preset - Create with generic preset - Create with libar-generic preset @@ -177,6 +189,7 @@ > **Rationale:** Consuming projects may use different annotation prefixes — custom prefixes enable the toolkit to work with any tag convention without forking presets. **Verified by:** + - Custom tag prefix overrides preset - Custom file opt-in tag overrides preset - Both prefix and opt-in tag can be customized together @@ -190,6 +203,7 @@ > **Rationale:** Category sets are curated per-preset — merging would include irrelevant categories (e.g., DDD categories in a generic project) that pollute taxonomy reports. **Verified by:** + - Generic preset excludes DDD categories - Libar-generic preset excludes DDD categories @@ -202,6 +216,7 @@ > **Rationale:** Regex patterns that ignore the configured prefix would miss annotations in projects using custom prefixes, silently skipping source files. **Verified by:** + - hasFileOptIn detects configured opt-in tag - hasFileOptIn rejects wrong opt-in tag - hasDocDirectives detects configured prefix @@ -209,11 +224,11 @@ - normalizeTag removes configured prefix - normalizeTag handles tag without prefix -*configuration-api.feature* +_configuration-api.feature_ ### Define Config -*- Users need type-safe config authoring without runtime overhead* +_- Users need type-safe config authoring without runtime overhead_ --- @@ -224,6 +239,7 @@ > **Rationale:** defineConfig exists for TypeScript type inference in config files — any transformation would surprise users who expect their config object to pass through unmodified. **Verified by:** + - defineConfig returns input unchanged --- @@ -235,6 +251,7 @@ > **Rationale:** The schema must accept all legitimate configuration shapes — rejecting valid configs would block users from using supported features. **Verified by:** + - Valid minimal config passes validation - Valid full config passes validation @@ -247,6 +264,7 @@ > **Rationale:** Schema validation is the first line of defense against misconfiguration — permissive validation lets invalid configs produce confusing downstream errors. **Verified by:** + - Empty glob pattern rejected - Parent directory traversal rejected in globs - replaceFeatures and additionalFeatures mutually exclusive @@ -262,16 +280,17 @@ > **Rationale:** The codebase supports both config formats during migration — incorrect type detection would apply the wrong loading path and produce runtime errors. **Verified by:** + - isProjectConfig returns true for new-style config - isProjectConfig returns false for legacy instance - isLegacyInstance returns true for legacy objects - isLegacyInstance returns false for new-style config -*define-config.feature* +_define-config.feature_ ### Preset System -*- New users need sensible defaults for their project type* +_- New users need sensible defaults for their project type_ --- @@ -282,6 +301,7 @@ > **Rationale:** Simple projects need minimal configuration without DDD-specific categories cluttering the taxonomy. **Verified by:** + - Generic preset has correct prefix configuration - Generic preset has core categories only @@ -294,6 +314,7 @@ > **Rationale:** This package uses @libar-docs- prefix to avoid collisions with consumer projects' annotations. **Verified by:** + - Libar generic preset has correct prefix configuration - Libar generic preset has core categories only @@ -306,6 +327,7 @@ > **Rationale:** DDD architectures require fine-grained categorization to distinguish bounded contexts, aggregates, and projections. **Verified by:** + - Full preset has correct prefix configuration - Full preset has all DDD categories - Full preset has infrastructure categories @@ -320,15 +342,16 @@ > **Rationale:** Programmatic access enables config files to reference presets by name instead of importing instances. **Verified by:** + - Generic preset accessible via PRESETS map - DDD preset accessible via PRESETS map - Libar generic preset accessible via PRESETS map -*preset-system.feature* +_preset-system.feature_ ### Project Config Loader -*- Two config formats exist (new-style and legacy) that need unified loading* +_- Two config formats exist (new-style and legacy) that need unified loading_ --- @@ -339,6 +362,7 @@ > **Rationale:** Graceful fallback enables zero-config usage — new projects work without requiring config file creation. **Verified by:** + - No config file returns default resolved config --- @@ -350,6 +374,7 @@ > **Rationale:** defineConfig is the primary config format — correct loading is the critical path for all documentation generation. **Verified by:** + - defineConfig export loads and resolves correctly --- @@ -361,6 +386,7 @@ > **Rationale:** Backward compatibility prevents breaking existing consumers during migration to the new config format. **Verified by:** + - Legacy createDeliveryProcess export loads correctly --- @@ -372,14 +398,15 @@ > **Rationale:** Actionable error messages reduce debugging time — users need to know what to fix, not just that something failed. **Verified by:** + - Config without default export returns error - Config with invalid project config returns Zod error -*project-config-loader.feature* +_project-config-loader.feature_ ### Source Merging -*- Different generators may need different feature or input sources* +_- Different generators may need different feature or input sources_ --- @@ -390,6 +417,7 @@ > **Rationale:** The merge function must be safe to call unconditionally — returning modified results without overrides would corrupt default source paths. **Verified by:** + - No override returns base sources --- @@ -401,6 +429,7 @@ > **Rationale:** Projects need both additive and replacement strategies — additive for extending (monorepo packages), replacement for narrowing (focused generation runs). **Verified by:** + - additionalFeatures appended to base features - replaceFeatures replaces base features entirely - Empty replaceFeatures does NOT replace @@ -414,6 +443,7 @@ > **Rationale:** TypeScript sources are always additive — the base sources contain core patterns that must always be included alongside project-specific additions. **Verified by:** + - additionalInput appended to typescript sources --- @@ -425,6 +455,7 @@ > **Rationale:** Real configs often specify both feature and TypeScript overrides — they must not interfere with each other or produce order-dependent results. **Verified by:** + - additionalFeatures and additionalInput combined --- @@ -436,9 +467,10 @@ > **Rationale:** Exclude patterns are a safety mechanism — allowing overrides to modify excludes could accidentally include sensitive or generated files in the scan. **Verified by:** + - Exclude always inherited -*source-merging.feature* +_source-merging.feature_ --- diff --git a/docs-generated/business-rules/core-types.md b/docs-live/business-rules/core-types.md similarity index 95% rename from docs-generated/business-rules/core-types.md rename to docs-live/business-rules/core-types.md index f1db7b7a..64a60555 100644 --- a/docs-generated/business-rules/core-types.md +++ b/docs-live/business-rules/core-types.md @@ -1,6 +1,6 @@ -# CoreTypes Business Rules +# Core Types Business Rules -**Purpose:** Business rules for the CoreTypes product area +**Purpose:** Business rules for the Core Types product area --- @@ -12,7 +12,7 @@ ### Kebab Case Slugs -*As a documentation generator* +_As a documentation generator_ --- @@ -23,6 +23,7 @@ > **Rationale:** Generated file names and URL fragments must be human-readable and URL-safe; unsplit CamelCase produces opaque slugs that are difficult to scan in directory listings. **Verified by:** + - Convert pattern names to readable slugs --- @@ -34,6 +35,7 @@ > **Rationale:** Unhandled edge cases produce malformed file names (double hyphens, leading dashes) that break cross-platform path resolution and make generated links inconsistent. **Verified by:** + - Handle edge cases in slug generation --- @@ -45,6 +47,7 @@ > **Rationale:** Phase prefixes enable lexicographic sorting of requirement files by delivery order, so directory listings naturally reflect the roadmap sequence. **Verified by:** + - Requirement slugs include phase number - Requirement without phase uses phase 00 @@ -57,10 +60,11 @@ > **Rationale:** A consistent "phase-NN-name" format ensures phase files sort numerically and remain identifiable even when the phase number alone would be ambiguous across roadmap versions. **Verified by:** + - Phase slugs combine number and kebab-case name - Phase without name uses "unnamed" -*kebab-case-slugs.feature* +_kebab-case-slugs.feature_ --- @@ -68,7 +72,7 @@ ### Error Factories -*Error factories create structured, discriminated error types with consistent* +_Error factories create structured, discriminated error types with consistent_ --- @@ -79,6 +83,7 @@ > **Rationale:** File system errors are the most common failure mode in the scanner; discriminated types enable exhaustive switch/case handling in error recovery paths. **Verified by:** + - createFileSystemError generates correct message for each reason - createFileSystemError includes optional originalError - createFileSystemError omits originalError when not provided @@ -92,6 +97,7 @@ > **Rationale:** The "file:line" format enables click-to-navigate in IDEs and terminals, turning validation errors into actionable links rather than requiring manual file/line lookup. **Verified by:** + - createDirectiveValidationError includes line number in message - createDirectiveValidationError includes optional directive snippet - createDirectiveValidationError omits directive when not provided @@ -105,6 +111,7 @@ > **Rationale:** Pattern names appear across many source files; without the pattern name and file path in the error, developers cannot locate which annotation triggered the validation failure. **Verified by:** + - createPatternValidationError formats pattern name and file - createPatternValidationError includes validation errors array - createPatternValidationError omits validationErrors when not provided @@ -118,6 +125,7 @@ > **Rationale:** Process metadata (status, phase, deliverables) drives FSM validation and documentation generation; silent metadata errors propagate incorrect state across all downstream consumers. **Verified by:** + - createProcessMetadataValidationError formats file and reason - createProcessMetadataValidationError includes readonly validation errors @@ -130,16 +138,17 @@ > **Rationale:** Features often contain multiple deliverables; without the deliverable name in the error, developers must manually inspect the entire Background table to find the failing row. **Verified by:** + - createDeliverableValidationError formats file and reason - createDeliverableValidationError includes optional deliverableName - createDeliverableValidationError omits deliverableName when not provided - createDeliverableValidationError includes validation errors -*error-factories.feature* +_error-factories.feature_ ### Error Handling Unification -*- Raw errors lack context (no file path, line number, or pattern name)* +_- Raw errors lack context (no file path, line number, or pattern name)_ --- @@ -150,6 +159,7 @@ > **Rationale:** Without a reliable type guard, error handlers cannot safely narrow unknown caught values to DocError, forcing unsafe casts or redundant field checks at every catch site. **Verified by:** + - isDocError detects valid DocError instances - isDocError rejects non-DocError objects - isDocError rejects null and undefined @@ -163,6 +173,7 @@ > **Rationale:** Omitting context fields forces developers to cross-reference logs with source files manually; including all fields in a single formatted message makes errors actionable on first read. **Verified by:** + - formatDocError includes structured context - formatDocError includes validation errors for pattern errors @@ -175,6 +186,7 @@ > **Rationale:** console.warn bypasses error collection, making warnings invisible to callers and untestable. Structured error objects enable programmatic handling across all consumers. **Verified by:** + - Errors include structured context - No console.warn bypasses error collection - Skip feature files without @libar-docs opt-in @@ -188,13 +200,14 @@ > **Rationale:** CLI commands can receive arbitrary thrown values (strings, numbers, objects); coercing them to a safe string prevents the error handler itself from crashing on unexpected types. **Verified by:** + - handleCliError formats unknown errors -*error-handling.feature* +_error-handling.feature_ ### Result Monad -*The Result type provides explicit error handling via a discriminated union.* +_The Result type provides explicit error handling via a discriminated union._ --- @@ -205,6 +218,7 @@ > **Rationale:** Consumers rely on isOk to branch logic; if Result.ok could produce an ambiguous state, every call site would need defensive checks beyond the type guard. **Verified by:** + - Result.ok wraps a primitive value - Result.ok wraps an object value - Result.ok wraps null value @@ -219,6 +233,7 @@ > **Rationale:** Supporting multiple error value types allows callers to propagate rich context (structured objects) or simple messages (strings) without forcing a single error representation. **Verified by:** + - Result.err wraps an Error instance - Result.err wraps a string error - Result.err wraps a structured error object @@ -232,6 +247,7 @@ > **Rationale:** If both guards could return true (or both false), TypeScript type narrowing would break, leaving the value/error branch unreachable or unsound. **Verified by:** + - Type guards correctly identify success results - Type guards correctly identify error results @@ -244,6 +260,7 @@ > **Rationale:** Wrapping non-Error values in Error instances ensures stack traces are always available for debugging, preventing the loss of call-site context when string or object errors are thrown. **Verified by:** + - unwrap extracts value from success result - unwrap throws the Error from error result - unwrap wraps non-Error in Error for proper stack trace @@ -258,6 +275,7 @@ > **Rationale:** Providing a safe fallback path avoids forcing callers to handle errors explicitly when a sensible default exists, reducing boilerplate in non-critical error recovery. **Verified by:** + - unwrapOr returns value from success result - unwrapOr returns default from error result - unwrapOr returns numeric default from error result @@ -271,6 +289,7 @@ > **Rationale:** Skipping the transformation on error results enables chained pipelines to short-circuit on the first failure without requiring explicit error checks at each step. **Verified by:** + - map transforms success value - map passes through error unchanged - map chains multiple transformations @@ -284,15 +303,16 @@ > **Rationale:** Allowing error-type conversion at boundaries (e.g., low-level I/O errors to domain errors) keeps success paths untouched and preserves the original value through error-handling layers. **Verified by:** + - mapErr transforms error value - mapErr passes through success unchanged - mapErr converts error type -*result-monad.feature* +_result-monad.feature_ ### String Utils -*String utilities provide consistent text transformations across the codebase.* +_String utilities provide consistent text transformations across the codebase._ --- @@ -303,6 +323,7 @@ > **Rationale:** URL slugs appear in file paths and links across all generated documentation; inconsistent slugification would break cross-references. **Verified by:** + - slugify converts text to URL-safe format - slugify handles empty-ish input - slugify handles single word @@ -316,11 +337,12 @@ > **Rationale:** Pattern names stored as PascalCase identifiers appear as human-readable titles in generated documentation; incorrect splitting would produce unreadable headings. **Verified by:** + - camelCaseToTitleCase converts to title case - camelCaseToTitleCase handles all-uppercase acronym - camelCaseToTitleCase handles lowercase word -*string-utils.feature* +_string-utils.feature_ --- diff --git a/docs-generated/business-rules/data-api.md b/docs-live/business-rules/data-api.md similarity index 92% rename from docs-generated/business-rules/data-api.md rename to docs-live/business-rules/data-api.md index 0b2a83de..9922ff1e 100644 --- a/docs-generated/business-rules/data-api.md +++ b/docs-live/business-rules/data-api.md @@ -1,10 +1,10 @@ -# DataAPI Business Rules +# Data API Business Rules -**Purpose:** Business rules for the DataAPI product area +**Purpose:** Business rules for the Data API product area --- -**86 rules** from 20 features. 86 rules have explicit invariants. +**89 rules** from 21 features. 89 rules have explicit invariants. --- @@ -21,6 +21,7 @@ > **Rationale:** The patternName tag allows human-friendly display names — without the fallback, patterns missing the tag would display as undefined. **Verified by:** + - Returns patternName when set - Falls back to name when patternName is absent @@ -33,6 +34,7 @@ > **Rationale:** Case-insensitive matching prevents frustrating "not found" errors when developers type "processguard" instead of "ProcessGuard" — both clearly refer to the same pattern. **Verified by:** + - Exact case match - Case-insensitive match - No match returns undefined @@ -46,6 +48,7 @@ > **Rationale:** Exact-first with case-insensitive fallback balances performance (O(1) exact lookup) with usability (tolerates case mismatches in cross-references). **Verified by:** + - Exact key match in relationship index - Case-insensitive fallback match - Missing relationship index returns undefined @@ -59,10 +62,11 @@ > **Rationale:** Fuzzy suggestions power "did you mean?" UX in the CLI — without them, typos produce unhelpful "pattern not found" messages. **Verified by:** + - Suggests close match - No close match returns empty -*pattern-helpers.feature* +_pattern-helpers.feature_ --- @@ -79,6 +83,7 @@ > **Rationale:** Neighborhood and comparison views are the primary navigation tools for understanding architecture — without them, developers must manually trace relationship chains across files. **Verified by:** + - Pattern neighborhood shows direct connections - Cross-context comparison shows shared and unique dependencies - Neighborhood for nonexistent pattern returns undefined @@ -92,6 +97,7 @@ > **Rationale:** Tag aggregation reveals annotation coverage gaps and source inventory helps teams understand their codebase composition — both are essential for project health monitoring. **Verified by:** + - Tag aggregation counts values across patterns - Source inventory categorizes files by type - Tags with no patterns returns empty report @@ -105,16 +111,17 @@ > **Rationale:** Unused taxonomy entries indicate dead configuration while missing relationship types produce incomplete architecture views — both degrade the reliability of generated documentation. **Verified by:** + - Unused taxonomy detection - Cross-context comparison with integration points - Neighborhood includes implements relationships - Neighborhood includes dependsOn and enables relationships -*arch-queries.feature* +_arch-queries.feature_ ### Context Assembler Tests -*Tests for assembleContext(), buildDepTree(), buildFileReadingList(), and* +_Tests for assembleContext(), buildDepTree(), buildFileReadingList(), and_ --- @@ -125,6 +132,7 @@ > **Rationale:** Over-fetching wastes AI context window tokens; under-fetching causes the agent to make uninformed decisions. **Verified by:** + - Design session includes stubs, consumers, and architecture - Planning session includes only metadata and dependencies - Implement session includes deliverables and FSM @@ -145,6 +153,7 @@ > **Rationale:** Dependency chains reveal implementation prerequisites — cycles and infinite recursion would crash the CLI. **Verified by:** + - Dependency tree shows chain with status markers - Depth limit truncates branches - Circular dependencies are handled safely @@ -159,6 +168,7 @@ > **Rationale:** The overview is the first command in every session start recipe — it must provide a complete project health snapshot. **Verified by:** + - Overview shows progress, active phases, and blocking - Empty dataset returns zero-state overview - Overview shows progress @@ -174,15 +184,16 @@ > **Rationale:** File reading lists power the "what to read" guidance — relevance sorting ensures the most important files are read first within token budgets. **Verified by:** + - File list includes primary and related files - File list includes implementation files for completed dependencies - File list without related returns only primary -*context-assembler.feature* +_context-assembler.feature_ ### Context Formatter Tests -*Tests for formatContextBundle(), formatDepTree(), formatFileReadingList(),* +_Tests for formatContextBundle(), formatDepTree(), formatFileReadingList(),_ --- @@ -193,6 +204,7 @@ > **Rationale:** Section markers enable structured parsing of context output — without them, AI consumers cannot reliably extract specific sections from the formatted bundle. **Verified by:** + - Design bundle renders all populated sections - Implement bundle renders deliverables and FSM @@ -205,6 +217,7 @@ > **Rationale:** Visual hierarchy in the dependency tree makes dependency chains scannable at a glance — flat output would require mental parsing to understand depth and relationships. **Verified by:** + - Tree renders with arrows and focal marker --- @@ -216,6 +229,7 @@ > **Rationale:** The progress line is the first thing developers see when starting a session — it provides immediate project health awareness without requiring detailed exploration. **Verified by:** + - Overview renders progress line --- @@ -227,14 +241,15 @@ > **Rationale:** Categorized file lists tell developers which files to read first (primary) versus reference (dependency) — uncategorized lists waste time on low-priority files. **Verified by:** + - File list renders primary and dependency sections - Empty file reading list renders minimal output -*context-formatter.feature* +_context-formatter.feature_ ### Fuzzy Match Tests -*Validates tiered fuzzy matching: exact > prefix > substring > Levenshtein.* +_Validates tiered fuzzy matching: exact > prefix > substring > Levenshtein._ --- @@ -245,6 +260,7 @@ > **Rationale:** Tiered scoring ensures the most intuitive match wins — an exact match should always rank above a substring match, preventing surprising suggestions for common pattern names. **Verified by:** + - Exact match scores 1.0 - Exact match is case-insensitive - Prefix match scores 0.9 @@ -263,6 +279,7 @@ > **Rationale:** A single best suggestion simplifies "did you mean?" prompts in the CLI — returning multiple matches would require additional UI to disambiguate. **Verified by:** + - Best match returns suggestion above threshold - No match returns undefined when below threshold @@ -275,14 +292,15 @@ > **Rationale:** Levenshtein distance is the fallback matching tier — incorrect distance computation would produce wrong fuzzy match scores for typo correction. **Verified by:** + - Identical strings have distance 0 - Single character difference -*fuzzy-match.feature* +_fuzzy-match.feature_ ### Generate Docs Cli -*Command-line interface for generating documentation from annotated TypeScript.* +_Command-line interface for generating documentation from annotated TypeScript._ --- @@ -293,6 +311,7 @@ > **Rationale:** Help and version are universal CLI conventions — they must work standalone so users can discover usage without reading external documentation. **Verified by:** + - Display help with --help flag - Display version with -v flag @@ -305,6 +324,7 @@ > **Rationale:** Without input source paths, the generator has nothing to scan — failing early with a clear message prevents confusing "no patterns found" errors downstream. **Verified by:** + - Fail without --input flag --- @@ -316,6 +336,7 @@ > **Rationale:** Users need to discover available generators before specifying --generator — listing them avoids trial-and-error with invalid generator names. **Verified by:** + - List generators with --list-generators --- @@ -327,6 +348,7 @@ > **Rationale:** This is the core pipeline — the CLI is the primary entry point for transforming annotated source code into generated documentation. **Verified by:** + - Generate patterns documentation - Use default generator (patterns) when not specified @@ -339,13 +361,14 @@ > **Rationale:** Silent flag ignoring hides typos and misconfigurations — users typing --ouput instead of --output would get unexpected default behavior without realizing their flag was ignored. **Verified by:** + - Unknown option causes error -*generate-docs.feature* +_generate-docs.feature_ ### Generate Tag Taxonomy Cli -*Command-line interface for generating TAG_TAXONOMY.md from tag registry configuration.* +_Command-line interface for generating TAG_TAXONOMY.md from tag registry configuration._ --- @@ -356,6 +379,7 @@ > **Rationale:** Help and version are universal CLI conventions — both short and long flag forms must work for discoverability and scripting compatibility. **Verified by:** + - Display help with --help flag - Display help with -h flag - Display version with --version flag @@ -370,6 +394,7 @@ > **Rationale:** Flexible output paths support both default conventions and custom layouts — auto-creating directories prevents "ENOENT" errors on first run. **Verified by:** + - Generate taxonomy at default path - Generate taxonomy at custom output path - Create output directory if missing @@ -383,6 +408,7 @@ > **Rationale:** Overwrite protection prevents accidental destruction of hand-edited taxonomy files — requiring an explicit flag makes destructive operations intentional. **Verified by:** + - Fail when output file exists without --overwrite - Overwrite existing file with -f flag - Overwrite existing file with --overwrite flag @@ -396,6 +422,7 @@ > **Rationale:** The taxonomy is a reference document — incomplete output missing categories or statistics would leave developers without the information they need to annotate correctly. **Verified by:** + - Generated file contains category documentation - Generated file reports statistics @@ -408,13 +435,14 @@ > **Rationale:** Taxonomy generation is non-destructive — warning without failing is more user-friendly than hard errors for minor flag typos, while still surfacing the issue. **Verified by:** + - Warn on unknown flag but continue -*generate-tag-taxonomy.feature* +_generate-tag-taxonomy.feature_ ### Handoff Generator Tests -*Multi-session work loses critical state between sessions when handoff* +_Multi-session work loses critical state between sessions when handoff_ --- @@ -425,6 +453,7 @@ > **Rationale:** Handoff documents are the bridge between multi-session work — without compact state capture, the next session starts from scratch instead of resuming where the previous one left off. **Verified by:** + - Generate handoff for in-progress pattern - Handoff captures discovered items - Session type is inferred from status @@ -443,13 +472,14 @@ > **Rationale:** ADR-008 markers enable the context assembler to parse handoff output programmatically — unstructured text would require fragile regex parsing. **Verified by:** + - Handoff formatter produces markers per ADR-008 -*handoff-generator.feature* +_handoff-generator.feature_ ### Lint Patterns Cli -*Command-line interface for validating pattern annotation quality.* +_Command-line interface for validating pattern annotation quality._ --- @@ -460,6 +490,7 @@ > **Rationale:** Help and version are universal CLI conventions — they must work standalone so users can discover usage without reading external documentation. **Verified by:** + - Display help with --help flag - Display version with -v flag @@ -472,6 +503,7 @@ > **Rationale:** Without input paths, the linter has nothing to validate — failing early prevents confusing "no violations" output that falsely implies clean annotations. **Verified by:** + - Fail without --input flag --- @@ -483,6 +515,7 @@ > **Rationale:** False positives erode developer trust in the linter — valid annotations must always pass to maintain the tool's credibility. **Verified by:** + - Lint passes for complete annotations --- @@ -494,6 +527,7 @@ > **Rationale:** Actionable violation messages guide developers to fix annotations — generic "lint failed" messages without specifics waste debugging time. **Verified by:** + - Report violations for incomplete annotations --- @@ -505,6 +539,7 @@ > **Rationale:** Pretty format serves interactive use while JSON format enables CI/CD pipeline integration and programmatic consumption of lint results. **Verified by:** + - JSON output format - Pretty output format is default @@ -517,14 +552,15 @@ > **Rationale:** CI pipelines need strict enforcement while local development benefits from lenient mode — the flag lets teams choose their enforcement level. **Verified by:** + - Strict mode fails on warnings - Non-strict mode passes with warnings -*lint-patterns.feature* +_lint-patterns.feature_ ### Lint Process Cli -*Command-line interface for validating changes against delivery process rules.* +_Command-line interface for validating changes against delivery process rules._ --- @@ -535,6 +571,7 @@ > **Rationale:** Help and version are universal CLI conventions — both short and long flag forms must work for discoverability and scripting compatibility. **Verified by:** + - Display help with --help flag - Display help with -h flag - Display version with --version flag @@ -549,6 +586,7 @@ > **Rationale:** Process guard validation depends on git diff for change detection — running without git produces undefined behavior rather than useful validation results. **Verified by:** + - Fail without git repository in staged mode - Fail without git repository in all mode @@ -561,6 +599,7 @@ > **Rationale:** File mode is for targeted validation of specific files — accepting zero files would silently produce a "no violations" result that falsely implies the files are valid. **Verified by:** + - Fail when files mode has no files - Accept file via positional argument - Accept file via --file flag @@ -574,6 +613,7 @@ > **Rationale:** No changes means no violations are possible — failing on empty diffs would break CI pipelines on commits that only modify non-spec files. **Verified by:** + - No changes detected exits successfully --- @@ -585,6 +625,7 @@ > **Rationale:** Pretty format serves interactive pre-commit use while JSON format enables CI/CD pipeline integration and automated violation processing. **Verified by:** + - JSON output format - Pretty output format is default @@ -597,6 +638,7 @@ > **Rationale:** Process guard decisions are derived from complex state — exposing the intermediate state helps developers understand why a specific validation passed or failed. **Verified by:** + - Show state flag displays derived state --- @@ -608,13 +650,14 @@ > **Rationale:** Process validation is critical-path at commit time — hard-failing on a typo in an optional flag would block commits unnecessarily when the core validation would succeed. **Verified by:** + - Warn on unknown flag but continue -*lint-process.feature* +_lint-process.feature_ ### Output Pipeline Tests -*Validates the output pipeline transforms: summarization, modifiers,* +_Validates the output pipeline transforms: summarization, modifiers,_ --- @@ -625,6 +668,7 @@ > **Rationale:** Predictable modifier behavior enables composable CLI queries — unexpected precedence or scalar handling would produce confusing output for piped commands. **Verified by:** + - Default mode returns summaries for pattern arrays - Count modifier returns integer - Names-only modifier returns string array @@ -642,6 +686,7 @@ > **Rationale:** Conflicting modifiers produce ambiguous intent — rejecting early with a clear message is better than silently picking one modifier and ignoring the other. **Verified by:** + - Full combined with names-only is rejected - Full combined with count is rejected - Full combined with fields is rejected @@ -656,6 +701,7 @@ > **Rationale:** AND composition is the intuitive default for filters — "status=active AND category=core" should narrow results, not widen them via OR logic. **Verified by:** + - Filter by status returns matching patterns - Filter by status and category narrows results - Pagination with limit and offset @@ -670,13 +716,14 @@ > **Rationale:** Empty fields in pattern summaries create visual clutter and waste tokens in AI context windows — stripping them keeps output focused on meaningful data. **Verified by:** + - Null and empty values are stripped -*output-pipeline.feature* +_output-pipeline.feature_ ### Pattern Summarize Tests -*Validates that summarizePattern() projects ExtractedPattern (~3.5KB) to* +_Validates that summarizePattern() projects ExtractedPattern (~3.5KB) to_ --- @@ -687,6 +734,7 @@ > **Rationale:** Compact summaries reduce token usage by 80-90% compared to full patterns — they provide enough context for navigation without overwhelming AI context windows. **Verified by:** + - Summary includes all 6 fields for a TypeScript pattern - Summary includes all 6 fields for a Gherkin pattern - Summary uses patternName tag over name field @@ -701,13 +749,14 @@ > **Rationale:** Batch processing avoids N individual function calls — the API frequently needs to summarize all patterns matching a query in a single operation. **Verified by:** + - Batch summarization returns correct count -*summarize.feature* +_summarize.feature_ ### Process Api Cli Core -*Core CLI infrastructure: help, version, input validation, status, query, pattern, arch basics, missing args, edge cases.* +_Core CLI infrastructure: help, version, input validation, status, query, pattern, arch basics, missing args, edge cases._ --- @@ -718,6 +767,7 @@ > **Rationale:** Without accessible help and version output, users cannot self-serve CLI usage or report issues with a specific version. **Verified by:** + - Display help with --help flag - Display version with -v flag - No subcommand shows help @@ -731,6 +781,7 @@ > **Rationale:** Without an input source, the pipeline has no files to scan and would produce empty or misleading results instead of a clear error. **Verified by:** + - Fail without --input flag when running status - Reject unknown options @@ -743,6 +794,7 @@ > **Rationale:** Consumers depend on machine-readable status output for scripting and CI integration; unstructured output breaks downstream automation. **Verified by:** + - Status shows counts and completion percentage --- @@ -754,6 +806,7 @@ > **Rationale:** The CLI is the primary interface for ad-hoc queries; failing to resolve a valid method name or its arguments silently drops the user's request. **Verified by:** + - Query getStatusCounts returns count object - Query isValidTransition with arguments - Unknown API method shows error @@ -767,6 +820,7 @@ > **Rationale:** Pattern lookup is the primary debugging tool for annotation issues; ambiguous or silent failures waste investigation time. **Verified by:** + - Pattern lookup returns full detail - Pattern not found shows error @@ -779,6 +833,7 @@ > **Rationale:** Architecture queries replace manual exploration of annotated sources; missing or incorrect results lead to wrong structural assumptions during design sessions. **Verified by:** + - Arch roles lists roles with counts - Arch context filters to bounded context - Arch layer lists layers with counts @@ -792,6 +847,7 @@ > **Rationale:** Silent acceptance of incomplete input would produce confusing pipeline errors instead of actionable feedback at the CLI boundary. **Verified by:** + - Query without method name shows error - Pattern without name shows error - Unknown subcommand shows error @@ -805,14 +861,15 @@ > **Rationale:** Real-world invocations via pnpm pass `--` separators and numeric strings; mishandling these causes silent data loss or crashes in automated workflows. **Verified by:** + - Integer arguments are coerced for phase queries - Double-dash separator is handled gracefully -*process-api-core.feature* +_process-api-core.feature_ ### Process Api Cli Modifiers And Rules -*Output modifiers, arch health, and rules subcommand.* +_Output modifiers, arch health, and rules subcommand._ --- @@ -823,6 +880,7 @@ > **Rationale:** Users should not need to memorize argument ordering rules; the CLI should be forgiving. **Verified by:** + - Count modifier after list subcommand returns count - Names-only modifier after list subcommand returns names - Count modifier combined with list filter @@ -836,6 +894,7 @@ > **Rationale:** Graph quality issues (broken references, isolated patterns, blocked dependencies) are relationship-level concerns that should be queryable even when no architecture metadata exists. **Verified by:** + - Arch dangling returns broken references - Arch orphans returns isolated patterns - Arch blocking returns blocked patterns @@ -849,6 +908,7 @@ > **Rationale:** Live business rule queries replace static generated markdown, enabling on-demand filtering by product area, pattern, and invariant presence. **Verified by:** + - Rules returns business rules from feature files - Rules filters by product area - Rules with count modifier returns totals @@ -859,11 +919,11 @@ - Rules for non-existent product area returns hint - Rules combines product area and only-invariants filters -*process-api-modifiers-rules.feature* +_process-api-modifiers-rules.feature_ ### Process Api Cli Subcommands -*Discovery subcommands: list, search, context assembly, tags/sources, extended arch, unannotated.* +_Discovery subcommands: list, search, context assembly, tags/sources, extended arch, unannotated._ --- @@ -874,6 +934,7 @@ > **Rationale:** Consumers parse list output programmatically; malformed JSON or silent failures cause downstream tooling to break without diagnosis. **Verified by:** + - List all patterns returns JSON array - List with invalid phase shows error @@ -886,6 +947,7 @@ > **Rationale:** Missing query validation would produce unfiltered result sets, defeating the purpose of search and wasting context budget in AI sessions. **Verified by:** + - Search returns matching patterns - Search without query shows error @@ -898,6 +960,7 @@ > **Rationale:** These subcommands replace manual file reads in AI sessions; empty or off-target output forces expensive explore-agent fallbacks that consume 5-10x more context. **Verified by:** + - Context returns curated text bundle - Context without pattern name shows error - Overview returns executive summary text @@ -912,6 +975,7 @@ > **Rationale:** Annotation exploration depends on machine-parseable output; invalid JSON prevents automated enrichment workflows from detecting unannotated files and tag gaps. **Verified by:** + - Tags returns tag usage counts - Sources returns file inventory @@ -924,6 +988,7 @@ > **Rationale:** Architecture queries drive design-session decisions; stale or structurally invalid output leads to incorrect dependency analysis and missed coupling between bounded contexts. **Verified by:** + - Arch neighborhood returns pattern relationships - Arch compare returns context comparison - Arch coverage returns annotation coverage @@ -937,13 +1002,56 @@ > **Rationale:** Files missing the opt-in marker are invisible to the scanner; without this subcommand, unannotated files silently drop out of generated documentation and validation. **Verified by:** + - Unannotated finds files missing libar-docs marker -*process-api-subcommands.feature* +_process-api-subcommands.feature_ + +### Process Api Reference Tests + +_Verifies that the declarative CLI schema drives reference table generation_ + +--- + +#### Generated reference file contains all three table sections + +> **Invariant:** PROCESS-API-REFERENCE.md contains Global Options, Output Modifiers, and List Filters tables generated from the CLI schema. + +**Verified by:** + +- Generated file contains Global Options table +- Generated file contains Output Modifiers table +- Generated file contains List Filters table +- Generated file includes inter-table prose + +--- + +#### CLI schema stays in sync with parser + +> **Invariant:** Every flag recognized by parseArgs() has a corresponding entry in the CLI schema. A missing schema entry means the sync test fails. + +**Verified by:** + +- Schema covers all global option flags +- Schema covers all output modifier flags +- Schema covers all list filter flags +- Schema covers session option + +--- + +#### showHelp output reflects CLI schema + +> **Invariant:** The help text rendered by showHelp() includes all options from the CLI schema, formatted for terminal display. + +**Verified by:** + +- Help text includes schema-defined options + +_process-api-reference.feature_ ### Process State API -*- Markdown generation is not ideal for programmatic access* +_- Markdown generation is not ideal for programmatic access_ --- @@ -954,6 +1062,7 @@ > **Rationale:** The two-domain status convention requires separate query methods — mixing them produces incorrect filtered results. **Verified by:** + - Get patterns by normalized status - Get patterns by FSM status - Get current work returns active patterns @@ -970,6 +1079,7 @@ > **Rationale:** Phase-level queries power the roadmap and session planning views — incorrect counts cascade into wrong progress percentages. **Verified by:** + - Get patterns by phase - Get phase progress - Get nonexistent phase returns undefined @@ -984,6 +1094,7 @@ > **Rationale:** Programmatic FSM access enables tooling to enforce delivery process rules without reimplementing the state machine. **Verified by:** + - Check valid transition - Check invalid transition - Get valid transitions from status @@ -998,6 +1109,7 @@ > **Rationale:** Case-insensitive search reduces friction in CLI and AI agent usage where exact casing is often unknown. **Verified by:** + - Find pattern by name (case insensitive) - Find nonexistent pattern returns undefined - Get patterns by category @@ -1012,15 +1124,16 @@ > **Rationale:** Timeline grouping enables quarterly reporting and session context — recent completions show delivery momentum. **Verified by:** + - Get patterns by quarter - Get all quarters - Get recently completed sorted by date -*process-state-api.feature* +_process-state-api.feature_ ### Scope Validator Tests -*Starting an implementation or design session without checking prerequisites* +_Starting an implementation or design session without checking prerequisites_ --- @@ -1031,6 +1144,7 @@ > **Rationale:** Starting implementation without passing scope validation wastes an entire session — the validator catches all known blockers before any code is written. **Verified by:** + - All implementation checks pass - Incomplete dependency blocks implementation - FSM transition from completed blocks implementation @@ -1048,6 +1162,7 @@ > **Rationale:** Design sessions that reference unstubbed dependencies cannot produce actionable interfaces — stub presence indicates the dependency's API surface is at least sketched. **Verified by:** + - Design session with no dependencies passes - Design session with dependencies lacking stubs produces WARN @@ -1060,15 +1175,16 @@ > **Rationale:** Structured formatter output enables the CLI to display verdicts consistently — unstructured output would vary by validation type and be hard to parse. **Verified by:** + - Formatter produces markers per ADR-008 - Formatter shows warnings verdict text - Formatter shows blocker details for blocked verdict -*scope-validator.feature* +_scope-validator.feature_ ### Stub Resolver Tests -*Design session stubs need structured discovery and resolution* +_Design session stubs need structured discovery and resolution_ --- @@ -1079,6 +1195,7 @@ > **Rationale:** Dual identification supports both convention-based (directory) and metadata-based (targetPath) stub detection — relying on only one would miss stubs organized differently. **Verified by:** + - Patterns in stubs directory are identified as stubs - Patterns with targetPath are identified as stubs @@ -1091,6 +1208,7 @@ > **Rationale:** Target existence status tells developers whether a stub has been implemented — grouping by pattern enables the "stubs --unresolved" command to show per-pattern implementation gaps. **Verified by:** + - Resolved stubs show target existence status - Stubs are grouped by implementing pattern @@ -1103,6 +1221,7 @@ > **Rationale:** Decision items (AD-1, AD-2, etc.) link stubs to architectural decisions — extracting them enables traceability from code stubs back to the design rationale. **Verified by:** + - AD-N items are extracted from description text - Empty description returns no decision items - Malformed AD items are skipped @@ -1116,14 +1235,15 @@ > **Rationale:** PDR cross-referencing enables impact analysis — knowing which patterns reference a decision helps assess the blast radius of changing that decision. **Verified by:** + - Patterns referencing a PDR are found - No references returns empty result -*stub-resolver.feature* +_stub-resolver.feature_ ### Stub Taxonomy Tag Tests -*Stub metadata (target path, design session) was stored as plain text* +_Stub metadata (target path, design session) was stored as plain text_ --- @@ -1134,6 +1254,7 @@ > **Rationale:** Unregistered tags would be flagged as unknown by the linter — registration ensures stub metadata tags pass validation alongside standard annotation tags. **Verified by:** + - Target and since tags exist in registry --- @@ -1145,13 +1266,14 @@ > **Rationale:** Domain grouping enables the taxonomy codec to render stub metadata tags in their own section — ungrouped tags would be lost in the "Other" category. **Verified by:** + - Built registry groups target and since as stub tags -*taxonomy-tags.feature* +_taxonomy-tags.feature_ ### Validate Patterns Cli -*Command-line interface for cross-validating TypeScript patterns vs Gherkin feature files.* +_Command-line interface for cross-validating TypeScript patterns vs Gherkin feature files._ --- @@ -1162,6 +1284,7 @@ > **Rationale:** Help and version are universal CLI conventions — both short and long flag forms must work for discoverability and scripting compatibility. **Verified by:** + - Display help with --help flag - Display help with -h flag - Display version with --version flag @@ -1176,6 +1299,7 @@ > **Rationale:** Cross-source validation requires both TypeScript and Gherkin inputs — running with only one source would produce incomplete validation that misses cross-source mismatches. **Verified by:** + - Fail without --input flag - Fail without --features flag @@ -1188,6 +1312,7 @@ > **Rationale:** Dual-source architecture requires consistency — a pattern with status "active" in TypeScript but "roadmap" in Gherkin creates conflicting truth and broken reports. **Verified by:** + - Validation passes for matching patterns - Detect phase mismatch between sources - Detect status mismatch between sources @@ -1201,6 +1326,7 @@ > **Rationale:** Pretty format serves interactive use while JSON format enables CI/CD pipeline integration and programmatic consumption of validation results. **Verified by:** + - JSON output format - Pretty output format is default @@ -1213,6 +1339,7 @@ > **Rationale:** CI pipelines need strict enforcement while local development benefits from lenient mode — the flag lets teams choose their enforcement level. **Verified by:** + - Strict mode exits with code 2 on warnings - Non-strict mode passes with warnings @@ -1225,9 +1352,10 @@ > **Rationale:** Pattern validation is non-destructive — warning without failing is more user-friendly than hard errors for minor flag typos, while still surfacing the issue. **Verified by:** + - Warn on unknown flag but continue -*validate-patterns.feature* +_validate-patterns.feature_ --- diff --git a/docs-generated/business-rules/generation.md b/docs-live/business-rules/generation.md similarity index 87% rename from docs-generated/business-rules/generation.md rename to docs-live/business-rules/generation.md index 293c17d9..dbedb327 100644 --- a/docs-generated/business-rules/generation.md +++ b/docs-live/business-rules/generation.md @@ -4,7 +4,7 @@ --- -**265 rules** from 55 features. 265 rules have explicit invariants. +**287 rules** from 58 features. 287 rules have explicit invariants. --- @@ -12,7 +12,7 @@ ### Rich Content Helpers -*As a document codec author* +_As a document codec author_ --- @@ -23,6 +23,7 @@ > **Rationale:** Codecs receive uncontrolled user content from feature file descriptions; unhandled edge cases would crash document generation for the entire pipeline. **Verified by:** + - Empty description returns empty array - Description with no DocStrings returns single paragraph - Single DocString parses correctly @@ -39,6 +40,7 @@ > **Rationale:** Malformed tables break markdown rendering and downstream tooling; missing cells would produce undefined values that corrupt table alignment. **Verified by:** + - Single row DataTable renders correctly - Multi-row DataTable renders correctly - Missing cell values become empty strings @@ -52,6 +54,7 @@ > **Rationale:** Ignoring the includeSteps option would bloat summary views with unwanted detail, and dropping embedded DataTables would lose structured test data. **Verified by:** + - Render scenario with steps - Skip steps when includeSteps is false - Render scenario with DataTable in step @@ -65,6 +68,7 @@ > **Rationale:** Omitting the rule name makes rendered output unnavigable, and skipping DocString parsing would output raw delimiter syntax instead of formatted code blocks. **Verified by:** + - Rule with simple description - Rule with no description - Rule with embedded DocString in description @@ -78,12 +82,13 @@ > **Rationale:** Without dedentation, code blocks inherit the Gherkin indentation level, rendering as deeply indented and unreadable in generated markdown. **Verified by:** + - Code block preserves internal relative indentation - Empty lines in code block are preserved - Trailing whitespace is trimmed from each line - Code with mixed indentation is preserved -*rich-content-helpers.feature* +_rich-content-helpers.feature_ --- @@ -91,7 +96,7 @@ ### Test Content Blocks -*This feature demonstrates what content blocks are captured and rendered* +_This feature demonstrates what content blocks are captured and rendered_ --- @@ -102,6 +107,7 @@ > **Rationale:** Without guaranteed capture, rule descriptions and rich content (DocStrings, DataTables) would be silently dropped from generated documentation. Rule descriptions provide context for why this business rule exists. You can include multiple paragraphs here. This is a second paragraph explaining edge cases or exceptions. **Verified by:** + - Scenario with DocString for rich content - Scenario with DataTable for structured data @@ -114,10 +120,11 @@ > **Rationale:** Merging rules into a single entry would collapse distinct business domains, making it impossible to trace scenarios back to their governing constraint. Each Rule keyword creates a separate entry in the Business Rules section. This helps organize complex features into logical business domains. **Verified by:** + - Simple scenario under second rule - Scenario with examples table -*test-content-blocks.feature* +_test-content-blocks.feature_ --- @@ -125,7 +132,7 @@ ### Arch Generator Registration -*I want an architecture generator registered in the generator registry* +_I want an architecture generator registered in the generator registry_ --- @@ -136,11 +143,12 @@ > **Rationale:** Without a registered entry, the CLI cannot discover or invoke architecture diagram generation. **Verified by:** + - Generator is available in registry - Generator is available in registry - The architecture generator must be registered like other built-in - generators so it can be invoked via CLI. + The architecture generator must be registered like other built-in + generators so it can be invoked via CLI. --- @@ -151,11 +159,12 @@ > **Rationale:** A sensible default prevents users from needing to specify options for the most common use case. **Verified by:** + - Default generation produces component diagram - Default generation produces component diagram - Running the architecture generator without options produces - a component diagram (bounded context view). + Running the architecture generator without options produces + a component diagram (bounded context view). --- @@ -166,11 +175,12 @@ > **Rationale:** Different architectural perspectives (bounded context vs. layer hierarchy) require different diagram types, and the user must be able to select which to generate. **Verified by:** + - Generate layered diagram with options - Generate layered diagram with options - The generator accepts options to specify diagram type - (component or layered). + The generator accepts options to specify diagram type + (component or layered). --- @@ -181,17 +191,18 @@ > **Rationale:** Without filtering, large monorepos would produce unreadable diagrams with dozens of bounded contexts; filtering enables focused per-context views. **Verified by:** + - Filter to specific contexts - Filter to specific contexts - The generator can filter to specific bounded contexts - for focused diagram output. + The generator can filter to specific bounded contexts + for focused diagram output. -*generator-registration.feature* +_generator-registration.feature_ ### Arch Index Dataset -*As a documentation generator* +_As a documentation generator_ --- @@ -202,11 +213,13 @@ > **Rationale:** Diagram generators need O(1) lookup of patterns by role to render role-based groupings efficiently. **Verified by:** + - Group patterns by role - Group patterns by role - The archIndex.byRole map groups patterns by their architectural role - (command-handler + The archIndex.byRole map groups patterns by their architectural role + (command-handler + - projection - saga - etc.) for efficient lookup. @@ -220,11 +233,12 @@ > **Rationale:** Component diagrams render bounded context subgraphs and need patterns grouped by context. **Verified by:** + - Group patterns by context - Group patterns by context - The archIndex.byContext map groups patterns by bounded context - for subgraph rendering in component diagrams. + The archIndex.byContext map groups patterns by bounded context + for subgraph rendering in component diagrams. --- @@ -235,11 +249,13 @@ > **Rationale:** Layered diagrams render layer subgraphs and need patterns grouped by architectural layer. **Verified by:** + - Group patterns by layer - Group patterns by layer - The archIndex.byLayer map groups patterns by architectural layer - (domain + The archIndex.byLayer map groups patterns by architectural layer + (domain + - application - infrastructure) for layered diagram rendering. @@ -252,14 +268,16 @@ > **Rationale:** Consumers iterating over all architectural patterns need a single canonical list; omitting partially-tagged patterns would silently drop them from diagrams. **Verified by:** + - archIndex.all includes all annotated patterns - archIndex.all includes all annotated patterns - The archIndex.all array contains all patterns that have at least - one arch tag (role + The archIndex.all array contains all patterns that have at least + one arch tag (role + - context - or layer). Patterns without any arch - tags are excluded. + tags are excluded. --- @@ -270,19 +288,125 @@ > **Rationale:** Including non-architectural patterns would pollute diagrams with irrelevant components. **Verified by:** + - Non-annotated patterns excluded - Non-annotated patterns excluded - Patterns that have no arch-role + Patterns that have no arch-role + - arch-context - or arch-layer are - not included in the archIndex at all. + not included in the archIndex at all. + +_arch-index.feature_ + +### Architecture Doc Refactoring + +_Validates that ARCHITECTURE.md retains its full reference content and that_ + +--- + +#### Product area sections coexist with generated documents + +> **Invariant:** Each architecture section in docs/ARCHITECTURE.md has a corresponding generated document in docs-live/product-areas/ covering equivalent content from annotated sources. +> +> **Rationale:** Manual and generated docs must coexist during the transition period. Generated docs prove that annotated sources produce equivalent coverage before manual sections are deprecated. + +**Verified by:** + +- Configuration Architecture section retained and generated doc exists +- Source Systems section retained and annotation product area exists +- Workflow Integration section retained and process product area exists + +--- + +#### Four-Stage Pipeline section retains annotation format examples + +> **Invariant:** The Four-Stage Pipeline section contains annotation format examples (e.g., @libar-docs-shape, extract-shapes) and appears before the Source Systems section in document order. +> +> **Rationale:** Annotation format examples in the pipeline section demonstrate the source-first architecture. Their ordering establishes the conceptual flow: pipeline stages first, then the source systems that feed them. + +**Verified by:** + +- Annotation format examples appear before Source Systems + +--- + +#### Convention extraction produces ARCHITECTURE-CODECS reference document + +> **Invariant:** The ARCHITECTURE-CODECS.md reference document is generated from convention-tagged JSDoc in codec source files and contains structured sections for each codec with output file references. +> +> **Rationale:** Codec documentation must stay synchronized with source code. Convention extraction from JSDoc ensures the reference document reflects actual codec implementations rather than manually maintained descriptions that drift. + +**Verified by:** + +- Session codecs file produces multiple convention sections +- Convention sections include output file references +- ARCHITECTURE-CODECS document has substantial content from all codec files +- Session codec source file has structured JSDoc headings +- Convention rule titles match source heading text in generated output + +--- + +#### Full sections coexist with generated equivalents in docs-live + +> **Invariant:** Major sections of ARCHITECTURE.md (Unified Transformation, Data Flow Diagrams, Quick Reference) are retained alongside their generated equivalents in docs-live/reference/. +> +> **Rationale:** Generated reference documents (ARCHITECTURE-TYPES.md, ARCHITECTURE-CODECS.md) provide exhaustive type and codec listings, but the manual sections offer architectural narrative and design rationale that generated docs cannot yet replicate. + +**Verified by:** + +- Unified Transformation Architecture section retained and ARCHITECTURE-TYPES exists +- Data Flow Diagrams section retained and ARCHITECTURE-TYPES exists +- Quick Reference section retained and ARCHITECTURE-CODECS exists + +--- + +#### MasterDataset shapes appear in ARCHITECTURE-TYPES reference -*arch-index.feature* +> **Invariant:** The ARCHITECTURE-TYPES.md reference document contains core MasterDataset types (MasterDataset, RuntimeMasterDataset, RawDataset) and pipeline types (PipelineOptions, PipelineResult) extracted from shape annotations. +> +> **Rationale:** Type shapes are the structural backbone of the pipeline. Generating their documentation from annotations ensures the reference always matches the actual TypeScript interfaces, eliminating manual drift. + +**Verified by:** + +- Core MasterDataset types appear in ARCHITECTURE-TYPES +- Pipeline types appear in ARCHITECTURE-TYPES reference +- Unified Transformation section has full MasterDataset content + +--- + +#### Pipeline architecture convention appears in generated reference + +> **Invariant:** Source files in the pipeline layer (orchestrator.ts, build-pipeline.ts) carry the pipeline-architecture convention tag, enabling convention extraction into the ARCHITECTURE-TYPES reference document. +> +> **Rationale:** Convention tags on pipeline source files are the mechanism that feeds content into generated reference docs. Without these tags, the architecture reference would have no source material to extract. + +**Verified by:** + +- Orchestrator source file has pipeline-architecture convention tag +- Build-pipeline source file has pipeline-architecture convention tag + +--- + +#### Full ARCHITECTURE.md retains all sections with substantial content + +> **Invariant:** ARCHITECTURE.md retains all major sections (Programmatic Usage, Extending the System, Key Design Patterns) with substantial content and remains under 1700 lines as a comprehensive reference. +> +> **Rationale:** These sections contain editorial content (usage examples, extension guides, design pattern explanations) that cannot be generated from annotations. They remain manual until procedural guide codecs can replicate their depth. + +**Verified by:** + +- Programmatic Usage section exists in ARCHITECTURE.md +- Extending the System section exists in ARCHITECTURE.md +- Key Design Patterns section has design pattern content +- ARCHITECTURE.md is under 1700 lines as full reference + +_architecture-doc-refactoring.feature_ ### Arch Tag Extraction -*As a documentation generator* +_As a documentation generator_ --- @@ -293,12 +417,14 @@ > **Rationale:** Without a registry-defined arch-role tag, the extractor cannot validate role values and diagrams may render invalid roles. **Verified by:** + - arch-role tag exists with enum format - arch-role has required enum values - arch-role has required enum values - Architecture roles classify components for diagram rendering. - Valid roles: command-handler + Architecture roles classify components for diagram rendering. + Valid roles: command-handler + - projection - saga - process-manager @@ -317,11 +443,13 @@ > **Rationale:** Without a registry-defined arch-context tag, bounded context groupings cannot be validated and diagrams may contain arbitrary context names. **Verified by:** + - arch-context tag exists with value format - arch-context tag exists with value format - Context tags group components into bounded context subgraphs. - Format is "value" (free-form string like "orders" + Context tags group components into bounded context subgraphs. + Format is "value" (free-form string like "orders" + - "inventory"). --- @@ -333,12 +461,14 @@ > **Rationale:** Allowing arbitrary layer values would break the fixed Clean Architecture ordering that layered diagrams depend on. **Verified by:** + - arch-layer tag exists with enum format - arch-layer has exactly three values - arch-layer has exactly three values - Layer tags enable layered architecture diagrams. - Valid layers: domain + Layer tags enable layered architecture diagrams. + Valid layers: domain + - application - infrastructure. @@ -351,11 +481,12 @@ > **Rationale:** If arch-role is not extracted, patterns cannot be classified by architectural role and diagram node styling is lost. **Verified by:** + - Extract arch-role projection - Extract arch-role command-handler - Extract arch-role command-handler - The AST parser must extract arch-role alongside other pattern metadata. + The AST parser must extract arch-role alongside other pattern metadata. --- @@ -366,11 +497,12 @@ > **Rationale:** If arch-context is not extracted, component diagrams cannot group patterns into bounded context subgraphs. **Verified by:** + - Extract arch-context orders - Extract arch-context inventory - Extract arch-context inventory - Context values are free-form strings naming the bounded context. + Context values are free-form strings naming the bounded context. --- @@ -381,11 +513,12 @@ > **Rationale:** If arch-layer is not extracted, layered diagrams cannot group patterns into domain/application/infrastructure subgraphs. **Verified by:** + - Extract arch-layer application - Extract arch-layer infrastructure - Extract arch-layer infrastructure - Layer tags classify components by architectural layer. + Layer tags classify components by architectural layer. --- @@ -396,10 +529,11 @@ > **Rationale:** Partial extraction would cause components to be missing from role, context, or layer groupings depending on which tag was dropped. **Verified by:** + - Extract all three arch tags - Extract all three arch tags - Components often have role + context + layer together. + Components often have role + context + layer together. --- @@ -410,16 +544,17 @@ > **Rationale:** Downstream consumers distinguish between "not annotated" (undefined) and "annotated with empty value" to avoid rendering ghost nodes. **Verified by:** + - Missing arch tags are undefined - Missing arch tags are undefined - Components without arch tags should have undefined (not null or empty). + Components without arch tags should have undefined (not null or empty). -*arch-tag-extraction.feature* +_arch-tag-extraction.feature_ ### Business Rules Document Codec -*Tests the BusinessRulesCodec transformation from MasterDataset to RenderableDocument.* +_Tests the BusinessRulesCodec transformation from MasterDataset to RenderableDocument._ --- @@ -430,6 +565,7 @@ > **Rationale:** These structured annotations are the primary content of business rules documentation; losing them silently produces incomplete output. **Verified by:** + - Extracts annotated Rule with Invariant and Rationale - Extracts unannotated Rule without showing not specified @@ -442,6 +578,7 @@ > **Rationale:** Ungrouped or misordered rules make it impossible to find domain-specific constraints or understand their delivery sequence. **Verified by:** + - Groups rules by product area and phase - Orders rules by phase within domain @@ -454,6 +591,7 @@ > **Rationale:** AI context windows have strict token limits; including full detail in summary mode wastes context budget and degrades session quality. **Verified by:** + - Summary mode includes statistics line - Summary mode excludes detailed sections @@ -466,6 +604,7 @@ > **Rationale:** Code blocks in standard mode clutter the overview and push important rule summaries out of view; detailed mode is the opt-in path for full content. **Verified by:** + - Code examples included in detailed mode - Code examples excluded in standard mode @@ -478,6 +617,7 @@ > **Rationale:** Links without file paths are unresolvable, breaking the traceability chain between business rules and their executable specifications. **Verified by:** + - Verification links include file path --- @@ -489,6 +629,7 @@ > **Rationale:** A single monolithic document becomes unnavigable at scale; progressive disclosure lets readers drill into only the product area they need. **Verified by:** + - Detail files are generated per product area - Main document has product area index table with links - Detail files have back-link to main document @@ -502,6 +643,7 @@ > **Rationale:** Blank rule sections are indistinguishable from rendering bugs; explicit placeholders signal intentional incompleteness versus broken extraction. **Verified by:** + - Rule without invariant or description or scenarios shows placeholder - Rule without invariant but with scenarios shows verified-by instead @@ -514,6 +656,7 @@ > **Rationale:** Business rules are compliance-critical content; hiding them behind collapsible sections risks rules being overlooked during review. **Verified by:** + - Features with many rules render flat without collapsible blocks --- @@ -525,6 +668,7 @@ > **Rationale:** Markdown links to local file paths break in every viewer except the local filesystem, producing dead links that erode trust in the documentation. **Verified by:** + - Source file rendered as plain text not link --- @@ -536,6 +680,7 @@ > **Rationale:** Duplicate entries inflate the checklist and mislead reviewers into thinking more verification exists than actually does. **Verified by:** + - Rules with scenarios show verified-by checklist - Duplicate scenario names are deduplicated @@ -548,14 +693,15 @@ > **Rationale:** Raw camelCase names are unreadable in documentation headings, and "Testing" suffixes leak implementation concerns into user-facing output. **Verified by:** + - CamelCase pattern name becomes spaced heading - Testing suffix is stripped from feature names -*business-rules-codec.feature* +_business-rules-codec.feature_ ### Codec Based Generator -*Tests the CodecBasedGenerator which adapts the RenderableDocument Model (RDM)* +_Tests the CodecBasedGenerator which adapts the RenderableDocument Model (RDM)_ --- @@ -566,15 +712,16 @@ > **Rationale:** The adapter pattern enables codec-based rendering to integrate with the existing orchestrator without modifying either side. **Verified by:** + - Generator delegates to codec - Missing MasterDataset returns error - Codec options are passed through -*codec-based.feature* +_codec-based.feature_ ### Component Diagram Generation -*As a documentation generator* +_As a documentation generator_ --- @@ -585,11 +732,12 @@ > **Rationale:** Without subgraph grouping, the visual relationship between components and their bounded context is lost, making the diagram structurally meaningless. **Verified by:** + - Generate subgraphs for bounded contexts - Generate subgraphs for bounded contexts - Patterns with arch-context are grouped into Mermaid subgraphs. - Each bounded context becomes a visual container. + Patterns with arch-context are grouped into Mermaid subgraphs. + Each bounded context becomes a visual container. --- @@ -600,11 +748,12 @@ > **Rationale:** Cross-cutting infrastructure components (event bus, logger) belong to no bounded context but must still appear in the diagram. **Verified by:** + - Shared infrastructure subgraph for context-less patterns - Shared infrastructure subgraph for context-less patterns - Patterns without arch-context are grouped into a - "Shared Infrastructure" subgraph. + Patterns without arch-context are grouped into a + "Shared Infrastructure" subgraph. --- @@ -615,14 +764,15 @@ > **Rationale:** Distinct arrow styles convey dependency semantics visually; conflating them loses architectural information. **Verified by:** + - Arrow styles for relationship types - Arrow styles for relationship types - Arrow styles follow UML conventions: - - uses: solid arrow (-->) - - depends-on: dashed arrow (-.->) - - implements: dotted arrow (..->) - - extends: open arrow (-->>) + Arrow styles follow UML conventions: + - uses: solid arrow (-->) + - depends-on: dashed arrow (-.->) + - implements: dotted arrow (..->) + - extends: open arrow (-->>) --- @@ -633,11 +783,12 @@ > **Rationale:** Rendering an arrow to a non-existent node would produce invalid Mermaid syntax or dangling references. **Verified by:** + - Skip arrows to non-annotated targets - Skip arrows to non-annotated targets - Relationships pointing to non-annotated patterns - are not rendered (target would not exist in diagram). + Relationships pointing to non-annotated patterns + are not rendered (target would not exist in diagram). --- @@ -648,11 +799,12 @@ > **Rationale:** Without summary counts, readers cannot quickly assess diagram scope or detect missing components. **Verified by:** + - Summary section with counts - Summary section with counts - The generated document starts with an overview section - showing component counts and bounded context statistics. + The generated document starts with an overview section + showing component counts and bounded context statistics. --- @@ -663,10 +815,11 @@ > **Rationale:** Without a legend, readers cannot distinguish uses, depends-on, implements, and extends arrows, making relationship semantics ambiguous. **Verified by:** + - Legend section with arrow explanations - Legend section with arrow explanations - The legend explains arrow style meanings for readers. + The legend explains arrow style meanings for readers. --- @@ -677,10 +830,11 @@ > **Rationale:** The inventory provides a searchable, text-based alternative to the visual diagram for tooling and accessibility. **Verified by:** + - Inventory table with component details - Inventory table with component details - The inventory lists all components with their metadata. + The inventory lists all components with their metadata. --- @@ -691,17 +845,19 @@ > **Rationale:** An empty diagram with no explanation would be confusing; guidance helps users onboard to the annotation system. **Verified by:** + - No architecture data message - No architecture data message - If no patterns have architecture annotations + If no patterns have architecture annotations + - the document explains how to add them. -*component-diagram.feature* +_component-diagram.feature_ ### Composite Codec -*Assembles reference documents from multiple codec outputs by* +_Assembles reference documents from multiple codec outputs by_ --- @@ -712,6 +868,7 @@ > **Rationale:** Non-deterministic section ordering would make generated documents unstable across runs, breaking diff-based review workflows. **Verified by:** + - Sections from two codecs appear in order - Three codecs produce sections in array order @@ -724,6 +881,7 @@ > **Rationale:** Without configurable separators, consumers cannot control visual grouping — some documents need clear boundaries between codec outputs while others need seamless flow. **Verified by:** + - Default separator between sections - No separator when disabled @@ -736,6 +894,7 @@ > **Rationale:** Silently dropping colliding keys would lose content without warning, while throwing on collision would prevent composing codecs that intentionally override shared file paths. **Verified by:** + - Non-overlapping files merged - Colliding keys use last-wins @@ -748,6 +907,7 @@ > **Rationale:** Requiring a full codec instance for simple document merging would force unnecessary schema definitions when callers already hold pre-rendered documents. **Verified by:** + - Direct document composition --- @@ -759,13 +919,14 @@ > **Rationale:** Emitting separators around empty sections would produce orphaned dividers in the generated markdown, creating visual noise with no content between them. **Verified by:** + - Empty codec skipped without separator -*composite-codec.feature* +_composite-codec.feature_ ### Content Deduplication -*Multiple sources may extract identical content, leading to* +_Multiple sources may extract identical content, leading to_ --- @@ -776,15 +937,17 @@ > **Rationale:** Fingerprinting enables efficient duplicate detection without full text comparison. **Verified by:** + - Identical content produces same fingerprint - Whitespace differences are normalized - Different content produces different fingerprints - Similar headers with different content are preserved - @acceptance-criteria scenarios below. - Content fingerprints are computed from normalized text + Content fingerprints are computed from normalized text + - ignoring whitespace - differences and minor formatting variations. + differences and minor formatting variations. --- @@ -795,13 +958,14 @@ > **Rationale:** TypeScript sources have richer JSDoc; feature files provide behavioral context. **Verified by:** + - TypeScript source takes priority over feature file - Richer content takes priority when sources equal - Source attribution is added to merged content - @acceptance-criteria scenarios below. - The merge strategy determines which content to keep based on source file - priority and content richness once duplicates are detected. + The merge strategy determines which content to keep based on source file + priority and content richness once duplicates are detected. --- @@ -812,12 +976,13 @@ > **Rationale:** Predictable ordering ensures consistent documentation structure. **Verified by:** + - Original order maintained after dedup - Empty sections after dedup are removed - @acceptance-criteria scenarios below. - The order of sections in the source mapping table is preserved even - after duplicates are removed. + The order of sections in the source mapping table is preserved even + after duplicates are removed. --- @@ -828,17 +993,18 @@ > **Rationale:** All content must be extracted before duplicates can be identified. **Verified by:** + - Deduplication happens in pipeline - @acceptance-criteria scenarios below. - The deduplicator is called after all extractions complete but before - the RenderableDocument is assembled. + The deduplicator is called after all extractions complete but before + the RenderableDocument is assembled. -*content-deduplication.feature* +_content-deduplication.feature_ ### Convention Extractor -*Extracts convention content from MasterDataset decision records* +_Extracts convention content from MasterDataset decision records_ --- @@ -849,6 +1015,7 @@ > **Rationale:** Callers must be able to distinguish "no conventions found" from errors without special-casing nulls or exceptions. **Verified by:** + - Empty convention tags returns empty array - No matching patterns returns empty array @@ -861,6 +1028,7 @@ > **Rationale:** Without tag-based grouping and merging, convention content would be fragmented across duplicates, making downstream rendering unreliable. **Verified by:** + - Single pattern with one convention tag produces one bundle - Pattern with CSV conventions contributes to multiple bundles - Multiple patterns with same convention merge into one bundle @@ -874,6 +1042,7 @@ > **Rationale:** Downstream renderers depend on structured fields to produce consistent documentation; unstructured text would require re-parsing at every consumption point. **Verified by:** + - Invariant and rationale are extracted from rule description - Tables in rule descriptions are extracted as structured data @@ -886,6 +1055,7 @@ > **Rationale:** Losing code examples during extraction would silently degrade generated documentation, removing diagrams and samples authors intended to publish. **Verified by:** + - Mermaid diagram in rule description is extracted as code example - Rule description without code examples has no code examples field @@ -898,18 +1068,20 @@ > **Rationale:** Conventions are defined across both TypeScript and Gherkin; failing to merge them would split a single logical convention into incomplete fragments. **Verified by:** + - TypeScript pattern with heading sections produces multiple rules - TypeScript pattern without headings becomes single rule - TypeScript and Gherkin conventions merge in same bundle - TypeScript pattern with convention but empty description - TypeScript description with tables is extracted correctly +- TypeScript table with escaped union pipes preserves full cell values - TypeScript description with code examples -*convention-extractor.feature* +_convention-extractor.feature_ ### Decision Doc Codec -*Validates the Decision Doc Codec that parses decision documents (ADR/PDR* +_Validates the Decision Doc Codec that parses decision documents (ADR/PDR_ --- @@ -920,6 +1092,7 @@ > **Rationale:** Semantic partitioning produces structured ADR output that follows the standard ADR format — unpartitioned rules would generate a flat, unnavigable document. **Verified by:** + - Partition rules into ADR sections - Non-standard rules go to other category @@ -932,6 +1105,7 @@ > **Rationale:** Language tags enable syntax highlighting in generated markdown code blocks — losing the tag produces unformatted code that is harder to read. **Verified by:** + - Extract single DocString - Extract multiple DocStrings - DocString without language defaults to text @@ -945,6 +1119,7 @@ > **Rationale:** Source mapping tables drive the extraction pipeline — they define which files to read and what content to extract for each decision section. **Verified by:** + - Parse basic source mapping table - No source mapping returns empty @@ -957,6 +1132,7 @@ > **Rationale:** Self-references enable decisions to extract content from their own rules — misdetecting them would trigger file-system lookups for a non-existent "THIS DECISION" file. **Verified by:** + - Detect THIS DECISION marker - Detect THIS DECISION with Rule - Regular file path is not self-reference @@ -972,6 +1148,7 @@ > **Rationale:** Users may write extraction methods in various formats (e.g., "Decision rule description", "extract-shapes") — normalization ensures consistent dispatch regardless of formatting. **Verified by:** + - Normalize Decision rule description - Normalize extract-shapes - Normalize unknown method @@ -985,6 +1162,7 @@ > **Rationale:** Complete parsing validates that all codec features compose correctly — partial parsing could miss interactions between features. **Verified by:** + - Parse complete decision document --- @@ -996,15 +1174,16 @@ > **Rationale:** Partial matching supports flexible cross-references between decisions — requiring exact matches would make references brittle to minor naming changes. **Verified by:** + - Find rule by exact name - Find rule by partial name - Rule not found returns undefined -*decision-doc-codec.feature* +_decision-doc-codec.feature_ ### Decision Doc Generator -*The Decision Doc Generator orchestrates the full documentation generation* +_The Decision Doc Generator orchestrates the full documentation generation_ --- @@ -1015,6 +1194,7 @@ > **Rationale:** Consistent path derivation ensures generated files are predictable and linkable — ad-hoc paths would break cross-document references. **Verified by:** + - Default output paths for pattern - Custom section for compact output - CamelCase pattern converted to kebab-case @@ -1028,6 +1208,7 @@ > **Rationale:** Compact output is designed for AI context windows where token budget is limited — including full descriptions would negate the space savings. **Verified by:** + - Compact output excludes full descriptions - Compact output includes type shapes - Compact output handles empty content @@ -1041,6 +1222,7 @@ > **Rationale:** Detailed output serves as the complete human reference — omitting any section would force readers to consult source files for the full picture. **Verified by:** + - Detailed output includes all sections - Detailed output includes consequences - Detailed output includes DocStrings as code blocks @@ -1054,6 +1236,7 @@ > **Rationale:** Both output levels serve different audiences (AI vs human) — generating them together ensures consistency and eliminates the risk of one becoming stale. **Verified by:** + - Generate both compact and detailed outputs - Pattern name falls back to pattern.name @@ -1066,6 +1249,7 @@ > **Rationale:** Registry registration enables discovery via --list-generators — filtering to source-mapped patterns prevents empty output for patterns without decision metadata. **Verified by:** + - Generator is registered with correct name - Generator filters patterns by source mapping presence - Generator processes patterns with source mappings @@ -1079,14 +1263,15 @@ > **Rationale:** Source mappings are the bridge between decision specs and implementation — unexecuted mappings produce empty sections, while silent missing-file errors hide broken references. **Verified by:** + - Source mappings are executed - Missing source files are reported as validation errors -*decision-doc-generator.feature* +_decision-doc-generator.feature_ ### Dedent Helper -*- DocStrings in Gherkin files have consistent indentation for alignment* +_- DocStrings in Gherkin files have consistent indentation for alignment_ --- @@ -1097,6 +1282,7 @@ > **Rationale:** Mixing tabs and spaces produces incorrect indentation calculations — normalizing first ensures consistent dedent depth. **Verified by:** + - Tab-indented code is properly dedented - Mixed tabs and spaces are normalized @@ -1109,6 +1295,7 @@ > **Rationale:** Counting whitespace-only lines as indented content would inflate the minimum indentation, causing non-empty lines to retain unwanted leading spaces. **Verified by:** + - Empty lines with trailing spaces are preserved - All empty lines returns original text @@ -1121,6 +1308,7 @@ > **Rationale:** Failing or returning empty output on single-line input would break callers that extract individual lines from multi-line DocStrings. **Verified by:** + - Single line with indentation is dedented - Single line without indentation is unchanged @@ -1133,6 +1321,7 @@ > **Rationale:** Stripping Unicode whitespace as indentation would corrupt intentional formatting in source code and documentation content. **Verified by:** + - Non-breaking space is treated as content --- @@ -1144,14 +1333,15 @@ > **Rationale:** Altering relative indentation would break the syntactic structure of extracted code blocks, making them unparseable or semantically incorrect. **Verified by:** + - Nested code blocks preserve relative indentation - Mixed indentation levels are preserved relatively -*dedent.feature* +_dedent.feature_ ### Description Header Normalization -*Pattern descriptions should not create duplicate headers when rendered.* +_Pattern descriptions should not create duplicate headers when rendered._ --- @@ -1162,6 +1352,7 @@ > **Rationale:** The codec already emits a "## Description" header; preserving the source header would create a redundant or conflicting heading hierarchy. **Verified by:** + - Strip single leading markdown header - Strip multiple leading headers - Preserve description without leading header @@ -1175,6 +1366,7 @@ > **Rationale:** Patterns with unusual descriptions (header-only stubs, whitespace padding) are common in early roadmap stages; crashing on these would block documentation generation for the entire dataset. **Verified by:** + - Empty description after stripping headers - Description with only whitespace and headers - Header in middle of description is preserved @@ -1188,6 +1380,7 @@ > **Rationale:** Mid-description headers are intentional structural elements authored by the user; stripping them would silently destroy document structure. **Verified by:** + - Strips h1 header - Strips h2 through h6 headers - Strips leading empty lines before header @@ -1195,11 +1388,11 @@ - Returns empty string for header-only input - Handles null/undefined input -*description-headers.feature* +_description-headers.feature_ ### Description Quality Foundation -*- CamelCase pattern names (e.g., "RemainingWorkEnhancement") are hard to read* +_- CamelCase pattern names (e.g., "RemainingWorkEnhancement") are hard to read_ --- @@ -1210,6 +1403,7 @@ > **Rationale:** Without verification at extraction time, traceability reports would silently include broken references to non-existent behavior files. **Verified by:** + - Behavior file existence verified during extraction - Missing behavior file sets verification to false - Explicit behavior file tag skips verification @@ -1224,6 +1418,7 @@ > **Rationale:** Conflating verified and unverified coverage would overstate test confidence, hiding gaps that should be addressed before release. **Verified by:** + - Traceability shows covered phases with verified behavior files --- @@ -1235,6 +1430,7 @@ > **Rationale:** CamelCase identifiers are unreadable in generated documentation; human-readable names are essential for non-developer consumers of pattern registries. **Verified by:** + - CamelCase pattern names transformed to title case - PascalCase with consecutive caps handled correctly - Falls back to name when no patternName @@ -1249,6 +1445,7 @@ > **Rationale:** Unnumbered criteria are difficult to reference in reviews; unformatted step keywords blend into prose, making scenarios harder to parse visually. **Verified by:** + - PRD shows numbered acceptance criteria with bold keywords - PRD respects includeScenarioSteps flag - PRD shows full Feature description without truncation @@ -1262,15 +1459,16 @@ > **Rationale:** Raw hyphenated tags like "enable-rich-prd" are annotation artifacts; displaying them verbatim in generated docs confuses readers expecting natural language. **Verified by:** + - Hyphenated business value converted to spaces - Business value displayed in Next Actionable table - File extensions not treated as sentence endings -*description-quality-foundation.feature* +_description-quality-foundation.feature_ ### Documentation Orchestrator -*Tests the orchestrator's pattern merging, conflict detection, and generator* +_Tests the orchestrator's pattern merging, conflict detection, and generator_ --- @@ -1281,17 +1479,18 @@ > **Rationale:** Silent merging of conflicting patterns would produce incorrect documentation — fail-fast ensures data integrity across the pipeline. **Verified by:** + - Non-overlapping patterns merge successfully - Orchestrator detects pattern name conflicts - Orchestrator detects pattern name conflicts with status mismatch - Unknown generator name fails gracefully - Partial success when some generators are invalid -*orchestrator.feature* +_orchestrator.feature_ ### Extract Summary -*The extractSummary function transforms multi-line pattern descriptions into* +_The extractSummary function transforms multi-line pattern descriptions into_ --- @@ -1302,6 +1501,7 @@ > **Rationale:** Summaries appear in pattern tables where readers expect grammatically complete text; an ellipsis signals intentional truncation rather than a rendering bug. **Verified by:** + - Complete sentence on single line - Single line without sentence ending gets ellipsis @@ -1314,6 +1514,7 @@ > **Rationale:** Splitting at arbitrary line breaks produces sentence fragments that lose meaning; combining until a natural boundary preserves semantic completeness. **Verified by:** + - Two lines combine into complete sentence - Combines lines up to sentence boundary within limit - Long multi-line text truncates when exceeds limit @@ -1328,6 +1529,7 @@ > **Rationale:** Sentence-boundary truncation preserves semantic completeness; word-boundary fallback avoids mid-word breaks. **Verified by:** + - Long text truncates at sentence boundary within limit - Long text without sentence boundary truncates at word with ellipsis @@ -1340,6 +1542,7 @@ > **Rationale:** Tautological opening lines waste the limited summary space without adding information. **Verified by:** + - Skips pattern name as first line - Skips section header labels - Skips multiple header patterns @@ -1353,17 +1556,73 @@ > **Rationale:** Summary extraction runs on every pattern in the dataset; an unhandled edge case would crash the entire documentation generation pipeline. **Verified by:** + - Empty description returns empty string - Markdown headers are stripped - Bold markdown is stripped - Multiple sentence endings - takes first complete sentence - Question mark as sentence ending -*extract-summary.feature* +_extract-summary.feature_ + +### Generated Doc Quality Tests + +_Tests for the four quality fixes in GeneratedDocQuality (Phase 38):_ + +--- + +#### Behavior-specs renderer does not duplicate convention table content + +> **Invariant:** Convention tables appear exactly once in the output — in the convention section. The behavior-specs section shows only metadata. +> +> **Rationale:** DD-4: Duplicate tables waste 500+ lines and agent context tokens. + +**Verified by:** + +- Convention rule table appears exactly once in generated output +- Behavior-specs show rule metadata without tables + +--- + +#### ARCHITECTURE-TYPES leads with type definitions + +> **Invariant:** When shapesFirst is true, shapes render before conventions. +> +> **Rationale:** ARCHITECTURE-TYPES.md should open with type definitions, not orchestrator prose. + +**Verified by:** + +- Shapes section appears before conventions when shapesFirst is true + +--- + +#### Product area docs have a generated table of contents + +> **Invariant:** Product area docs with 3+ H2 headings include a Contents section with anchor links. +> +> **Rationale:** Large product area docs need browser-navigable TOC for human developers. + +**Verified by:** + +- Product area doc with multiple sections gets a TOC + +--- + +#### Generation compact is self-sufficient + +> **Invariant:** The Generation compact contains codec inventory and pipeline summary at 4+ KB. +> +> **Rationale:** DD-2: A 1.4 KB compact for the largest area means agents have no usable summary. + +**Verified by:** + +- Generation compact contains enriched content + +_generated-doc-quality.feature_ ### Generator Registry -*Tests the GeneratorRegistry registration, lookup, and listing capabilities.* +_Tests the GeneratorRegistry registration, lookup, and listing capabilities._ --- @@ -1374,17 +1633,18 @@ > **Rationale:** Allowing duplicate names would silently overwrite an existing generator, causing previously registered behavior to disappear without warning. **Verified by:** + - Register generator with unique name - Duplicate registration throws error - Get registered generator - Get unknown generator returns undefined - Available returns sorted list -*registry.feature* +_registry.feature_ ### Implementation Link Path Normalization -*Links to implementation files in generated pattern documents should have* +_Links to implementation files in generated pattern documents should have_ --- @@ -1395,6 +1655,7 @@ > **Rationale:** Generated links are relative to the output directory; repository prefixes produce broken paths. **Verified by:** + - Strip libar-platform prefix from implementation paths - Strip monorepo prefix from implementation paths - Preserve paths without repository prefix @@ -1408,6 +1669,7 @@ > **Rationale:** A single un-normalized link in a multi-implementation pattern produces a broken reference that undermines trust in the entire generated document. **Verified by:** + - Multiple implementations with mixed prefixes --- @@ -1419,16 +1681,17 @@ > **Rationale:** Over-stripping would corrupt legitimate path segments that happen to match a prefix name, producing silent broken links. **Verified by:** + - Strips libar-platform/ prefix - Strips monorepo/ prefix - Returns unchanged path without known prefix - Only strips prefix at start of path -*implementation-links.feature* +_implementation-links.feature_ ### Layered Diagram Generation -*As a documentation generator* +_As a documentation generator_ --- @@ -1439,11 +1702,12 @@ > **Rationale:** Without layer subgraphs, the Clean Architecture boundary between domain, application, and infrastructure is not visually enforced. **Verified by:** + - Generate subgraphs for each layer - Generate subgraphs for each layer - Patterns with arch-layer are grouped into Mermaid subgraphs. - Each layer becomes a visual container. + Patterns with arch-layer are grouped into Mermaid subgraphs. + Each layer becomes a visual container. --- @@ -1454,14 +1718,16 @@ > **Rationale:** The visual order reflects the dependency rule where outer layers depend on inner layers; reversing it would misrepresent the architecture. **Verified by:** + - Layers render in correct order - Layers render in correct order - The layer subgraphs are rendered in Clean Architecture order: - domain at top + The layer subgraphs are rendered in Clean Architecture order: + domain at top + - then application - then infrastructure at bottom. - This reflects the dependency rule: outer layers depend on inner layers. + This reflects the dependency rule: outer layers depend on inner layers. --- @@ -1472,12 +1738,14 @@ > **Rationale:** Layered diagrams group by layer, not context, so the context label is the only way to identify which bounded context a node belongs to. **Verified by:** + - Nodes include context labels - Nodes include context labels - Unlike component diagrams which group by context + Unlike component diagrams which group by context + - layered diagrams - include the context as a label in each node name. + include the context as a label in each node name. --- @@ -1488,11 +1756,12 @@ > **Rationale:** Omitting unlayered patterns would silently hide architectural components; the "Other" group makes their missing classification visible. **Verified by:** + - Unlayered patterns in Other subgraph - Unlayered patterns in Other subgraph - Patterns that have arch-role or arch-context but no arch-layer - are grouped into an "Other" subgraph. + Patterns that have arch-role or arch-context but no arch-layer + are grouped into an "Other" subgraph. --- @@ -1503,17 +1772,148 @@ > **Rationale:** Without summary counts, readers cannot assess diagram completeness or detect missing annotated sources. **Verified by:** + - Summary section for layered view - Summary section for layered view - The generated document starts with an overview section - specific to layered architecture visualization. + The generated document starts with an overview section + specific to layered architecture visualization. + +_layered-diagram.feature_ + +### Load Preamble Parser + +_Preamble content authored as inline TypeScript SectionBlock[] literals is_ + +--- + +#### Headings are parsed into HeadingBlock + +> **Invariant:** Lines starting with 1-6 hash characters followed by a space produce HeadingBlock with the correct level and text. +> +> **Rationale:** Headings are the primary structural element in preamble markdown and must map exactly to HeadingBlock level values. + +**Verified by:** + +- Single heading is parsed +- All heading levels are parsed correctly + +--- + +#### Paragraphs are parsed into ParagraphBlock + +> **Invariant:** Consecutive non-empty, non-construct lines produce a single ParagraphBlock with lines joined by spaces. +> +> **Rationale:** Multi-line paragraphs in markdown are a single logical block separated by blank lines. + +**Verified by:** + +- Single line paragraph +- Multi-line paragraph joined with space + +--- + +#### Separators are parsed into SeparatorBlock + +> **Invariant:** Lines matching exactly three or more dashes, asterisks, or underscores produce SeparatorBlock. +> +> **Rationale:** Horizontal rules serve as visual separators in preamble content and must be faithfully represented. + +**Verified by:** + +- Triple dash separator + +--- + +#### Tables are parsed into TableBlock + +> **Invariant:** A line starting with pipe followed by a separator row produces TableBlock with columns from the header and rows from subsequent pipe-delimited lines. +> +> **Rationale:** Tables are heavily used in preamble content for structured reference data and must preserve column names and cell values exactly. + +**Verified by:** + +- Simple table with header and rows + +--- + +#### Unordered lists are parsed into ListBlock + +> **Invariant:** Lines starting with dash-space or asterisk-space produce ListBlock with ordered=false and string items. +> +> **Rationale:** Unordered lists are common in preamble content for enumerating capabilities or constraints. + +**Verified by:** + +- Dash list items +- GFM checkbox list items + +--- + +#### Ordered lists are parsed into ListBlock + +> **Invariant:** Lines starting with a digit followed by period-space produce ListBlock with ordered=true. +> +> **Rationale:** Ordered lists represent sequential steps in procedural guides and must preserve ordering semantics. + +**Verified by:** + +- Numbered list items + +--- + +#### Code blocks are parsed into CodeBlock + +> **Invariant:** Fenced code blocks with a language info string produce CodeBlock with the language and content fields. +> +> **Rationale:** Code examples in preamble content must preserve the language annotation for syntax highlighting in generated docs. + +**Verified by:** + +- Code block with language +- Empty code block + +--- -*layered-diagram.feature* +#### Mermaid blocks are parsed into MermaidBlock + +> **Invariant:** Code fences with the info string "mermaid" produce MermaidBlock instead of CodeBlock. +> +> **Rationale:** Mermaid diagrams have a dedicated SectionBlock type for specialized rendering in generated docs. + +**Verified by:** + +- Mermaid diagram block + +--- + +#### Mixed content produces correct block sequence + +> **Invariant:** A markdown document with multiple construct types produces blocks in document order with correct types. +> +> **Rationale:** Preamble files combine headings, paragraphs, code blocks, and tables in sequence. The parser must handle transitions between all state machine states correctly. + +**Verified by:** + +- Mixed content in sequence + +--- + +#### Bold and inline formatting is preserved in paragraphs + +> **Invariant:** Inline markdown formatting such as bold, italic, and code spans are preserved as-is in ParagraphBlock text. +> +> **Rationale:** The parser produces structural blocks. Inline formatting is the responsibility of the markdown renderer, not the block parser. + +**Verified by:** + +- Bold text preserved in paragraph + +_load-preamble.feature_ ### Mermaid Relationship Rendering -*Tests for rendering all relationship types in Mermaid dependency graphs* +_Tests for rendering all relationship types in Mermaid dependency graphs_ --- @@ -1524,6 +1924,7 @@ > **Rationale:** Identical arrow styles would make relationship semantics indistinguishable in generated diagrams. **Verified by:** + - Uses relationships render as solid arrows - Depends-on relationships render as dashed arrows - Implements relationships render as dotted arrows @@ -1538,6 +1939,7 @@ > **Rationale:** Unsanitized names containing dots, hyphens, or spaces produce invalid Mermaid syntax that fails to render. **Verified by:** + - Special characters are replaced --- @@ -1549,13 +1951,14 @@ > **Rationale:** Splitting relationship types into separate graphs would fragment the dependency picture and hide cross-type interactions. **Verified by:** + - Complete dependency graph with all relationship types -*mermaid-rendering.feature* +_mermaid-rendering.feature_ ### Patterns Codec -*- Need to generate a comprehensive pattern registry from extracted patterns* +_- Need to generate a comprehensive pattern registry from extracted patterns_ --- @@ -1566,6 +1969,7 @@ > **Rationale:** The PATTERNS.md is the primary entry point for understanding project scope; incomplete structure would leave consumers without context. **Verified by:** + - Decode empty dataset - Decode dataset with patterns - document structure - Progress summary shows correct counts @@ -1579,6 +1983,7 @@ > **Rationale:** Consistent ordering allows quick scanning of project progress; completed patterns at top confirm done work, while roadmap items at bottom show remaining scope. **Verified by:** + - Pattern table includes all patterns - Pattern table is sorted by status then name @@ -1591,6 +1996,7 @@ > **Rationale:** Without category grouping, consumers must scan the entire flat pattern list to find domain-relevant patterns; filtering avoids noise in focused documentation. **Verified by:** + - Category sections with pattern lists - Filter to specific categories @@ -1603,6 +2009,7 @@ > **Rationale:** Dependency relationships are invisible in flat pattern lists; the graph reveals implementation ordering and coupling that affects planning decisions. **Verified by:** + - Dependency graph included when relationships exist - No dependency graph when no relationships - Dependency graph disabled by option @@ -1616,15 +2023,16 @@ > **Rationale:** Detail files enable deep-linking into specific patterns from the main registry while keeping the index document scannable. **Verified by:** + - Generate individual pattern files when enabled - No detail files when disabled - Individual pattern file contains full details -*patterns-codec.feature* +_patterns-codec.feature_ ### Planning Codec -*- Need to generate planning checklists, session plans, and findings documents from patterns* +_- Need to generate planning checklists, session plans, and findings documents from patterns_ --- @@ -1635,6 +2043,7 @@ > **Rationale:** Implementation sessions fail without upfront preparation — the checklist surfaces blockers before work begins. **Verified by:** + - No actionable phases produces empty message - Summary shows phases to plan count - Pre-planning questions section @@ -1654,6 +2063,7 @@ > **Rationale:** A structured implementation plan ensures all deliverables and acceptance criteria are visible before coding starts. **Verified by:** + - No phases to plan produces empty message - Summary shows status counts - Implementation approach from useCases @@ -1672,6 +2082,7 @@ > **Rationale:** Retrospective findings drive continuous improvement — categorization enables prioritized follow-up across sessions. **Verified by:** + - No findings produces empty message - Summary shows finding type counts - Gaps section @@ -1684,11 +2095,11 @@ - showSourcePhase option enabled - showSourcePhase option disabled -*planning-codecs.feature* +_planning-codecs.feature_ ### Poc Integration -*End-to-end integration tests that exercise the full documentation generation* +_End-to-end integration tests that exercise the full documentation generation_ --- @@ -1699,6 +2110,7 @@ > **Rationale:** Integration testing against the actual POC document validates that the codec works with real-world content, not just synthetic test data. **Verified by:** + - Load actual POC decision document - Source mappings include all extraction types @@ -1711,6 +2123,7 @@ > **Rationale:** Self-references are the most common extraction type in decision docs — they must work correctly for the POC to demonstrate the end-to-end pipeline. **Verified by:** + - Extract Context rule from THIS DECISION - Extract Decision rule from THIS DECISION - Extract DocStrings from THIS DECISION @@ -1724,6 +2137,7 @@ > **Rationale:** TypeScript extraction is the primary mechanism for pulling implementation details into decision docs — it must work with actual project files. **Verified by:** + - Extract shapes from types.ts - Extract shapes from decider.ts - Extract createViolation patterns from decider.ts @@ -1737,6 +2151,7 @@ > **Rationale:** Behavior spec extraction bridges decision documents to executable specifications — incorrect extraction would misrepresent the verified behavior. **Verified by:** + - Extract Rule blocks from process-guard.feature - Extract Scenario Outline Examples from process-guard-linter.feature @@ -1749,6 +2164,7 @@ > **Rationale:** CLI documentation often lives in JSDoc comments — extracting them into decision docs avoids duplicating CLI usage information manually. **Verified by:** + - Extract JSDoc from lint-process.ts --- @@ -1760,6 +2176,7 @@ > **Rationale:** End-to-end execution validates that all extraction types work with real files — a single failing mapping would produce incomplete decision documentation. **Verified by:** + - Execute all 11 source mappings from POC --- @@ -1771,6 +2188,7 @@ > **Rationale:** Compact output is the AI-facing artifact — verifying it against the real POC ensures the format serves its purpose of providing concise decision context. **Verified by:** + - Generate compact output from POC - Compact output contains essential sections @@ -1783,6 +2201,7 @@ > **Rationale:** Detailed output is the human-facing artifact — verifying it against the real POC ensures no content is lost in the generation pipeline. **Verified by:** + - Generate detailed output from POC - Detailed output contains full content @@ -1795,14 +2214,15 @@ > **Rationale:** Quality assertions catch regressions in output formatting — structural drift in generated documents would degrade their usefulness as references. **Verified by:** + - Compact output matches target structure - Validation rules are complete in output -*poc-integration.feature* +_poc-integration.feature_ ### Pr Changes Codec Options -*- Need to generate PR-specific documentation from patterns* +_- Need to generate PR-specific documentation from patterns_ --- @@ -1813,6 +2233,7 @@ > **Rationale:** A context-sensitive checklist prevents reviewers from missing state-specific concerns (e.g., verifying completed patterns still work, or that dependencies are satisfied) that a static checklist would not cover. **Verified by:** + - Review checklist generated with standard items - Review checklist includes completed patterns item when applicable - Review checklist includes active work item when applicable @@ -1829,6 +2250,7 @@ > **Rationale:** Dependency visibility in PR reviews prevents merging changes that break upstream or downstream patterns, which would otherwise only surface during integration. **Verified by:** + - Dependencies section shows depends on relationships - Dependencies section shows enables relationships - No dependencies section when patterns have no dependencies @@ -1843,6 +2265,7 @@ > **Rationale:** Filtering by changed files scopes the PR document to only the patterns actually touched, preventing reviewers from wading through unrelated patterns. **Verified by:** + - Patterns filtered by changedFiles match - changedFiles filter matches partial paths @@ -1855,6 +2278,7 @@ > **Rationale:** Release filtering isolates the patterns scheduled for a specific version, enabling targeted release reviews without noise from other versions' deliverables. **Verified by:** + - Patterns filtered by release version --- @@ -1866,6 +2290,7 @@ > **Rationale:** OR logic maximizes PR coverage — a change may affect files not yet assigned to a release, or a release may include patterns from unchanged files. **Verified by:** + - Combined filters match patterns meeting either criterion - Patterns matching both criteria are not duplicated @@ -1878,14 +2303,15 @@ > **Rationale:** PR changes reflect work that is in progress or done — roadmap and deferred patterns have no code changes to review. **Verified by:** + - Roadmap patterns are excluded - Deferred patterns are excluded -*pr-changes-codec-options.feature* +_pr-changes-codec-options.feature_ ### Pr Changes Codec Rendering -*- Need to generate PR-specific documentation from patterns* +_- Need to generate PR-specific documentation from patterns_ --- @@ -1896,6 +2322,7 @@ > **Rationale:** Reviewers need to distinguish "nothing matched" from "codec error" and understand why no patterns appear. **Verified by:** + - No changes when no patterns match changedFiles filter - No changes when no patterns match releaseFilter - No changes with combined filters when nothing matches @@ -1909,6 +2336,7 @@ > **Rationale:** Without a summary, reviewers must scan the entire document to understand the scope and filtering context of the PR changes. **Verified by:** + - Summary section shows pattern counts - Summary shows release tag when releaseFilter is set - Summary shows files filter count when changedFiles is set @@ -1922,6 +2350,7 @@ > **Rationale:** Phase grouping aligns PR changes with the delivery roadmap, letting reviewers verify that changes belong to the expected implementation phase. **Verified by:** + - Changes grouped by phase with default sortBy - Pattern details shown within phase groups @@ -1934,6 +2363,7 @@ > **Rationale:** Priority grouping lets reviewers focus on high-impact changes first, ensuring critical patterns receive the most review attention. **Verified by:** + - Changes grouped by priority - Priority groups show correct patterns @@ -1946,6 +2376,7 @@ > **Rationale:** Workflow sorting presents patterns in review order without structural grouping, suited for quick PR reviews. **Verified by:** + - Flat changes list with workflow sort --- @@ -1957,6 +2388,7 @@ > **Rationale:** Metadata and description provide the context reviewers need to evaluate whether a pattern's implementation aligns with its stated purpose and delivery status. **Verified by:** + - Pattern detail shows metadata table - Pattern detail shows business value when available - Pattern detail shows description @@ -1970,6 +2402,7 @@ > **Rationale:** Deliverables add bulk to the PR document; gating them behind a flag keeps default output concise, while release filtering prevents reviewers from seeing unrelated work items. **Verified by:** + - Deliverables shown when patterns have deliverables - Deliverables filtered by release when releaseFilter is set - No deliverables section when includeDeliverables is disabled @@ -1983,6 +2416,7 @@ > **Rationale:** Acceptance criteria give reviewers a concrete checklist to verify that the PR's implementation satisfies the behavioral requirements defined in the spec. **Verified by:** + - Acceptance criteria rendered when patterns have scenarios - Acceptance criteria shows scenario steps @@ -1995,14 +2429,15 @@ > **Rationale:** Business rules surface domain invariants directly in the PR review, ensuring reviewers can verify that implementation changes respect the documented constraints. **Verified by:** + - Business rules rendered when patterns have rules - Business rules show rule names and verification info -*pr-changes-codec-rendering.feature* +_pr-changes-codec-rendering.feature_ ### Pr Changes Generation -*- PR descriptions are manually written, often incomplete or inconsistent* +_- PR descriptions are manually written, often incomplete or inconsistent_ --- @@ -2013,6 +2448,7 @@ > **Rationale:** Including unrelated releases or unstarted roadmap items in a PR description misleads reviewers about the scope of actual changes. **Verified by:** + - Filter phases by specific release version - Show all active and completed phases when no releaseFilter - Active phases with matching deliverables are included @@ -2027,6 +2463,7 @@ > **Rationale:** Without phase grouping, reviewers cannot distinguish which changes belong to which delivery phase, making incremental review impossible. **Verified by:** + - Patterns grouped by phase number --- @@ -2038,6 +2475,7 @@ > **Rationale:** Without a summary, reviewers must read the entire document to understand the PR's scope; the release tag anchors the summary to a specific version. **Verified by:** + - Summary shows pattern counts in table format - Summary shows release tag when filtering @@ -2050,6 +2488,7 @@ > **Rationale:** Hiding deliverables forces reviewers to cross-reference feature files to verify completion; inline display makes review self-contained. **Verified by:** + - Deliverables shown inline with patterns - Deliverables show release tags @@ -2062,6 +2501,7 @@ > **Rationale:** Omitting the checklist means quality gates depend on reviewer memory; a consistent checklist ensures no standard verification step is skipped. **Verified by:** + - Review checklist includes standard code quality items - Review checklist includes completed pattern verification @@ -2074,6 +2514,7 @@ > **Rationale:** Hidden dependencies cause merge-order mistakes and broken builds; surfacing them in the PR lets reviewers verify prerequisite work is complete. **Verified by:** + - Dependencies shows what patterns enable - Dependencies shows what patterns depend on @@ -2086,6 +2527,7 @@ > **Rationale:** Not all consumers need business value context; making it opt-in keeps the default output concise for technical reviewers. **Verified by:** + - Pattern metadata includes business value when enabled - Business value can be excluded @@ -2098,6 +2540,7 @@ > **Rationale:** Non-deterministic ordering produces diff noise between regenerations, making it impossible to tell if content actually changed. **Verified by:** + - Phases sorted by phase number - Phases sorted by priority @@ -2110,6 +2553,7 @@ > **Rationale:** Crashing on incomplete data prevents PR generation entirely; graceful degradation ensures output is always available even with partial inputs. **Verified by:** + - No matching phases produces no changes message - Patterns without deliverables still display - Patterns without phase show in phase 0 group @@ -2123,13 +2567,14 @@ > **Rationale:** Showing all deliverables regardless of release tag pollutes the PR with unrelated work, obscuring what actually shipped in the target release. **Verified by:** + - Mixed releases within single phase shows only matching deliverables -*pr-changes-generation.feature* +_pr-changes-generation.feature_ ### Pr Changes Options -*Tests the PrChangesCodec filtering capabilities for generating PR-scoped* +_Tests the PrChangesCodec filtering capabilities for generating PR-scoped_ --- @@ -2140,15 +2585,16 @@ > **Rationale:** PR-scoped documentation must reflect exactly what changed, avoiding noise from unrelated patterns. **Verified by:** + - PR changes filters to explicit file list - PR changes filters by release version - Combined filters use OR logic -*pr-changes-options.feature* +_pr-changes-options.feature_ ### Prd Implementation Section -*Tests the Implementations section rendering in pattern documents.* +_Tests the Implementations section rendering in pattern documents._ --- @@ -2159,6 +2605,7 @@ > **Rationale:** Implementation discovery relies on tag-based linking — missing entries break traceability between specs and code. **Verified by:** + - Implementations section renders with file links - Implementation includes description when available @@ -2171,6 +2618,7 @@ > **Rationale:** Deterministic ordering ensures stable document output across regeneration runs. **Verified by:** + - Multiple implementations sorted by file path --- @@ -2182,6 +2630,7 @@ > **Rationale:** Rendering an empty Implementations section misleads readers into thinking implementations were expected but are missing, rather than simply not applicable. **Verified by:** + - No implementations section when none exist --- @@ -2193,13 +2642,14 @@ > **Rationale:** Absolute paths break when documentation is viewed from different locations; relative paths ensure portability. **Verified by:** + - Links are relative from patterns directory -*prd-implementation-section.feature* +_prd-implementation-section.feature_ ### Reference Codec Core -*Parameterized codec factory that creates reference document codecs* +_Parameterized codec factory that creates reference document codecs_ --- @@ -2210,6 +2660,7 @@ > **Rationale:** Consumers rely on a consistent document structure; a missing or null document would cause rendering failures downstream. **Verified by:** + - Codec with no matching content produces fallback message --- @@ -2221,6 +2672,7 @@ > **Rationale:** Conventions define project-wide constraints; losing their structure in generated docs would make them unenforceable and undiscoverable. **Verified by:** + - Convention rules appear as H2 headings with content - Convention tables are rendered in the document @@ -2233,6 +2685,7 @@ > **Rationale:** AI session contexts have strict token budgets; uncontrolled output density wastes context window and degrades session quality. **Verified by:** + - Summary level omits narrative and rationale - Detailed level includes rationale and verified-by @@ -2245,6 +2698,7 @@ > **Rationale:** Mixing unrelated categories into a single behavior section would produce misleading documentation that conflates distinct concerns. **Verified by:** + - Behavior-tagged patterns appear in a Behavior Specifications section --- @@ -2256,6 +2710,7 @@ > **Rationale:** Including shapes from unrelated source paths would pollute the API Types section with irrelevant type definitions, breaking the scoped documentation contract. **Verified by:** + - Shapes appear when source file matches shapeSources glob - Summary level shows shapes as a compact table - No shapes when source file does not match glob @@ -2269,6 +2724,7 @@ > **Rationale:** Splitting conventions and behaviors into separate documents would force consumers to cross-reference multiple files, losing the unified view of a product area. **Verified by:** + - Both convention and behavior sections appear when data exists --- @@ -2280,6 +2736,7 @@ > **Rationale:** AD-5 establishes a consistent reading flow (rules, then types, then specs); violating this order would confuse readers who expect a stable document structure. **Verified by:** + - Convention headings appear before shapes before behaviors --- @@ -2291,14 +2748,15 @@ > **Rationale:** Mermaid diagrams are visual aids that require rendering support; emitting them as plain text would produce unreadable output, and including them in summaries wastes token budget. **Verified by:** + - Convention with mermaid content produces mermaid block in output - Summary level omits convention code examples -*reference-codec-core.feature* +_reference-codec-core.feature_ ### Reference Codec Detail Rendering -*Standard detail level behavior, deep behavior rendering with structured* +_Standard detail level behavior, deep behavior rendering with structured_ --- @@ -2309,6 +2767,7 @@ > **Rationale:** Progressive disclosure prevents information overload at the standard level while ensuring readers who need deeper justification can access it at the detailed level. **Verified by:** + - Standard level includes narrative but omits rationale --- @@ -2320,6 +2779,7 @@ > **Rationale:** Structured annotations are the primary mechanism for surfacing business rules from Gherkin sources; inconsistent rendering across detail levels would produce misleading or incomplete documentation. **Verified by:** + - Detailed level renders structured behavior rules - Standard level renders behavior rules without rationale - Summary level shows behavior rules as truncated table @@ -2334,6 +2794,7 @@ > **Rationale:** JSDoc prose provides essential context for API types; omitting it would force readers to open source files to understand a shape's purpose, undermining the generated documentation's self-sufficiency. **Verified by:** + - Standard level includes JSDoc in code blocks - Detailed level includes JSDoc in code block and property table - Shapes without JSDoc render code blocks only @@ -2347,6 +2808,7 @@ > **Rationale:** Throws documentation is diagnostic detail that clutters standard output; separating it into detailed level keeps standard output focused on the function's contract while preserving full error documentation for consumers who need it. **Verified by:** + - Detailed level renders param table for function shapes - Detailed level renders returns and throws documentation - Standard level renders param table without throws @@ -2361,6 +2823,7 @@ > **Rationale:** Behavior sections with many rules produce substantial content at detailed level. Collapsible blocks enable progressive disclosure so readers can expand only the rules they need. **Verified by:** + - Behavior pattern with many rules uses collapsible blocks at detailed level - Behavior pattern with few rules does not use collapsible blocks - Summary level never produces collapsible blocks @@ -2377,6 +2840,7 @@ > **Rationale:** Cross-reference links enable readers to navigate from generated documentation to the annotated source files, closing the loop between generated docs and the single source of truth. **Verified by:** + - Behavior pattern includes source file link-out at detailed level - Standard level includes source file link-out - Summary level omits link-out blocks @@ -2393,15 +2857,16 @@ > **Rationale:** Cross-cutting patterns (e.g., shared utilities, common validators) belong in multiple reference documents; without include-tag routing, these patterns would only appear in their home category, leaving dependent documents incomplete. **Verified by:** + - Include-tagged pattern appears in behavior section - Include-tagged pattern is additive with category-selected patterns - Pattern without matching include tag is excluded -*reference-codec-detail-rendering.feature* +_reference-codec-detail-rendering.feature_ ### Reference Codec Diagram -*Scoped diagram generation from diagramScope and diagramScopes config,* +_Scoped diagram generation from diagramScope and diagramScopes config,_ --- @@ -2412,6 +2877,7 @@ > **Rationale:** Without filter-driven scoping, diagrams would include all patterns regardless of relevance, producing unreadable visualizations that obscure architectural boundaries. **Verified by:** + - Config with diagramScope produces mermaid block at detailed level - Neighbor patterns appear in diagram with distinct style - include filter selects patterns by include tag membership @@ -2425,6 +2891,19 @@ --- +#### Hardcoded diagram sources render deterministic output + +> **Invariant:** Hardcoded diagram sources render without relationship-scoping input and emit stable, source-specific Mermaid content. +> +> **Rationale:** Domain diagrams such as pipeline and MasterDataset fan-out encode canonical architecture views that should not depend on ad-hoc test dataset shape. + +**Verified by:** + +- master-dataset-views source produces MasterDataset fan-out diagram +- master-dataset-views source renders expected fan-out nodes + +--- + #### Multiple diagram scopes produce multiple mermaid blocks > **Invariant:** Each entry in the diagramScopes array produces an independent Mermaid block with its own title and direction, and legacy singular diagramScope remains supported as a fallback. @@ -2432,15 +2911,16 @@ > **Rationale:** Product areas require multiple architectural views (e.g., system overview and data flow) from a single configuration, and breaking backward compatibility with the singular diagramScope would silently remove diagrams from existing consumers. **Verified by:** + - Config with diagramScopes array produces multiple diagrams - Diagram direction is reflected in mermaid output - Legacy diagramScope still works when diagramScopes is absent -*reference-codec-diagrams.feature* +_reference-codec-diagrams.feature_ ### Reference Codec Diagram Type -*Diagram type controls Mermaid output format including flowchart,* +_Diagram type controls Mermaid output format including flowchart,_ --- @@ -2451,6 +2931,7 @@ > **Rationale:** Flowcharts cannot naturally express event flows (sequence), FSM visualization (state), or temporal ordering. Multiple diagram types unlock richer architectural documentation from the same relationship data. **Verified by:** + - Default diagramType produces flowchart - Sequence diagram renders participant-message format - State diagram renders state transitions @@ -2470,6 +2951,7 @@ > **Rationale:** Unlabeled edges are ambiguous without consulting a legend. Custom node shapes make archRole visually distinguishable without color reliance, improving accessibility and scanability. **Verified by:** + - Relationship edges display type labels by default - Edge labels can be disabled for compact diagrams - archRole controls Mermaid node shape @@ -2479,11 +2961,11 @@ - archRole controls node shape - Unknown archRole falls back to rectangle -*reference-codec-diagram-types.feature* +_reference-codec-diagram-types.feature_ ### Reference Generator -*Registers reference document generators from project config.* +_Registers reference document generators from project config._ --- @@ -2494,6 +2976,7 @@ > **Rationale:** The count is deterministic from config — any mismatch indicates a registration bug that would silently drop generated documents. **Verified by:** + - Generators are registered from configs plus meta-generators --- @@ -2505,6 +2988,7 @@ > **Rationale:** Product area docs are rendered into per-area subdirectories while standalone references go to the root output. **Verified by:** + - Product area meta-generator is registered --- @@ -2516,8 +3000,10 @@ > **Rationale:** Consistent naming enables programmatic discovery and distinguishes human-readable from AI-optimized outputs. **Verified by:** + - Detailed generator has name ending in "-reference" - Summary generator has name ending in "-reference-claude" +- Architecture-types generators are registered --- @@ -2528,14 +3014,16 @@ > **Rationale:** A generator that produces empty output wastes a pipeline slot and creates confusion when expected docs are missing. **Verified by:** + - Product area generator with matching data produces non-empty output - Product area generator with no patterns still produces intro +- ARCHITECTURE-TYPES generator produces shapes and convention content -*reference-generators.feature* +_reference-generators.feature_ ### Remaining Work Enhancement -*- Flat phase lists make it hard to identify what to work on next* +_- Flat phase lists make it hard to identify what to work on next_ --- @@ -2546,6 +3034,7 @@ > **Rationale:** Without priority sorting, critical work gets buried under low-priority items, delaying urgent deliverables. **Verified by:** + - Next Actionable sorted by priority - Undefined priority sorts last - Priority icons displayed in table @@ -2559,6 +3048,7 @@ > **Rationale:** Comparing raw strings like "2h" and "3d" lexicographically produces incorrect ordering; normalization to hours ensures consistent comparison. **Verified by:** + - Phases sorted by effort ascending - Effort parsing handles hours - Effort parsing handles days @@ -2574,6 +3064,7 @@ > **Rationale:** Flat lists obscure time-based planning; grouping by quarter lets planners see what is committed per period and what remains unscheduled. **Verified by:** + - Planned phases grouped by quarter - Quarters sorted chronologically @@ -2586,6 +3077,7 @@ > **Rationale:** Mixing priority levels in a flat list forces readers to visually scan for urgency; grouping by priority makes triage immediate. **Verified by:** + - Planned phases grouped by priority --- @@ -2597,6 +3089,7 @@ > **Rationale:** Displaying hundreds of phases in the summary overwhelms planners; progressive disclosure keeps the summary scannable while preserving access to the full backlog. **Verified by:** + - Large backlog uses progressive disclosure - Moderate backlog shows count without link @@ -2609,6 +3102,7 @@ > **Rationale:** Blank or errored output when the backlog is empty confuses users into thinking the generator is broken rather than reflecting a genuinely empty state. **Verified by:** + - Empty backlog handling - All phases blocked @@ -2621,14 +3115,15 @@ > **Rationale:** Changing default behavior would break existing consumers that rely on phase-number ordering without specifying options. **Verified by:** + - Default sorting is by phase number - Default grouping is none (flat list) -*remaining-work-enhancement.feature* +_remaining-work-enhancement.feature_ ### Remaining Work Summary Accuracy -*Summary totals in REMAINING-WORK.md must match the sum of phase table rows.* +_Summary totals in REMAINING-WORK.md must match the sum of phase table rows._ --- @@ -2639,6 +3134,7 @@ > **Rationale:** A mismatch between summary and phase-level totals indicates patterns are being double-counted or dropped. **Verified by:** + - Summary matches phase table with all patterns having phases - Summary includes completed patterns correctly @@ -2651,6 +3147,7 @@ > **Rationale:** Unphased patterns are still remaining work; omitting them would undercount the total. **Verified by:** + - Summary includes backlog patterns without phase - All patterns in backlog when none have phases @@ -2663,6 +3160,7 @@ > **Rationale:** patternName is optional; relying on it for counting would miss unnamed patterns entirely. **Verified by:** + - Patterns with undefined patternName counted correctly - Mixed patterns with and without patternName @@ -2675,14 +3173,15 @@ > **Rationale:** Showing fully completed phases inflates the remaining work view, while omitting phases with incomplete patterns hides outstanding work. **Verified by:** + - Multiple phases shown in order - Completed phases not shown in remaining work -*remaining-work-totals.feature* +_remaining-work-totals.feature_ ### Renderer Block Types -*The universal renderer converts RenderableDocument to markdown.* +_The universal renderer converts RenderableDocument to markdown._ --- @@ -2693,6 +3192,7 @@ > **Rationale:** Consistent frontmatter structure allows downstream tooling and readers to reliably locate the document title and metadata without parsing the full body. **Verified by:** + - Render minimal document with title only - Render document with purpose - Render document with detail level @@ -2707,6 +3207,7 @@ > **Rationale:** Markdown only supports heading levels 1-6; unclamped values would produce invalid syntax that renders as plain text in all markdown processors. **Verified by:** + - Render headings at different levels - Clamp heading level 0 to 1 - Clamp heading level 7 to 6 @@ -2720,6 +3221,7 @@ > **Rationale:** The renderer is a dumb printer; altering paragraph content would break codec-controlled formatting and violate the separation between codec logic and rendering. **Verified by:** + - Render paragraph - Render paragraph with special characters - Render separator @@ -2733,6 +3235,7 @@ > **Rationale:** Unescaped pipes corrupt table column boundaries, raw newlines break row parsing, and short rows cause column misalignment in every markdown renderer. **Verified by:** + - Render basic table - Render table with alignment - Render empty table (no columns) @@ -2749,16 +3252,17 @@ > **Rationale:** Incorrect prefixes or indentation levels cause markdown parsers to break list continuity, rendering nested items as separate top-level lists or plain text. **Verified by:** + - Render unordered list - Render ordered list - Render checkbox list with checked items - Render nested list -*render-blocks.feature* +_render-blocks.feature_ ### Renderer Output Formats -*The universal renderer converts RenderableDocument to markdown.* +_The universal renderer converts RenderableDocument to markdown._ --- @@ -2769,6 +3273,7 @@ > **Rationale:** Inconsistent fencing breaks syntax highlighting in GitHub/IDE markdown previews and prevents Mermaid renderers from detecting diagram blocks. **Verified by:** + - Render code block with language - Render code block without language - Render mermaid diagram @@ -2782,6 +3287,7 @@ > **Rationale:** Unescaped HTML in summary text enables XSS when generated markdown is rendered in browsers; malformed details tags break progressive disclosure in documentation. **Verified by:** + - Render collapsible block - Render collapsible with HTML entities in summary - Render nested collapsible content @@ -2795,6 +3301,7 @@ > **Rationale:** Unencoded spaces produce broken links in markdown renderers, making cross-document navigation fail silently for files with spaces in their paths. **Verified by:** + - Render link-out block - Render link-out with spaces in path @@ -2807,6 +3314,7 @@ > **Rationale:** A mismatch between expected and actual file count causes the orchestrator to write orphaned files or miss outputs, corrupting the generated documentation directory. **Verified by:** + - Render document with additional files - Render document without additional files @@ -2819,6 +3327,7 @@ > **Rationale:** Block ordering reflects the codec's semantic structure; out-of-order or swallowed blocks would produce misleading documentation that diverges from the source of truth. **Verified by:** + - Render complex document with multiple block types --- @@ -2830,6 +3339,7 @@ > **Rationale:** LLM context windows are token-limited; visual-only blocks waste tokens without adding semantic value, and verbose markdown syntax inflates context size unnecessarily. **Verified by:** + - Claude context renders title and headings as section markers - Claude context renders sub-headings with different markers - Claude context omits mermaid blocks @@ -2847,6 +3357,7 @@ > **Rationale:** The modular-claude-md system manages CLAUDE.md as composable H3-rooted modules. Generating incompatible formats (like section markers) produces orphaned files that are never consumed. **Verified by:** + - Module title renders as H3 - Module section headings offset by plus 2 - Module frontmatter is omitted @@ -2855,11 +3366,11 @@ - Module collapsible blocks flatten to headings - Module heading level clamped at H6 -*render-output.feature* +_render-output.feature_ ### Reporting Codec -*- Need to generate changelog, traceability, and overview documents* +_- Need to generate changelog, traceability, and overview documents_ --- @@ -2870,6 +3381,7 @@ > **Rationale:** Keep a Changelog is an industry standard format — following it ensures the output is immediately familiar to developers. **Verified by:** + - Decode empty dataset produces changelog header only - Unreleased section shows active and vNEXT patterns - Release sections sorted by semver descending @@ -2888,6 +3400,7 @@ > **Rationale:** Traceability ensures every planned pattern has executable verification — gaps represent unverified claims about system behavior. **Verified by:** + - No timeline patterns produces empty message - Coverage statistics show totals and percentage - Coverage gaps table shows missing coverage @@ -2906,6 +3419,7 @@ > **Rationale:** The architecture overview is the primary entry point for understanding the project — it must provide a complete picture at a glance. **Verified by:** + - Decode empty dataset produces minimal overview - Architecture section from overview-tagged patterns - Patterns summary with progress bar @@ -2915,11 +3429,11 @@ - Exclude timeline summary when option disabled - Multiple overview patterns create multiple architecture subsections -*reporting-codecs.feature* +_reporting-codecs.feature_ ### Requirements Adr Codec -*- Need to generate product requirements documents with flexible groupings* +_- Need to generate product requirements documents with flexible groupings_ --- @@ -2930,6 +3444,7 @@ > **Rationale:** Flexible grouping lets stakeholders view requirements through their preferred lens (area, role, or phase), and detail files provide deep-dive context without bloating the summary document. **Verified by:** + - No patterns with PRD metadata produces empty message - Summary shows counts and groupings - By product area section groups patterns correctly @@ -2952,6 +3467,7 @@ > **Rationale:** Architecture decisions lose value without status tracking and supersession chains; without them, teams act on outdated decisions and cannot trace why a previous approach was abandoned. **Verified by:** + - No ADR patterns produces empty message - Summary shows status counts and categories - ADRs grouped by category @@ -2967,11 +3483,11 @@ - Decision - Consequences sections from Rule keywords -*requirements-adr-codecs.feature* +_requirements-adr-codecs.feature_ ### Robustness Integration -*Document generation pipeline needs validation, deduplication, and* +_Document generation pipeline needs validation, deduplication, and_ --- @@ -2982,13 +3498,15 @@ > **Rationale:** Prevents wasted extraction work and provides clear fail-fast behavior. **Verified by:** + - Valid decision document generates successfully - Invalid mapping halts pipeline before extraction - Multiple validation errors are reported together - @acceptance-criteria scenarios below. - The validation layer must run first and halt the pipeline if errors - are found + The validation layer must run first and halt the pipeline if errors + are found + - preventing wasted extraction work. --- @@ -3000,11 +3518,13 @@ > **Rationale:** All sources must be extracted to identify cross-source duplicates. **Verified by:** + - Duplicate content is removed from final output - Non-duplicate sections are preserved - @acceptance-criteria scenarios below. - Content from all sources is extracted first + Content from all sources is extracted first + - then deduplicated - then assembled into the final document. @@ -3017,14 +3537,16 @@ > **Rationale:** Users need visibility into non-fatal issues without blocking generation. **Verified by:** + - Warnings are collected across pipeline stages - Warnings do not prevent successful generation - @acceptance-criteria scenarios below. - Non-fatal issues from validation + Non-fatal issues from validation + - extraction - and deduplication are - collected and included in the result. + collected and included in the result. --- @@ -3035,12 +3557,13 @@ > **Rationale:** Users should fix issues in one iteration without guessing. **Verified by:** + - File not found error includes fix suggestion - Invalid method error includes valid alternatives - Extraction error includes source context - @acceptance-criteria scenarios below. - Errors include enough context for users to understand and fix the issue. + Errors include enough context for users to understand and fix the issue. --- @@ -3051,18 +3574,19 @@ > **Rationale:** Robustness improvements must be backward compatible. **Verified by:** + - PoC decision document still generates - Process Guard decision document still generates - @acceptance-criteria scenarios below. - The robustness improvements must not break existing valid decision - documents that worked with the PoC. + The robustness improvements must not break existing valid decision + documents that worked with the PoC. -*robustness-integration.feature* +_robustness-integration.feature_ ### Rule Keyword Po C -*This feature tests whether vitest-cucumber supports the Rule keyword* +_This feature tests whether vitest-cucumber supports the Rule keyword_ --- @@ -3073,6 +3597,7 @@ > **Rationale:** Incorrect arithmetic results silently corrupt downstream calculations, making errors undetectable at their source. The calculator should perform standard math operations with correct results. **Verified by:** + - Addition of two positive numbers - Subtraction of two numbers @@ -3085,14 +3610,15 @@ > **Rationale:** Unguarded division by zero causes runtime exceptions that crash the process instead of returning a recoverable error. Division by zero must be handled gracefully to prevent system errors. **Verified by:** + - Division of two numbers - Division by zero is prevented -*rule-keyword-poc.feature* +_rule-keyword-poc.feature_ ### Session Codec -*- Need to generate session context and remaining work documents from patterns* +_- Need to generate session context and remaining work documents from patterns_ --- @@ -3103,6 +3629,7 @@ > **Rationale:** AI agents need a compact, navigable view of current project state to make informed implementation decisions. **Verified by:** + - Decode empty dataset produces minimal session context - Decode dataset with timeline patterns - Session status shows current focus @@ -3123,6 +3650,7 @@ > **Rationale:** Remaining work visibility prevents scope blindness — knowing what's left, what's blocked, and what's ready drives efficient session planning. **Verified by:** + - All work complete produces celebration message - Summary shows remaining counts - Phase navigation with remaining count @@ -3134,11 +3662,11 @@ - Generate remaining work detail files when enabled - No detail files when disabled for remaining -*session-codecs.feature* +_session-codecs.feature_ ### Shape Matcher -*Matches file paths against glob patterns for TypeScript shape extraction.* +_Matches file paths against glob patterns for TypeScript shape extraction._ --- @@ -3149,6 +3677,7 @@ > **Rationale:** Loose matching on non-glob patterns would silently include unintended files, causing incorrect shapes to appear in generated documentation. **Verified by:** + - Exact path matches identical path - Exact path does not match different path @@ -3161,6 +3690,7 @@ > **Rationale:** Crossing directory boundaries would violate standard glob semantics and pull in shapes from nested modules that belong to different product areas. **Verified by:** + - Single glob matches file in target directory - Single glob does not match nested subdirectory - Single glob does not match wrong extension @@ -3174,6 +3704,7 @@ > **Rationale:** Recursive globs enable broad subtree selection for shape extraction; failing to respect prefix and extension constraints would leak unrelated shapes into the output. **Verified by:** + - Recursive glob matches file at target depth - Recursive glob matches file at deeper depth - Recursive glob matches file at top level @@ -3188,15 +3719,16 @@ > **Rationale:** Duplicate shape names in generated documentation confuse readers and inflate type registries. **Verified by:** + - Shapes are extracted from matching patterns - Duplicate shape names are deduplicated - No shapes returned when glob does not match -*shape-matcher.feature* +_shape-matcher.feature_ ### Shape Selector -*Tests the filterShapesBySelectors function that provides fine-grained* +_Tests the filterShapesBySelectors function that provides fine-grained_ --- @@ -3207,6 +3739,7 @@ > **Rationale:** Multiple selection modes let reference docs curate precisely which shapes appear, preventing either over-inclusion of internal types or under-inclusion of public API surfaces. **Verified by:** + - Select specific shapes by source and names - Select all shapes in a group - Select all tagged shapes from a source file @@ -3216,11 +3749,11 @@ - Select by source alone - shapeSources backward compatibility preserved -*shape-selector.feature* +_shape-selector.feature_ ### Source Mapper -*The Source Mapper aggregates content from multiple source files based on* +_The Source Mapper aggregates content from multiple source files based on_ --- @@ -3231,6 +3764,7 @@ > **Rationale:** Wrong dispatch would apply TypeScript extraction logic to Gherkin files (or vice versa), producing garbled or empty results. **Verified by:** + - Dispatch to decision extraction for THIS DECISION - Dispatch to TypeScript extractor for .ts files - Dispatch to behavior spec extractor for .feature files @@ -3244,6 +3778,7 @@ > **Rationale:** Self-references avoid circular file reads — the document content is already in memory, so extraction is a lookup operation rather than a file I/O operation. **Verified by:** + - Extract from THIS DECISION using rule description - Extract DocStrings from THIS DECISION - Extract full document from THIS DECISION @@ -3257,6 +3792,7 @@ > **Rationale:** Mapping order is intentional — authors structure their source tables to produce a logical reading flow, and reordering would break the narrative. **Verified by:** + - Aggregate from multiple sources - Ordering is preserved from mapping table @@ -3269,6 +3805,7 @@ > **Rationale:** Partial extraction is more useful than total failure — a decision document with most sections populated and one warning is better than no document at all. **Verified by:** + - Missing source file produces warning - Partial extraction when some files missing - Validation checks all files before extraction @@ -3282,6 +3819,7 @@ > **Rationale:** Empty results often indicate stale source mappings pointing to renamed or removed content — warnings surface these issues before they reach generated output. **Verified by:** + - Empty shapes extraction produces info warning - No matching rules produces info warning @@ -3294,14 +3832,15 @@ > **Rationale:** Users write extraction methods in natural language — normalization bridges the gap between human-readable table entries and programmatic dispatch keys. **Verified by:** + - Normalize various extraction method formats - Unknown extraction method produces warning -*source-mapper.feature* +_source-mapper.feature_ ### Source Mapping Validator -*Source mappings reference files that may not exist, use invalid* +_Source mappings reference files that may not exist, use invalid_ --- @@ -3312,6 +3851,7 @@ > **Rationale:** Prevents extraction failures and provides clear error messages upfront. **Verified by:** + - Existing file passes validation - Missing file produces error with path - Directory instead of file produces error @@ -3328,6 +3868,7 @@ > **Rationale:** Invalid methods cannot extract content; suggest valid alternatives. **Verified by:** + - Valid extraction methods pass validation - Unknown method produces error with suggestions - Empty method produces error @@ -3343,6 +3884,7 @@ > **Rationale:** Incompatible combinations fail at extraction; catch early with clear guidance. **Verified by:** + - TypeScript method on feature file produces error - Gherkin method on TypeScript file produces error - Compatible method-file combination passes @@ -3358,6 +3900,7 @@ > **Rationale:** Missing columns prevent extraction; alternative column names are mapped. **Verified by:** + - Missing Section column produces error - Missing Source File column produces error - Alternative column names are accepted @@ -3372,15 +3915,16 @@ > **Rationale:** Enables users to fix all issues in a single iteration. **Verified by:** + - Multiple errors are aggregated - Warnings are collected alongside errors - @acceptance-criteria scenarios below. -*source-mapping-validator.feature* +_source-mapping-validator.feature_ ### Table Extraction -*Tables in business rule descriptions should appear exactly once in output.* +_Tables in business rule descriptions should appear exactly once in output._ --- @@ -3391,6 +3935,7 @@ > **Rationale:** Without deduplication, tables extracted for formatting would also remain in the raw description text, producing duplicate output. **Verified by:** + - Single table renders once in detailed mode - Table is extracted and properly formatted @@ -3403,6 +3948,7 @@ > **Rationale:** Merging or dropping tables would lose distinct data structures that the author intentionally separated, corrupting the rendered documentation. **Verified by:** + - Two tables in description render as two separate tables --- @@ -3414,15 +3960,16 @@ > **Rationale:** If table syntax is not stripped from the raw text, the same table data appears twice in the rendered output -- once from the extracted table block and once as raw pipe characters in the description. **Verified by:** + - Strips single table from text - Strips multiple tables from text - Preserves text without tables -*table-extraction.feature* +_table-extraction.feature_ ### Taxonomy Codec -*Validates the Taxonomy Codec that transforms MasterDataset into a* +_Validates the Taxonomy Codec that transforms MasterDataset into a_ --- @@ -3433,6 +3980,7 @@ > **Rationale:** Document metadata drives the table of contents and navigation in generated doc sites — incorrect metadata produces broken links and misleading titles. **Verified by:** + - Document title is Taxonomy Reference - Document purpose describes tag taxonomy - Detail level reflects generateDetailFiles option @@ -3446,6 +3994,7 @@ > **Rationale:** Categories are the primary navigation structure in the taxonomy — missing categories leave developers unable to find the correct annotation tags. **Verified by:** + - Categories section is included in output - Category table has correct columns - LinkOut to detail file when generateDetailFiles enabled @@ -3459,6 +4008,7 @@ > **Rationale:** Domain grouping improves scannability for large tag sets (21 categories in ddd-es-cqrs) while flat mode is simpler for small presets (3 categories in generic). **Verified by:** + - With groupByDomain enabled tags are grouped into subsections - With groupByDomain disabled single table rendered @@ -3471,6 +4021,7 @@ > **Rationale:** Domain classification is stable across releases — hardcoding prevents miscategorization from user config errors while the "Other" fallback handles future tag additions gracefully. **Verified by:** + - Core tags correctly classified - Relationship tags correctly classified - Timeline tags correctly classified @@ -3486,6 +4037,7 @@ > **Rationale:** Not all projects need all sections — disabling irrelevant sections reduces generated document size and prevents confusion from inapplicable content. **Verified by:** + - includeFormatTypes disabled excludes Format Types section - includePresets disabled excludes Presets section - includeArchDiagram disabled excludes Architecture section @@ -3499,6 +4051,7 @@ > **Rationale:** Progressive disclosure keeps the main document scannable while providing deep-dive content in linked pages — monolithic documents become unwieldy for large tag sets. **Verified by:** + - generateDetailFiles creates 3 additional files - Detail files have correct paths - generateDetailFiles disabled creates no additional files @@ -3512,13 +4065,14 @@ > **Rationale:** Format types control how tag values are parsed — undocumented formats force developers to guess the correct syntax, leading to annotation errors. **Verified by:** + - All 6 format types are documented -*taxonomy-codec.feature* +_taxonomy-codec.feature_ ### Timeline Codec -*- Need to generate roadmap, milestones, and current work documents from patterns* +_- Need to generate roadmap, milestones, and current work documents from patterns_ --- @@ -3529,6 +4083,7 @@ > **Rationale:** The roadmap is the primary planning artifact — progress tracking at both project and phase level enables informed prioritization. **Verified by:** + - Decode empty dataset produces minimal roadmap - Decode dataset with multiple phases - Progress section shows correct status counts @@ -3547,6 +4102,7 @@ > **Rationale:** Milestone tracking provides a historical record of delivery — grouping by quarter aligns with typical reporting cadence. **Verified by:** + - No completed patterns produces empty message - Summary shows completed counts - Quarterly navigation with completed patterns @@ -3563,6 +4119,7 @@ > **Rationale:** Current work focus eliminates noise from completed and planned items — teams need to see only what's in flight. **Verified by:** + - No active work produces empty message - Summary shows overall progress - Active phases with progress bars @@ -3570,11 +4127,11 @@ - All active patterns table - Generate current work detail files when enabled -*timeline-codecs.feature* +_timeline-codecs.feature_ ### Transform Dataset -*- Generators need multiple views of the same pattern data* +_- Generators need multiple views of the same pattern data_ --- @@ -3585,6 +4142,7 @@ > **Rationale:** Generators must handle the zero-state gracefully; a missing or malformed empty dataset would cause null-reference errors across all rendering codecs. **Verified by:** + - Transform empty dataset --- @@ -3596,6 +4154,7 @@ > **Rationale:** Generators need O(1) access to status-filtered and phase-ordered views without recomputing on each render pass. **Verified by:** + - Group patterns by status - Normalize status variants to canonical values - Group patterns by phase @@ -3612,6 +4171,7 @@ > **Rationale:** Timeline and domain views must exclude patterns without the relevant metadata to prevent misleading counts and empty groupings in generated documentation. **Verified by:** + - Group patterns by quarter - Patterns without quarter are not in byQuarter - Group patterns by category @@ -3625,6 +4185,7 @@ > **Rationale:** Codecs that render TypeScript-specific or Gherkin-specific views depend on pre-partitioned sources; mixing sources would produce incorrect per-origin statistics and broken cross-references. **Verified by:** + - Group patterns by source file type - Patterns with phase are also in roadmap view @@ -3637,6 +4198,7 @@ > **Rationale:** Bidirectional navigation is required for dependency tree queries without O(n) scans per lookup. **Verified by:** + - Build relationship index from patterns - Build relationship index with all relationship types - Reverse lookup computes enables from dependsOn @@ -3652,6 +4214,7 @@ > **Rationale:** Inconsistent rounding or a false-positive fully-completed signal on an empty dataset would misrepresent project health in dashboards and generated progress reports. **Verified by:** + - Calculate completion percentage - Check if fully completed @@ -3664,14 +4227,15 @@ > **Rationale:** Projects without a delivery workflow must still produce valid datasets; unconditionally requiring workflow data would break standalone documentation generation. **Verified by:** + - Include workflow in result when provided - Result omits workflow when not provided -*transform-dataset.feature* +_transform-dataset.feature_ ### Validation Rules Codec -*Validates the Validation Rules Codec that transforms MasterDataset into a* +_Validates the Validation Rules Codec that transforms MasterDataset into a_ --- @@ -3682,6 +4246,7 @@ > **Rationale:** Accurate metadata ensures the validation rules document is correctly indexed in the generated documentation site. **Verified by:** + - Document title is Validation Rules - Document purpose describes Process Guard - Detail level reflects generateDetailFiles option @@ -3695,6 +4260,7 @@ > **Rationale:** The rules table is the primary reference for understanding what Process Guard enforces — missing rules would leave developers surprised by undocumented validation failures. **Verified by:** + - All 6 rules appear in table - Rules have correct severity levels @@ -3707,6 +4273,7 @@ > **Rationale:** The state diagram is the most intuitive representation of allowed transitions — it answers "where can I go from here?" faster than a text table. **Verified by:** + - Mermaid diagram generated when includeFSMDiagram enabled - Diagram includes all 4 states - FSM diagram excluded when includeFSMDiagram disabled @@ -3720,6 +4287,7 @@ > **Rationale:** The protection matrix explains why certain edits are blocked — without it, developers encounter cryptic "scope-creep" or "completed-protection" errors without understanding the underlying model. **Verified by:** + - Matrix shows all 4 statuses with protection levels - Protection matrix excluded when includeProtectionMatrix disabled @@ -3732,6 +4300,7 @@ > **Rationale:** CLI documentation in the validation rules doc provides a single reference for both the rules and how to run them — separate docs would fragment the developer experience. **Verified by:** + - CLI example code block included - All 6 CLI options documented - Exit codes documented @@ -3746,14 +4315,15 @@ > **Rationale:** Escape hatches prevent the validation system from becoming a blocker — developers need to know how to safely bypass rules for legitimate exceptions. **Verified by:** + - All 3 escape hatches documented - Escape hatches section excluded when includeEscapeHatches disabled -*validation-rules-codec.feature* +_validation-rules-codec.feature_ ### Warning Collector -*The warning collector provides a unified system for capturing, categorizing,* +_The warning collector provides a unified system for capturing, categorizing,_ --- @@ -3764,6 +4334,7 @@ > **Rationale:** Context-free warnings are impossible to act on — developers need to know which file and line produced the warning to fix the underlying issue. **Verified by:** + - Warning includes source file - Warning includes line number when available - Warning includes category @@ -3777,6 +4348,7 @@ > **Rationale:** Large codebases produce many warnings — filtering by category or file lets developers focus on one concern at a time instead of triaging an overwhelming flat list. **Verified by:** + - Warning categories are supported - Warnings can be filtered by category - Warnings can be filtered by source file @@ -3790,6 +4362,7 @@ > **Rationale:** Pipeline stages run independently — without aggregation, warnings would be scattered across stage outputs, making it impossible to see the full picture. **Verified by:** + - Warnings from multiple stages are collected - Warnings are grouped by source file - Summary counts by category @@ -3803,6 +4376,7 @@ > **Rationale:** The Result pattern is the standard error-handling mechanism — warnings that don't propagate through Results would be silently lost when functions compose. **Verified by:** + - Successful result includes warnings - Failed result includes warnings collected before failure - Warnings propagate through pipeline @@ -3816,6 +4390,7 @@ > **Rationale:** Different consumers need different formats — CI pipelines parse JSON, developers read console output, and generated docs embed markdown. **Verified by:** + - Console format includes color and location - JSON format is machine-readable - Markdown format for documentation @@ -3829,14 +4404,15 @@ > **Rationale:** Direct console.warn calls bypass aggregation and filtering — migrating to the collector ensures all warnings are captured, categorized, and available for programmatic consumption. **Verified by:** + - Source mapper uses warning collector - Shape extractor uses warning collector -*warning-collector.feature* +_warning-collector.feature_ ### Zod Codec Migration -*- Raw JSON.parse returns unknown/any types, losing type safety at runtime* +_- Raw JSON.parse returns unknown/any types, losing type safety at runtime_ --- @@ -3847,6 +4423,7 @@ > **Rationale:** Separating parse from validate allows invalid data to leak past the boundary — a single-step codec ensures callers never hold an unvalidated value. **Verified by:** + - Input codec parses valid JSON to typed object - Input codec returns error for malformed JSON - Input codec returns validation errors for schema violations @@ -3861,6 +4438,7 @@ > **Rationale:** Serializing without validation can produce JSON that downstream consumers cannot parse, causing failures far from the source of the invalid data. **Verified by:** + - Output codec serializes valid object to JSON - Output codec returns error for schema violations - Output codec respects indent option @@ -3874,6 +4452,7 @@ > **Rationale:** Non-conformant lint output breaks CI pipeline parsers and IDE integrations that depend on a stable JSON contract. **Verified by:** + - LintOutputSchema validates correct lint output - LintOutputSchema rejects invalid severity @@ -3886,6 +4465,7 @@ > **Rationale:** Inconsistent validation summaries cause miscounted pattern coverage, leading to false confidence or missed gaps in cross-source analysis. **Verified by:** + - ValidationSummaryOutputSchema validates correct validation output - ValidationSummaryOutputSchema rejects invalid issue source @@ -3898,6 +4478,7 @@ > **Rationale:** Registry consumers attach domain-specific metadata whose shape varies per preset — constraining the nested structure would break extensibility across presets. **Verified by:** + - RegistryMetadataOutputSchema accepts arbitrary metadata --- @@ -3909,6 +4490,7 @@ > **Rationale:** Omitting the operation context or individual field errors forces developers to reproduce failures manually instead of diagnosing from the error message alone. **Verified by:** + - formatCodecError includes validation errors in output --- @@ -3920,6 +4502,7 @@ > **Rationale:** Throwing on invalid input forces every call site to wrap in try/catch — returning undefined lets callers use simple conditional checks and avoids unhandled exception crashes. **Verified by:** + - safeParse returns typed value on valid JSON - safeParse returns undefined on malformed JSON - safeParse returns undefined on schema violation @@ -3933,13 +4516,14 @@ > **Rationale:** Propagating raw filesystem exceptions leaks Node.js error internals to consumers and prevents consistent error formatting across parse, validate, and I/O failures. **Verified by:** + - createFileLoader loads and parses valid JSON file - createFileLoader handles ENOENT error - createFileLoader handles EACCES error - createFileLoader handles general read error - createFileLoader handles invalid JSON in file -*codec-migration.feature* +_codec-migration.feature_ --- diff --git a/docs-generated/business-rules/process.md b/docs-live/business-rules/process.md similarity index 94% rename from docs-generated/business-rules/process.md rename to docs-live/business-rules/process.md index c494d09f..3a8306fa 100644 --- a/docs-generated/business-rules/process.md +++ b/docs-live/business-rules/process.md @@ -12,7 +12,7 @@ ### Session File Lifecycle -*- Session files for completed phases become orphaned and show stale data* +_- Session files for completed phases become orphaned and show stale data_ --- @@ -23,6 +23,7 @@ > **Rationale:** Stale session files for completed or deferred phases mislead LLMs that read the sessions directory for context, causing incorrect planning decisions. **Verified by:** + - Orphaned session files are deleted during generation - Active phase session files are preserved and regenerated @@ -35,6 +36,7 @@ > **Rationale:** Generator runs are not guarded by precondition checks for directory existence. Cleanup must never crash regardless of filesystem state. **Verified by:** + - No active phases results in empty sessions directory - Cleanup is idempotent - Missing sessions directory is handled gracefully @@ -48,13 +50,14 @@ > **Rationale:** Without deletion tracking, operators cannot audit what the generator removed, making it impossible to diagnose missing file issues after a run. **Verified by:** + - Deleted files are tracked in generator output -*session-file-lifecycle.feature* +_session-file-lifecycle.feature_ ### Session Handoffs -*- Context is lost when work pauses mid-phase (LLM sessions have no memory)* +_- Context is lost when work pauses mid-phase (LLM sessions have no memory)_ --- @@ -65,6 +68,7 @@ > **Rationale:** Without structured handoff sections, LLM sessions lose context between runs and developers waste time re-discovering phase state. **Verified by:** + - SESSION-CONTEXT.md includes handoff section for active phases - Discovery tags appear in handoff context section - Paused phase shows status indicator @@ -78,6 +82,7 @@ > **Rationale:** Missing template sections cause incomplete handoffs, leading to lost context and repeated work when a new session resumes. **Verified by:** + - Handoff template exists and contains required sections - Retrospective checklist exists and contains required sections @@ -90,6 +95,7 @@ > **Rationale:** Without a single authoritative coordination reference, parallel developers follow ad-hoc processes that cause merge conflicts and duplicated effort. **Verified by:** + - PROCESS_SETUP.md documents handoff protocol - PROCESS_SETUP.md documents multi-developer coordination @@ -102,13 +108,14 @@ > **Rationale:** If handoff generation crashes on empty state or cannot be disabled, it blocks unrelated generation workflows and erodes trust in the automation. **Verified by:** + - Fresh phase shows no previous context message - Handoff context can be disabled - Mid-phase handoff preserves context - Multiple developers can coordinate - Session retrospective captures learnings -*session-handoffs.feature* +_session-handoffs.feature_ --- diff --git a/docs-generated/business-rules/validation.md b/docs-live/business-rules/validation.md similarity index 95% rename from docs-generated/business-rules/validation.md rename to docs-live/business-rules/validation.md index 250da05a..eec62b88 100644 --- a/docs-generated/business-rules/validation.md +++ b/docs-live/business-rules/validation.md @@ -12,7 +12,7 @@ ### Anti Pattern Detector -*- Dependencies in features (should be code-only) cause drift* +_- Dependencies in features (should be code-only) cause drift_ --- @@ -23,6 +23,7 @@ > **Rationale:** TypeScript owns runtime behavior while Gherkin owns delivery process metadata — mixing them creates dual-source conflicts and validation ambiguity. **Verified by:** + - Code without process tags passes - Feature-only process tags in code are flagged @@ -35,6 +36,7 @@ > **Rationale:** Generator hints are implementation details that belong in TypeScript — excessive magic comments in specs indicate leaking implementation concerns into business requirements. **Verified by:** + - Feature without magic comments passes - Features with excessive magic comments are flagged - Magic comments within threshold pass @@ -48,6 +50,7 @@ > **Rationale:** Oversized feature files indicate missing decomposition — they become hard to maintain and slow to execute. **Verified by:** + - Feature with few scenarios passes - Feature exceeding scenario threshold is flagged @@ -60,6 +63,7 @@ > **Rationale:** Excessively large files indicate a feature that should be split into focused, independently testable specifications. **Verified by:** + - Normal-sized feature passes - Oversized feature is flagged @@ -69,9 +73,10 @@ > **Invariant:** The anti-pattern detector must evaluate all registered rules in a single scan pass over the source files. > -> **Rationale:** Single-pass detection ensures consistent results and avoids O(n*m) performance degradation with multiple file traversals. +> **Rationale:** Single-pass detection ensures consistent results and avoids O(n\*m) performance degradation with multiple file traversals. **Verified by:** + - Combined detection finds process-in-code issues --- @@ -83,14 +88,15 @@ > **Rationale:** Developers need actionable feedback at commit time — ungrouped or unformatted violations are hard to triage and fix. **Verified by:** + - Empty violations produce clean report - Violations are grouped by severity -*anti-patterns.feature* +_anti-patterns.feature_ ### Config Schema Validation -*Configuration schemas validate scanner and generator inputs with security* +_Configuration schemas validate scanner and generator inputs with security_ --- @@ -101,6 +107,7 @@ > **Rationale:** Malformed or malicious glob patterns could scan outside project boundaries, exposing sensitive files. **Verified by:** + - ScannerConfigSchema validates correct configuration - ScannerConfigSchema accepts multiple patterns - ScannerConfigSchema rejects empty patterns array @@ -118,6 +125,7 @@ > **Rationale:** Non-JSON registry files could introduce parsing vulnerabilities, and unrestricted output paths could overwrite files outside the project. **Verified by:** + - GeneratorConfigSchema validates correct configuration - GeneratorConfigSchema requires .json registry file - GeneratorConfigSchema rejects outputDir with parent traversal @@ -134,6 +142,7 @@ > **Rationale:** Without a reliable type guard, callers cannot safely narrow unknown config objects and risk accessing properties on incompatible types at runtime. **Verified by:** + - isScannerConfig returns true for valid config - isScannerConfig returns false for invalid config - isScannerConfig returns false for null @@ -148,15 +157,16 @@ > **Rationale:** Without a reliable type guard, callers cannot safely narrow unknown config objects and risk passing malformed generator configs that bypass schema validation. **Verified by:** + - isGeneratorConfig returns true for valid config - isGeneratorConfig returns false for invalid config - isGeneratorConfig returns false for non-json registry -*config-schemas.feature* +_config-schemas.feature_ ### Detect Changes -*Tests for the detectDeliverableChanges function that parses git diff output.* +_Tests for the detectDeliverableChanges function that parses git diff output._ --- @@ -167,6 +177,7 @@ > **Rationale:** Correct change classification drives scope-creep detection — misclassifying a status change as an addition would trigger false scope-creep violations on active specs. **Verified by:** + - Single deliverable status change is detected as modification - Multiple deliverable status changes are all modifications @@ -179,6 +190,7 @@ > **Rationale:** Addition detection powers the scope-creep rule — new deliverables added to active specs must be flagged as violations. **Verified by:** + - New deliverable is detected as addition --- @@ -190,6 +202,7 @@ > **Rationale:** Removal detection enables the deliverable-removed warning — silently dropping deliverables could hide incomplete work. **Verified by:** + - Removed deliverable is detected as removal --- @@ -201,6 +214,7 @@ > **Rationale:** Real-world commits often contain mixed changes — incorrect categorization of any single change cascades into wrong validation decisions. **Verified by:** + - Mixed additions, removals, and modifications are handled correctly - Mixed additions - removals @@ -215,13 +229,14 @@ > **Rationale:** Feature files contain many table structures — only the Background deliverables table is semantically relevant to process guard validation. **Verified by:** + - Changes in Examples tables are not detected as deliverable changes -*detect-changes.feature* +_detect-changes.feature_ -### Do D Validator +### DoD Validator -*- Phases marked "completed" without all deliverables done* +_- Phases marked "completed" without all deliverables done_ --- @@ -232,6 +247,7 @@ > **Rationale:** Freeform status strings bypass schema validation and produce inconsistent completion tracking across the monorepo. **Verified by:** + - Complete status is detected as complete - Non-complete canonical statuses are correctly identified @@ -244,6 +260,7 @@ > **Rationale:** Without explicit acceptance criteria tags, there is no machine-verifiable proof that the delivered work meets its requirements. **Verified by:** + - Feature with @acceptance-criteria scenario passes - Feature without @acceptance-criteria fails - Tag matching is case-insensitive @@ -257,6 +274,7 @@ > **Rationale:** Extracted names appear in traceability reports and DoD summaries, providing an audit trail from requirement to verification. **Verified by:** + - Extract multiple AC scenario names - No AC scenarios returns empty list @@ -269,6 +287,7 @@ > **Rationale:** Partial completion or missing acceptance criteria means the pattern is not verified — marking it complete would bypass quality gates. **Verified by:** + - Phase with all deliverables complete and AC passes - Phase with incomplete deliverables fails - Phase without acceptance criteria fails @@ -283,6 +302,7 @@ > **Rationale:** Multi-phase patterns need granular validation — a single aggregate result would hide which specific phase failed its Definition of Done. **Verified by:** + - All completed phases passing DoD - Mixed pass/fail results - Only completed phases are validated by default @@ -297,15 +317,16 @@ > **Rationale:** Developers need immediate, actionable feedback during pre-commit validation — raw data structures are not human-readable. **Verified by:** + - Empty summary shows no completed phases message - Summary with passed phases shows details - Summary with failed phases shows details -*dod-validator.feature* +_dod-validator.feature_ ### FSM Validator -*- Status values must conform to PDR-005 FSM states* +_- Status values must conform to PDR-005 FSM states_ --- @@ -316,6 +337,7 @@ > **Rationale:** Invalid status values bypass FSM transition validation and produce undefined behavior in process guard enforcement. **Verified by:** + - Valid status values are accepted - Invalid status values are rejected - Terminal state returns warning @@ -329,6 +351,7 @@ > **Rationale:** The FSM encodes the delivery workflow contract — invalid transitions indicate process violations that could corrupt delivery tracking. **Verified by:** + - Valid transitions are accepted - Invalid transitions are rejected with alternatives - Terminal state has no valid transitions @@ -344,6 +367,7 @@ > **Rationale:** Completion metadata enables retrospective analysis and effort estimation — missing metadata degrades project planning accuracy over time. **Verified by:** + - Completed pattern with full metadata has no warnings - Completed pattern without date shows warning - Completed pattern with planned but no actual effort shows warning @@ -358,6 +382,7 @@ > **Rationale:** Protection levels enforce edit constraints per state — mismatched protection would allow prohibited modifications to active or completed specs. **Verified by:** + - Roadmap status has no protection - Active status has scope protection - Completed status has hard protection @@ -372,13 +397,14 @@ > **Rationale:** Callers need a complete validation picture — requiring multiple separate calls risks partial validation and inconsistent error reporting. **Verified by:** + - Valid completed pattern returns combined results -*fsm-validator.feature* +_fsm-validator.feature_ ### Lint Engine -*The lint engine orchestrates rule execution, aggregates violations,* +_The lint engine orchestrates rule execution, aggregates violations,_ --- @@ -389,6 +415,7 @@ > **Rationale:** Skipping rules or omitting source locations makes violations unactionable, as developers cannot locate or understand the issue. **Verified by:** + - Return empty array when all rules pass - Return violations for failing rules - Run all provided rules @@ -403,6 +430,7 @@ > **Rationale:** Missing files or inaccurate severity counts cause silent rule violations in CI and undermine trust in the linting pipeline. **Verified by:** + - Return empty results for clean files - Collect violations by file - Count violations by severity @@ -417,6 +445,7 @@ > **Rationale:** Without correct severity-to-exit-code mapping, CI pipelines either miss real errors or block on informational messages, eroding developer trust in the linter. **Verified by:** + - Return true when there are errors - Return false for warnings only in non-strict mode - Return true for warnings in strict mode @@ -432,6 +461,7 @@ > **Rationale:** Unsorted output forces developers to manually scan for critical errors among lower-severity noise, and mutating the original array would break callers that hold a reference to it. **Verified by:** + - Sort errors first then warnings then info - Sort by line number within same severity - Not mutate original array @@ -445,6 +475,7 @@ > **Rationale:** Incomplete formatting (missing file paths or line numbers) prevents developers from navigating directly to violations, and noisy output in quiet mode defeats its purpose. **Verified by:** + - Show success message when no violations - Format violations with file line severity and message - Show summary line with counts @@ -459,15 +490,16 @@ > **Rationale:** Machine consumers (CI pipelines, IDE integrations) depend on valid JSON with complete fields; missing or malformed output breaks automated tooling downstream. **Verified by:** + - Return valid JSON - Include all summary fields - Include violation details -*lint-engine.feature* +_lint-engine.feature_ ### Linter Validation -*Tests for lint rules that validate relationship integrity, detect conflicts,* +_Tests for lint rules that validate relationship integrity, detect conflicts,_ --- @@ -478,12 +510,13 @@ > **Rationale:** Self-implementing patterns create circular references that break the sub-pattern hierarchy. **Verified by:** + - Pattern tag with implements tag causes error - Implements without pattern tag is valid - Implements without pattern tag is valid - A file cannot define a pattern that implements itself. This creates a - circular reference. Different patterns are allowed (sub-pattern hierarchy). + A file cannot define a pattern that implements itself. This creates a + circular reference. Different patterns are allowed (sub-pattern hierarchy). --- @@ -494,12 +527,14 @@ > **Rationale:** Dangling references to non-existent patterns produce broken dependency graphs and misleading documentation. **Verified by:** + - Uses referencing non-existent pattern warns - Implements referencing non-existent pattern warns - Valid relationship target passes - Valid relationship target passes - In strict mode + In strict mode + - all relationship targets are validated against known patterns. --- @@ -511,6 +546,7 @@ > **Rationale:** Asymmetric links mean one side of the traceability chain is invisible, defeating the purpose of bidirectional tracing. **Verified by:** + - Missing back-link detected - Orphan executable spec detected @@ -523,14 +559,15 @@ > **Rationale:** Dangling parent references break the epic-to-pattern hierarchy, causing patterns to appear orphaned in roadmap views and losing rollup visibility. **Verified by:** + - Invalid parent reference detected - Valid parent reference passes -*linter-validation.feature* +_linter-validation.feature_ ### Lint Rule Advanced -*Complex lint rule logic and collection-level behavior.* +_Complex lint rule logic and collection-level behavior._ --- @@ -541,6 +578,7 @@ > **Rationale:** Tautological descriptions waste reader attention and indicate missing documentation effort. **Verified by:** + - Detect description that equals pattern name - Detect description that is pattern name with punctuation - Detect short description starting with pattern name @@ -560,6 +598,7 @@ > **Rationale:** A complete, ordered collection ensures no rule is silently dropped and severity-based filtering works correctly. **Verified by:** + - Default rules contains all 8 rules - Default rules have unique IDs - Default rules are ordered by severity @@ -574,15 +613,16 @@ > **Rationale:** CI pipelines need to control which violations block merges vs. which are advisory. **Verified by:** + - Filter returns all rules for info severity - Filter excludes info rules for warning severity - Filter returns only errors for error severity -*lint-rules-advanced.feature* +_lint-rules-advanced.feature_ ### Lint Rule Individual -*Individual lint rules that check parsed directives for completeness.* +_Individual lint rules that check parsed directives for completeness._ --- @@ -593,6 +633,7 @@ > **Rationale:** Without a pattern name, the file cannot be tracked, linked, or referenced in generated documentation. **Verified by:** + - Detect missing pattern name - Detect empty string pattern name - Detect whitespace-only pattern name @@ -608,6 +649,7 @@ > **Rationale:** Missing status prevents FSM validation and roadmap tracking. **Verified by:** + - Detect missing status - Accept completed status - Accept active status @@ -623,6 +665,7 @@ > **Rationale:** Without usage guidance, patterns become undiscoverable despite being documented. **Verified by:** + - Detect missing whenToUse - Detect empty whenToUse array - Accept whenToUse with content @@ -636,17 +679,18 @@ > **Rationale:** Isolated patterns without relationships produce diagrams with no edges and prevent dependency analysis. **Verified by:** + - Detect missing relationship tags - Detect empty uses array - Accept uses with content - Accept usedBy with content - Accept both uses and usedBy -*lint-rules-individual.feature* +_lint-rules-individual.feature_ ### Process Guard -*- Completed specs modified without explicit unlock reason* +_- Completed specs modified without explicit unlock reason_ --- @@ -657,6 +701,7 @@ > **Rationale:** Completed work represents validated, shipped functionality — accidental modification risks regression. **Verified by:** + - Completed file with unlock-reason passes validation - Completed file without unlock-reason fails validation - Protection levels and unlock requirement @@ -671,6 +716,7 @@ > **Rationale:** The FSM prevents skipping required stages (e.g., roadmap->completed bypasses implementation). **Verified by:** + - Valid transitions pass validation - Invalid transitions fail validation @@ -683,6 +729,7 @@ > **Rationale:** Scope-locking active work prevents mid-sprint scope creep that derails delivery commitments. **Verified by:** + - Active spec with no deliverable changes passes - Active spec adding deliverable fails validation - Roadmap spec can add deliverables freely @@ -699,6 +746,7 @@ > **Rationale:** Session scoping keeps focus on planned work and makes accidental cross-cutting changes visible. **Verified by:** + - File in session scope passes validation - File outside session scope triggers warning - No active session means all files in scope @@ -713,6 +761,7 @@ > **Rationale:** Exclusion is stronger than scope — it marks files that must NOT be touched during this session. **Verified by:** + - Excluded file triggers error - Non-excluded file passes validation - ignoreSession flag suppresses excluded errors @@ -726,15 +775,16 @@ > **Rationale:** Independent evaluation ensures no rule masks another, giving complete diagnostic output. **Verified by:** + - Multiple violations from different rules - Strict mode promotes warnings to errors - Clean change produces empty violations -*process-guard.feature* +_process-guard.feature_ ### Status Transition Detection -*Tests for the detectStatusTransitions function that parses git diff output.* +_Tests for the detectStatusTransitions function that parses git diff output._ --- @@ -745,6 +795,7 @@ > **Rationale:** File-level tags are the canonical source of pattern status — detecting transitions from tags ensures consistency with the FSM validator. **Verified by:** + - New file with status tag is detected as transition from roadmap - Modified file with status change is detected - No transition when status unchanged @@ -758,6 +809,7 @@ > **Rationale:** Docstrings often contain example code or documentation showing status tags — parsing these as real would cause phantom status transitions. **Verified by:** + - Status tag inside docstring is not used for transition - Multiple docstring status tags are all ignored - Only docstring status tags results in no transition @@ -771,6 +823,7 @@ > **Rationale:** A single canonical status per file prevents ambiguity — using the first tag matches Gherkin convention where file-level tags appear at the top. **Verified by:** + - First file-level tag wins over subsequent tags --- @@ -782,6 +835,7 @@ > **Rationale:** Line numbers enable precise error reporting — developers need to know exactly where in the file the transition was detected. **Verified by:** + - Transition location includes correct line number --- @@ -793,10 +847,11 @@ > **Rationale:** Generated files are projections of source files — detecting transitions in them would produce duplicate violations and false positives. **Verified by:** + - Status in docs-generated directory is ignored - Status in docs-living directory is ignored -*status-transition-detection.feature* +_status-transition-detection.feature_ --- diff --git a/docs-live/decisions/adr-001-taxonomy-canonical-values.md b/docs-live/decisions/adr-001-taxonomy-canonical-values.md index 3544b6b8..cd418218 100644 --- a/docs-live/decisions/adr-001-taxonomy-canonical-values.md +++ b/docs-live/decisions/adr-001-taxonomy-canonical-values.md @@ -6,10 +6,10 @@ ## Overview -| Property | Value | -| -------- | -------- | -| Status | accepted | -| Category | process | +| Property | Value | +| --- | --- | +| Status | accepted | +| Category | process | **Context:** The annotation system requires well-defined canonical values for taxonomy @@ -24,11 +24,11 @@ These are the durable constants of the delivery process. **Consequences:** -| Type | Impact | -| -------- | ------------------------------------------------------------- | -| Positive | Generated docs group into coherent sections | -| Positive | FSM enforcement has clear, auditable state definitions | -| Positive | Source ownership prevents cross-domain tag confusion | +| Type | Impact | +| --- | --- | +| Positive | Generated docs group into coherent sections | +| Positive | FSM enforcement has clear, auditable state definitions | +| Positive | Source ownership prevents cross-domain tag confusion | | Negative | Migration effort for existing specs with non-canonical values | ## Rules @@ -39,15 +39,19 @@ These are the durable constants of the delivery process. **Rationale:** Without canonical values, organic drift (e.g., Generator vs Generators) produces inconsistent grouping in generated documentation and fragmented product area pages. -| Value | Reader Question | Covers | -| ------------- | ----------------------------------- | ----------------------------------------------- | -| Annotation | How do I annotate code? | Scanning, extraction, tag parsing, dual-source | -| Configuration | How do I configure the tool? | Config loading, presets, resolution | -| Generation | How does code become docs? | Codecs, generators, rendering, diagrams | -| Validation | How is the workflow enforced? | FSM, DoD, anti-patterns, process guard, lint | -| DataAPI | How do I query process state? | Process state API, stubs, context assembly, CLI | -| CoreTypes | What foundational types exist? | Result monad, error factories, string utils | -| Process | How does the session workflow work? | Session lifecycle, handoffs, conventions | +| Value | Reader Question | Covers | +| --- | --- | --- | +| Annotation | How do I annotate code? | Scanning, extraction, tag parsing, dual-source | +| Configuration | How do I configure the tool? | Config loading, presets, resolution | +| Generation | How does code become docs? | Codecs, generators, rendering, diagrams | +| Validation | How is the workflow enforced? | FSM, DoD, anti-patterns, process guard, lint | +| DataAPI | How do I query process state? | Process state API, stubs, context assembly, CLI | +| CoreTypes | What foundational types exist? | Result monad, error factories, string utils | +| Process | How does the session workflow work? | Session lifecycle, handoffs, conventions | + +**Verified by:** + +- Canonical values are enforced ### ADR category canonical values @@ -55,12 +59,16 @@ These are the durable constants of the delivery process. **Rationale:** Unbounded category values prevent meaningful grouping of architecture decisions and make cross-cutting queries unreliable. -| Value | Purpose | -| ------------- | --------------------------------------------- | -| architecture | System structure, component design, data flow | -| process | Workflow, conventions, annotation rules | -| testing | Test strategy, verification approach | -| documentation | Documentation generation, content structure | +| Value | Purpose | +| --- | --- | +| architecture | System structure, component design, data flow | +| process | Workflow, conventions, annotation rules | +| testing | Test strategy, verification approach | +| documentation | Documentation generation, content structure | + +**Verified by:** + +- Canonical values are enforced ### FSM status values and protection levels @@ -68,26 +76,38 @@ These are the durable constants of the delivery process. **Rationale:** Without protection levels, active specs accumulate scope creep and completed specs get silently modified, undermining delivery process integrity. -| Status | Protection | Can Add Deliverables | Allowed Actions | -| --------- | ------------ | -------------------- | ------------------------------- | -| roadmap | None | Yes | Full editing | -| active | Scope-locked | No | Edit existing deliverables only | -| completed | Hard-locked | No | Requires unlock-reason tag | -| deferred | None | Yes | Full editing | +| Status | Protection | Can Add Deliverables | Allowed Actions | +| --- | --- | --- | --- | +| roadmap | None | Yes | Full editing | +| active | Scope-locked | No | Edit existing deliverables only | +| completed | Hard-locked | No | Requires unlock-reason tag | +| deferred | None | Yes | Full editing | + +**Verified by:** + +- Canonical values are enforced ### Valid FSM transitions **Invariant:** Only these transitions are valid. All others are rejected by Process Guard. -**Rationale:** Allowing arbitrary transitions (e.g., roadmap to completed) bypasses the active phase where scope-lock and deliverable tracking provide quality assurance. Completed is a terminal state. Modifications require `@libar-docs-unlock-reason` escape hatch. +**Rationale:** Allowing arbitrary transitions (e.g., roadmap to completed) bypasses the active phase where scope-lock and deliverable tracking provide quality assurance. + +| From | To | Trigger | +| --- | --- | --- | +| roadmap | active | Start work | +| roadmap | deferred | Postpone | +| active | completed | All deliverables done | +| active | roadmap | Blocked/regressed | +| deferred | roadmap | Resume planning | + +**Verified by:** + +- Canonical values are enforced + -| From | To | Trigger | -| -------- | --------- | --------------------- | -| roadmap | active | Start work | -| roadmap | deferred | Postpone | -| active | completed | All deliverables done | -| active | roadmap | Blocked/regressed | -| deferred | roadmap | Resume planning | + Completed is a terminal state. Modifications require + `@libar-docs-unlock-reason` escape hatch. ### Tag format types @@ -95,14 +115,18 @@ These are the durable constants of the delivery process. **Rationale:** Without explicit format types, parsers must guess value structure, leading to silent data corruption when CSV values are treated as single strings or numbers are treated as text. -| Format | Parsing | Example | -| ------------ | ------------------------------ | ------------------------------ | -| flag | Boolean presence, no value | @libar-docs-core | -| value | Simple string | @libar-docs-pattern MyPattern | -| enum | Constrained to predefined list | @libar-docs-status completed | -| csv | Comma-separated values | @libar-docs-uses A, B, C | -| number | Numeric value | @libar-docs-phase 15 | -| quoted-value | Preserves spaces | @libar-docs-brief:'Multi word' | +| Format | Parsing | Example | +| --- | --- | --- | +| flag | Boolean presence, no value | @libar-docs-core | +| value | Simple string | @libar-docs-pattern MyPattern | +| enum | Constrained to predefined list | @libar-docs-status completed | +| csv | Comma-separated values | @libar-docs-uses A, B, C | +| number | Numeric value | @libar-docs-phase 15 | +| quoted-value | Preserves spaces | @libar-docs-brief:'Multi word' | + +**Verified by:** + +- Canonical values are enforced ### Source ownership @@ -110,12 +134,16 @@ These are the durable constants of the delivery process. **Rationale:** Cross-domain tag placement (e.g., runtime dependencies in Gherkin) creates conflicting sources of truth and breaks the dual-source architecture ownership model. -| Tag | Correct Source | Wrong Source | Rationale | -| ---------- | -------------- | ------------- | ---------------------------------- | -| uses | TypeScript | Feature files | TS owns runtime dependencies | -| depends-on | Feature files | TypeScript | Gherkin owns planning dependencies | -| quarter | Feature files | TypeScript | Gherkin owns timeline metadata | -| team | Feature files | TypeScript | Gherkin owns ownership metadata | +| Tag | Correct Source | Wrong Source | Rationale | +| --- | --- | --- | --- | +| uses | TypeScript | Feature files | TS owns runtime dependencies | +| depends-on | Feature files | TypeScript | Gherkin owns planning dependencies | +| quarter | Feature files | TypeScript | Gherkin owns timeline metadata | +| team | Feature files | TypeScript | Gherkin owns ownership metadata | + +**Verified by:** + +- Canonical values are enforced ### Quarter format convention @@ -123,20 +151,28 @@ These are the durable constants of the delivery process. **Rationale:** Non-standard formats (e.g., Q1-2026) break lexicographic sorting, which roadmap generation and timeline queries depend on for correct ordering. +**Verified by:** + +- Canonical values are enforced + ### Canonical phase definitions (6-phase USDP standard) **Invariant:** The default workflow defines exactly 6 phases in fixed order. These are the canonical phase names and ordinals used by all generated documentation. **Rationale:** Ad-hoc phase names and ordering produce inconsistent roadmap grouping across packages and make cross-package progress tracking impossible. -| Order | Phase | Purpose | -| ----- | ------------- | ---------------------------------------------- | -| 1 | Inception | Problem framing, scope definition | -| 2 | Elaboration | Design decisions, architecture exploration | -| 3 | Session | Planning and design session work | -| 4 | Construction | Implementation, testing, integration | -| 5 | Validation | Verification, acceptance criteria confirmation | -| 6 | Retrospective | Review, lessons learned, documentation | +| Order | Phase | Purpose | +| --- | --- | --- | +| 1 | Inception | Problem framing, scope definition | +| 2 | Elaboration | Design decisions, architecture exploration | +| 3 | Session | Planning and design session work | +| 4 | Construction | Implementation, testing, integration | +| 5 | Validation | Verification, acceptance criteria confirmation | +| 6 | Retrospective | Review, lessons learned, documentation | + +**Verified by:** + +- Canonical values are enforced ### Deliverable status canonical values @@ -144,14 +180,18 @@ These are the durable constants of the delivery process. **Rationale:** Freeform status strings bypass Zod validation and break DoD checks, which rely on terminal status classification to determine pattern completeness. -| Value | Meaning | -| ----------- | -------------------- | -| complete | Work is done | -| in-progress | Work is ongoing | -| pending | Work has not started | -| deferred | Work postponed | -| superseded | Replaced by another | -| n/a | Not applicable | +| Value | Meaning | +| --- | --- | +| complete | Work is done | +| in-progress | Work is ongoing | +| pending | Work has not started | +| deferred | Work postponed | +| superseded | Replaced by another | +| n/a | Not applicable | + +**Verified by:** + +- Canonical values are enforced --- diff --git a/docs-live/decisions/adr-002-gherkin-only-testing.md b/docs-live/decisions/adr-002-gherkin-only-testing.md index d1291ba9..9b68b76b 100644 --- a/docs-live/decisions/adr-002-gherkin-only-testing.md +++ b/docs-live/decisions/adr-002-gherkin-only-testing.md @@ -6,10 +6,10 @@ ## Overview -| Property | Value | -| -------- | -------- | -| Status | accepted | -| Category | testing | +| Property | Value | +| --- | --- | +| Status | accepted | +| Category | testing | **Context:** A package that generates documentation from `.feature` files had dual @@ -18,20 +18,19 @@ This undermined the core thesis that Gherkin IS sufficient for all testing. **Decision:** Enforce strict Gherkin-only testing for the delivery-process package: - - All tests must be `.feature` files with step definitions - No new `.test.ts` files - Edge cases use Scenario Outline with Examples tables **Consequences:** -| Type | Impact | -| -------- | -------------------------------------------------------------------------- | -| Positive | Single source of truth for tests AND documentation | +| Type | Impact | +| --- | --- | +| Positive | Single source of truth for tests AND documentation | | Positive | Demonstrates Gherkin sufficiency -- the package practices what it preaches | -| Positive | Living documentation always matches test coverage | -| Positive | Forces better scenario design with Examples tables | -| Negative | Scenario Outline syntax more verbose than parameterized tests | +| Positive | Living documentation always matches test coverage | +| Positive | Forces better scenario design with Examples tables | +| Negative | Scenario Outline syntax more verbose than parameterized tests | ## Rules @@ -41,12 +40,16 @@ Enforce strict Gherkin-only testing for the delivery-process package: **Rationale:** Parallel `.test.ts` files create a hidden test layer invisible to the documentation pipeline, undermining the single source of truth principle this package enforces. -| Artifact | Without Gherkin-Only | With Gherkin-Only | -| ------------------- | --------------------------- | ---------------------------------- | -| Tests | .test.ts (hidden from docs) | .feature (visible in docs) | -| Business rules | Manually maintained | Extracted from Rule blocks | -| Acceptance criteria | Implicit in test code | Explicit @acceptance-criteria tags | -| Traceability | Manual cross-referencing | @libar-docs-implements links | +| Artifact | Without Gherkin-Only | With Gherkin-Only | +| --- | --- | --- | +| Tests | .test.ts (hidden from docs) | .feature (visible in docs) | +| Business rules | Manually maintained | Extracted from Rule blocks | +| Acceptance criteria | Implicit in test code | Explicit @acceptance-criteria tags | +| Traceability | Manual cross-referencing | @libar-docs-implements links | + +**Verified by:** + +- Gherkin-only policy enforced --- diff --git a/docs-live/decisions/adr-003-source-first-pattern-architecture.md b/docs-live/decisions/adr-003-source-first-pattern-architecture.md index 0d1a462a..68b62050 100644 --- a/docs-live/decisions/adr-003-source-first-pattern-architecture.md +++ b/docs-live/decisions/adr-003-source-first-pattern-architecture.md @@ -6,10 +6,10 @@ ## Overview -| Property | Value | -| -------- | -------- | -| Status | accepted | -| Category | process | +| Property | Value | +| --- | --- | +| Status | accepted | +| Category | process | **Context:** The original annotation architecture assumed pattern definitions live @@ -26,14 +26,14 @@ artifacts are annotated source code, executable specs, and decision specs. **Consequences:** -| Type | Impact | -| -------- | ------------------------------------------------------------------- | -| Positive | Pattern identity travels with code from stub through production | -| Positive | Eliminates stale tier 1 spec maintenance burden | +| Type | Impact | +| --- | --- | +| Positive | Pattern identity travels with code from stub through production | +| Positive | Eliminates stale tier 1 spec maintenance burden | | Positive | Executable specs become the living specification (richer, verified) | -| Positive | Retroactive annotation works without merge conflicts | -| Negative | Migration effort for existing tier 1 specs | -| Negative | Requires updating CLAUDE.md annotation ownership guidance | +| Positive | Retroactive annotation works without merge conflicts | +| Negative | Migration effort for existing tier 1 specs | +| Negative | Requires updating CLAUDE.md annotation ownership guidance | ## Rules @@ -43,43 +43,56 @@ artifacts are annotated source code, executable specs, and decision specs. **Rationale:** If pattern identity lives in tier 1 specs, it becomes stale after implementation and diverges from the code that actually realizes the pattern. -| Phase | Location | Status | -| -------------- | -------------------------------------- | --------- | -| Design | `delivery-process/stubs/pattern-name/` | roadmap | -| Implementation | `src/path/to/module.ts` | active | -| Completed | `src/path/to/module.ts` | completed | +| Phase | Location | Status | +| --- | --- | --- | +| Design | `delivery-process/stubs/pattern-name/` | roadmap | +| Implementation | `src/path/to/module.ts` | active | +| Completed | `src/path/to/module.ts` | completed | **Pattern Definition Lifecycle:** + Exception: Patterns with no TypeScript implementation (pure process or workflow concerns) may be defined in decision specs. The constraint is: one definition per pattern, regardless of source type. +**Verified by:** + +- TypeScript source is canonical pattern definition + ### Tier 1 specs are ephemeral working documents **Invariant:** Tier 1 roadmap specs serve planning and delivery tracking. They are not the source of truth for pattern identity, invariants, or acceptance criteria. After completion, they may be archived. **Rationale:** Treating tier 1 specs as durable creates a maintenance burden — at scale only 39% maintain traceability, and duplicated Rules/Scenarios average 200-400 stale lines. -| Phase | Planning Value | Documentation Value | -| --------- | ----------------------------- | ---------------------------------- | -| roadmap | High | None (not yet built) | -| active | Medium (deliverable tracking) | Low (stale snapshot) | -| completed | None | None (executable specs are better) | +| Phase | Planning Value | Documentation Value | +| --- | --- | --- | +| roadmap | High | None (not yet built) | +| active | Medium (deliverable tracking) | Low (stale snapshot) | +| completed | None | None (executable specs are better) | **Value by lifecycle phase:** +**Verified by:** + +- TypeScript source is canonical pattern definition + ### Three durable artifact types **Invariant:** The delivery process produces three artifact types with long-term value. All other artifacts are projections or ephemeral. **Rationale:** Without a clear boundary between durable and ephemeral artifacts, teams maintain redundant documents that inevitably drift from the source of truth. -| Artifact | Purpose | Owns | -| ------------------------ | ------------------------------------ | ------------------------------------- | -| Annotated TypeScript | Pattern identity, architecture graph | Name, status, uses, categories | -| Executable specs | Behavior verification, invariants | Rules, rationale, acceptance criteria | -| Decision specs (ADR/PDR) | Architectural choices, rationale | Why decisions were made | +| Artifact | Purpose | Owns | +| --- | --- | --- | +| Annotated TypeScript | Pattern identity, architecture graph | Name, status, uses, categories | +| Executable specs | Behavior verification, invariants | Rules, rationale, acceptance criteria | +| Decision specs (ADR/PDR) | Architectural choices, rationale | Why decisions were made | + +**Verified by:** + +- TypeScript source is canonical pattern definition ### Implements is UML Realization (many-to-one) @@ -87,10 +100,14 @@ artifacts are annotated source code, executable specs, and decision specs. **Rationale:** Without many-to-one realization, cross-cutting patterns that span multiple files cannot be traced back to a single canonical definition. -| Relationship | Tag | Cardinality | -| ------------ | ------------------------ | ----------------------- | -| Definition | `@libar-docs-pattern` | Exactly one per pattern | -| Realization | `@libar-docs-implements` | Many-to-one | +| Relationship | Tag | Cardinality | +| --- | --- | --- | +| Definition | `@libar-docs-pattern` | Exactly one per pattern | +| Realization | `@libar-docs-implements` | Many-to-one | + +**Verified by:** + +- TypeScript source is canonical pattern definition ### Single-definition constraint @@ -98,25 +115,33 @@ artifacts are annotated source code, executable specs, and decision specs. **Rationale:** Duplicate pattern definitions cause merge conflicts in the MasterDataset and produce ambiguous ownership in generated documentation. -| Current State | Resolution | -| ------------------------------- | ----------------------------------------------- | -| Pattern in both TS and feature | Keep TS definition, feature uses `@implements` | -| Pattern only in tier 1 spec | Move definition to TS stub, archive tier 1 spec | -| Pattern only in TS | Already correct | -| Pattern only in executable spec | Valid if no TS implementation exists | +| Current State | Resolution | +| --- | --- | +| Pattern in both TS and feature | Keep TS definition, feature uses `@implements` | +| Pattern only in tier 1 spec | Move definition to TS stub, archive tier 1 spec | +| Pattern only in TS | Already correct | +| Pattern only in executable spec | Valid if no TS implementation exists | **Migration path for existing conflicts:** +**Verified by:** + +- TypeScript source is canonical pattern definition + ### Reverse links preferred over forward links **Invariant:** `@libar-docs-implements` (reverse: "I verify this pattern") is the primary traceability mechanism. `@libar-docs-executable-specs` (forward: "my tests live here") is retained but not required. **Rationale:** Forward links in tier 1 specs go stale when specs are archived, while reverse links in test files are self-maintaining because the test cannot run without the implementation. -| Mechanism | Usage | Reliability | -| ----------------------------- | ----------------- | -------------------------------- | -| `@implements` (reverse) | 14 patterns (32%) | Self-maintaining, lives in test | -| `@executable-specs` (forward) | 9 patterns (20%) | Requires tier 1 spec maintenance | +| Mechanism | Usage | Reliability | +| --- | --- | --- | +| `@implements` (reverse) | 14 patterns (32%) | Self-maintaining, lives in test | +| `@executable-specs` (forward) | 9 patterns (20%) | Requires tier 1 spec maintenance | + +**Verified by:** + +- TypeScript source is canonical pattern definition --- diff --git a/docs-live/decisions/adr-004-session-workflow-commands.md b/docs-live/decisions/adr-004-session-workflow-commands.md index 2c79a77c..4df3b26c 100644 --- a/docs-live/decisions/adr-004-session-workflow-commands.md +++ b/docs-live/decisions/adr-004-session-workflow-commands.md @@ -6,9 +6,9 @@ ## Overview -| Property | Value | -| -------- | ------------ | -| Status | accepted | +| Property | Value | +| --- | --- | +| Status | accepted | | Category | architecture | **Context:** @@ -25,56 +25,111 @@ Seven design decisions (DD-1 through DD-7) captured as Rules below. **Invariant:** scope-validate and handoff must return plain text with === SECTION === markers, never JSON. -**Rationale:** Inconsistent output formats force consumers to detect and branch on format type, breaking the dual output path contract. Both scope-validate and handoff return string from the router, using === SECTION === markers. Follows the dual output path where text commands bypass JSON.stringify. +**Rationale:** Inconsistent output formats force consumers to detect and branch on format type, breaking the dual output path contract. + +**Verified by:** + +- scope-validate outputs structured text + + Both scope-validate and handoff return string from the router +- using + === SECTION === markers. Follows the dual output path where text + commands bypass JSON.stringify. ### DD-2 - Git integration is opt-in via --git flag **Invariant:** Domain logic must never invoke shell commands or depend on git directly. -**Rationale:** Shell dependencies in domain logic make functions untestable without git fixtures and break deterministic behavior. The handoff command accepts an optional --git flag. The CLI handler calls git diff and passes file list to the pure generator function. No shell dependency in domain logic. +**Rationale:** Shell dependencies in domain logic make functions untestable without git fixtures and break deterministic behavior. + +**Verified by:** + +- N/A — no-shell constraint verified by code review (no exec/spawn calls in domain logic) + + The handoff command accepts an optional --git flag. The CLI handler + calls git diff and passes file list to the pure generator function. + No shell dependency in domain logic. ### DD-3 - Session type inferred from FSM status **Invariant:** Every FSM status must map to exactly one default session type, overridable by an explicit --session flag. -**Rationale:** Ambiguous or missing inference forces users to always specify --session manually, defeating the ergonomic benefit of status-based defaults. Handoff infers session type from pattern's current FSM status. An explicit --session flag overrides inference. +**Rationale:** Ambiguous or missing inference forces users to always specify --session manually, defeating the ergonomic benefit of status-based defaults. -| Status | Inferred Session | -| --------- | ---------------- | -| roadmap | design | -| active | implement | -| completed | review | -| deferred | design | +| Status | Inferred Session | +| --- | --- | +| roadmap | design | +| active | implement | +| completed | review | +| deferred | design | + +**Verified by:** + +- N/A — full mapping table (4 statuses) verified by code review; active→implement example in "Active pattern infers implement session" + + Handoff infers session type from pattern's current FSM status. + An explicit --session flag overrides inference. ### DD-4 - Severity levels match Process Guard model **Invariant:** Scope validation must use exactly three severity levels (PASS, BLOCKED, WARN) consistent with Process Guard. -**Rationale:** Divergent severity models cause confusion when the same violation appears in both systems with different severity classifications. Scope validation uses three severity levels: The --strict flag promotes WARN to BLOCKED. +**Rationale:** Divergent severity models cause confusion when the same violation appears in both systems with different severity classifications. + +| Severity | Meaning | +| --- | --- | +| PASS | Check passed | +| BLOCKED | Hard prerequisite missing | +| WARN | Recommendation not met | + +**Verified by:** + +- N/A — three severity levels defined as type-system enum; verified by code review -| Severity | Meaning | -| -------- | ------------------------- | -| PASS | Check passed | -| BLOCKED | Hard prerequisite missing | -| WARN | Recommendation not met | + Scope validation uses three severity levels: + + + The --strict flag promotes WARN to BLOCKED. ### DD-5 - Current date only for handoff **Invariant:** Handoff must always use the current system date with no override mechanism. -**Rationale:** A --date flag enables backdating handoff timestamps, which breaks audit trail integrity for multi-session work. Handoff always uses the current date. No --date flag. +**Rationale:** A --date flag enables backdating handoff timestamps, which breaks audit trail integrity for multi-session work. + +**Verified by:** + +- N/A — no --date flag by design; verified by code review and CLI arg inventory + + Handoff always uses the current date. No --date flag. ### DD-6 - Both positional and flag forms for scope type **Invariant:** scope-validate must accept scope type as both a positional argument and a --type flag. -**Rationale:** Supporting only one form creates inconsistency with CLI conventions and forces users to remember which form each subcommand uses. scope-validate accepts scope type as both positional argument and --type flag. +**Rationale:** Supporting only one form creates inconsistency with CLI conventions and forces users to remember which form each subcommand uses. + +**Verified by:** + +- N/A — dual-form acceptance verified by code review (both positional and --type flag parsed in CLI handler) + + scope-validate accepts scope type as both positional argument + and --type flag. ### DD-7 - Co-located formatter functions **Invariant:** Each module must export both its data builder and text formatter as co-located functions. -**Rationale:** Splitting builder and formatter across files increases coupling surface and makes it harder to trace data flow through the module. Each module (scope-validator.ts, handoff-generator.ts) exports both the data builder and the text formatter. Simpler than the context-assembler/context-formatter split. +**Rationale:** Splitting builder and formatter across files increases coupling surface and makes it harder to trace data flow through the module. + +**Verified by:** + +- N/A — co-location is a module structure decision; verified by code review of scope-validator.ts and handoff-generator.ts exports + + Each module (scope-validator.ts +- handoff-generator.ts) exports + both the data builder and the text formatter. Simpler than the + context-assembler/context-formatter split. --- diff --git a/docs-live/decisions/adr-005-codec-based-markdown-rendering.md b/docs-live/decisions/adr-005-codec-based-markdown-rendering.md index cbe9827e..ef8c485e 100644 --- a/docs-live/decisions/adr-005-codec-based-markdown-rendering.md +++ b/docs-live/decisions/adr-005-codec-based-markdown-rendering.md @@ -6,9 +6,9 @@ ## Overview -| Property | Value | -| -------- | ------------ | -| Status | accepted | +| Property | Value | +| --- | --- | +| Status | accepted | | Category | architecture | **Context:** @@ -30,23 +30,23 @@ include) from formatting (how it looks) from serialization (markdown syntax). **Consequences:** -| Type | Impact | -| -------- | --------------------------------------------------------------------------------- | -| Positive | Codecs are pure functions: dataset in, document out -- trivially testable | +| Type | Impact | +| --- | --- | +| Positive | Codecs are pure functions: dataset in, document out -- trivially testable | | Positive | RenderableDocument is an inspectable IR -- tests assert on structure, not strings | -| Positive | Composable via CompositeCodec -- reference docs assemble from child codecs | -| Positive | Same dataset can produce different outputs (full doc, compact doc, AI context) | -| Negative | Extra abstraction layer between data and output | -| Negative | RenderableDocument vocabulary must cover all needed output patterns | +| Positive | Composable via CompositeCodec -- reference docs assemble from child codecs | +| Positive | Same dataset can produce different outputs (full doc, compact doc, AI context) | +| Negative | Extra abstraction layer between data and output | +| Negative | RenderableDocument vocabulary must cover all needed output patterns | **Benefits:** -| Benefit | Before (String Concat) | After (Codec) | -| ---------------------- | ----------------------------- | --------------------------------- | -| Testability | Assert on markdown strings | Assert on typed section blocks | -| Composability | Copy-paste between generators | CompositeCodec assembles children | -| Format variants | Duplicate generator logic | Same codec, different renderer | -| Progressive disclosure | Manual heading management | Heading depth auto-calculated | +| Benefit | Before (String Concat) | After (Codec) | +| --- | --- | --- | +| Testability | Assert on markdown strings | Assert on typed section blocks | +| Composability | Copy-paste between generators | CompositeCodec assembles children | +| Format variants | Duplicate generator logic | Same codec, different renderer | +| Progressive disclosure | Manual heading management | Heading depth auto-calculated | ## Rules @@ -60,8 +60,8 @@ include) from formatting (how it looks) from serialization (markdown syntax). ```typescript interface DocumentCodec { - decode(dataset: MasterDataset): RenderableDocument; -} + decode(dataset: MasterDataset): RenderableDocument; + } ``` **Verified by:** @@ -75,15 +75,15 @@ interface DocumentCodec { **Rationale:** A typed IR decouples codecs from rendering. Codecs express intent ("this is a table with these rows") and the renderer handles syntax ("pipe-delimited markdown with separator row"). This means switching output format (e.g., HTML instead of markdown) requires only a new renderer, not changes to every codec. -| Block Type | Purpose | Markdown Output | -| ---------- | ----------------------------- | --------------------------- | -| heading | Section title with depth | ## Title (depth-adjusted) | -| paragraph | Prose text | Plain text with blank lines | -| table | Structured data | Pipe-delimited table | -| code | Code sample with language | Fenced code block | -| list | Ordered or unordered items | - item or 1. item | -| separator | Visual break between sections | --- | -| metaRow | Key-value metadata | **Key:** Value | +| Block Type | Purpose | Markdown Output | +| --- | --- | --- | +| heading | Section title with depth | ## Title (depth-adjusted) | +| paragraph | Prose text | Plain text with blank lines | +| table | Structured data | Pipe-delimited table | +| code | Code sample with language | Fenced code block | +| list | Ordered or unordered items | - item or 1. item | +| separator | Visual break between sections | --- | +| metaRow | Key-value metadata | **Key:** Value | **Section block types:** @@ -102,14 +102,14 @@ interface DocumentCodec { ```typescript const referenceDoc = CompositeCodec.create({ - title: 'Architecture Reference', - codecs: [ - behaviorCodec, // patterns with rules - conventionCodec, // decision records - shapeCodec, // type definitions - diagramCodec, // mermaid diagrams - ], -}); + title: 'Architecture Reference', + codecs: [ + behaviorCodec, // patterns with rules + conventionCodec, // decision records + shapeCodec, // type definitions + diagramCodec, // mermaid diagrams + ], + }); ``` **Verified by:** @@ -123,9 +123,9 @@ const referenceDoc = CompositeCodec.create({ **Rationale:** Early ADRs used name prefixes like "Context - ..." and "Decision - ..." on Rule blocks to structure content. Later ADRs placed Context, Decision, and Consequences as bold-annotated prose in the Feature description, reserving Rule: blocks for invariants and design rules. Both conventions are valid. The ADR codec must handle both because the codebase contains ADRs authored in each style. The Feature description lives in pattern.directive.description. If the codec only renders Rules (via partitionRulesByPrefix), then Feature description content is silently dropped -- no error, no warning. This caused confusion across two repos where ADR content appeared in the feature file but was missing from generated docs. The fix renders pattern.directive.description in buildSingleAdrDocument between the Overview metadata table and the partitioned Rules section, using renderFeatureDescription() which walks content linearly and handles prose, tables, and DocStrings with correct interleaving. -| Source | Location | Example | Rendered Via | -| ------------------- | ----------------------------------- | ------------------------- | -------------------------- | -| Rule prefix | Rule: Context - ... | ADR-001 (taxonomy) | partitionRulesByPrefix() | +| Source | Location | Example | Rendered Via | +| --- | --- | --- | --- | +| Rule prefix | Rule: Context - ... | ADR-001 (taxonomy) | partitionRulesByPrefix() | | Feature description | **Context:** prose in Feature block | ADR-005 (codec rendering) | renderFeatureDescription() | **Verified by:** diff --git a/docs-live/decisions/adr-006-single-read-model-architecture.md b/docs-live/decisions/adr-006-single-read-model-architecture.md index 871457db..56c1a7f1 100644 --- a/docs-live/decisions/adr-006-single-read-model-architecture.md +++ b/docs-live/decisions/adr-006-single-read-model-architecture.md @@ -6,9 +6,9 @@ ## Overview -| Property | Value | -| -------- | ------------ | -| Status | proposed | +| Property | Value | +| --- | --- | +| Status | proposed | | Category | architecture | **Context:** @@ -38,14 +38,14 @@ consume the same pre-computed read model. **Consequences:** -| Type | Impact | -| -------- | ---------------------------------------------------------------------------------------------- | -| Positive | Relationship resolution happens once — no consumer re-derives implements, uses, or dependsOn | -| Positive | Eliminates lossy local types that discard fields from canonical ExtractedPattern | -| Positive | Validation rules automatically benefit from new MasterDataset views and indices | +| Type | Impact | +| --- | --- | +| Positive | Relationship resolution happens once — no consumer re-derives implements, uses, or dependsOn | +| Positive | Eliminates lossy local types that discard fields from canonical ExtractedPattern | +| Positive | Validation rules automatically benefit from new MasterDataset views and indices | | Positive | Aligns with the monorepo's own ADR-006: projections for all reads, never query aggregate state | -| Negative | Validators that today only need stage 1-2 data will import the transformer | -| Negative | MasterDataset schema changes affect more consumers | +| Negative | Validators that today only need stage 1-2 data will import the transformer | +| Negative | MasterDataset schema changes affect more consumers | ## Rules @@ -53,12 +53,22 @@ consume the same pre-computed read model. **Invariant:** Code that needs pattern relationships, status groupings, cross-source resolution, or dependency information consumes the MasterDataset. Direct scanner/extractor imports are permitted only in pipeline orchestration code that builds the MasterDataset. -**Rationale:** Bypassing the read model forces consumers to re-derive data that the MasterDataset already computes, creating duplicate logic and divergent behavior when the pipeline evolves. Exception: `lint-patterns.ts` is a pure stage-1 consumer. It validates annotation syntax on scanned files. No relationships, no cross-source resolution. Direct scanner consumption is correct for that use case. +**Rationale:** Bypassing the read model forces consumers to re-derive data that the MasterDataset already computes, creating duplicate logic and divergent behavior when the pipeline evolves. -| Layer | May Import | Examples | -| ---------------------- | -------------------------------- | --------------------------------------------------- | -| Pipeline Orchestration | scanner/, extractor/, pipeline/ | orchestrator.ts, process-api.ts pipeline setup | -| Feature Consumption | MasterDataset, relationshipIndex | codecs, ProcessStateAPI, validators, query handlers | +| Layer | May Import | Examples | +| --- | --- | --- | +| Pipeline Orchestration | scanner/, extractor/, pipeline/ | orchestrator.ts, process-api.ts pipeline setup | +| Feature Consumption | MasterDataset, relationshipIndex | codecs, ProcessStateAPI, validators, query handlers | + +**Verified by:** + +- Feature consumers import from MasterDataset not from raw pipeline stages + + + Exception: `lint-patterns.ts` is a pure stage-1 consumer. It validates + annotation syntax on scanned files. No relationships +- no cross-source + resolution. Direct scanner consumption is correct for that use case. ### No lossy local types @@ -66,45 +76,61 @@ consume the same pre-computed read model. **Rationale:** Lossy local types silently drop fields that later become needed, causing bugs that only surface when new MasterDataset capabilities are added and the local type lacks them. +**Verified by:** + +- Feature consumers import from MasterDataset not from raw pipeline stages + ### Relationship resolution is computed once **Invariant:** Forward relationships (uses, dependsOn, implementsPatterns) and reverse lookups (usedBy, implementedBy, extendedBy) are computed in `transformToMasterDataset()`. No consumer re-derives these from raw pattern arrays or scanned file tags. **Rationale:** Re-deriving relationships in consumers duplicates the resolution logic and risks inconsistency when different consumers implement subtly different traversal or filtering rules. +**Verified by:** + +- Feature consumers import from MasterDataset not from raw pipeline stages + ### Three named anti-patterns **Invariant:** These are recognized violations, serving as review criteria for new code and refactoring targets for existing code. -**Rationale:** Without named anti-patterns, violations appear as one-off style issues rather than systematic architectural drift, making them harder to detect and communicate in code review. Naming them makes them visible in code review — including AI-assisted sessions where the default proposal is often "add a helper function." +**Rationale:** Without named anti-patterns, violations appear as one-off style issues rather than systematic architectural drift, making them harder to detect and communicate in code review. -| Anti-Pattern | Detection Signal | -| ----------------------- | ---------------------------------------------------------------------------------------- | -| Parallel Pipeline | Feature consumer imports from scanner/ or extractor/ | -| Lossy Local Type | Local interface with subset of ExtractedPattern fields + dedicated extraction function | +| Anti-Pattern | Detection Signal | +| --- | --- | +| Parallel Pipeline | Feature consumer imports from scanner/ or extractor/ | +| Lossy Local Type | Local interface with subset of ExtractedPattern fields + dedicated extraction function | | Re-derived Relationship | Building Map or Set from pattern.implementsPatterns, uses, or dependsOn in consumer code | **Good vs Bad** ```typescript // Good: consume the read model - function validateCrossSource(dataset: RuntimeMasterDataset): ValidationSummary { - const rel = dataset.relationshipIndex[patternName]; - const isImplemented = rel.implementedBy.length > 0; - } - - // Bad: re-derive from raw state (Parallel Pipeline + Re-derived Relationship) - function buildImplementsLookup( - gherkinFiles: readonly ScannedGherkinFile[], - tsPatterns: readonly ExtractedPattern[] - ): ReadonlySet { ... } + function validateCrossSource(dataset: RuntimeMasterDataset): ValidationSummary { + const rel = dataset.relationshipIndex[patternName]; + const isImplemented = rel.implementedBy.length > 0; + } + + // Bad: re-derive from raw state (Parallel Pipeline + Re-derived Relationship) + function buildImplementsLookup( + gherkinFiles: readonly ScannedGherkinFile[], + tsPatterns: readonly ExtractedPattern[] + ): ReadonlySet { ... } ``` **References** -- Monorepo ADR-006: Projections for All Reads (same principle, application domain) -- ADR-005: Codec-Based Markdown Rendering (established MasterDataset as codec input) -- Order-management ARCHITECTURE.md: CommandOrchestrator + Read Model separation + - Monorepo ADR-006: Projections for All Reads (same principle, application domain) + - ADR-005: Codec-Based Markdown Rendering (established MasterDataset as codec input) + - Order-management ARCHITECTURE.md: CommandOrchestrator + Read Model separation + +**Verified by:** + +- Feature consumers import from MasterDataset not from raw pipeline stages + + + Naming them makes them visible in code review — including AI-assisted + sessions where the default proposal is often "add a helper function." --- diff --git a/docs-live/decisions/adr-021-doc-generation-proof-of-concept.md b/docs-live/decisions/adr-021-doc-generation-proof-of-concept.md index 158930c4..287cc688 100644 --- a/docs-live/decisions/adr-021-doc-generation-proof-of-concept.md +++ b/docs-live/decisions/adr-021-doc-generation-proof-of-concept.md @@ -6,14 +6,13 @@ ## Overview -| Property | Value | -| -------- | ------------- | -| Status | superseded | +| Property | Value | +| --- | --- | +| Status | superseded | | Category | documentation | -| Phase | 27 | +| Phase | 27 | **Status: SUPERSEDED** - This POC has been implemented. See: - - Convention-tagged decision records (ADR/PDR) with @libar-docs-convention tags - `docs-generated/ANNOTATION-GUIDE.md` - Comprehensive guide for fixing generated docs @@ -27,18 +26,18 @@ the PROOF OF CONCEPT (demonstrating the pattern works). **Rationale:** Manual documentation drifts from source as the codebase evolves, creating stale references that mislead both humans and AI coding sessions. -| Document | Lines | Maintenance Burden | -| ---------------------------- | -------- | --------------------------------- | -| docs/PROCESS-GUARD.md | ~300 | High - duplicates code behavior | -| docs/METHODOLOGY.md | ~400 | Medium - conceptual, changes less | -| \_claude-md/validation/\*.md | ~50 each | High - must match detailed docs | -| CLAUDE.md | ~800 | Very High - aggregates everything | +| Document | Lines | Maintenance Burden | +| --- | --- | --- | +| docs/PROCESS-GUARD.md | ~300 | High - duplicates code behavior | +| docs/METHODOLOGY.md | ~400 | Medium - conceptual, changes less | +| _claude-md/validation/*.md | ~50 each | High - must match detailed docs | +| CLAUDE.md | ~800 | Very High - aggregates everything | -| Gap | Impact | Solution | -| -------------------------------- | ------ | -------------------------------------- | -| Shape extraction from TypeScript | High | New @extract-shapes tag | -| Convention-tagged content | Medium | Decision records as convention sources | -| Durable intro/context content | Medium | Decision Rule: Context sections | +| Gap | Impact | Solution | +| --- | --- | --- | +| Shape extraction from TypeScript | High | New @extract-shapes tag | +| Convention-tagged content | Medium | Decision records as convention sources | +| Durable intro/context content | Medium | Decision Rule: Context sections | **The Problem:** @@ -70,46 +69,50 @@ the PROOF OF CONCEPT (demonstrating the pattern works). **What's Missing:** +**Verified by:** + +- Full pipeline generates documentation from decision documents + ## Decision **Invariant:** Each content type (intro/rationale, rules/examples, API types) is owned by exactly one source type (decision, behavior spec, or code). **Rationale:** Shared ownership leads to conflicting updates and ambiguous authority over what the "correct" version is. -| Source Type | Durability | Content Ownership | -| ---------------------------- | ---------- | -------------------------------------- | -| Decision documents (ADR/PDR) | Permanent | Intro, context, rationale, conventions | -| Behavior specs (.feature) | Permanent | Rules, examples, acceptance criteria | -| Implementation code (.ts) | Compiled | API types, error messages, signatures | - -| Rule Prefix | ADR Section | Doc Section | -| ---------------- | ---------------------- | ---------------------------- | -| `Context...` | context | ## Background / Introduction | -| `Decision...` | decision | ## How It Works | -| `Consequence...` | consequences | ## Trade-offs | -| Other rules | other (warning logged) | Custom sections | - -| Target Document | Sources | Detail Level | Effect | -| --------------------------------------- | ------------------------------------- | ------------ | ------------------------ | -| docs/PROCESS-GUARD.md | This decision + behavior specs + code | detailed | All sections, full JSDoc | -| \_claude-md/validation/process-guard.md | This decision + behavior specs + code | summary | Rules table, types only | - -| Level | Content Included | Rendering Style | -| -------- | ------------------------------------ | ------------------------------ | -| summary | Essential tables, type names only | Compact - lists vs code blocks | -| standard | Tables, types, key descriptions | Balanced | -| detailed | Everything including JSDoc, examples | Full - code blocks with JSDoc | - -| Source | What's Extracted | How | -| ------------------------------- | -------------------------------- | ------------------------- | -| Decision Rule: Context | Intro/background section | Rule description text | -| Decision Rule: Decision | How it works section | Rule description text | -| Decision Rule: Consequences | Trade-offs section | Rule description text | -| Decision DocStrings | Code examples (Husky, API) | Fenced code blocks | -| Behavior spec Rules | Validation rules, business rules | Rule names + descriptions | -| Behavior spec Scenario Outlines | Decision tables, lookup tables | Examples tables | -| TypeScript @extract-shapes | API types, interfaces | AST extraction | -| TypeScript JSDoc | Implementation notes | Markdown in comments | +| Source Type | Durability | Content Ownership | +| --- | --- | --- | +| Decision documents (ADR/PDR) | Permanent | Intro, context, rationale, conventions | +| Behavior specs (.feature) | Permanent | Rules, examples, acceptance criteria | +| Implementation code (.ts) | Compiled | API types, error messages, signatures | + +| Rule Prefix | ADR Section | Doc Section | +| --- | --- | --- | +| `Context...` | context | ## Background / Introduction | +| `Decision...` | decision | ## How It Works | +| `Consequence...` | consequences | ## Trade-offs | +| Other rules | other (warning logged) | Custom sections | + +| Target Document | Sources | Detail Level | Effect | +| --- | --- | --- | --- | +| docs/PROCESS-GUARD.md | This decision + behavior specs + code | detailed | All sections, full JSDoc | +| _claude-md/validation/process-guard.md | This decision + behavior specs + code | summary | Rules table, types only | + +| Level | Content Included | Rendering Style | +| --- | --- | --- | +| summary | Essential tables, type names only | Compact - lists vs code blocks | +| standard | Tables, types, key descriptions | Balanced | +| detailed | Everything including JSDoc, examples | Full - code blocks with JSDoc | + +| Source | What's Extracted | How | +| --- | --- | --- | +| Decision Rule: Context | Intro/background section | Rule description text | +| Decision Rule: Decision | How it works section | Rule description text | +| Decision Rule: Consequences | Trade-offs section | Rule description text | +| Decision DocStrings | Code examples (Husky, API) | Fenced code blocks | +| Behavior spec Rules | Validation rules, business rules | Rule names + descriptions | +| Behavior spec Scenario Outlines | Decision tables, lookup tables | Examples tables | +| TypeScript @extract-shapes | API types, interfaces | AST extraction | +| TypeScript JSDoc | Implementation notes | Markdown in comments | **The Pattern:** @@ -151,34 +154,39 @@ the PROOF OF CONCEPT (demonstrating the pattern works). generate-docs --decisions 'specs/**/*.feature' --features 'tests/**/*.feature' --typescript 'src/**/*.ts' --generators doc-from-decision --output docs ``` +**Verified by:** + +- Decision Rule descriptions become documentation sections; Decision DocStrings become code examples + **Invariant:** The source mapping table in a decision document defines how documentation sections are assembled from multiple source files. **Rationale:** Without a declarative mapping, generators must hard-code source-to-section relationships, making the system brittle to new document types. -| Column | Purpose | Example | -| ----------------- | -------------------------------------------- | -------------------------------- | -| Section | Target section heading in generated doc | "Intro & Context", "API Types" | -| Source File | Path to source file or self-reference marker | "src/types.ts", "THIS DECISION" | -| Extraction Method | How to extract content from source | "@extract-shapes", "Rule blocks" | - -| Marker | Meaning | -| ------------------------- | -------------------------------------------------- | -| THIS DECISION | Extract from the current decision document | -| THIS DECISION (Rule: X) | Extract specific Rule: block from current document | -| THIS DECISION (DocString) | Extract fenced code blocks from current document | - -| Extraction Method | Source Type | Action | -| -------------------------- | ------------------------ | ----------------------------------------------------- | -| Decision rule description | Decision (.feature) | Extract Rule: block content (Invariant, Rationale) | -| @extract-shapes tag | TypeScript (.ts) | Invoke shape extractor for @libar-docs-extract-shapes | -| Rule blocks | Behavior spec (.feature) | Extract Rule: names and descriptions | -| Scenario Outline Examples | Behavior spec (.feature) | Extract Examples tables as markdown | -| JSDoc section | TypeScript (.ts) | Extract markdown from JSDoc comments | -| createViolation() patterns | TypeScript (.ts) | Extract error message literals | -| Fenced code block | Decision (.feature) | Extract DocString code blocks with language | +| Column | Purpose | Example | +| --- | --- | --- | +| Section | Target section heading in generated doc | "Intro & Context", "API Types" | +| Source File | Path to source file or self-reference marker | "src/types.ts", "THIS DECISION" | +| Extraction Method | How to extract content from source | "@extract-shapes", "Rule blocks" | + +| Marker | Meaning | +| --- | --- | +| THIS DECISION | Extract from the current decision document | +| THIS DECISION (Rule: X) | Extract specific Rule: block from current document | +| THIS DECISION (DocString) | Extract fenced code blocks from current document | + +| Extraction Method | Source Type | Action | +| --- | --- | --- | +| Decision rule description | Decision (.feature) | Extract Rule: block content (Invariant, Rationale) | +| @extract-shapes tag | TypeScript (.ts) | Invoke shape extractor for @libar-docs-extract-shapes | +| Rule blocks | Behavior spec (.feature) | Extract Rule: names and descriptions | +| Scenario Outline Examples | Behavior spec (.feature) | Extract Examples tables as markdown | +| JSDoc section | TypeScript (.ts) | Extract markdown from JSDoc comments | +| createViolation() patterns | TypeScript (.ts) | Extract error message literals | +| Fenced code block | Decision (.feature) | Extract DocString code blocks with language | **Table Format:** + **Self-Reference Markers:** @@ -191,74 +199,83 @@ generate-docs --decisions 'specs/**/*.feature' --features 'tests/**/*.feature' - - `THIS DECISION` resolves to the current decision document - Missing files produce warnings but generation continues +**Verified by:** + +- Source mapping aggregates multiple files; Source mapping validated at generation time + ## Consequences **Invariant:** Decision documents remain the authoritative source for intro, rationale, and convention content until explicitly superseded. **Rationale:** Without durable ownership, documentation sections lose their authoritative source and degrade into unattributed prose that no one updates. -| Benefit | How | -| ---------------------- | ----------------------------------------- | -| Single source of truth | Each content type owned by one source | -| Always-current docs | Generated from tested/compiled sources | -| Reduced maintenance | Change source once, docs regenerate | +| Benefit | How | +| --- | --- | +| Single source of truth | Each content type owned by one source | +| Always-current docs | Generated from tested/compiled sources | +| Reduced maintenance | Change source once, docs regenerate | | Progressive disclosure | Same sources → compact + detailed outputs | -| Clear ownership | Decisions own "why", code owns "what" | +| Clear ownership | Decisions own "why", code owns "what" | -| Trade-off | Mitigation | -| ------------------------------------------------- | ---------------------------------------- | +| Trade-off | Mitigation | +| --- | --- | | Decisions must be updated for fundamental changes | Appropriate - fundamentals ARE decisions | -| New @extract-shapes capability required | Spec created (shape-extraction.feature) | -| Initial annotation effort on existing code | One-time migration, then maintained | -| Generated docs in git history | Same as current manual approach | - -| Content Type | Owner | Update Trigger | -| --------------------------- | ------------------------- | ------------------------------- | -| Intro, rationale, context | Decision document | Fundamental change to approach | -| Rules, examples, edge cases | Behavior specs | Behavior change (tests fail) | -| API types, signatures | Code with @extract-shapes | Interface change (compile fail) | -| Error messages | Code patterns | Message text change | -| Code examples | Decision DocStrings | Example needs update | +| New @extract-shapes capability required | Spec created (shape-extraction.feature) | +| Initial annotation effort on existing code | One-time migration, then maintained | +| Generated docs in git history | Same as current manual approach | + +| Content Type | Owner | Update Trigger | +| --- | --- | --- | +| Intro, rationale, context | Decision document | Fundamental change to approach | +| Rules, examples, edge cases | Behavior specs | Behavior change (tests fail) | +| API types, signatures | Code with @extract-shapes | Interface change (compile fail) | +| Error messages | Code patterns | Message text change | +| Code examples | Decision DocStrings | Example needs update | **Benefits:** + **Trade-offs:** **Ownership Boundaries:** +**Verified by:** + +- Decision Rule descriptions become documentation sections + **Invariant:** Pre-implementation design stubs must reside in `delivery-process/stubs/`, never in `src/`. **Rationale:** Stubs in `src/` require ESLint exceptions, create confusion between production and design code, and risk accidental imports of unimplemented functions. -| Issue | Impact | -| ------------------------ | ------------------------------------------- | -| ESLint exceptions needed | Rules relaxed for "not-yet-real" code | -| Confusion | What's production vs. what's design? | -| Pollution | Stubs mixed with implemented code | -| Import accidents | Other code might import unimplemented stubs | -| Maintenance burden | Must track which files are stubs | - -| Location | Content | When Moved to src/ | -| -------------------------------------- | --------------------------------------------- | ---------------------- | -| delivery-process/stubs/{pattern}/\*.ts | API shapes, interfaces, throw-not-implemented | Implementation session | -| src/\*_/_.ts | Production code only | Already there | - -| Benefit | How | -| --------------------- | -------------------------------------------------------------------- | -| No ESLint exceptions | Stubs aren't in src/, no relaxation needed | -| Clear separation | delivery-process/stubs/ = design, src/ = production | -| Documentation source | Stubs with @extract-shapes generate API docs | -| Safe iteration | Can refine stub APIs without breaking anything | +| Issue | Impact | +| --- | --- | +| ESLint exceptions needed | Rules relaxed for "not-yet-real" code | +| Confusion | What's production vs. what's design? | +| Pollution | Stubs mixed with implemented code | +| Import accidents | Other code might import unimplemented stubs | +| Maintenance burden | Must track which files are stubs | + +| Location | Content | When Moved to src/ | +| --- | --- | --- | +| delivery-process/stubs/{pattern}/*.ts | API shapes, interfaces, throw-not-implemented | Implementation session | +| src/**/*.ts | Production code only | Already there | + +| Benefit | How | +| --- | --- | +| No ESLint exceptions | Stubs aren't in src/, no relaxation needed | +| Clear separation | delivery-process/stubs/ = design, src/ = production | +| Documentation source | Stubs with @extract-shapes generate API docs | +| Safe iteration | Can refine stub APIs without breaking anything | | Implementation signal | Moving from delivery-process/stubs/ to src/ = implementation started | -| Document | Decision Source | -| ---------------------- | ----------------------------------------------- | -| docs/METHODOLOGY.md | ADR for delivery process methodology | -| docs/TAXONOMY.md | PDR-006 TypeScript Taxonomy (exists) | -| docs/VALIDATION.md | ADR for validation approach | -| docs/SESSION-GUIDES.md | ADR for session workflows | -| \_claude-md/\*_/_.md | Corresponding decisions with compact extraction | +| Document | Decision Source | +| --- | --- | +| docs/METHODOLOGY.md | ADR for delivery process methodology | +| docs/TAXONOMY.md | PDR-006 TypeScript Taxonomy (exists) | +| docs/VALIDATION.md | ADR for validation approach | +| docs/SESSION-GUIDES.md | ADR for session workflows | +| _claude-md/**/*.md | Corresponding decisions with compact extraction | **The Problem:** @@ -290,32 +307,33 @@ generate-docs --decisions 'specs/**/*.feature' --features 'tests/**/*.feature' - ```typescript // delivery-process/stubs/shape-extractor/shape-extractor.ts -/** - * @libar-docs - * @libar-docs-pattern ShapeExtractorStub - * @libar-docs-status roadmap - * - * ## Shape Extractor - Design Stub - * - * API design for extracting TypeScript types from source files. - */ - -export interface ExtractedShape { - name: string; - kind: 'interface' | 'type' | 'enum' | 'function'; - sourceText: string; -} - -export function extractShapes( - sourceCode: string, - shapeNames: string[] -): Map { - throw new Error('ShapeExtractor not yet implemented - roadmap pattern'); -} + /** + * @libar-docs + * @libar-docs-pattern ShapeExtractorStub + * @libar-docs-status roadmap + * + * ## Shape Extractor - Design Stub + * + * API design for extracting TypeScript types from source files. + */ + + export interface ExtractedShape { + name: string; + kind: 'interface' | 'type' | 'enum' | 'function'; + sourceText: string; + } + + export function extractShapes( + sourceCode: string, + shapeNames: string[] + ): Map { + throw new Error('ShapeExtractor not yet implemented - roadmap pattern'); + } ``` **Benefits:** + **Workflow:** 1. **Design session:** Create stub in `delivery-process/stubs/{pattern-name}/` @@ -327,39 +345,44 @@ export function extractShapes( Once proven with Process Guard, the pattern applies to all documentation: +**Verified by:** + +- N/A - architectural constraint verified by code structure +- not runtime scenario + ## Rules ### Proof of Concept - Self-documentation validates the pattern **Invariant:** The documentation generation pattern must be validated by generating documentation about itself from its own annotated sources. -**Rationale:** A self-referential proof of concept exposes extraction gaps and source mapping issues that synthetic test data would miss. This POC demonstrates the doc-from-decision pattern by generating docs about ITSELF. The DocGenerationProofOfConcept pattern produces: - -| Output | Purpose | Detail Level | -| -------------------------------------------------------- | ------------------ | ------------ | -| docs/DOC-GENERATION-PROOF-OF-CONCEPT.md | Detailed reference | detailed | -| \_claude-md/generated/doc-generation-proof-of-concept.md | AI context | summary | - -| Section | Source File | Extraction Method | -| ----------------- | --------------------------------------------------- | -------------------------- | -| Intro & Context | THIS DECISION (Rule: Context above) | Decision rule description | -| How It Works | THIS DECISION (Rule: Decision above) | Decision rule description | -| Validation Rules | tests/features/validation/process-guard.feature | Rule blocks | -| Protection Levels | delivery-process/specs/process-guard-linter.feature | Scenario Outline Examples | -| Valid Transitions | delivery-process/specs/process-guard-linter.feature | Scenario Outline Examples | -| API Types | src/lint/process-guard/types.ts | @extract-shapes tag | -| Decider API | src/lint/process-guard/decider.ts | @extract-shapes tag | -| CLI Options | src/cli/lint-process.ts | JSDoc section | -| Error Messages | src/lint/process-guard/decider.ts | createViolation() patterns | -| Pre-commit Setup | THIS DECISION (DocString) | Fenced code block | -| Programmatic API | THIS DECISION (DocString) | Fenced code block | - -| Situation | Solution | Example | -| ----------------------------- | --------------------- | ----------------------------------------- | -| Fix bug in completed spec | Add unlock reason tag | `@libar-docs-unlock-reason:'Fix-typo'` | -| Modify outside session scope | Use ignore flag | `lint-process --staged --ignore-session` | -| CI treats warnings as errors | Use strict flag | `lint-process --all --strict` | -| Skip workflow (legacy import) | Multiple transitions | Set roadmap then completed in same commit | +**Rationale:** A self-referential proof of concept exposes extraction gaps and source mapping issues that synthetic test data would miss. + +| Output | Purpose | Detail Level | +| --- | --- | --- | +| docs/DOC-GENERATION-PROOF-OF-CONCEPT.md | Detailed reference | detailed | +| _claude-md/generated/doc-generation-proof-of-concept.md | AI context | summary | + +| Section | Source File | Extraction Method | +| --- | --- | --- | +| Intro & Context | THIS DECISION (Rule: Context above) | Decision rule description | +| How It Works | THIS DECISION (Rule: Decision above) | Decision rule description | +| Validation Rules | tests/features/validation/process-guard.feature | Rule blocks | +| Protection Levels | delivery-process/specs/process-guard-linter.feature | Scenario Outline Examples | +| Valid Transitions | delivery-process/specs/process-guard-linter.feature | Scenario Outline Examples | +| API Types | src/lint/process-guard/types.ts | @extract-shapes tag | +| Decider API | src/lint/process-guard/decider.ts | @extract-shapes tag | +| CLI Options | src/cli/lint-process.ts | JSDoc section | +| Error Messages | src/lint/process-guard/decider.ts | createViolation() patterns | +| Pre-commit Setup | THIS DECISION (DocString) | Fenced code block | +| Programmatic API | THIS DECISION (DocString) | Fenced code block | + +| Situation | Solution | Example | +| --- | --- | --- | +| Fix bug in completed spec | Add unlock reason tag | `@libar-docs-unlock-reason:'Fix-typo'` | +| Modify outside session scope | Use ignore flag | `lint-process --staged --ignore-session` | +| CI treats warnings as errors | Use strict flag | `lint-process --all --strict` | +| Skip workflow (legacy import) | Multiple transitions | Set roadmap then completed in same commit | **Process Guard docs are generated separately from `adr-006-process-guard.feature`.** @@ -381,60 +404,67 @@ npx lint-process --staged ```json { - "scripts": { - "lint:process": "lint-process --staged", - "lint:process:ci": "lint-process --all --strict" - } -} + "scripts": { + "lint:process": "lint-process --staged", + "lint:process:ci": "lint-process --all --strict" + } + } ``` **Programmatic API Example:** ```typescript import { - deriveProcessState, - detectStagedChanges, - validateChanges, - hasErrors, - summarizeResult, -} from '@libar-dev/delivery-process/lint'; - -// 1. Derive state from annotations -const state = (await deriveProcessState({ baseDir: '.' })).value; - -// 2. Detect changes -const changes = detectStagedChanges('.').value; - -// 3. Validate -const { result } = validateChanges({ - state, - changes, - options: { strict: false, ignoreSession: false }, -}); - -// 4. Handle results -if (hasErrors(result)) { - console.log(summarizeResult(result)); - process.exit(1); -} + deriveProcessState, + detectStagedChanges, + validateChanges, + hasErrors, + summarizeResult, + } from '@libar-dev/delivery-process/lint'; + + // 1. Derive state from annotations + const state = (await deriveProcessState({ baseDir: '.' })).value; + + // 2. Detect changes + const changes = detectStagedChanges('.').value; + + // 3. Validate + const { result } = validateChanges({ + state, + changes, + options: { strict: false, ignoreSession: false }, + }); + + // 4. Handle results + if (hasErrors(result)) { + console.log(summarizeResult(result)); + process.exit(1); + } ``` **Escape Hatches:** +**Verified by:** + +- Full pipeline generates documentation from decision documents + + This POC demonstrates the doc-from-decision pattern by generating docs + about ITSELF. The DocGenerationProofOfConcept pattern produces: + ### Expected Output - Compact claude module structure **Invariant:** Compact output must contain only essential tables and type names, with no JSDoc comments or implementation details. **Rationale:** AI context windows are finite; including non-essential content displaces actionable information and degrades session effectiveness. -| Section | Content | -| ------------------ | ----------------------------------------------------------- | -| Header + Intro | Pattern name, problem/solution summary | -| API Types | Core interface definitions (DeciderInput, ValidationResult) | -| 7 Validation Rules | Rule table with severity and description | -| Protection Levels | Status-to-protection mapping table | -| CLI | Essential command examples | -| Link | Reference to full documentation | +| Section | Content | +| --- | --- | +| Header + Intro | Pattern name, problem/solution summary | +| API Types | Core interface definitions (DeciderInput, ValidationResult) | +| 7 Validation Rules | Rule table with severity and description | +| Protection Levels | Status-to-protection mapping table | +| CLI | Essential command examples | +| Link | Reference to full documentation | **File:** `_claude-md/validation/process-guard.md` @@ -452,6 +482,10 @@ if (hasErrors(result)) { - Inline code blocks for CLI examples - Cross-reference to detailed documentation +**Verified by:** + +- Compact and detailed outputs from same sources + --- [← Back to All Decisions](../DECISIONS.md) diff --git a/docs-live/product-areas/ANNOTATION.md b/docs-live/product-areas/ANNOTATION.md index 87319997..09060a57 100644 --- a/docs-live/product-areas/ANNOTATION.md +++ b/docs-live/product-areas/ANNOTATION.md @@ -16,6 +16,16 @@ --- +## Contents + +- [Key Invariants](#key-invariants) +- [Scanning & Extraction Boundary](#scanning-extraction-boundary) +- [Annotation Pipeline](#annotation-pipeline) +- [API Types](#api-types) +- [Business Rules](#business-rules) + +--- + ## Scanning & Extraction Boundary Scoped architecture diagram showing component relationships: @@ -113,15 +123,15 @@ interface TagRegistry { } ``` -| Property | Description | -| --------------- | ------------------------------------------------------------------------------ | -| version | Schema version for forward/backward compatibility checking | -| categories | Category definitions for classifying patterns by domain (e.g., core, api, ddd) | -| metadataTags | Metadata tag definitions with format, purpose, and validation rules | -| aggregationTags | Aggregation tag definitions for document-level grouping | -| formatOptions | Available format options for documentation output | -| tagPrefix | Prefix for all tags (e.g., "@libar-docs-") | -| fileOptInTag | File-level opt-in marker tag (e.g., "@libar-docs") | +| Property | Description | +| --- | --- | +| version | Schema version for forward/backward compatibility checking | +| categories | Category definitions for classifying patterns by domain (e.g., core, api, ddd) | +| metadataTags | Metadata tag definitions with format, purpose, and validation rules | +| aggregationTags | Aggregation tag definitions for document-level grouping | +| formatOptions | Available format options for documentation output | +| tagPrefix | Prefix for all tags (e.g., "@libar-docs-") | +| fileOptInTag | File-level opt-in marker tag (e.g., "@libar-docs") | ### MetadataTagDefinitionForRegistry (interface) @@ -150,18 +160,18 @@ interface MetadataTagDefinitionForRegistry { } ``` -| Property | Description | -| ----------- | ------------------------------------------------------------------------------------------ | -| tag | Tag name without prefix (e.g., "pattern", "status", "phase") | -| format | Value format type determining parsing rules (flag, value, enum, csv, number, quoted-value) | -| purpose | Human-readable description of the tag's purpose and usage | -| required | Whether this tag must be present for valid patterns | -| repeatable | Whether this tag can appear multiple times on a single pattern | -| values | Valid values for enum-type tags (undefined for non-enum formats) | -| default | Default value applied when tag is not specified | -| example | Example usage showing tag syntax (e.g., "@libar-docs-pattern MyPattern") | -| metadataKey | Maps tag name to metadata object property name (defaults to kebab-to-camelCase) | -| transform | Post-parse value transformer applied after format-based parsing | +| Property | Description | +| --- | --- | +| tag | Tag name without prefix (e.g., "pattern", "status", "phase") | +| format | Value format type determining parsing rules (flag, value, enum, csv, number, quoted-value) | +| purpose | Human-readable description of the tag's purpose and usage | +| required | Whether this tag must be present for valid patterns | +| repeatable | Whether this tag can appear multiple times on a single pattern | +| values | Valid values for enum-type tags (undefined for non-enum formats) | +| default | Default value applied when tag is not specified | +| example | Example usage showing tag syntax (e.g., "@libar-docs-pattern MyPattern") | +| metadataKey | Maps tag name to metadata object property name (defaults to kebab-to-camelCase) | +| transform | Post-parse value transformer applied after format-based parsing | ### CategoryDefinition (interface) @@ -180,13 +190,13 @@ interface CategoryDefinition { } ``` -| Property | Description | -| ----------- | --------------------------------------------------------------------------------- | -| tag | Category tag name without prefix (e.g., "core", "api", "ddd", "saga") | -| domain | Human-readable domain name for display (e.g., "Strategic DDD", "Event Sourcing") | -| priority | Display order priority - lower values appear first in sorted output | -| description | Brief description of the category's purpose and typical patterns | -| aliases | Alternative tag names that map to this category (e.g., "es" for "event-sourcing") | +| Property | Description | +| --- | --- | +| tag | Category tag name without prefix (e.g., "core", "api", "ddd", "saga") | +| domain | Human-readable domain name for display (e.g., "Strategic DDD", "Event Sourcing") | +| priority | Display order priority - lower values appear first in sorted output | +| description | Brief description of the category's purpose and typical patterns | +| aliases | Alternative tag names that map to this category (e.g., "es" for "event-sourcing") | ### TagDefinition (type) @@ -290,7 +300,8 @@ METADATA_TAGS_BY_GROUP = { extraction: ['extract-shapes', 'shape'] as const, stub: ['target', 'since'] as const, convention: ['convention'] as const, -} as const; + claude: ['claude-module', 'claude-section', 'claude-tags'] as const, +} as const ``` ### CATEGORIES (const) @@ -314,7 +325,7 @@ const CATEGORIES: readonly CategoryDefinition[]; ``` ```typescript -CATEGORY_TAGS = CATEGORIES.map((c) => c.tag) as readonly CategoryTag[]; +CATEGORY_TAGS = CATEGORIES.map((c) => c.tag) as readonly CategoryTag[] ``` --- @@ -325,243 +336,243 @@ CATEGORY_TAGS = CATEGORIES.map((c) => c.tag) as readonly CategoryTag[]; ### Ast Parser Exports -| Rule | Invariant | Rationale | -| ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Rule | Invariant | Rationale | +| --- | --- | --- | | Export types are correctly identified from TypeScript declarations | Every exported TypeScript declaration type (function, type, interface, const, class, enum, abstract class, arrow function, async function, generic function, default export, re-export) is correctly classified. | Export type classification drives how codecs render API documentation — misclassifying a function as a const (or vice versa) produces incorrect signatures and misleading docs. | ### Ast Parser Metadata -| Rule | Invariant | Rationale | -| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Metadata is correctly extracted from JSDoc comments | Examples, multi-line descriptions, line numbers, function signatures, and standard JSDoc tags are all correctly parsed and separated. | Downstream codecs render each metadata field independently — incorrect parsing causes examples to leak into descriptions or signatures to be lost in generated documentation. | -| Tags are extracted only from the directive section, not from description or examples | Only tags appearing in the directive section (before the description) are extracted. Tags mentioned in description prose or example code blocks are ignored. | Tags control taxonomy classification and pattern routing — extracting them from prose or examples would create phantom patterns and corrupt the registry. | -| When to Use sections are extracted in all supported formats | When to Use content is extracted from heading format with bullet points, inline bold format, and asterisk bullet format. When no When to Use section exists, the field is undefined. | Generated pattern documentation includes a When to Use section — failing to recognize any supported format means valid guidance silently disappears from output. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Metadata is correctly extracted from JSDoc comments | Examples, multi-line descriptions, line numbers, function signatures, and standard JSDoc tags are all correctly parsed and separated. | Downstream codecs render each metadata field independently — incorrect parsing causes examples to leak into descriptions or signatures to be lost in generated documentation. | +| Tags are extracted only from the directive section, not from description or examples | Only tags appearing in the directive section (before the description) are extracted. Tags mentioned in description prose or example code blocks are ignored. | Tags control taxonomy classification and pattern routing — extracting them from prose or examples would create phantom patterns and corrupt the registry. | +| When to Use sections are extracted in all supported formats | When to Use content is extracted from heading format with bullet points, inline bold format, and asterisk bullet format. When no When to Use section exists, the field is undefined. | Generated pattern documentation includes a When to Use section — failing to recognize any supported format means valid guidance silently disappears from output. | ### Ast Parser Relationships Edges -| Rule | Invariant | Rationale | -| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -| Relationship tags extract uses and usedBy dependencies | The uses and usedBy relationship arrays are populated from directive tags, not from description content. When no relationship tags exist, the fields are undefined. | Relationship data drives dependency diagrams and impact analysis — extracting from prose would produce false edges from incidental mentions. | -| Edge cases and malformed input are handled gracefully | The parser never crashes on invalid input. Files without directives return empty results. Malformed TypeScript returns a structured error with the file path. | The scanner processes hundreds of files in bulk — a single malformed file must not abort the entire pipeline or produce an undiagnosable crash. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Relationship tags extract uses and usedBy dependencies | The uses and usedBy relationship arrays are populated from directive tags, not from description content. When no relationship tags exist, the fields are undefined. | Relationship data drives dependency diagrams and impact analysis — extracting from prose would produce false edges from incidental mentions. | +| Edge cases and malformed input are handled gracefully | The parser never crashes on invalid input. Files without directives return empty results. Malformed TypeScript returns a structured error with the file path. | The scanner processes hundreds of files in bulk — a single malformed file must not abort the entire pipeline or produce an undiagnosable crash. | ### Context Inference -| Rule | Invariant | Rationale | -| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -| matchPattern supports recursive wildcard \*\* | The `**` wildcard matches files at any nesting depth below the specified directory prefix. | Directory hierarchies vary in depth; recursive matching ensures all nested files inherit context. | -| matchPattern supports single-level wildcard /\* | The `/*` wildcard matches only direct children of the specified directory, not deeper nested files. | Some contexts apply only to a specific directory level, not its entire subtree. | -| matchPattern supports prefix matching | A trailing slash pattern matches any file whose path starts with that directory prefix. | Without prefix matching, users would need separate wildcard patterns for each nesting depth, making rule configuration verbose and error-prone. | -| inferContext returns undefined when no rules match | When no inference rule matches a file path, the pattern receives no inferred context and is excluded from the byContext index. | Unmatched files must not receive a spurious context assignment; absence of context is a valid state. | -| inferContext applies first matching rule | When multiple rules could match a file path, only the first matching rule determines the inferred context. | Deterministic ordering prevents ambiguous context assignment when rules overlap. | -| Explicit archContext is not overridden | A pattern with an explicitly annotated archContext retains that value regardless of matching inference rules. | Explicit annotations represent intentional developer decisions that must not be silently overwritten by automation. | -| Inference works independently of archLayer | Context inference operates on file path alone; the presence or absence of archLayer does not affect context assignment. | Coupling context inference to archLayer would prevent context-based queries from finding patterns that lack explicit layer annotations. | -| Default rules map standard directories | Each standard source directory (validation, scanner, extractor, etc.) maps to a well-known bounded context name via the default rule set. | Convention-based mapping eliminates the need for explicit context annotations on every file in standard directories. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| matchPattern supports recursive wildcard ** | The `**` wildcard matches files at any nesting depth below the specified directory prefix. | Directory hierarchies vary in depth; recursive matching ensures all nested files inherit context. | +| matchPattern supports single-level wildcard /* | The `/*` wildcard matches only direct children of the specified directory, not deeper nested files. | Some contexts apply only to a specific directory level, not its entire subtree. | +| matchPattern supports prefix matching | A trailing slash pattern matches any file whose path starts with that directory prefix. | Without prefix matching, users would need separate wildcard patterns for each nesting depth, making rule configuration verbose and error-prone. | +| inferContext returns undefined when no rules match | When no inference rule matches a file path, the pattern receives no inferred context and is excluded from the byContext index. | Unmatched files must not receive a spurious context assignment; absence of context is a valid state. | +| inferContext applies first matching rule | When multiple rules could match a file path, only the first matching rule determines the inferred context. | Deterministic ordering prevents ambiguous context assignment when rules overlap. | +| Explicit archContext is not overridden | A pattern with an explicitly annotated archContext retains that value regardless of matching inference rules. | Explicit annotations represent intentional developer decisions that must not be silently overwritten by automation. | +| Inference works independently of archLayer | Context inference operates on file path alone; the presence or absence of archLayer does not affect context assignment. | Coupling context inference to archLayer would prevent context-based queries from finding patterns that lack explicit layer annotations. | +| Default rules map standard directories | Each standard source directory (validation, scanner, extractor, etc.) maps to a well-known bounded context name via the default rule set. | Convention-based mapping eliminates the need for explicit context annotations on every file in standard directories. | ### Cross Source Validation -| Rule | Invariant | Rationale | -| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Rule | Invariant | Rationale | +| --- | --- | --- | | Pattern names must be consistent across sources | A pattern name referenced in one source must resolve to the same canonical name in all other sources. | Typos or inconsistencies between TypeScript and Gherkin pattern names cause silent data loss — the pattern appears as two unrelated entries instead of a unified cross-source record. | -| Circular dependencies are detected | The dependency graph must be a directed acyclic graph (DAG) with no cycles. | Circular dependencies create unresolvable ordering — no pattern in the cycle can be completed first, blocking the entire chain from progressing. | -| Dependency references must resolve | Every `@depends-on` reference must resolve to an existing pattern in the registry. | Dangling dependency references produce incomplete ordering and missing relationship edges in generated documentation, hiding actual inter-pattern constraints. | +| Circular dependencies are detected | The dependency graph must be a directed acyclic graph (DAG) with no cycles. | Circular dependencies create unresolvable ordering — no pattern in the cycle can be completed first, blocking the entire chain from progressing. | +| Dependency references must resolve | Every `@depends-on` reference must resolve to an existing pattern in the registry. | Dangling dependency references produce incomplete ordering and missing relationship edges in generated documentation, hiding actual inter-pattern constraints. | ### Declaration Level Shape Tagging -| Rule | Invariant | Rationale | -| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Declarations opt in via libar-docs-shape tag | Only declarations with the libar-docs-shape tag in their immediately preceding JSDoc are collected as tagged shapes. Declarations without the tag are ignored even if they are exported. The tag value is optional -- bare libar-docs-shape opts in without a group, while libar-docs-shape group-name assigns the declaration to a named group. Tagged non-exported declarations are included (DD-7). | Explicit opt-in prevents over-extraction of internal helpers. Unlike auto-discovery mode (extract-shapes \*) which grabs all exports, declaration-level tagging gives precise control. This matches how TypeDoc uses public/internal tags -- the annotation lives next to the code it describes, surviving refactors without breaking extraction. | -| Reference doc configs select shapes via shapeSelectors | shapeSelectors provides three selection modes: by source path + specific names (DD-6 source+names variant), by group tag (DD-6 group variant), or by source path alone (DD-6 source-only variant). shapeSources remains for backward compatibility. When both are present, shapeSources provides the coarse file-level filter and shapeSelectors adds fine-grained name/group filtering on top. | The reference doc system composes focused documents from cherry-picked content. Every other content axis (conventions, behaviors, diagrams) has content-level filtering. shapeSources was the only axis limited to file-level granularity. shapeSelectors closes this gap with the same explicitness as conventionTags. | -| Discovery uses existing estree parser with JSDoc comment scanning | The discoverTaggedShapes function uses the existing typescript-estree parse() and extractPrecedingJsDoc() approach. It does not require the TypeScript compiler API, ts-morph, or parseAndGenerateServices. Tag detection is a regex match on the JSDoc comment text already extracted by the existing infrastructure. The tag regex pattern is: /libar-docs-shape(?:\s+(\S+))?/ where capture group 1 is the optional group name. | The shape extractor already traverses declarations and extracts their JSDoc. Adding libar-docs-shape detection is a string search on content that is already available -- approximately 15 lines of new logic. Switching parsers would introduce churn with no benefit for the v1 use case of tag detection on top-level declarations. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Declarations opt in via libar-docs-shape tag | Only declarations with the libar-docs-shape tag in their immediately preceding JSDoc are collected as tagged shapes. Declarations without the tag are ignored even if they are exported. The tag value is optional -- bare libar-docs-shape opts in without a group, while libar-docs-shape group-name assigns the declaration to a named group. Tagged non-exported declarations are included (DD-7). | Explicit opt-in prevents over-extraction of internal helpers. Unlike auto-discovery mode (extract-shapes *) which grabs all exports, declaration-level tagging gives precise control. This matches how TypeDoc uses public/internal tags -- the annotation lives next to the code it describes, surviving refactors without breaking extraction. | +| Reference doc configs select shapes via shapeSelectors | shapeSelectors provides three selection modes: by source path + specific names (DD-6 source+names variant), by group tag (DD-6 group variant), or by source path alone (DD-6 source-only variant). shapeSources remains for backward compatibility. When both are present, shapeSources provides the coarse file-level filter and shapeSelectors adds fine-grained name/group filtering on top. | The reference doc system composes focused documents from cherry-picked content. Every other content axis (conventions, behaviors, diagrams) has content-level filtering. shapeSources was the only axis limited to file-level granularity. shapeSelectors closes this gap with the same explicitness as conventionTags. | +| Discovery uses existing estree parser with JSDoc comment scanning | The discoverTaggedShapes function uses the existing typescript-estree parse() and extractPrecedingJsDoc() approach. It does not require the TypeScript compiler API, ts-morph, or parseAndGenerateServices. Tag detection is a regex match on the JSDoc comment text already extracted by the existing infrastructure. The tag regex pattern is: /libar-docs-shape(?:\s+(\S+))?/ where capture group 1 is the optional group name. | The shape extractor already traverses declarations and extracts their JSDoc. Adding libar-docs-shape detection is a string search on content that is already available -- approximately 15 lines of new logic. Switching parsers would introduce churn with no benefit for the v1 use case of tag detection on top-level declarations. | ### Declaration Level Shape Tagging Testing -| Rule | Invariant | Rationale | -| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Declarations opt in via libar-docs-shape tag | Only declarations with the libar-docs-shape tag in their immediately preceding JSDoc are collected as tagged shapes. | Extracting shapes without an explicit opt-in tag would surface internal implementation details in generated API documentation, violating information hiding. | -| Discovery uses existing estree parser with JSDoc comment scanning | The discoverTaggedShapes function uses the existing typescript-estree parse() and extractPrecedingJsDoc() approach. | Introducing a second parser would create divergent AST behavior — reusing the established parser ensures consistent JSDoc handling and avoids subtle extraction differences. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Declarations opt in via libar-docs-shape tag | Only declarations with the libar-docs-shape tag in their immediately preceding JSDoc are collected as tagged shapes. | Extracting shapes without an explicit opt-in tag would surface internal implementation details in generated API documentation, violating information hiding. | +| Discovery uses existing estree parser with JSDoc comment scanning | The discoverTaggedShapes function uses the existing typescript-estree parse() and extractPrecedingJsDoc() approach. | Introducing a second parser would create divergent AST behavior — reusing the established parser ensures consistent JSDoc handling and avoids subtle extraction differences. | ### Depends On Tag Testing -| Rule | Invariant | Rationale | -| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -| Depends-on tag is defined in taxonomy registry | The depends-on and enables tags must exist in the taxonomy registry with CSV format. | Without registry definitions, the data-driven AST parser cannot discover or extract these planning dependency tags from source files. | -| Depends-on tag is extracted from Gherkin files | The Gherkin parser must extract depends-on values from feature file tags, including CSV multi-value lists. | Missing dependency extraction causes the dependency tree and blocking-pattern queries to return incomplete results. | -| Depends-on in TypeScript triggers anti-pattern warning | The depends-on tag must only appear in Gherkin files; its presence in TypeScript is an anti-pattern. | Depends-on represents planning dependencies owned by Gherkin specs, not runtime dependencies owned by TypeScript. | -| Enables tag is extracted from Gherkin files | The Gherkin parser must extract enables values from feature file tags, including CSV multi-value lists. | Missing enables extraction breaks forward-looking dependency queries, hiding which patterns are unblocked when a prerequisite completes. | -| Planning dependencies are stored in relationship index | The relationship index must store dependsOn and enables relationships extracted from pattern metadata. | Omitting planning dependencies from the index causes blocking-pattern and critical-path queries to return incomplete results. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Depends-on tag is defined in taxonomy registry | The depends-on and enables tags must exist in the taxonomy registry with CSV format. | Without registry definitions, the data-driven AST parser cannot discover or extract these planning dependency tags from source files. | +| Depends-on tag is extracted from Gherkin files | The Gherkin parser must extract depends-on values from feature file tags, including CSV multi-value lists. | Missing dependency extraction causes the dependency tree and blocking-pattern queries to return incomplete results. | +| Depends-on in TypeScript triggers anti-pattern warning | The depends-on tag must only appear in Gherkin files; its presence in TypeScript is an anti-pattern. | Depends-on represents planning dependencies owned by Gherkin specs, not runtime dependencies owned by TypeScript. | +| Enables tag is extracted from Gherkin files | The Gherkin parser must extract enables values from feature file tags, including CSV multi-value lists. | Missing enables extraction breaks forward-looking dependency queries, hiding which patterns are unblocked when a prerequisite completes. | +| Planning dependencies are stored in relationship index | The relationship index must store dependsOn and enables relationships extracted from pattern metadata. | Omitting planning dependencies from the index causes blocking-pattern and critical-path queries to return incomplete results. | ### Directive Detection -| Rule | Invariant | Rationale | -| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| hasDocDirectives detects @libar-docs-\* section directives | hasDocDirectives must return true if and only if the source contains at least one @libar-docs-{suffix} directive (case-sensitive, @ required, suffix required). | This is the first-pass filter in the scanner pipeline; false negatives cause patterns to be silently missed, while false positives only waste AST parsing time. | -| hasFileOptIn detects file-level @libar-docs marker | hasFileOptIn must return true if and only if the source contains a bare @libar-docs tag (not followed by a hyphen) inside a JSDoc block comment; line comments and @libar-docs-\* suffixed tags must not match. | File-level opt-in is the gate for including a file in the scanner pipeline; confusing @libar-docs-core (a section tag) with @libar-docs (file opt-in) would either miss files or over-include them. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| hasDocDirectives detects @libar-docs-* section directives | hasDocDirectives must return true if and only if the source contains at least one @libar-docs-{suffix} directive (case-sensitive, @ required, suffix required). | This is the first-pass filter in the scanner pipeline; false negatives cause patterns to be silently missed, while false positives only waste AST parsing time. | +| hasFileOptIn detects file-level @libar-docs marker | hasFileOptIn must return true if and only if the source contains a bare @libar-docs tag (not followed by a hyphen) inside a JSDoc block comment; line comments and @libar-docs-* suffixed tags must not match. | File-level opt-in is the gate for including a file in the scanner pipeline; confusing @libar-docs-core (a section tag) with @libar-docs (file opt-in) would either miss files or over-include them. | ### Doc String Media Type -| Rule | Invariant | Rationale | -| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Parser preserves DocString mediaType during extraction | The Gherkin parser must retain the mediaType annotation from DocString delimiters through to the parsed AST; DocStrings without a mediaType have undefined mediaType. | Losing the mediaType causes downstream renderers to apply incorrect escaping or default language hints, corrupting code block output. | -| MediaType is used when rendering code blocks | The rendered code block language must match the DocString mediaType; when mediaType is absent, the renderer falls back to a caller-specified default language. | Using the wrong language hint causes syntax highlighters to misrender code blocks, and losing mediaType entirely can trigger incorrect escaping (e.g., asterisks in JSDoc). | -| renderDocString handles both string and object formats | renderDocString accepts both plain string and object DocString formats; when an object has a mediaType, it takes precedence over the caller-supplied language parameter. | Legacy callers pass raw strings while newer code passes structured objects — the renderer must handle both without breaking existing usage. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Parser preserves DocString mediaType during extraction | The Gherkin parser must retain the mediaType annotation from DocString delimiters through to the parsed AST; DocStrings without a mediaType have undefined mediaType. | Losing the mediaType causes downstream renderers to apply incorrect escaping or default language hints, corrupting code block output. | +| MediaType is used when rendering code blocks | The rendered code block language must match the DocString mediaType; when mediaType is absent, the renderer falls back to a caller-specified default language. | Using the wrong language hint causes syntax highlighters to misrender code blocks, and losing mediaType entirely can trigger incorrect escaping (e.g., asterisks in JSDoc). | +| renderDocString handles both string and object formats | renderDocString accepts both plain string and object DocString formats; when an object has a mediaType, it takes precedence over the caller-supplied language parameter. | Legacy callers pass raw strings while newer code passes structured objects — the renderer must handle both without breaking existing usage. | ### Dual Source Extractor Testing -| Rule | Invariant | Rationale | -| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Process metadata is extracted from feature tags | A feature file must have both @pattern and @phase tags to produce valid process metadata; missing either yields null. | Pattern name and phase are the minimum identifiers for placing a pattern in the roadmap — without both, the pattern cannot be tracked. | -| Deliverables are extracted from Background tables | Deliverables are sourced exclusively from Background tables; features without a Background produce an empty deliverable list. | The Background table is the single source of truth for deliverable tracking — extracting from other locations would create ambiguity. | -| Code and feature patterns are combined into dual-source patterns | A combined pattern is produced only when both a code stub and a feature file exist for the same pattern name; unmatched sources are tracked separately as code-only or feature-only. | Dual-source combination ensures documentation reflects both implementation intent (code) and specification (Gherkin) — mismatches signal inconsistency. | -| Dual-source results are validated for consistency | Cross-source validation reports errors for metadata mismatches and warnings for orphaned patterns that are still in roadmap status. | Inconsistencies between code stubs and feature files indicate drift — errors catch conflicts while warnings surface missing counterparts that may be intentional. | -| Include tags are extracted from Gherkin feature tags | Include tags are parsed as comma-separated values; absence of the tag means the pattern has no includes. | Include tags control which patterns appear in scoped diagrams — incorrect parsing drops patterns from diagrams or includes unrelated ones. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Process metadata is extracted from feature tags | A feature file must have both @pattern and @phase tags to produce valid process metadata; missing either yields null. | Pattern name and phase are the minimum identifiers for placing a pattern in the roadmap — without both, the pattern cannot be tracked. | +| Deliverables are extracted from Background tables | Deliverables are sourced exclusively from Background tables; features without a Background produce an empty deliverable list. | The Background table is the single source of truth for deliverable tracking — extracting from other locations would create ambiguity. | +| Code and feature patterns are combined into dual-source patterns | A combined pattern is produced only when both a code stub and a feature file exist for the same pattern name; unmatched sources are tracked separately as code-only or feature-only. | Dual-source combination ensures documentation reflects both implementation intent (code) and specification (Gherkin) — mismatches signal inconsistency. | +| Dual-source results are validated for consistency | Cross-source validation reports errors for metadata mismatches and warnings for orphaned patterns that are still in roadmap status. | Inconsistencies between code stubs and feature files indicate drift — errors catch conflicts while warnings surface missing counterparts that may be intentional. | +| Include tags are extracted from Gherkin feature tags | Include tags are parsed as comma-separated values; absence of the tag means the pattern has no includes. | Include tags control which patterns appear in scoped diagrams — incorrect parsing drops patterns from diagrams or includes unrelated ones. | ### Extends Tag Testing -| Rule | Invariant | Rationale | -| -------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | -| Extends tag is defined in taxonomy registry | The extends tag must exist in the taxonomy registry with single-value format. | Without a registry definition, the data-driven AST parser cannot discover or extract the extends tag from source files. | -| Patterns can extend exactly one base pattern | A pattern may extend at most one base pattern, enforced by single-value tag format. | Single inheritance avoids diamond-problem ambiguity in pattern generalization hierarchies. | -| Transform builds extendedBy reverse lookup | The transform must compute an extendedBy reverse index so base patterns know which patterns extend them. | Without the reverse index, base patterns cannot discover their extensions, breaking generalization hierarchy navigation in generated docs. | -| Linter detects circular inheritance chains | Circular inheritance chains (direct or transitive) must be detected and reported as errors. | Circular extends relationships create infinite resolution loops and undefined behavior. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Extends tag is defined in taxonomy registry | The extends tag must exist in the taxonomy registry with single-value format. | Without a registry definition, the data-driven AST parser cannot discover or extract the extends tag from source files. | +| Patterns can extend exactly one base pattern | A pattern may extend at most one base pattern, enforced by single-value tag format. | Single inheritance avoids diamond-problem ambiguity in pattern generalization hierarchies. | +| Transform builds extendedBy reverse lookup | The transform must compute an extendedBy reverse index so base patterns know which patterns extend them. | Without the reverse index, base patterns cannot discover their extensions, breaking generalization hierarchy navigation in generated docs. | +| Linter detects circular inheritance chains | Circular inheritance chains (direct or transitive) must be detected and reported as errors. | Circular extends relationships create infinite resolution loops and undefined behavior. | ### Extraction Pipeline Enhancements Testing -| Rule | Invariant | Rationale | -| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Function signatures surface full parameter types in ExportInfo | ExportInfo.signature shows full parameter types and return type instead of the placeholder value. | Reference documentation renders signatures verbatim — placeholder values instead of real types make the API docs unusable for consumers. | -| Property-level JSDoc preserves full multi-line content | Property-level JSDoc preserves full multi-line content without first-line truncation. | Truncated property descriptions lose important behavioral details (defaults, units, constraints) that consumers rely on when integrating with the API. | -| Param returns and throws tags are extracted from function JSDoc | JSDoc param, returns, and throws tags are extracted and stored on ExtractedShape for function-kind shapes. | Function reference docs require parameter, return, and exception documentation — missing extraction means consumers must read source code instead of generated docs. | -| Auto-shape discovery extracts all exported types via wildcard | When extract-shapes tag value is the wildcard character, all exported declarations are extracted without listing names. | Requiring explicit names for every export creates maintenance burden and stale annotations — wildcard discovery keeps shape docs in sync as exports are added or removed. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Function signatures surface full parameter types in ExportInfo | ExportInfo.signature shows full parameter types and return type instead of the placeholder value. | Reference documentation renders signatures verbatim — placeholder values instead of real types make the API docs unusable for consumers. | +| Property-level JSDoc preserves full multi-line content | Property-level JSDoc preserves full multi-line content without first-line truncation. | Truncated property descriptions lose important behavioral details (defaults, units, constraints) that consumers rely on when integrating with the API. | +| Param returns and throws tags are extracted from function JSDoc | JSDoc param, returns, and throws tags are extracted and stored on ExtractedShape for function-kind shapes. | Function reference docs require parameter, return, and exception documentation — missing extraction means consumers must read source code instead of generated docs. | +| Auto-shape discovery extracts all exported types via wildcard | When extract-shapes tag value is the wildcard character, all exported declarations are extracted without listing names. | Requiring explicit names for every export creates maintenance burden and stale annotations — wildcard discovery keeps shape docs in sync as exports are added or removed. | ### File Discovery -| Rule | Invariant | Rationale | -| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Glob patterns match TypeScript source files | findFilesToScan must return absolute paths for all files matching the configured glob patterns. | Downstream pipeline stages (AST parser, extractor) require absolute paths to read file contents; relative paths would break when baseDir differs from cwd. | -| Default exclusions filter non-source files | node_modules, dist, .test.ts, .spec.ts, and .d.ts files must be excluded by default without explicit configuration. | Scanning generated output (dist), third-party code (node_modules), or test files would produce false positives in the pattern registry and waste processing time. | -| Custom configuration extends discovery behavior | User-provided exclude patterns must be applied in addition to (not replacing) the default exclusions. | Replacing defaults with custom patterns would silently re-include node_modules and dist, causing false positives in the pattern registry. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Glob patterns match TypeScript source files | findFilesToScan must return absolute paths for all files matching the configured glob patterns. | Downstream pipeline stages (AST parser, extractor) require absolute paths to read file contents; relative paths would break when baseDir differs from cwd. | +| Default exclusions filter non-source files | node_modules, dist, .test.ts, .spec.ts, and .d.ts files must be excluded by default without explicit configuration. | Scanning generated output (dist), third-party code (node_modules), or test files would produce false positives in the pattern registry and waste processing time. | +| Custom configuration extends discovery behavior | User-provided exclude patterns must be applied in addition to (not replacing) the default exclusions. | Replacing defaults with custom patterns would silently re-include node_modules and dist, causing false positives in the pattern registry. | ### Gherkin Ast Parser -| Rule | Invariant | Rationale | -| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Successful feature file parsing extracts complete metadata | A valid feature file must produce a ParsedFeature with name, description, language, tags, and all nested scenarios with their steps. | Downstream generators (timeline, business rules) depend on complete AST extraction; missing fields cause silent gaps in generated documentation. | -| Invalid Gherkin produces structured errors | Malformed or incomplete Gherkin input must return a Result.err with the source file path and a descriptive error message. | The scanner processes many feature files in batch; structured errors allow graceful degradation and per-file error reporting rather than aborting the entire scan. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Successful feature file parsing extracts complete metadata | A valid feature file must produce a ParsedFeature with name, description, language, tags, and all nested scenarios with their steps. | Downstream generators (timeline, business rules) depend on complete AST extraction; missing fields cause silent gaps in generated documentation. | +| Invalid Gherkin produces structured errors | Malformed or incomplete Gherkin input must return a Result.err with the source file path and a descriptive error message. | The scanner processes many feature files in batch; structured errors allow graceful degradation and per-file error reporting rather than aborting the entire scan. | ### Gherkin Rules Support -| Rule | Invariant | Rationale | -| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Rules flow through the entire pipeline without data loss | Rule data (name, description, tags, scenarios) must be preserved through every pipeline stage from parser to ExtractedPattern. | Any data loss at an intermediate stage makes rule content invisible to all downstream generators, silently producing incomplete documentation. The @cucumber/gherkin parser extracts Rules natively. Our pipeline must preserve this data through scanner, extractor, and into ExtractedPattern so generators can access rule names, descriptions, and nested scenarios. | -| Generators can render rules as business documentation | Rules must render as human-readable Business Rules sections, not as raw Given/When/Then syntax. | Business stakeholders cannot interpret Gherkin step definitions; without rendering transformation, feature files remain developer-only artifacts. Business stakeholders see rule names and descriptions as "Business Rules" sections, not Given/When/Then syntax. This enables human-readable PRDs from the same files used for test execution. | -| Custom content blocks render in acceptance criteria | DataTables and DocStrings attached to steps must appear in generated documentation as Markdown tables and fenced code blocks respectively. | Without rendering custom content blocks, acceptance criteria lose the structured data and code examples that make them self-contained and verifiable. DataTables and DocStrings in steps should appear in generated documentation, providing structured data and code examples alongside step descriptions. | -| vitest-cucumber executes scenarios inside Rules | Scenarios nested inside Rule blocks must be executable by vitest-cucumber using the Rule() and RuleScenario() API. | If Rule-scoped scenarios cannot execute, adding Rule blocks to feature files would break the test suite, forcing a choice between documentation structure and test coverage. Test execution must work for scenarios inside Rule blocks. Use Rule() function with RuleScenario() instead of Scenario(). | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Rules flow through the entire pipeline without data loss | Rule data (name, description, tags, scenarios) must be preserved through every pipeline stage from parser to ExtractedPattern. | Any data loss at an intermediate stage makes rule content invisible to all downstream generators, silently producing incomplete documentation. The @cucumber/gherkin parser extracts Rules natively. Our pipeline must preserve this data through scanner, extractor, and into ExtractedPattern so generators can access rule names, descriptions, and nested scenarios. | +| Generators can render rules as business documentation | Rules must render as human-readable Business Rules sections, not as raw Given/When/Then syntax. | Business stakeholders cannot interpret Gherkin step definitions; without rendering transformation, feature files remain developer-only artifacts. Business stakeholders see rule names and descriptions as "Business Rules" sections, not Given/When/Then syntax. This enables human-readable PRDs from the same files used for test execution. | +| Custom content blocks render in acceptance criteria | DataTables and DocStrings attached to steps must appear in generated documentation as Markdown tables and fenced code blocks respectively. | Without rendering custom content blocks, acceptance criteria lose the structured data and code examples that make them self-contained and verifiable. DataTables and DocStrings in steps should appear in generated documentation, providing structured data and code examples alongside step descriptions. | +| vitest-cucumber executes scenarios inside Rules | Scenarios nested inside Rule blocks must be executable by vitest-cucumber using the Rule() and RuleScenario() API. | If Rule-scoped scenarios cannot execute, adding Rule blocks to feature files would break the test suite, forcing a choice between documentation structure and test coverage. Test execution must work for scenarios inside Rule blocks. Use Rule() function with RuleScenario() instead of Scenario(). | ### Implements Tag Processing -| Rule | Invariant | Rationale | -| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | -| Implements tag is defined in taxonomy registry | The implements tag must exist in the taxonomy registry with CSV format. | Without a registry definition, the data-driven AST parser cannot discover or extract the implements tag from source files. | -| Files can implement a single pattern | The AST parser must extract a single implements value and preserve it through the extraction pipeline. | Lost implements values sever the link between implementation files and their roadmap specs, breaking traceability. | -| Files can implement multiple patterns using CSV format | The AST parser must split CSV implements values into individual pattern references with whitespace trimming. | Unsplit or untrimmed CSV values produce invalid pattern references that fail relationship index lookups. | -| Transform builds implementedBy reverse lookup | The transform must compute an implementedBy reverse index so spec patterns know which files implement them. | Without the reverse index, roadmap specs cannot discover their implementation files, breaking traceability and DoD validation. | -| Schemas validate implements field correctly | The Zod schemas must accept implements and implementedBy fields with correct array-of-string types. | Schema rejection of valid implements/implementedBy values causes runtime parse failures that silently drop traceability links. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Implements tag is defined in taxonomy registry | The implements tag must exist in the taxonomy registry with CSV format. | Without a registry definition, the data-driven AST parser cannot discover or extract the implements tag from source files. | +| Files can implement a single pattern | The AST parser must extract a single implements value and preserve it through the extraction pipeline. | Lost implements values sever the link between implementation files and their roadmap specs, breaking traceability. | +| Files can implement multiple patterns using CSV format | The AST parser must split CSV implements values into individual pattern references with whitespace trimming. | Unsplit or untrimmed CSV values produce invalid pattern references that fail relationship index lookups. | +| Transform builds implementedBy reverse lookup | The transform must compute an implementedBy reverse index so spec patterns know which files implement them. | Without the reverse index, roadmap specs cannot discover their implementation files, breaking traceability and DoD validation. | +| Schemas validate implements field correctly | The Zod schemas must accept implements and implementedBy fields with correct array-of-string types. | Schema rejection of valid implements/implementedBy values causes runtime parse failures that silently drop traceability links. | ### Layer Inference Testing -| Rule | Invariant | Rationale | -| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Timeline layer is detected from /timeline/ directory segments | Any feature file path containing a /timeline/ directory segment is classified as timeline layer. | Timeline features track phased delivery progress and must be grouped separately for roadmap generation and phase filtering. | -| Domain layer is detected from business context directory segments | Feature files in /deciders/, /orders/, or /inventory/ directories are classified as domain layer. | Domain features define core business rules and must be distinguished from infrastructure tests for accurate coverage reporting. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Timeline layer is detected from /timeline/ directory segments | Any feature file path containing a /timeline/ directory segment is classified as timeline layer. | Timeline features track phased delivery progress and must be grouped separately for roadmap generation and phase filtering. | +| Domain layer is detected from business context directory segments | Feature files in /deciders/, /orders/, or /inventory/ directories are classified as domain layer. | Domain features define core business rules and must be distinguished from infrastructure tests for accurate coverage reporting. | | Integration layer is detected and takes priority over domain directories | Paths containing /integration-features/ or /integration/ are classified as integration, even when they also contain domain directory names. | Integration tests nested under domain directories (e.g., /integration/orders/) would be misclassified as domain without explicit priority, skewing layer coverage metrics. | -| E2E layer is detected from /e2e/ directory segments | Any feature file path containing an /e2e/ directory segment is classified as e2e layer. | E2E tests require separate execution infrastructure and longer timeouts; misclassification would mix them into faster test suites. | -| Component layer is detected from tool-specific directory segments | Feature files in /scanner/ or /lint/ directories are classified as component layer. | Tool-specific features test internal pipeline stages and must be isolated from business domain and integration layers in documentation grouping. | -| Unknown layer is the fallback for unclassified paths | Any feature file path that does not match a known layer pattern is classified as unknown. | Silently dropping unclassified features would create invisible gaps in test coverage; the unknown fallback ensures every feature is accounted for. | -| Path normalization handles cross-platform and case differences | Layer inference produces correct results regardless of path separators, case, or absolute vs relative paths. | The consumer monorepo runs on multiple platforms; platform-dependent classification would produce inconsistent documentation across developer machines and CI. | -| FEATURE_LAYERS constant provides validated layer enumeration | FEATURE_LAYERS is a readonly array containing exactly all 6 valid layer values. | Consumers iterate over FEATURE_LAYERS for exhaustive layer handling; a mutable or incomplete array would cause missed layers at runtime. | +| E2E layer is detected from /e2e/ directory segments | Any feature file path containing an /e2e/ directory segment is classified as e2e layer. | E2E tests require separate execution infrastructure and longer timeouts; misclassification would mix them into faster test suites. | +| Component layer is detected from tool-specific directory segments | Feature files in /scanner/ or /lint/ directories are classified as component layer. | Tool-specific features test internal pipeline stages and must be isolated from business domain and integration layers in documentation grouping. | +| Unknown layer is the fallback for unclassified paths | Any feature file path that does not match a known layer pattern is classified as unknown. | Silently dropping unclassified features would create invisible gaps in test coverage; the unknown fallback ensures every feature is accounted for. | +| Path normalization handles cross-platform and case differences | Layer inference produces correct results regardless of path separators, case, or absolute vs relative paths. | The consumer monorepo runs on multiple platforms; platform-dependent classification would produce inconsistent documentation across developer machines and CI. | +| FEATURE_LAYERS constant provides validated layer enumeration | FEATURE_LAYERS is a readonly array containing exactly all 6 valid layer values. | Consumers iterate over FEATURE_LAYERS for exhaustive layer handling; a mutable or incomplete array would cause missed layers at runtime. | ### Pattern Relationship Model -| Rule | Invariant | Rationale | -| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Rule | Invariant | Rationale | +| --- | --- | --- | | Code files declare pattern realization via implements tag | Files with `@libar-docs-implements:PatternName,OtherPattern` are linked to the specified patterns without causing conflicts. Pattern definitions remain in roadmap specs; implementation files provide supplementary metadata. Multiple files can implement the same pattern, and one file can implement multiple patterns. | This mirrors UML's "realization" relationship where a class implements an interface. Code realizes the specification. Direction is code→spec (backward link). CSV format allows a single implementation file to realize multiple patterns when implementing a pattern family (e.g., durability primitives). | -| Pattern inheritance uses extends relationship tag | Files with `@libar-docs-extends:BasePattern` declare that they extend another pattern's capabilities. This is a generalization relationship where the extending pattern is a specialization of the base pattern. | Pattern families exist where specialized patterns build on base patterns. For example, `ReactiveProjections` extends `ProjectionCategories`. The extends relationship enables inheritance-based documentation and validates pattern hierarchy. | -| Technical dependencies use directed relationship tags | `@libar-docs-uses` declares outbound dependencies (what this pattern depends on). `@libar-docs-used-by` declares inbound dependencies (what depends on this pattern). Both are CSV format. | These represent technical coupling between patterns. The distinction matters for impact analysis: changing a pattern affects its `used-by` consumers but not its `uses` dependencies. | -| Roadmap sequencing uses ordering relationship tags | `@libar-docs-depends-on` declares what must be completed first (roadmap sequencing). `@libar-docs-enables` declares what this unlocks when completed. These are planning relationships, not technical dependencies. | Sequencing is about order of work, not runtime coupling. A pattern may depend on another being complete without using its code. | -| Cross-tier linking uses traceability tags (PDR-007) | `@libar-docs-executable-specs` on roadmap specs points to test locations. `@libar-docs-roadmap-spec` on package specs points back to the pattern. These create bidirectional traceability. | Two-tier architecture (PDR-007) separates planning specs from executable tests. Traceability tags maintain the connection for navigation and completeness checking. | -| Epic/Phase/Task hierarchy uses parent-child relationships | `@libar-docs-level` declares the hierarchy tier (epic, phase, task). `@libar-docs-parent` links to the containing pattern. This enables rollup progress tracking. | Large initiatives decompose into phases and tasks. The hierarchy allows progress aggregation (e.g., "Epic 80% complete based on child phases"). | -| All relationships appear in generated documentation | The PATTERNS.md dependency graph renders all relationship types with distinct visual styles. Pattern detail pages list all related artifacts grouped by relationship type. | Visualization makes the relationship model accessible. Different arrow styles distinguish relationship semantics at a glance. | -| Linter detects relationship violations | The pattern linter validates that all relationship targets exist, implements files don't have pattern tags, and bidirectional links are consistent. | Broken relationships cause confusion and incorrect generated docs. Early detection during linting prevents propagation of errors. | +| Pattern inheritance uses extends relationship tag | Files with `@libar-docs-extends:BasePattern` declare that they extend another pattern's capabilities. This is a generalization relationship where the extending pattern is a specialization of the base pattern. | Pattern families exist where specialized patterns build on base patterns. For example, `ReactiveProjections` extends `ProjectionCategories`. The extends relationship enables inheritance-based documentation and validates pattern hierarchy. | +| Technical dependencies use directed relationship tags | `@libar-docs-uses` declares outbound dependencies (what this pattern depends on). `@libar-docs-used-by` declares inbound dependencies (what depends on this pattern). Both are CSV format. | These represent technical coupling between patterns. The distinction matters for impact analysis: changing a pattern affects its `used-by` consumers but not its `uses` dependencies. | +| Roadmap sequencing uses ordering relationship tags | `@libar-docs-depends-on` declares what must be completed first (roadmap sequencing). `@libar-docs-enables` declares what this unlocks when completed. These are planning relationships, not technical dependencies. | Sequencing is about order of work, not runtime coupling. A pattern may depend on another being complete without using its code. | +| Cross-tier linking uses traceability tags (PDR-007) | `@libar-docs-executable-specs` on roadmap specs points to test locations. `@libar-docs-roadmap-spec` on package specs points back to the pattern. These create bidirectional traceability. | Two-tier architecture (PDR-007) separates planning specs from executable tests. Traceability tags maintain the connection for navigation and completeness checking. | +| Epic/Phase/Task hierarchy uses parent-child relationships | `@libar-docs-level` declares the hierarchy tier (epic, phase, task). `@libar-docs-parent` links to the containing pattern. This enables rollup progress tracking. | Large initiatives decompose into phases and tasks. The hierarchy allows progress aggregation (e.g., "Epic 80% complete based on child phases"). | +| All relationships appear in generated documentation | The PATTERNS.md dependency graph renders all relationship types with distinct visual styles. Pattern detail pages list all related artifacts grouped by relationship type. | Visualization makes the relationship model accessible. Different arrow styles distinguish relationship semantics at a glance. | +| Linter detects relationship violations | The pattern linter validates that all relationship targets exist, implements files don't have pattern tags, and bidirectional links are consistent. | Broken relationships cause confusion and incorrect generated docs. Early detection during linting prevents propagation of errors. | ### Pattern Tag Extraction -| Rule | Invariant | Rationale | -| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Single value tags produce scalar metadata fields | Each single-value tag (pattern, phase, status, brief) maps to exactly one metadata field with the correct type. | Incorrect type coercion (e.g., phase as string instead of number) causes downstream pipeline failures in filtering and sorting. | -| Array value tags accumulate into list metadata fields | Tags for depends-on and enables split comma-separated values and accumulate across multiple tag occurrences. | Missing a dependency value silently breaks the dependency graph, causing incorrect build ordering and orphaned pattern references. | -| Category tags are colon-free tags filtered against known non-categories | Tags without colons become categories, except known non-category tags (acceptance-criteria, happy-path) and the libar-docs opt-in marker. | Including test-control tags (acceptance-criteria, happy-path) as categories pollutes the pattern taxonomy with non-semantic values. | -| Complex tag lists produce fully populated metadata | All tag types (scalar, array, category) are correctly extracted from a single mixed tag list. | Real feature files combine many tag types; extraction must handle all types simultaneously without interference between parsers. | -| Edge cases produce safe defaults | Empty or invalid inputs produce empty metadata or omit invalid fields rather than throwing errors. | Throwing on malformed tags would abort extraction for the entire file, losing valid metadata from well-formed tags. | -| Convention tags support CSV values with whitespace trimming | Convention tags split comma-separated values and trim whitespace from each value. | Untrimmed whitespace creates distinct values for the same convention, causing false negatives in convention-based filtering and validation. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Single value tags produce scalar metadata fields | Each single-value tag (pattern, phase, status, brief) maps to exactly one metadata field with the correct type. | Incorrect type coercion (e.g., phase as string instead of number) causes downstream pipeline failures in filtering and sorting. | +| Array value tags accumulate into list metadata fields | Tags for depends-on and enables split comma-separated values and accumulate across multiple tag occurrences. | Missing a dependency value silently breaks the dependency graph, causing incorrect build ordering and orphaned pattern references. | +| Category tags are colon-free tags filtered against known non-categories | Tags without colons become categories, except known non-category tags (acceptance-criteria, happy-path) and the libar-docs opt-in marker. | Including test-control tags (acceptance-criteria, happy-path) as categories pollutes the pattern taxonomy with non-semantic values. | +| Complex tag lists produce fully populated metadata | All tag types (scalar, array, category) are correctly extracted from a single mixed tag list. | Real feature files combine many tag types; extraction must handle all types simultaneously without interference between parsers. | +| Edge cases produce safe defaults | Empty or invalid inputs produce empty metadata or omit invalid fields rather than throwing errors. | Throwing on malformed tags would abort extraction for the entire file, losing valid metadata from well-formed tags. | +| Convention tags support CSV values with whitespace trimming | Convention tags split comma-separated values and trim whitespace from each value. | Untrimmed whitespace creates distinct values for the same convention, causing false negatives in convention-based filtering and validation. | | Registry-driven extraction handles enums, transforms, and value constraints | Tags defined in the registry use data-driven extraction with enum validation, CSV accumulation, value transforms, and constraint checking. | Hard-coded if/else branches for each tag type cannot scale; registry-driven extraction ensures new tags are supported by configuration, not code changes. | ### Scanner Core -| Rule | Invariant | Rationale | -| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| scanPatterns extracts directives from TypeScript files | Every file with a valid opt-in marker and JSDoc directives produces a complete ScannedFile with tags, description, examples, and exports. | Downstream generators depend on complete directive data; partial extraction causes silent documentation gaps across the monorepo. | -| scanPatterns collects errors without aborting | A parse failure in one file never prevents other files from being scanned; the result is always Ok with errors collected separately. | In a monorepo with hundreds of files, a single syntax error must not block the entire documentation pipeline. | -| Pattern matching and exclusion filtering | Glob patterns control file discovery and exclusion patterns remove matched files before scanning. | Without exclusion filtering, internal directories and generated files would pollute the pattern registry with false positives and slow down scanning. | -| File opt-in requirement gates scanning | Only files containing a standalone @libar-docs marker (not @libar-docs-\*) are eligible for directive extraction. | Without opt-in gating, every TypeScript file in the monorepo would be parsed, wasting processing time on files that have no documentation directives. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| scanPatterns extracts directives from TypeScript files | Every file with a valid opt-in marker and JSDoc directives produces a complete ScannedFile with tags, description, examples, and exports. | Downstream generators depend on complete directive data; partial extraction causes silent documentation gaps across the monorepo. | +| scanPatterns collects errors without aborting | A parse failure in one file never prevents other files from being scanned; the result is always Ok with errors collected separately. | In a monorepo with hundreds of files, a single syntax error must not block the entire documentation pipeline. | +| Pattern matching and exclusion filtering | Glob patterns control file discovery and exclusion patterns remove matched files before scanning. | Without exclusion filtering, internal directories and generated files would pollute the pattern registry with false positives and slow down scanning. | +| File opt-in requirement gates scanning | Only files containing a standalone @libar-docs marker (not @libar-docs-*) are eligible for directive extraction. | Without opt-in gating, every TypeScript file in the monorepo would be parsed, wasting processing time on files that have no documentation directives. | ### Shape Extraction -| Rule | Invariant | Rationale | -| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| extract-shapes tag is defined in registry | The `extract-shapes` tag must exist with CSV format to list multiple type names for extraction. | Without a CSV-format tag, there is no mechanism to specify which type names to extract, and the extractor cannot discover shapes from source files. | -| Interfaces are extracted from TypeScript AST | When `@libar-docs-extract-shapes` lists an interface name, the extractor must find and extract the complete interface definition including JSDoc comments, generics, and extends clauses. | Partial extraction (missing generics, JSDoc, or extends clauses) produces incomplete API documentation that misleads consumers about a type's actual contract. | -| Type aliases are extracted from TypeScript AST | Type aliases (including union types, intersection types, and mapped types) are extracted when listed in extract-shapes. | Type aliases define domain vocabulary (status enums, branded types, utility types) that consumers need to understand API signatures; omitting them leaves gaps in generated documentation. | -| Enums are extracted from TypeScript AST | Both string and numeric enums are extracted with their complete member definitions. | Enum members define the closed set of valid values for a type; extracting only the enum name without its members provides no useful information to documentation consumers. | -| Function signatures are extracted (body omitted) | When a function name is listed in extract-shapes, only the signature (parameters, return type, generics) is extracted. The function body is replaced with ellipsis for documentation purposes. | Including implementation bodies in generated documentation exposes internal logic, bloats output size, and creates a maintenance burden when internals change without API changes. | -| Multiple shapes are extracted in specified order | When multiple shapes are listed, they appear in the documentation in the order specified in the tag, not source order. | Authors intentionally order shapes for progressive disclosure (e.g., output before input); using source order would break the author's intended documentation narrative. | -| Extracted shapes render as fenced code blocks | Codecs render extracted shapes as TypeScript fenced code blocks, grouped under an "API Types" or similar section. | Rendering shapes as plain text or without language hints prevents syntax highlighting and makes API types unreadable in generated markdown documentation. | -| Shapes can reference types from imports | Extracted shapes may reference types from imports. The extractor does NOT resolve imports - it extracts the shape as-is. Consumers understand that referenced types are defined elsewhere. | Resolving imports would require full dependency graph traversal across the codebase, dramatically increasing complexity and coupling the extractor to the project's module structure. | -| Overloaded function signatures are all extracted | When a function has multiple overload signatures, all signatures are extracted together as they represent the complete API. | Extracting only one overload signature hides valid call patterns from consumers, leading to incorrect usage assumptions about the function's capabilities. | -| Shape rendering supports grouping options | Codecs can render shapes grouped in a single code block or as separate code blocks, depending on detail level. | Compact claude-md modules need grouped blocks to minimize token usage, while detailed human docs benefit from separate blocks with individual JSDoc annotations. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| extract-shapes tag is defined in registry | The `extract-shapes` tag must exist with CSV format to list multiple type names for extraction. | Without a CSV-format tag, there is no mechanism to specify which type names to extract, and the extractor cannot discover shapes from source files. | +| Interfaces are extracted from TypeScript AST | When `@libar-docs-extract-shapes` lists an interface name, the extractor must find and extract the complete interface definition including JSDoc comments, generics, and extends clauses. | Partial extraction (missing generics, JSDoc, or extends clauses) produces incomplete API documentation that misleads consumers about a type's actual contract. | +| Type aliases are extracted from TypeScript AST | Type aliases (including union types, intersection types, and mapped types) are extracted when listed in extract-shapes. | Type aliases define domain vocabulary (status enums, branded types, utility types) that consumers need to understand API signatures; omitting them leaves gaps in generated documentation. | +| Enums are extracted from TypeScript AST | Both string and numeric enums are extracted with their complete member definitions. | Enum members define the closed set of valid values for a type; extracting only the enum name without its members provides no useful information to documentation consumers. | +| Function signatures are extracted (body omitted) | When a function name is listed in extract-shapes, only the signature (parameters, return type, generics) is extracted. The function body is replaced with ellipsis for documentation purposes. | Including implementation bodies in generated documentation exposes internal logic, bloats output size, and creates a maintenance burden when internals change without API changes. | +| Multiple shapes are extracted in specified order | When multiple shapes are listed, they appear in the documentation in the order specified in the tag, not source order. | Authors intentionally order shapes for progressive disclosure (e.g., output before input); using source order would break the author's intended documentation narrative. | +| Extracted shapes render as fenced code blocks | Codecs render extracted shapes as TypeScript fenced code blocks, grouped under an "API Types" or similar section. | Rendering shapes as plain text or without language hints prevents syntax highlighting and makes API types unreadable in generated markdown documentation. | +| Shapes can reference types from imports | Extracted shapes may reference types from imports. The extractor does NOT resolve imports - it extracts the shape as-is. Consumers understand that referenced types are defined elsewhere. | Resolving imports would require full dependency graph traversal across the codebase, dramatically increasing complexity and coupling the extractor to the project's module structure. | +| Overloaded function signatures are all extracted | When a function has multiple overload signatures, all signatures are extracted together as they represent the complete API. | Extracting only one overload signature hides valid call patterns from consumers, leading to incorrect usage assumptions about the function's capabilities. | +| Shape rendering supports grouping options | Codecs can render shapes grouped in a single code block or as separate code blocks, depending on detail level. | Compact claude-md modules need grouped blocks to minimize token usage, while detailed human docs benefit from separate blocks with individual JSDoc annotations. | ### Shape Extraction Rendering Testing -| Rule | Invariant | Rationale | -| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Multiple shapes are extracted in specified order | Extracted shapes appear in the order specified by the tag list, not in source file declaration order. | Documentation consumers rely on tag-specified ordering for consistent, predictable layout regardless of how source files are organized. | -| Extracted shapes render as fenced code blocks | Every extracted shape renders as a fenced TypeScript code block in the markdown output. | Fenced code blocks provide syntax highlighting and preserve type definition formatting, which is essential for readable API documentation. | -| Imported and re-exported shapes are tracked separately | Shapes resolved via import or re-export statements are classified distinctly from locally declared shapes. | Silently extracting imported types as if they were local declarations would produce duplicate or misleading documentation, since the canonical definition lives in another file. | -| Invalid TypeScript produces error result | Malformed TypeScript source returns an error Result instead of throwing or producing partial shapes. | Unhandled parse exceptions would crash the pipeline mid-run, preventing all subsequent files from being processed. | -| Shape rendering supports grouping options | The `groupInSingleBlock` option controls whether shapes render in one combined code fence or in separate per-shape code fences. | Different documentation layouts require different grouping strategies; a single block provides compact overviews while separate blocks allow per-type commentary. | -| Annotation tags are stripped from extracted JSDoc while preserving standard tags | Extracted shapes never contain @libar-docs-\* annotation lines in their jsDoc field. | Shape JSDoc is rendered in documentation output. Annotation tags are metadata for the extraction pipeline, not user-visible documentation content. | -| Large source files are rejected to prevent memory exhaustion | Source files exceeding 5MB are rejected before parsing begins. | Feeding unbounded input to the TypeScript parser risks out-of-memory crashes that would halt the entire extraction pipeline. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Multiple shapes are extracted in specified order | Extracted shapes appear in the order specified by the tag list, not in source file declaration order. | Documentation consumers rely on tag-specified ordering for consistent, predictable layout regardless of how source files are organized. | +| Extracted shapes render as fenced code blocks | Every extracted shape renders as a fenced TypeScript code block in the markdown output. | Fenced code blocks provide syntax highlighting and preserve type definition formatting, which is essential for readable API documentation. | +| Imported and re-exported shapes are tracked separately | Shapes resolved via import or re-export statements are classified distinctly from locally declared shapes. | Silently extracting imported types as if they were local declarations would produce duplicate or misleading documentation, since the canonical definition lives in another file. | +| Invalid TypeScript produces error result | Malformed TypeScript source returns an error Result instead of throwing or producing partial shapes. | Unhandled parse exceptions would crash the pipeline mid-run, preventing all subsequent files from being processed. | +| Shape rendering supports grouping options | The `groupInSingleBlock` option controls whether shapes render in one combined code fence or in separate per-shape code fences. | Different documentation layouts require different grouping strategies; a single block provides compact overviews while separate blocks allow per-type commentary. | +| Annotation tags are stripped from extracted JSDoc while preserving standard tags | Extracted shapes never contain @libar-docs-* annotation lines in their jsDoc field. | Shape JSDoc is rendered in documentation output. Annotation tags are metadata for the extraction pipeline, not user-visible documentation content. | +| Large source files are rejected to prevent memory exhaustion | Source files exceeding 5MB are rejected before parsing begins. | Feeding unbounded input to the TypeScript parser risks out-of-memory crashes that would halt the entire extraction pipeline. | ### Shape Extraction Types Testing -| Rule | Invariant | Rationale | -| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| extract-shapes tag exists in registry with CSV format | The `extract-shapes` tag must be registered with CSV format so multiple shape names can be specified in a single annotation. | Without CSV format registration, the tag parser cannot split comma-separated shape lists, causing only the first shape to be extracted. | -| Interfaces are extracted from TypeScript AST | Every named interface declaration in a TypeScript source file must be extractable as a shape with kind `interface`, including generics, extends clauses, and JSDoc. | Interfaces are the primary API surface for TypeScript libraries; failing to extract them leaves the most important type contracts undocumented. | -| Property-level JSDoc is extracted for interface properties | Property-level JSDoc must be attributed only to the immediately adjacent property, never inherited from the parent interface declaration. | Misattributing interface-level JSDoc to the first property produces incorrect per-field documentation and misleads consumers about individual property semantics. The extractor uses strict adjacency (gap = 1 line) to prevent interface-level JSDoc from being misattributed to the first property. | -| Type aliases are extracted from TypeScript AST | Union types, mapped types, and conditional types must all be extractable as shapes with kind `type`, preserving their full type expression. | Type aliases encode domain constraints (e.g., discriminated unions, mapped utilities) that are essential for API documentation; omitting them hides the type-level design. | -| Enums are extracted from TypeScript AST | Both regular and const enums must be extractable as shapes with kind `enum`, including their member values. | Enums define finite value sets used in validation and serialization; missing them from documentation forces consumers to read source code to discover valid values. | -| Function signatures are extracted with body omitted | Extracted function shapes must include the full signature (name, parameters, return type, async modifier) but never the implementation body. | Including function bodies in documentation exposes implementation details, inflates output size, and creates a maintenance burden when internals change without signature changes. | -| Const declarations are extracted from TypeScript AST | Const declarations must be extractable as shapes with kind `const`, whether or not they carry an explicit type annotation. | Constants define configuration defaults, version strings, and sentinel values that consumers depend on; excluding them creates documentation gaps for public API surface. | -| Non-exported shapes are extractable | Shape extraction must succeed for declarations regardless of export status, with the `exported` flag accurately reflecting visibility. | Internal types often define the core domain model; restricting extraction to exports only would omit types that are essential for understanding module internals. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| extract-shapes tag exists in registry with CSV format | The `extract-shapes` tag must be registered with CSV format so multiple shape names can be specified in a single annotation. | Without CSV format registration, the tag parser cannot split comma-separated shape lists, causing only the first shape to be extracted. | +| Interfaces are extracted from TypeScript AST | Every named interface declaration in a TypeScript source file must be extractable as a shape with kind `interface`, including generics, extends clauses, and JSDoc. | Interfaces are the primary API surface for TypeScript libraries; failing to extract them leaves the most important type contracts undocumented. | +| Property-level JSDoc is extracted for interface properties | Property-level JSDoc must be attributed only to the immediately adjacent property, never inherited from the parent interface declaration. | Misattributing interface-level JSDoc to the first property produces incorrect per-field documentation and misleads consumers about individual property semantics. The extractor uses strict adjacency (gap = 1 line) to prevent interface-level JSDoc from being misattributed to the first property. | +| Type aliases are extracted from TypeScript AST | Union types, mapped types, and conditional types must all be extractable as shapes with kind `type`, preserving their full type expression. | Type aliases encode domain constraints (e.g., discriminated unions, mapped utilities) that are essential for API documentation; omitting them hides the type-level design. | +| Enums are extracted from TypeScript AST | Both regular and const enums must be extractable as shapes with kind `enum`, including their member values. | Enums define finite value sets used in validation and serialization; missing them from documentation forces consumers to read source code to discover valid values. | +| Function signatures are extracted with body omitted | Extracted function shapes must include the full signature (name, parameters, return type, async modifier) but never the implementation body. | Including function bodies in documentation exposes implementation details, inflates output size, and creates a maintenance burden when internals change without signature changes. | +| Const declarations are extracted from TypeScript AST | Const declarations must be extractable as shapes with kind `const`, whether or not they carry an explicit type annotation. | Constants define configuration defaults, version strings, and sentinel values that consumers depend on; excluding them creates documentation gaps for public API surface. | +| Non-exported shapes are extractable | Shape extraction must succeed for declarations regardless of export status, with the `exported` flag accurately reflecting visibility. | Internal types often define the core domain model; restricting extraction to exports only would omit types that are essential for understanding module internals. | ### Uses Tag Testing -| Rule | Invariant | Rationale | -| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -| Uses tag is defined in taxonomy registry | The uses and used-by tags must be registered in the taxonomy with CSV format and dependency-related purpose descriptions. | Without registry definitions, the data-driven AST parser cannot discover or extract these tags from source files. | -| Uses tag is extracted from TypeScript files | The AST parser must extract single and comma-separated uses values from TypeScript JSDoc annotations. | Missing or malformed uses extraction breaks runtime dependency tracking and produces incomplete relationship diagrams. | -| Used-by tag is extracted from TypeScript files | The AST parser must extract single and comma-separated used-by values from TypeScript JSDoc annotations. | Missing used-by extraction prevents reverse dependency lookups, leaving consumers unable to discover which patterns depend on them. | -| Uses relationships are stored in relationship index | All declared uses and usedBy relationships must be stored in the relationship index as explicitly declared entries. | Omitting relationships from the index causes dependency diagrams and impact-analysis queries to silently miss connections. | -| Schemas validate uses field correctly | DocDirective and RelationshipEntry schemas must accept uses and usedBy fields as valid CSV string values. | Schema rejection of valid uses/usedBy values causes runtime parse failures that silently drop relationship data. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Uses tag is defined in taxonomy registry | The uses and used-by tags must be registered in the taxonomy with CSV format and dependency-related purpose descriptions. | Without registry definitions, the data-driven AST parser cannot discover or extract these tags from source files. | +| Uses tag is extracted from TypeScript files | The AST parser must extract single and comma-separated uses values from TypeScript JSDoc annotations. | Missing or malformed uses extraction breaks runtime dependency tracking and produces incomplete relationship diagrams. | +| Used-by tag is extracted from TypeScript files | The AST parser must extract single and comma-separated used-by values from TypeScript JSDoc annotations. | Missing used-by extraction prevents reverse dependency lookups, leaving consumers unable to discover which patterns depend on them. | +| Uses relationships are stored in relationship index | All declared uses and usedBy relationships must be stored in the relationship index as explicitly declared entries. | Omitting relationships from the index causes dependency diagrams and impact-analysis queries to silently miss connections. | +| Schemas validate uses field correctly | DocDirective and RelationshipEntry schemas must accept uses and usedBy fields as valid CSV string values. | Schema rejection of valid uses/usedBy values causes runtime parse failures that silently drop relationship data. | --- diff --git a/docs-live/product-areas/CONFIGURATION.md b/docs-live/product-areas/CONFIGURATION.md index a8145ceb..415ed7df 100644 --- a/docs-live/product-areas/CONFIGURATION.md +++ b/docs-live/product-areas/CONFIGURATION.md @@ -16,6 +16,16 @@ --- +## Contents + +- [Key Invariants](#key-invariants) +- [Configuration Loading Boundary](#configuration-loading-boundary) +- [Configuration Resolution Pipeline](#configuration-resolution-pipeline) +- [API Types](#api-types) +- [Business Rules](#business-rules) + +--- + ## Configuration Loading Boundary Scoped architecture diagram showing component relationships: @@ -145,13 +155,13 @@ interface DeliveryProcessConfig { } ```` -| Property | Description | -| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| tagPrefix | Tag prefix for directives (e.g., "@docs-" or "@libar-docs-") | -| fileOptInTag | File-level opt-in tag (e.g., "@docs" or "@libar-docs") | -| categories | Category definitions for pattern classification | -| metadataTags | Optional metadata tag definitions | -| contextInferenceRules | Optional context inference rules for auto-inferring bounded context from file paths. When provided, these rules are merged with the default rules. User-provided rules take precedence over defaults (applied first in the rule list). `typescript contextInferenceRules: [ { pattern: 'packages/orders/**', context: 'orders' }, { pattern: 'packages/inventory/**', context: 'inventory' }, ] ` | +| Property | Description | +| --- | --- | +| tagPrefix | Tag prefix for directives (e.g., "@docs-" or "@libar-docs-") | +| fileOptInTag | File-level opt-in tag (e.g., "@docs" or "@libar-docs") | +| categories | Category definitions for pattern classification | +| metadataTags | Optional metadata tag definitions | +| contextInferenceRules | Optional context inference rules for auto-inferring bounded context from file paths. When provided, these rules are merged with the default rules. User-provided rules take precedence over defaults (applied first in the rule list). ```typescript contextInferenceRules: [ { pattern: 'packages/orders/**', context: 'orders' }, { pattern: 'packages/inventory/**', context: 'inventory' }, ] ``` | ### DeliveryProcessInstance (interface) @@ -170,10 +180,10 @@ interface DeliveryProcessInstance { } ``` -| Property | Description | -| ------------- | --------------------------------- | -| registry | The fully configured tag registry | -| regexBuilders | Regex builders for tag detection | +| Property | Description | +| --- | --- | +| registry | The fully configured tag registry | +| regexBuilders | Regex builders for tag detection | ### RegexBuilders (interface) @@ -201,9 +211,9 @@ interface RegexBuilders { } ``` -| Property | Description | -| ---------------- | --------------------------------------------------------------- | -| fileOptInPattern | Pattern to match file-level opt-in (e.g., /\*_ @docs _\/) | +| Property | Description | +| --- | --- | +| fileOptInPattern | Pattern to match file-level opt-in (e.g., /** @docs *\/) | | directivePattern | Pattern to match directives (e.g., @docs-pattern, @docs-status) | ### DeliveryProcessProjectConfig (interface) @@ -298,20 +308,20 @@ interface DeliveryProcessProjectConfig { } ``` -| Property | Description | -| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| preset | Use a preset taxonomy configuration | -| tagPrefix | Custom tag prefix (overrides preset, e.g., '@docs-') | -| fileOptInTag | Custom file opt-in tag (overrides preset, e.g., '@docs') | -| categories | Custom categories (replaces preset categories entirely) | -| sources | Source file glob configuration | -| output | Output configuration for generated docs | -| generators | Default generator names to run when CLI doesn't specify --generators | -| generatorOverrides | Per-generator source and output overrides | -| contextInferenceRules | Rules for auto-inferring bounded context from file paths | -| workflowPath | Path to custom workflow config JSON (relative to config file) | -| codecOptions | Per-codec options for fine-tuning document generation. Keys match codec names (e.g., 'business-rules', 'patterns'). Passed through to codec factories at generation time. | -| referenceDocConfigs | Reference document configurations for convention-based doc generation. Each config defines one reference document's content composition via convention tags, shape sources, behavior categories, and diagram scopes. When not specified, no reference generators are registered. Import `LIBAR_REFERENCE_CONFIGS` from the generators module to use the built-in set. | +| Property | Description | +| --- | --- | +| preset | Use a preset taxonomy configuration | +| tagPrefix | Custom tag prefix (overrides preset, e.g., '@docs-') | +| fileOptInTag | Custom file opt-in tag (overrides preset, e.g., '@docs') | +| categories | Custom categories (replaces preset categories entirely) | +| sources | Source file glob configuration | +| output | Output configuration for generated docs | +| generators | Default generator names to run when CLI doesn't specify --generators | +| generatorOverrides | Per-generator source and output overrides | +| contextInferenceRules | Rules for auto-inferring bounded context from file paths | +| workflowPath | Path to custom workflow config JSON (relative to config file) | +| codecOptions | Per-codec options for fine-tuning document generation. Keys match codec names (e.g., 'business-rules', 'patterns'). Passed through to codec factories at generation time. | +| referenceDocConfigs | Reference document configurations for convention-based doc generation. Each config defines one reference document's content composition via convention tags, shape sources, behavior categories, and diagram scopes. When not specified, no reference generators are registered. Import `LIBAR_REFERENCE_CONFIGS` from the generators module to use the built-in set. | ### SourcesConfig (interface) @@ -345,12 +355,12 @@ interface SourcesConfig { } ``` -| Property | Description | -| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| typescript | Glob patterns for TypeScript source files (replaces --input) | -| features | Glob patterns for Gherkin feature files (replaces --features). Includes both `.feature` and `.feature.md` files. | -| stubs | Glob patterns for design stub files. Stubs are TypeScript files that live outside `src/` (e.g., `delivery-process/stubs/`). Merged into TypeScript sources at resolution time. | -| exclude | Glob patterns to exclude from all scanning | +| Property | Description | +| --- | --- | +| typescript | Glob patterns for TypeScript source files (replaces --input) | +| features | Glob patterns for Gherkin feature files (replaces --features). Includes both `.feature` and `.feature.md` files. | +| stubs | Glob patterns for design stub files. Stubs are TypeScript files that live outside `src/` (e.g., `delivery-process/stubs/`). Merged into TypeScript sources at resolution time. | +| exclude | Glob patterns to exclude from all scanning | ### OutputConfig (interface) @@ -369,10 +379,10 @@ interface OutputConfig { } ``` -| Property | Description | -| --------- | ------------------------------------------------------------------ | +| Property | Description | +| --- | --- | | directory | Output directory for generated docs (default: 'docs/architecture') | -| overwrite | Overwrite existing files (default: false) | +| overwrite | Overwrite existing files (default: false) | ### GeneratorSourceOverride (interface) @@ -420,12 +430,12 @@ interface GeneratorSourceOverride { } ``` -| Property | Description | -| ------------------ | ---------------------------------------------------------------------------------------------------- | -| additionalFeatures | Additional feature file globs appended to base features | -| additionalInput | Additional TypeScript globs appended to base TypeScript sources | -| replaceFeatures | Feature globs used INSTEAD of base features. Mutually exclusive with non-empty `additionalFeatures`. | -| outputDirectory | Override output directory for this generator | +| Property | Description | +| --- | --- | +| additionalFeatures | Additional feature file globs appended to base features | +| additionalInput | Additional TypeScript globs appended to base TypeScript sources | +| replaceFeatures | Feature globs used INSTEAD of base features. Mutually exclusive with non-empty `additionalFeatures`. | +| outputDirectory | Override output directory for this generator | ### ResolvedProjectConfig (interface) @@ -456,16 +466,16 @@ interface ResolvedProjectConfig { } ``` -| Property | Description | -| --------------------- | ---------------------------------------------------------- | -| sources | Resolved source globs (stubs merged, defaults applied) | -| output | Resolved output config with all defaults | -| generators | Default generator names | -| generatorOverrides | Per-generator source overrides | +| Property | Description | +| --- | --- | +| sources | Resolved source globs (stubs merged, defaults applied) | +| output | Resolved output config with all defaults | +| generators | Default generator names | +| generatorOverrides | Per-generator source overrides | | contextInferenceRules | Context inference rules (user rules prepended to defaults) | -| workflowPath | Workflow config path (null if not specified) | -| codecOptions | Per-codec options for document generation (empty if none) | -| referenceDocConfigs | Reference document configurations (empty array if none) | +| workflowPath | Workflow config path (null if not specified) | +| codecOptions | Per-codec options for document generation (empty if none) | +| referenceDocConfigs | Reference document configurations (empty array if none) | ### ResolvedSourcesConfig (interface) @@ -486,11 +496,11 @@ interface ResolvedSourcesConfig { } ``` -| Property | Description | -| ---------- | ----------------------------------------------- | +| Property | Description | +| --- | --- | | typescript | TypeScript source globs (includes merged stubs) | -| features | Gherkin feature file globs | -| exclude | Glob patterns to exclude from scanning | +| features | Gherkin feature file globs | +| exclude | Glob patterns to exclude from scanning | ### CreateDeliveryProcessOptions (interface) @@ -513,12 +523,12 @@ interface CreateDeliveryProcessOptions { } ``` -| Property | Description | -| ------------ | ------------------------------------------------------- | -| preset | Use a preset configuration | -| tagPrefix | Custom tag prefix (overrides preset) | -| fileOptInTag | Custom file opt-in tag (overrides preset) | -| categories | Custom categories (replaces preset categories entirely) | +| Property | Description | +| --- | --- | +| preset | Use a preset configuration | +| tagPrefix | Custom tag prefix (overrides preset) | +| fileOptInTag | Custom file opt-in tag (overrides preset) | +| categories | Custom categories (replaces preset categories entirely) | ### ConfigDiscoveryResult (interface) @@ -541,12 +551,12 @@ interface ConfigDiscoveryResult { } ``` -| Property | Description | -| --------- | ------------------------------------------- | -| found | Whether a config file was found | -| path | Absolute path to the config file (if found) | -| instance | The loaded configuration instance | -| isDefault | Whether the default configuration was used | +| Property | Description | +| --- | --- | +| found | Whether a config file was found | +| path | Absolute path to the config file (if found) | +| instance | The loaded configuration instance | +| isDefault | Whether the default configuration was used | ### ConfigLoadError (interface) @@ -569,12 +579,12 @@ interface ConfigLoadError { } ``` -| Property | Description | -| -------- | ----------------------------------------------------- | -| type | Discriminant for error type identification | -| path | Absolute path to the config file that failed to load | -| message | Human-readable error description | -| cause | The underlying error that caused the failure (if any) | +| Property | Description | +| --- | --- | +| type | Discriminant for error type identification | +| path | Absolute path to the config file that failed to load | +| message | Human-readable error description | +| cause | The underlying error that caused the failure (if any) | ### ResolvedConfig (type) @@ -682,10 +692,10 @@ type ConfigLoadResult = function createRegexBuilders(tagPrefix: string, fileOptInTag: string): RegexBuilders; ``` -| Parameter | Type | Description | -| ------------ | ---- | ---------------------------------------------------- | -| tagPrefix | | The tag prefix (e.g., "@docs-" or "@libar-docs-") | -| fileOptInTag | | The file opt-in tag (e.g., "@docs" or "@libar-docs") | +| Parameter | Type | Description | +| --- | --- | --- | +| tagPrefix | | The tag prefix (e.g., "@docs-" or "@libar-docs-") | +| fileOptInTag | | The file opt-in tag (e.g., "@docs" or "@libar-docs") | **Returns:** RegexBuilders instance with pattern matching methods @@ -733,12 +743,14 @@ function createRegexBuilders(tagPrefix: string, fileOptInTag: string): RegexBuil ```` ```typescript -function createDeliveryProcess(options: CreateDeliveryProcessOptions = {}): DeliveryProcessInstance; +function createDeliveryProcess( + options: CreateDeliveryProcessOptions = {} +): DeliveryProcessInstance; ``` -| Parameter | Type | Description | -| --------- | ---- | --------------------- | -| options | | Configuration options | +| Parameter | Type | Description | +| --- | --- | --- | +| options | | Configuration options | **Returns:** Configured delivery process instance @@ -757,9 +769,9 @@ function createDeliveryProcess(options: CreateDeliveryProcessOptions = {}): Deli async function findConfigFile(startDir: string): Promise; ``` -| Parameter | Type | Description | -| --------- | ---- | --------------------------------- | -| startDir | | Directory to start searching from | +| Parameter | Type | Description | +| --- | --- | --- | +| startDir | | Directory to start searching from | **Returns:** Path to config file or null if not found @@ -798,9 +810,9 @@ async function findConfigFile(startDir: string): Promise; async function loadConfig(baseDir: string): Promise; ``` -| Parameter | Type | Description | -| --------- | ---- | --------------------------------------------------------------- | -| baseDir | | Directory to start searching from (usually cwd or project root) | +| Parameter | Type | Description | +| --- | --- | --- | +| baseDir | | Directory to start searching from (usually cwd or project root) | **Returns:** Result with loaded configuration or error @@ -819,9 +831,9 @@ async function loadConfig(baseDir: string): Promise; function formatConfigError(error: ConfigLoadError): string; ``` -| Parameter | Type | Description | -| --------- | ---- | ----------------- | -| error | | Config load error | +| Parameter | Type | Description | +| --- | --- | --- | +| error | | Config load error | **Returns:** Formatted error message @@ -873,7 +885,7 @@ GENERIC_PRESET = { aliases: ['infrastructure'], }, ] as const satisfies readonly CategoryDefinition[], -} as const satisfies DeliveryProcessConfig; +} as const satisfies DeliveryProcessConfig ``` ### LIBAR_GENERIC_PRESET (const) @@ -931,7 +943,7 @@ LIBAR_GENERIC_PRESET = { aliases: ['infrastructure'], }, ] as const satisfies readonly CategoryDefinition[], -} as const satisfies DeliveryProcessConfig; +} as const satisfies DeliveryProcessConfig ``` ### DDD_ES_CQRS_PRESET (const) @@ -961,7 +973,7 @@ DDD_ES_CQRS_PRESET = { fileOptInTag: DEFAULT_FILE_OPT_IN_TAG, categories: CATEGORIES, metadataTags: buildRegistry().metadataTags, -} as const satisfies DeliveryProcessConfig; +} as const satisfies DeliveryProcessConfig ``` ### PRESETS (const) @@ -993,78 +1005,78 @@ const PRESETS: Record; ### Config Based Workflow Definition -| Rule | Invariant | Rationale | -| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Default workflow is built from an inline constant | `loadDefaultWorkflow()` returns a `LoadedWorkflow` without file system access. It cannot fail. The default workflow constant uses only canonical status values from `src/taxonomy/status-values.ts`. | The file-based loading path (`catalogue/workflows/`) has been dead code since monorepo extraction. Both callers (orchestrator, process-api) already handle the failure gracefully, proving the system works without it. Making the function synchronous and infallible removes the try-catch ceremony and the warning noise. | -| Custom workflow files still work via --workflow flag | `loadWorkflowFromPath()` remains available for projects that need custom workflow definitions. The `--workflow ` CLI flag and `workflowPath` config field continue to work. | The inline default replaces file-based _default_ loading, not file-based _custom_ loading. Projects may define custom phases or additional statuses via JSON files. | -| FSM validation and Process Guard are not affected | The FSM transition matrix, protection levels, and Process Guard rules remain hardcoded in `src/validation/fsm/` and `src/lint/process-guard/`. They do not read from `LoadedWorkflow`. | FSM and workflow are separate concerns. FSM enforces status transitions (4-state model from PDR-005). Workflow defines phase structure (6-phase USDP). The workflow JSON declared `transitionsTo` on its statuses, but no code ever read those values — the FSM uses its own `VALID_TRANSITIONS` constant. This separation is correct and intentional. Blast radius analysis confirmed zero workflow imports in: - src/validation/fsm/ (4 files) - src/lint/process-guard/ (5 files) - src/taxonomy/ (all files) | -| Workflow as a configurable preset field is deferred | The inline default workflow constant is the only workflow source until preset integration is implemented. No preset or project config field exposes workflow customization. | Coupling workflow into the preset/config system before the inline fix ships would widen the blast radius and risk type regressions across all config consumers. Adding `workflow` as a field on `DeliveryProcessConfig` (presets) and `DeliveryProcessProjectConfig` (project config) is a natural next step but NOT required for the MVP fix. The inline constant in `workflow-loader.ts` resolves the warning. Moving workflow into the preset/config system enables: - Different presets with different default phases (e.g., 3-phase generic) - Per-project phase customization in delivery-process.config.ts - Phase definitions appearing in generated documentation See ideation artifact for design options: delivery-process/ideations/2026-02-15-workflow-config-and-fsm-extensibility.feature | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Default workflow is built from an inline constant | `loadDefaultWorkflow()` returns a `LoadedWorkflow` without file system access. It cannot fail. The default workflow constant uses only canonical status values from `src/taxonomy/status-values.ts`. | The file-based loading path (`catalogue/workflows/`) has been dead code since monorepo extraction. Both callers (orchestrator, process-api) already handle the failure gracefully, proving the system works without it. Making the function synchronous and infallible removes the try-catch ceremony and the warning noise. | +| Custom workflow files still work via --workflow flag | `loadWorkflowFromPath()` remains available for projects that need custom workflow definitions. The `--workflow ` CLI flag and `workflowPath` config field continue to work. | The inline default replaces file-based *default* loading, not file-based *custom* loading. Projects may define custom phases or additional statuses via JSON files. | +| FSM validation and Process Guard are not affected | The FSM transition matrix, protection levels, and Process Guard rules remain hardcoded in `src/validation/fsm/` and `src/lint/process-guard/`. They do not read from `LoadedWorkflow`. | FSM and workflow are separate concerns. FSM enforces status transitions (4-state model from PDR-005). Workflow defines phase structure (6-phase USDP). The workflow JSON declared `transitionsTo` on its statuses, but no code ever read those values — the FSM uses its own `VALID_TRANSITIONS` constant. This separation is correct and intentional. Blast radius analysis confirmed zero workflow imports in: - src/validation/fsm/ (4 files) - src/lint/process-guard/ (5 files) - src/taxonomy/ (all files) | +| Workflow as a configurable preset field is deferred | The inline default workflow constant is the only workflow source until preset integration is implemented. No preset or project config field exposes workflow customization. | Coupling workflow into the preset/config system before the inline fix ships would widen the blast radius and risk type regressions across all config consumers. | ### Config Loader Testing -| Rule | Invariant | Rationale | -| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| Rule | Invariant | Rationale | +| --- | --- | --- | | Config files are discovered by walking up directories | The config loader must search for configuration files starting from the current directory and walking up parent directories until a match is found or the filesystem root is reached. | Projects may run CLI commands from subdirectories — upward traversal ensures the nearest config file is always found regardless of working directory. | -| Config discovery stops at repo root | Directory traversal must stop at repository root markers (e.g., .git directory) and not search beyond them. | Searching beyond the repo root could find unrelated config files from parent projects, producing confusing cross-project behavior. | -| Config is loaded and validated | Loaded config files must have a valid default export matching the expected configuration schema, with appropriate error messages for invalid formats. | Invalid configurations produce cryptic downstream errors — early validation with clear messages prevents debugging wasted on malformed config. | -| Config errors are formatted for display | Configuration loading errors must be formatted as human-readable messages including the file path and specific error description. | Raw error objects are not actionable — developers need the config file path and a clear description to diagnose and fix configuration issues. | +| Config discovery stops at repo root | Directory traversal must stop at repository root markers (e.g., .git directory) and not search beyond them. | Searching beyond the repo root could find unrelated config files from parent projects, producing confusing cross-project behavior. | +| Config is loaded and validated | Loaded config files must have a valid default export matching the expected configuration schema, with appropriate error messages for invalid formats. | Invalid configurations produce cryptic downstream errors — early validation with clear messages prevents debugging wasted on malformed config. | +| Config errors are formatted for display | Configuration loading errors must be formatted as human-readable messages including the file path and specific error description. | Raw error objects are not actionable — developers need the config file path and a clear description to diagnose and fix configuration issues. | ### Config Resolution -| Rule | Invariant | Rationale | -| ------------------------------------------ | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------- | -| Default config provides sensible fallbacks | A config created without user input must have isDefault=true and empty source collections. | Downstream consumers need a safe starting point when no config file exists. | -| Preset creates correct taxonomy instance | Each preset must produce a taxonomy with the correct number of categories and tag prefix. | Presets are the primary user-facing configuration — wrong category counts break downstream scanning. | -| Stubs are merged into typescript sources | Stub glob patterns must appear in resolved typescript sources alongside original globs. | Stubs extend the scanner's source set without requiring users to manually list them. | -| Output defaults are applied | Missing output configuration must resolve to "docs/architecture" with overwrite=false. | Consistent defaults prevent accidental overwrites and establish a predictable output location. | -| Generator defaults are applied | A config with no generators specified must default to the "patterns" generator. | Patterns is the most commonly needed output — defaulting to it reduces boilerplate. | -| Context inference rules are prepended | User-defined inference rules must appear before built-in defaults in the resolved array. | Prepending gives user rules priority during context matching without losing defaults. | -| Config path is carried from options | The configPath from resolution options must be preserved unchanged in resolved config. | Downstream tools need the original config file location for error reporting and relative path resolution. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Default config provides sensible fallbacks | A config created without user input must have isDefault=true and empty source collections. | Downstream consumers need a safe starting point when no config file exists. | +| Preset creates correct taxonomy instance | Each preset must produce a taxonomy with the correct number of categories and tag prefix. | Presets are the primary user-facing configuration — wrong category counts break downstream scanning. | +| Stubs are merged into typescript sources | Stub glob patterns must appear in resolved typescript sources alongside original globs. | Stubs extend the scanner's source set without requiring users to manually list them. | +| Output defaults are applied | Missing output configuration must resolve to "docs/architecture" with overwrite=false. | Consistent defaults prevent accidental overwrites and establish a predictable output location. | +| Generator defaults are applied | A config with no generators specified must default to the "patterns" generator. | Patterns is the most commonly needed output — defaulting to it reduces boilerplate. | +| Context inference rules are prepended | User-defined inference rules must appear before built-in defaults in the resolved array. | Prepending gives user rules priority during context matching without losing defaults. | +| Config path is carried from options | The configPath from resolution options must be preserved unchanged in resolved config. | Downstream tools need the original config file location for error reporting and relative path resolution. | ### Configuration API -| Rule | Invariant | Rationale | -| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Rule | Invariant | Rationale | +| --- | --- | --- | | Factory creates configured instances with correct defaults | The configuration factory must produce a fully initialized instance for any supported preset, with the libar-generic preset as the default when no arguments are provided. | A sensible default preset eliminates boilerplate for the common case while still supporting specialized presets (ddd-es-cqrs) for advanced monorepo configurations. | -| Custom prefix configuration works correctly | Custom tag prefix and file opt-in tag overrides must be applied to the configuration instance, replacing the preset defaults. | Consuming projects may use different annotation prefixes — custom prefixes enable the toolkit to work with any tag convention without forking presets. | -| Preset categories replace base categories entirely | When a preset defines its own category set, it must fully replace (not merge with) the base categories. | Category sets are curated per-preset — merging would include irrelevant categories (e.g., DDD categories in a generic project) that pollute taxonomy reports. | -| Regex builders use configured prefix | All regex builders (hasFileOptIn, hasDocDirectives, normalizeTag) must use the configured tag prefix, not a hardcoded one. | Regex patterns that ignore the configured prefix would miss annotations in projects using custom prefixes, silently skipping source files. | +| Custom prefix configuration works correctly | Custom tag prefix and file opt-in tag overrides must be applied to the configuration instance, replacing the preset defaults. | Consuming projects may use different annotation prefixes — custom prefixes enable the toolkit to work with any tag convention without forking presets. | +| Preset categories replace base categories entirely | When a preset defines its own category set, it must fully replace (not merge with) the base categories. | Category sets are curated per-preset — merging would include irrelevant categories (e.g., DDD categories in a generic project) that pollute taxonomy reports. | +| Regex builders use configured prefix | All regex builders (hasFileOptIn, hasDocDirectives, normalizeTag) must use the configured tag prefix, not a hardcoded one. | Regex patterns that ignore the configured prefix would miss annotations in projects using custom prefixes, silently skipping source files. | ### Define Config Testing -| Rule | Invariant | Rationale | -| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| defineConfig is an identity function | The defineConfig helper must return its input unchanged, serving only as a type annotation aid for IDE autocomplete. | defineConfig exists for TypeScript type inference in config files — any transformation would surprise users who expect their config object to pass through unmodified. | -| Schema validates correct configurations | Valid configuration objects (both minimal and fully-specified) must pass schema validation without errors. | The schema must accept all legitimate configuration shapes — rejecting valid configs would block users from using supported features. | -| Schema rejects invalid configurations | The configuration schema must reject invalid values including empty globs, directory traversal patterns, mutually exclusive options, invalid preset names, and unknown fields. | Schema validation is the first line of defense against misconfiguration — permissive validation lets invalid configs produce confusing downstream errors. | -| Type guards distinguish config formats | The isProjectConfig and isLegacyInstance type guards must correctly distinguish between new-style project configs and legacy configuration instances. | The codebase supports both config formats during migration — incorrect type detection would apply the wrong loading path and produce runtime errors. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| defineConfig is an identity function | The defineConfig helper must return its input unchanged, serving only as a type annotation aid for IDE autocomplete. | defineConfig exists for TypeScript type inference in config files — any transformation would surprise users who expect their config object to pass through unmodified. | +| Schema validates correct configurations | Valid configuration objects (both minimal and fully-specified) must pass schema validation without errors. | The schema must accept all legitimate configuration shapes — rejecting valid configs would block users from using supported features. | +| Schema rejects invalid configurations | The configuration schema must reject invalid values including empty globs, directory traversal patterns, mutually exclusive options, invalid preset names, and unknown fields. | Schema validation is the first line of defense against misconfiguration — permissive validation lets invalid configs produce confusing downstream errors. | +| Type guards distinguish config formats | The isProjectConfig and isLegacyInstance type guards must correctly distinguish between new-style project configs and legacy configuration instances. | The codebase supports both config formats during migration — incorrect type detection would apply the wrong loading path and produce runtime errors. | ### Preset System -| Rule | Invariant | Rationale | -| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | -| Generic preset provides minimal taxonomy | The generic preset must provide exactly 3 categories (core, api, infra) with @docs- prefix. | Simple projects need minimal configuration without DDD-specific categories cluttering the taxonomy. | -| Libar generic preset provides minimal taxonomy with libar prefix | The libar-generic preset must provide exactly 3 categories with @libar-docs- prefix. | This package uses @libar-docs- prefix to avoid collisions with consumer projects' annotations. | -| DDD-ES-CQRS preset provides full taxonomy | The DDD preset must provide all 21 categories spanning DDD, ES, CQRS, and infrastructure domains. | DDD architectures require fine-grained categorization to distinguish bounded contexts, aggregates, and projections. | -| Presets can be accessed by name | All preset instances must be accessible via the PRESETS map using their canonical string key. | Programmatic access enables config files to reference presets by name instead of importing instances. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Generic preset provides minimal taxonomy | The generic preset must provide exactly 3 categories (core, api, infra) with @docs- prefix. | Simple projects need minimal configuration without DDD-specific categories cluttering the taxonomy. | +| Libar generic preset provides minimal taxonomy with libar prefix | The libar-generic preset must provide exactly 3 categories with @libar-docs- prefix. | This package uses @libar-docs- prefix to avoid collisions with consumer projects' annotations. | +| DDD-ES-CQRS preset provides full taxonomy | The DDD preset must provide all 21 categories spanning DDD, ES, CQRS, and infrastructure domains. | DDD architectures require fine-grained categorization to distinguish bounded contexts, aggregates, and projections. | +| Presets can be accessed by name | All preset instances must be accessible via the PRESETS map using their canonical string key. | Programmatic access enables config files to reference presets by name instead of importing instances. | ### Project Config Loader -| Rule | Invariant | Rationale | -| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -| Missing config returns defaults | When no config file exists, loadProjectConfig must return a default resolved config with isDefault=true. | Graceful fallback enables zero-config usage — new projects work without requiring config file creation. | -| New-style config is loaded and resolved | A file exporting defineConfig must be loaded, validated, and resolved with correct preset categories. | defineConfig is the primary config format — correct loading is the critical path for all documentation generation. | -| Legacy config is loaded with backward compatibility | A file exporting createDeliveryProcess must be loaded and produce a valid resolved config. | Backward compatibility prevents breaking existing consumers during migration to the new config format. | -| Invalid configs produce clear errors | Config files without a default export or with invalid data must produce descriptive error messages. | Actionable error messages reduce debugging time — users need to know what to fix, not just that something failed. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Missing config returns defaults | When no config file exists, loadProjectConfig must return a default resolved config with isDefault=true. | Graceful fallback enables zero-config usage — new projects work without requiring config file creation. | +| New-style config is loaded and resolved | A file exporting defineConfig must be loaded, validated, and resolved with correct preset categories. | defineConfig is the primary config format — correct loading is the critical path for all documentation generation. | +| Legacy config is loaded with backward compatibility | A file exporting createDeliveryProcess must be loaded and produce a valid resolved config. | Backward compatibility prevents breaking existing consumers during migration to the new config format. | +| Invalid configs produce clear errors | Config files without a default export or with invalid data must produce descriptive error messages. | Actionable error messages reduce debugging time — users need to know what to fix, not just that something failed. | ### Source Merging -| Rule | Invariant | Rationale | -| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| No override returns base unchanged | When no source overrides are provided, the merged result must be identical to the base source configuration. | The merge function must be safe to call unconditionally — returning modified results without overrides would corrupt default source paths. | -| Feature overrides control feature source selection | additionalFeatures must append to base feature sources while replaceFeatures must completely replace them, and these two options are mutually exclusive. | Projects need both additive and replacement strategies — additive for extending (monorepo packages), replacement for narrowing (focused generation runs). | -| TypeScript source overrides append additional input | additionalInput must append to (not replace) the base TypeScript source paths. | TypeScript sources are always additive — the base sources contain core patterns that must always be included alongside project-specific additions. | -| Combined overrides apply together | Feature overrides and TypeScript overrides must compose independently when both are provided simultaneously. | Real configs often specify both feature and TypeScript overrides — they must not interfere with each other or produce order-dependent results. | -| Exclude is always inherited from base | The exclude patterns must always come from the base configuration, never from overrides. | Exclude patterns are a safety mechanism — allowing overrides to modify excludes could accidentally include sensitive or generated files in the scan. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| No override returns base unchanged | When no source overrides are provided, the merged result must be identical to the base source configuration. | The merge function must be safe to call unconditionally — returning modified results without overrides would corrupt default source paths. | +| Feature overrides control feature source selection | additionalFeatures must append to base feature sources while replaceFeatures must completely replace them, and these two options are mutually exclusive. | Projects need both additive and replacement strategies — additive for extending (monorepo packages), replacement for narrowing (focused generation runs). | +| TypeScript source overrides append additional input | additionalInput must append to (not replace) the base TypeScript source paths. | TypeScript sources are always additive — the base sources contain core patterns that must always be included alongside project-specific additions. | +| Combined overrides apply together | Feature overrides and TypeScript overrides must compose independently when both are provided simultaneously. | Real configs often specify both feature and TypeScript overrides — they must not interfere with each other or produce order-dependent results. | +| Exclude is always inherited from base | The exclude patterns must always come from the base configuration, never from overrides. | Exclude patterns are a safety mechanism — allowing overrides to modify excludes could accidentally include sensitive or generated files in the scan. | --- diff --git a/docs-live/product-areas/CORE-TYPES.md b/docs-live/product-areas/CORE-TYPES.md index bd33333a..a251499a 100644 --- a/docs-live/product-areas/CORE-TYPES.md +++ b/docs-live/product-areas/CORE-TYPES.md @@ -16,6 +16,16 @@ --- +## Contents + +- [Key Invariants](#key-invariants) +- [Core Type System](#core-type-system) +- [Error Handling Flow](#error-handling-flow) +- [API Types](#api-types) +- [Business Rules](#business-rules) + +--- + ## Core Type System Scoped architecture diagram showing component relationships: diff --git a/docs-live/product-areas/DATA-API.md b/docs-live/product-areas/DATA-API.md index 15e042ba..1daa2de2 100644 --- a/docs-live/product-areas/DATA-API.md +++ b/docs-live/product-areas/DATA-API.md @@ -15,6 +15,49 @@ --- +## Contents + +- [Key Invariants](#key-invariants) +- [Shared Pipeline Factory Responsibilities](#shared-pipeline-factory-responsibilities) +- [8-Step Dataset Build Flow](#8-step-dataset-build-flow) +- [Consumer Architecture and PipelineOptions Differentiation](#consumer-architecture-and-pipelineoptions-differentiation) +- [DataAPI Components](#dataapi-components) +- [API Types](#api-types) +- [Business Rules](#business-rules) + +--- + +## Shared Pipeline Factory Responsibilities + +**Invariant:** `buildMasterDataset()` is the shared factory for Steps 1-8 of the architecture pipeline and returns `Result` without process-level side effects. + +**Rationale:** Centralizing scan/extract/merge/transform flow prevents divergence between CLI consumers and preserves a single ADR-006 read-model path. + +--- + +## 8-Step Dataset Build Flow + +The factory owns: configuration load, TypeScript scan + extraction, Gherkin scan + +extraction, merge conflict handling, hierarchy child derivation, workflow load, +and `transformToMasterDataset` with validation summary. + +--- + +## Consumer Architecture and PipelineOptions Differentiation + +Three consumers share this factory: `process-api`, `validate-patterns`, and the +generation orchestrator. `PipelineOptions` differentiates behavior by +`mergeConflictStrategy` (`fatal` vs `concatenate`), `includeValidation` toggles, +and `failOnScanErrors` policy without forking pipeline logic. + +### When to Use + +- Any consumer needs a MasterDataset without rewriting scan/extract/merge flow +- CLI consumers require differentiated conflict strategy and validation behavior +- Orchestrator needs a shared steps 1-8 implementation before codec/file execution + +--- + ## DataAPI Components Scoped architecture diagram showing component relationships: @@ -37,6 +80,7 @@ graph TB subgraph cli["Cli"] ProcessAPICLIImpl("ProcessAPICLIImpl") OutputPipelineImpl("OutputPipelineImpl") + CLISchema["CLISchema"] end subgraph related["Related"] Pattern_Scanner["Pattern Scanner"]:::neighbor @@ -45,6 +89,7 @@ graph TB FSMValidator["FSMValidator"]:::neighbor PipelineFactory["PipelineFactory"]:::neighbor ProcessStateAPICLI["ProcessStateAPICLI"]:::neighbor + ProcessApiHybridGeneration["ProcessApiHybridGeneration"]:::neighbor PhaseStateMachineValidation["PhaseStateMachineValidation"]:::neighbor DataAPIDesignSessionSupport["DataAPIDesignSessionSupport"]:::neighbor DataAPIOutputShaping["DataAPIOutputShaping"]:::neighbor @@ -61,6 +106,7 @@ graph TB ProcessAPICLIImpl ..->|implements| ProcessStateAPICLI OutputPipelineImpl -->|uses| PatternSummarizerImpl OutputPipelineImpl ..->|implements| DataAPIOutputShaping + CLISchema ..->|implements| ProcessApiHybridGeneration PatternSummarizerImpl -->|uses| ProcessStateAPI PatternSummarizerImpl ..->|implements| DataAPIOutputShaping ScopeValidatorImpl -->|uses| ProcessStateAPI @@ -103,6 +149,59 @@ graph TB ## API Types +### PipelineOptions (interface) + +```typescript +/** + * Options for building a MasterDataset via the shared pipeline. + * + * DD-1: Factory lives at src/generators/pipeline/build-pipeline.ts. + * DD-2: mergeConflictStrategy controls per-consumer conflict handling. + * DD-3: exclude, contextInferenceRules support future orchestrator + * migration without breaking changes. + * + */ +``` + +```typescript +interface PipelineOptions { + readonly input: readonly string[]; + readonly features: readonly string[]; + readonly baseDir: string; + readonly mergeConflictStrategy: 'fatal' | 'concatenate'; + readonly exclude?: readonly string[]; + readonly workflowPath?: string; + readonly contextInferenceRules?: readonly ContextInferenceRule[]; + /** DD-3: When false, skip validation pass (default true). */ + readonly includeValidation?: boolean; + /** DD-5: When true, return error on individual scan failures (default false). */ + readonly failOnScanErrors?: boolean; +} +``` + +| Property | Description | +| --- | --- | +| includeValidation | DD-3: When false, skip validation pass (default true). | +| failOnScanErrors | DD-5: When true, return error on individual scan failures (default false). | + +### PipelineResult (interface) + +```typescript +/** + * Successful pipeline result containing the dataset and validation summary. + * + */ +``` + +```typescript +interface PipelineResult { + readonly dataset: RuntimeMasterDataset; + readonly validation: ValidationSummary; + readonly warnings: readonly PipelineWarning[]; + readonly scanMetadata: ScanMetadata; +} +``` + ### MasterDatasetSchema (const) ```typescript @@ -111,6 +210,7 @@ graph TB * * Contains raw patterns plus pre-computed views and statistics. * This is the primary data structure passed to generators and sections. + * */ ``` @@ -149,6 +249,9 @@ MasterDatasetSchema = z.object({ /** Patterns grouped by source type */ bySource: SourceViewsSchema, + /** Patterns grouped by product area (for O(1) product area lookups) */ + byProductArea: z.record(z.string(), z.array(ExtractedPatternSchema)), + // ───────────────────────────────────────────────────────────────────────── // Aggregate Statistics // ───────────────────────────────────────────────────────────────────────── @@ -175,7 +278,7 @@ MasterDatasetSchema = z.object({ /** Optional architecture index for diagram generation */ archIndex: ArchIndexSchema.optional(), -}); +}) ``` ### StatusGroupsSchema (const) @@ -188,6 +291,7 @@ MasterDatasetSchema = z.object({ * - completed: implemented, completed * - active: active, partial, in-progress * - planned: roadmap, planned, undefined + * */ ``` @@ -201,7 +305,7 @@ StatusGroupsSchema = z.object({ /** Patterns with status 'roadmap', 'planned', or undefined */ planned: z.array(ExtractedPatternSchema), -}); +}) ``` ### StatusCountsSchema (const) @@ -209,6 +313,7 @@ StatusGroupsSchema = z.object({ ```typescript /** * Status counts for aggregate statistics + * */ ``` @@ -225,7 +330,7 @@ StatusCountsSchema = z.object({ /** Total number of patterns */ total: z.number().int().nonnegative(), -}); +}) ``` ### PhaseGroupSchema (const) @@ -236,6 +341,7 @@ StatusCountsSchema = z.object({ * * Groups patterns by their phase number, with pre-computed * status counts for each phase. + * */ ``` @@ -252,7 +358,7 @@ PhaseGroupSchema = z.object({ /** Pre-computed status counts for this phase */ counts: StatusCountsSchema, -}); +}) ``` ### SourceViewsSchema (const) @@ -260,6 +366,7 @@ PhaseGroupSchema = z.object({ ```typescript /** * Source-based views for different data origins + * */ ``` @@ -276,7 +383,7 @@ SourceViewsSchema = z.object({ /** Patterns with PRD metadata (productArea, userRole, businessValue) */ prd: z.array(ExtractedPatternSchema), -}); +}) ``` ### RelationshipEntrySchema (const) @@ -286,6 +393,7 @@ SourceViewsSchema = z.object({ * Relationship index for dependency tracking * * Maps pattern names to their relationship metadata. + * */ ``` @@ -321,7 +429,7 @@ RelationshipEntrySchema = z.object({ /** File paths to implementation APIs (from @libar-docs-api-ref tag) */ apiRef: z.array(z.string()), -}); +}) ``` ### ArchIndexSchema (const) @@ -350,310 +458,318 @@ ArchIndexSchema = z.object({ /** Patterns with any architecture metadata (for diagram generation) */ all: z.array(ExtractedPatternSchema), -}); +}) ``` --- ## Business Rules -32 patterns, 137 rules with invariants (137 total) +33 patterns, 140 rules with invariants (140 total) ### Arch Queries Test -| Rule | Invariant | Rationale | -| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Neighborhood and comparison views | The architecture query API must provide pattern neighborhood views (direct connections) and cross-context comparison views (shared/unique dependencies), returning undefined for nonexistent patterns. | Neighborhood and comparison views are the primary navigation tools for understanding architecture — without them, developers must manually trace relationship chains across files. | -| Taxonomy discovery via tags and sources | The API must aggregate tag values with counts across all patterns and categorize source files by type, returning empty reports when no patterns match. | Tag aggregation reveals annotation coverage gaps and source inventory helps teams understand their codebase composition — both are essential for project health monitoring. | -| Coverage analysis reports annotation completeness | Coverage analysis must detect unused taxonomy entries, cross-context integration points, and include all relationship types (implements, dependsOn, enables) in neighborhood views. | Unused taxonomy entries indicate dead configuration while missing relationship types produce incomplete architecture views — both degrade the reliability of generated documentation. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Neighborhood and comparison views | The architecture query API must provide pattern neighborhood views (direct connections) and cross-context comparison views (shared/unique dependencies), returning undefined for nonexistent patterns. | Neighborhood and comparison views are the primary navigation tools for understanding architecture — without them, developers must manually trace relationship chains across files. | +| Taxonomy discovery via tags and sources | The API must aggregate tag values with counts across all patterns and categorize source files by type, returning empty reports when no patterns match. | Tag aggregation reveals annotation coverage gaps and source inventory helps teams understand their codebase composition — both are essential for project health monitoring. | +| Coverage analysis reports annotation completeness | Coverage analysis must detect unused taxonomy entries, cross-context integration points, and include all relationship types (implements, dependsOn, enables) in neighborhood views. | Unused taxonomy entries indicate dead configuration while missing relationship types produce incomplete architecture views — both degrade the reliability of generated documentation. | ### Context Assembler Tests -| Rule | Invariant | Rationale | -| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| assembleContext produces session-tailored context bundles | Each session type (design/planning/implement) must include exactly the context sections defined by its profile — no more, no less. | Over-fetching wastes AI context window tokens; under-fetching causes the agent to make uninformed decisions. | -| buildDepTree walks dependency chains with cycle detection | The dependency tree must walk the full chain up to the depth limit, mark the focal node, and terminate safely on circular references. | Dependency chains reveal implementation prerequisites — cycles and infinite recursion would crash the CLI. | -| buildOverview provides executive project summary | The overview must include progress counts (completed/active/planned), active phase listing, and blocking dependencies. | The overview is the first command in every session start recipe — it must provide a complete project health snapshot. | -| buildFileReadingList returns paths by relevance | Primary files (spec, implementation) must always be included; related files (dependency implementations) are included only when requested. | File reading lists power the "what to read" guidance — relevance sorting ensures the most important files are read first within token budgets. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| assembleContext produces session-tailored context bundles | Each session type (design/planning/implement) must include exactly the context sections defined by its profile — no more, no less. | Over-fetching wastes AI context window tokens; under-fetching causes the agent to make uninformed decisions. | +| buildDepTree walks dependency chains with cycle detection | The dependency tree must walk the full chain up to the depth limit, mark the focal node, and terminate safely on circular references. | Dependency chains reveal implementation prerequisites — cycles and infinite recursion would crash the CLI. | +| buildOverview provides executive project summary | The overview must include progress counts (completed/active/planned), active phase listing, and blocking dependencies. | The overview is the first command in every session start recipe — it must provide a complete project health snapshot. | +| buildFileReadingList returns paths by relevance | Primary files (spec, implementation) must always be included; related files (dependency implementations) are included only when requested. | File reading lists power the "what to read" guidance — relevance sorting ensures the most important files are read first within token budgets. | ### Context Formatter Tests -| Rule | Invariant | Rationale | -| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| formatContextBundle renders section markers | The context formatter must render section markers for all populated sections in a context bundle, with design bundles rendering all sections and implement bundles focusing on deliverables and FSM. | Section markers enable structured parsing of context output — without them, AI consumers cannot reliably extract specific sections from the formatted bundle. | -| formatDepTree renders indented tree | The dependency tree formatter must render with indentation arrows and a focal pattern marker to visually distinguish the target pattern from its dependencies. | Visual hierarchy in the dependency tree makes dependency chains scannable at a glance — flat output would require mental parsing to understand depth and relationships. | -| formatOverview renders progress summary | The overview formatter must render a progress summary line showing completion metrics for the project. | The progress line is the first thing developers see when starting a session — it provides immediate project health awareness without requiring detailed exploration. | -| formatFileReadingList renders categorized file paths | The file reading list formatter must categorize paths into primary and dependency sections, producing minimal output when the list is empty. | Categorized file lists tell developers which files to read first (primary) versus reference (dependency) — uncategorized lists waste time on low-priority files. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| formatContextBundle renders section markers | The context formatter must render section markers for all populated sections in a context bundle, with design bundles rendering all sections and implement bundles focusing on deliverables and FSM. | Section markers enable structured parsing of context output — without them, AI consumers cannot reliably extract specific sections from the formatted bundle. | +| formatDepTree renders indented tree | The dependency tree formatter must render with indentation arrows and a focal pattern marker to visually distinguish the target pattern from its dependencies. | Visual hierarchy in the dependency tree makes dependency chains scannable at a glance — flat output would require mental parsing to understand depth and relationships. | +| formatOverview renders progress summary | The overview formatter must render a progress summary line showing completion metrics for the project. | The progress line is the first thing developers see when starting a session — it provides immediate project health awareness without requiring detailed exploration. | +| formatFileReadingList renders categorized file paths | The file reading list formatter must categorize paths into primary and dependency sections, producing minimal output when the list is empty. | Categorized file lists tell developers which files to read first (primary) versus reference (dependency) — uncategorized lists waste time on low-priority files. | ### Data API Architecture Queries -| Rule | Invariant | Rationale | -| -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Arch subcommand provides neighborhood and comparison views | Architecture queries resolve pattern names to concrete relationships and file paths, not just abstract names. | The current `arch graph ` returns dependency and relationship names but not the full picture of what surrounds a pattern. Design sessions need to understand: "If I'm working on X, what else is directly connected?" and "How do contexts A and B relate?" | -| Coverage analysis reports annotation completeness with gaps | Coverage reports identify unannotated files that should have the libar-docs opt-in marker based on their location and content. | Annotation completeness directly impacts the quality of all generated documentation and API queries. Files without the opt-in marker are invisible to the pipeline. Coverage gaps mean missing patterns in the registry, incomplete dependency graphs, and blind spots in architecture views. | -| Tags and sources commands provide taxonomy and inventory views | All tag values in use are discoverable without reading configuration files. Source file inventory shows the full scope of annotated and scanned content. | Agents frequently need to know "what categories exist?" or "how many feature files are there?" without reading taxonomy configuration. These are meta-queries about the annotation system itself, essential for writing new annotations correctly and understanding scope. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Arch subcommand provides neighborhood and comparison views | Architecture queries resolve pattern names to concrete relationships and file paths, not just abstract names. | The current `arch graph ` returns dependency and relationship names but not the full picture of what surrounds a pattern. Design sessions need to understand: "If I'm working on X, what else is directly connected?" and "How do contexts A and B relate?" | +| Coverage analysis reports annotation completeness with gaps | Coverage reports identify unannotated files that should have the libar-docs opt-in marker based on their location and content. | Annotation completeness directly impacts the quality of all generated documentation and API queries. Files without the opt-in marker are invisible to the pipeline. Coverage gaps mean missing patterns in the registry, incomplete dependency graphs, and blind spots in architecture views. | +| Tags and sources commands provide taxonomy and inventory views | All tag values in use are discoverable without reading configuration files. Source file inventory shows the full scope of annotated and scanned content. | Agents frequently need to know "what categories exist?" or "how many feature files are there?" without reading taxonomy configuration. These are meta-queries about the annotation system itself, essential for writing new annotations correctly and understanding scope. | ### Data API CLI Ergonomics -| Rule | Invariant | Rationale | -| ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| MasterDataset is cached between invocations with file-change invalidation | Cache is automatically invalidated when any source file (TypeScript or Gherkin) has a modification time newer than the cache. | The pipeline (scan -> extract -> transform) runs fresh on every invocation (~2-5 seconds). Most queries during a session don't need fresh data -- the source files haven't changed between queries. Caching the MasterDataset to a temp file with file-modification-time invalidation makes subsequent queries instant while ensuring staleness is impossible. | -| REPL mode keeps pipeline loaded for interactive multi-query sessions | REPL mode loads the pipeline once and accepts multiple queries on stdin, with optional tab completion for pattern names and subcommands. | Design sessions often involve 10-20 exploratory queries in sequence (check status, look up pattern, check deps, look up another pattern). REPL mode eliminates per-query pipeline overhead entirely. | -| Per-subcommand help and diagnostic modes aid discoverability | Every subcommand supports `--help` with usage, flags, and examples. Dry-run shows pipeline scope without executing. | AI agents read `--help` output to discover available commands and flags. Without per-subcommand help, agents must read external documentation. Dry-run mode helps diagnose "why no patterns found?" issues by showing what would be scanned. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| MasterDataset is cached between invocations with file-change invalidation | Cache is automatically invalidated when any source file (TypeScript or Gherkin) has a modification time newer than the cache. | The pipeline (scan -> extract -> transform) runs fresh on every invocation (~2-5 seconds). Most queries during a session don't need fresh data -- the source files haven't changed between queries. Caching the MasterDataset to a temp file with file-modification-time invalidation makes subsequent queries instant while ensuring staleness is impossible. | +| REPL mode keeps pipeline loaded for interactive multi-query sessions | REPL mode loads the pipeline once and accepts multiple queries on stdin, with optional tab completion for pattern names and subcommands. | Design sessions often involve 10-20 exploratory queries in sequence (check status, look up pattern, check deps, look up another pattern). REPL mode eliminates per-query pipeline overhead entirely. | +| Per-subcommand help and diagnostic modes aid discoverability | Every subcommand supports `--help` with usage, flags, and examples. Dry-run shows pipeline scope without executing. | AI agents read `--help` output to discover available commands and flags. Without per-subcommand help, agents must read external documentation. Dry-run mode helps diagnose "why no patterns found?" issues by showing what would be scanned. | ### Data API Context Assembly -| Rule | Invariant | Rationale | -| -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Context command assembles curated context for a single pattern | Given a pattern name, `context` returns everything needed to start working on that pattern: metadata, file locations, dependency status, and architecture position -- in ~1.5KB of structured text. | This is the core value proposition. The command crosses five gaps simultaneously: it assembles data from multiple MasterDataset indexes, shapes it compactly, resolves file paths from pattern names, discovers stubs by convention, and tailors output by session type. | -| Files command returns only file paths organized by relevance | `files` returns the most token-efficient output possible -- just file paths that Claude Code can read directly. | Most context tokens are spent reading actual files, not metadata. The `files` command tells Claude Code _which_ files to read, organized by importance. Claude Code then reads what it needs. This is more efficient than `context` when the agent already knows the pattern and just needs the file list. | -| Dep-tree command shows recursive dependency chain with status | The dependency tree walks both `dependsOn`/`enables` (planning) and `uses`/`usedBy` (implementation) relationships with configurable depth. | Before starting work on a pattern, agents need to know the full dependency chain: what must be complete first, what this unblocks, and where the current pattern sits in the sequence. A tree visualization with status markers makes blocking relationships immediately visible. | -| Context command supports multiple patterns with merged output | Multi-pattern context deduplicates shared dependencies and highlights overlap between patterns. | Design sessions often span multiple related patterns (e.g., reviewing DS-2 through DS-5 together). Separate `context` calls would duplicate shared dependencies. Merged context shows the union of all dependencies with overlap analysis. | -| Overview provides executive project summary | `overview` returns project-wide health in one command. | Planning sessions start with "where are we?" This command answers that question without needing to run multiple queries and mentally aggregate results. Implementation readiness checks for specific patterns live in DataAPIDesignSessionSupport's `scope-validate` command. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Context command assembles curated context for a single pattern | Given a pattern name, `context` returns everything needed to start working on that pattern: metadata, file locations, dependency status, and architecture position -- in ~1.5KB of structured text. | This is the core value proposition. The command crosses five gaps simultaneously: it assembles data from multiple MasterDataset indexes, shapes it compactly, resolves file paths from pattern names, discovers stubs by convention, and tailors output by session type. | +| Files command returns only file paths organized by relevance | `files` returns the most token-efficient output possible -- just file paths that Claude Code can read directly. | Most context tokens are spent reading actual files, not metadata. The `files` command tells Claude Code *which* files to read, organized by importance. Claude Code then reads what it needs. This is more efficient than `context` when the agent already knows the pattern and just needs the file list. | +| Dep-tree command shows recursive dependency chain with status | The dependency tree walks both `dependsOn`/`enables` (planning) and `uses`/`usedBy` (implementation) relationships with configurable depth. | Before starting work on a pattern, agents need to know the full dependency chain: what must be complete first, what this unblocks, and where the current pattern sits in the sequence. A tree visualization with status markers makes blocking relationships immediately visible. | +| Context command supports multiple patterns with merged output | Multi-pattern context deduplicates shared dependencies and highlights overlap between patterns. | Design sessions often span multiple related patterns (e.g., reviewing DS-2 through DS-5 together). Separate `context` calls would duplicate shared dependencies. Merged context shows the union of all dependencies with overlap analysis. | +| Overview provides executive project summary | `overview` returns project-wide health in one command. | Planning sessions start with "where are we?" This command answers that question without needing to run multiple queries and mentally aggregate results. Implementation readiness checks for specific patterns live in DataAPIDesignSessionSupport's `scope-validate` command. | ### Data API Design Session Support -| Rule | Invariant | Rationale | -| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Scope-validate checks implementation prerequisites before session start | Scope validation surfaces all blocking conditions before committing to a session, preventing wasted effort on unready patterns. | Starting implementation on a pattern with incomplete dependencies wastes an entire session. Starting a design session without prior session deliverables means working with incomplete context. Pre-flight validation catches these issues in seconds rather than discovering them mid-session. | -| Handoff generates compact session state summary for multi-session work | Handoff documentation captures everything the next session needs to continue work without context loss. | Multi-session work (common for design phases spanning DS-1 through DS-7) requires state transfer between sessions. Without automated handoff, critical information is lost: what was completed, what's in progress, what blockers were discovered, and what should happen next. Manual handoff documentation is inconsistent and often forgotten. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Scope-validate checks implementation prerequisites before session start | Scope validation surfaces all blocking conditions before committing to a session, preventing wasted effort on unready patterns. | Starting implementation on a pattern with incomplete dependencies wastes an entire session. Starting a design session without prior session deliverables means working with incomplete context. Pre-flight validation catches these issues in seconds rather than discovering them mid-session. | +| Handoff generates compact session state summary for multi-session work | Handoff documentation captures everything the next session needs to continue work without context loss. | Multi-session work (common for design phases spanning DS-1 through DS-7) requires state transfer between sessions. Without automated handoff, critical information is lost: what was completed, what's in progress, what blockers were discovered, and what should happen next. Manual handoff documentation is inconsistent and often forgotten. | ### Data API Output Shaping -| Rule | Invariant | Rationale | -| ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| List queries return compact pattern summaries by default | List-returning API methods produce summaries, not full ExtractedPattern objects, unless `--full` is explicitly requested. | The single biggest usability problem. `getCurrentWork` returns 3 active patterns at ~3.5KB each = 10.5KB. Summarized: ~300 bytes total. The `directive` field (raw JSDoc AST) and `code` field (full source) are almost never needed for list queries. AI agents need name, status, category, phase, and file path -- nothing more. | -| Global output modifier flags apply to any list-returning command | Output modifiers are composable and apply uniformly across all list-returning subcommands and query methods. | AI agents frequently need just pattern names (for further queries), just counts (for progress checks), or specific fields (for focused analysis). These are post-processing transforms that should work with any data source. | -| Output format is configurable with typed response envelope | All CLI output uses the QueryResult envelope for success/error discrimination. The compact format strips empty and null fields. | The existing `QueryResult` types (`QuerySuccess`, `QueryError`) are defined in `src/api/types.ts` but not wired into the CLI output. Agents cannot distinguish success from error without try/catch on JSON parsing. Empty arrays, null values, and empty strings add noise to every response. | -| List subcommand provides composable filters and fuzzy search | The `list` subcommand replaces the need to call specific `getPatternsByX` methods. Filters are composable via AND logic. The `query` subcommand remains available for programmatic/raw access. | Currently, filtering by status AND category requires calling `getPatternsByCategory` then manually filtering by status. A single `list` command with composable filters eliminates multi-step queries. Fuzzy search reduces agent retry loops when pattern names are approximate. | -| CLI provides ergonomic defaults and helpful error messages | Common operations require minimal flags. Pattern name typos produce actionable suggestions. Empty results explain why. | Every extra flag and every retry loop costs AI agent context tokens. Config file defaults eliminate repetitive path arguments. Fuzzy matching with suggestions prevents the common "Pattern not found" → retry → still not found loop. Empty result hints guide agents toward productive queries. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| List queries return compact pattern summaries by default | List-returning API methods produce summaries, not full ExtractedPattern objects, unless `--full` is explicitly requested. | The single biggest usability problem. `getCurrentWork` returns 3 active patterns at ~3.5KB each = 10.5KB. Summarized: ~300 bytes total. The `directive` field (raw JSDoc AST) and `code` field (full source) are almost never needed for list queries. AI agents need name, status, category, phase, and file path -- nothing more. | +| Global output modifier flags apply to any list-returning command | Output modifiers are composable and apply uniformly across all list-returning subcommands and query methods. | AI agents frequently need just pattern names (for further queries), just counts (for progress checks), or specific fields (for focused analysis). These are post-processing transforms that should work with any data source. | +| Output format is configurable with typed response envelope | All CLI output uses the QueryResult envelope for success/error discrimination. The compact format strips empty and null fields. | The existing `QueryResult` types (`QuerySuccess`, `QueryError`) are defined in `src/api/types.ts` but not wired into the CLI output. Agents cannot distinguish success from error without try/catch on JSON parsing. Empty arrays, null values, and empty strings add noise to every response. | +| List subcommand provides composable filters and fuzzy search | The `list` subcommand replaces the need to call specific `getPatternsByX` methods. Filters are composable via AND logic. The `query` subcommand remains available for programmatic/raw access. | Currently, filtering by status AND category requires calling `getPatternsByCategory` then manually filtering by status. A single `list` command with composable filters eliminates multi-step queries. Fuzzy search reduces agent retry loops when pattern names are approximate. | +| CLI provides ergonomic defaults and helpful error messages | Common operations require minimal flags. Pattern name typos produce actionable suggestions. Empty results explain why. | Every extra flag and every retry loop costs AI agent context tokens. Config file defaults eliminate repetitive path arguments. Fuzzy matching with suggestions prevents the common "Pattern not found" → retry → still not found loop. Empty result hints guide agents toward productive queries. | ### Data API Platform Integration -| Rule | Invariant | Rationale | -| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| ProcessStateAPI is accessible as an MCP server for Claude Code | The MCP server exposes all ProcessStateAPI methods as MCP tools with typed input/output schemas. The pipeline is loaded once on server start and refreshed on source file changes. | MCP is Claude Code's native tool integration protocol. An MCP server eliminates the CLI subprocess overhead (2-5s per query) and enables Claude Code to call process queries as naturally as it calls other tools. Stateful operation means the pipeline loads once and serves many queries. | -| Process state can be auto-generated as CLAUDE.md context sections | Generated CLAUDE.md sections are additive layers that provide pattern metadata, relationships, and reading lists for specific scopes. | CLAUDE.md is the primary mechanism for providing persistent context to Claude Code sessions. Auto-generating CLAUDE.md sections from process state ensures the context is always fresh and consistent with the source annotations. This applies the "code-first documentation" principle to AI context itself. | -| Cross-package views show dependencies spanning multiple packages | Cross-package queries aggregate patterns from multiple input sources and resolve cross-package relationships. | In the monorepo, patterns in `platform-core` are used by patterns in `platform-bc`, which are used by the example app. Understanding these cross-package dependencies is essential for release planning and impact analysis. Currently each package must be queried independently with separate input globs. | -| Process validation integrates with git hooks and file watching | Pre-commit hooks validate annotation consistency. Watch mode re-generates docs on source changes. | Git hooks catch annotation errors at commit time (e.g., new `uses` reference to non-existent pattern, invalid `arch-role` value, stub `@target` to non-existent directory). Watch mode enables live documentation regeneration during implementation sessions. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| ProcessStateAPI is accessible as an MCP server for Claude Code | The MCP server exposes all ProcessStateAPI methods as MCP tools with typed input/output schemas. The pipeline is loaded once on server start and refreshed on source file changes. | MCP is Claude Code's native tool integration protocol. An MCP server eliminates the CLI subprocess overhead (2-5s per query) and enables Claude Code to call process queries as naturally as it calls other tools. Stateful operation means the pipeline loads once and serves many queries. | +| Process state can be auto-generated as CLAUDE.md context sections | Generated CLAUDE.md sections are additive layers that provide pattern metadata, relationships, and reading lists for specific scopes. | CLAUDE.md is the primary mechanism for providing persistent context to Claude Code sessions. Auto-generating CLAUDE.md sections from process state ensures the context is always fresh and consistent with the source annotations. This applies the "code-first documentation" principle to AI context itself. | +| Cross-package views show dependencies spanning multiple packages | Cross-package queries aggregate patterns from multiple input sources and resolve cross-package relationships. | In the monorepo, patterns in `platform-core` are used by patterns in `platform-bc`, which are used by the example app. Understanding these cross-package dependencies is essential for release planning and impact analysis. Currently each package must be queried independently with separate input globs. | +| Process validation integrates with git hooks and file watching | Pre-commit hooks validate annotation consistency. Watch mode re-generates docs on source changes. | Git hooks catch annotation errors at commit time (e.g., new `uses` reference to non-existent pattern, invalid `arch-role` value, stub `@target` to non-existent directory). Watch mode enables live documentation regeneration during implementation sessions. | ### Data API Relationship Graph -| Rule | Invariant | Rationale | -| ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Graph command traverses relationships recursively with configurable depth | Graph traversal walks both planning relationships (`dependsOn`, `enables`) and implementation relationships (`uses`, `usedBy`) with cycle detection to prevent infinite loops. | Flat lookups show direct connections. Recursive traversal shows the full picture: transitive dependencies, indirect consumers, and the complete chain from root to leaf. Depth limiting prevents overwhelming output on deeply connected graphs. | -| Impact analysis shows transitive dependents of a pattern | Impact analysis answers "if I change X, what else is affected?" by walking `usedBy` + `enables` recursively. | Before modifying a completed pattern (which requires unlock), understanding the blast radius prevents unintended breakage. Impact analysis is the reverse of dependency traversal -- it looks forward, not backward. | -| Path finding discovers relationship chains between two patterns | Path finding returns the shortest chain of relationships connecting two patterns, or indicates no path exists. Traversal considers all relationship types (uses, usedBy, dependsOn, enables). | Understanding how two seemingly unrelated patterns connect helps agents assess indirect dependencies before making changes. When pattern A and pattern D are connected through B and C, modifying A requires understanding that chain. | -| Graph health commands detect broken references and isolated patterns | Dangling references (pattern names in `uses`/`dependsOn` that don't match any pattern definition) are detectable. Orphan patterns (no relationships at all) are identifiable. | The MasterDataset transformer already computes dangling references during Pass 3 (relationship resolution) but does not expose them via the API. Orphan patterns indicate missing annotations. Both are data quality signals that improve over time with attention. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Graph command traverses relationships recursively with configurable depth | Graph traversal walks both planning relationships (`dependsOn`, `enables`) and implementation relationships (`uses`, `usedBy`) with cycle detection to prevent infinite loops. | Flat lookups show direct connections. Recursive traversal shows the full picture: transitive dependencies, indirect consumers, and the complete chain from root to leaf. Depth limiting prevents overwhelming output on deeply connected graphs. | +| Impact analysis shows transitive dependents of a pattern | Impact analysis answers "if I change X, what else is affected?" by walking `usedBy` + `enables` recursively. | Before modifying a completed pattern (which requires unlock), understanding the blast radius prevents unintended breakage. Impact analysis is the reverse of dependency traversal -- it looks forward, not backward. | +| Path finding discovers relationship chains between two patterns | Path finding returns the shortest chain of relationships connecting two patterns, or indicates no path exists. Traversal considers all relationship types (uses, usedBy, dependsOn, enables). | Understanding how two seemingly unrelated patterns connect helps agents assess indirect dependencies before making changes. When pattern A and pattern D are connected through B and C, modifying A requires understanding that chain. | +| Graph health commands detect broken references and isolated patterns | Dangling references (pattern names in `uses`/`dependsOn` that don't match any pattern definition) are detectable. Orphan patterns (no relationships at all) are identifiable. | The MasterDataset transformer already computes dangling references during Pass 3 (relationship resolution) but does not expose them via the API. Orphan patterns indicate missing annotations. Both are data quality signals that improve over time with attention. | ### Data API Stub Integration -| Rule | Invariant | Rationale | -| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| All stubs are visible to the scanner pipeline | Every stub file in `delivery-process/stubs/` has `@libar-docs` opt-in and `@libar-docs-implements` linking it to its parent pattern. | The scanner requires `@libar-docs` opt-in marker to include a file. Without it, stubs are invisible regardless of other annotations. The `@libar-docs-implements` tag creates the bidirectional link: spec defines the pattern (via `@libar-docs-pattern`), stub implements it. Per PDR-009, stubs must NOT use `@libar-docs-pattern` -- that belongs to the feature file. | -| Stubs subcommand lists design stubs with implementation status | `stubs` returns stub files with their target paths, design session origins, and whether the target file already exists. | Before implementation, agents need to know: which stubs exist for a pattern, where they should be moved to, and which have already been implemented. The stub-to-implementation resolver compares `@libar-docs-target` paths against actual files to determine status. | -| Decisions and PDR commands surface design rationale | Design decisions (AD-N items) and PDR references from stub annotations are queryable by pattern name or PDR number. | Design sessions produce numbered decisions (AD-1, AD-2, etc.) and reference PDR decision records (see PDR-012). When reviewing designs or starting implementation, agents need to find these decisions without reading every stub file manually. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| All stubs are visible to the scanner pipeline | Every stub file in `delivery-process/stubs/` has `@libar-docs` opt-in and `@libar-docs-implements` linking it to its parent pattern. | The scanner requires `@libar-docs` opt-in marker to include a file. Without it, stubs are invisible regardless of other annotations. The `@libar-docs-implements` tag creates the bidirectional link: spec defines the pattern (via `@libar-docs-pattern`), stub implements it. Per PDR-009, stubs must NOT use `@libar-docs-pattern` -- that belongs to the feature file. | +| Stubs subcommand lists design stubs with implementation status | `stubs` returns stub files with their target paths, design session origins, and whether the target file already exists. | Before implementation, agents need to know: which stubs exist for a pattern, where they should be moved to, and which have already been implemented. The stub-to-implementation resolver compares `@libar-docs-target` paths against actual files to determine status. | +| Decisions and PDR commands surface design rationale | Design decisions (AD-N items) and PDR references from stub annotations are queryable by pattern name or PDR number. | Design sessions produce numbered decisions (AD-1, AD-2, etc.) and reference PDR decision records (see PDR-012). When reviewing designs or starting implementation, agents need to find these decisions without reading every stub file manually. | ### Fuzzy Match Tests -| Rule | Invariant | Rationale | -| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Fuzzy matching uses tiered scoring | Pattern matching must use a tiered scoring system: exact match (1.0) > prefix match (0.9) > substring match (0.7) > Levenshtein distance, with results sorted by score descending and case-insensitive matching. | Tiered scoring ensures the most intuitive match wins — an exact match should always rank above a substring match, preventing surprising suggestions for common pattern names. | -| findBestMatch returns single suggestion | findBestMatch must return the single highest-scoring match above the threshold, or undefined when no match exceeds the threshold. | A single best suggestion simplifies "did you mean?" prompts in the CLI — returning multiple matches would require additional UI to disambiguate. | -| Levenshtein distance computation | The Levenshtein distance function must correctly compute edit distance between strings, returning 0 for identical strings. | Levenshtein distance is the fallback matching tier — incorrect distance computation would produce wrong fuzzy match scores for typo correction. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Fuzzy matching uses tiered scoring | Pattern matching must use a tiered scoring system: exact match (1.0) > prefix match (0.9) > substring match (0.7) > Levenshtein distance, with results sorted by score descending and case-insensitive matching. | Tiered scoring ensures the most intuitive match wins — an exact match should always rank above a substring match, preventing surprising suggestions for common pattern names. | +| findBestMatch returns single suggestion | findBestMatch must return the single highest-scoring match above the threshold, or undefined when no match exceeds the threshold. | A single best suggestion simplifies "did you mean?" prompts in the CLI — returning multiple matches would require additional UI to disambiguate. | +| Levenshtein distance computation | The Levenshtein distance function must correctly compute edit distance between strings, returning 0 for identical strings. | Levenshtein distance is the fallback matching tier — incorrect distance computation would produce wrong fuzzy match scores for typo correction. | ### Generate Docs Cli -| Rule | Invariant | Rationale | -| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| CLI displays help and version information | The --help and -v flags must produce usage/version output and exit successfully without requiring other arguments. | Help and version are universal CLI conventions — they must work standalone so users can discover usage without reading external documentation. | -| CLI requires input patterns | The generate-docs CLI must fail with a clear error when the --input flag is not provided. | Without input source paths, the generator has nothing to scan — failing early with a clear message prevents confusing "no patterns found" errors downstream. | -| CLI lists available generators | The --list-generators flag must display all registered generator names without performing any generation. | Users need to discover available generators before specifying --generator — listing them avoids trial-and-error with invalid generator names. | -| CLI generates documentation from source files | Given valid input patterns and a generator name, the CLI must scan sources, extract patterns, and produce markdown output files. | This is the core pipeline — the CLI is the primary entry point for transforming annotated source code into generated documentation. | -| CLI rejects unknown options | Unrecognized CLI flags must cause an error with a descriptive message rather than being silently ignored. | Silent flag ignoring hides typos and misconfigurations — users typing --ouput instead of --output would get unexpected default behavior without realizing their flag was ignored. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| CLI displays help and version information | The --help and -v flags must produce usage/version output and exit successfully without requiring other arguments. | Help and version are universal CLI conventions — they must work standalone so users can discover usage without reading external documentation. | +| CLI requires input patterns | The generate-docs CLI must fail with a clear error when the --input flag is not provided. | Without input source paths, the generator has nothing to scan — failing early with a clear message prevents confusing "no patterns found" errors downstream. | +| CLI lists available generators | The --list-generators flag must display all registered generator names without performing any generation. | Users need to discover available generators before specifying --generator — listing them avoids trial-and-error with invalid generator names. | +| CLI generates documentation from source files | Given valid input patterns and a generator name, the CLI must scan sources, extract patterns, and produce markdown output files. | This is the core pipeline — the CLI is the primary entry point for transforming annotated source code into generated documentation. | +| CLI rejects unknown options | Unrecognized CLI flags must cause an error with a descriptive message rather than being silently ignored. | Silent flag ignoring hides typos and misconfigurations — users typing --ouput instead of --output would get unexpected default behavior without realizing their flag was ignored. | ### Generate Tag Taxonomy Cli -| Rule | Invariant | Rationale | -| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| CLI displays help and version information | The --help/-h and --version/-v flags must produce usage/version output and exit successfully without requiring other arguments. | Help and version are universal CLI conventions — both short and long flag forms must work for discoverability and scripting compatibility. | -| CLI generates taxonomy at specified output path | The taxonomy generator must write output to the specified path, creating parent directories if they do not exist, and defaulting to a standard path when no output is specified. | Flexible output paths support both default conventions and custom layouts — auto-creating directories prevents "ENOENT" errors on first run. | -| CLI respects overwrite flag for existing files | The CLI must refuse to overwrite existing output files unless the --overwrite or -f flag is explicitly provided. | Overwrite protection prevents accidental destruction of hand-edited taxonomy files — requiring an explicit flag makes destructive operations intentional. | -| Generated taxonomy contains expected sections | The generated taxonomy file must include category documentation and statistics sections reflecting the configured tag registry. | The taxonomy is a reference document — incomplete output missing categories or statistics would leave developers without the information they need to annotate correctly. | -| CLI warns about unknown flags | Unrecognized CLI flags must produce a warning message but allow execution to continue. | Taxonomy generation is non-destructive — warning without failing is more user-friendly than hard errors for minor flag typos, while still surfacing the issue. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| CLI displays help and version information | The --help/-h and --version/-v flags must produce usage/version output and exit successfully without requiring other arguments. | Help and version are universal CLI conventions — both short and long flag forms must work for discoverability and scripting compatibility. | +| CLI generates taxonomy at specified output path | The taxonomy generator must write output to the specified path, creating parent directories if they do not exist, and defaulting to a standard path when no output is specified. | Flexible output paths support both default conventions and custom layouts — auto-creating directories prevents "ENOENT" errors on first run. | +| CLI respects overwrite flag for existing files | The CLI must refuse to overwrite existing output files unless the --overwrite or -f flag is explicitly provided. | Overwrite protection prevents accidental destruction of hand-edited taxonomy files — requiring an explicit flag makes destructive operations intentional. | +| Generated taxonomy contains expected sections | The generated taxonomy file must include category documentation and statistics sections reflecting the configured tag registry. | The taxonomy is a reference document — incomplete output missing categories or statistics would leave developers without the information they need to annotate correctly. | +| CLI warns about unknown flags | Unrecognized CLI flags must produce a warning message but allow execution to continue. | Taxonomy generation is non-destructive — warning without failing is more user-friendly than hard errors for minor flag typos, while still surfacing the issue. | ### Handoff Generator Tests -| Rule | Invariant | Rationale | -| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Rule | Invariant | Rationale | +| --- | --- | --- | | Handoff generates compact session state summary | The handoff generator must produce a compact session state summary including pattern status, discovered items, inferred session type, modified files, and dependency blockers, throwing an error for unknown patterns. | Handoff documents are the bridge between multi-session work — without compact state capture, the next session starts from scratch instead of resuming where the previous one left off. | -| Formatter produces structured text output | The handoff formatter must produce structured text output with ADR-008 section markers for machine-parseable session state. | ADR-008 markers enable the context assembler to parse handoff output programmatically — unstructured text would require fragile regex parsing. | +| Formatter produces structured text output | The handoff formatter must produce structured text output with ADR-008 section markers for machine-parseable session state. | ADR-008 markers enable the context assembler to parse handoff output programmatically — unstructured text would require fragile regex parsing. | ### Lint Patterns Cli -| Rule | Invariant | Rationale | -| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| CLI displays help and version information | The --help and -v flags must produce usage/version output and exit successfully without requiring other arguments. | Help and version are universal CLI conventions — they must work standalone so users can discover usage without reading external documentation. | -| CLI requires input patterns | The lint-patterns CLI must fail with a clear error when the --input flag is not provided. | Without input paths, the linter has nothing to validate — failing early prevents confusing "no violations" output that falsely implies clean annotations. | -| Lint passes for valid patterns | Fully annotated patterns with all required tags must pass linting with zero violations. | False positives erode developer trust in the linter — valid annotations must always pass to maintain the tool's credibility. | -| Lint detects violations in incomplete patterns | Patterns with missing or incomplete annotations must produce specific violation reports identifying what is missing. | Actionable violation messages guide developers to fix annotations — generic "lint failed" messages without specifics waste debugging time. | -| CLI supports multiple output formats | The CLI must support JSON and pretty (human-readable) output formats, with pretty as the default. | Pretty format serves interactive use while JSON format enables CI/CD pipeline integration and programmatic consumption of lint results. | -| Strict mode treats warnings as errors | When --strict is enabled, warnings must be promoted to errors causing a non-zero exit code; without --strict, warnings must not cause failure. | CI pipelines need strict enforcement while local development benefits from lenient mode — the flag lets teams choose their enforcement level. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| CLI displays help and version information | The --help and -v flags must produce usage/version output and exit successfully without requiring other arguments. | Help and version are universal CLI conventions — they must work standalone so users can discover usage without reading external documentation. | +| CLI requires input patterns | The lint-patterns CLI must fail with a clear error when the --input flag is not provided. | Without input paths, the linter has nothing to validate — failing early prevents confusing "no violations" output that falsely implies clean annotations. | +| Lint passes for valid patterns | Fully annotated patterns with all required tags must pass linting with zero violations. | False positives erode developer trust in the linter — valid annotations must always pass to maintain the tool's credibility. | +| Lint detects violations in incomplete patterns | Patterns with missing or incomplete annotations must produce specific violation reports identifying what is missing. | Actionable violation messages guide developers to fix annotations — generic "lint failed" messages without specifics waste debugging time. | +| CLI supports multiple output formats | The CLI must support JSON and pretty (human-readable) output formats, with pretty as the default. | Pretty format serves interactive use while JSON format enables CI/CD pipeline integration and programmatic consumption of lint results. | +| Strict mode treats warnings as errors | When --strict is enabled, warnings must be promoted to errors causing a non-zero exit code; without --strict, warnings must not cause failure. | CI pipelines need strict enforcement while local development benefits from lenient mode — the flag lets teams choose their enforcement level. | ### Lint Process Cli -| Rule | Invariant | Rationale | -| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| CLI displays help and version information | The --help/-h and --version/-v flags must produce usage/version output and exit successfully without requiring other arguments. | Help and version are universal CLI conventions — both short and long flag forms must work for discoverability and scripting compatibility. | -| CLI requires git repository for validation | The lint-process CLI must fail with a clear error when run outside a git repository in both staged and all modes. | Process guard validation depends on git diff for change detection — running without git produces undefined behavior rather than useful validation results. | -| CLI validates file mode input | In file mode, the CLI must require at least one file path via positional argument or --file flag, and fail with a clear error when none is provided. | File mode is for targeted validation of specific files — accepting zero files would silently produce a "no violations" result that falsely implies the files are valid. | -| CLI handles no changes gracefully | When no relevant changes are detected (empty diff), the CLI must exit successfully with a zero exit code. | No changes means no violations are possible — failing on empty diffs would break CI pipelines on commits that only modify non-spec files. | -| CLI supports multiple output formats | The CLI must support JSON and pretty (human-readable) output formats, with pretty as the default. | Pretty format serves interactive pre-commit use while JSON format enables CI/CD pipeline integration and automated violation processing. | -| CLI supports debug options | The --show-state flag must display the derived process state (FSM states, protection levels, deliverables) without affecting validation behavior. | Process guard decisions are derived from complex state — exposing the intermediate state helps developers understand why a specific validation passed or failed. | -| CLI warns about unknown flags | Unrecognized CLI flags must produce a warning message but allow execution to continue. | Process validation is critical-path at commit time — hard-failing on a typo in an optional flag would block commits unnecessarily when the core validation would succeed. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| CLI displays help and version information | The --help/-h and --version/-v flags must produce usage/version output and exit successfully without requiring other arguments. | Help and version are universal CLI conventions — both short and long flag forms must work for discoverability and scripting compatibility. | +| CLI requires git repository for validation | The lint-process CLI must fail with a clear error when run outside a git repository in both staged and all modes. | Process guard validation depends on git diff for change detection — running without git produces undefined behavior rather than useful validation results. | +| CLI validates file mode input | In file mode, the CLI must require at least one file path via positional argument or --file flag, and fail with a clear error when none is provided. | File mode is for targeted validation of specific files — accepting zero files would silently produce a "no violations" result that falsely implies the files are valid. | +| CLI handles no changes gracefully | When no relevant changes are detected (empty diff), the CLI must exit successfully with a zero exit code. | No changes means no violations are possible — failing on empty diffs would break CI pipelines on commits that only modify non-spec files. | +| CLI supports multiple output formats | The CLI must support JSON and pretty (human-readable) output formats, with pretty as the default. | Pretty format serves interactive pre-commit use while JSON format enables CI/CD pipeline integration and automated violation processing. | +| CLI supports debug options | The --show-state flag must display the derived process state (FSM states, protection levels, deliverables) without affecting validation behavior. | Process guard decisions are derived from complex state — exposing the intermediate state helps developers understand why a specific validation passed or failed. | +| CLI warns about unknown flags | Unrecognized CLI flags must produce a warning message but allow execution to continue. | Process validation is critical-path at commit time — hard-failing on a typo in an optional flag would block commits unnecessarily when the core validation would succeed. | ### Output Pipeline Tests -| Rule | Invariant | Rationale | -| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Rule | Invariant | Rationale | +| --- | --- | --- | | Output modifiers apply with correct precedence | Output modifiers (count, names-only, fields, full) must apply to pattern arrays with correct precedence, passing scalar inputs through unchanged, with summaries as the default mode. | Predictable modifier behavior enables composable CLI queries — unexpected precedence or scalar handling would produce confusing output for piped commands. | -| Modifier conflicts are rejected | Mutually exclusive modifier combinations (full+names-only, full+count, full+fields) and invalid field names must be rejected with clear error messages. | Conflicting modifiers produce ambiguous intent — rejecting early with a clear message is better than silently picking one modifier and ignoring the other. | -| List filters compose via AND logic | Multiple list filters (status, category) must compose via AND logic, with pagination (limit/offset) applied after filtering and empty results for out-of-range offsets. | AND composition is the intuitive default for filters — "status=active AND category=core" should narrow results, not widen them via OR logic. | -| Empty stripping removes noise | Null and empty values must be stripped from output objects to reduce noise in API responses. | Empty fields in pattern summaries create visual clutter and waste tokens in AI context windows — stripping them keeps output focused on meaningful data. | +| Modifier conflicts are rejected | Mutually exclusive modifier combinations (full+names-only, full+count, full+fields) and invalid field names must be rejected with clear error messages. | Conflicting modifiers produce ambiguous intent — rejecting early with a clear message is better than silently picking one modifier and ignoring the other. | +| List filters compose via AND logic | Multiple list filters (status, category) must compose via AND logic, with pagination (limit/offset) applied after filtering and empty results for out-of-range offsets. | AND composition is the intuitive default for filters — "status=active AND category=core" should narrow results, not widen them via OR logic. | +| Empty stripping removes noise | Null and empty values must be stripped from output objects to reduce noise in API responses. | Empty fields in pattern summaries create visual clutter and waste tokens in AI context windows — stripping them keeps output focused on meaningful data. | ### Pattern Helpers Tests -| Rule | Invariant | Rationale | -| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| getPatternName uses patternName tag when available | getPatternName must return the patternName tag value when set, falling back to the pattern's name field when the tag is absent. | The patternName tag allows human-friendly display names — without the fallback, patterns missing the tag would display as undefined. | -| findPatternByName performs case-insensitive matching | findPatternByName must match pattern names case-insensitively, returning undefined when no match exists. | Case-insensitive matching prevents frustrating "not found" errors when developers type "processguard" instead of "ProcessGuard" — both clearly refer to the same pattern. | -| getRelationships looks up with case-insensitive fallback | getRelationships must first try exact key lookup in the relationship index, then fall back to case-insensitive matching, returning undefined when no match exists. | Exact-first with case-insensitive fallback balances performance (O(1) exact lookup) with usability (tolerates case mismatches in cross-references). | -| suggestPattern provides fuzzy suggestions | suggestPattern must return fuzzy match suggestions for close pattern names, returning empty results when no close match exists. | Fuzzy suggestions power "did you mean?" UX in the CLI — without them, typos produce unhelpful "pattern not found" messages. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| getPatternName uses patternName tag when available | getPatternName must return the patternName tag value when set, falling back to the pattern's name field when the tag is absent. | The patternName tag allows human-friendly display names — without the fallback, patterns missing the tag would display as undefined. | +| findPatternByName performs case-insensitive matching | findPatternByName must match pattern names case-insensitively, returning undefined when no match exists. | Case-insensitive matching prevents frustrating "not found" errors when developers type "processguard" instead of "ProcessGuard" — both clearly refer to the same pattern. | +| getRelationships looks up with case-insensitive fallback | getRelationships must first try exact key lookup in the relationship index, then fall back to case-insensitive matching, returning undefined when no match exists. | Exact-first with case-insensitive fallback balances performance (O(1) exact lookup) with usability (tolerates case mismatches in cross-references). | +| suggestPattern provides fuzzy suggestions | suggestPattern must return fuzzy match suggestions for close pattern names, returning empty results when no close match exists. | Fuzzy suggestions power "did you mean?" UX in the CLI — without them, typos produce unhelpful "pattern not found" messages. | ### Pattern Summarize Tests -| Rule | Invariant | Rationale | -| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Rule | Invariant | Rationale | +| --- | --- | --- | | summarizePattern projects to compact summary | summarizePattern must project a full pattern object to a compact summary containing exactly 6 fields, using the patternName tag over the name field when available and omitting undefined optional fields. | Compact summaries reduce token usage by 80-90% compared to full patterns — they provide enough context for navigation without overwhelming AI context windows. | -| summarizePatterns batch processes arrays | summarizePatterns must batch-process an array of patterns, returning a correctly-sized array of compact summaries. | Batch processing avoids N individual function calls — the API frequently needs to summarize all patterns matching a query in a single operation. | +| summarizePatterns batch processes arrays | summarizePatterns must batch-process an array of patterns, returning a correctly-sized array of compact summaries. | Batch processing avoids N individual function calls — the API frequently needs to summarize all patterns matching a query in a single operation. | ### PDR 001 Session Workflow Commands -| Rule | Invariant | Rationale | -| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| DD-1 - Text output with section markers | scope-validate and handoff must return plain text with === SECTION === markers, never JSON. | Inconsistent output formats force consumers to detect and branch on format type, breaking the dual output path contract. Both scope-validate and handoff return string from the router, using === SECTION === markers. Follows the dual output path where text commands bypass JSON.stringify. | -| DD-2 - Git integration is opt-in via --git flag | Domain logic must never invoke shell commands or depend on git directly. | Shell dependencies in domain logic make functions untestable without git fixtures and break deterministic behavior. The handoff command accepts an optional --git flag. The CLI handler calls git diff and passes file list to the pure generator function. No shell dependency in domain logic. | -| DD-3 - Session type inferred from FSM status | Every FSM status must map to exactly one default session type, overridable by an explicit --session flag. | Ambiguous or missing inference forces users to always specify --session manually, defeating the ergonomic benefit of status-based defaults. Handoff infers session type from pattern's current FSM status. An explicit --session flag overrides inference. | -| DD-4 - Severity levels match Process Guard model | Scope validation must use exactly three severity levels (PASS, BLOCKED, WARN) consistent with Process Guard. | Divergent severity models cause confusion when the same violation appears in both systems with different severity classifications. Scope validation uses three severity levels: The --strict flag promotes WARN to BLOCKED. | -| DD-5 - Current date only for handoff | Handoff must always use the current system date with no override mechanism. | A --date flag enables backdating handoff timestamps, which breaks audit trail integrity for multi-session work. Handoff always uses the current date. No --date flag. | -| DD-6 - Both positional and flag forms for scope type | scope-validate must accept scope type as both a positional argument and a --type flag. | Supporting only one form creates inconsistency with CLI conventions and forces users to remember which form each subcommand uses. scope-validate accepts scope type as both positional argument and --type flag. | -| DD-7 - Co-located formatter functions | Each module must export both its data builder and text formatter as co-located functions. | Splitting builder and formatter across files increases coupling surface and makes it harder to trace data flow through the module. Each module (scope-validator.ts, handoff-generator.ts) exports both the data builder and the text formatter. Simpler than the context-assembler/context-formatter split. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| DD-1 - Text output with section markers | scope-validate and handoff must return plain text with === SECTION === markers, never JSON. | Inconsistent output formats force consumers to detect and branch on format type, breaking the dual output path contract. | +| DD-2 - Git integration is opt-in via --git flag | Domain logic must never invoke shell commands or depend on git directly. | Shell dependencies in domain logic make functions untestable without git fixtures and break deterministic behavior. | +| DD-3 - Session type inferred from FSM status | Every FSM status must map to exactly one default session type, overridable by an explicit --session flag. | Ambiguous or missing inference forces users to always specify --session manually, defeating the ergonomic benefit of status-based defaults. | +| DD-4 - Severity levels match Process Guard model | Scope validation must use exactly three severity levels (PASS, BLOCKED, WARN) consistent with Process Guard. | Divergent severity models cause confusion when the same violation appears in both systems with different severity classifications. | +| DD-5 - Current date only for handoff | Handoff must always use the current system date with no override mechanism. | A --date flag enables backdating handoff timestamps, which breaks audit trail integrity for multi-session work. | +| DD-6 - Both positional and flag forms for scope type | scope-validate must accept scope type as both a positional argument and a --type flag. | Supporting only one form creates inconsistency with CLI conventions and forces users to remember which form each subcommand uses. | +| DD-7 - Co-located formatter functions | Each module must export both its data builder and text formatter as co-located functions. | Splitting builder and formatter across files increases coupling surface and makes it harder to trace data flow through the module. | ### Process Api Cli Core -| Rule | Invariant | Rationale | -| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| CLI displays help and version information | The CLI must always provide discoverable usage and version information via standard flags. | Without accessible help and version output, users cannot self-serve CLI usage or report issues with a specific version. | -| CLI requires input flag for subcommands | Every data-querying subcommand must receive an explicit `--input` glob specifying the source files to scan. | Without an input source, the pipeline has no files to scan and would produce empty or misleading results instead of a clear error. | -| CLI status subcommand shows delivery state | The status subcommand must return structured JSON containing delivery progress derived from the MasterDataset. | Consumers depend on machine-readable status output for scripting and CI integration; unstructured output breaks downstream automation. | -| CLI query subcommand executes API methods | The query subcommand must dispatch to any public Data API method by name and pass positional arguments through. | The CLI is the primary interface for ad-hoc queries; failing to resolve a valid method name or its arguments silently drops the user's request. | -| CLI pattern subcommand shows pattern detail | The pattern subcommand must return the full JSON detail for an exact pattern name match, or a clear error if not found. | Pattern lookup is the primary debugging tool for annotation issues; ambiguous or silent failures waste investigation time. | -| CLI arch subcommand queries architecture | The arch subcommand must expose role, bounded context, and layer queries over the MasterDataset's architecture metadata. | Architecture queries replace manual exploration of annotated sources; missing or incorrect results lead to wrong structural assumptions during design sessions. | -| CLI shows errors for missing subcommand arguments | Subcommands that require arguments must reject invocations with missing arguments and display usage guidance. | Silent acceptance of incomplete input would produce confusing pipeline errors instead of actionable feedback at the CLI boundary. | -| CLI handles argument edge cases | The CLI must gracefully handle non-standard argument forms including numeric coercion and the `--` pnpm separator. | Real-world invocations via pnpm pass `--` separators and numeric strings; mishandling these causes silent data loss or crashes in automated workflows. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| CLI displays help and version information | The CLI must always provide discoverable usage and version information via standard flags. | Without accessible help and version output, users cannot self-serve CLI usage or report issues with a specific version. | +| CLI requires input flag for subcommands | Every data-querying subcommand must receive an explicit `--input` glob specifying the source files to scan. | Without an input source, the pipeline has no files to scan and would produce empty or misleading results instead of a clear error. | +| CLI status subcommand shows delivery state | The status subcommand must return structured JSON containing delivery progress derived from the MasterDataset. | Consumers depend on machine-readable status output for scripting and CI integration; unstructured output breaks downstream automation. | +| CLI query subcommand executes API methods | The query subcommand must dispatch to any public Data API method by name and pass positional arguments through. | The CLI is the primary interface for ad-hoc queries; failing to resolve a valid method name or its arguments silently drops the user's request. | +| CLI pattern subcommand shows pattern detail | The pattern subcommand must return the full JSON detail for an exact pattern name match, or a clear error if not found. | Pattern lookup is the primary debugging tool for annotation issues; ambiguous or silent failures waste investigation time. | +| CLI arch subcommand queries architecture | The arch subcommand must expose role, bounded context, and layer queries over the MasterDataset's architecture metadata. | Architecture queries replace manual exploration of annotated sources; missing or incorrect results lead to wrong structural assumptions during design sessions. | +| CLI shows errors for missing subcommand arguments | Subcommands that require arguments must reject invocations with missing arguments and display usage guidance. | Silent acceptance of incomplete input would produce confusing pipeline errors instead of actionable feedback at the CLI boundary. | +| CLI handles argument edge cases | The CLI must gracefully handle non-standard argument forms including numeric coercion and the `--` pnpm separator. | Real-world invocations via pnpm pass `--` separators and numeric strings; mishandling these causes silent data loss or crashes in automated workflows. | ### Process Api Cli Modifiers And Rules -| Rule | Invariant | Rationale | -| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Output modifiers work when placed after the subcommand | Output modifiers (--count, --names-only, --fields) produce identical results regardless of position relative to the subcommand and its filters. | Users should not need to memorize argument ordering rules; the CLI should be forgiving. | -| CLI arch health subcommands detect graph quality issues | Health subcommands (dangling, orphans, blocking) operate on the relationship index, not the architecture index, and return results without requiring arch annotations. | Graph quality issues (broken references, isolated patterns, blocked dependencies) are relationship-level concerns that should be queryable even when no architecture metadata exists. | -| CLI rules subcommand queries business rules and invariants | The rules subcommand returns structured business rules extracted from Gherkin Rule: blocks, grouped by product area and phase, with parsed invariant and rationale annotations. | Live business rule queries replace static generated markdown, enabling on-demand filtering by product area, pattern, and invariant presence. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Output modifiers work when placed after the subcommand | Output modifiers (--count, --names-only, --fields) produce identical results regardless of position relative to the subcommand and its filters. | Users should not need to memorize argument ordering rules; the CLI should be forgiving. | +| CLI arch health subcommands detect graph quality issues | Health subcommands (dangling, orphans, blocking) operate on the relationship index, not the architecture index, and return results without requiring arch annotations. | Graph quality issues (broken references, isolated patterns, blocked dependencies) are relationship-level concerns that should be queryable even when no architecture metadata exists. | +| CLI rules subcommand queries business rules and invariants | The rules subcommand returns structured business rules extracted from Gherkin Rule: blocks, grouped by product area and phase, with parsed invariant and rationale annotations. | Live business rule queries replace static generated markdown, enabling on-demand filtering by product area, pattern, and invariant presence. | ### Process Api Cli Subcommands -| Rule | Invariant | Rationale | -| -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| CLI list subcommand filters patterns | The list subcommand must return a valid JSON result for valid filters and a non-zero exit code with a descriptive error for invalid filters. | Consumers parse list output programmatically; malformed JSON or silent failures cause downstream tooling to break without diagnosis. | -| CLI search subcommand finds patterns by fuzzy match | The search subcommand must require a query argument and return only patterns whose names match the query. | Missing query validation would produce unfiltered result sets, defeating the purpose of search and wasting context budget in AI sessions. | -| CLI context assembly subcommands return text output | Context assembly subcommands (context, overview, dep-tree) must produce non-empty human-readable text containing the requested pattern or summary, and require a pattern argument where applicable. | These subcommands replace manual file reads in AI sessions; empty or off-target output forces expensive explore-agent fallbacks that consume 5-10x more context. | -| CLI tags and sources subcommands return JSON | The tags and sources subcommands must return valid JSON with the expected top-level structure (data key for tags, array for sources). | Annotation exploration depends on machine-parseable output; invalid JSON prevents automated enrichment workflows from detecting unannotated files and tag gaps. | -| CLI extended arch subcommands query architecture relationships | Extended arch subcommands (neighborhood, compare, coverage) must return valid JSON reflecting the actual architecture relationships present in the scanned sources. | Architecture queries drive design-session decisions; stale or structurally invalid output leads to incorrect dependency analysis and missed coupling between bounded contexts. | -| CLI unannotated subcommand finds files without annotations | The unannotated subcommand must return valid JSON listing every TypeScript file that lacks the `@libar-docs` opt-in marker. | Files missing the opt-in marker are invisible to the scanner; without this subcommand, unannotated files silently drop out of generated documentation and validation. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| CLI list subcommand filters patterns | The list subcommand must return a valid JSON result for valid filters and a non-zero exit code with a descriptive error for invalid filters. | Consumers parse list output programmatically; malformed JSON or silent failures cause downstream tooling to break without diagnosis. | +| CLI search subcommand finds patterns by fuzzy match | The search subcommand must require a query argument and return only patterns whose names match the query. | Missing query validation would produce unfiltered result sets, defeating the purpose of search and wasting context budget in AI sessions. | +| CLI context assembly subcommands return text output | Context assembly subcommands (context, overview, dep-tree) must produce non-empty human-readable text containing the requested pattern or summary, and require a pattern argument where applicable. | These subcommands replace manual file reads in AI sessions; empty or off-target output forces expensive explore-agent fallbacks that consume 5-10x more context. | +| CLI tags and sources subcommands return JSON | The tags and sources subcommands must return valid JSON with the expected top-level structure (data key for tags, array for sources). | Annotation exploration depends on machine-parseable output; invalid JSON prevents automated enrichment workflows from detecting unannotated files and tag gaps. | +| CLI extended arch subcommands query architecture relationships | Extended arch subcommands (neighborhood, compare, coverage) must return valid JSON reflecting the actual architecture relationships present in the scanned sources. | Architecture queries drive design-session decisions; stale or structurally invalid output leads to incorrect dependency analysis and missed coupling between bounded contexts. | +| CLI unannotated subcommand finds files without annotations | The unannotated subcommand must return valid JSON listing every TypeScript file that lacks the `@libar-docs` opt-in marker. | Files missing the opt-in marker are invisible to the scanner; without this subcommand, unannotated files silently drop out of generated documentation and validation. | ### Process API Layered Extraction -| Rule | Invariant | Rationale | -| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| CLI file contains only routing, no domain logic | `process-api.ts` parses arguments, calls the pipeline factory for the MasterDataset, routes subcommands to API modules, and formats output. It does not build Maps, filter patterns, group data, or resolve relationships. Thin view projections (3-5 line `.map()` calls over pre-computed archIndex views) are acceptable as formatting. | Domain logic in the CLI file is only accessible via the command line. Extracting it to `src/api/` makes it programmatically testable, reusable by future consumers (MCP server, watch mode), and aligned with the feature-consumption layer defined in ADR-006. | -| Pipeline factory is shared across CLI consumers | The scan-extract-transform sequence is defined once in `src/generators/pipeline/build-pipeline.ts`. CLI consumers that need a MasterDataset call the factory rather than wiring the pipeline independently. The factory accepts `mergeConflictStrategy` to handle behavioral differences between consumers. | Three consumers (process-api, validate-patterns, orchestrator) independently wire the same 8-step sequence: loadConfig, scanPatterns, extractPatterns, scanGherkinFiles, extractPatternsFromGherkin, mergePatterns, computeHierarchyChildren, transformToMasterDataset. The only semantic difference is merge-conflict handling (fatal vs concatenate). This is a Parallel Pipeline anti-pattern per ADR-006. | -| Domain logic lives in API modules | Query logic that operates on MasterDataset lives in `src/api/` modules. The `rules-query.ts` module provides business rules querying with the same grouping logic that was inline in handleRules: filter by product area and pattern, group by area -> phase -> feature -> rules, parse annotations, compute totals. | `handleRules` is 184 lines with 5 Map/Set constructions, codec-layer imports (`parseBusinessRuleAnnotations`, `deduplicateScenarioNames`), and a complex 3-level grouping algorithm. This is the last significant inline domain logic in process-api.ts. Moving it to `src/api/` follows the same pattern as the 12 existing API modules (context-assembler, arch-queries, scope-validator, etc.). | -| Pipeline factory returns Result for consumer-owned error handling | The factory returns `Result` rather than throwing or calling `process.exit()`. Each consumer maps the error to its own strategy: process-api.ts calls `process.exit(1)`, validate-patterns.ts throws, and orchestrator.ts (future) returns `Result.err()`. | The current `buildPipeline()` in process-api.ts calls `process.exit(1)` on errors, making it non-reusable. The factory must work across consumers with different error handling models. The Result monad is the project's established pattern for this (see `src/types/result.ts`). | -| End-to-end verification confirms behavioral equivalence | After extraction, all CLI commands produce identical output to pre-refactor behavior with zero build, test, lint, and validation errors. | The refactor must not change observable behavior. Full CLI verification confirms the extraction is a pure refactor. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| CLI file contains only routing, no domain logic | `process-api.ts` parses arguments, calls the pipeline factory for the MasterDataset, routes subcommands to API modules, and formats output. It does not build Maps, filter patterns, group data, or resolve relationships. Thin view projections (3-5 line `.map()` calls over pre-computed archIndex views) are acceptable as formatting. | Domain logic in the CLI file is only accessible via the command line. Extracting it to `src/api/` makes it programmatically testable, reusable by future consumers (MCP server, watch mode), and aligned with the feature-consumption layer defined in ADR-006. | +| Pipeline factory is shared across CLI consumers | The scan-extract-transform sequence is defined once in `src/generators/pipeline/build-pipeline.ts`. CLI consumers that need a MasterDataset call the factory rather than wiring the pipeline independently. The factory accepts `mergeConflictStrategy` to handle behavioral differences between consumers. | Three consumers (process-api, validate-patterns, orchestrator) independently wire the same 8-step sequence: loadConfig, scanPatterns, extractPatterns, scanGherkinFiles, extractPatternsFromGherkin, mergePatterns, computeHierarchyChildren, transformToMasterDataset. The only semantic difference is merge-conflict handling (fatal vs concatenate). This is a Parallel Pipeline anti-pattern per ADR-006. | +| Domain logic lives in API modules | Query logic that operates on MasterDataset lives in `src/api/` modules. The `rules-query.ts` module provides business rules querying with the same grouping logic that was inline in handleRules: filter by product area and pattern, group by area -> phase -> feature -> rules, parse annotations, compute totals. | `handleRules` is 184 lines with 5 Map/Set constructions, codec-layer imports (`parseBusinessRuleAnnotations`, `deduplicateScenarioNames`), and a complex 3-level grouping algorithm. This is the last significant inline domain logic in process-api.ts. Moving it to `src/api/` follows the same pattern as the 12 existing API modules (context-assembler, arch-queries, scope-validator, etc.). | +| Pipeline factory returns Result for consumer-owned error handling | The factory returns `Result` rather than throwing or calling `process.exit()`. Each consumer maps the error to its own strategy: process-api.ts calls `process.exit(1)`, validate-patterns.ts throws, and orchestrator.ts (future) returns `Result.err()`. | The current `buildPipeline()` in process-api.ts calls `process.exit(1)` on errors, making it non-reusable. The factory must work across consumers with different error handling models. The Result monad is the project's established pattern for this (see `src/types/result.ts`). | +| End-to-end verification confirms behavioral equivalence | After extraction, all CLI commands produce identical output to pre-refactor behavior with zero build, test, lint, and validation errors. | The refactor must not change observable behavior. Full CLI verification confirms the extraction is a pure refactor. | + +### Process Api Reference Tests + +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Generated reference file contains all three table sections | PROCESS-API-REFERENCE.md contains Global Options, Output Modifiers, and List Filters tables generated from the CLI schema. | | +| CLI schema stays in sync with parser | Every flag recognized by parseArgs() has a corresponding entry in the CLI schema. A missing schema entry means the sync test fails. | | +| showHelp output reflects CLI schema | The help text rendered by showHelp() includes all options from the CLI schema, formatted for terminal display. | | ### Process State API CLI -| Rule | Invariant | Rationale | -| ----------------------------------------- | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Rule | Invariant | Rationale | +| --- | --- | --- | | CLI supports status-based pattern queries | Every ProcessStateAPI status query method is accessible via CLI. | The most common planning question is "what's the current state?" Status queries (active, roadmap, completed) answer this directly without reading docs. Without CLI access, Claude Code must regenerate markdown and parse unstructured text. | -| CLI supports phase-based queries | Patterns can be filtered by phase number. | Phase 18 (Event Durability) is the current focus per roadmap priorities. Quick phase queries help assess progress and remaining work within a phase. Phase-based planning is the primary organization method for roadmap work. | -| CLI provides progress summary queries | Overall and per-phase progress is queryable in a single command. | Planning sessions need quick answers to "where are we?" without reading the full PATTERNS.md generated file. Progress metrics drive prioritization and help identify where to focus effort. | -| CLI supports multiple output formats | JSON output is parseable by AI agents without transformation. | Claude Code can parse JSON directly. Text format is for human reading. JSON format enables scripting and integration with other tools. The primary use case is AI agent parsing where structured output reduces context and errors. | -| CLI supports individual pattern lookup | Any pattern can be queried by name with full details. | During implementation, Claude Code needs to check specific pattern status, deliverables, and dependencies without reading the full spec file. Pattern lookup is essential for focused implementation work. | -| CLI provides discoverable help | All flags are documented via --help with examples. | Claude Code can read --help output to understand available queries without needing external documentation. Self-documenting CLIs reduce the need for Claude Code to read additional context files. | +| CLI supports phase-based queries | Patterns can be filtered by phase number. | Phase 18 (Event Durability) is the current focus per roadmap priorities. Quick phase queries help assess progress and remaining work within a phase. Phase-based planning is the primary organization method for roadmap work. | +| CLI provides progress summary queries | Overall and per-phase progress is queryable in a single command. | Planning sessions need quick answers to "where are we?" without reading the full PATTERNS.md generated file. Progress metrics drive prioritization and help identify where to focus effort. | +| CLI supports multiple output formats | JSON output is parseable by AI agents without transformation. | Claude Code can parse JSON directly. Text format is for human reading. JSON format enables scripting and integration with other tools. The primary use case is AI agent parsing where structured output reduces context and errors. | +| CLI supports individual pattern lookup | Any pattern can be queried by name with full details. | During implementation, Claude Code needs to check specific pattern status, deliverables, and dependencies without reading the full spec file. Pattern lookup is essential for focused implementation work. | +| CLI provides discoverable help | All flags are documented via --help with examples. | Claude Code can read --help output to understand available queries without needing external documentation. Self-documenting CLIs reduce the need for Claude Code to read additional context files. | ### Process State API Relationship Queries -| Rule | Invariant | Rationale | -| ------------------------------------------------ | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| API provides implementation relationship queries | Every pattern with `implementedBy` entries is discoverable via the API. | Claude Code needs to navigate from abstract patterns to concrete code. Without this, exploration requires manual grep + file reading, wasting context tokens. | -| API provides inheritance hierarchy queries | Pattern inheritance chains are fully navigable in both directions. | Patterns form specialization hierarchies (e.g., ReactiveProjections extends ProjectionCategories). Claude Code needs to understand what specializes a base pattern and what a specialized pattern inherits from. | -| API provides combined relationship views | All relationship types are accessible through a unified interface. | Claude Code often needs the complete picture: dependencies AND implementations AND inheritance. A single call reduces round-trips and context switching. | -| API supports bidirectional traceability queries | Navigation from spec to code and code to spec is symmetric. | Traceability is bidirectional by definition. If a spec links to code, the code should link back to the spec. The API should surface broken links. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| API provides implementation relationship queries | Every pattern with `implementedBy` entries is discoverable via the API. | Claude Code needs to navigate from abstract patterns to concrete code. Without this, exploration requires manual grep + file reading, wasting context tokens. | +| API provides inheritance hierarchy queries | Pattern inheritance chains are fully navigable in both directions. | Patterns form specialization hierarchies (e.g., ReactiveProjections extends ProjectionCategories). Claude Code needs to understand what specializes a base pattern and what a specialized pattern inherits from. | +| API provides combined relationship views | All relationship types are accessible through a unified interface. | Claude Code often needs the complete picture: dependencies AND implementations AND inheritance. A single call reduces round-trips and context switching. | +| API supports bidirectional traceability queries | Navigation from spec to code and code to spec is symmetric. | Traceability is bidirectional by definition. If a spec links to code, the code should link back to the spec. The API should surface broken links. | ### Process State API Testing -| Rule | Invariant | Rationale | -| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -| Status queries return correct patterns | Status queries must correctly filter by both normalized status (planned = roadmap + deferred) and FSM status (exact match). | The two-domain status convention requires separate query methods — mixing them produces incorrect filtered results. | -| Phase queries return correct phase data | Phase queries must return only patterns in the requested phase, with accurate progress counts and completion percentage. | Phase-level queries power the roadmap and session planning views — incorrect counts cascade into wrong progress percentages. | -| FSM queries expose transition validation | FSM queries must validate transitions against the PDR-005 state machine and expose protection levels per status. | Programmatic FSM access enables tooling to enforce delivery process rules without reimplementing the state machine. | -| Pattern queries find and retrieve pattern data | Pattern lookup must be case-insensitive by name, and category queries must return only patterns with the requested category. | Case-insensitive search reduces friction in CLI and AI agent usage where exact casing is often unknown. | -| Timeline queries group patterns by time | Quarter queries must correctly filter by quarter string, and recently completed must be sorted by date descending with limit. | Timeline grouping enables quarterly reporting and session context — recent completions show delivery momentum. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Status queries return correct patterns | Status queries must correctly filter by both normalized status (planned = roadmap + deferred) and FSM status (exact match). | The two-domain status convention requires separate query methods — mixing them produces incorrect filtered results. | +| Phase queries return correct phase data | Phase queries must return only patterns in the requested phase, with accurate progress counts and completion percentage. | Phase-level queries power the roadmap and session planning views — incorrect counts cascade into wrong progress percentages. | +| FSM queries expose transition validation | FSM queries must validate transitions against the PDR-005 state machine and expose protection levels per status. | Programmatic FSM access enables tooling to enforce delivery process rules without reimplementing the state machine. | +| Pattern queries find and retrieve pattern data | Pattern lookup must be case-insensitive by name, and category queries must return only patterns with the requested category. | Case-insensitive search reduces friction in CLI and AI agent usage where exact casing is often unknown. | +| Timeline queries group patterns by time | Quarter queries must correctly filter by quarter string, and recently completed must be sorted by date descending with limit. | Timeline grouping enables quarterly reporting and session context — recent completions show delivery momentum. | ### Scope Validator Tests -| Rule | Invariant | Rationale | -| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Implementation scope validation checks all prerequisites | Implementation scope validation must check FSM transition validity, dependency completeness, PDR references, and deliverable presence, with strict mode promoting warnings to blockers. | Starting implementation without passing scope validation wastes an entire session — the validator catches all known blockers before any code is written. | -| Design scope validation checks dependency stubs | Design scope validation must verify that dependencies have corresponding code stubs, producing warnings when stubs are missing. | Design sessions that reference unstubbed dependencies cannot produce actionable interfaces — stub presence indicates the dependency's API surface is at least sketched. | -| Formatter produces structured text output | The scope validator formatter must produce structured text with ADR-008 markers, showing verdict text for warnings and blocker details for blocked verdicts. | Structured formatter output enables the CLI to display verdicts consistently — unstructured output would vary by validation type and be hard to parse. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Implementation scope validation checks all prerequisites | Implementation scope validation must check FSM transition validity, dependency completeness, PDR references, and deliverable presence, with strict mode promoting warnings to blockers. | Starting implementation without passing scope validation wastes an entire session — the validator catches all known blockers before any code is written. | +| Design scope validation checks dependency stubs | Design scope validation must verify that dependencies have corresponding code stubs, producing warnings when stubs are missing. | Design sessions that reference unstubbed dependencies cannot produce actionable interfaces — stub presence indicates the dependency's API surface is at least sketched. | +| Formatter produces structured text output | The scope validator formatter must produce structured text with ADR-008 markers, showing verdict text for warnings and blocker details for blocked verdicts. | Structured formatter output enables the CLI to display verdicts consistently — unstructured output would vary by validation type and be hard to parse. | ### Stub Resolver Tests -| Rule | Invariant | Rationale | -| ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Stubs are identified by path or target metadata | A pattern must be identified as a stub if it resides in the stubs directory OR has a targetPath metadata field. | Dual identification supports both convention-based (directory) and metadata-based (targetPath) stub detection — relying on only one would miss stubs organized differently. | -| Stubs are resolved against the filesystem | Resolved stubs must show whether their target file exists on the filesystem and must be grouped by the pattern they implement. | Target existence status tells developers whether a stub has been implemented — grouping by pattern enables the "stubs --unresolved" command to show per-pattern implementation gaps. | -| Decision items are extracted from descriptions | AD-N formatted items must be extracted from pattern description text, with empty descriptions returning no items and malformed items being skipped. | Decision items (AD-1, AD-2, etc.) link stubs to architectural decisions — extracting them enables traceability from code stubs back to the design rationale. | -| PDR references are found across patterns | The resolver must find all patterns that reference a given PDR identifier, returning empty results when no references exist. | PDR cross-referencing enables impact analysis — knowing which patterns reference a decision helps assess the blast radius of changing that decision. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| Stubs are identified by path or target metadata | A pattern must be identified as a stub if it resides in the stubs directory OR has a targetPath metadata field. | Dual identification supports both convention-based (directory) and metadata-based (targetPath) stub detection — relying on only one would miss stubs organized differently. | +| Stubs are resolved against the filesystem | Resolved stubs must show whether their target file exists on the filesystem and must be grouped by the pattern they implement. | Target existence status tells developers whether a stub has been implemented — grouping by pattern enables the "stubs --unresolved" command to show per-pattern implementation gaps. | +| Decision items are extracted from descriptions | AD-N formatted items must be extracted from pattern description text, with empty descriptions returning no items and malformed items being skipped. | Decision items (AD-1, AD-2, etc.) link stubs to architectural decisions — extracting them enables traceability from code stubs back to the design rationale. | +| PDR references are found across patterns | The resolver must find all patterns that reference a given PDR identifier, returning empty results when no references exist. | PDR cross-referencing enables impact analysis — knowing which patterns reference a decision helps assess the blast radius of changing that decision. | ### Stub Taxonomy Tag Tests -| Rule | Invariant | Rationale | -| -------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Rule | Invariant | Rationale | +| --- | --- | --- | | Taxonomy tags are registered in the registry | The target and since stub metadata tags must be registered in the tag registry as recognized taxonomy entries. | Unregistered tags would be flagged as unknown by the linter — registration ensures stub metadata tags pass validation alongside standard annotation tags. | -| Tags are part of the stub metadata group | The target and since tags must be grouped under the stub metadata domain in the built registry. | Domain grouping enables the taxonomy codec to render stub metadata tags in their own section — ungrouped tags would be lost in the "Other" category. | +| Tags are part of the stub metadata group | The target and since tags must be grouped under the stub metadata domain in the built registry. | Domain grouping enables the taxonomy codec to render stub metadata tags in their own section — ungrouped tags would be lost in the "Other" category. | ### Validate Patterns Cli -| Rule | Invariant | Rationale | -| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| CLI displays help and version information | The --help/-h and --version/-v flags must produce usage/version output and exit successfully without requiring other arguments. | Help and version are universal CLI conventions — both short and long flag forms must work for discoverability and scripting compatibility. | -| CLI requires input and feature patterns | The validate-patterns CLI must fail with clear errors when either --input or --features flags are missing. | Cross-source validation requires both TypeScript and Gherkin inputs — running with only one source would produce incomplete validation that misses cross-source mismatches. | -| CLI validates patterns across TypeScript and Gherkin sources | The validator must detect mismatches between TypeScript and Gherkin sources including phase and status discrepancies. | Dual-source architecture requires consistency — a pattern with status "active" in TypeScript but "roadmap" in Gherkin creates conflicting truth and broken reports. | -| CLI supports multiple output formats | The CLI must support JSON and pretty (human-readable) output formats, with pretty as the default. | Pretty format serves interactive use while JSON format enables CI/CD pipeline integration and programmatic consumption of validation results. | -| Strict mode treats warnings as errors | When --strict is enabled, warnings must be promoted to errors causing a non-zero exit code (exit 2); without --strict, warnings must not cause failure. | CI pipelines need strict enforcement while local development benefits from lenient mode — the flag lets teams choose their enforcement level. | -| CLI warns about unknown flags | Unrecognized CLI flags must produce a warning message but allow execution to continue. | Pattern validation is non-destructive — warning without failing is more user-friendly than hard errors for minor flag typos, while still surfacing the issue. | +| Rule | Invariant | Rationale | +| --- | --- | --- | +| CLI displays help and version information | The --help/-h and --version/-v flags must produce usage/version output and exit successfully without requiring other arguments. | Help and version are universal CLI conventions — both short and long flag forms must work for discoverability and scripting compatibility. | +| CLI requires input and feature patterns | The validate-patterns CLI must fail with clear errors when either --input or --features flags are missing. | Cross-source validation requires both TypeScript and Gherkin inputs — running with only one source would produce incomplete validation that misses cross-source mismatches. | +| CLI validates patterns across TypeScript and Gherkin sources | The validator must detect mismatches between TypeScript and Gherkin sources including phase and status discrepancies. | Dual-source architecture requires consistency — a pattern with status "active" in TypeScript but "roadmap" in Gherkin creates conflicting truth and broken reports. | +| CLI supports multiple output formats | The CLI must support JSON and pretty (human-readable) output formats, with pretty as the default. | Pretty format serves interactive use while JSON format enables CI/CD pipeline integration and programmatic consumption of validation results. | +| Strict mode treats warnings as errors | When --strict is enabled, warnings must be promoted to errors causing a non-zero exit code (exit 2); without --strict, warnings must not cause failure. | CI pipelines need strict enforcement while local development benefits from lenient mode — the flag lets teams choose their enforcement level. | +| CLI warns about unknown flags | Unrecognized CLI flags must produce a warning message but allow execution to continue. | Pattern validation is non-destructive — warning without failing is more user-friendly than hard errors for minor flag typos, while still surfacing the issue. | --- diff --git a/docs-live/product-areas/GENERATION.md b/docs-live/product-areas/GENERATION.md index ee55d5fc..0fb73532 100644 --- a/docs-live/product-areas/GENERATION.md +++ b/docs-live/product-areas/GENERATION.md @@ -5,13 +5,50 @@ --- -**How does code become docs?** The generation pipeline transforms annotated source code into markdown documents. It follows a four-stage architecture: Scanner → Extractor → Transformer → Codec. Codecs are pure functions — given a MasterDataset, they produce a RenderableDocument without side effects. CompositeCodec composes multiple codecs into a single document. +**How does code become docs?** The generation pipeline transforms annotated source code into markdown documents through a four-stage architecture: Scanner discovers files, Extractor produces `ExtractedPattern` objects, Transformer builds MasterDataset with pre-computed views, and Codecs render to markdown via RenderableDocument IR. Nine specialized codecs handle reference docs, planning, session, reporting, timeline, ADRs, business rules, taxonomy, and composite output — each supporting three detail levels (detailed, standard, summary). The Orchestrator runs generators in registration order, producing both detailed `docs-live/` references and compact `_claude-md/` summaries. + +### Pipeline Stages + +| Stage | Module | Responsibility | +| ----------- | -------------------------- | --------------------------------------------------------------- | +| Scanner | `src/scanner/` | File discovery, AST parsing, opt-in via `@libar-docs` | +| Extractor | `src/extractor/` | Pattern extraction from TypeScript JSDoc and Gherkin tags | +| Transformer | `src/generators/pipeline/` | MasterDataset with pre-computed views for O(1) access (ADR-006) | +| Codec | `src/renderable/` | Pure functions: MasterDataset → RenderableDocument → Markdown | + +### Codec Inventory + +| Codec | Purpose | +| ---------------------- | -------------------------------------------------------------- | +| ReferenceDocumentCodec | Conventions, diagrams, shapes, behaviors (4-layer composition) | +| PlanningCodec | Roadmap and remaining work | +| SessionCodec | Current work and session findings | +| ReportingCodec | Changelog | +| TimelineCodec | Timeline and traceability | +| RequirementsAdrCodec | ADR generation | +| BusinessRulesCodec | Gherkin rule extraction | +| TaxonomyCodec | Tag registry docs | +| CompositeCodec | Composes multiple codecs into a single document | ## Key Invariants - Codec purity: Every codec is a pure function (dataset in, document out). No side effects, no filesystem access. Same input always produces same output +- Single read model (ADR-006): All codecs consume MasterDataset. No codec reads raw scanner/extractor output. Anti-patterns: Parallel Pipeline, Lossy Local Type, Re-derived Relationship +- Progressive disclosure: Every document renders at three detail levels (detailed, standard, summary) from the same codec. Summary feeds `_claude-md/` modules; detailed feeds `docs-live/reference/` - Config-driven generation: A single `ReferenceDocConfig` produces a complete document. Content sources compose in fixed order: conventions, diagrams, shapes, behaviors - RenderableDocument IR: Codecs express intent ("this is a table"), the renderer handles syntax ("pipe-delimited markdown"). Switching output format requires only a new renderer +- Composition order: Reference docs compose four content layers in fixed order. Product area docs compose five layers: intro, conventions, diagrams, shapes, business rules +- Shape extraction: TypeScript shapes (`interface`, `type`, `enum`, `function`, `const`) are extracted by declaration-level `@libar-docs-shape` tags. Shapes include source text, JSDoc, type parameters, and property documentation +- Generator registration: Generators self-register via `registerGenerator()`. The orchestrator runs them in registration order. Each generator owns its output files and codec configuration + +--- + +## Contents + +- [Key Invariants](#key-invariants) +- [Generation Components](#generation-components) +- [API Types](#api-types) +- [Business Rules](#business-rules) --- @@ -25,9 +62,12 @@ graph TB SourceMapper[/"SourceMapper"/] Documentation_Generation_Orchestrator("Documentation Generation Orchestrator") TransformDataset("TransformDataset") + ProcessApiReferenceGenerator["ProcessApiReferenceGenerator"] DecisionDocGenerator("DecisionDocGenerator") + CliRecipeGenerator["CliRecipeGenerator"] end subgraph renderer["Renderer"] + loadPreambleFromMarkdown___Shared_Markdown_to_SectionBlock_Parser["loadPreambleFromMarkdown — Shared Markdown-to-SectionBlock Parser"] PatternsCodec[("PatternsCodec")] DecisionDocCodec[("DecisionDocCodec")] CompositeCodec[("CompositeCodec")] @@ -39,8 +79,12 @@ graph TB GherkinASTParser["GherkinASTParser"]:::neighbor ShapeExtractor["ShapeExtractor"]:::neighbor ReferenceDocShowcase["ReferenceDocShowcase"]:::neighbor + ProcessApiHybridGeneration["ProcessApiHybridGeneration"]:::neighbor + ProceduralGuideCodec["ProceduralGuideCodec"]:::neighbor PatternRelationshipModel["PatternRelationshipModel"]:::neighbor + CliRecipeCodec["CliRecipeCodec"]:::neighbor end + loadPreambleFromMarkdown___Shared_Markdown_to_SectionBlock_Parser ..->|implements| ProceduralGuideCodec SourceMapper -.->|depends on| DecisionDocCodec SourceMapper -.->|depends on| ShapeExtractor SourceMapper -.->|depends on| GherkinASTParser @@ -50,8 +94,11 @@ graph TB ArchitectureCodec -->|uses| MasterDataset TransformDataset -->|uses| MasterDataset TransformDataset ..->|implements| PatternRelationshipModel + ProcessApiReferenceGenerator ..->|implements| ProcessApiHybridGeneration DecisionDocGenerator -.->|depends on| DecisionDocCodec DecisionDocGenerator -.->|depends on| SourceMapper + CliRecipeGenerator ..->|implements| CliRecipeCodec + CliRecipeCodec -.->|depends on| ProcessApiHybridGeneration classDef neighbor stroke-dasharray: 5 5 ``` @@ -68,6 +115,7 @@ graph TB * Extends the Zod-compatible MasterDataset with workflow reference. * LoadedWorkflow contains Maps which aren't JSON-serializable, * so it's kept separate from the Zod schema. + * */ ``` @@ -87,6 +135,7 @@ interface RuntimeMasterDataset extends MasterDataset { ```typescript /** * Raw input data for transformation + * */ ``` @@ -231,7 +280,7 @@ function transformToMasterDataset(raw: RawDataset): RuntimeMasterDataset; ## Business Rules -72 patterns, 344 rules with invariants (344 total) +88 patterns, 423 rules with invariants (424 total) ### ADR 005 Codec Based Markdown Rendering @@ -245,12 +294,12 @@ function transformToMasterDataset(raw: RawDataset): RuntimeMasterDataset; ### ADR 006 Single Read Model Architecture -| Rule | Invariant | Rationale | -| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| All feature consumers query the read model, not raw state | Code that needs pattern relationships, status groupings, cross-source resolution, or dependency information consumes the MasterDataset. Direct scanner/extractor imports are permitted only in pipeline orchestration code that builds the MasterDataset. | Bypassing the read model forces consumers to re-derive data that the MasterDataset already computes, creating duplicate logic and divergent behavior when the pipeline evolves. Exception: `lint-patterns.ts` is a pure stage-1 consumer. It validates annotation syntax on scanned files. No relationships, no cross-source resolution. Direct scanner consumption is correct for that use case. | -| No lossy local types | Consumers do not define local DTOs that duplicate and discard fields from ExtractedPattern. If a consumer needs a subset, the type system provides the projection — not a hand-written extraction function that becomes a barrier between the consumer and canonical data. | Lossy local types silently drop fields that later become needed, causing bugs that only surface when new MasterDataset capabilities are added and the local type lacks them. | -| Relationship resolution is computed once | Forward relationships (uses, dependsOn, implementsPatterns) and reverse lookups (usedBy, implementedBy, extendedBy) are computed in `transformToMasterDataset()`. No consumer re-derives these from raw pattern arrays or scanned file tags. | Re-deriving relationships in consumers duplicates the resolution logic and risks inconsistency when different consumers implement subtly different traversal or filtering rules. | -| Three named anti-patterns | These are recognized violations, serving as review criteria for new code and refactoring targets for existing code. | Without named anti-patterns, violations appear as one-off style issues rather than systematic architectural drift, making them harder to detect and communicate in code review. Naming them makes them visible in code review — including AI-assisted sessions where the default proposal is often "add a helper function." | +| Rule | Invariant | Rationale | +| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| All feature consumers query the read model, not raw state | Code that needs pattern relationships, status groupings, cross-source resolution, or dependency information consumes the MasterDataset. Direct scanner/extractor imports are permitted only in pipeline orchestration code that builds the MasterDataset. | Bypassing the read model forces consumers to re-derive data that the MasterDataset already computes, creating duplicate logic and divergent behavior when the pipeline evolves. | +| No lossy local types | Consumers do not define local DTOs that duplicate and discard fields from ExtractedPattern. If a consumer needs a subset, the type system provides the projection — not a hand-written extraction function that becomes a barrier between the consumer and canonical data. | Lossy local types silently drop fields that later become needed, causing bugs that only surface when new MasterDataset capabilities are added and the local type lacks them. | +| Relationship resolution is computed once | Forward relationships (uses, dependsOn, implementsPatterns) and reverse lookups (usedBy, implementedBy, extendedBy) are computed in `transformToMasterDataset()`. No consumer re-derives these from raw pattern arrays or scanned file tags. | Re-deriving relationships in consumers duplicates the resolution logic and risks inconsistency when different consumers implement subtly different traversal or filtering rules. | +| Three named anti-patterns | These are recognized violations, serving as review criteria for new code and refactoring targets for existing code. | Without named anti-patterns, violations appear as one-off style issues rather than systematic architectural drift, making them harder to detect and communicate in code review. | ### Arch Generator Registration @@ -288,6 +337,31 @@ function transformToMasterDataset(raw: RawDataset): RuntimeMasterDataset; | MasterDataset builds archIndex during transformation | The `transformToMasterDataset` function must build an `archIndex` that groups patterns by role, context, and layer for efficient diagram generation. | Single-pass extraction during dataset transformation avoids expensive re-traversal. Index structure enables O(1) lookup by each dimension. | | Component diagrams group patterns by bounded context | Component diagrams must render patterns as nodes grouped into bounded context subgraphs, with relationship arrows using UML-inspired styles. | Component diagrams visualize system architecture showing how bounded contexts isolate components. Subgraphs enforce visual separation. | +### Architecture Doc Refactoring + +| Rule | Invariant | Rationale | +| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Convention-tagged JSDoc produces machine-extractable codec documentation | Every codec source file annotated with `@libar-docs-convention
codec-registry` must have structured JSDoc following the machine-extractable format. The convention extractor splits multi-codec files by `## Heading` into separate convention rules, each rendered as its own section in the generated reference document. | DD-1: Convention tag approach over dedicated codec. Rather than creating a new "codec inventory" codec that enumerates codecs from source, the existing convention-tag mechanism is reused. Each codec file's JSDoc is treated as convention rules tagged with `codec-registry`. This avoids new codec infrastructure and leverages the proven convention extractor path. The reference codec already handles 4-layer composition, so convention tags slot into the existing Layer 1 (conventions) position. | +| Machine-extractable JSDoc format follows structured heading convention | DD-2: Multi-codec JSDoc splitting uses one `## Heading` per codec per file. Each heading block contains structured fields in a fixed order: `**Purpose:**` one-liner, `**Output Files:**` file paths, options table with Type/Default/Description columns, `**When to Use:**` bullet list, and `**Factory Pattern:**` code example. Fields are optional -- codecs without options omit the table, codecs without factory patterns omit the code block. | The convention extractor uses `## ` heading regex to split descriptions into rules. Without this structure, a file like `session.ts` (3 codecs) would produce a single undifferentiated blob. The heading text becomes the convention rule title in the generated reference. The fixed field order ensures consistent rendering across all 20+ codec entries. | +| Heading match in convention extractor handles whitespace correctly | The convention extractor's heading parser uses `matchEnd` (the character position after the full regex match) rather than `indexOf('\n',
heading.index)` to calculate where content starts after a heading. This prevents the `\s*` prefix in the heading regex from consuming leading newlines, which would cause `heading.index` to point to those newlines instead of the heading text. | Discovered during Phase 2 implementation. The heading regex `/^\s*##\s+(.+)$/gm` matches headings with optional leading whitespace. When a heading has leading newlines, `heading.index` points to the first newline (part of the `\s*` match), not the `##` character. Using `indexOf('\n', heading.index)` then finds the newline BEFORE the heading, producing content that includes the heading text itself. The fix uses the regex match's end position directly. | +| Section disposition follows content-type routing | DD-3: Each ARCHITECTURE.md section is routed based on content type. Three routing strategies apply: (1) product area absorption -- sections describing a specific pipeline stage move to the corresponding product area document where they get live diagrams and relationship graphs; (2) generated shapes -- sections documenting TypeScript interfaces move to generated shape reference docs; (3) generated diagrams -- ASCII/text data flow diagrams are replaced by live Mermaid diagrams generated from architecture annotations. | The routing heuristic is: if a generated equivalent already exists, replace with pointer; if content is convention-taggable in source files, tag and generate; if editorial content that cannot be expressed as annotations, retain. This ensures each section lands in the location with the best maintenance model for its content type. | +| Product area absorption validates content coverage before pointer replacement | DD-4: Product area absorption replaces ARCHITECTURE.md sections with pointers only when the target product area document already covers the equivalent content. Three sections route to product areas: Configuration Architecture (L70-139) to CONFIGURATION.md, Source Systems (L585-692) to ANNOTATION.md, and Workflow Integration (L959-1068) to PROCESS.md. Annotation format examples from Source Systems merge into the Four-Stage Pipeline retained section rather than being lost. Workflow API code examples are dropped -- Claude reads source files directly. | Product area documents are generated from annotated source code and already contain live diagrams, relationship graphs, and API types. Absorbing manual Architecture sections into these generated docs eliminates drift while preserving the content in a maintained location. The key test is: does the product area doc cover the same technical facts? If yes, the manual section becomes a 4-line pointer. | +| MasterDataset shapes generate a dedicated ARCHITECTURE-TYPES reference document | DD-6: A new ReferenceDocConfig produces ARCHITECTURE-TYPES.md using shapeSelectors with group master-dataset to extract MasterDataset schema types, RuntimeMasterDataset, RawDataset, PipelineOptions, and PipelineResult. Source files tagged with libar-docs-shape master-dataset and libar-docs-include master-dataset contribute shapes to the reference doc. The Unified Transformation section (L345-478) is replaced with a condensed narrative (~15 lines) and pointer to ARCHITECTURE-TYPES.md. | The MasterDataset is the central data structure -- the sole read model per ADR-006. It deserves dedicated reference doc treatment alongside ARCHITECTURE-CODECS.md. Shape extraction from TypeScript declarations provides exact type signatures that stay in sync with code, unlike the manual schema table in ARCHITECTURE.md. | +| Pipeline architecture convention content replaces ASCII data flow diagrams | DD-7: The Data Flow Diagrams section (L774-957) contains 4 ASCII diagrams totaling ~183 lines. These are replaced using a hybrid approach: convention tag pipeline-architecture (already registered, currently unused) on orchestrator.ts and build-pipeline.ts produces prose descriptions of pipeline steps and consumer architecture. A new master-dataset-views hardcoded diagram source generates a Mermaid fan-out diagram showing dataset view relationships. DD-8: Both convention content and diagram source are configured on the ARCHITECTURE-TYPES.md ReferenceDocConfig, keeping all architecture reference content in one generated document. | ASCII diagrams cannot be generated from code annotations. The hybrid approach maximizes generated coverage: convention-tagged JSDoc captures the narrative (pipeline steps, ADR-006 consumer pattern) while the hardcoded diagram source produces visual Mermaid output. Using the already-registered pipeline-architecture convention tag avoids new taxonomy entries. | +| Usefulness-driven editorial trimming targets Claude as primary consumer | DD-9: ARCHITECTURE.md serves Claude (primary audience) and human developers (secondary). Content retained must answer architectural "why" and "how things connect" questions. Content available via source file reads or generated reference documents is removed. Post-decomposition target: ~320 lines (~75% reduction from 1,287 lines). Sections dropped entirely: Programmatic Usage (L1070-1125) and Extending the System (L1127-1194) -- Claude reads source files directly and infers extension patterns from existing codec implementations. DD-5: Key Design Patterns section (L693-772) trimmed from ~80 to ~15 lines: Result Monad becomes a pointer to CORE-TYPES.md, Schema-First Validation becomes a 3-line summary with source pointer, Tag Registry becomes a 4-line summary with source pointer. | Claude has direct access to source files and generated reference docs. Duplicating this content in ARCHITECTURE.md wastes context window tokens. The remaining editorial sections (Executive Summary, Four-Stage Pipeline, Codec Architecture, Progressive Disclosure) provide the mental model and architectural "why" that cannot be inferred from code alone. | + +### Architecture Doc Refactoring Testing + +| Rule | Invariant | Rationale | +| --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Product area sections coexist with generated documents | Each architecture section in docs/ARCHITECTURE.md has a corresponding generated document in docs-live/product-areas/ covering equivalent content from annotated sources. | Manual and generated docs must coexist during the transition period. Generated docs prove that annotated sources produce equivalent coverage before manual sections are deprecated. | +| Four-Stage Pipeline section retains annotation format examples | The Four-Stage Pipeline section contains annotation format examples (e.g., @libar-docs-shape, extract-shapes) and appears before the Source Systems section in document order. | Annotation format examples in the pipeline section demonstrate the source-first architecture. Their ordering establishes the conceptual flow: pipeline stages first, then the source systems that feed them. | +| Convention extraction produces ARCHITECTURE-CODECS reference document | The ARCHITECTURE-CODECS.md reference document is generated from convention-tagged JSDoc in codec source files and contains structured sections for each codec with output file references. | Codec documentation must stay synchronized with source code. Convention extraction from JSDoc ensures the reference document reflects actual codec implementations rather than manually maintained descriptions that drift. | +| Full sections coexist with generated equivalents in docs-live | Major sections of ARCHITECTURE.md (Unified Transformation, Data Flow Diagrams, Quick Reference) are retained alongside their generated equivalents in docs-live/reference/. | Generated reference documents (ARCHITECTURE-TYPES.md, ARCHITECTURE-CODECS.md) provide exhaustive type and codec listings, but the manual sections offer architectural narrative and design rationale that generated docs cannot yet replicate. | +| MasterDataset shapes appear in ARCHITECTURE-TYPES reference | The ARCHITECTURE-TYPES.md reference document contains core MasterDataset types (MasterDataset, RuntimeMasterDataset, RawDataset) and pipeline types (PipelineOptions, PipelineResult) extracted from shape annotations. | Type shapes are the structural backbone of the pipeline. Generating their documentation from annotations ensures the reference always matches the actual TypeScript interfaces, eliminating manual drift. | +| Pipeline architecture convention appears in generated reference | Source files in the pipeline layer (orchestrator.ts, build-pipeline.ts) carry the pipeline-architecture convention tag, enabling convention extraction into the ARCHITECTURE-TYPES reference document. | Convention tags on pipeline source files are the mechanism that feeds content into generated reference docs. Without these tags, the architecture reference would have no source material to extract. | +| Full ARCHITECTURE.md retains all sections with substantial content | ARCHITECTURE.md retains all major sections (Programmatic Usage, Extending the System, Key Design Patterns) with substantial content and remains under 1700 lines as a comprehensive reference. | These sections contain editorial content (usage examples, extension guides, design pattern explanations) that cannot be generated from annotations. They remain manual until procedural guide codecs can replicate their depth. | + ### Arch Tag Extraction | Rule | Invariant | Rationale | @@ -328,15 +402,25 @@ function transformToMasterDataset(raw: RawDataset): RuntimeMasterDataset; ### Claude Module Generation -| Rule | Invariant | Rationale | -| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Claude module tags exist in the tag registry | Three claude-specific tags (`claude-module`, `claude-section`, `claude-tags`) must exist in the tag registry with correct format and values. | Module generation requires metadata to determine output path, section placement, and variation filtering. Standard tag infrastructure enables consistent extraction via the existing Gherkin parser. | -| Gherkin parser extracts claude module tags from feature files | The Gherkin extractor must extract `claude-module`, `claude-section`, and `claude-tags` from feature file tags into ExtractedPattern objects. | Behavior specs are the source of truth for CLAUDE.md module content. Parser must extract module metadata alongside existing pattern metadata. | -| Module content is extracted from feature file structure | The codec must extract content from standard feature file elements: Feature description (Problem/Solution), Rule blocks, and Scenario Outline Examples. | Behavior specs already contain well-structured, prescriptive content. The extraction preserves structure rather than flattening to prose. | -| ClaudeModuleCodec produces compact markdown modules | The codec transforms patterns with claude tags into markdown files suitable for the `_claude-md/` directory structure. | CLAUDE.md modules must be compact and actionable. The codec produces ready-to-use markdown without truncation (let modular-claude-md handle token budget warnings). | -| Claude module generator writes files to correct locations | The generator must write module files to `{outputDir}/{section}/{module}.md` based on the `claude-section` and `claude-module` tags. | Output path structure must match modular-claude-md expectations. The `claude-section` determines the subdirectory, `claude-module` determines filename. | -| Claude module generator is registered with generator registry | A "claude-modules" generator must be registered with the generator registry to enable `pnpm docs:claude-modules` via the existing CLI. | Consistent with architecture-diagram-generation pattern. New generators register with the orchestrator rather than creating separate commands. | -| Same source generates detailed docs with progressive disclosure | When running with `detailLevel: "detailed"`, the codec produces expanded documentation including all Rule content, code examples, and scenario details. | Single source generates both compact modules (AI context) and detailed docs (human reference). Progressive disclosure is already a codec capability. | +| Rule | Invariant | Rationale | +| --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Claude module tags exist in the tag registry | Three claude-specific tags (`claude-module`, `claude-section`, `claude-tags`) must exist in the tag registry with correct format and values. | Module generation requires metadata to determine output path, section placement, and variation filtering. Standard tag infrastructure enables consistent extraction via the existing Gherkin parser. | +| Gherkin parser extracts claude module tags from feature files | The Gherkin extractor must extract `claude-module`, `claude-section`, and `claude-tags` from feature file tags into ExtractedPattern objects. | Behavior specs are the source of truth for CLAUDE.md module content. Parser must extract module metadata alongside existing pattern metadata. | +| Module content is extracted from feature file structure | The codec extracts content from Rule blocks and Scenario Outline Examples only. Feature descriptions (Problem/Solution preamble) are skipped because they contain meta-documentation about why the spec exists, not operational content for AI sessions. | Behavior specs contain well-structured, prescriptive content in Rule blocks. Feature descriptions waste context in compact AI modules — the invariants and rationale in Rule blocks are the actionable content. | +| ClaudeModuleCodec produces compact markdown modules | The codec transforms patterns with claude tags into markdown files suitable for the `_claude-md/` directory structure. | CLAUDE.md modules must be compact and actionable. The codec produces ready-to-use markdown without truncation (let modular-claude-md handle token budget warnings). | +| Claude module generator writes files to correct locations | The generator must write module files to `{outputDir}/{section}/{module}.md` based on the `claude-section` and `claude-module` tags. | Output path structure must match modular-claude-md expectations. The `claude-section` determines the subdirectory, `claude-module` determines filename. | +| Claude module generator is registered with generator registry | A "claude-modules" generator must be registered with the generator registry to enable `pnpm docs:claude-modules` via the existing CLI. | Consistent with architecture-diagram-generation pattern. New generators register with the orchestrator rather than creating separate commands. | +| Same source generates detailed docs with progressive disclosure | When running with `detailLevel: "detailed"`, the codec produces expanded documentation including all Rule content, code examples, and scenario details. | Single source generates both compact modules (AI context) and detailed docs (human reference). Progressive disclosure is already a codec capability. | + +### Cli Recipe Codec + +| Rule | Invariant | Rationale | +| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| CLI recipes are a separate generator from reference tables | The `CliRecipeGenerator` is a standalone sibling to `ProcessApiReferenceGenerator`, not an extension of it. Both implement `DocumentGenerator`, both consume `CLI_SCHEMA` directly, and both produce independent `OutputFile[]` via the standard orchestrator write path. The recipe generator produces `docs-live/reference/PROCESS-API-RECIPES.md` while the reference generator produces `docs-live/reference/PROCESS-API-REFERENCE.md`. | Reference tables and recipe guides serve different audiences and change at different cadences. Reference tables change when CLI flags are added or removed. Recipes change when workflow recommendations evolve. Coupling them in one generator would force both to change together and make the generator responsible for two distinct content types. ProcessApiReferenceGenerator is already completed and tested (Phase 43) -- extending it risks regressions. Two small standalone generators are easier to test and maintain than one large one. | +| Recipe content uses a structured schema extension | `CLI_SCHEMA` is extended with a `recipes` field containing `RecipeGroup[]`. Each `RecipeGroup` has a title, optional description, and an array of `RecipeExample` objects. Each `RecipeExample` has a title, a purpose description, an array of command strings, and an optional expected output block. The schema extension is additive -- existing `CLIOptionGroup` types are unchanged. | Recipes are multi-command sequences ("run these 3 commands in order") with explanatory context. They do not fit into `CLIOptionGroup` which models individual flags. A separate `RecipeGroup[]` keeps the schema type-safe and makes recipes independently testable. Static expected output strings in the schema are deterministic -- no build-time CLI execution needed. | +| Narrative prose uses preamble mechanism | Editorial content that cannot be derived from the CLI schema -- specifically "Why Use This" motivational prose, the Quick Start example with output, and the session type decision tree -- uses a preamble mechanism in the generator configuration. Preamble content is manually authored in `delivery-process.config.ts` as structured section data and appears before all generated recipe content in the output file. | The "Why Use This" section explains the value proposition of the Data API CLI with a comparison table (CLI vs reading markdown). This is editorial judgment, not derivable from command metadata. The Quick Start shows a specific 3-command workflow with example terminal output. The session decision tree maps cognitive states ("Starting to code?") to session types. None of these have a source annotation -- they are instructional content authored for human understanding. The preamble mechanism exists precisely for this (proven by DocsConsolidationStrategy Phase 2 preamble implementation). | +| Generated recipe file complements manual PROCESS-API.md | After this pattern completes, `docs/PROCESS-API.md` is trimmed to a slim editorial introduction (~30 lines) containing the document title, a one-paragraph purpose statement, and links to both generated files: `docs-live/reference/PROCESS-API-REFERENCE.md` (option tables from Phase 43) and `docs-live/reference/PROCESS-API-RECIPES.md` (recipes and narratives from this pattern). The manual file retains the JSON Envelope, Exit Codes, and JSON Piping sections (~40 lines) which are operational reference unlikely to drift. All other prose sections are replaced by the generated recipe file. | Phase 43 established the hybrid pattern: keep editorial prose in the manual file, extract derivable content to generated files. This pattern extends the hybrid by recognizing that recipe content IS derivable from a structured schema. The ~460 lines of command descriptions, example output, and recipe blocks can be maintained as schema data rather than freeform markdown. What remains in the manual file (~70 lines total) is true operational reference (JSON envelope format, exit codes, piping tips) that changes rarely and has no schema source. | +| Command narrative descriptions are sourced from schema metadata | Each command group in the generated recipe file includes a narrative description sourced from the CLI schema, not hardcoded in the generator. The existing `CLIOptionGroup.description` and `CLIOptionGroup.postNote` fields carry per-group narrative text. For command groups not currently in CLI_SCHEMA (Session Workflow Commands, Pattern Discovery, Architecture Queries, Metadata and Inventory), new `CommandGroup` entries are added to the schema with title, description, and per-command narrative metadata. | The manual PROCESS-API.md contains narrative descriptions for each command ("Highest-impact command. Pre-flight readiness check that prevents wasted sessions.") that are valuable developer context. Hardcoding these in the generator would create a second maintenance location. Placing them in CLI_SCHEMA co-locates command metadata (what the command does) with command definition (what flags it accepts), following the same single-source-of-truth principle that drove Phase 43. | ### Codec Based Generator Testing @@ -467,15 +551,32 @@ function transformToMasterDataset(raw: RawDataset): RuntimeMasterDataset; ### Doc Generation Proof Of Concept -| Rule | Invariant | Rationale | -| ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Context - Manual documentation maintenance does not scale | Documentation must be generated from annotated source code, never manually maintained as a separate artifact. | Manual documentation drifts from source as the codebase evolves, creating stale references that mislead both humans and AI coding sessions. | -| Decision - Decisions own convention content and durable context, code owns details | Each content type (intro/rationale, rules/examples, API types) is owned by exactly one source type (decision, behavior spec, or code). | Shared ownership leads to conflicting updates and ambiguous authority over what the "correct" version is. | -| Proof of Concept - Self-documentation validates the pattern | The documentation generation pattern must be validated by generating documentation about itself from its own annotated sources. | A self-referential proof of concept exposes extraction gaps and source mapping issues that synthetic test data would miss. This POC demonstrates the doc-from-decision pattern by generating docs about ITSELF. The DocGenerationProofOfConcept pattern produces: | -| Expected Output - Compact claude module structure | Compact output must contain only essential tables and type names, with no JSDoc comments or implementation details. | AI context windows are finite; including non-essential content displaces actionable information and degrades session effectiveness. | -| Consequences - Durable sources with clear ownership boundaries | Decision documents remain the authoritative source for intro, rationale, and convention content until explicitly superseded. | Without durable ownership, documentation sections lose their authoritative source and degrade into unattributed prose that no one updates. | -| Consequences - Design stubs live in stubs, not src | Pre-implementation design stubs must reside in `delivery-process/stubs/`, never in `src/`. | Stubs in `src/` require ESLint exceptions, create confusion between production and design code, and risk accidental imports of unimplemented functions. | -| Decision - Source mapping table parsing and extraction method dispatch | The source mapping table in a decision document defines how documentation sections are assembled from multiple source files. | Without a declarative mapping, generators must hard-code source-to-section relationships, making the system brittle to new document types. | +| Rule | Invariant | Rationale | +| ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Context - Manual documentation maintenance does not scale | Documentation must be generated from annotated source code, never manually maintained as a separate artifact. | Manual documentation drifts from source as the codebase evolves, creating stale references that mislead both humans and AI coding sessions. | +| Decision - Decisions own convention content and durable context, code owns details | Each content type (intro/rationale, rules/examples, API types) is owned by exactly one source type (decision, behavior spec, or code). | Shared ownership leads to conflicting updates and ambiguous authority over what the "correct" version is. | +| Proof of Concept - Self-documentation validates the pattern | The documentation generation pattern must be validated by generating documentation about itself from its own annotated sources. | A self-referential proof of concept exposes extraction gaps and source mapping issues that synthetic test data would miss. | +| Expected Output - Compact claude module structure | Compact output must contain only essential tables and type names, with no JSDoc comments or implementation details. | AI context windows are finite; including non-essential content displaces actionable information and degrades session effectiveness. | +| Consequences - Durable sources with clear ownership boundaries | Decision documents remain the authoritative source for intro, rationale, and convention content until explicitly superseded. | Without durable ownership, documentation sections lose their authoritative source and degrade into unattributed prose that no one updates. | +| Consequences - Design stubs live in stubs, not src | Pre-implementation design stubs must reside in `delivery-process/stubs/`, never in `src/`. | Stubs in `src/` require ESLint exceptions, create confusion between production and design code, and risk accidental imports of unimplemented functions. | +| Decision - Source mapping table parsing and extraction method dispatch | The source mapping table in a decision document defines how documentation sections are assembled from multiple source files. | Without a declarative mapping, generators must hard-code source-to-section relationships, making the system brittle to new document types. | + +### Docs Consolidation Strategy + +| Rule | Invariant | Rationale | +| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Convention tags are the primary consolidation mechanism | Each consolidation phase follows the same pattern: register a convention tag value in `src/taxonomy/conventions.ts`, annotate source files with `@libar-docs-convention` tags using structured JSDoc, add a `ReferenceDocConfig` entry in `delivery-process.config.ts`, and replace the manual doc section with a pointer to the generated reference document. | Convention-tagged annotations are the only sustainable way to keep docs in sync with implementation. The reference codec (`createReferenceCodec`) already handles the 4-layer composition so each phase only needs annotation work and config — no new codec infrastructure required. | +| Preamble preserves editorial context in generated docs | `ReferenceDocConfig.preamble` accepts `readonly SectionBlock[]` that are prepended before all generated content. Preamble sections appear in both detailed and summary (claude-md) outputs, followed by a separator. A config without preamble produces no extra separator or empty sections. | Not all documentation content can be extracted from code annotations. Introductory prose, cross-cutting context, and reading guides require human authorship. The preamble provides a designated place for this content within the generated document structure, avoiding a separate hand-maintained file. | +| Each consolidation phase is independently deliverable | Each phase can be implemented and validated independently. A phase is complete when: the manual doc section has been replaced with a pointer to the generated equivalent, `pnpm docs:all` produces the generated output without errors, and the generated content covers the replaced manual content. No phase requires another uncompleted phase to function. | Independent phases allow incremental consolidation without blocking on the full initiative. Each merged PR reduces manual maintenance immediately. Phase ordering in the plan is a suggested sequence (simplest first), not a dependency chain. | +| Manual docs retain editorial and tutorial content | Documents containing philosophy (METHODOLOGY.md), workflow guides (SESSION-GUIDES.md), tutorials (GHERKIN-PATTERNS.md), CLI reference (PROCESS-API.md), and operational procedures (PUBLISHING.md) remain fully manual. These docs are ~2,300 lines total and contain instructional content that cannot be expressed as source annotations. | The consolidation targets sections most likely to drift when code changes: reference tables, codec listings, validation rules, API types. Editorial content changes at a different cadence and requires human judgment to update. Forcing this into annotations would produce worse documentation. | +| Audience alignment determines document location | Each document lives in the location matching its primary audience: `docs/` (deployed to libar.dev) for content that serves package users and developers; repo root for GitHub-visible metadata (CONTRIBUTING.md, SECURITY.md, MAINTAINERS.md); CLAUDE.md for AI session context. A document appearing in docs/ must be useful to a developer or user visiting the website — maintainer-only operational procedures (npm publishing workflow, GitHub Actions setup) belong at the repo root. | The audit found PUBLISHING.md (maintainer-only) in docs/ alongside user-facing guides. SESSION-GUIDES.md (AI session procedures) duplicates CLAUDE.md with 95% overlap. Audience mismatches increase website noise for users and create drift risk when the same content lives in two locations. | + +### Docs Live Consolidation + +| Rule | Invariant | Rationale | +| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| docs-live/ is the single directory for website-published content | Every file appearing on `libar.dev` or referenced by CLAUDE.md comes from `docs-live/`. No production reference document is published from `docs-generated/`. The `docs-generated/` directory contains no production reference content after `docs:all` runs. Business-rules, taxonomy, and validation-rules output to `docs-live/` alongside other reference docs. | DD-1: Splitting production output across two directories creates ambiguity about where authoritative content lives. Website configuration, CLAUDE.md path references, and team navigation all benefit from a single source directory. `docs-generated/` name signals "build cache", not "publishable output". | +| All \_claude-md/ compact files consolidate under docs-live/ | All `_claude-md/` compact context files live under `docs-live/_claude-md/`. Architecture-scoped compacts (architecture-codecs, architecture-types) move from `docs-generated/_claude-md/architecture/` to `docs-live/_claude-md/architecture/`. Product-area compacts remain at `docs-live/_claude-md/` unchanged. | DD-2: `_claude-md/` compact versions are the Claude consumption contract — agents read compacts, not full product area docs. Having compacts split across two directories (docs-generated/ and docs-live/) means Claude sessions following "read from docs-live/" miss the architecture compacts entirely. | ### Documentation Orchestrator @@ -483,6 +584,24 @@ function transformToMasterDataset(raw: RawDataset): RuntimeMasterDataset; | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | | Orchestrator coordinates full documentation generation pipeline | Non-overlapping patterns from TypeScript and Gherkin sources must merge into a unified dataset; overlapping pattern names must fail with conflict error. | Silent merging of conflicting patterns would produce incorrect documentation — fail-fast ensures data integrity across the pipeline. | +### Enhanced Index Generation + +| Rule | Invariant | Rationale | +| ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| IndexCodec composes generated statistics with editorial navigation | The IndexCodec generates document listings and pattern statistics from MasterDataset pre-computed views (`byCategory`, `byPhase`, `byProductArea`, `byStatus`), while audience reading paths, the document roles matrix, and the quick finder table use the `ReferenceDocConfig.preamble` mechanism as manually authored `SectionBlock[]`. The codec does not hardcode document metadata -- all statistics are derived from the dataset at generation time. Editorial content changes at authorial cadence via config edits, not code changes. | Approximately 40% of INDEX.md content (product area lists, file inventories, pattern statistics, phase progress) is directly derivable from MasterDataset views and drifts when patterns change status or new patterns are added. The remaining 60% (audience paths, document roles, quick finder) requires human editorial judgment about which documents serve which readers. The preamble mechanism cleanly separates these two content types within a single generated output, as proven by CodecDrivenReferenceGeneration and DocsConsolidationStrategy Phase 2. | +| Audience reading paths are first-class sections | Three audience profiles exist in the generated index: New User, Developer/AI, and Team Lead/CI. Each profile has a curated reading order that lists documents in recommended sequence with a one-line description of what each document provides for that audience. Reading paths appear prominently after the quick navigation table and before the auto-generated statistics sections. The reading paths are sourced from preamble, not derived from pattern metadata. | The manual INDEX.md reading orders are consistently cited as the most useful navigation aid by developers onboarding to the project. A flat alphabetical file listing (as in the current docs-live/INDEX.md) forces readers to guess which documents are relevant to their role. Audience-specific paths reduce time-to-relevance from minutes of scanning to seconds of following a curated sequence. This content is inherently editorial -- no annotation can express "read this third because it builds on concepts from document two." | +| Index unifies manual and generated doc listings | The generated index covers both `docs/` (manual reference documents) and `docs-live/` (generated reference documents) in a single unified navigation structure. Documents are organized by topic or audience, not by source directory. The reader does not need to know whether a document is manually authored or auto-generated. Each document entry includes its title, a brief description, and its primary audience. The directory source (docs/ or docs-live/) appears only in the link path, not as a section heading or organizational axis. | The current documentation set splits across two directories for implementation reasons (manual vs generated), but this split is meaningless to readers. A developer looking for architecture documentation should find one entry, not separate entries under "Manual Docs" and "Generated Docs" sections. The unified listing follows the same principle as a library catalog -- books are organized by subject, not by whether they were hand-typeset or digitally printed. | +| Document metadata drives auto-generated sections | Pattern counts per product area, phase progress summaries, and product area coverage percentages are derived from MasterDataset pre-computed views at generation time. The IndexCodec accesses `dataset.byProductArea` for area statistics, `dataset.byStatus` for status distribution, and `dataset.byPhase` for phase ordering. No statistics are hardcoded in the codec or config. When a pattern changes status or a new pattern is added, regenerating the index reflects the change without any manual update. | The manual INDEX.md has no statistics section because maintaining accurate counts manually is unsustainable across 196+ patterns. The MasterDataset pre-computed views provide O(1) access to grouped pattern data. Surfacing these statistics in the index gives readers an at-a-glance project health overview (how many patterns per area, what percentage are completed, which phases are active) that was previously only available via the Process Data API CLI. | + +### Error Guide Codec + +| Rule | Invariant | Rationale | +| ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Error guide extends the existing ValidationRulesCodec | Error diagnosis guide content is produced by enhancing the existing `ValidationRulesCodec` and its `RULE_DEFINITIONS` constant, not by creating a parallel codec. The enhanced codec adds fix rationale, alternative approaches, and integration context to the existing error catalog, FSM transitions, and protection level detail files. A separate `ErrorGuideCodec` class is not created. | `ValidationRulesCodec` already owns `RULE_DEFINITIONS` with error codes, causes, and fixes. It generates `error-catalog.md`, `fsm-transitions.md`, and `protection-levels.md`. Creating a parallel codec would duplicate RULE_DEFINITIONS access and fragment validation documentation across two codecs. Extending the existing codec keeps all validation reference content in one place. | +| Each error code has fix rationale explaining why the rule exists | Every error code in the generated output includes not just a fix command but a "why this rule exists" rationale. The rationale is sourced from `@libar-docs-convention:process-guard-errors` JSDoc annotations on the error-handling code in `src/lint/process-guard/`. The `RuleDefinition` interface is extended with a `rationale` field, or rationale is composed from convention-extracted content. | The existing `error-catalog.md` tells developers what to do (fix command) but not why the rule exists. Without rationale, developers reach for escape hatches instead of understanding the workflow constraint. PROCESS-GUARD.md includes rationale like "Prevents scope creep during implementation. Plan fully before starting; implement what was planned." -- this must survive in the generated output. | +| Preamble carries integration content that cannot come from annotations | Pre-commit setup instructions (Husky configuration, package.json scripts), CI pipeline patterns, programmatic API examples, and the Decider pattern architecture diagram use the `ReferenceDocConfig.preamble` mechanism. These are `SectionBlock[]` defined in the config entry, prepended before all generated content. Preamble content is manually authored and changes at editorial cadence, not code cadence. | Integration recipes (Husky hook setup, CI YAML patterns, API usage examples) are not extractable from source annotations because they describe how external systems consume Process Guard, not how Process Guard is implemented. The preamble mechanism exists precisely for this: editorial prose that lives in the config, not in a separate manual file, and appears in the generated output. | +| Convention tags source error context from annotated lint code | Error-handling code in `src/lint/process-guard/` is annotated with `@libar-docs-convention:process-guard-errors` using structured JSDoc that includes rationale, alternative approaches, and common mistake patterns. The convention tag value `process-guard-errors` is registered in `src/taxonomy/conventions.ts` in the `CONVENTION_VALUES` array. The `createReferenceCodec` factory extracts this content via the existing convention extractor pipeline. | Convention-tagged annotations on the error-handling code co-locate rationale with implementation. When a developer changes an error rule in the decider, the convention JSDoc is right there -- they update both in the same commit. This is the same pattern used by `codec-registry`, `pipeline-architecture`, and `taxonomy-rules` convention tags, all proven by CodecDrivenReferenceGeneration. | + ### Extract Summary | Rule | Invariant | Rationale | @@ -493,6 +612,23 @@ function transformToMasterDataset(raw: RawDataset): RuntimeMasterDataset; | Tautological and header lines are skipped | Lines that merely repeat the pattern name or consist only of a section header label (e.g., "Problem:", "Solution:") are skipped; the summary begins with the first substantive line. | Tautological opening lines waste the limited summary space without adding information. | | Edge cases are handled gracefully | Degenerate inputs (empty strings, markdown-only content, bold markers) produce valid output without errors: empty input yields empty string, formatting is stripped, and multiple sentence endings use the first. | Summary extraction runs on every pattern in the dataset; an unhandled edge case would crash the entire documentation generation pipeline. | +### Generated Doc Quality + +| Rule | Invariant | Rationale | +| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Behavior-specs renderer does not duplicate convention table content | When the reference codec renders a convention rule that contains a table, the table appears exactly once in the output: in the main convention section. The behavior-specs (expanded rule detail) section shows only the Invariant, Rationale, and Verified-by metadata — not the table body. A convention section with N tables produces exactly N table instances in the generated document, regardless of detail level. | DD-4: The current renderer re-includes the full convention table when rendering the expanded rule detail section. For REFERENCE-SAMPLE.md with 5 canonical value tables, this produces 500+ lines of exact duplication. Agents consuming this file waste context on content they already parsed. Human readers see the same table twice in the same scroll view. | +| Compact \_claude-md/ files are self-sufficient for their product area | Each product area compact (`_claude-md//-overview.md`) is self-sufficient as a standalone context file — an agent reading only the compact can answer: what does this area do, what are its key patterns, what are its invariants, and what files to read for details. Minimum target: 4 KB. The Generation compact is a specific gap: 1.4 KB for an area with 20+ codecs and the entire rendering pipeline. | DD-2: `_claude-md/` compacts are the Claude consumption contract. A 1.4 KB compact for the largest product area (233 KB) means agents have no usable summary context for Generation. They fall back to reading the full file or hallucinating based on names alone. The contract requires each compact to be a genuine summary, not a stub. | +| ARCHITECTURE-TYPES.md leads with type definitions, not convention content | ARCHITECTURE-TYPES.md opens with the MasterDataset type definitions section before any pipeline-architecture convention content. An agent querying "what is MasterDataset" finds the type definition within the first 30 lines. The pipeline-architecture convention prose (orchestrator responsibilities, pipeline steps) follows the type definitions section. | The file is named ARCHITECTURE-TYPES — type definitions are the primary content. The pipeline-architecture convention content was added as a secondary layer. Current output opens with orchestrator prose, burying the type definitions that both Claude and human developers are most likely seeking. Section ordering in ReferenceDocConfig determines render order. | + +### Generated Doc Quality Tests + +| Rule | Invariant | Rationale | +| ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | +| Behavior-specs renderer does not duplicate convention table content | Convention tables appear exactly once in the output — in the convention section. The behavior-specs section shows only metadata. | DD-4: Duplicate tables waste 500+ lines and agent context tokens. | +| ARCHITECTURE-TYPES leads with type definitions | When shapesFirst is true, shapes render before conventions. | ARCHITECTURE-TYPES.md should open with type definitions, not orchestrator prose. | +| Product area docs have a generated table of contents | Product area docs with 3+ H2 headings include a Contents section with anchor links. | Large product area docs need browser-navigable TOC for human developers. | +| Generation compact is self-sufficient | The Generation compact contains codec inventory and pipeline summary at 4+ KB. | DD-2: A 1.4 KB compact for the largest area means agents have no usable summary. | + ### Generator Infrastructure Testing | Rule | Invariant | Rationale | @@ -508,6 +644,14 @@ function transformToMasterDataset(raw: RawDataset): RuntimeMasterDataset; | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | | Registry manages generator registration and retrieval | Each generator name is unique within the registry; duplicate registration is rejected and lookup of unknown names returns undefined. | Allowing duplicate names would silently overwrite an existing generator, causing previously registered behavior to disappear without warning. | +### Gherkin Patterns Restructure + +| Rule | Invariant | Rationale | +| ----------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Step Linting content belongs in VALIDATION.md | All validation tooling reference content lives in VALIDATION.md. | VALIDATION.md already documents lint-patterns, lint-process, and validate-patterns. Step Linting is a fourth quality tool in the same family — it must follow the same pattern. Redirecting from VALIDATION.md to GHERKIN-PATTERNS.md for lint rules breaks the principle that VALIDATION.md is the single place to find quality tooling documentation. | +| GHERKIN-PATTERNS.md remains the authoring guide | GHERKIN-PATTERNS.md covers only Gherkin writing patterns, not tooling reference. | The writing guide is useful during spec authoring. Quality tool reference is useful during CI setup and debugging. Mixing them forces authors to scroll past 148 lines of tooling reference they do not need during writing, and forces CI engineers to look in the wrong file for lint rule documentation. | +| INDEX.md reflects current document structure | INDEX.md section tables and line counts must be updated when content moves between docs. | INDEX.md serves as the navigation hub for all documentation. Stale line counts and missing section entries cause developers to land in the wrong part of a document or miss content entirely. Both GHERKIN-PATTERNS.md and VALIDATION.md entries must reflect the restructure. | + ### Implementation Link Path Normalization | Rule | Invariant | Rationale | @@ -526,6 +670,21 @@ function transformToMasterDataset(raw: RawDataset): RuntimeMasterDataset; | Patterns without layer go to Other subgraph | Patterns that have arch-role or arch-context but no arch-layer must be placed in an "Other" subgraph, never omitted from the diagram. | Omitting unlayered patterns would silently hide architectural components; the "Other" group makes their missing classification visible. | | Layered diagram includes summary section | The generated layered diagram document must include an Overview section with annotated source file count. | Without summary counts, readers cannot assess diagram completeness or detect missing annotated sources. | +### Load Preamble Parser + +| Rule | Invariant | Rationale | +| ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Headings are parsed into HeadingBlock | Lines starting with 1-6 hash characters followed by a space produce HeadingBlock with the correct level and text. | Headings are the primary structural element in preamble markdown and must map exactly to HeadingBlock level values. | +| Paragraphs are parsed into ParagraphBlock | Consecutive non-empty, non-construct lines produce a single ParagraphBlock with lines joined by spaces. | Multi-line paragraphs in markdown are a single logical block separated by blank lines. | +| Separators are parsed into SeparatorBlock | Lines matching exactly three or more dashes, asterisks, or underscores produce SeparatorBlock. | Horizontal rules serve as visual separators in preamble content and must be faithfully represented. | +| Tables are parsed into TableBlock | A line starting with pipe followed by a separator row produces TableBlock with columns from the header and rows from subsequent pipe-delimited lines. | Tables are heavily used in preamble content for structured reference data and must preserve column names and cell values exactly. | +| Unordered lists are parsed into ListBlock | Lines starting with dash-space or asterisk-space produce ListBlock with ordered=false and string items. | Unordered lists are common in preamble content for enumerating capabilities or constraints. | +| Ordered lists are parsed into ListBlock | Lines starting with a digit followed by period-space produce ListBlock with ordered=true. | Ordered lists represent sequential steps in procedural guides and must preserve ordering semantics. | +| Code blocks are parsed into CodeBlock | Fenced code blocks with a language info string produce CodeBlock with the language and content fields. | Code examples in preamble content must preserve the language annotation for syntax highlighting in generated docs. | +| Mermaid blocks are parsed into MermaidBlock | Code fences with the info string "mermaid" produce MermaidBlock instead of CodeBlock. | Mermaid diagrams have a dedicated SectionBlock type for specialized rendering in generated docs. | +| Mixed content produces correct block sequence | A markdown document with multiple construct types produces blocks in document order with correct types. | Preamble files combine headings, paragraphs, code blocks, and tables in sequence. The parser must handle transitions between all state machine states correctly. | +| Bold and inline formatting is preserved in paragraphs | Inline markdown formatting such as bold, italic, and code spans are preserved as-is in ParagraphBlock text. | The parser produces structural blocks. Inline formatting is the responsibility of the markdown renderer, not the block parser. | + ### Mermaid Relationship Rendering | Rule | Invariant | Rationale | @@ -639,6 +798,41 @@ function transformToMasterDataset(raw: RawDataset): RuntimeMasterDataset; | Patterns without implementations omit the section | The Implementations heading must not appear in pattern documents when no implementing files exist. | Rendering an empty Implementations section misleads readers into thinking implementations were expected but are missing, rather than simply not applicable. | | Implementation references use relative file links | Implementation file links must be relative paths starting from the patterns output directory. | Absolute paths break when documentation is viewed from different locations; relative paths ensure portability. | +### Procedural Guide Codec + +| Rule | Invariant | Rationale | +| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Procedural guides use a dual-source codec | The ProceduralGuideCodec composes auto-generated reference sections (from MasterDataset and taxonomy) with manually-authored procedural content (from preamble `SectionBlock[]`). Auto-generated content covers ~5% of the output (tag reference tables, pattern statistics, session type contract tables extracted from | | +| blocks). The remaining ~95% is editorial preamble: checklists, decision trees, | | Gap analysis found that SESSION-GUIDES.md and ANNOTATION-GUIDE.md content is overwhelmingly procedural and editorial. Attempting to annotate checklists and walkthroughs as source code would produce worse documentation than hand-authoring. The dual-source pattern (proven by CodecDrivenReferenceGeneration, ErrorGuideCodec, and CliRecipeCodec) composes preamble editorial content with auto-generated reference sections. The codec's value is not in generating the procedural content but in providing a single output pipeline that keeps reference tables current while carrying editorial content in a consistent structure. | +| Session workflow checklists derive from annotated Rule: blocks | The SessionGuidesModuleSource spec's Rule: blocks (Rules 3-8) are the canonical source for session workflow invariants. The ProceduralGuideCodec extracts structured tables from these Rule: blocks and renders them as developer-facing checklists at the detailed level. The same Rule: blocks produce compact invariant statements for `_claude-md/workflow/` modules at the summary level. Two audiences (public developers and AI sessions) are served from a single annotated source with different rendering detail levels. The codec does not duplicate or re-derive Rule: block content -- it reads from MasterDataset's behavior extraction views. | SessionGuidesModuleSource already captures session type contracts (Rule 3), planning constraints (Rule 4), design constraints (Rule 5), implementation execution order (Rule 6), FSM error reference (Rule 7), and handoff patterns (Rule 8) as structured tables within Rule: block descriptions. These tables contain the same information as the manual SESSION-GUIDES.md checklists, but in a machine-extractable format. Rendering these as developer-facing checklists eliminates the maintenance burden of keeping the manual file in sync with the spec, while the compact rendering for AI context was already delivered by Phase 39. | +| Annotation guide content remains separate from session guides | The ProceduralGuideCodec produces two separate generated files via two `ReferenceDocConfig` entries: one for session workflow guides (replacing SESSION-GUIDES.md) and one for annotation guides (replacing ANNOTATION-GUIDE.md). The session workflow guide targets workflow practitioners who need to know session type selection, execution order, and FSM error recovery. The annotation guide targets annotation authors who need to know opt-in markers, tag syntax, shape extraction modes, and verification steps. These audiences overlap but have distinct primary needs. The codec class is shared; the config entries and preamble content differ. | SESSION-GUIDES.md and ANNOTATION-GUIDE.md serve different audiences at different points in the development lifecycle. Merging them into a single guide would force annotation authors to navigate session workflow content and vice versa. The existing DocsConsolidationStrategy Phase 5 (Guide trimming) already treats them as separate documents. Using one codec class with two config entries follows the same pattern as `createReferenceCodec` producing multiple documents from different configs. | +| Decision trees render as Mermaid flowcharts | Session type decision trees and annotation workflow decision trees render as Mermaid flowchart diagrams in the detailed output level. The session type decision tree replaces the ASCII art tree in SESSION-GUIDES.md with a Mermaid `graph TD` diagram that renders as an interactive flowchart on the Starlight website. Decision tree content is authored as fenced mermaid code blocks in the markdown source file, parsed into `MermaidBlock` entries by `loadPreambleFromMarkdown()` at config load time. At summary level, decision trees render as compact text tables instead of diagrams. | The manual SESSION-GUIDES.md uses an ASCII art tree for the session decision flow, which renders poorly on the website and cannot be interacted with. Mermaid flowcharts are already supported by the Starlight website (proven by product area docs with C4Context and graph LR diagrams). Converting decision trees to Mermaid provides visual clarity, click-through navigation, and consistent rendering across platforms. The content block type `mermaid` is already one of the 9 supported SectionBlock types (proven by ReferenceDocShowcase). | +| Generated guide supersedes manual only at quality parity | The manual `docs/SESSION-GUIDES.md` is retained in the repository until the generated equivalent matches or exceeds its quality across all content dimensions: completeness (all checklists present), accuracy (all FSM states current), visual clarity (decision trees render correctly), and usability (verified by comparison audit). The SessionGuidesModuleSource invariant ("not deleted, shortened, or replaced with a redirect") is respected during the transition period. The quality comparison deliverable produces an explicit audit document recording which sections have parity and which gaps remain. Only after the audit confirms full parity is the manual file replaced with a pointer to the generated output. | SESSION-GUIDES.md is cited in the SessionGuidesModuleSource spec as "the authoritative public human reference" serving developers on libar.dev. Replacing it prematurely with a generated equivalent that lacks checklists, has formatting issues, or omits edge cases would degrade the developer experience. The quality-gated approach ensures the generated version earns its place as the replacement by demonstrating equivalent or better quality, not merely by existing. This is the same principle applied by DocsConsolidationStrategy: "Manual docs retain editorial and tutorial content" until generation quality is sufficient. | + +### Process Api Hybrid Generation + +| Rule | Invariant | Rationale | +| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| CLI schema is single source of truth for reference tables | A declarative CLI schema in `src/cli/cli-schema.ts` defines all global options, output modifiers, and list filters with their flags, descriptions, defaults, and value types. The three reference tables in `docs-live/reference/PROCESS-API-REFERENCE.md` are generated from this schema by a standalone `ProcessApiReferenceGenerator`. The schema also drives `showHelp()`. | CLI options are defined imperatively in `parseArgs()` (lines 132-265 of `src/cli/process-api.ts`) and `OutputModifiers`/`ListFilters` interfaces (lines 43-83 of `src/cli/output-pipeline.ts`). A declarative schema extracts this into a single structured definition that both documentation and help text consume. The existing `ReferenceDocConfig` system cannot be used because it sources from MasterDataset (annotation-derived data), not static constants (ADR-006). | +| Narrative prose sections remain manual | PROCESS-API.md sections covering "Why Use This", session type decision tree, workflow recipes, worked examples with expected output, and "Common Recipes" are not generated. They require editorial judgment and context that cannot be extracted from code annotations. The document's value comes from these sections — the generated reference tables are supporting material only. | Generated docs without prose context would be a bare options table — usable as reference but not as a learning resource. The hybrid approach gives both: accurate tables from code, readable narrative from editorial work. | +| Standalone generator respects ADR-006 single read model | The `ProcessApiReferenceGenerator` imports CLI schema data directly from `src/cli/cli-schema.ts`. It does NOT inject CLI data into MasterDataset or consume MasterDataset for table generation. It implements `DocumentGenerator` and returns `OutputFile[]` via the standard orchestrator write path. | ADR-006 establishes MasterDataset as the sole read model for annotation-sourced data. CLI schema is a static TypeScript constant, not extracted from annotations. Forcing it through MasterDataset would violate the "no parallel pipeline" anti-pattern. A standalone generator with its own data source is architecturally correct. | + +### Publishing Relocation + +| Rule | Invariant | Rationale | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| All publishing content moves to MAINTAINERS.md intact | MAINTAINERS.md at the repository root contains all 8 H2 sections previously in docs/PUBLISHING.md: Prerequisites, Version Strategy, Publishing Workflow (with Pre-releases, Subsequent Pre-releases, and Stable Releases subsections), Automated Publishing (GitHub Actions), Pre-commit and Pre-push Hooks, Dry Run, Verifying a Published Package, and Troubleshooting. No content is summarized, condensed, or omitted during the move. The H1 title changes from "Publishing Guide" to "Maintainer Guide" to reflect the broader MAINTAINERS.md convention. PUBLISHING.md contains zero relative links to other docs/ files, so no link rewriting is required. | The relocation is a pure audience-alignment fix, not a content review. Condensing content during the move would conflate two concerns. The maintainer procedures are complete and accurate — they simply live in the wrong location. A faithful copy ensures no institutional knowledge is lost in translation. | +| docs/PUBLISHING.md is deleted after relocation | After Phase 40 completes, `docs/PUBLISHING.md` does not exist. The file is not kept as a redirect stub or summary pointer. MAINTAINERS.md at the repo root is the sole location for publishing procedures. | A deleted file cannot serve the wrong audience. Keeping docs/PUBLISHING.md as a stub pointing to MAINTAINERS.md would still deploy a maintainer-only page to the website. The correct fix is deletion, not redirection. Maintainers navigating to the repo root will find MAINTAINERS.md via standard GitHub repository conventions. | +| Cross-references and website manifest are updated | After Phase 40 completes, docs/INDEX.md contains zero references to PUBLISHING.md. The 3 locations that previously referenced it are removed: the Quick Navigation table row (line 32), the Detailed Table of Contents subsection (lines 260-272), and the Document Roles Summary row (line 338). The website content manifest no longer includes PUBLISHING.md in the guides array. A link rewrite entry maps "./PUBLISHING.md" to the GitHub blob URL for MAINTAINERS.md so any remaining cross-references in other docs resolve correctly after website deployment. | Deleting a file without updating its references creates broken links in both the docs/ index and the website. The INDEX.md references are removed entirely (not redirected) because the content is no longer in the docs/ directory. The website manifest removal prevents a dead sync target. The link rewrite handles any generated docs that reference PUBLISHING.md — they will link to the GitHub-hosted MAINTAINERS.md instead of a 404. | + +### Readme Rationalization + +| Rule | Invariant | Rationale | +| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| README must be an npm package landing page | README.md content is scoped to what an npm package consumer needs: title and badges, one-paragraph value proposition, install instructions, quick start (annotate, generate, enforce), one annotated code example, content block summary table, CLI command table, and documentation index. | npm package pages are scanned by developers evaluating installation decisions. Content above 150-200 lines increases time-to-value. Enterprise pitch content (benchmark tables, methodology comparisons, session workflows, relationship models, comparison matrices) is not actionable at install time and belongs on the project website where it receives proper formatting, navigation, and updates without coupling to the package release cycle. The libar.dev website already contains 9 landing page components covering all enterprise pitch content: Metrics.astro (Proven at Scale), Pillars.astro (FSM, dual-source, relationships, codecs), DataAPI.astro (Data API CLI), Workflows.astro (session types), CodeExamples.astro (annotation examples), and Pipeline.astro (four-stage pipeline). | +| Configuration reference must not be duplicated in README | docs/CONFIGURATION.md is the single source of truth for preset and tag configuration. | README.md lines 441-474 reproduce the exact same preset table and config code examples that appear in docs/CONFIGURATION.md. Duplicate reference content diverges over time -- when a new preset is added, both files require updates. Removing the README copy and pointing to CONFIGURATION.md eliminates the divergence risk and removes approximately 34 lines from the README with no loss of information. | +| Trimmed README must serve as an effective getting-started page | The website publishes README.md as /delivery-process/getting-started/ via content-manifest.mjs (line 57). After trimming, the remaining content must serve a first-time visitor arriving at that URL: install instructions, a quick annotated code example, CLI commands to run, and navigation links to deeper documentation. | The current 504-line README is a poor getting-started page because the install command is buried after 50+ lines of marketing content. The trimmed 150-line version places install instructions within the first 20 lines and follows with practical steps -- this is a better getting-started experience than the current version. No manifest changes are needed; the trim improves alignment with the URL. | + ### Reference Codec Core Testing | Rule | Invariant | Rationale | @@ -669,6 +863,7 @@ function transformToMasterDataset(raw: RawDataset): RuntimeMasterDataset; | Rule | Invariant | Rationale | | ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Scoped diagrams are generated from diagramScope config | Diagram content is determined exclusively by diagramScope filters (archContext, include, archLayer, patterns), and filters compose via OR — a pattern matching any single filter appears in the diagram. | Without filter-driven scoping, diagrams would include all patterns regardless of relevance, producing unreadable visualizations that obscure architectural boundaries. | +| Hardcoded diagram sources render deterministic output | Hardcoded diagram sources render without relationship-scoping input and emit stable, source-specific Mermaid content. | Domain diagrams such as pipeline and MasterDataset fan-out encode canonical architecture views that should not depend on ad-hoc test dataset shape. | | Multiple diagram scopes produce multiple mermaid blocks | Each entry in the diagramScopes array produces an independent Mermaid block with its own title and direction, and legacy singular diagramScope remains supported as a fallback. | Product areas require multiple architectural views (e.g., system overview and data flow) from a single configuration, and breaking backward compatibility with the singular diagramScope would silently remove diagrams from existing consumers. | ### Reference Codec Diagram Type Testing @@ -799,6 +994,20 @@ function transformToMasterDataset(raw: RawDataset): RuntimeMasterDataset; | SessionContextCodec provides working context for AI sessions | Session context must include session status with active/completed/remaining counts, phase navigation for incomplete phases, and active work grouped by phase. | AI agents need a compact, navigable view of current project state to make informed implementation decisions. | | RemainingWorkCodec aggregates incomplete work by phase | Remaining work must show status counts, phase-grouped navigation, priority classification (in-progress/ready/blocked), and next actionable items. | Remaining work visibility prevents scope blindness — knowing what's left, what's blocked, and what's ready drives efficient session planning. | +### Session Guides Module Source + +| Rule | Invariant | Rationale | +| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| SESSION-GUIDES.md is the authoritative public human reference | `docs/SESSION-GUIDES.md` exists and is not deleted, shortened, or replaced with a redirect. Its comprehensive checklists, CLI command examples, and session decision trees serve developers on libar.dev. | Session workflow guidance requires two formats for two audiences. Public developers need comprehensive checklists with full examples. AI sessions need compact invariants they can apply without reading 389 lines. | +| CLAUDE.md session workflow content is derived, not hand-authored | After Phase 39 generation deliverables complete, the "Session Workflows" section in CLAUDE.md contains no manually-authored content. It is composed from generated `_claude-md/workflow/` modules. | A hand-maintained CLAUDE.md session section creates two copies of session workflow guidance with no synchronization mechanism. Regeneration from annotated source eliminates drift. | +| Session type determines artifacts and FSM changes | Four session types exist, each with defined input, output, and FSM impact. Mixing outputs across session types (e.g., writing code in a planning session) violates session discipline. | Session type confusion causes wasted work — a design mistake discovered mid-implementation wastes the entire session. Clear contracts prevent scope bleeding between session types. | +| Planning sessions produce roadmap specs only | A planning session creates a roadmap spec with metadata, deliverables table, Rule: blocks with invariants, and scenarios. It must not produce implementation code, transition to active, or prompt for implementation readiness. | Planning is the cheapest session type — it produces .feature file edits, no compilation needed. Mixing implementation into planning defeats the cost advantage and introduces untested code without a locked scope. | +| Design sessions produce decisions and stubs only | A design session makes architectural decisions and creates code stubs with interfaces. It must not produce implementation code. Context gathering via the Process Data API must precede any explore agent usage. | Design sessions resolve ambiguity before implementation begins. Code stubs in delivery-process/stubs/ live outside src/ to avoid TypeScript compilation and ESLint issues, making them zero-risk artifacts. | +| Implementation sessions follow FSM-enforced execution order | Implementation sessions must follow a strict 5-step execution order. Transition to active must happen before any code changes. Transition to completed must happen only when ALL deliverables are done. Skipping steps causes Process Guard rejection at commit time. | The execution order ensures FSM state accurately reflects work state at every point. Writing code before transitioning to active means Process Guard sees changes to a roadmap spec (no scope protection). Marking completed with incomplete work creates a hard-locked state that requires unlock-reason to fix. | +| FSM errors have documented fixes | Every Process Guard error code has a defined cause and fix. The error codes, causes, and fixes form a closed set — no undocumented error states exist. | Undocumented FSM errors cause session-blocking confusion. A lookup table from error code to fix eliminates guesswork and prevents workarounds that bypass process integrity. | +| Handoff captures session-end state for continuity | Multi-session work requires handoff documentation generated from the Process Data API. Handoff output always reflects actual annotation state, not manual notes. | Manual session notes drift from actual deliverable state. The handoff command derives state from annotations, ensuring the next session starts from ground truth rather than stale notes. | +| ClaudeModuleGeneration is the generation mechanism | Phase 39 depends on ClaudeModuleGeneration (Phase 25). Adding `@libar-docs-claude-module` and `@libar-docs-claude-section:workflow` tags to this spec will cause ClaudeModuleGeneration to produce `_claude-md/workflow/` output files. The hand-written `_claude-md/workflow/` files are deleted after successful verified generation. | The annotation work (Rule blocks in this spec) is immediately useful — queryable via `pnpm process:query -- rules`. Generation deliverables cannot complete until Phase 25 ships the ClaudeModuleCodec. This sequencing is intentional: the annotation investment has standalone value regardless of whether the codec exists yet. | + ### Shape Matcher Testing | Rule | Invariant | Rationale | diff --git a/docs-live/product-areas/PROCESS.md b/docs-live/product-areas/PROCESS.md index 31a8a733..3b54cb68 100644 --- a/docs-live/product-areas/PROCESS.md +++ b/docs-live/product-areas/PROCESS.md @@ -16,6 +16,24 @@ --- +## Contents + +- [Key Invariants](#key-invariants) +- [Product area canonical values](#product-area-canonical-values) +- [ADR category canonical values](#adr-category-canonical-values) +- [FSM status values and protection levels](#fsm-status-values-and-protection-levels) +- [Valid FSM transitions](#valid-fsm-transitions) +- [Tag format types](#tag-format-types) +- [Source ownership](#source-ownership) +- [Quarter format convention](#quarter-format-convention) +- [Canonical phase definitions (6-phase USDP standard)](#canonical-phase-definitions-6-phase-usdp-standard) +- [Deliverable status canonical values](#deliverable-status-canonical-values) +- [Delivery Lifecycle FSM](#delivery-lifecycle-fsm) +- [Process Pattern Relationships](#process-pattern-relationships) +- [Business Rules](#business-rules) + +--- + ## Product area canonical values **Invariant:** The product-area tag uses one of 7 canonical values. Each value represents a reader-facing documentation section, not a source module. @@ -32,6 +50,8 @@ | CoreTypes | What foundational types exist? | Result monad, error factories, string utils | | Process | How does the session workflow work? | Session lifecycle, handoffs, conventions | +**Verified by:** Canonical values are enforced + --- ## ADR category canonical values @@ -47,6 +67,8 @@ | testing | Test strategy, verification approach | | documentation | Documentation generation, content structure | +**Verified by:** Canonical values are enforced + --- ## FSM status values and protection levels @@ -62,13 +84,15 @@ | completed | Hard-locked | No | Requires unlock-reason tag | | deferred | None | Yes | Full editing | +**Verified by:** Canonical values are enforced + --- ## Valid FSM transitions **Invariant:** Only these transitions are valid. All others are rejected by Process Guard. -**Rationale:** Allowing arbitrary transitions (e.g., roadmap to completed) bypasses the active phase where scope-lock and deliverable tracking provide quality assurance. Completed is a terminal state. Modifications require `@libar-docs-unlock-reason` escape hatch. +**Rationale:** Allowing arbitrary transitions (e.g., roadmap to completed) bypasses the active phase where scope-lock and deliverable tracking provide quality assurance. | From | To | Trigger | | -------- | --------- | --------------------- | @@ -78,6 +102,11 @@ | active | roadmap | Blocked/regressed | | deferred | roadmap | Resume planning | +**Verified by:** Canonical values are enforced + + Completed is a terminal state. Modifications require + `@libar-docs-unlock-reason` escape hatch. + --- ## Tag format types @@ -95,6 +124,8 @@ | number | Numeric value | @libar-docs-phase 15 | | quoted-value | Preserves spaces | @libar-docs-brief:'Multi word' | +**Verified by:** Canonical values are enforced + --- ## Source ownership @@ -110,6 +141,8 @@ | quarter | Feature files | TypeScript | Gherkin owns timeline metadata | | team | Feature files | TypeScript | Gherkin owns ownership metadata | +**Verified by:** Canonical values are enforced + --- ## Quarter format convention @@ -118,6 +151,8 @@ **Rationale:** Non-standard formats (e.g., Q1-2026) break lexicographic sorting, which roadmap generation and timeline queries depend on for correct ordering. +**Verified by:** Canonical values are enforced + --- ## Canonical phase definitions (6-phase USDP standard) @@ -135,6 +170,8 @@ | 5 | Validation | Verification, acceptance criteria confirmation | | 6 | Retrospective | Review, lessons learned, documentation | +**Verified by:** Canonical values are enforced + --- ## Deliverable status canonical values @@ -152,6 +189,8 @@ | superseded | Replaced by another | | n/a | Not applicable | +**Verified by:** Canonical values are enforced + --- ## Delivery Lifecycle FSM @@ -190,6 +229,10 @@ Scoped architecture diagram showing component relationships: ```mermaid graph LR + ADR006SingleReadModelArchitecture["ADR006SingleReadModelArchitecture"] + ADR003SourceFirstPatternArchitecture["ADR003SourceFirstPatternArchitecture"] + ADR002GherkinOnlyTesting["ADR002GherkinOnlyTesting"] + ADR001TaxonomyCanonicalValues["ADR001TaxonomyCanonicalValues"] ValidatorReadModelConsolidation["ValidatorReadModelConsolidation"] StepDefinitionCompletion["StepDefinitionCompletion"] SessionFileCleanup["SessionFileCleanup"] @@ -200,14 +243,12 @@ graph LR EffortVarianceTracking["EffortVarianceTracking"] ConfigBasedWorkflowDefinition["ConfigBasedWorkflowDefinition"] CliBehaviorTesting["CliBehaviorTesting"] - ADR006SingleReadModelArchitecture["ADR006SingleReadModelArchitecture"] - ADR003SourceFirstPatternArchitecture["ADR003SourceFirstPatternArchitecture"] - ADR002GherkinOnlyTesting["ADR002GherkinOnlyTesting"] - ADR001TaxonomyCanonicalValues["ADR001TaxonomyCanonicalValues"] SessionFileLifecycle["SessionFileLifecycle"] subgraph related["Related"] ADR005CodecBasedMarkdownRendering["ADR005CodecBasedMarkdownRendering"]:::neighbor end + ADR006SingleReadModelArchitecture -.->|depends on| ADR005CodecBasedMarkdownRendering + ADR003SourceFirstPatternArchitecture -.->|depends on| ADR001TaxonomyCanonicalValues ValidatorReadModelConsolidation -.->|depends on| ADR006SingleReadModelArchitecture StepDefinitionCompletion -.->|depends on| ADR002GherkinOnlyTesting SessionFileCleanup -.->|depends on| SessionFileLifecycle @@ -217,8 +258,6 @@ graph LR EffortVarianceTracking -.->|depends on| MvpWorkflowImplementation ConfigBasedWorkflowDefinition -.->|depends on| MvpWorkflowImplementation CliBehaviorTesting -.->|depends on| ADR002GherkinOnlyTesting - ADR006SingleReadModelArchitecture -.->|depends on| ADR005CodecBasedMarkdownRendering - ADR003SourceFirstPatternArchitecture -.->|depends on| ADR001TaxonomyCanonicalValues classDef neighbor stroke-dasharray: 5 5 ``` @@ -230,17 +269,17 @@ graph LR ### ADR 001 Taxonomy Canonical Values -| Rule | Invariant | Rationale | -| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Product area canonical values | The product-area tag uses one of 7 canonical values. Each value represents a reader-facing documentation section, not a source module. | Without canonical values, organic drift (e.g., Generator vs Generators) produces inconsistent grouping in generated documentation and fragmented product area pages. | -| ADR category canonical values | The adr-category tag uses one of 4 values. | Unbounded category values prevent meaningful grouping of architecture decisions and make cross-cutting queries unreliable. | -| FSM status values and protection levels | Pattern status uses exactly 4 values with defined protection levels. These are enforced by Process Guard at commit time. | Without protection levels, active specs accumulate scope creep and completed specs get silently modified, undermining delivery process integrity. | -| Valid FSM transitions | Only these transitions are valid. All others are rejected by Process Guard. | Allowing arbitrary transitions (e.g., roadmap to completed) bypasses the active phase where scope-lock and deliverable tracking provide quality assurance. Completed is a terminal state. Modifications require `@libar-docs-unlock-reason` escape hatch. | -| Tag format types | Every tag has one of 6 format types that determines how its value is parsed. | Without explicit format types, parsers must guess value structure, leading to silent data corruption when CSV values are treated as single strings or numbers are treated as text. | -| Source ownership | Relationship tags have defined ownership by source type. Anti-pattern detection enforces these boundaries. | Cross-domain tag placement (e.g., runtime dependencies in Gherkin) creates conflicting sources of truth and breaks the dual-source architecture ownership model. | -| Quarter format convention | The quarter tag uses `YYYY-QN` format (e.g., `2026-Q1`). ISO-year-first sorting works lexicographically. | Non-standard formats (e.g., Q1-2026) break lexicographic sorting, which roadmap generation and timeline queries depend on for correct ordering. | -| Canonical phase definitions (6-phase USDP standard) | The default workflow defines exactly 6 phases in fixed order. These are the canonical phase names and ordinals used by all generated documentation. | Ad-hoc phase names and ordering produce inconsistent roadmap grouping across packages and make cross-package progress tracking impossible. | -| Deliverable status canonical values | Deliverable status (distinct from pattern FSM status) uses exactly 6 values, enforced by Zod schema at parse time. | Freeform status strings bypass Zod validation and break DoD checks, which rely on terminal status classification to determine pattern completeness. | +| Rule | Invariant | Rationale | +| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Product area canonical values | The product-area tag uses one of 7 canonical values. Each value represents a reader-facing documentation section, not a source module. | Without canonical values, organic drift (e.g., Generator vs Generators) produces inconsistent grouping in generated documentation and fragmented product area pages. | +| ADR category canonical values | The adr-category tag uses one of 4 values. | Unbounded category values prevent meaningful grouping of architecture decisions and make cross-cutting queries unreliable. | +| FSM status values and protection levels | Pattern status uses exactly 4 values with defined protection levels. These are enforced by Process Guard at commit time. | Without protection levels, active specs accumulate scope creep and completed specs get silently modified, undermining delivery process integrity. | +| Valid FSM transitions | Only these transitions are valid. All others are rejected by Process Guard. | Allowing arbitrary transitions (e.g., roadmap to completed) bypasses the active phase where scope-lock and deliverable tracking provide quality assurance. | +| Tag format types | Every tag has one of 6 format types that determines how its value is parsed. | Without explicit format types, parsers must guess value structure, leading to silent data corruption when CSV values are treated as single strings or numbers are treated as text. | +| Source ownership | Relationship tags have defined ownership by source type. Anti-pattern detection enforces these boundaries. | Cross-domain tag placement (e.g., runtime dependencies in Gherkin) creates conflicting sources of truth and breaks the dual-source architecture ownership model. | +| Quarter format convention | The quarter tag uses `YYYY-QN` format (e.g., `2026-Q1`). ISO-year-first sorting works lexicographically. | Non-standard formats (e.g., Q1-2026) break lexicographic sorting, which roadmap generation and timeline queries depend on for correct ordering. | +| Canonical phase definitions (6-phase USDP standard) | The default workflow defines exactly 6 phases in fixed order. These are the canonical phase names and ordinals used by all generated documentation. | Ad-hoc phase names and ordering produce inconsistent roadmap grouping across packages and make cross-package progress tracking impossible. | +| Deliverable status canonical values | Deliverable status (distinct from pattern FSM status) uses exactly 6 values, enforced by Zod schema at parse time. | Freeform status strings bypass Zod validation and break DoD checks, which rely on terminal status classification to determine pattern completeness. | ### ADR 002 Gherkin Only Testing @@ -270,10 +309,10 @@ graph LR ### Mvp Workflow Implementation -| Rule | Invariant | Rationale | -| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| PDR-005 status values are recognized | The scanner and validation schemas must accept exactly the four PDR-005 status values: roadmap, active, completed, deferred. | Unrecognized status values silently drop patterns from generated documents, causing missing documentation across the entire monorepo. | -| Generators map statuses to documents | Each status value must route to exactly one target document: roadmap/deferred to ROADMAP.md, active to CURRENT-WORK.md, completed to CHANGELOG. | Incorrect status-to-document mapping causes patterns to appear in the wrong document or be omitted entirely, breaking the project overview for all consumers. | +| Rule | Invariant | Rationale | +| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| PDR-005 status values are recognized | The scanner and validation schemas must accept exactly the four PDR-005 status values: roadmap, active, completed, deferred. | Unrecognized status values silently drop patterns from generated documents, causing missing documentation across the entire monorepo. | +| Generators map statuses to documents | Each status value must route to exactly one target document: roadmap/deferred to ROADMAP.md, active to CURRENT-WORK.md, completed to CHANGELOG-GENERATED.md. | Incorrect status-to-document mapping causes patterns to appear in the wrong document or be omitted entirely, breaking the project overview for all consumers. | ### Session File Cleanup diff --git a/docs-live/product-areas/VALIDATION.md b/docs-live/product-areas/VALIDATION.md index cb1f984b..51226c6d 100644 --- a/docs-live/product-areas/VALIDATION.md +++ b/docs-live/product-areas/VALIDATION.md @@ -16,6 +16,16 @@ --- +## Contents + +- [Key Invariants](#key-invariants) +- [Validation & Lint Boundary](#validation-lint-boundary) +- [Enforcement Pipeline](#enforcement-pipeline) +- [API Types](#api-types) +- [Business Rules](#business-rules) + +--- + ## Validation & Lint Boundary Scoped architecture diagram showing component relationships: @@ -1010,15 +1020,15 @@ const missingStatus: LintRule; ### Process Guard Linter -| Rule | Invariant | Rationale | -| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Protection levels determine modification restrictions | Every file's modification restrictions are determined solely by its `@libar-docs-status` tag, with `completed` requiring an explicit unlock reason for any change. | Without status-derived protection, completed and approved work can be silently overwritten by bulk edits or accidental modifications. Files inherit protection from their `@libar-docs-status` tag. Higher protection levels require explicit unlock to modify. | -| Session definition files scope what can be modified | When an active session exists, only specs explicitly listed in the session definition may be modified without warning, and excluded specs cannot be modified at all. | Without session scoping, bulk operations and context switches cause unintended modifications to specs outside the current work focus. Optional session files (`delivery-process/sessions/*.feature`) explicitly declare which specs are in-scope for modification during a work session. If active, modifications outside scope trigger warnings or errors. | -| Status transitions follow PDR-005 FSM | Every status change must follow a valid edge in the PDR-005 finite state machine; no transition may skip intermediate states. | Skipping states (e.g., `roadmap` directly to `completed`) bypasses scope-locking and review gates, allowing incomplete work to be marked as done. Status changes in a file must follow a valid transition per PDR-005. This extends phase-state-machine.feature to the linter context. | -| Active specs cannot add new deliverables | The deliverables table of an `active` spec is immutable with respect to new rows; only existing deliverable statuses may change. | Adding deliverables after work has begun constitutes scope creep, undermining effort estimates and blocking completion. Once a spec transitions to `active`, its deliverables table is considered scope-locked. Adding new rows indicates scope creep. | -| CLI provides flexible validation modes | The CLI must support both pre-commit (staged-only) and CI (all-files) validation modes with deterministic exit codes reflecting violation severity. | Without flexible modes, teams cannot integrate process guard into both local developer workflows and CI pipelines with appropriate strictness levels. | -| Integrates with existing lint infrastructure | Process guard output format and exit code semantics must be consistent with the existing `lint-patterns` tool. | Inconsistent output formats force consumers to maintain separate parsers, and inconsistent exit codes break combined lint pipelines. | -| New tags support process guard functionality | Session and protection tags must be registered in the TypeScript taxonomy with defined formats before use in feature files. | Unregistered tags bypass schema validation and are silently ignored by the scanner, causing process guard rules to fail without diagnostics. The following tags are defined in the TypeScript taxonomy to support process guard: | +| Rule | Invariant | Rationale | +| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| Protection levels determine modification restrictions | Every file's modification restrictions are determined solely by its `@libar-docs-status` tag, with `completed` requiring an explicit unlock reason for any change. | Without status-derived protection, completed and approved work can be silently overwritten by bulk edits or accidental modifications. | +| Session definition files scope what can be modified | When an active session exists, only specs explicitly listed in the session definition may be modified without warning, and excluded specs cannot be modified at all. | Without session scoping, bulk operations and context switches cause unintended modifications to specs outside the current work focus. | +| Status transitions follow PDR-005 FSM | Every status change must follow a valid edge in the PDR-005 finite state machine; no transition may skip intermediate states. | Skipping states (e.g., `roadmap` directly to `completed`) bypasses scope-locking and review gates, allowing incomplete work to be marked as done. | +| Active specs cannot add new deliverables | The deliverables table of an `active` spec is immutable with respect to new rows; only existing deliverable statuses may change. | Adding deliverables after work has begun constitutes scope creep, undermining effort estimates and blocking completion. | +| CLI provides flexible validation modes | The CLI must support both pre-commit (staged-only) and CI (all-files) validation modes with deterministic exit codes reflecting violation severity. | Without flexible modes, teams cannot integrate process guard into both local developer workflows and CI pipelines with appropriate strictness levels. | +| Integrates with existing lint infrastructure | Process guard output format and exit code semantics must be consistent with the existing `lint-patterns` tool. | Inconsistent output formats force consumers to maintain separate parsers, and inconsistent exit codes break combined lint pipelines. | +| New tags support process guard functionality | Session and protection tags must be registered in the TypeScript taxonomy with defined formats before use in feature files. | Unregistered tags bypass schema validation and are silently ignored by the scanner, causing process guard rules to fail without diagnostics. | ### Process Guard Testing diff --git a/docs-live/reference/ANNOTATION-REFERENCE.md b/docs-live/reference/ANNOTATION-REFERENCE.md new file mode 100644 index 00000000..19e6f164 --- /dev/null +++ b/docs-live/reference/ANNOTATION-REFERENCE.md @@ -0,0 +1,146 @@ +# Annotation Reference Guide + +**Purpose:** Reference document: Annotation Reference Guide +**Detail Level:** Full reference + +--- + +## Getting Started + +Every file that participates in the annotation system must have a `@libar-docs` opt-in marker. Files without this marker are invisible to the scanner. + +### File-Level Opt-In + +**TypeScript** -- file-level JSDoc block: + +```typescript +/** + * @libar-docs + * @libar-docs-pattern MyPattern + * @libar-docs-status roadmap + * @libar-docs-uses EventStore, CommandBus + * + * ## My Pattern - Description + */ +``` + +**Gherkin** -- file-level tags before `Feature:`: + +```gherkin +@libar-docs +@libar-docs-pattern:MyPattern +@libar-docs-status:roadmap +@libar-docs-phase:14 +Feature: My Pattern + + **Problem:** + Description of the problem. +``` + +### Tag Prefix by Preset + +| Preset | Prefix | Categories | Use Case | +| ------------------------- | -------------- | ---------- | ----------------------------- | +| `libar-generic` (default) | `@libar-docs-` | 3 | Simple projects | +| `ddd-es-cqrs` | `@libar-docs-` | 21 | DDD/Event Sourcing monorepos | +| `generic` | `@docs-` | 3 | Simple projects, short prefix | + +### Dual-Source Ownership + +| Source | Owns | Example Tags | +| -------------- | ----------------------------------------------- | -------------------------------------------- | +| **TypeScript** | Implementation: runtime deps, category, shapes | `uses`, `used-by`, `extract-shapes`, `shape` | +| **Gherkin** | Planning: status, phase, timeline, dependencies | `status`, `phase`, `depends-on`, `quarter` | + +--- + +## Shape Extraction + +Shape extraction pulls TypeScript type definitions (interfaces, type aliases, enums, functions, consts) into generated documentation. There are three modes: + +### Mode 1: File-Level Explicit Names + +List specific declaration names in the file-level JSDoc: + +```typescript +/** + * @libar-docs + * @libar-docs-extract-shapes MasterDatasetSchema, StatusGroupsSchema + */ +``` + +Names appear in the generated output in the order listed. + +### Mode 2: File-Level Wildcard + +```typescript +/** + * @libar-docs + * @libar-docs-extract-shapes * + */ +``` + +Wildcard must be the sole value -- `*, Foo` is invalid. + +### Mode 3: Declaration-Level Tagging + +Tag individual declarations with `@libar-docs-shape`, optionally with a group name: + +```typescript +/** @libar-docs-shape api-types */ +export interface CommandInput { + readonly aggregateId: string; + readonly payload: unknown; +} +``` + +The optional group name (`api-types`) enables filtering in diagram scopes and product area documents via `@libar-docs-include`. + +--- + +## Critical Gotcha: Zod Schemas + +For Zod files, extract the **schema constant** (with `Schema` suffix), not the inferred type alias: + +| Wrong (type alias) | Correct (schema constant) | +| ---------------------------------------- | ----------------------------------------- | +| `@extract-shapes MasterDataset` | `@extract-shapes MasterDatasetSchema` | +| Shows: `z.infer` (unhelpful) | Shows: `z.object({...})` (full structure) | + +--- + +## Verification + +### CLI Commands + +```bash +# Tag usage inventory (counts per tag and value) +pnpm process:query -- tags + +# Find files missing @libar-docs opt-in marker +pnpm process:query -- unannotated --path src/types + +# File inventory by type (TS, Gherkin, Stubs) +pnpm process:query -- sources + +# Full pattern JSON including extractedShapes +pnpm process:query -- query getPattern MyPattern + +# Generate complete tag reference +npx generate-tag-taxonomy -o TAG_TAXONOMY.md -f +``` + +--- + +## Common Issues + +| Symptom | Cause | Fix | +| ------------------------------- | ----------------------------------- | ------------------------------------------------ | +| Pattern not in scanner output | Missing `@libar-docs` opt-in marker | Add file-level `@libar-docs` JSDoc/tag | +| Shape shows `z.infer<>` wrapper | Extracted type alias, not schema | Use schema constant name (e.g., `FooSchema`) | +| Shape not in product area doc | Missing `@libar-docs-product-area` | Add product-area tag to file-level annotation | +| Declaration-level shape missing | No `@libar-docs-shape` on decl | Add `@libar-docs-shape` JSDoc to the declaration | +| Tag value rejected | Wrong format or invalid enum value | Check format type in taxonomy reference | +| Anti-pattern validation error | Tag on wrong source type | Move tag to correct source (TS vs Gherkin) | + +--- diff --git a/docs-live/reference/ARCHITECTURE-CODECS.md b/docs-live/reference/ARCHITECTURE-CODECS.md new file mode 100644 index 00000000..bf17cad6 --- /dev/null +++ b/docs-live/reference/ARCHITECTURE-CODECS.md @@ -0,0 +1,656 @@ +# Available Codecs Reference + +**Purpose:** Reference document: Available Codecs Reference +**Detail Level:** Full reference + +--- + +## ValidationRulesCodec + +Transforms MasterDataset into a RenderableDocument for Process Guard validation +rules reference. Generates VALIDATION-RULES.md and detail files (validation/\*.md). + +**Purpose:** Process Guard validation rules reference with FSM diagrams and protection level matrix. + +**Output Files:** `VALIDATION-RULES.md` (main reference), `validation/.md` (category details) + +### When to Use + +- When generating validation rules reference documentation +- When creating FSM state transition diagrams +- When building protection level reference files + +### Factory Pattern + +Use `createValidationRulesCodec(options)` to create a configured codec: + +Or use the default export for standard behavior: + +| Option | Type | Default | Description | +| ----------------------- | ------- | ------- | --------------------------------------------------- | +| includeFSMDiagram | boolean | true | Include FSM state diagram | +| includeCLIUsage | boolean | true | Include CLI usage section | +| includeEscapeHatches | boolean | true | Include escape hatches section | +| includeProtectionMatrix | boolean | true | Include protection levels matrix | +| includeErrorGuide | boolean | true | Include error guide with rationale and alternatives | + +```typescript +const codec = createValidationRulesCodec({ includeFSMDiagram: false }); +const doc = codec.decode(dataset); +``` + +```typescript +const doc = ValidationRulesCodec.decode(dataset); +``` + +--- + +## RoadmapDocumentCodec + +**Purpose:** Development roadmap organized by phase with progress tracking. + +**Output Files:** `ROADMAP.md` (main roadmap), `phases/phase--.md` (phase details) + +| Option | Type | Default | Description | +| ------------------- | ------------------------ | ------- | ----------------------------------- | +| generateDetailFiles | boolean | true | Create phase detail files | +| filterStatus | NormalizedStatusFilter[] | [] | Filter by status | +| includeProcess | boolean | true | Show quarter, effort, team metadata | +| includeDeliverables | boolean | true | List deliverables per phase | +| filterPhases | number[] | [] | Filter to specific phases | + +--- + +## CompletedMilestonesCodec + +**Purpose:** Historical record of completed work organized by quarter. + +**Output Files:** `COMPLETED-MILESTONES.md` (summary), `milestones/.md` (quarter details) + +### When to Use + +- When documenting project history and completed phases +- When generating quarterly achievement summaries +- When tracking velocity by quarter + +--- + +## CurrentWorkCodec + +**Purpose:** Active development work currently in progress. + +**Output Files:** `CURRENT-WORK.md` (summary), `current/phase--.md` (active phase details) + +### When to Use + +- When monitoring active development across all in-progress phases +- When generating sprint/session status dashboards +- When checking which patterns are currently being worked on + +--- + +## TaxonomyDocumentCodec + +Transforms MasterDataset into a RenderableDocument for taxonomy reference output. +Generates TAXONOMY.md and detail files (taxonomy/\*.md). + +**Purpose:** Taxonomy reference documentation with tag definitions, preset comparison, and format type reference. + +**Output Files:** `TAXONOMY.md` (main reference), `taxonomy/.md` (domain details) + +### When to Use + +- When generating the taxonomy reference documentation (TAXONOMY.md) +- When creating tag reference files for progressive disclosure +- When building taxonomy overview reports + +### Factory Pattern + +Use `createTaxonomyCodec(options)` to create a configured codec: + +Or use the default export for standard behavior: + +| Option | Type | Default | Description | +| ------------------ | ------- | ------- | ------------------------------- | +| includePresets | boolean | true | Include preset comparison table | +| includeFormatTypes | boolean | true | Include format type reference | +| includeArchDiagram | boolean | true | Include architecture diagram | +| groupByDomain | boolean | true | Group metadata tags by domain | + +```typescript +const codec = createTaxonomyCodec({ generateDetailFiles: false }); +const doc = codec.decode(dataset); +``` + +```typescript +const doc = TaxonomyDocumentCodec.decode(dataset); +``` + +--- + +## SessionContextCodec + +**Purpose:** Current session context for AI agents and developers. + +**Output Files:** `SESSION-CONTEXT.md` (session status), `sessions/phase--.md` (incomplete phase details) + +### When to Use + +- When starting a new implementation session and need to see active work status +- When generating compact context for AI agent consumption (\_claude-md/ output) +- When checking incomplete phases and their deliverable progress + +--- + +## RemainingWorkCodec + +**Purpose:** Aggregate view of all incomplete work across phases. + +**Output Files:** `REMAINING-WORK.md` (summary), `remaining/phase--.md` (phase details) + +| Option | Type | Default | Description | +| --------------------- | ---------------------------------------------- | ------- | ----------------------------- | +| includeIncomplete | boolean | true | Include planned items | +| includeBlocked | boolean | true | Show blocked items analysis | +| includeNextActionable | boolean | true | Next actionable items section | +| maxNextActionable | number | 5 | Max items in next actionable | +| sortBy | "phase" \| "priority" \| "effort" \| "quarter" | "phase" | Sort order | +| groupPlannedBy | "quarter" \| "priority" \| "level" \| "none" | "none" | Group planned items | + +--- + +## RequirementsDocumentCodec + +Transforms MasterDataset into RenderableDocument for PRD/requirements output. +Generates PRODUCT-REQUIREMENTS.md and detail files (requirements/\*.md). + +**Purpose:** Product requirements documentation grouped by product area or user role. + +**Output Files:** `PRODUCT-REQUIREMENTS.md` (main index), `requirements/.md` (area details) + +### When to Use + +- When generating product requirements documentation +- When creating stakeholder-facing PRD documents +- When organizing requirements by user role or product area + +### Factory Pattern + +Use `createRequirementsCodec(options)` for custom options: + +| Option | Type | Default | Description | +| -------------------- | ---------------------------------------- | -------------- | -------------------------------- | +| generateDetailFiles | boolean | true | Create product area detail files | +| groupBy | "product-area" \| "user-role" \| "phase" | "product-area" | Primary grouping | +| filterStatus | NormalizedStatusFilter[] | [] | Filter by status (empty = all) | +| includeScenarioSteps | boolean | true | Show Given/When/Then steps | +| includeBusinessValue | boolean | true | Display business value metadata | +| includeBusinessRules | boolean | true | Show Gherkin Rule: sections | + +```typescript +const codec = createRequirementsCodec({ groupBy: 'user-role' }); +const doc = codec.decode(dataset); +``` + +--- + +## ChangelogCodec + +**Purpose:** Keep a Changelog format changelog grouped by release version. + +**Output Files:** `CHANGELOG.md` + +| Option | Type | Default | Description | +| ----------------- | ---------------------- | ------- | --------------------------------- | +| includeUnreleased | boolean | true | Include unreleased section | +| includeLinks | boolean | true | Include links | +| categoryMapping | Record | {} | Map categories to changelog types | + +--- + +## TraceabilityCodec + +**Purpose:** Timeline to behavior file coverage report. + +**Output Files:** `TRACEABILITY.md` + +### When to Use + +- When auditing which timeline patterns have associated behavior specifications +- When checking feature file coverage across roadmap phases +- When identifying patterns missing executable specs + +--- + +## OverviewCodec + +**Purpose:** Project architecture and status overview. + +**Output Files:** `OVERVIEW.md` + +### When to Use + +- When generating a high-level project dashboard with architecture summary +- When providing stakeholder-facing status reports +- When combining completion stats with architecture context + +--- + +## ReferenceDocumentCodec + +A single codec factory that creates reference document codecs from +configuration objects. Convention content is sourced from +decision records tagged with @libar-docs-convention. + +**Purpose:** Scoped reference documentation assembling four content layers (conventions, diagrams, shapes, behaviors) into a single document. + +**Output Files:** Configured per-instance (e.g., `docs/REFERENCE-SAMPLE.md`, `_claude-md/architecture/reference-sample.md`) + +### 4-Layer Composition (in order) + +1. **Convention content** -- Extracted from `@libar-docs-convention`-tagged patterns (rules, invariants, tables) +2. **Scoped diagrams** -- Mermaid diagrams filtered by `archContext`, `archLayer`, `patterns`, or `include` tags +3. **TypeScript shapes** -- API surfaces from `shapeSources` globs or `shapeSelectors` (declaration-level filtering) +4. **Behavior content** -- Gherkin-sourced patterns from `behaviorCategories` + +### Key Options (ReferenceDocConfig) + +### DiagramScope.diagramType Values + +### ShapeSelector Variants + +### When to Use + +- When generating reference documentation from convention-tagged decisions +- When creating scoped product area documents with live diagrams +- When creating both detailed (docs/) and summary (\_claude-md/) outputs +- When assembling multi-layer documents that combine conventions, diagrams, shapes, and behaviors + +### Factory Pattern + +| Option | Type | Description | +| ------------------ | --------------- | ------------------------------------------------------------ | +| conventionTags | string[] | Convention tag values to extract from decision records | +| diagramScope | DiagramScope | Single diagram configuration | +| diagramScopes | DiagramScope[] | Multiple diagrams (takes precedence over diagramScope) | +| shapeSources | string[] | Glob patterns for TypeScript shape extraction | +| shapeSelectors | ShapeSelector[] | Fine-grained declaration-level shape filtering | +| behaviorCategories | string[] | Category tags for behavior pattern content | +| includeTags | string[] | Cross-cutting content routing via include tags | +| preamble | SectionBlock[] | Static editorial sections prepended before generated content | +| productArea | string | Pre-filter all content sources to matching product area | +| excludeSourcePaths | string[] | Exclude patterns by source path prefix | + +| Type | Description | +| --------------- | -------------------------------------------------------------- | +| graph (default) | Flowchart with subgraphs by archContext, custom node shapes | +| sequenceDiagram | Sequence diagram with typed messages between participants | +| stateDiagram-v2 | State diagram with transitions from dependsOn relationships | +| C4Context | C4 context diagram with boundaries, systems, and relationships | +| classDiagram | Class diagram with archRole stereotypes and typed arrows | + +| Variant | Example | Behavior | +| -------------- | ----------------------------------------------- | --------------------------- | +| group only | `{ group: "api-types" }` | Match shapes by group tag | +| source + names | `{ source: "src/types.ts", names: ["Config"] }` | Named shapes from file | +| source only | `{ source: "src/path/*.ts" }` | All tagged shapes from glob | + +```typescript +const codec = createReferenceCodec(config, { detailLevel: 'detailed' }); +const doc = codec.decode(dataset); +``` + +--- + +## PrChangesCodec + +Transforms MasterDataset into RenderableDocument for PR-scoped output. +Filters patterns by changed files and/or release version tags. + +**Purpose:** PR-scoped view filtered by changed files or release version. + +**Output Files:** `working/PR-CHANGES.md` + +### When to Use + +- When generating PR summaries filtered by changed files +- When creating release-scoped documentation for PR reviews +- When building CI/CD outputs focused on PR scope + +### Factory Pattern + +Use `createPrChangesCodec(options)` for custom options: + +### Scope Filtering + +PR Changes codec filters patterns by: + +1. Changed files (matches against pattern.filePath) +2. Release version (matches against deliverable.release tags) + +If both are specified, patterns must match at least one criterion. + +```typescript +const codec = createPrChangesCodec({ + changedFiles: ['src/commands/order.ts'], + releaseFilter: 'v1.0.0', +}); +const doc = codec.decode(dataset); +``` + +--- + +## PlanningChecklistCodec + +**Purpose:** Pre-planning questions and Definition of Done validation. + +**Output Files:** `PLANNING-CHECKLIST.md` + +### When to Use + +- When starting a new implementation session and need pre-flight validation +- When generating Definition of Done checklists for active phases +- When checking readiness criteria before transitioning patterns to active + +--- + +## SessionPlanCodec + +**Purpose:** Implementation plans for coding sessions. + +**Output Files:** `SESSION-PLAN.md` + +### When to Use + +- When generating a structured implementation plan for an active coding session +- When documenting planned deliverables and their execution order +- When creating session-scoped plans aligned with FSM transitions + +--- + +## SessionFindingsCodec + +**Purpose:** Retrospective discoveries for roadmap refinement. + +**Output Files:** `SESSION-FINDINGS.md` + +### When to Use + +- When capturing session retrospective findings across all patterns +- When surfacing discovered gaps, improvements, risks, and learnings +- When refining roadmap priorities based on implementation discoveries + +### Finding Sources + +- `pattern.discoveredGaps` -- Gap findings +- `pattern.discoveredImprovements` -- Improvement suggestions +- `pattern.discoveredRisks` / `pattern.risk` -- Risk findings +- `pattern.discoveredLearnings` -- Learned insights + +--- + +## PatternsDocumentCodec + +Transforms MasterDataset into a RenderableDocument for pattern registry output. +Generates PATTERNS.md and category detail files (patterns/\*.md). + +**Purpose:** Pattern registry with category-based organization. + +**Output Files:** `PATTERNS.md` (main index), `patterns/.md` (category details) + +### When to Use + +- When generating the pattern registry documentation (PATTERNS.md) +- When creating category-specific pattern detail files +- When building pattern overview reports with status tracking + +### Factory Pattern + +Use `createPatternsCodec(options)` to create a configured codec: + +Or use the default export for standard behavior: + +| Option | Type | Default | Description | +| ---------------------- | ------------------------------------- | ---------- | ------------------------------------------- | +| generateDetailFiles | boolean | true | Create category detail files | +| detailLevel | "summary" \| "standard" \| "detailed" | "standard" | Output verbosity | +| includeDependencyGraph | boolean | true | Render Mermaid dependency graph | +| includeUseCases | boolean | true | Show use cases section | +| filterCategories | string[] | [] | Filter to specific categories (empty = all) | + +```typescript +const codec = createPatternsCodec({ generateDetailFiles: false }); +const doc = codec.decode(dataset); +``` + +```typescript +const doc = PatternsDocumentCodec.decode(dataset); +``` + +--- + +## IndexCodec + +**Purpose:** Navigation hub composing editorial preamble with MasterDataset statistics. + +**Output Files:** `INDEX.md` (single page, no detail files) + +### Design Decisions + +- DD-1: New IndexCodec in CodecRegistry (not a ReferenceDocConfig entry) +- DD-2: Document entries configured statically, not filesystem discovery +- DD-3: Audience reading paths are full preamble (editorial judgment) +- DD-4: Key concepts glossary uses preamble +- DD-5: Standalone codec, not routed through reference codec pipeline + +| Option | Type | Default | Description | +| ------------------------ | --------------- | ------- | ---------------------------------------------------------------- | +| preamble | SectionBlock[] | [] | Editorial sections (reading paths, document roles, key concepts) | +| documentEntries | DocumentEntry[] | [] | Static document inventory entries | +| includeProductAreaStats | boolean | true | Product area statistics table | +| includePhaseProgress | boolean | true | Phase progress summary | +| includeDocumentInventory | boolean | true | Unified document inventory | +| includePackageMetadata | boolean | true | Package metadata header | + +--- + +## CompositeCodec + +Assembles reference documents from multiple codec outputs by concatenating +RenderableDocument sections. Enables building documents composed from any +combination of existing codecs. + +**Purpose:** Assembles documents from multiple child codecs into a single RenderableDocument. + +**Output Files:** Configured per-instance (composes child codec outputs) + +### When to Use + +- When building reference docs from multiple codec outputs +- When composing session briefs from overview + current work + remaining work +- When referenceDocConfigs need content from arbitrary codecs + +### Factory Pattern + +Use the factory function with child codecs and options: + +Or use `composeDocuments` directly at the document level: + +```typescript +const codec = createCompositeCodec([OverviewCodec, CurrentWorkCodec, RemainingWorkCodec], { + title: 'Session Brief', +}); +const doc = codec.decode(dataset); +``` + +```typescript +const doc = composeDocuments([docA, docB], { title: 'Combined' }); +``` + +--- + +## ClaudeModuleCodec + +Transforms MasterDataset into RenderableDocuments for CLAUDE.md module generation. +Filters patterns with `claudeModule` tags and generates compact markdown modules +suitable for the `_claude-md/` directory structure. + +**Purpose:** Generate CLAUDE.md modules from annotated behavior specs. + +**Output Files:** One file per claude-module-tagged pattern at `{section}/{module}.md` + +### Content Extraction + +- Feature description → skipped (meta-documentation, not operational content) +- Rule: blocks → H4 sections with invariant + rationale +- Scenario Outline Examples → decision tables +- Tables in Rule descriptions → preserved as-is + +### Factory Pattern + +Use `createClaudeModuleCodec(options)` for custom options: + +```typescript +const codec = createClaudeModuleCodec({ detailLevel: 'detailed' }); +const doc = codec.decode(dataset); +``` + +--- + +## BusinessRulesCodec + +Transforms MasterDataset into a RenderableDocument for business rules output. +Generates BUSINESS-RULES.md organized by product area, phase, and feature. + +**Purpose:** Business rules documentation organized by product area, phase, and feature. Extracts domain constraints from Gherkin Rule: blocks. + +**Output Files:** `BUSINESS-RULES.md` (main index), `business-rules/.md` (area details) + +### When to Use + +- When generating business rules documentation for stakeholders +- When extracting domain constraints without implementation details +- When creating compliance or audit documentation from feature specs + +### Information Architecture + +### Progressive Disclosure + +- **summary**: Statistics only (compact reference) +- **standard**: Above + all features with rules inline +- **detailed**: Full content including code examples and verification links + +### Factory Pattern + +Use `createBusinessRulesCodec(options)` to create a configured codec: + +| Option | Type | Default | Description | +| -------------------- | ------------------------------------------ | ------------------- | ----------------------------------------- | +| groupBy | "domain" \| "phase" \| "domain-then-phase" | "domain-then-phase" | Primary grouping strategy | +| includeCodeExamples | boolean | false | Include code examples from DocStrings | +| includeTables | boolean | true | Include markdown tables from descriptions | +| includeRationale | boolean | true | Include rationale section per rule | +| filterDomains | string[] | [] | Filter by domain categories (empty = all) | +| filterPhases | number[] | [] | Filter by phases (empty = all) | +| onlyWithInvariants | boolean | false | Show only rules with explicit invariants | +| includeSource | boolean | true | Include source feature file link | +| includeVerifiedBy | boolean | true | Include Verified by scenario links | +| maxDescriptionLength | number | 150 | Max description length in standard mode | +| excludeSourcePaths | string[] | [] | Exclude patterns by source path prefix | + +```text +Product Area (Platform, DeliveryProcess) + └── Phase (21, 15, etc.) or Release (v0.1.0 for DeliveryProcess) + └── Feature (pattern name with description) + └── Rules (inline with Invariant + Rationale) +``` + +```typescript +const codec = createBusinessRulesCodec({ detailLevel: 'summary' }); +const doc = codec.decode(dataset); +``` + +--- + +## ArchitectureDocumentCodec + +Transforms MasterDataset into a RenderableDocument containing +architecture diagrams (Mermaid) generated from source annotations. + +**Purpose:** Architecture diagrams (Mermaid) generated from source annotations. Supports component and layered views. + +**Output Files:** `ARCHITECTURE.md` (generated architecture diagrams with component inventory) + +### When to Use + +- When generating architecture diagrams from code annotations +- When visualizing bounded contexts and component relationships +- When creating layered architecture views (domain/application/infrastructure) + +### Factory Pattern + +Use `createArchitectureCodec(options)` to create a configured codec: + +Or use the default export for standard behavior: + +### Supported Diagram Types + +- **component**: System overview with bounded context subgraphs +- **layered**: Components organized by architectural layer + +| Option | Type | Default | Description | +| ---------------- | ------------------------ | ----------- | ----------------------------------------- | +| diagramType | "component" \| "layered" | "component" | Type of diagram to generate | +| includeInventory | boolean | true | Include component inventory table | +| includeLegend | boolean | true | Include legend for arrow styles | +| filterContexts | string[] | [] | Filter to specific contexts (empty = all) | + +```typescript +const codec = createArchitectureCodec({ diagramType: 'component' }); +const doc = codec.decode(dataset); +``` + +```typescript +const doc = ArchitectureDocumentCodec.decode(dataset); +``` + +--- + +## AdrDocumentCodec + +Transforms MasterDataset into RenderableDocument for Architecture Decision Records. +Extracts ADRs from patterns with `@libar-docs-adr` tags. + +**Purpose:** Architecture Decision Records extracted from patterns with @libar-docs-adr tags. + +**Output Files:** `DECISIONS.md` (ADR index), `decisions/.md` (category details) + +### When to Use + +- When generating Architecture Decision Record documentation +- When extracting ADRs from feature files with structured annotations +- When building custom ADR reports with configurable content sections + +### Factory Pattern + +Use `createAdrCodec(options)` for custom options: + +### ADR Content + +ADR content is parsed from feature file descriptions: + +- **Context**: Problem background and constraints +- **Decision**: The chosen solution +- **Consequences**: Positive and negative outcomes + +```typescript +const codec = createAdrCodec({ + groupBy: 'phase', + includeContext: true, + includeDecision: true, + includeConsequences: false, +}); +const doc = codec.decode(dataset); +``` + +--- diff --git a/docs-live/reference/ARCHITECTURE-TYPES.md b/docs-live/reference/ARCHITECTURE-TYPES.md new file mode 100644 index 00000000..238ce0a8 --- /dev/null +++ b/docs-live/reference/ARCHITECTURE-TYPES.md @@ -0,0 +1,429 @@ +# Architecture Types Reference + +**Purpose:** Reference document: Architecture Types Reference +**Detail Level:** Full reference + +--- + +## API Types + +### MasterDatasetSchema (const) + +```typescript +/** + * Master Dataset - Unified view of all extracted patterns + * + * Contains raw patterns plus pre-computed views and statistics. + * This is the primary data structure passed to generators and sections. + * + */ +``` + +```typescript +MasterDatasetSchema = z.object({ + // ───────────────────────────────────────────────────────────────────────── + // Raw Data + // ───────────────────────────────────────────────────────────────────────── + + /** All extracted patterns (both TypeScript and Gherkin) */ + patterns: z.array(ExtractedPatternSchema), + + /** Tag registry for category lookups */ + tagRegistry: TagRegistrySchema, + + // Note: workflow is not in the Zod schema because LoadedWorkflow contains Maps + // (statusMap, phaseMap) which are not JSON-serializable. When workflow access + // is needed, get it from SectionContext/GeneratorContext instead. + + // ───────────────────────────────────────────────────────────────────────── + // Pre-computed Views + // ───────────────────────────────────────────────────────────────────────── + + /** Patterns grouped by normalized status */ + byStatus: StatusGroupsSchema, + + /** Patterns grouped by phase number (sorted ascending) */ + byPhase: z.array(PhaseGroupSchema), + + /** Patterns grouped by quarter (e.g., "Q4-2024") */ + byQuarter: z.record(z.string(), z.array(ExtractedPatternSchema)), + + /** Patterns grouped by category */ + byCategory: z.record(z.string(), z.array(ExtractedPatternSchema)), + + /** Patterns grouped by source type */ + bySource: SourceViewsSchema, + + /** Patterns grouped by product area (for O(1) product area lookups) */ + byProductArea: z.record(z.string(), z.array(ExtractedPatternSchema)), + + // ───────────────────────────────────────────────────────────────────────── + // Aggregate Statistics + // ───────────────────────────────────────────────────────────────────────── + + /** Overall status counts */ + counts: StatusCountsSchema, + + /** Number of distinct phases */ + phaseCount: z.number().int().nonnegative(), + + /** Number of distinct categories */ + categoryCount: z.number().int().nonnegative(), + + // ───────────────────────────────────────────────────────────────────────── + // Relationship Data (optional) + // ───────────────────────────────────────────────────────────────────────── + + /** Optional relationship index for dependency graph */ + relationshipIndex: z.record(z.string(), RelationshipEntrySchema).optional(), + + // ───────────────────────────────────────────────────────────────────────── + // Architecture Data (optional) + // ───────────────────────────────────────────────────────────────────────── + + /** Optional architecture index for diagram generation */ + archIndex: ArchIndexSchema.optional(), +}) +``` + +### StatusGroupsSchema (const) + +```typescript +/** + * Status-based grouping of patterns + * + * Patterns are normalized to three canonical states: + * - completed: implemented, completed + * - active: active, partial, in-progress + * - planned: roadmap, planned, undefined + * + */ +``` + +```typescript +StatusGroupsSchema = z.object({ + /** Patterns with status 'completed' or 'implemented' */ + completed: z.array(ExtractedPatternSchema), + + /** Patterns with status 'active', 'partial', or 'in-progress' */ + active: z.array(ExtractedPatternSchema), + + /** Patterns with status 'roadmap', 'planned', or undefined */ + planned: z.array(ExtractedPatternSchema), +}) +``` + +### StatusCountsSchema (const) + +```typescript +/** + * Status counts for aggregate statistics + * + */ +``` + +```typescript +StatusCountsSchema = z.object({ + /** Number of completed patterns */ + completed: z.number().int().nonnegative(), + + /** Number of active patterns */ + active: z.number().int().nonnegative(), + + /** Number of planned patterns */ + planned: z.number().int().nonnegative(), + + /** Total number of patterns */ + total: z.number().int().nonnegative(), +}) +``` + +### PhaseGroupSchema (const) + +```typescript +/** + * Phase grouping with patterns and counts + * + * Groups patterns by their phase number, with pre-computed + * status counts for each phase. + * + */ +``` + +```typescript +PhaseGroupSchema = z.object({ + /** Phase number (e.g., 1, 2, 3, 14, 39) */ + phaseNumber: z.number().int(), + + /** Optional phase name from workflow config */ + phaseName: z.string().optional(), + + /** Patterns in this phase */ + patterns: z.array(ExtractedPatternSchema), + + /** Pre-computed status counts for this phase */ + counts: StatusCountsSchema, +}) +``` + +### SourceViewsSchema (const) + +```typescript +/** + * Source-based views for different data origins + * + */ +``` + +```typescript +SourceViewsSchema = z.object({ + /** Patterns from TypeScript files (.ts) */ + typescript: z.array(ExtractedPatternSchema), + + /** Patterns from Gherkin feature files (.feature) */ + gherkin: z.array(ExtractedPatternSchema), + + /** Patterns with phase metadata (roadmap items) */ + roadmap: z.array(ExtractedPatternSchema), + + /** Patterns with PRD metadata (productArea, userRole, businessValue) */ + prd: z.array(ExtractedPatternSchema), +}) +``` + +### RelationshipEntrySchema (const) + +```typescript +/** + * Relationship index for dependency tracking + * + * Maps pattern names to their relationship metadata. + * + */ +``` + +```typescript +RelationshipEntrySchema = z.object({ + /** Patterns this pattern uses (from @libar-docs-uses) */ + uses: z.array(z.string()), + + /** Patterns that use this pattern (from @libar-docs-used-by) */ + usedBy: z.array(z.string()), + + /** Patterns this pattern depends on (from @libar-docs-depends-on) */ + dependsOn: z.array(z.string()), + + /** Patterns this pattern enables (from @libar-docs-enables) */ + enables: z.array(z.string()), + + // UML-inspired relationship fields (PatternRelationshipModel) + /** Patterns this item implements (realization relationship) */ + implementsPatterns: z.array(z.string()), + + /** Files/patterns that implement this pattern (computed inverse with file paths) */ + implementedBy: z.array(ImplementationRefSchema), + + /** Pattern this extends (generalization relationship) */ + extendsPattern: z.string().optional(), + + /** Patterns that extend this pattern (computed inverse) */ + extendedBy: z.array(z.string()), + + /** Related patterns for cross-reference without dependency (from @libar-docs-see-also tag) */ + seeAlso: z.array(z.string()), + + /** File paths to implementation APIs (from @libar-docs-api-ref tag) */ + apiRef: z.array(z.string()), +}) +``` + +### RuntimeMasterDataset (interface) + +```typescript +/** + * Runtime MasterDataset with optional workflow + * + * Extends the Zod-compatible MasterDataset with workflow reference. + * LoadedWorkflow contains Maps which aren't JSON-serializable, + * so it's kept separate from the Zod schema. + * + */ +``` + +```typescript +interface RuntimeMasterDataset extends MasterDataset { + /** Optional workflow configuration (not serializable) */ + readonly workflow?: LoadedWorkflow; +} +``` + +| Property | Description | +| --- | --- | +| workflow | Optional workflow configuration (not serializable) | + +### RawDataset (interface) + +```typescript +/** + * Raw input data for transformation + * + */ +``` + +```typescript +interface RawDataset { + /** Extracted patterns from TypeScript and/or Gherkin sources */ + readonly patterns: readonly ExtractedPattern[]; + + /** Tag registry for category lookups */ + readonly tagRegistry: TagRegistry; + + /** Optional workflow configuration for phase names (can be undefined) */ + readonly workflow?: LoadedWorkflow | undefined; + + /** Optional rules for inferring bounded context from file paths */ + readonly contextInferenceRules?: readonly ContextInferenceRule[] | undefined; +} +``` + +| Property | Description | +| --- | --- | +| patterns | Extracted patterns from TypeScript and/or Gherkin sources | +| tagRegistry | Tag registry for category lookups | +| workflow | Optional workflow configuration for phase names (can be undefined) | +| contextInferenceRules | Optional rules for inferring bounded context from file paths | + +### PipelineOptions (interface) + +```typescript +/** + * Options for building a MasterDataset via the shared pipeline. + * + * DD-1: Factory lives at src/generators/pipeline/build-pipeline.ts. + * DD-2: mergeConflictStrategy controls per-consumer conflict handling. + * DD-3: exclude, contextInferenceRules support future orchestrator + * migration without breaking changes. + * + */ +``` + +```typescript +interface PipelineOptions { + readonly input: readonly string[]; + readonly features: readonly string[]; + readonly baseDir: string; + readonly mergeConflictStrategy: 'fatal' | 'concatenate'; + readonly exclude?: readonly string[]; + readonly workflowPath?: string; + readonly contextInferenceRules?: readonly ContextInferenceRule[]; + /** DD-3: When false, skip validation pass (default true). */ + readonly includeValidation?: boolean; + /** DD-5: When true, return error on individual scan failures (default false). */ + readonly failOnScanErrors?: boolean; +} +``` + +| Property | Description | +| --- | --- | +| includeValidation | DD-3: When false, skip validation pass (default true). | +| failOnScanErrors | DD-5: When true, return error on individual scan failures (default false). | + +### PipelineResult (interface) + +```typescript +/** + * Successful pipeline result containing the dataset and validation summary. + * + */ +``` + +```typescript +interface PipelineResult { + readonly dataset: RuntimeMasterDataset; + readonly validation: ValidationSummary; + readonly warnings: readonly PipelineWarning[]; + readonly scanMetadata: ScanMetadata; +} +``` + +--- + +## Orchestrator Pipeline Responsibilities + +**Invariant:** The orchestrator is the integration boundary for full docs generation: it delegates dataset construction to the shared pipeline, then executes codecs and writes files. + +**Rationale:** Splitting orchestration into dataset construction (shared) and output execution (orchestrator-owned) keeps Data API and validation consumers aligned on one read-model path while preserving generator-specific output handling. + +--- + +## Steps 1-8 via buildMasterDataset() + +Steps 1-8 (config load, TypeScript/Gherkin scan + extraction, merge, hierarchy +derivation, workflow load, and `transformToMasterDataset`) are delegated to +`buildMasterDataset()`. + +--- + +## Steps 9-10: Codec Execution and File Writing + +After dataset creation, the orchestrator owns Step 9 (codec execution per generator, +output rendering, additional file fan-out) and Step 10 (path validation, overwrite +policy, and persisted file writes). + +### When to Use + +- Running complete documentation generation programmatically +- Integrating doc generation into build scripts +- Testing the full pipeline without CLI overhead + +--- + +## Shared Pipeline Factory Responsibilities + +**Invariant:** `buildMasterDataset()` is the shared factory for Steps 1-8 of the architecture pipeline and returns `Result` without process-level side effects. + +**Rationale:** Centralizing scan/extract/merge/transform flow prevents divergence between CLI consumers and preserves a single ADR-006 read-model path. + +--- + +## 8-Step Dataset Build Flow + +The factory owns: configuration load, TypeScript scan + extraction, Gherkin scan + +extraction, merge conflict handling, hierarchy child derivation, workflow load, +and `transformToMasterDataset` with validation summary. + +--- + +## Consumer Architecture and PipelineOptions Differentiation + +Three consumers share this factory: `process-api`, `validate-patterns`, and the +generation orchestrator. `PipelineOptions` differentiates behavior by +`mergeConflictStrategy` (`fatal` vs `concatenate`), `includeValidation` toggles, +and `failOnScanErrors` policy without forking pipeline logic. + +### When to Use + +- Any consumer needs a MasterDataset without rewriting scan/extract/merge flow +- CLI consumers require differentiated conflict strategy and validation behavior +- Orchestrator needs a shared steps 1-8 implementation before codec/file execution + +--- + +## MasterDataset View Fan-out + +Pre-computed view fan-out from MasterDataset (single-pass transform): + +```mermaid +graph TB + MD[MasterDataset] + MD --> byStatus["byStatus
(completed / active / planned)"] + MD --> byPhase["byPhase
(sorted, with counts)"] + MD --> byQuarter["byQuarter
(keyed by Q-YYYY)"] + MD --> byCategory["byCategory
(keyed by category name)"] + MD --> bySource["bySource
(typescript / gherkin / roadmap / prd)"] + MD --> counts["counts
(aggregate statistics)"] + MD --> RI["relationshipIndex?
(forward + reverse lookups)"] + MD --> AI["archIndex?
(role / context / layer / view)"] +``` + +--- diff --git a/docs-live/reference/PROCESS-API-RECIPES.md b/docs-live/reference/PROCESS-API-RECIPES.md new file mode 100644 index 00000000..f180b2bc --- /dev/null +++ b/docs-live/reference/PROCESS-API-RECIPES.md @@ -0,0 +1,476 @@ +# Process API CLI — Recipes & Workflow Guide + +> Auto-generated from CLI schema. See [CLI Reference](./PROCESS-API-REFERENCE.md) for flag tables. + +## Why Use This + +Traditional approach: read generated Markdown, parse it mentally, hope it's current. This CLI queries the **same annotated sources** that generate those docs -- in real time, with typed output. + +| Approach | Context Cost | Accuracy | Speed | +| ------------------------ | ------------ | --------------------- | ------- | +| Parse generated Markdown | High | Snapshot at gen time | Slow | +| **Data API CLI** | **Low** | Real-time from source | Instant | + +The CLI has two output modes: + +- **Text commands** (6) -- formatted for terminal reading or AI context. Use `===` section markers for structure. +- **JSON commands** (12+) -- wrapped in a `QueryResult` envelope. Pipeable to `jq`. + +Run `process-api --help` for the full command reference with all flags and 26 available API methods. + +## Quick Start + +The recommended session startup is three commands: + +```bash +pnpm process:query -- overview +pnpm process:query -- scope-validate MyPattern implement +pnpm process:query -- context MyPattern --session implement +``` + +Example `overview` output: + +```text +=== PROGRESS === +318 patterns (224 completed, 47 active, 47 planned) = 70% + +=== ACTIVE PHASES === +Phase 24: ProcessStateAPIRelationshipQueries (1 active) +Phase 25: DataAPIStubIntegration (1 active) + +=== BLOCKING === +StepLintExtendedRules blocked by: StepLintVitestCucumber + +=== DATA API === +pnpm process:query -- + overview, context, scope-validate, dep-tree, list, stubs, files, rules, arch blocking +``` + +## Session Types + +The `--session` flag tailors output to what you need right now: + +| Type | Includes | When to Use | +| ----------- | -------------------------------------------- | ---------------------------------- | +| `planning` | Pattern metadata and spec file only | Creating a new roadmap spec | +| `design` | Full: metadata, stubs, deps, deliverables | Making architectural decisions | +| `implement` | Focused: deliverables, FSM state, test files | Writing code from an existing spec | + +**Decision tree:** Starting to code? `implement`. Complex decisions? `design`. New pattern? `planning`. Not sure? Run `overview` first. + +--- + +## Session Workflow Commands + +These 6 commands output structured text (not JSON). They are designed for terminal reading and AI context consumption. + +### `overview` + +Executive summary: progress percentage, active phases, blocking patterns, and a CLI cheat sheet. + +```bash +pnpm process:query -- overview +``` + +Example output: + +``` +=== PROGRESS === +318 patterns (224 completed, 47 active, 47 planned) = 70% + +=== ACTIVE PHASES === +Phase 24: ProcessStateAPIRelationshipQueries (1 active) +Phase 25: DataAPIStubIntegration (1 active) + +=== BLOCKING === +StepLintExtendedRules blocked by: StepLintVitestCucumber + +=== DATA API — Use Instead of Explore Agents === +pnpm process:query -- + overview, context, scope-validate, dep-tree, list, stubs, files, rules, arch blocking +``` + +### `scope-validate` + +**Highest-impact command.** Pre-flight readiness check that prevents wasted sessions. Returns a PASS/BLOCKED/WARN verdict covering: dependency completion, deliverable definitions, FSM transition validity, and design decisions. + +```bash +pnpm process:query -- scope-validate MyPattern implement +``` + +Checks: dependency completion, deliverable definitions, FSM transition validity, design decisions, executable spec location. Valid session types for scope-validate: `implement`, `design`. + +Example output: + +``` +=== SCOPE VALIDATION: DataAPIDesignSessionSupport (implement) === + +=== CHECKLIST === +[PASS] Dependencies completed: 2/2 completed +[PASS] Deliverables defined: 4 deliverable(s) found +[BLOCKED] FSM allows transition: completed → active is not valid. +[WARN] Design decisions recorded: No PDR/AD references found in stubs + +=== VERDICT === +BLOCKED: 1 blocker(s) prevent implement session +``` + +### `context` + +Curated context bundle tailored to session type. + +```bash +pnpm process:query -- context MyPattern --session design +``` + +Example output: + +``` +=== PATTERN: ContextAssemblerImpl === +Status: active | Category: pattern +## ContextAssembler — Session-Oriented Context Bundle Builder + +Pure function composition over MasterDataset. +File: src/api/context-assembler.ts + +=== DEPENDENCIES === +[active] ProcessStateAPI (implementation) src/api/process-state.ts +[completed] MasterDataset (implementation) src/validation-schemas/master-dataset.ts + +=== CONSUMERS === +ContextFormatterImpl (active) +ProcessAPICLIImpl (active) + +=== ARCHITECTURE (context: api) === +MasterDataset (completed, read-model) +ProcessStateAPI (active, service) +... +``` + +### `dep-tree` + +Dependency chain with status indicators. Shows what a pattern depends on, recursively. + +```bash +pnpm process:query -- dep-tree MyPattern +``` + +Use `--depth` to limit recursion depth: `pnpm process:query -- dep-tree MyPattern --depth 2`. + +### `files` + +File reading list with implementation paths. Use `--related` to include architecture neighbors. + +```bash +pnpm process:query -- files MyPattern --related +``` + +Example output: + +``` +=== PRIMARY === +src/cli/process-api.ts + +=== ARCHITECTURE NEIGHBORS === +src/cli/version.ts +src/cli/output-pipeline.ts +src/cli/error-handler.ts +``` + +### `handoff` + +Captures session-end state: deliverable statuses, blockers, and modification date. + +```bash +pnpm process:query -- handoff --pattern MyPattern +``` + +Use `--git` to include recent commits. Use `--session` to tag the handoff with a session id. + +Example output: + +``` +=== HANDOFF: DataAPIDesignSessionSupport (review) === +Date: 2026-02-21 | Status: completed + +=== COMPLETED === +[x] Scope validation logic (src/api/scope-validator.ts) +[x] Handoff document generator (src/api/handoff-generator.ts) + +=== BLOCKERS === +None +``` + +--- + +## Pattern Discovery + +These commands output JSON wrapped in a `QueryResult` envelope. + +### `status` + +Status counts and completion percentage. + +```bash +pnpm process:query -- status +``` + +**Output:** `{ counts: { completed, active, planned, total }, completionPercentage, distribution }` + +### `list` + +Filtered pattern listing. Composable with output modifiers and list filters. + +```bash +pnpm process:query -- list --status roadmap --names-only +``` + +See Output Modifiers and List Filters for all options. Examples: `list --status active --count`, `list --phase 25 --fields patternName,status,file`. + +### `search` + +Fuzzy name search with match scores. Suggests close matches when a pattern is not found. + +```bash +pnpm process:query -- search EventStore +``` + +### `pattern` + +Full detail for one pattern including deliverables, dependencies, and all relationship fields. + +```bash +pnpm process:query -- pattern TransformDataset +``` + +**Warning:** Completed patterns can produce ~66KB of output. Prefer `context --session` for interactive sessions. + +### `stubs` + +Design stubs with target paths and resolution status. + +```bash +pnpm process:query -- stubs MyPattern +``` + +Use `--unresolved` to show only stubs missing target files: `pnpm process:query -- stubs --unresolved`. + +### `decisions` + +AD-N design decisions extracted from stub descriptions. + +```bash +pnpm process:query -- decisions MyPattern +``` + +**Note:** Returns exit code 1 when no decisions are found (unlike `list`/`search` which return empty arrays). + +### `pdr` + +Cross-reference patterns mentioning a PDR number. + +```bash +pnpm process:query -- pdr 1 +``` + +**Note:** Returns exit code 1 when no PDR references are found, same as `decisions`. + +### `rules` + +Business rules and invariants extracted from Gherkin `Rule:` blocks, grouped by product area, phase, and feature. + +```bash +pnpm process:query -- rules --pattern ProcessGuardDecider +``` + +**Warning:** Unfiltered `rules` output can exceed 600KB. Always use `--pattern` or `--product-area` filters. **Output shape:** `{ productAreas: [{ productArea, ruleCount, invariantCount, phases: [{ phase, features: [{ pattern, source, rules }] }] }], totalRules, totalInvariants }` + +--- + +## Architecture Queries + +All architecture queries output JSON. They use `@libar-docs-arch-*` annotations. + +### `arch roles` + +All arch-roles with pattern counts + +```bash +pnpm process:query -- arch roles +``` + +### `arch context` + +All bounded contexts + +```bash +pnpm process:query -- arch context +``` + +### `arch context ` + +Patterns in one bounded context + +```bash +pnpm process:query -- arch context scanner +``` + +### `arch layer` + +All architecture layers + +```bash +pnpm process:query -- arch layer +``` + +### `arch layer ` + +Patterns in one layer + +```bash +pnpm process:query -- arch layer domain +``` + +### `arch neighborhood ` + +Uses, usedBy, dependsOn, same-context + +```bash +pnpm process:query -- arch neighborhood EventStore +``` + +### `arch compare ` + +Cross-context shared deps + integration + +```bash +pnpm process:query -- arch compare scanner codec +``` + +### `arch coverage` + +Annotation completeness across input files + +```bash +pnpm process:query -- arch coverage +``` + +### `arch dangling` + +Broken references (names that don't exist) + +```bash +pnpm process:query -- arch dangling +``` + +### `arch orphans` + +Patterns with no relationships (isolated) + +```bash +pnpm process:query -- arch orphans +``` + +### `arch blocking` + +Patterns blocked by incomplete deps + +```bash +pnpm process:query -- arch blocking +``` + +--- + +## Metadata & Inventory + +### `tags` + +Tag usage report — counts per tag and value across all annotated sources. + +```bash +pnpm process:query -- tags +``` + +### `sources` + +File inventory by type (TypeScript, Gherkin, Stubs, Decisions). + +```bash +pnpm process:query -- sources +``` + +### `unannotated` + +TypeScript files missing the `@libar-docs` opt-in marker. Use `--path` to scope to a directory. + +```bash +pnpm process:query -- unannotated --path src/types +``` + +### `query` + +Execute any of the 26 query API methods directly by name. This is the escape hatch for methods not exposed as dedicated subcommands. + +```bash +pnpm process:query -- query getStatusCounts +``` + +Integer-like arguments are automatically coerced to numbers. Run `process-api --help` for the full list of available API methods. Examples: `query isValidTransition roadmap active`, `query getPatternsByPhase 18`, `query getRecentlyCompleted 5`. + +--- + +## Common Recipes + +Frequently-used command sequences for daily workflow. + +### Starting a Session + +The recommended session startup is three commands. + +```bash +pnpm process:query -- overview # project health +pnpm process:query -- scope-validate MyPattern implement # pre-flight +pnpm process:query -- context MyPattern --session implement # curated context +``` + +### Finding What to Work On + +Discover available patterns, blockers, and missing implementations. + +```bash +pnpm process:query -- list --status roadmap --names-only # available patterns +pnpm process:query -- arch blocking # stuck patterns +pnpm process:query -- stubs --unresolved # missing implementations +``` + +### Investigating a Pattern + +Deep-dive into a specific pattern: search, dependencies, neighbors, and files. + +```bash +pnpm process:query -- search EventStore # fuzzy name search +pnpm process:query -- dep-tree MyPattern --depth 2 # dependency chain +pnpm process:query -- arch neighborhood MyPattern # what it touches +pnpm process:query -- files MyPattern --related # file paths +``` + +### Design Session Prep + +Gather full context, design decisions, and stubs before a design session. + +```bash +pnpm process:query -- context MyPattern --session design # full context +pnpm process:query -- decisions MyPattern # design decisions +pnpm process:query -- stubs MyPattern # existing stubs +``` + +### Ending a Session + +Capture session-end state for continuity. + +```bash +pnpm process:query -- handoff --pattern MyPattern # capture state +pnpm process:query -- handoff --pattern MyPattern --git # include commits +``` + +--- diff --git a/docs-live/reference/PROCESS-API-REFERENCE.md b/docs-live/reference/PROCESS-API-REFERENCE.md new file mode 100644 index 00000000..3b78e3a4 --- /dev/null +++ b/docs-live/reference/PROCESS-API-REFERENCE.md @@ -0,0 +1,63 @@ +# Process API CLI Reference + +> Auto-generated from CLI schema. See [Process API Guide](../../docs/PROCESS-API.md) for usage examples and recipes. + +## Global Options + +| Flag | Short | Description | Default | +| --- | --- | --- | --- | +| `--input ` | `-i` | TypeScript glob pattern (repeatable) | from config or auto-detected | +| `--features ` | `-f` | Gherkin glob pattern (repeatable) | from config or auto-detected | +| `--base-dir ` | `-b` | Base directory | cwd | +| `--workflow ` | `-w` | Workflow config JSON | default | +| `--help` | `-h` | Show help | --- | +| `--version` | `-v` | Show version | --- | + +**Config auto-detection:** If `--input` and `--features` are not provided, the CLI loads defaults from `delivery-process.config.ts` in the current directory. If no config file exists, it falls back to filesystem-based detection. If neither works, `--input` is required. + +--- + +## Output Modifiers + +Composable with `list`, `arch context/layer`, and pattern-array `query` methods. + +| Output Modifier | Description | +| --- | --- | +| `--names-only` | Return array of pattern name strings | +| `--count` | Return integer count | +| `--fields ` | Return only specified fields per pattern | +| `--full` | Bypass summarization, return raw patterns | +| `--format ` | `json` (default, pretty-printed) or `compact` | + +Valid fields for `--fields`: `patternName`, `status`, `category`, `phase`, `file`, `source`. + +Precedence: `--count` > `--names-only` > `--fields` > default summarize. + +**Note on summarization:** By default, pattern arrays are summarized to ~100 bytes per pattern (from ~3.5KB raw). Use `--full` to get complete pattern objects. + +--- + +## List Filters + +For the `list` subcommand. All filters are composable. + +| List Filter | Description | +| --- | --- | +| `--status ` | Filter by FSM status (roadmap, active, completed, deferred) | +| `--phase ` | Filter by roadmap phase number | +| `--category ` | Filter by category | +| `--source ` | Filter by source type | +| `--arch-context ` | Filter by architecture context | +| `--product-area ` | Filter by product area | +| `--limit ` | Maximum results | +| `--offset ` | Skip first n results | + +--- + +## Session Types + +For the `--session` flag used with `context` and `scope-validate`. + +| Session Types | Description | +| --- | --- | +| `--session ` | Session type: `planning`, `design`, or `implement` | diff --git a/docs-live/reference/PROCESS-GUARD-REFERENCE.md b/docs-live/reference/PROCESS-GUARD-REFERENCE.md new file mode 100644 index 00000000..eabc5ade --- /dev/null +++ b/docs-live/reference/PROCESS-GUARD-REFERENCE.md @@ -0,0 +1,179 @@ +# Process Guard Reference + +**Purpose:** Reference document: Process Guard Reference +**Detail Level:** Full reference + +--- + +## Pre-commit Setup + +Configure Process Guard as a pre-commit hook using Husky. + +```bash +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx lint-process --staged +``` + +### package.json Scripts + +```json +{ + "scripts": { + "lint:process": "lint-process --staged", + "lint:process:ci": "lint-process --all --strict" + } +} +``` + +## Programmatic API + +Use Process Guard programmatically for custom validation workflows. + +```typescript +import { + deriveProcessState, + detectStagedChanges, + validateChanges, + hasErrors, + summarizeResult, +} from '@libar-dev/delivery-process/lint'; + +// 1. Derive state from annotations +const state = (await deriveProcessState({ baseDir: '.' })).value; + +// 2. Detect changes +const changes = detectStagedChanges('.').value; + +// 3. Validate +const { result } = validateChanges({ + state, + changes, + options: { strict: false, ignoreSession: false }, +}); + +// 4. Handle results +if (hasErrors(result)) { + console.log(summarizeResult(result)); + process.exit(1); +} +``` + +### API Functions + +| Category | Function | Description | +| -------- | ------------------------ | --------------------------------- | +| State | deriveProcessState(cfg) | Build state from file annotations | +| Changes | detectStagedChanges(dir) | Parse staged git diff | +| Changes | detectBranchChanges(dir) | Parse all changes vs main | +| Validate | validateChanges(input) | Run all validation rules | +| Results | hasErrors(result) | Check for blocking errors | +| Results | summarizeResult(result) | Human-readable summary | + +## Architecture + +Process Guard uses the Decider pattern: pure functions with no I/O. + +```mermaid +graph LR + A[deriveProcessState] --> C[validateChanges] + B[detectChanges] --> C + C --> D[ValidationResult] +``` + +--- + +## ProcessGuardDecider - Pure Validation Logic + +Pure function that validates changes against process rules. +Follows the Decider pattern from platform-core: no I/O, no side effects. + +### When to Use + +- When validating proposed changes against delivery process rules +- When implementing custom validation rules for the process guard +- When building pre-commit hooks that enforce FSM transitions + +### Design Principles + +- **Pure Function**: (state, changes, options) => result +- **No I/O**: All data passed in, no file reads +- **Composable Rules**: Rules are separate functions combined in decider +- **Testable**: Easy to unit test with mock data + +### Rules Implemented + +1. **Protection Level** - Completed files require unlock-reason +2. **Status Transition** - Transitions must follow PDR-005 FSM +3. **Scope Creep** - Active specs cannot add new deliverables +4. **Session Scope** - Modifications outside session scope warn + +### Error Guide Content (convention: process-guard-errors) + +--- + +## completed-protection + +**Invariant:** Completed specs are immutable without an explicit unlock reason. The unlock reason must be at least 10 characters and cannot be a placeholder. + +**Rationale:** The `completed` status represents verified, accepted work. Allowing silent modification undermines the terminal-state guarantee. Requiring an unlock reason creates an audit trail and forces the developer to justify why completed work needs revisiting. + +| Situation | Solution | Example | +| -------------------------- | ---------------------------------- | --------------------------------------------------- | +| Fix typo in completed spec | Add unlock reason tag | `@libar-docs-unlock-reason:Fix-typo-in-FSM-diagram` | +| Spec needs rework | Create new spec instead | New feature file with `roadmap` status | +| Legacy import | Multiple transitions in one commit | Set `roadmap` then `completed` | + +--- + +## invalid-status-transition + +**Invariant:** Status transitions must follow the PDR-005 FSM path. The only valid paths are: roadmap to active, roadmap to deferred, active to completed, active to roadmap, deferred to roadmap. + +**Rationale:** The FSM enforces a deliberate progression through planning, implementation, and completion. Skipping states (e.g., roadmap to completed) means work was never tracked as active, breaking session scoping and deliverable validation. + +| Attempted | Why Invalid | Valid Path | +| --------------------- | ---------------------------- | ------------------------------------------ | +| roadmap to completed | Must go through active | roadmap to active to completed | +| deferred to active | Must return to roadmap first | deferred to roadmap to active | +| deferred to completed | Cannot skip two states | deferred to roadmap to active to completed | + +--- + +## scope-creep + +**Invariant:** Active specs cannot add new deliverables. Scope is locked when status transitions to `active`. + +**Rationale:** Prevents scope creep during implementation. Plan fully before starting; implement what was planned. Adding deliverables mid- implementation signals inadequate planning and risks incomplete work. + +| Situation | Solution | Example | +| ------------------------------------- | ----------------------- | -------------------------------------------------------------- | +| Need new deliverable | Revert to roadmap first | Change status to roadmap, add deliverable, then back to active | +| Discovered work during implementation | Create new spec | New feature file for the discovered work | + +--- + +## session-scope + +**Invariant:** Files outside the active session scope trigger warnings to prevent accidental cross-session modifications. + +**Rationale:** Session scoping ensures focused work. Modifying files outside the session scope often indicates scope creep or working on the wrong task. The warning is informational (not blocking) to allow intentional cross-scope changes with `--ignore-session`. + +--- + +## session-excluded + +**Invariant:** Files explicitly excluded from a session cannot be modified in that session. This is a hard error, not a warning. + +**Rationale:** Explicit exclusion is a deliberate decision to protect certain files from modification during a session. Unlike session-scope (warning), exclusion represents a conscious boundary that should not be violated without changing the session configuration. + +--- + +## deliverable-removed + +**Invariant:** Removing a deliverable from an active spec triggers a warning to ensure the removal is intentional and documented. + +**Rationale:** Deliverable removal during active implementation may indicate descoping or completion elsewhere. The warning ensures visibility -- the commit message should document why the deliverable was removed. + +--- diff --git a/docs-generated/docs/REFERENCE-SAMPLE.md b/docs-live/reference/REFERENCE-SAMPLE.md similarity index 65% rename from docs-generated/docs/REFERENCE-SAMPLE.md rename to docs-live/reference/REFERENCE-SAMPLE.md index 4bf0019c..cad683c4 100644 --- a/docs-generated/docs/REFERENCE-SAMPLE.md +++ b/docs-live/reference/REFERENCE-SAMPLE.md @@ -11,15 +11,17 @@ **Rationale:** Without canonical values, organic drift (e.g., Generator vs Generators) produces inconsistent grouping in generated documentation and fragmented product area pages. -| Value | Reader Question | Covers | -| --- | --- | --- | -| Annotation | How do I annotate code? | Scanning, extraction, tag parsing, dual-source | -| Configuration | How do I configure the tool? | Config loading, presets, resolution | -| Generation | How does code become docs? | Codecs, generators, rendering, diagrams | -| Validation | How is the workflow enforced? | FSM, DoD, anti-patterns, process guard, lint | -| DataAPI | How do I query process state? | Process state API, stubs, context assembly, CLI | -| CoreTypes | What foundational types exist? | Result monad, error factories, string utils | -| Process | How does the session workflow work? | Session lifecycle, handoffs, conventions | +| Value | Reader Question | Covers | +| ------------- | ----------------------------------- | ----------------------------------------------- | +| Annotation | How do I annotate code? | Scanning, extraction, tag parsing, dual-source | +| Configuration | How do I configure the tool? | Config loading, presets, resolution | +| Generation | How does code become docs? | Codecs, generators, rendering, diagrams | +| Validation | How is the workflow enforced? | FSM, DoD, anti-patterns, process guard, lint | +| DataAPI | How do I query process state? | Process state API, stubs, context assembly, CLI | +| CoreTypes | What foundational types exist? | Result monad, error factories, string utils | +| Process | How does the session workflow work? | Session lifecycle, handoffs, conventions | + +**Verified by:** Canonical values are enforced --- @@ -29,12 +31,14 @@ **Rationale:** Unbounded category values prevent meaningful grouping of architecture decisions and make cross-cutting queries unreliable. -| Value | Purpose | -| --- | --- | -| architecture | System structure, component design, data flow | -| process | Workflow, conventions, annotation rules | -| testing | Test strategy, verification approach | -| documentation | Documentation generation, content structure | +| Value | Purpose | +| ------------- | --------------------------------------------- | +| architecture | System structure, component design, data flow | +| process | Workflow, conventions, annotation rules | +| testing | Test strategy, verification approach | +| documentation | Documentation generation, content structure | + +**Verified by:** Canonical values are enforced --- @@ -44,12 +48,14 @@ **Rationale:** Without protection levels, active specs accumulate scope creep and completed specs get silently modified, undermining delivery process integrity. -| Status | Protection | Can Add Deliverables | Allowed Actions | -| --- | --- | --- | --- | -| roadmap | None | Yes | Full editing | -| active | Scope-locked | No | Edit existing deliverables only | -| completed | Hard-locked | No | Requires unlock-reason tag | -| deferred | None | Yes | Full editing | +| Status | Protection | Can Add Deliverables | Allowed Actions | +| --------- | ------------ | -------------------- | ------------------------------- | +| roadmap | None | Yes | Full editing | +| active | Scope-locked | No | Edit existing deliverables only | +| completed | Hard-locked | No | Requires unlock-reason tag | +| deferred | None | Yes | Full editing | + +**Verified by:** Canonical values are enforced --- @@ -57,15 +63,20 @@ **Invariant:** Only these transitions are valid. All others are rejected by Process Guard. -**Rationale:** Allowing arbitrary transitions (e.g., roadmap to completed) bypasses the active phase where scope-lock and deliverable tracking provide quality assurance. Completed is a terminal state. Modifications require `@libar-docs-unlock-reason` escape hatch. +**Rationale:** Allowing arbitrary transitions (e.g., roadmap to completed) bypasses the active phase where scope-lock and deliverable tracking provide quality assurance. + +| From | To | Trigger | +| -------- | --------- | --------------------- | +| roadmap | active | Start work | +| roadmap | deferred | Postpone | +| active | completed | All deliverables done | +| active | roadmap | Blocked/regressed | +| deferred | roadmap | Resume planning | + +**Verified by:** Canonical values are enforced -| From | To | Trigger | -| --- | --- | --- | -| roadmap | active | Start work | -| roadmap | deferred | Postpone | -| active | completed | All deliverables done | -| active | roadmap | Blocked/regressed | -| deferred | roadmap | Resume planning | + Completed is a terminal state. Modifications require + `@libar-docs-unlock-reason` escape hatch. --- @@ -75,14 +86,16 @@ **Rationale:** Without explicit format types, parsers must guess value structure, leading to silent data corruption when CSV values are treated as single strings or numbers are treated as text. -| Format | Parsing | Example | -| --- | --- | --- | -| flag | Boolean presence, no value | @libar-docs-core | -| value | Simple string | @libar-docs-pattern MyPattern | -| enum | Constrained to predefined list | @libar-docs-status completed | -| csv | Comma-separated values | @libar-docs-uses A, B, C | -| number | Numeric value | @libar-docs-phase 15 | -| quoted-value | Preserves spaces | @libar-docs-brief:'Multi word' | +| Format | Parsing | Example | +| ------------ | ------------------------------ | ------------------------------ | +| flag | Boolean presence, no value | @libar-docs-core | +| value | Simple string | @libar-docs-pattern MyPattern | +| enum | Constrained to predefined list | @libar-docs-status completed | +| csv | Comma-separated values | @libar-docs-uses A, B, C | +| number | Numeric value | @libar-docs-phase 15 | +| quoted-value | Preserves spaces | @libar-docs-brief:'Multi word' | + +**Verified by:** Canonical values are enforced --- @@ -92,12 +105,14 @@ **Rationale:** Cross-domain tag placement (e.g., runtime dependencies in Gherkin) creates conflicting sources of truth and breaks the dual-source architecture ownership model. -| Tag | Correct Source | Wrong Source | Rationale | -| --- | --- | --- | --- | -| uses | TypeScript | Feature files | TS owns runtime dependencies | -| depends-on | Feature files | TypeScript | Gherkin owns planning dependencies | -| quarter | Feature files | TypeScript | Gherkin owns timeline metadata | -| team | Feature files | TypeScript | Gherkin owns ownership metadata | +| Tag | Correct Source | Wrong Source | Rationale | +| ---------- | -------------- | ------------- | ---------------------------------- | +| uses | TypeScript | Feature files | TS owns runtime dependencies | +| depends-on | Feature files | TypeScript | Gherkin owns planning dependencies | +| quarter | Feature files | TypeScript | Gherkin owns timeline metadata | +| team | Feature files | TypeScript | Gherkin owns ownership metadata | + +**Verified by:** Canonical values are enforced --- @@ -107,6 +122,8 @@ **Rationale:** Non-standard formats (e.g., Q1-2026) break lexicographic sorting, which roadmap generation and timeline queries depend on for correct ordering. +**Verified by:** Canonical values are enforced + --- ## Canonical phase definitions (6-phase USDP standard) @@ -115,14 +132,16 @@ **Rationale:** Ad-hoc phase names and ordering produce inconsistent roadmap grouping across packages and make cross-package progress tracking impossible. -| Order | Phase | Purpose | -| --- | --- | --- | -| 1 | Inception | Problem framing, scope definition | -| 2 | Elaboration | Design decisions, architecture exploration | -| 3 | Session | Planning and design session work | -| 4 | Construction | Implementation, testing, integration | -| 5 | Validation | Verification, acceptance criteria confirmation | -| 6 | Retrospective | Review, lessons learned, documentation | +| Order | Phase | Purpose | +| ----- | ------------- | ---------------------------------------------- | +| 1 | Inception | Problem framing, scope definition | +| 2 | Elaboration | Design decisions, architecture exploration | +| 3 | Session | Planning and design session work | +| 4 | Construction | Implementation, testing, integration | +| 5 | Validation | Verification, acceptance criteria confirmation | +| 6 | Retrospective | Review, lessons learned, documentation | + +**Verified by:** Canonical values are enforced --- @@ -132,14 +151,16 @@ **Rationale:** Freeform status strings bypass Zod validation and break DoD checks, which rely on terminal status classification to determine pattern completeness. -| Value | Meaning | -| --- | --- | -| complete | Work is done | -| in-progress | Work is ongoing | -| pending | Work has not started | -| deferred | Work postponed | -| superseded | Replaced by another | -| n/a | Not applicable | +| Value | Meaning | +| ----------- | -------------------- | +| complete | Work is done | +| in-progress | Work is ongoing | +| pending | Work has not started | +| deferred | Work postponed | +| superseded | Replaced by another | +| n/a | Not applicable | + +**Verified by:** Canonical values are enforced --- @@ -230,23 +251,32 @@ classDiagram class TransformDataset { <> } + class ProcessApiReferenceGenerator { + } class DecisionDocGenerator { <> } + class CliRecipeGenerator { + } class MasterDataset class Pattern_Scanner class GherkinASTParser class ShapeExtractor class DecisionDocCodec + class ProcessApiHybridGeneration class PatternRelationshipModel + class CliRecipeCodec SourceMapper ..> DecisionDocCodec : depends on SourceMapper ..> ShapeExtractor : depends on SourceMapper ..> GherkinASTParser : depends on Documentation_Generation_Orchestrator ..> Pattern_Scanner : uses TransformDataset ..> MasterDataset : uses TransformDataset ..|> PatternRelationshipModel : implements + ProcessApiReferenceGenerator ..|> ProcessApiHybridGeneration : implements DecisionDocGenerator ..> DecisionDocCodec : depends on DecisionDocGenerator ..> SourceMapper : depends on + CliRecipeGenerator ..|> CliRecipeCodec : implements + CliRecipeCodec ..> ProcessApiHybridGeneration : depends on ``` --- @@ -325,11 +355,17 @@ graph LR PatternHelpers["PatternHelpers"] ArchQueriesImpl("ArchQueriesImpl") end + subgraph cli["Cli"] + CLISchema["CLISchema"] + end subgraph config["Config"] ConfigurationTypes["ConfigurationTypes"] ProjectConfigTypes["ProjectConfigTypes"] ConfigurationPresets["ConfigurationPresets"] end + subgraph renderer["Renderer"] + loadPreambleFromMarkdown___Shared_Markdown_to_SectionBlock_Parser["loadPreambleFromMarkdown — Shared Markdown-to-SectionBlock Parser"] + end subgraph taxonomy["Taxonomy"] TagRegistryBuilder("TagRegistryBuilder") end @@ -340,11 +376,15 @@ graph LR subgraph related["Related"] ProcessStateAPI["ProcessStateAPI"]:::neighbor TypeScriptTaxonomyImplementation["TypeScriptTaxonomyImplementation"]:::neighbor + ProcessApiHybridGeneration["ProcessApiHybridGeneration"]:::neighbor + ProceduralGuideCodec["ProceduralGuideCodec"]:::neighbor PhaseStateMachineValidation["PhaseStateMachineValidation"]:::neighbor DataAPIOutputShaping["DataAPIOutputShaping"]:::neighbor DataAPIArchitectureQueries["DataAPIArchitectureQueries"]:::neighbor end TagRegistryBuilder ..->|implements| TypeScriptTaxonomyImplementation + loadPreambleFromMarkdown___Shared_Markdown_to_SectionBlock_Parser ..->|implements| ProceduralGuideCodec + CLISchema ..->|implements| ProcessApiHybridGeneration ProjectConfigTypes -->|uses| ConfigurationTypes ProjectConfigTypes -->|uses| ConfigurationPresets ConfigurationPresets -->|uses| ConfigurationTypes @@ -364,21 +404,6 @@ graph LR ## API Types -### SectionBlock (type) - -```typescript -type SectionBlock = - | HeadingBlock - | ParagraphBlock - | SeparatorBlock - | TableBlock - | ListBlock - | CodeBlock - | MermaidBlock - | CollapsibleBlock - | LinkOutBlock; -``` - ### normalizeStatus (function) ````typescript @@ -410,9 +435,9 @@ type SectionBlock = function normalizeStatus(status: string | undefined): NormalizedStatus; ``` -| Parameter | Type | Description | -| --- | --- | --- | -| status | | Raw status from pattern (case-insensitive) | +| Parameter | Type | Description | +| --------- | ---- | ------------------------------------------ | +| status | | Raw status from pattern (case-insensitive) | **Returns:** "completed" | "active" | "planned" @@ -444,7 +469,7 @@ DELIVERABLE_STATUS_VALUES = [ 'deferred', 'superseded', 'n/a', -] as const +] as const; ``` ### CategoryDefinition (interface) @@ -464,13 +489,28 @@ interface CategoryDefinition { } ``` -| Property | Description | -| --- | --- | -| tag | Category tag name without prefix (e.g., "core", "api", "ddd", "saga") | -| domain | Human-readable domain name for display (e.g., "Strategic DDD", "Event Sourcing") | -| priority | Display order priority - lower values appear first in sorted output | -| description | Brief description of the category's purpose and typical patterns | -| aliases | Alternative tag names that map to this category (e.g., "es" for "event-sourcing") | +| Property | Description | +| ----------- | --------------------------------------------------------------------------------- | +| tag | Category tag name without prefix (e.g., "core", "api", "ddd", "saga") | +| domain | Human-readable domain name for display (e.g., "Strategic DDD", "Event Sourcing") | +| priority | Display order priority - lower values appear first in sorted output | +| description | Brief description of the category's purpose and typical patterns | +| aliases | Alternative tag names that map to this category (e.g., "es" for "event-sourcing") | + +### SectionBlock (type) + +```typescript +type SectionBlock = + | HeadingBlock + | ParagraphBlock + | SeparatorBlock + | TableBlock + | ListBlock + | CodeBlock + | MermaidBlock + | CollapsibleBlock + | LinkOutBlock; +``` --- @@ -505,53 +545,160 @@ Validation happens later at load time via Zod schema in `loadProjectConfig()`. ### When to Use -In `delivery-process.config.ts` at project root: +- In `delivery-process.config.ts` at project root to get type-safe configuration with autocompletion. -```typescript -import { defineConfig } from '@libar-dev/delivery-process/config'; +### ConfigBasedWorkflowDefinition -export default defineConfig({ - preset: 'ddd-es-cqrs', - sources: { typescript: ['src/** /*.ts'] }, -}); -``` +[View ConfigBasedWorkflowDefinition source](delivery-process/specs/config-based-workflow-definition.feature) + +**Problem:** +Every `pnpm process:query` and `pnpm docs:*` invocation prints: +`Failed to load default workflow (6-phase-standard): Workflow file not found` + +The `loadDefaultWorkflow()` function resolves to `catalogue/workflows/` +which does not exist. The directory was deleted during monorepo extraction. +The system already degrades gracefully (workflow = undefined), but the +warning is noise for both human CLI use and future hook consumers (HUD). + +The old `6-phase-standard.json` conflated three concerns: + +- Taxonomy vocabulary (status names) — already in `src/taxonomy/` +- FSM behavior (transitions) — already in `src/validation/fsm/` +- Workflow structure (phases) — orphaned, no proper home + +**Solution:** +Inline the default workflow as a constant in `workflow-loader.ts`, built +from canonical taxonomy values. Make `loadDefaultWorkflow()` synchronous. +Preserve `loadWorkflowFromPath()` for custom `--workflow ` overrides. + +The workflow definition uses only the 4 canonical statuses from ADR-001 +(roadmap, active, completed, deferred) — not the stale 5-status set from +the deleted JSON (which included non-canonical `implemented` and `partial`). + +Phase definitions (Inception, Elaboration, Session, Construction, +Validation, Retrospective) move from a missing JSON file to an inline +constant, making the default workflow always available without file I/O. + +Design Decisions (DS-1, 2026-02-15): + +| ID | Decision | Rationale | +| DD-1 | Inline constant in workflow-loader.ts, not preset integration | Minimal correct fix, zero type regression risk. Preset integration deferred. | +| DD-2 | Constant satisfies existing WorkflowConfig type | Reuse createLoadedWorkflow() from workflow-config.ts. No new types needed. | +| DD-3 | Remove dead code: getCatalogueWorkflowsPath, loadWorkflowConfig, DEFAULT_WORKFLOW_NAME | Dead since monorepo extraction. Public API break is safe (function always threw). | +| DD-4 | loadDefaultWorkflow() returns LoadedWorkflow synchronously | Infallible constant needs no async or error handling. | +| DD-5 | Amend ADR-001 with canonical phase definitions | Phase names are canonical values; fits existing governance in ADR-001. | + +
+Default workflow is built from an inline constant (2 scenarios) + +#### Default workflow is built from an inline constant + +**Invariant:** `loadDefaultWorkflow()` returns a `LoadedWorkflow` without file system access. It cannot fail. The default workflow constant uses only canonical status values from `src/taxonomy/status-values.ts`. + +**Rationale:** The file-based loading path (`catalogue/workflows/`) has been dead code since monorepo extraction. Both callers (orchestrator, process-api) already handle the failure gracefully, proving the system works without it. Making the function synchronous and infallible removes the try-catch ceremony and the warning noise. + +**Verified by:** + +- Default workflow loads without warning +- Workflow constant uses canonical statuses only +- Workflow constant uses canonical statuses only + + Implementation approach: + +
+ +
+Custom workflow files still work via --workflow flag (1 scenarios) + +#### Custom workflow files still work via --workflow flag + +**Invariant:** `loadWorkflowFromPath()` remains available for projects that need custom workflow definitions. The `--workflow ` CLI flag and `workflowPath` config field continue to work. + +**Rationale:** The inline default replaces file-based _default_ loading, not file-based _custom_ loading. Projects may define custom phases or additional statuses via JSON files. + +**Verified by:** + +- Custom workflow file overrides default + +
+ +
+FSM validation and Process Guard are not affected + +#### FSM validation and Process Guard are not affected + +**Invariant:** The FSM transition matrix, protection levels, and Process Guard rules remain hardcoded in `src/validation/fsm/` and `src/lint/process-guard/`. They do not read from `LoadedWorkflow`. + +**Rationale:** FSM and workflow are separate concerns. FSM enforces status transitions (4-state model from PDR-005). Workflow defines phase structure (6-phase USDP). The workflow JSON declared `transitionsTo` on its statuses, but no code ever read those values — the FSM uses its own `VALID_TRANSITIONS` constant. This separation is correct and intentional. Blast radius analysis confirmed zero workflow imports in: - src/validation/fsm/ (4 files) - src/lint/process-guard/ (5 files) - src/taxonomy/ (all files) + +
+ +
+Workflow as a configurable preset field is deferred + +#### Workflow as a configurable preset field is deferred + +**Invariant:** The inline default workflow constant is the only workflow source until preset integration is implemented. No preset or project config field exposes workflow customization. + +**Rationale:** Coupling workflow into the preset/config system before the inline fix ships would widen the blast radius and risk type regressions across all config consumers. + +**Verified by:** + +- N/A - deferred until preset integration + + Adding `workflow` as a field on `DeliveryProcessConfig` (presets) and + `DeliveryProcessProjectConfig` (project config) is a natural next step + but NOT required for the MVP fix. + + The inline constant in `workflow-loader.ts` resolves the warning. Moving + workflow into the preset/config system enables: + - Different presets with different default phases (e.g. + +- 3-phase generic) + - Per-project phase customization in delivery-process.config.ts + - Phase definitions appearing in generated documentation + + See ideation artifact for design options: + delivery-process/ideations/2026-02-15-workflow-config-and-fsm-extensibility.feature + +
### ADR005CodecBasedMarkdownRendering [View ADR005CodecBasedMarkdownRendering source](delivery-process/decisions/adr-005-codec-based-markdown-rendering.feature) **Context:** - The documentation generator needs to transform structured pattern data - (MasterDataset) into markdown files. The initial approach used direct - string concatenation in generator functions, mixing data selection, - formatting logic, and output assembly in a single pass. This made - generators hard to test, difficult to compose, and impossible to - render the same data in different formats (e.g., full docs vs compact - AI context). - - **Decision:** - Adopt a codec architecture inspired by serialization codecs (encode/decode). - Each document type has a codec that decodes a MasterDataset into a - RenderableDocument — an intermediate representation of sections, headings, - tables, paragraphs, and code blocks. A separate renderer transforms the - RenderableDocument into markdown. This separates data selection (what to - include) from formatting (how it looks) from serialization (markdown syntax). - - **Consequences:** - | Type | Impact | - | Positive | Codecs are pure functions: dataset in, document out -- trivially testable | - | Positive | RenderableDocument is an inspectable IR -- tests assert on structure, not strings | - | Positive | Composable via CompositeCodec -- reference docs assemble from child codecs | - | Positive | Same dataset can produce different outputs (full doc, compact doc, AI context) | - | Negative | Extra abstraction layer between data and output | - | Negative | RenderableDocument vocabulary must cover all needed output patterns | - - **Benefits:** - | Benefit | Before (String Concat) | After (Codec) | - | Testability | Assert on markdown strings | Assert on typed section blocks | - | Composability | Copy-paste between generators | CompositeCodec assembles children | - | Format variants | Duplicate generator logic | Same codec, different renderer | - | Progressive disclosure | Manual heading management | Heading depth auto-calculated | +The documentation generator needs to transform structured pattern data +(MasterDataset) into markdown files. The initial approach used direct +string concatenation in generator functions, mixing data selection, +formatting logic, and output assembly in a single pass. This made +generators hard to test, difficult to compose, and impossible to +render the same data in different formats (e.g., full docs vs compact +AI context). + +**Decision:** +Adopt a codec architecture inspired by serialization codecs (encode/decode). +Each document type has a codec that decodes a MasterDataset into a +RenderableDocument — an intermediate representation of sections, headings, +tables, paragraphs, and code blocks. A separate renderer transforms the +RenderableDocument into markdown. This separates data selection (what to +include) from formatting (how it looks) from serialization (markdown syntax). + +**Consequences:** +| Type | Impact | +| Positive | Codecs are pure functions: dataset in, document out -- trivially testable | +| Positive | RenderableDocument is an inspectable IR -- tests assert on structure, not strings | +| Positive | Composable via CompositeCodec -- reference docs assemble from child codecs | +| Positive | Same dataset can produce different outputs (full doc, compact doc, AI context) | +| Negative | Extra abstraction layer between data and output | +| Negative | RenderableDocument vocabulary must cover all needed output patterns | + +**Benefits:** +| Benefit | Before (String Concat) | After (Codec) | +| Testability | Assert on markdown strings | Assert on typed section blocks | +| Composability | Copy-paste between generators | CompositeCodec assembles children | +| Format variants | Duplicate generator logic | Same codec, different renderer | +| Progressive disclosure | Manual heading management | Heading depth auto-calculated |
Codecs implement a decode-only contract (2 scenarios) @@ -566,8 +713,8 @@ export default defineConfig({ ```typescript interface DocumentCodec { - decode(dataset: MasterDataset): RenderableDocument; - } + decode(dataset: MasterDataset): RenderableDocument; +} ``` **Verified by:** @@ -588,16 +735,6 @@ interface DocumentCodec { **Section block types:** -| Block Type | Purpose | Markdown Output | -| --- | --- | --- | -| heading | Section title with depth | ## Title (depth-adjusted) | -| paragraph | Prose text | Plain text with blank lines | -| table | Structured data | Pipe-delimited table | -| code | Code sample with language | Fenced code block | -| list | Ordered or unordered items | - item or 1. item | -| separator | Visual break between sections | --- | -| metaRow | Key-value metadata | **Key:** Value | - **Verified by:** - All block types render to markdown @@ -618,14 +755,14 @@ interface DocumentCodec { ```typescript const referenceDoc = CompositeCodec.create({ - title: 'Architecture Reference', - codecs: [ - behaviorCodec, // patterns with rules - conventionCodec, // decision records - shapeCodec, // type definitions - diagramCodec, // mermaid diagrams - ], - }); + title: 'Architecture Reference', + codecs: [ + behaviorCodec, // patterns with rules + conventionCodec, // decision records + shapeCodec, // type definitions + diagramCodec, // mermaid diagrams + ], +}); ``` **Verified by:** @@ -644,11 +781,6 @@ const referenceDoc = CompositeCodec.create({ **Rationale:** Early ADRs used name prefixes like "Context - ..." and "Decision - ..." on Rule blocks to structure content. Later ADRs placed Context, Decision, and Consequences as bold-annotated prose in the Feature description, reserving Rule: blocks for invariants and design rules. Both conventions are valid. The ADR codec must handle both because the codebase contains ADRs authored in each style. The Feature description lives in pattern.directive.description. If the codec only renders Rules (via partitionRulesByPrefix), then Feature description content is silently dropped -- no error, no warning. This caused confusion across two repos where ADR content appeared in the feature file but was missing from generated docs. The fix renders pattern.directive.description in buildSingleAdrDocument between the Overview metadata table and the partitioned Rules section, using renderFeatureDescription() which walks content linearly and handles prose, tables, and DocStrings with correct interleaving. -| Source | Location | Example | Rendered Via | -| --- | --- | --- | --- | -| Rule prefix | Rule: Context - ... | ADR-001 (taxonomy) | partitionRulesByPrefix() | -| Feature description | **Context:** prose in Feature block | ADR-005 (codec rendering) | renderFeatureDescription() | - **Verified by:** - Feature description content is rendered @@ -678,22 +810,22 @@ const referenceDoc = CompositeCodec.create({ [View ADR001TaxonomyCanonicalValues source](delivery-process/decisions/adr-001-taxonomy-canonical-values.feature) **Context:** - The annotation system requires well-defined canonical values for taxonomy - tags, FSM status lifecycle, and source ownership rules. Without canonical - values, organic growth produces drift (Generator vs Generators, Process - vs DeliveryProcess) and inconsistent grouping in generated documentation. - - **Decision:** - Define canonical values for all taxonomy enums, FSM states with protection - levels, valid transitions, tag format types, and source ownership rules. - These are the durable constants of the delivery process. - - **Consequences:** - | Type | Impact | - | Positive | Generated docs group into coherent sections | - | Positive | FSM enforcement has clear, auditable state definitions | - | Positive | Source ownership prevents cross-domain tag confusion | - | Negative | Migration effort for existing specs with non-canonical values | +The annotation system requires well-defined canonical values for taxonomy +tags, FSM status lifecycle, and source ownership rules. Without canonical +values, organic growth produces drift (Generator vs Generators, Process +vs DeliveryProcess) and inconsistent grouping in generated documentation. + +**Decision:** +Define canonical values for all taxonomy enums, FSM states with protection +levels, valid transitions, tag format types, and source ownership rules. +These are the durable constants of the delivery process. + +**Consequences:** +| Type | Impact | +| Positive | Generated docs group into coherent sections | +| Positive | FSM enforcement has clear, auditable state definitions | +| Positive | Source ownership prevents cross-domain tag confusion | +| Negative | Migration effort for existing specs with non-canonical values |
Product area canonical values @@ -704,15 +836,9 @@ const referenceDoc = CompositeCodec.create({ **Rationale:** Without canonical values, organic drift (e.g., Generator vs Generators) produces inconsistent grouping in generated documentation and fragmented product area pages. -| Value | Reader Question | Covers | -| --- | --- | --- | -| Annotation | How do I annotate code? | Scanning, extraction, tag parsing, dual-source | -| Configuration | How do I configure the tool? | Config loading, presets, resolution | -| Generation | How does code become docs? | Codecs, generators, rendering, diagrams | -| Validation | How is the workflow enforced? | FSM, DoD, anti-patterns, process guard, lint | -| DataAPI | How do I query process state? | Process state API, stubs, context assembly, CLI | -| CoreTypes | What foundational types exist? | Result monad, error factories, string utils | -| Process | How does the session workflow work? | Session lifecycle, handoffs, conventions | +**Verified by:** + +- Canonical values are enforced
@@ -725,12 +851,9 @@ const referenceDoc = CompositeCodec.create({ **Rationale:** Unbounded category values prevent meaningful grouping of architecture decisions and make cross-cutting queries unreliable. -| Value | Purpose | -| --- | --- | -| architecture | System structure, component design, data flow | -| process | Workflow, conventions, annotation rules | -| testing | Test strategy, verification approach | -| documentation | Documentation generation, content structure | +**Verified by:** + +- Canonical values are enforced
@@ -743,12 +866,9 @@ const referenceDoc = CompositeCodec.create({ **Rationale:** Without protection levels, active specs accumulate scope creep and completed specs get silently modified, undermining delivery process integrity. -| Status | Protection | Can Add Deliverables | Allowed Actions | -| --- | --- | --- | --- | -| roadmap | None | Yes | Full editing | -| active | Scope-locked | No | Edit existing deliverables only | -| completed | Hard-locked | No | Requires unlock-reason tag | -| deferred | None | Yes | Full editing | +**Verified by:** + +- Canonical values are enforced @@ -759,15 +879,14 @@ const referenceDoc = CompositeCodec.create({ **Invariant:** Only these transitions are valid. All others are rejected by Process Guard. -**Rationale:** Allowing arbitrary transitions (e.g., roadmap to completed) bypasses the active phase where scope-lock and deliverable tracking provide quality assurance. Completed is a terminal state. Modifications require `@libar-docs-unlock-reason` escape hatch. +**Rationale:** Allowing arbitrary transitions (e.g., roadmap to completed) bypasses the active phase where scope-lock and deliverable tracking provide quality assurance. + +**Verified by:** -| From | To | Trigger | -| --- | --- | --- | -| roadmap | active | Start work | -| roadmap | deferred | Postpone | -| active | completed | All deliverables done | -| active | roadmap | Blocked/regressed | -| deferred | roadmap | Resume planning | +- Canonical values are enforced + + Completed is a terminal state. Modifications require + `@libar-docs-unlock-reason` escape hatch. @@ -780,14 +899,9 @@ const referenceDoc = CompositeCodec.create({ **Rationale:** Without explicit format types, parsers must guess value structure, leading to silent data corruption when CSV values are treated as single strings or numbers are treated as text. -| Format | Parsing | Example | -| --- | --- | --- | -| flag | Boolean presence, no value | @libar-docs-core | -| value | Simple string | @libar-docs-pattern MyPattern | -| enum | Constrained to predefined list | @libar-docs-status completed | -| csv | Comma-separated values | @libar-docs-uses A, B, C | -| number | Numeric value | @libar-docs-phase 15 | -| quoted-value | Preserves spaces | @libar-docs-brief:'Multi word' | +**Verified by:** + +- Canonical values are enforced @@ -800,12 +914,9 @@ const referenceDoc = CompositeCodec.create({ **Rationale:** Cross-domain tag placement (e.g., runtime dependencies in Gherkin) creates conflicting sources of truth and breaks the dual-source architecture ownership model. -| Tag | Correct Source | Wrong Source | Rationale | -| --- | --- | --- | --- | -| uses | TypeScript | Feature files | TS owns runtime dependencies | -| depends-on | Feature files | TypeScript | Gherkin owns planning dependencies | -| quarter | Feature files | TypeScript | Gherkin owns timeline metadata | -| team | Feature files | TypeScript | Gherkin owns ownership metadata | +**Verified by:** + +- Canonical values are enforced @@ -818,6 +929,10 @@ const referenceDoc = CompositeCodec.create({ **Rationale:** Non-standard formats (e.g., Q1-2026) break lexicographic sorting, which roadmap generation and timeline queries depend on for correct ordering. +**Verified by:** + +- Canonical values are enforced +
@@ -829,14 +944,9 @@ const referenceDoc = CompositeCodec.create({ **Rationale:** Ad-hoc phase names and ordering produce inconsistent roadmap grouping across packages and make cross-package progress tracking impossible. -| Order | Phase | Purpose | -| --- | --- | --- | -| 1 | Inception | Problem framing, scope definition | -| 2 | Elaboration | Design decisions, architecture exploration | -| 3 | Session | Planning and design session work | -| 4 | Construction | Implementation, testing, integration | -| 5 | Validation | Verification, acceptance criteria confirmation | -| 6 | Retrospective | Review, lessons learned, documentation | +**Verified by:** + +- Canonical values are enforced
@@ -849,145 +959,33 @@ const referenceDoc = CompositeCodec.create({ **Rationale:** Freeform status strings bypass Zod validation and break DoD checks, which rely on terminal status classification to determine pattern completeness. -| Value | Meaning | -| --- | --- | -| complete | Work is done | -| in-progress | Work is ongoing | -| pending | Work has not started | -| deferred | Work postponed | -| superseded | Replaced by another | -| n/a | Not applicable | - **Verified by:** - Canonical values are enforced -### ConfigBasedWorkflowDefinition - -[View ConfigBasedWorkflowDefinition source](delivery-process/specs/config-based-workflow-definition.feature) - -**Problem:** - Every `pnpm process:query` and `pnpm docs:*` invocation prints: - `Failed to load default workflow (6-phase-standard): Workflow file not found` - - The `loadDefaultWorkflow()` function resolves to `catalogue/workflows/` - which does not exist. The directory was deleted during monorepo extraction. - The system already degrades gracefully (workflow = undefined), but the - warning is noise for both human CLI use and future hook consumers (HUD). - - The old `6-phase-standard.json` conflated three concerns: - - Taxonomy vocabulary (status names) — already in `src/taxonomy/` - - FSM behavior (transitions) — already in `src/validation/fsm/` - - Workflow structure (phases) — orphaned, no proper home - - **Solution:** - Inline the default workflow as a constant in `workflow-loader.ts`, built - from canonical taxonomy values. Make `loadDefaultWorkflow()` synchronous. - Preserve `loadWorkflowFromPath()` for custom `--workflow ` overrides. - - The workflow definition uses only the 4 canonical statuses from ADR-001 - (roadmap, active, completed, deferred) — not the stale 5-status set from - the deleted JSON (which included non-canonical `implemented` and `partial`). - - Phase definitions (Inception, Elaboration, Session, Construction, - Validation, Retrospective) move from a missing JSON file to an inline - constant, making the default workflow always available without file I/O. - - Design Decisions (DS-1, 2026-02-15): - - | ID | Decision | Rationale | - | DD-1 | Inline constant in workflow-loader.ts, not preset integration | Minimal correct fix, zero type regression risk. Preset integration deferred. | - | DD-2 | Constant satisfies existing WorkflowConfig type | Reuse createLoadedWorkflow() from workflow-config.ts. No new types needed. | - | DD-3 | Remove dead code: getCatalogueWorkflowsPath, loadWorkflowConfig, DEFAULT_WORKFLOW_NAME | Dead since monorepo extraction. Public API break is safe (function always threw). | - | DD-4 | loadDefaultWorkflow() returns LoadedWorkflow synchronously | Infallible constant needs no async or error handling. | - | DD-5 | Amend ADR-001 with canonical phase definitions | Phase names are canonical values; fits existing governance in ADR-001. | - -
-Default workflow is built from an inline constant (2 scenarios) - -#### Default workflow is built from an inline constant - -**Invariant:** `loadDefaultWorkflow()` returns a `LoadedWorkflow` without file system access. It cannot fail. The default workflow constant uses only canonical status values from `src/taxonomy/status-values.ts`. - -**Rationale:** The file-based loading path (`catalogue/workflows/`) has been dead code since monorepo extraction. Both callers (orchestrator, process-api) already handle the failure gracefully, proving the system works without it. Making the function synchronous and infallible removes the try-catch ceremony and the warning noise. - -| Step | Change | Impact | -| --- | --- | --- | -| Add DEFAULT_WORKFLOW_CONFIG constant | WorkflowConfig literal with 4 statuses, 6 phases | New code in workflow-loader.ts | -| Change loadDefaultWorkflow() to sync | Returns createLoadedWorkflow(DEFAULT_WORKFLOW_CONFIG) | Signature: Promise to sync | -| Remove dead code paths | Delete getCatalogueWorkflowsPath, loadWorkflowConfig, DEFAULT_WORKFLOW_NAME, dead imports | workflow-loader.ts cleanup | -| Remove loadWorkflowConfig from public API | Update src/config/index.ts exports | Breaking change (safe: function always threw) | -| Update orchestrator call site | Remove await and try-catch (lines 410-418) | orchestrator.ts | -| Update process-api call site | Remove await and try-catch (lines 549-555) | process-api.ts | - -**Verified by:** - -- Default workflow loads without warning -- Workflow constant uses canonical statuses only -- Workflow constant uses canonical statuses only - - Implementation approach: - -
- -
-Custom workflow files still work via --workflow flag (1 scenarios) - -#### Custom workflow files still work via --workflow flag - -**Invariant:** `loadWorkflowFromPath()` remains available for projects that need custom workflow definitions. The `--workflow ` CLI flag and `workflowPath` config field continue to work. - -**Rationale:** The inline default replaces file-based *default* loading, not file-based *custom* loading. Projects may define custom phases or additional statuses via JSON files. - -**Verified by:** - -- Custom workflow file overrides default - -
- -
-FSM validation and Process Guard are not affected - -#### FSM validation and Process Guard are not affected - -**Invariant:** The FSM transition matrix, protection levels, and Process Guard rules remain hardcoded in `src/validation/fsm/` and `src/lint/process-guard/`. They do not read from `LoadedWorkflow`. - -**Rationale:** FSM and workflow are separate concerns. FSM enforces status transitions (4-state model from PDR-005). Workflow defines phase structure (6-phase USDP). The workflow JSON declared `transitionsTo` on its statuses, but no code ever read those values — the FSM uses its own `VALID_TRANSITIONS` constant. This separation is correct and intentional. Blast radius analysis confirmed zero workflow imports in: - src/validation/fsm/ (4 files) - src/lint/process-guard/ (5 files) - src/taxonomy/ (all files) - -
- -
-Workflow as a configurable preset field is deferred - -#### Workflow as a configurable preset field is deferred +### ProcessGuardTesting -**Invariant:** The inline default workflow constant is the only workflow source until preset integration is implemented. No preset or project config field exposes workflow customization. +[View ProcessGuardTesting source](tests/features/validation/process-guard.feature) -**Rationale:** Coupling workflow into the preset/config system before the inline fix ships would widen the blast radius and risk type regressions across all config consumers. Adding `workflow` as a field on `DeliveryProcessConfig` (presets) and `DeliveryProcessProjectConfig` (project config) is a natural next step but NOT required for the MVP fix. The inline constant in `workflow-loader.ts` resolves the warning. Moving workflow into the preset/config system enables: - Different presets with different default phases (e.g., 3-phase generic) - Per-project phase customization in delivery-process.config.ts - Phase definitions appearing in generated documentation See ideation artifact for design options: delivery-process/ideations/2026-02-15-workflow-config-and-fsm-extensibility.feature +Pure validation functions for enforcing delivery process rules per PDR-005. +All validation follows the Decider pattern: (state, changes, options) => result. -
+**Problem:** -### ProcessGuardTesting +- Completed specs modified without explicit unlock reason +- Invalid status transitions bypass FSM rules +- Active specs expand scope unexpectedly with new deliverables +- Changes occur outside session boundaries -[View ProcessGuardTesting source](tests/features/validation/process-guard.feature) +**Solution:** -Pure validation functions for enforcing delivery process rules per PDR-005. - All validation follows the Decider pattern: (state, changes, options) => result. - - **Problem:** - - Completed specs modified without explicit unlock reason - - Invalid status transitions bypass FSM rules - - Active specs expand scope unexpectedly with new deliverables - - Changes occur outside session boundaries - - **Solution:** - - checkProtectionLevel() enforces unlock-reason for completed (hard) files - - checkStatusTransitions() validates transitions against FSM matrix - - checkScopeCreep() prevents deliverable addition to active (scope) specs - - checkSessionScope() warns about files outside session scope - - checkSessionExcluded() errors on explicitly excluded files +- checkProtectionLevel() enforces unlock-reason for completed (hard) files +- checkStatusTransitions() validates transitions against FSM matrix +- checkScopeCreep() prevents deliverable addition to active (scope) specs +- checkSessionScope() warns about files outside session scope +- checkSessionExcluded() errors on explicitly excluded files
Completed files require unlock-reason to modify (4 scenarios) diff --git a/docs-live/reference/SESSION-WORKFLOW-GUIDE.md b/docs-live/reference/SESSION-WORKFLOW-GUIDE.md new file mode 100644 index 00000000..bd9e3ac8 --- /dev/null +++ b/docs-live/reference/SESSION-WORKFLOW-GUIDE.md @@ -0,0 +1,384 @@ +# Session Workflow Guide + +**Purpose:** Reference document: Session Workflow Guide +**Detail Level:** Full reference + +--- + +## Session Decision Tree + +Use this flowchart to determine which session type to run. + +```mermaid +graph TD + A[Starting from pattern brief?] -->|Yes| B[Need code stubs now?] + A -->|No| C[Ready to code?] + B -->|Yes| D[Planning + Design Session] + B -->|No| E[Planning Session] + C -->|Yes| F[Complex decisions?] + C -->|No| E + F -->|Yes| G[Design Session] + F -->|No| H[Implementation Session] + + style D fill:#e1f5fe + style E fill:#e8f5e9 + style G fill:#fff3e0 + style H fill:#fce4ec +``` + +## Session Type Contracts + +| Session | Input | Output | FSM Change | +| ----------------- | ------------------- | --------------------------- | ------------------------------------ | +| Planning | Pattern brief | Roadmap spec (`.feature`) | Creates `roadmap` | +| Design | Complex requirement | Decision specs + code stubs | None | +| Implementation | Roadmap spec | Code + tests | `roadmap` -> `active` -> `completed` | +| Planning + Design | Pattern brief | Spec + stubs | Creates `roadmap` | + +--- + +## Implementation Execution Order + +Implementation sessions MUST follow this strict 5-step sequence. Skipping steps causes Process Guard rejection at commit time. + +1. **Transition to `active` FIRST** (before any code changes) +2. **Create executable spec stubs** (if `@libar-docs-executable-specs` present) +3. **For each deliverable:** implement, test, update status to `complete` +4. **Transition to `completed`** (only when ALL deliverables done) +5. **Regenerate docs:** `pnpm docs:all` + +### Implementation Do NOT + +| Do NOT | Why | +| ----------------------------------- | --------------------------------------- | +| Add new deliverables to active spec | Scope-locked state prevents scope creep | +| Mark completed with incomplete work | Hard-locked state cannot be undone | +| Skip FSM transitions | Process Guard will reject | +| Edit generated docs directly | Regenerate from source | + +--- + +## Planning Session + +**Goal:** Create a roadmap spec. Do not write implementation code. + +### Context Gathering + +```bash +pnpm process:query -- overview # Project health +pnpm process:query -- list --status roadmap --names-only # Available patterns +``` + +### Planning Checklist + +- [ ] **Extract metadata** from pattern brief: phase, dependencies, status +- [ ] **Create spec file** at `{specs-directory}/{product-area}/{pattern}.feature` +- [ ] **Structure the feature** with Problem/Solution, tags, deliverables table +- [ ] **Convert constraints to Rule: blocks** with Invariant/Rationale +- [ ] **Add scenarios** per Rule: 1 happy-path + 1 validation minimum +- [ ] **Set executable specs location** via `@libar-docs-executable-specs` tag + +### Planning Do NOT + +- Create `.ts` implementation files +- Transition to `active` +- Ask "Ready to implement?" + +--- + +## Design Session + +**Goal:** Make architectural decisions. Create code stubs with interfaces. Do not implement. + +### Context Gathering + +```bash +pnpm process:query -- context --session design # Full context bundle +pnpm process:query -- dep-tree # Dependency chain +pnpm process:query -- stubs # Existing design stubs +``` + +### When to Use Design Sessions + +| Use Design Session | Skip Design Session | +| -------------------------- | ------------------- | +| Multiple valid approaches | Single obvious path | +| New patterns/capabilities | Bug fix | +| Cross-context coordination | Clear requirements | + +### Design Checklist + +- [ ] **Record decisions** as PDR `.feature` files in `delivery-process/decisions/` +- [ ] **Document options** with at least 2-3 approaches and pros/cons +- [ ] **Get approval** from user on recommended approach +- [ ] **Create code stubs** in `delivery-process/stubs/{pattern-name}/` +- [ ] **Verify stub identifier spelling** before committing +- [ ] **List canonical helpers** in `@libar-docs-uses` tags + +### Design Do NOT + +- Create markdown design documents (use decision specs instead) +- Create implementation plans +- Transition spec to `active` +- Write full implementations (stubs only) + +--- + +## Planning + Design Session + +**Goal:** Create spec AND code stubs in one session. For immediate implementation handoff. + +### When to Use + +| Use Planning + Design | Use Planning Only | +| ----------------------------------- | ---------------------------- | +| Need stubs for implementation | Only enhancing spec | +| Preparing for immediate handoff | Still exploring requirements | +| Want complete two-tier architecture | Don't need Tier 2 yet | + +--- + +## Handoff Documentation + +For multi-session work, capture state at session boundaries using the Process Data API. + +```bash +pnpm process:query -- handoff --pattern +pnpm process:query -- handoff --pattern --git # include recent commits +``` + +--- + +## Quick Reference: FSM Protection + +| State | Protection | Can Add Deliverables | Needs Unlock | +| ----------- | ------------ | -------------------- | ------------ | +| `roadmap` | None | Yes | No | +| `active` | Scope-locked | No | No | +| `completed` | Hard-locked | No | Yes | +| `deferred` | None | Yes | No | + +--- + +## Behavior Specifications + +### SessionGuidesModuleSource + +[View SessionGuidesModuleSource source](delivery-process/specs/session-guides-module-source.feature) + +**Problem:** +CLAUDE.md contains a "Session Workflows" section (~160 lines) that is hand-maintained +with no link to any annotated source. Three hand-written files in `_claude-md/workflow/` +(session-workflows.md, session-details.md, fsm-handoff.md) are equally opaque: no +machine-readable origin, no regeneration from source annotations. + +The prior plan proposed tagging ADR-001, ADR-003, and PDR-001 with `@libar-docs-claude-module` +to make them the source for generated workflow modules. Design analysis revealed this is +fundamentally flawed: `claude-module` is a file-level tag that pulls ALL Rules from a file, +but most Rules in those decision specs are irrelevant to session workflows (ADR-001 has 9 +Rules, only 2-3 are workflow-relevant; PDR-001 has 7 Rules about CLI implementation +decisions, not workflow guidance). + +**Solution:** +This spec file itself becomes the annotated source for session workflow content. +Session workflow invariants are captured as Rule: blocks here, covering session type +contracts, FSM protection, execution order, error recovery, and handoff patterns. + +Once ClaudeModuleGeneration (Phase 25) ships, adding `@libar-docs-claude-module` and +`@libar-docs-claude-section:workflow` tags to this spec will cause the codec to produce +`_claude-md/workflow/` modules automatically. The hand-written files are then deleted +and the CLAUDE.md section becomes a generated include. + +Retain `docs/SESSION-GUIDES.md` (389 lines) as the authoritative public human reference +deployed to libar.dev. It serves developers with comprehensive checklists and full CLI +examples — content that cannot be expressed as compact invariants. + +Three-layer architecture after Phase 39: + +| Layer | Location | Content | Maintenance | +| Public human reference | docs/SESSION-GUIDES.md | Full checklists, CLI examples, decision trees | Manual (editorial) | +| Compact AI context | \_claude-md/workflow/ | Invariants, session contracts, FSM reference | Generated from this spec | +| Machine-queryable source | Process Data API | Rules from this spec via `rules` command | Derived from annotations | + +**Why It Matters:** +| Benefit | How | +| No CLAUDE.md drift | Session workflow section generated, not hand-authored | +| Single annotated source | This spec owns all session workflow invariants | +| Correct audience alignment | Public guide stays in docs/, AI context in \_claude-md/ | +| Process API coverage | Session workflow content queryable via `pnpm process:query -- rules` | +| Immediately useful | Rule: blocks are queryable today, generation follows when Phase 25 ships | + +**Design Session Findings (2026-03-05):** +| Finding | Impact | +| claude-module is file-level, not Rule-level | Cannot selectively tag individual Rules in ADR/PDR files | +| ADR-001 has 9 Rules, only 2-3 workflow-relevant | Tagging ADR-001 would create noisy, diluted context | +| PDR-001 Rules are CLI implementation decisions | Not session workflow guidance, wrong audience | +| Phase 25 claude-section enum lacks workflow value | Must add workflow to enum before annotation | +| Self-referential spec is correct source | This spec captures invariants, SESSION-GUIDES.md has editorial content | + +
+SESSION-GUIDES.md is the authoritative public human reference (2 scenarios) + +#### SESSION-GUIDES.md is the authoritative public human reference + +**Invariant:** `docs/SESSION-GUIDES.md` exists and is not deleted, shortened, or replaced with a redirect. Its comprehensive checklists, CLI command examples, and session decision trees serve developers on libar.dev. + +**Rationale:** Session workflow guidance requires two formats for two audiences. Public developers need comprehensive checklists with full examples. AI sessions need compact invariants they can apply without reading 389 lines. + +**Verified by:** + +- SESSION-GUIDES.md exists after Phase 39 completes +- No broken links after Phase 39 +- SESSION-GUIDES.md exists after Phase 39 + +
+ +
+CLAUDE.md session workflow content is derived, not hand-authored (1 scenarios) + +#### CLAUDE.md session workflow content is derived, not hand-authored + +**Invariant:** After Phase 39 generation deliverables complete, the "Session Workflows" section in CLAUDE.md contains no manually-authored content. It is composed from generated `_claude-md/workflow/` modules. + +**Rationale:** A hand-maintained CLAUDE.md session section creates two copies of session workflow guidance with no synchronization mechanism. Regeneration from annotated source eliminates drift. + +**Verified by:** + +- CLAUDE.md session section is a generated module reference + +
+ +
+Session type determines artifacts and FSM changes (1 scenarios) + +#### Session type determines artifacts and FSM changes + +**Invariant:** Four session types exist, each with defined input, output, and FSM impact. Mixing outputs across session types (e.g., writing code in a planning session) violates session discipline. + +**Rationale:** Session type confusion causes wasted work — a design mistake discovered mid-implementation wastes the entire session. Clear contracts prevent scope bleeding between session types. + +**Verified by:** + +- Session type contracts are enforced + +
+ +
+Planning sessions produce roadmap specs only (1 scenarios) + +#### Planning sessions produce roadmap specs only + +**Invariant:** A planning session creates a roadmap spec with metadata, deliverables table, Rule: blocks with invariants, and scenarios. It must not produce implementation code, transition to active, or prompt for implementation readiness. + +**Rationale:** Planning is the cheapest session type — it produces .feature file edits, no compilation needed. Mixing implementation into planning defeats the cost advantage and introduces untested code without a locked scope. + +**Verified by:** + +- Planning session output constraints + +
+ +
+Design sessions produce decisions and stubs only (1 scenarios) + +#### Design sessions produce decisions and stubs only + +**Invariant:** A design session makes architectural decisions and creates code stubs with interfaces. It must not produce implementation code. Context gathering via the Process Data API must precede any explore agent usage. + +**Rationale:** Design sessions resolve ambiguity before implementation begins. Code stubs in delivery-process/stubs/ live outside src/ to avoid TypeScript compilation and ESLint issues, making them zero-risk artifacts. + +**Verified by:** + +- Design session output constraints + +
+ +
+Implementation sessions follow FSM-enforced execution order (1 scenarios) + +#### Implementation sessions follow FSM-enforced execution order + +**Invariant:** Implementation sessions must follow a strict 5-step execution order. Transition to active must happen before any code changes. Transition to completed must happen only when ALL deliverables are done. Skipping steps causes Process Guard rejection at commit time. + +**Rationale:** The execution order ensures FSM state accurately reflects work state at every point. Writing code before transitioning to active means Process Guard sees changes to a roadmap spec (no scope protection). Marking completed with incomplete work creates a hard-locked state that requires unlock-reason to fix. + +**Verified by:** + +- Implementation execution order is enforced +- Implementation execution order is enforced + + Execution order: + 1. Transition to active FIRST (before any code changes) + 2. Create executable spec stubs (if libar-docs-executable-specs present) + 3. For each deliverable: implement + +- test +- update status to complete 4. Transition to completed (only when ALL deliverables done) 5. Regenerate docs: pnpm docs:all + +
+ +
+FSM errors have documented fixes (1 scenarios) + +#### FSM errors have documented fixes + +**Invariant:** Every Process Guard error code has a defined cause and fix. The error codes, causes, and fixes form a closed set — no undocumented error states exist. + +**Rationale:** Undocumented FSM errors cause session-blocking confusion. A lookup table from error code to fix eliminates guesswork and prevents workarounds that bypass process integrity. + +**Verified by:** + +- All FSM errors have documented recovery paths +- All FSM errors have documented recovery paths + + Escape hatches for exceptional situations: + +
+ +
+Handoff captures session-end state for continuity (1 scenarios) + +#### Handoff captures session-end state for continuity + +**Invariant:** Multi-session work requires handoff documentation generated from the Process Data API. Handoff output always reflects actual annotation state, not manual notes. + +**Rationale:** Manual session notes drift from actual deliverable state. The handoff command derives state from annotations, ensuring the next session starts from ground truth rather than stale notes. + +**Verified by:** + +- Handoff output reflects annotation state +- Handoff output reflects annotation state + + Generate handoff via: pnpm process:query -- handoff --pattern PatternName + Options: --git (include recent commits) + +- --session (session identifier) + + Output includes: deliverable statuses + +- blockers +- modification date +- and next + steps — all derived from current annotation state. + +
+ +
+ClaudeModuleGeneration is the generation mechanism (1 scenarios) + +#### ClaudeModuleGeneration is the generation mechanism + +**Invariant:** Phase 39 depends on ClaudeModuleGeneration (Phase 25). Adding `@libar-docs-claude-module` and `@libar-docs-claude-section:workflow` tags to this spec will cause ClaudeModuleGeneration to produce `_claude-md/workflow/` output files. The hand-written `_claude-md/workflow/` files are deleted after successful verified generation. + +**Rationale:** The annotation work (Rule blocks in this spec) is immediately useful — queryable via `pnpm process:query -- rules`. Generation deliverables cannot complete until Phase 25 ships the ClaudeModuleCodec. This sequencing is intentional: the annotation investment has standalone value regardless of whether the codec exists yet. + +**Prerequisite:** Phase 25 must add `workflow` to the `claude-section` enum +values (currently: core, delivery-process, testing, infrastructure). + +**Verified by:** + +- Generated modules replace hand-written workflow files + +
+ +--- diff --git a/docs-live/taxonomy/categories.md b/docs-live/taxonomy/categories.md new file mode 100644 index 00000000..c5c9ddc7 --- /dev/null +++ b/docs-live/taxonomy/categories.md @@ -0,0 +1,33 @@ +# Category Reference + +**Purpose:** Complete category definitions with aliases and domain groupings + +--- + +## Category Definitions + +3 categories sorted by priority. + +| Tag | Domain | Priority | Description | Aliases | +| ------- | -------------- | -------- | -------------- | ---------------- | +| `core` | Core | 1 | Core patterns | - | +| `api` | API | 2 | Public APIs | - | +| `infra` | Infrastructure | 3 | Infrastructure | `infrastructure` | + +## Categories by Domain + +### Core + +`core` + +### API + +`api` + +### Infrastructure + +`infra` + +--- + +[Back to Taxonomy Reference](../TAXONOMY.md) diff --git a/docs-live/taxonomy/format-types.md b/docs-live/taxonomy/format-types.md new file mode 100644 index 00000000..9a0bd1c8 --- /dev/null +++ b/docs-live/taxonomy/format-types.md @@ -0,0 +1,67 @@ +# Format Type Reference + +**Purpose:** Detailed format type parsing behavior and examples + +--- + +## Format Type Reference + +Detailed parsing behavior for each format type. + +### `value` + +| Property | Value | +| ---------------- | --------------------------------------------------- | +| Description | Simple string value | +| Parsing Behavior | Captures everything after the tag name as the value | +| Example | `@libar-docs-pattern CommandOrchestrator` | +| Notes | Most common format for single-value tags | + +### `enum` + +| Property | Value | +| ---------------- | ------------------------------------------------------------ | +| Description | Constrained to predefined values | +| Parsing Behavior | Validates value against allowed list; rejects invalid values | +| Example | `@libar-docs-status roadmap` | +| Notes | Used for FSM states, priority levels, risk levels | + +### `quoted-value` + +| Property | Value | +| ---------------- | -------------------------------------------------------------- | +| Description | String in quotes (preserves spaces) | +| Parsing Behavior | Extracts content between quotes; preserves internal whitespace | +| Example | `@libar-docs-usecase "When a user submits a form"` | +| Notes | Use for human-readable text with spaces | + +### `csv` + +| Property | Value | +| ---------------- | ----------------------------------------------------- | +| Description | Comma-separated values | +| Parsing Behavior | Splits on commas; trims whitespace from each value | +| Example | `@libar-docs-uses CommandBus, EventStore, Projection` | +| Notes | Used for relationship tags and multi-value references | + +### `number` + +| Property | Value | +| ---------------- | ----------------------------------- | +| Description | Numeric value | +| Parsing Behavior | Parses as integer; NaN if invalid | +| Example | `@libar-docs-phase 14` | +| Notes | Used for phase numbers and ordering | + +### `flag` + +| Property | Value | +| ---------------- | ------------------------------------------------------- | +| Description | Boolean presence (no value needed) | +| Parsing Behavior | Presence of tag indicates true; absence indicates false | +| Example | `@libar-docs-core` | +| Notes | Used for boolean markers like core, overview, decision | + +--- + +[Back to Taxonomy Reference](../TAXONOMY.md) diff --git a/docs-live/taxonomy/metadata-tags.md b/docs-live/taxonomy/metadata-tags.md new file mode 100644 index 00000000..14a70eff --- /dev/null +++ b/docs-live/taxonomy/metadata-tags.md @@ -0,0 +1,649 @@ +# Metadata Tag Reference + +**Purpose:** Complete metadata tag definitions with all fields + +--- + +## Metadata Tag Definitions + +56 metadata tags with full details. + +| Tag | Format | Purpose | Required | Repeatable | Values | Default | +| ------------------------ | ------------ | -------------------------------------------------------------------------- | -------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | +| `pattern` | value | Explicit pattern name | Yes | No | - | - | +| `status` | enum | Work item lifecycle status (per PDR-005 FSM) | No | No | roadmap, active, completed, deferred | roadmap | +| `core` | flag | Marks as essential/must-know pattern | No | No | - | - | +| `usecase` | quoted-value | Use case association | No | Yes | - | - | +| `uses` | csv | Patterns this depends on | No | No | - | - | +| `used-by` | csv | Patterns that depend on this | No | No | - | - | +| `phase` | number | Roadmap phase number (unified across monorepo) | No | No | - | - | +| `release` | value | Target release version (semver or vNEXT for unreleased work) | No | No | - | - | +| `brief` | value | Path to pattern brief markdown | No | No | - | - | +| `depends-on` | csv | Roadmap dependencies (pattern or phase names) | No | No | - | - | +| `enables` | csv | Patterns this enables | No | No | - | - | +| `implements` | csv | Patterns this code file realizes (realization relationship) | No | No | - | - | +| `extends` | value | Base pattern this pattern extends (generalization relationship) | No | No | - | - | +| `quarter` | value | Delivery quarter for timeline tracking | No | No | - | - | +| `completed` | value | Completion date (YYYY-MM-DD format) | No | No | - | - | +| `effort` | value | Estimated effort (4h, 2d, 1w format) | No | No | - | - | +| `effort-actual` | value | Actual effort spent (4h, 2d, 1w format) | No | No | - | - | +| `team` | value | Responsible team assignment | No | No | - | - | +| `workflow` | enum | Workflow discipline for process tracking | No | No | implementation, planning, validation, documentation | - | +| `risk` | enum | Risk level for planning | No | No | low, medium, high | - | +| `priority` | enum | Priority level for roadmap ordering | No | No | critical, high, medium, low | - | +| `product-area` | value | Product area for PRD grouping | No | No | - | - | +| `user-role` | value | Target user persona for this feature | No | No | - | - | +| `business-value` | value | Business value statement (hyphenated for tag format) | No | No | - | - | +| `constraint` | value | Technical constraint affecting feature implementation | No | Yes | - | - | +| `adr` | value | ADR/PDR number for decision tracking | No | No | - | - | +| `adr-status` | enum | ADR/PDR decision status | No | No | proposed, accepted, deprecated, superseded | proposed | +| `adr-category` | value | ADR/PDR category (architecture, process, tooling) | No | No | - | - | +| `adr-supersedes` | value | ADR/PDR number this decision supersedes | No | No | - | - | +| `adr-superseded-by` | value | ADR/PDR number that supersedes this decision | No | No | - | - | +| `adr-theme` | enum | Theme grouping for related decisions (from synthesis) | No | No | persistence, isolation, commands, projections, coordination, taxonomy, testing | - | +| `adr-layer` | enum | Evolutionary layer of the decision | No | No | foundation, infrastructure, refinement | - | +| `level` | enum | Hierarchy level for epic->phase->task breakdown | No | No | epic, phase, task | phase | +| `parent` | value | Parent pattern name in hierarchy (links tasks to phases, phases to epics) | No | No | - | - | +| `title` | quoted-value | Human-readable display title (supports quoted values with spaces) | No | No | - | - | +| `executable-specs` | csv | Links roadmap spec to package executable spec locations (PDR-007) | No | No | - | - | +| `roadmap-spec` | value | Links package spec back to roadmap pattern for traceability (PDR-007) | No | No | - | - | +| `behavior-file` | value | Path to behavior test feature file for traceability | No | No | - | - | +| `discovered-gap` | value | Gap identified during session retrospective | No | Yes | - | - | +| `discovered-improvement` | value | Improvement identified during session retrospective | No | Yes | - | - | +| `discovered-risk` | value | Risk identified during session retrospective | No | Yes | - | - | +| `discovered-learning` | value | Learning captured during session retrospective | No | Yes | - | - | +| `see-also` | csv | Related patterns for cross-reference without dependency implication | No | No | - | - | +| `api-ref` | csv | File paths to implementation APIs (replaces 'See:' Markdown text in Rules) | No | No | - | - | +| `extract-shapes` | csv | TypeScript type names to extract from this file for documentation | No | No | - | - | +| `shape` | value | Marks declaration as documentable shape, optionally with group name | No | No | - | - | +| `arch-role` | enum | Architectural role for diagram generation (component type) | No | No | bounded-context, command-handler, projection, saga, process-manager, infrastructure, repository, decider, read-model, service | - | +| `arch-context` | value | Bounded context this component belongs to (for subgraph grouping) | No | No | - | - | +| `arch-layer` | enum | Architectural layer for layered diagrams | No | No | domain, application, infrastructure | - | +| `include` | csv | Cross-cutting document inclusion for content routing and diagram scoping | No | No | - | - | +| `target` | value | Target implementation path for stub files | No | No | - | - | +| `since` | value | Design session that created this pattern | No | No | - | - | +| `convention` | csv | Convention domains for reference document generation from decision records | No | No | testing-policy, fsm-rules, cli-patterns, output-format, pattern-naming, session-workflow, config-presets, annotation-system, pipeline-architecture, publishing, doc-generation, taxonomy-rules, codec-registry, process-guard-errors | - | +| `claude-module` | value | Module identifier for CLAUDE.md module generation (becomes filename) | No | No | - | - | +| `claude-section` | enum | Target section directory in \_claude-md/ for module output | No | No | core, delivery-process, testing, infrastructure, workflow | - | +| `claude-tags` | csv | Variation filtering tags for modular-claude-md inclusion | No | No | - | - | + +## Tag Details + +### `pattern` + +| Property | Value | +| ---------- | ----------------------------------------- | +| Format | value | +| Purpose | Explicit pattern name | +| Required | Yes | +| Repeatable | No | +| Example | `@libar-docs-pattern CommandOrchestrator` | + +### `status` + +| Property | Value | +| ------------ | -------------------------------------------- | +| Format | enum | +| Purpose | Work item lifecycle status (per PDR-005 FSM) | +| Required | No | +| Repeatable | No | +| Valid Values | roadmap, active, completed, deferred | +| Default | roadmap | +| Example | `@libar-docs-status roadmap` | + +### `core` + +| Property | Value | +| ---------- | ------------------------------------ | +| Format | flag | +| Purpose | Marks as essential/must-know pattern | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-core` | + +### `usecase` + +| Property | Value | +| ---------- | ------------------------------------------------------ | +| Format | quoted-value | +| Purpose | Use case association | +| Required | No | +| Repeatable | Yes | +| Example | `@libar-docs-usecase "When handling command failures"` | + +### `uses` + +| Property | Value | +| ---------- | ----------------------------------------- | +| Format | csv | +| Purpose | Patterns this depends on | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-uses CommandBus, EventStore` | + +### `used-by` + +| Property | Value | +| ---------- | -------------------------------------- | +| Format | csv | +| Purpose | Patterns that depend on this | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-used-by SagaOrchestrator` | + +### `phase` + +| Property | Value | +| ---------- | ---------------------------------------------- | +| Format | number | +| Purpose | Roadmap phase number (unified across monorepo) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-phase 14` | + +### `release` + +| Property | Value | +| ---------- | ------------------------------------------------------------ | +| Format | value | +| Purpose | Target release version (semver or vNEXT for unreleased work) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-release v0.1.0` | + +### `brief` + +| Property | Value | +| ---------- | -------------------------------------------------- | +| Format | value | +| Purpose | Path to pattern brief markdown | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-brief docs/briefs/decider-pattern.md` | + +### `depends-on` + +| Property | Value | +| ---------- | ----------------------------------------------- | +| Format | csv | +| Purpose | Roadmap dependencies (pattern or phase names) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-depends-on EventStore, CommandBus` | + +### `enables` + +| Property | Value | +| ---------- | --------------------------------------------------------- | +| Format | csv | +| Purpose | Patterns this enables | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-enables SagaOrchestrator, ProjectionBuilder` | + +### `implements` + +| Property | Value | +| ---------- | --------------------------------------------------------------- | +| Format | csv | +| Purpose | Patterns this code file realizes (realization relationship) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-implements EventStoreDurability, IdempotentAppend` | + +### `extends` + +| Property | Value | +| ---------- | --------------------------------------------------------------- | +| Format | value | +| Purpose | Base pattern this pattern extends (generalization relationship) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-extends ProjectionCategories` | + +### `quarter` + +| Property | Value | +| ---------- | -------------------------------------- | +| Format | value | +| Purpose | Delivery quarter for timeline tracking | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-quarter Q1-2026` | + +### `completed` + +| Property | Value | +| ---------- | ----------------------------------- | +| Format | value | +| Purpose | Completion date (YYYY-MM-DD format) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-completed 2026-01-08` | + +### `effort` + +| Property | Value | +| ---------- | ------------------------------------ | +| Format | value | +| Purpose | Estimated effort (4h, 2d, 1w format) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-effort 2d` | + +### `effort-actual` + +| Property | Value | +| ---------- | --------------------------------------- | +| Format | value | +| Purpose | Actual effort spent (4h, 2d, 1w format) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-effort-actual 3d` | + +### `team` + +| Property | Value | +| ---------- | --------------------------- | +| Format | value | +| Purpose | Responsible team assignment | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-team platform` | + +### `workflow` + +| Property | Value | +| ------------ | --------------------------------------------------- | +| Format | enum | +| Purpose | Workflow discipline for process tracking | +| Required | No | +| Repeatable | No | +| Valid Values | implementation, planning, validation, documentation | +| Example | `@libar-docs-workflow implementation` | + +### `risk` + +| Property | Value | +| ------------ | ------------------------- | +| Format | enum | +| Purpose | Risk level for planning | +| Required | No | +| Repeatable | No | +| Valid Values | low, medium, high | +| Example | `@libar-docs-risk medium` | + +### `priority` + +| Property | Value | +| ------------ | ----------------------------------- | +| Format | enum | +| Purpose | Priority level for roadmap ordering | +| Required | No | +| Repeatable | No | +| Valid Values | critical, high, medium, low | +| Example | `@libar-docs-priority high` | + +### `product-area` + +| Property | Value | +| ---------- | --------------------------------------- | +| Format | value | +| Purpose | Product area for PRD grouping | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-product-area PlatformCore` | + +### `user-role` + +| Property | Value | +| ---------- | ------------------------------------ | +| Format | value | +| Purpose | Target user persona for this feature | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-user-role Developer` | + +### `business-value` + +| Property | Value | +| ---------- | --------------------------------------------------------------- | +| Format | value | +| Purpose | Business value statement (hyphenated for tag format) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-business-value eliminates-event-replay-complexity` | + +### `constraint` + +| Property | Value | +| ---------- | ----------------------------------------------------- | +| Format | value | +| Purpose | Technical constraint affecting feature implementation | +| Required | No | +| Repeatable | Yes | +| Example | `@libar-docs-constraint requires-convex-backend` | + +### `adr` + +| Property | Value | +| ---------- | ------------------------------------ | +| Format | value | +| Purpose | ADR/PDR number for decision tracking | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-adr 015` | + +### `adr-status` + +| Property | Value | +| ------------ | ------------------------------------------ | +| Format | enum | +| Purpose | ADR/PDR decision status | +| Required | No | +| Repeatable | No | +| Valid Values | proposed, accepted, deprecated, superseded | +| Default | proposed | +| Example | `@libar-docs-adr-status accepted` | + +### `adr-category` + +| Property | Value | +| ---------- | ------------------------------------------------- | +| Format | value | +| Purpose | ADR/PDR category (architecture, process, tooling) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-adr-category architecture` | + +### `adr-supersedes` + +| Property | Value | +| ---------- | --------------------------------------- | +| Format | value | +| Purpose | ADR/PDR number this decision supersedes | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-adr-supersedes 012` | + +### `adr-superseded-by` + +| Property | Value | +| ---------- | -------------------------------------------- | +| Format | value | +| Purpose | ADR/PDR number that supersedes this decision | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-adr-superseded-by 020` | + +### `adr-theme` + +| Property | Value | +| ------------ | ------------------------------------------------------------------------------ | +| Format | enum | +| Purpose | Theme grouping for related decisions (from synthesis) | +| Required | No | +| Repeatable | No | +| Valid Values | persistence, isolation, commands, projections, coordination, taxonomy, testing | +| Example | `@libar-docs-adr-theme persistence` | + +### `adr-layer` + +| Property | Value | +| ------------ | -------------------------------------- | +| Format | enum | +| Purpose | Evolutionary layer of the decision | +| Required | No | +| Repeatable | No | +| Valid Values | foundation, infrastructure, refinement | +| Example | `@libar-docs-adr-layer foundation` | + +### `level` + +| Property | Value | +| ------------ | ----------------------------------------------- | +| Format | enum | +| Purpose | Hierarchy level for epic->phase->task breakdown | +| Required | No | +| Repeatable | No | +| Valid Values | epic, phase, task | +| Default | phase | +| Example | `@libar-docs-level epic` | + +### `parent` + +| Property | Value | +| ---------- | ------------------------------------------------------------------------- | +| Format | value | +| Purpose | Parent pattern name in hierarchy (links tasks to phases, phases to epics) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-parent AggregateArchitecture` | + +### `title` + +| Property | Value | +| ---------- | ----------------------------------------------------------------- | +| Format | quoted-value | +| Purpose | Human-readable display title (supports quoted values with spaces) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-title:"Process Guard Linter"` | + +### `executable-specs` + +| Property | Value | +| ---------- | ----------------------------------------------------------------------- | +| Format | csv | +| Purpose | Links roadmap spec to package executable spec locations (PDR-007) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-executable-specs platform-decider/tests/features/behavior` | + +### `roadmap-spec` + +| Property | Value | +| ---------- | --------------------------------------------------------------------- | +| Format | value | +| Purpose | Links package spec back to roadmap pattern for traceability (PDR-007) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-roadmap-spec DeciderPattern` | + +### `behavior-file` + +| Property | Value | +| ---------- | ------------------------------------------------------- | +| Format | value | +| Purpose | Path to behavior test feature file for traceability | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-behavior-file behavior/my-pattern.feature` | + +### `discovered-gap` + +| Property | Value | +| ---------- | --------------------------------------------------- | +| Format | value | +| Purpose | Gap identified during session retrospective | +| Required | No | +| Repeatable | Yes | +| Example | `@libar-docs-discovered-gap missing-error-handling` | + +### `discovered-improvement` + +| Property | Value | +| ---------- | ------------------------------------------------------- | +| Format | value | +| Purpose | Improvement identified during session retrospective | +| Required | No | +| Repeatable | Yes | +| Example | `@libar-docs-discovered-improvement cache-invalidation` | + +### `discovered-risk` + +| Property | Value | +| ---------- | ---------------------------------------------------- | +| Format | value | +| Purpose | Risk identified during session retrospective | +| Required | No | +| Repeatable | Yes | +| Example | `@libar-docs-discovered-risk data-loss-on-migration` | + +### `discovered-learning` + +| Property | Value | +| ---------- | -------------------------------------------------------- | +| Format | value | +| Purpose | Learning captured during session retrospective | +| Required | No | +| Repeatable | Yes | +| Example | `@libar-docs-discovered-learning convex-mutation-limits` | + +### `see-also` + +| Property | Value | +| ---------- | --------------------------------------------------------------------- | +| Format | csv | +| Purpose | Related patterns for cross-reference without dependency implication | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-see-also AgentAsBoundedContext, CrossContextIntegration` | + +### `api-ref` + +| Property | Value | +| ---------- | -------------------------------------------------------------------------- | +| Format | csv | +| Purpose | File paths to implementation APIs (replaces 'See:' Markdown text in Rules) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-api-ref @libar-dev/platform-core/src/durability/outbox.ts` | + +### `extract-shapes` + +| Property | Value | +| ---------- | ----------------------------------------------------------------------------- | +| Format | csv | +| Purpose | TypeScript type names to extract from this file for documentation | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-extract-shapes DeciderInput, ValidationResult, ProcessViolation` | + +### `shape` + +| Property | Value | +| ---------- | ------------------------------------------------------------------- | +| Format | value | +| Purpose | Marks declaration as documentable shape, optionally with group name | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-shape api-types` | + +### `arch-role` + +| Property | Value | +| ------------ | ----------------------------------------------------------------------------------------------------------------------------- | +| Format | enum | +| Purpose | Architectural role for diagram generation (component type) | +| Required | No | +| Repeatable | No | +| Valid Values | bounded-context, command-handler, projection, saga, process-manager, infrastructure, repository, decider, read-model, service | +| Example | `@libar-docs-arch-role projection` | + +### `arch-context` + +| Property | Value | +| ---------- | ----------------------------------------------------------------- | +| Format | value | +| Purpose | Bounded context this component belongs to (for subgraph grouping) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-arch-context orders` | + +### `arch-layer` + +| Property | Value | +| ------------ | ---------------------------------------- | +| Format | enum | +| Purpose | Architectural layer for layered diagrams | +| Required | No | +| Repeatable | No | +| Valid Values | domain, application, infrastructure | +| Example | `@libar-docs-arch-layer application` | + +### `include` + +| Property | Value | +| ---------- | ------------------------------------------------------------------------ | +| Format | csv | +| Purpose | Cross-cutting document inclusion for content routing and diagram scoping | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-include reference-sample,codec-system` | + +### `target` + +| Property | Value | +| ---------- | --------------------------------------------- | +| Format | value | +| Purpose | Target implementation path for stub files | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-target src/api/stub-resolver.ts` | + +### `since` + +| Property | Value | +| ---------- | ---------------------------------------- | +| Format | value | +| Purpose | Design session that created this pattern | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-since DS-A` | + +### `convention` + +| Property | Value | +| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Format | csv | +| Purpose | Convention domains for reference document generation from decision records | +| Required | No | +| Repeatable | No | +| Valid Values | testing-policy, fsm-rules, cli-patterns, output-format, pattern-naming, session-workflow, config-presets, annotation-system, pipeline-architecture, publishing, doc-generation, taxonomy-rules, codec-registry, process-guard-errors | +| Example | `@libar-docs-convention fsm-rules, testing-policy` | + +### `claude-module` + +| Property | Value | +| ---------- | -------------------------------------------------------------------- | +| Format | value | +| Purpose | Module identifier for CLAUDE.md module generation (becomes filename) | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-claude-module process-guard` | + +### `claude-section` + +| Property | Value | +| ------------ | ---------------------------------------------------------- | +| Format | enum | +| Purpose | Target section directory in \_claude-md/ for module output | +| Required | No | +| Repeatable | No | +| Valid Values | core, delivery-process, testing, infrastructure, workflow | +| Example | `@libar-docs-claude-section delivery-process` | + +### `claude-tags` + +| Property | Value | +| ---------- | ---------------------------------------------------------- | +| Format | csv | +| Purpose | Variation filtering tags for modular-claude-md inclusion | +| Required | No | +| Repeatable | No | +| Example | `@libar-docs-claude-tags core-mandatory, delivery-process` | + +--- + +[Back to Taxonomy Reference](../TAXONOMY.md) diff --git a/docs-live/validation/error-catalog.md b/docs-live/validation/error-catalog.md new file mode 100644 index 00000000..7f6e28b0 --- /dev/null +++ b/docs-live/validation/error-catalog.md @@ -0,0 +1,78 @@ +# Error Catalog + +**Purpose:** Complete error message reference with fix instructions + +--- + +## Error Catalog + +Complete error messages and fix instructions for all 6 validation rules. + +| Rule ID | Severity | Description | +| --------------------------- | -------- | --------------------------------------------------- | +| `completed-protection` | error | Completed specs require unlock-reason tag to modify | +| `invalid-status-transition` | error | Status transitions must follow FSM path | +| `scope-creep` | error | Active specs cannot add new deliverables | +| `session-scope` | warning | File outside session scope | +| `session-excluded` | error | File explicitly excluded from session | +| `deliverable-removed` | warning | Deliverable was removed from spec | + +## Rule Details + +### `completed-protection` + +| Property | Value | +| ----------- | ------------------------------------------------------------------ | +| Severity | error | +| Description | Completed specs require unlock-reason tag to modify | +| Cause | File has `completed` status but no `@libar-docs-unlock-reason` tag | +| Fix | Add `@libar-docs-unlock-reason:'your reason'` to proceed | + +### `invalid-status-transition` + +| Property | Value | +| ----------- | ---------------------------------------------------- | +| Severity | error | +| Description | Status transitions must follow FSM path | +| Cause | Attempted transition not in VALID_TRANSITIONS matrix | +| Fix | Follow path: roadmap -> active -> completed | + +### `scope-creep` + +| Property | Value | +| ----------- | --------------------------------------------------- | +| Severity | error | +| Description | Active specs cannot add new deliverables | +| Cause | Added deliverable to spec with `active` status | +| Fix | Create new spec OR revert to `roadmap` status first | + +### `session-scope` + +| Property | Value | +| ----------- | --------------------------------------------------- | +| Severity | warning | +| Description | File outside session scope | +| Cause | Modified file not in session's scopedSpecs list | +| Fix | Add to session scope OR use `--ignore-session` flag | + +### `session-excluded` + +| Property | Value | +| ----------- | ---------------------------------------------- | +| Severity | error | +| Description | File explicitly excluded from session | +| Cause | File in session's excludedSpecs list | +| Fix | Remove from exclusion OR use different session | + +### `deliverable-removed` + +| Property | Value | +| ----------- | --------------------------------------------------- | +| Severity | warning | +| Description | Deliverable was removed from spec | +| Cause | Deliverable removed from Background table | +| Fix | Document reason for removal (completed or descoped) | + +--- + +[Back to Validation Rules](../VALIDATION-RULES.md) diff --git a/docs-live/validation/fsm-transitions.md b/docs-live/validation/fsm-transitions.md new file mode 100644 index 00000000..62512d5f --- /dev/null +++ b/docs-live/validation/fsm-transitions.md @@ -0,0 +1,50 @@ +# FSM Transitions + +**Purpose:** Complete state transition reference for Process Guard FSM + +--- + +## FSM Transition Matrix + +Complete transition matrix showing all valid state changes per PDR-005. + +| From | To | Description | +| ----------- | ----------- | -------------------------------------- | +| `roadmap` | `active` | Start implementation work | +| `roadmap` | `deferred` | Park work for later | +| `roadmap` | `roadmap` | Stay in planning (self-transition) | +| `active` | `completed` | Finish implementation | +| `active` | `roadmap` | Regress due to blocker or scope change | +| `completed` | (none) | Terminal state - no valid transitions | +| `deferred` | `roadmap` | Reactivate deferred work | + +## Transitions by State + +### From `roadmap` + +| Target | Description | +| ---------- | ---------------------------------- | +| `active` | Start implementation work | +| `deferred` | Park work for later | +| `roadmap` | Stay in planning (self-transition) | + +### From `active` + +| Target | Description | +| ----------- | -------------------------------------- | +| `completed` | Finish implementation | +| `roadmap` | Regress due to blocker or scope change | + +### From `completed` + +**Terminal state** - no valid transitions. Use `@libar-docs-unlock-reason` to modify. + +### From `deferred` + +| Target | Description | +| --------- | ------------------------ | +| `roadmap` | Reactivate deferred work | + +--- + +[Back to Validation Rules](../VALIDATION-RULES.md) diff --git a/docs-live/validation/protection-levels.md b/docs-live/validation/protection-levels.md new file mode 100644 index 00000000..f97043e9 --- /dev/null +++ b/docs-live/validation/protection-levels.md @@ -0,0 +1,51 @@ +# Protection Levels + +**Purpose:** Detailed protection level reference per PDR-005 + +--- + +## Protection Levels + +Detailed explanation of protection levels per PDR-005 MVP Workflow. + +| Level | Applies To | Meaning | +| ------- | --------------------- | ----------------------------------------------- | +| `none` | `roadmap`, `deferred` | Fully editable, no restrictions | +| `scope` | `active` | Scope-locked, prevents adding new deliverables | +| `hard` | `completed` | Hard-locked, requires explicit unlock to modify | + +## Level Details + +### `none` Protection + +**Applies to:** `roadmap`, `deferred` + +| Aspect | Description | +| ------- | --------------------------------------------------- | +| Meaning | Fully editable, no restrictions | +| Allowed | All modifications including adding new deliverables | +| Blocked | Nothing | + +### `scope` Protection + +**Applies to:** `active` + +| Aspect | Description | +| ------- | ---------------------------------------------- | +| Meaning | Scope-locked, prevents adding new deliverables | +| Allowed | Edit existing deliverables, change status | +| Blocked | Adding new deliverables (scope creep) | + +### `hard` Protection + +**Applies to:** `completed` + +| Aspect | Description | +| ------- | ----------------------------------------------- | +| Meaning | Hard-locked, requires explicit unlock to modify | +| Allowed | Nothing (without unlock-reason tag) | +| Blocked | All modifications | + +--- + +[Back to Validation Rules](../VALIDATION-RULES.md) diff --git a/docs-sources/annotation-guide.md b/docs-sources/annotation-guide.md new file mode 100644 index 00000000..7d0898ce --- /dev/null +++ b/docs-sources/annotation-guide.md @@ -0,0 +1,137 @@ +## Getting Started + +Every file that participates in the annotation system must have a `@libar-docs` opt-in marker. Files without this marker are invisible to the scanner. + +### File-Level Opt-In + +**TypeScript** -- file-level JSDoc block: + +```typescript +/** + * @libar-docs + * @libar-docs-pattern MyPattern + * @libar-docs-status roadmap + * @libar-docs-uses EventStore, CommandBus + * + * ## My Pattern - Description + */ +``` + +**Gherkin** -- file-level tags before `Feature:`: + +```gherkin +@libar-docs +@libar-docs-pattern:MyPattern +@libar-docs-status:roadmap +@libar-docs-phase:14 +Feature: My Pattern + + **Problem:** + Description of the problem. +``` + +### Tag Prefix by Preset + +| Preset | Prefix | Categories | Use Case | +| ------------------------- | -------------- | ---------- | ----------------------------- | +| `libar-generic` (default) | `@libar-docs-` | 3 | Simple projects | +| `ddd-es-cqrs` | `@libar-docs-` | 21 | DDD/Event Sourcing monorepos | +| `generic` | `@docs-` | 3 | Simple projects, short prefix | + +### Dual-Source Ownership + +| Source | Owns | Example Tags | +| -------------- | ----------------------------------------------- | -------------------------------------------- | +| **TypeScript** | Implementation: runtime deps, category, shapes | `uses`, `used-by`, `extract-shapes`, `shape` | +| **Gherkin** | Planning: status, phase, timeline, dependencies | `status`, `phase`, `depends-on`, `quarter` | + +--- + +## Shape Extraction + +Shape extraction pulls TypeScript type definitions (interfaces, type aliases, enums, functions, consts) into generated documentation. There are three modes: + +### Mode 1: File-Level Explicit Names + +List specific declaration names in the file-level JSDoc: + +```typescript +/** + * @libar-docs + * @libar-docs-extract-shapes MasterDatasetSchema, StatusGroupsSchema + */ +``` + +Names appear in the generated output in the order listed. + +### Mode 2: File-Level Wildcard + +```typescript +/** + * @libar-docs + * @libar-docs-extract-shapes * + */ +``` + +Wildcard must be the sole value -- `*, Foo` is invalid. + +### Mode 3: Declaration-Level Tagging + +Tag individual declarations with `@libar-docs-shape`, optionally with a group name: + +```typescript +/** @libar-docs-shape api-types */ +export interface CommandInput { + readonly aggregateId: string; + readonly payload: unknown; +} +``` + +The optional group name (`api-types`) enables filtering in diagram scopes and product area documents via `@libar-docs-include`. + +--- + +## Critical Gotcha: Zod Schemas + +For Zod files, extract the **schema constant** (with `Schema` suffix), not the inferred type alias: + +| Wrong (type alias) | Correct (schema constant) | +| ---------------------------------------- | ----------------------------------------- | +| `@extract-shapes MasterDataset` | `@extract-shapes MasterDatasetSchema` | +| Shows: `z.infer` (unhelpful) | Shows: `z.object({...})` (full structure) | + +--- + +## Verification + +### CLI Commands + +```bash +# Tag usage inventory (counts per tag and value) +pnpm process:query -- tags + +# Find files missing @libar-docs opt-in marker +pnpm process:query -- unannotated --path src/types + +# File inventory by type (TS, Gherkin, Stubs) +pnpm process:query -- sources + +# Full pattern JSON including extractedShapes +pnpm process:query -- query getPattern MyPattern + +# Generate complete tag reference +npx generate-tag-taxonomy -o TAG_TAXONOMY.md -f +``` + +--- + +## Common Issues + +| Symptom | Cause | Fix | +| ------------------------------- | ----------------------------------- | ------------------------------------------------ | +| Pattern not in scanner output | Missing `@libar-docs` opt-in marker | Add file-level `@libar-docs` JSDoc/tag | +| Shape shows `z.infer<>` wrapper | Extracted type alias, not schema | Use schema constant name (e.g., `FooSchema`) | +| Shape not in product area doc | Missing `@libar-docs-product-area` | Add product-area tag to file-level annotation | +| Declaration-level shape missing | No `@libar-docs-shape` on decl | Add `@libar-docs-shape` JSDoc to the declaration | +| Tag value rejected | Wrong format or invalid enum value | Check format type in taxonomy reference | +| Anti-pattern validation error | Tag on wrong source type | Move tag to correct source (TS vs Gherkin) | diff --git a/docs-sources/index-navigation.md b/docs-sources/index-navigation.md new file mode 100644 index 00000000..bf49f554 --- /dev/null +++ b/docs-sources/index-navigation.md @@ -0,0 +1,78 @@ +## Quick Navigation + +| If you want to... | Read this | +| ------------------------------ | --------------------------------------------------------------- | +| Learn the architecture | [ARCHITECTURE.md](ARCHITECTURE.md) | +| Browse product area overviews | [PRODUCT-AREAS.md](PRODUCT-AREAS.md) | +| Review architecture decisions | [DECISIONS.md](DECISIONS.md) | +| Check business rules | [BUSINESS-RULES.md](BUSINESS-RULES.md) | +| Understand the tag taxonomy | [TAXONOMY.md](TAXONOMY.md) | +| Check validation rules | [VALIDATION-RULES.md](VALIDATION-RULES.md) | +| Browse the changelog | [CHANGELOG-GENERATED.md](CHANGELOG-GENERATED.md) | +| Query process state via CLI | [Process API Reference](reference/PROCESS-API-REFERENCE.md) | +| Find CLI workflow recipes | [Process API Recipes](reference/PROCESS-API-RECIPES.md) | +| Run AI coding sessions | [Session Workflow Guide](reference/SESSION-WORKFLOW-GUIDE.md) | +| Enforce delivery process rules | [Process Guard Reference](reference/PROCESS-GUARD-REFERENCE.md) | +| Learn annotation mechanics | [Annotation Reference](reference/ANNOTATION-REFERENCE.md) | +| See codec patterns and options | [Architecture Codecs](reference/ARCHITECTURE-CODECS.md) | +| Understand MasterDataset types | [Architecture Types](reference/ARCHITECTURE-TYPES.md) | + +--- + +## Reading Order + +### Overview + +1. **[ARCHITECTURE.md](ARCHITECTURE.md)** -- Architecture diagram from source annotations +2. **[PRODUCT-AREAS.md](PRODUCT-AREAS.md)** -- Product area overviews with live statistics and diagrams +3. **[TAXONOMY.md](TAXONOMY.md)** -- Tag taxonomy configuration and format types + +### Deep Dive + +4. **[DECISIONS.md](DECISIONS.md)** -- Architecture Decision Records extracted from specs +5. **[BUSINESS-RULES.md](BUSINESS-RULES.md)** -- Domain constraints and invariants from feature files +6. **[VALIDATION-RULES.md](VALIDATION-RULES.md)** -- Process Guard validation rules and FSM reference + +### Reference Guides + +7. **[Annotation Reference](reference/ANNOTATION-REFERENCE.md)** -- Annotation mechanics and tag reference +8. **[Session Workflow Guide](reference/SESSION-WORKFLOW-GUIDE.md)** -- Planning, Design, Implementation workflows +9. **[Process API Reference](reference/PROCESS-API-REFERENCE.md)** -- CLI command reference with flags and examples +10. **[Process Guard Reference](reference/PROCESS-GUARD-REFERENCE.md)** -- Pre-commit hooks, error codes, programmatic API + +--- + +## Document Roles + +| Document | Audience | Focus | +| ----------------------- | ---------- | ------------------------------------------------ | +| ARCHITECTURE.md | Developers | Architecture diagram from source annotations | +| PRODUCT-AREAS.md | Everyone | Product area overviews with live statistics | +| DECISIONS.md | Developers | Architecture Decision Records | +| BUSINESS-RULES.md | Developers | Domain constraints and invariants | +| TAXONOMY.md | Reference | Tag taxonomy structure and format types | +| VALIDATION-RULES.md | CI/CD | Process Guard validation rules and FSM reference | +| CHANGELOG-GENERATED.md | Everyone | Project changelog from release specs | +| Annotation Reference | Developers | Annotation mechanics, shape extraction | +| Session Workflow Guide | AI/Devs | Session decision trees and workflow checklists | +| Process API Reference | AI/Devs | CLI command reference with flags and examples | +| Process API Recipes | AI/Devs | CLI workflow recipes and session guides | +| Process Guard Reference | Team Leads | Pre-commit hooks, error codes, programmatic API | +| Architecture Codecs | Developers | All codecs with factory patterns and options | +| Architecture Types | Developers | MasterDataset interface and type shapes | + +--- + +## Key Concepts + +**Delivery Process** -- A code-first documentation and workflow toolkit. Extracts patterns from annotated TypeScript and Gherkin sources, generates markdown documentation, and validates delivery workflow via pre-commit hooks. + +**Pattern** -- An annotated unit of work tracked by the delivery process. Each pattern has a status (roadmap, active, completed, deferred), belongs to a product area, and has deliverables. Patterns are the atomic unit of the MasterDataset. + +**MasterDataset** -- The single read model (ADR-006) containing all extracted patterns with pre-computed views (byProductArea, byPhase, byStatus, byCategory). All codecs and the Data API consume this dataset. + +**Codec** -- A Zod-based transformer that decodes MasterDataset into a RenderableDocument. Each codec produces a specific document type. Codecs are pure functions with no I/O. + +**Dual-Source Architecture** -- Feature files own planning metadata (status, phase, dependencies). TypeScript files own implementation metadata (uses, used-by, category). This split prevents ownership conflicts. + +**Delivery Workflow FSM** -- A finite state machine enforcing pattern lifecycle: roadmap -> active -> completed. Transitions are validated by Process Guard at commit time. diff --git a/docs-sources/process-api-recipes.md b/docs-sources/process-api-recipes.md new file mode 100644 index 00000000..f15d03be --- /dev/null +++ b/docs-sources/process-api-recipes.md @@ -0,0 +1,55 @@ +## Why Use This + +Traditional approach: read generated Markdown, parse it mentally, hope it's current. This CLI queries the **same annotated sources** that generate those docs -- in real time, with typed output. + +| Approach | Context Cost | Accuracy | Speed | +| ------------------------ | ------------ | --------------------- | ------- | +| Parse generated Markdown | High | Snapshot at gen time | Slow | +| **Data API CLI** | **Low** | Real-time from source | Instant | + +The CLI has two output modes: + +- **Text commands** (6) -- formatted for terminal reading or AI context. Use `===` section markers for structure. +- **JSON commands** (12+) -- wrapped in a `QueryResult` envelope. Pipeable to `jq`. + +Run `process-api --help` for the full command reference with all flags and 26 available API methods. + +## Quick Start + +The recommended session startup is three commands: + +```bash +pnpm process:query -- overview +pnpm process:query -- scope-validate MyPattern implement +pnpm process:query -- context MyPattern --session implement +``` + +Example `overview` output: + +```text +=== PROGRESS === +318 patterns (224 completed, 47 active, 47 planned) = 70% + +=== ACTIVE PHASES === +Phase 24: ProcessStateAPIRelationshipQueries (1 active) +Phase 25: DataAPIStubIntegration (1 active) + +=== BLOCKING === +StepLintExtendedRules blocked by: StepLintVitestCucumber + +=== DATA API === +pnpm process:query -- + overview, context, scope-validate, dep-tree, list, stubs, files, rules, arch blocking +``` + +## Session Types + +The `--session` flag tailors output to what you need right now: + +| Type | Includes | When to Use | +| ----------- | -------------------------------------------- | ---------------------------------- | +| `planning` | Pattern metadata and spec file only | Creating a new roadmap spec | +| `design` | Full: metadata, stubs, deps, deliverables | Making architectural decisions | +| `implement` | Focused: deliverables, FSM state, test files | Writing code from an existing spec | + +**Decision tree:** Starting to code? `implement`. Complex decisions? `design`. New pattern? `planning`. Not sure? Run `overview` first. diff --git a/docs-sources/session-workflow-guide.md b/docs-sources/session-workflow-guide.md new file mode 100644 index 00000000..9f2aa185 --- /dev/null +++ b/docs-sources/session-workflow-guide.md @@ -0,0 +1,152 @@ +## Session Decision Tree + +Use this flowchart to determine which session type to run. + +```mermaid +graph TD + A[Starting from pattern brief?] -->|Yes| B[Need code stubs now?] + A -->|No| C[Ready to code?] + B -->|Yes| D[Planning + Design Session] + B -->|No| E[Planning Session] + C -->|Yes| F[Complex decisions?] + C -->|No| E + F -->|Yes| G[Design Session] + F -->|No| H[Implementation Session] + + style D fill:#e1f5fe + style E fill:#e8f5e9 + style G fill:#fff3e0 + style H fill:#fce4ec +``` + +## Session Type Contracts + +| Session | Input | Output | FSM Change | +| ----------------- | ------------------- | --------------------------- | ------------------------------------ | +| Planning | Pattern brief | Roadmap spec (`.feature`) | Creates `roadmap` | +| Design | Complex requirement | Decision specs + code stubs | None | +| Implementation | Roadmap spec | Code + tests | `roadmap` -> `active` -> `completed` | +| Planning + Design | Pattern brief | Spec + stubs | Creates `roadmap` | + +--- + +## Implementation Execution Order + +Implementation sessions MUST follow this strict 5-step sequence. Skipping steps causes Process Guard rejection at commit time. + +1. **Transition to `active` FIRST** (before any code changes) +2. **Create executable spec stubs** (if `@libar-docs-executable-specs` present) +3. **For each deliverable:** implement, test, update status to `complete` +4. **Transition to `completed`** (only when ALL deliverables done) +5. **Regenerate docs:** `pnpm docs:all` + +### Implementation Do NOT + +| Do NOT | Why | +| ----------------------------------- | --------------------------------------- | +| Add new deliverables to active spec | Scope-locked state prevents scope creep | +| Mark completed with incomplete work | Hard-locked state cannot be undone | +| Skip FSM transitions | Process Guard will reject | +| Edit generated docs directly | Regenerate from source | + +--- + +## Planning Session + +**Goal:** Create a roadmap spec. Do not write implementation code. + +### Context Gathering + +```bash +pnpm process:query -- overview # Project health +pnpm process:query -- list --status roadmap --names-only # Available patterns +``` + +### Planning Checklist + +- [ ] **Extract metadata** from pattern brief: phase, dependencies, status +- [ ] **Create spec file** at `{specs-directory}/{product-area}/{pattern}.feature` +- [ ] **Structure the feature** with Problem/Solution, tags, deliverables table +- [ ] **Convert constraints to Rule: blocks** with Invariant/Rationale +- [ ] **Add scenarios** per Rule: 1 happy-path + 1 validation minimum +- [ ] **Set executable specs location** via `@libar-docs-executable-specs` tag + +### Planning Do NOT + +- Create `.ts` implementation files +- Transition to `active` +- Ask "Ready to implement?" + +--- + +## Design Session + +**Goal:** Make architectural decisions. Create code stubs with interfaces. Do not implement. + +### Context Gathering + +```bash +pnpm process:query -- context --session design # Full context bundle +pnpm process:query -- dep-tree # Dependency chain +pnpm process:query -- stubs # Existing design stubs +``` + +### When to Use Design Sessions + +| Use Design Session | Skip Design Session | +| -------------------------- | ------------------- | +| Multiple valid approaches | Single obvious path | +| New patterns/capabilities | Bug fix | +| Cross-context coordination | Clear requirements | + +### Design Checklist + +- [ ] **Record decisions** as PDR `.feature` files in `delivery-process/decisions/` +- [ ] **Document options** with at least 2-3 approaches and pros/cons +- [ ] **Get approval** from user on recommended approach +- [ ] **Create code stubs** in `delivery-process/stubs/{pattern-name}/` +- [ ] **Verify stub identifier spelling** before committing +- [ ] **List canonical helpers** in `@libar-docs-uses` tags + +### Design Do NOT + +- Create markdown design documents (use decision specs instead) +- Create implementation plans +- Transition spec to `active` +- Write full implementations (stubs only) + +--- + +## Planning + Design Session + +**Goal:** Create spec AND code stubs in one session. For immediate implementation handoff. + +### When to Use + +| Use Planning + Design | Use Planning Only | +| ----------------------------------- | ---------------------------- | +| Need stubs for implementation | Only enhancing spec | +| Preparing for immediate handoff | Still exploring requirements | +| Want complete two-tier architecture | Don't need Tier 2 yet | + +--- + +## Handoff Documentation + +For multi-session work, capture state at session boundaries using the Process Data API. + +```bash +pnpm process:query -- handoff --pattern +pnpm process:query -- handoff --pattern --git # include recent commits +``` + +--- + +## Quick Reference: FSM Protection + +| State | Protection | Can Add Deliverables | Needs Unlock | +| ----------- | ------------ | -------------------- | ------------ | +| `roadmap` | None | Yes | No | +| `active` | Scope-locked | No | No | +| `completed` | Hard-locked | No | Yes | +| `deferred` | None | Yes | No | diff --git a/docs/ANNOTATION-GUIDE.md b/docs/ANNOTATION-GUIDE.md index cb271949..a1609583 100644 --- a/docs/ANNOTATION-GUIDE.md +++ b/docs/ANNOTATION-GUIDE.md @@ -1,5 +1,9 @@ # Annotation Guide +> **Generated Reference Available:** Comprehensive annotation reference with +> tag tables and conventions is generated at `docs-live/reference/ANNOTATION-REFERENCE.md`. +> Run `pnpm docs:all` to regenerate. + How to annotate TypeScript and Gherkin files for pattern extraction, documentation generation, and architecture diagrams. For the **complete tag reference** (all 50+ tags with formats, values, and examples), generate the taxonomy: `npx generate-tag-taxonomy -o TAG_TAXONOMY.md -f` or see [TAXONOMY.md](./TAXONOMY.md) for the taxonomy architecture. @@ -192,6 +196,8 @@ Feature: Process Guard Linter ## Tag Groups Quick Reference +> For the complete tag reference with all values, see the [generated Taxonomy Reference](../docs-live/TAXONOMY.md). + Tags are organized into 12 functional groups. This table shows representative tags per group — for the **complete reference** with all formats, values, and examples, run `npx generate-tag-taxonomy -o TAG_TAXONOMY.md -f`. | Group | Tags (representative) | Format Types | diff --git a/docs/DOCS-GAP-ANALYSIS.md b/docs/DOCS-GAP-ANALYSIS.md new file mode 100644 index 00000000..070ac1ec --- /dev/null +++ b/docs/DOCS-GAP-ANALYSIS.md @@ -0,0 +1,811 @@ +# Documentation Gap Analysis: docs/ vs docs-live/ + +> **Purpose:** Input document for planning and design sessions to close the gap between +> manual reference docs (`docs/`) and auto-generated docs (`docs-live/`), ultimately +> enabling deprecation of manual docs when generated quality is sufficient. +> +> **Date:** 2026-03-06 +> **Branch:** feature/docs-consolidation (commit 223ace6) +> **Status:** Analysis complete, ready for spec authoring + +--- + +## Table of Contents + +1. [Executive Summary](#1-executive-summary) +2. [Related Specs & Prior Work](#2-related-specs--prior-work) +3. [Consolidation Mechanism](#3-consolidation-mechanism) +4. [Current State](#4-current-state) +5. [Website Publishing Pipeline](#5-website-publishing-pipeline) +6. [File-by-File Gap Analysis](#6-file-by-file-gap-analysis) +7. [Cross-Cutting Quality Gaps](#7-cross-cutting-quality-gaps) +8. [Unused Generation Capabilities](#8-unused-generation-capabilities) +9. [Website Sync Script Gaps](#9-website-sync-script-gaps) +10. [Recommended Work Packages](#10-recommended-work-packages) +11. [Prioritization Matrix](#11-prioritization-matrix) +12. [Appendix: File Inventories](#12-appendix-file-inventories) + +--- + +## 1. Executive Summary + +### The Goal + +Replace all 11 manual docs in `docs/` with auto-generated equivalents in `docs-live/` +of **equal or better quality**, enabling: + +- Zero manual documentation maintenance +- Single source of truth (annotated code drives everything) +- Automatic website publishing via the existing Starlight pipeline + +### Key Findings + +| Dimension | Current State | Gap | +| ------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------ | +| **Manual docs** | 11 files, ~4,537 lines | Curated editorial content, examples, decision trees | +| **Generated docs** | 48 files, ~20,548 lines | Comprehensive reference, but missing tutorials/guides/philosophy | +| **Website sync** | Reads from 3 dirs (`docs/`, `docs-live/`, `docs-generated/`) | `docs-generated/` is now empty after consolidation; sync script is stale | +| **Generation pipeline** | 22 codecs exist, only 8 run in `docs:all` | 14 codecs available but unused for published docs | +| **Content types missing** | N/A | How-to guides, decision trees, getting-started, philosophy, CI recipes | + +### The Core Challenge + +Manual docs contain three content types that current codecs cannot generate: + +1. **Editorial content** (philosophy, analogies, design rationale beyond Rule: blocks) +2. **Procedural guides** (step-by-step checklists, decision trees, CLI recipes) +3. **Integration patterns** (CI/CD setup, pre-commit hooks, GitHub Actions examples) + +These require either new codec capabilities or a hybrid approach where some +curated content is maintained alongside generated reference material. + +--- + +## 2. Related Specs & Prior Work + +### Master Roadmap: DocsConsolidationStrategy + +**Spec:** `delivery-process/specs/docs-consolidation-strategy.feature` +**Status:** roadmap | **Phase:** 35 | **Depends on:** CodecDrivenReferenceGeneration (completed) + +This is the **canonical plan** for the entire consolidation initiative. It defines a +6-phase strategy with 13 deliverables to replace ~5,400 lines of manual docs with +generated equivalents. Work packages in this gap analysis should map to its phases. + +**Deliverable Status (from spec Background):** + +| Deliverable | Status | Phase | Maps to WP | +| ------------------------------------------- | -------- | ----- | ----------------------------------------------- | +| Preamble capability on ReferenceDocConfig | complete | -- | N/A (done) | +| Phase 1 - Taxonomy consolidation | pending | 35 | Taxonomy deprecation | +| Phase 2 - Codec listings extraction | complete | 35 | N/A (done) | +| Phase 3 - Process Guard consolidation | pending | 35 | WP-5 | +| Phase 4 - Architecture decomposition | complete | 35 | N/A (done) | +| Phase 5 - Guide trimming | pending | 35 | WP-9 | +| Phase 6 - Index navigation update | pending | 35 | WP-2 | +| Phase 37 - docs-live/ consolidation | complete | 37 | N/A (done, commit 223ace6) | +| Phase 38 - Generated doc quality | pending | 38 | WP-9 | +| Phase 39 - Session workflow module gen | pending | 39 | Blocked on Phase 25 | +| Phase 40 - PUBLISHING.md relocation | complete | 40 | N/A (done) | +| Phase 41 - GHERKIN-PATTERNS.md restructure | pending | 41 | WP-7 | +| Phase 42 - README.md rationalization | pending | 42 | Not in this analysis | +| Phase 43 - PROCESS-API.md hybrid generation | complete | 43 | N/A (done); WP-6 extends with recipe generation | + +**Key Invariants from Spec:** + +1. **Convention tags are the primary consolidation mechanism** -- each phase registers a + convention tag, annotates sources, adds a ReferenceDocConfig entry, and replaces the + manual section with a pointer to generated output. +2. **Preamble preserves editorial context** -- `ReferenceDocConfig.preamble` accepts + `SectionBlock[]` prepended before generated content for introductory prose. +3. **Each phase is independently deliverable** -- no phase requires another to function. +4. **Manual docs retain editorial and tutorial content** -- ~2,300 lines of philosophy, + workflow guides, and tutorials stay manual. +5. **Audience alignment determines location** -- `docs/` for website users, repo root for + GitHub metadata, CLAUDE.md for AI sessions. + +### All Related Specs + +| Spec | Pattern | Status | Phase | Role in Gap Analysis | +| -------------------------------------------- | ------------------------------- | --------- | ----- | ------------------------------------------------ | +| `docs-consolidation-strategy.feature` | DocsConsolidationStrategy | roadmap | 35 | Master roadmap for all consolidation work | +| `docs-live-consolidation.feature` | DocsLiveConsolidation | completed | 37 | Established docs-live/ as single output dir | +| `publishing-relocation.feature` | PublishingRelocation | completed | 40 | Moved PUBLISHING.md to MAINTAINERS.md | +| `codec-driven-reference-generation.feature` | CodecDrivenReferenceGeneration | completed | 27 | Foundation: config-driven codec factory | +| `doc-generation-proof-of-concept.feature` | DocGenerationProofOfConcept | completed | 27 | Historical: ADR-021 POC (superseded) | +| `process-api-hybrid-generation.feature` | ProcessApiHybridGeneration | completed | 43 | CLI schema as single source for reference tables | +| `claude-module-generation.feature` | ClaudeModuleGeneration | completed | 25 | Claude module tags + behavior spec sourcing | +| `reference-doc-showcase.feature` | ReferenceDocShowcase | completed | 30 | All 9 content block types across 3 detail levels | +| `validator-read-model-consolidation.feature` | ValidatorReadModelConsolidation | completed | 100 | MasterDataset as single read model (ADR-006) | + +**Query these specs:** `pnpm process:query -- decisions DocsConsolidationStrategy` + +### Completed Foundation Work + +The following capabilities are already in place and available for new work: + +- **Config-driven codec factory** (`createReferenceCodec`) -- add a `ReferenceDocConfig` + entry and get detailed + summary docs automatically (CodecDrivenReferenceGeneration) +- **Preamble support** -- editorial prose can be prepended to any generated doc +- **3 detail levels** -- detailed, standard, summary from same codec (ReferenceDocShowcase) +- **9 content block types** -- headings, paragraphs, tables, code, mermaid, lists, sections, + metadata, collapsible (all exercised in REFERENCE-SAMPLE.md) +- **CLI schema extraction** -- `src/cli/cli-schema.ts` drives both help text and doc generation +- **Convention tag mechanism** -- `@libar-docs-convention` annotations compose into reference docs +- **Product area meta with diagram scopes** -- C4Context + graph LR per area + +--- + +## 3. Consolidation Mechanism + +Understanding how consolidation works is essential for design sessions. The mechanism +is defined in DocsConsolidationStrategy Rule 1 and implemented by CodecDrivenReferenceGeneration. + +### How Convention Tags Drive Generation + +``` +Step 1: Register convention tag value in src/taxonomy/conventions.ts + e.g., 'codec-registry', 'pipeline-architecture', 'taxonomy-rules' + +Step 2: Annotate source files with @libar-docs-convention: + TypeScript: JSDoc blocks with structured content + Gherkin: Rule: blocks with Invariant/Rationale markers + +Step 3: Add ReferenceDocConfig in delivery-process.config.ts + { + title: 'Available Codecs Reference', + conventionTags: ['codec-registry'], // <-- matches step 2 + docsFilename: 'ARCHITECTURE-CODECS.md', + claudeMdFilename: 'architecture-codecs.md', + claudeMdSection: 'architecture', + } + +Step 4: pnpm docs:all generates: + docs-live/reference/ARCHITECTURE-CODECS.md (detailed) + docs-live/_claude-md/architecture/architecture-codecs.md (summary) + +Step 5: Replace manual doc section with pointer to generated output +``` + +### Content Sources Available in ReferenceDocConfig + +| Source | Config Field | What It Produces | +| ---------------------- | --------------------------------- | ------------------------------------------------------------------------ | +| Convention annotations | `conventionTags` | Structured prose from JSDoc/Gherkin | +| Type shapes | `shapeSelectors` / `shapeSources` | TypeScript type definitions with field docs | +| Behavior specs | `behaviorCategories` | Rule invariants, scenarios, acceptance criteria | +| Diagrams | `diagramScopes` | Mermaid C4Context, graph LR, classDiagram, stateDiagram, sequenceDiagram | +| Include tags | `includeTags` | Filter patterns by tag for scoped reference | +| Editorial preamble | `preamble` | Hand-authored SectionBlock[] prepended to output | + +### Existing Convention Tags (from delivery-process.config.ts) + +| Tag Value | Used By | Produces | +| ----------------------- | ---------------------- | ------------------------------------ | +| `codec-registry` | ARCHITECTURE-CODECS.md | All 20 codecs with factory patterns | +| `pipeline-architecture` | ARCHITECTURE-TYPES.md | MasterDataset interface, shapes | +| `taxonomy-rules` | REFERENCE-SAMPLE.md | Tag rules + 6 diagram types showcase | + +### What This Means for New Work + +To consolidate a manual doc section, a design session needs to decide: + +1. **Which convention tag value** to register (or reuse existing) +2. **Which source files** to annotate with `@libar-docs-convention:` +3. **What content structure** the JSDoc/Gherkin annotations should use +4. **Which ReferenceDocConfig fields** to populate (shapes? diagrams? behaviors?) +5. **Whether preamble** is needed for editorial context that can't be annotated +6. **Output filenames** and whether to add a new website sync section + +This is a well-established pattern with 3 successful implementations. New phases +should follow the same recipe. + +--- + +## 4. Current State + +### Directory Layout After Commit 223ace6 + +``` +delivery-process/ + docs/ 11 manual files (~4,985 lines) -- human-authored reference + docs-live/ 48 generated files (~20,548 lines) -- auto-generated, committed + docs-generated/ empty after pnpm docs:all -- gitignored build cache + _claude-md/ 10 AI-optimized compacts -- composed into CLAUDE.md +``` + +### What `pnpm docs:all` Generates (9 generators) + +| Generator | Output Location | Files | Content | +| ----------------------- | ------------------------- | ----- | ------------------------------------------------ | +| `adrs` | docs-live/decisions/ | 8 | ADR index + 7 individual ADRs | +| `business-rules` | docs-live/business-rules/ | 8 | Overview + 7 area breakdowns (569 rules) | +| `taxonomy` | docs-live/taxonomy/ | 4 | Overview + categories, formats, metadata tags | +| `validation-rules` | docs-live/validation/ | 4 | Overview + error catalog, FSM, protection levels | +| `reference-docs` | docs-live/reference/ | 4 | Codecs, types, process-API ref, sample | +| `product-area-docs` | docs-live/product-areas/ | 8 | Overview + 7 area docs with diagrams | +| `claude-modules` | docs-live/\_claude-md/ | 10 | Compact AI context modules | +| `process-api-reference` | docs-live/reference/ | 1 | CLI command reference | +| `cli-recipe` | docs-live/reference/ | 1 | CLI recipes & workflow guide | + +### What `pnpm docs:all-preview` Adds (14 more generators) + +These exist and are functional but NOT in the standard build: + +| Generator | Would Produce | Potential Value for Website | +| ------------------ | -------------------------------- | ----------------------------- | +| `patterns` | PATTERNS.md + per-pattern detail | High -- pattern catalog | +| `roadmap` | ROADMAP.md + per-phase detail | Medium -- project status | +| `milestones` | COMPLETED-MILESTONES.md | Low -- internal tracking | +| `requirements` | PRODUCT-REQUIREMENTS.md | Medium -- feature specs | +| `session` | SESSION-CONTEXT.md | Low -- ephemeral session data | +| `remaining` | REMAINING-WORK.md | Low -- internal tracking | +| `current` | CURRENT-WORK.md | Low -- internal tracking | +| `session-plan` | SESSION-PLAN.md | Low -- ephemeral | +| `session-findings` | SESSION-FINDINGS.md | Low -- internal | +| `pr-changes` | PR-CHANGES.md | Low -- per-PR artifact | +| `changelog` | CHANGELOG-GENERATED.md | High -- release history | +| `traceability` | TRACEABILITY.md | Medium -- spec coverage | +| `architecture` | ARCHITECTURE.md | High -- architecture diagrams | +| `overview-rdm` | OVERVIEW.md | Medium -- project overview | + +--- + +## 5. Website Publishing Pipeline + +### Framework + +- **Astro + Starlight** (v0.37.6) with Mermaid rendering support +- Content synced at build time via `scripts/sync-content.mjs` +- Markdown processed: H1 stripped, frontmatter injected, links rewritten + +### Sync Script Architecture + +``` +sync-content.mjs + reads: content-manifest.mjs (section structure, link rewrites) + sources: + docs/ -> guides/ + reference/ (manual docs) + docs-live/ -> product-areas/ + decisions/ (generated) + docs-generated/ -> generated/ (business-rules, taxonomy) + output: src/content/docs/delivery-process/ +``` + +### Website Section Structure (from content-manifest.mjs) + +| Section | Directory | Source | Collapsed | +| ---------------------- | -------------- | ------------------------------------------ | --------- | +| Tutorial | tutorial/ | delivery-process-tutorials repo | No | +| Guides | guides/ | docs/ manual (5 files) | No | +| Reference | reference/ | docs/ manual (5 files) | No | +| Product Areas | product-areas/ | docs-live/product-areas/ | No | +| Architecture Decisions | decisions/ | docs-live/decisions/ | Yes | +| Generated Reference | generated/ | docs-generated/ (business-rules, taxonomy) | Yes | + +### CRITICAL: Sync Script is Stale After Consolidation + +The sync script (`sync-content.mjs`) has a **blocking issue**: + +| Problem | Detail | +| ---------------------------------------------- | --------------------------------------------------------------------------------------- | +| `docsGenerated` still required | Line 78-83: resolves `docs-generated/` as a source | +| Required source files expect `docs-generated/` | Lines 112-113: expects `BUSINESS-RULES.md` and `TAXONOMY.md` in `docs-generated/` | +| `syncGenerated()` reads from `docs-generated/` | Lines 456-503: business-rules, taxonomy, reference-sample synced from `docs-generated/` | +| **But `docs-generated/` is now empty** | After commit 223ace6, `pnpm docs:all` outputs everything to `docs-live/` | +| Impact | Website build will warn (non-strict) or fail (strict/CI) for business-rules + taxonomy | + +**Fix required:** Update sync script to read business-rules, taxonomy, validation, and +reference content from `docs-live/` instead of `docs-generated/`. + +### Content NOT Currently Synced to Website + +These `docs-live/` subdirectories exist but have no sync function: + +| Directory | Files | Content | +| ------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------- | +| `docs-live/reference/` | 5 files | ARCHITECTURE-CODECS.md, ARCHITECTURE-TYPES.md, PROCESS-API-RECIPES.md, PROCESS-API-REFERENCE.md, REFERENCE-SAMPLE.md | +| `docs-live/taxonomy/` | 3 files | categories.md, format-types.md, metadata-tags.md | +| `docs-live/validation/` | 3 files | error-catalog.md, fsm-transitions.md, protection-levels.md | +| `docs-live/business-rules/` | 7 files | Per-area business rule extractions | +| `docs-live/_claude-md/` | 10 files | AI context (may not need website publishing) | +| `docs-live/INDEX.md` | 1 file | Generated docs master index | +| `docs-live/TAXONOMY.md` | 1 file | Taxonomy overview | +| `docs-live/VALIDATION-RULES.md` | 1 file | Validation rules overview | +| `docs-live/BUSINESS-RULES.md` | 1 file | Business rules overview | + +--- + +## 6. File-by-File Gap Analysis + +### Legend + +- **Replacement Ready**: Generated equivalent exists and is comparable quality +- **Partial Coverage**: Generated docs cover some content, gaps remain +- **No Coverage**: No generated equivalent exists; content is editorial/procedural + +### docs/ Files vs docs-live/ Equivalents + +| Manual Doc | Lines | Generated Equivalent | Coverage | Gap Description | +| ----------------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **INDEX.md** | 353 | docs-live/INDEX.md (112 lines) | Partial | Manual has audience-based reading orders, document roles matrix, codec reference table. Generated has only file listing with regeneration commands. | +| **METHODOLOGY.md** | 238 | None | None | Core thesis (USDP inversion), event sourcing analogy, dogfooding examples, design philosophy. Pure editorial -- no annotation source exists for this content. | +| **CONFIGURATION.md** | 357 | docs-live/product-areas/CONFIGURATION.md (1,082 lines) | Partial | Generated has exhaustive pattern listings but lacks: preset selection rationale, decision rules ("when to use each preset"), monorepo setup example, backward compatibility guide, programmatic config loading examples. | +| **SESSION-GUIDES.md** | 389 | docs-live/\_claude-md/process/process-overview.md (138 lines) | Minimal | Decision tree for choosing session type, step-by-step checklists per session type, handoff documentation templates, "Do NOT" lists. Generated compact is AI-focused, not developer-facing. | +| **ARCHITECTURE.md** | 1,638 | docs-live/product-areas/GENERATION.md (1,065 lines) + docs-live/reference/ARCHITECTURE-CODECS.md (630 lines) + docs-live/reference/ARCHITECTURE-TYPES.md (429 lines) | Partial | Generated covers pipeline stages and codec listings well. Missing: executive summary, data flow diagrams, workflow integration section, "Extending the System" guide, programmatic usage examples, quick reference card. | +| **GHERKIN-PATTERNS.md** | 366 | None | None | Authoring style guide: 4 essential patterns, DataTable/DocString usage, tag conventions, feature file rich content rules, step linting reference. Pure editorial guidance -- no annotation source exists. | +| **ANNOTATION-GUIDE.md** | 270 | docs-live/taxonomy/metadata-tags.md (649 lines) | Partial | Generated has exhaustive tag reference (56 tags). Missing: getting-started guide, shape extraction modes explanation, "Zod schema gotcha" documentation, verification steps, common issues troubleshooting table. | +| **PROCESS-API.md** | ~60 | docs-live/reference/PROCESS-API-REFERENCE.md + PROCESS-API-RECIPES.md | **Replaced** | Trimmed to pointer file with operational reference (JSON envelope, exit codes, piping). All prose content now generated by CliRecipeCodec (WP-6 complete). | +| **PROCESS-GUARD.md** | 341 | docs-live/validation/error-catalog.md (79 lines) + docs-live/validation/fsm-transitions.md (49 lines) + docs-live/validation/protection-levels.md | Partial | Generated has error types, FSM matrix, protection levels. Missing: error fix rationale ("why this rule exists"), escape hatch alternatives, pre-commit setup instructions (Husky), programmatic API guide, Decider pattern architecture diagram. | +| **VALIDATION.md** | 418 | docs-live/product-areas/VALIDATION.md (1,115 lines) | Partial | Generated has pattern listings and business rules. Missing: "Which command do I run?" decision tree, 32+ individual lint rule explanations with code examples, anti-pattern detection rationale, CI/CD integration patterns (GitHub Actions YAML), vitest-cucumber two-pattern problem explanation. | +| **TAXONOMY.md** | 107 | docs-live/TAXONOMY.md (199 lines) + docs-live/taxonomy/ (3 files) | Good | Generated taxonomy reference is actually more comprehensive than manual. Manual adds: architecture explanation (file structure of src/taxonomy/), preset-to-taxonomy mapping, generation commands. Small gap. | + +### Coverage Summary + +| Coverage Level | Files | Lines | % of Manual Content | +| ---------------- | --------------------------------------- | ----- | ------------------- | +| Good (>80%) | 1 (TAXONOMY.md) | 107 | 2% | +| Partial (40-80%) | 7 | 3,685 | 74% | +| Minimal (<40%) | 1 (SESSION-GUIDES.md) | 389 | 8% | +| None (0%) | 2 (METHODOLOGY.md, GHERKIN-PATTERNS.md) | 604 | 12% | + +--- + +## 7. Cross-Cutting Quality Gaps + +### 7.1 Missing Content Types in Generated Docs + +| Content Type | Present in docs/ | Present in docs-live/ | Examples | +| ---------------------------- | ---------------------------------------- | ---------------------------- | --------------------------------------------------------------------------------- | +| Decision trees | Yes (3 docs) | No | "Which validation command?", "Which session type?", "When to use design session?" | +| Step-by-step checklists | Yes (SESSION-GUIDES) | No | Planning session checklist, implementation 5-step execution order | +| CLI recipes with output | Yes (PROCESS-API) | Yes (PROCESS-API-RECIPES.md) | WP-6 complete: generated from CLI_SCHEMA | +| Error fix guides | Yes (PROCESS-GUARD) | Partial (error-catalog) | "completed-protection: add unlock-reason tag" with alternatives | +| Code examples (before/after) | Yes (VALIDATION) | No | Lint rule violation + fix side-by-side | +| Philosophical rationale | Yes (METHODOLOGY) | No | USDP inversion thesis, event sourcing analogy | +| Integration patterns | Yes (VALIDATION, PROCESS-GUARD) | No | Husky pre-commit, GitHub Actions YAML, package.json scripts | +| Getting-started guides | Yes (ANNOTATION-GUIDE) | No | "Add your first annotation" walkthrough | +| Gotcha documentation | Yes (ANNOTATION-GUIDE, GHERKIN-PATTERNS) | No | "Zod schema needs constant not type alias", "# kills Gherkin parsing" | +| Audience-based navigation | Yes (INDEX) | No | "New user read X, Developer read Y, Team Lead read Z" | + +### 7.2 Structural Quality Comparison + +| Quality Dimension | docs/ (Manual) | docs-live/ (Generated) | Winner | +| -------------------------- | ------------------------- | ------------------------------ | --------- | +| Consistency of format | Medium (varies by author) | High (codec templates) | Generated | +| Completeness of coverage | Medium (11 topics) | High (48 files, 196 patterns) | Generated | +| Depth of individual topics | High (deep dives) | Medium (broad but shallow) | Manual | +| Practical examples | High (code + CLI output) | Low (few examples) | Manual | +| Cross-referencing | Medium (manual links) | High (auto-generated links) | Generated | +| Diagrams | Medium (4 ASCII diagrams) | High (Mermaid C4 + LR) | Generated | +| Freshness / accuracy | Medium (may drift) | High (regenerated from source) | Generated | +| Accessibility to newcomers | High (reading orders) | Low (reference-heavy) | Manual | +| Troubleshooting guidance | High (error tables) | Low (error catalog only) | Manual | + +### 7.3 Website Quality Requirements + +For libar.dev publication, docs need: + +| Requirement | docs/ Status | docs-live/ Status | Gap | +| ----------------------------------- | ------------------------------ | ------------------------------ | ------------------ | +| Starlight frontmatter compatibility | Handled by sync | Handled by sync | None | +| Mermaid diagram rendering | ASCII only | C4Context + graph LR | Generated better | +| Internal link resolution | Manual links rewritten by sync | Internal links may not resolve | Needs sync update | +| Progressive disclosure | Good (sections, tables) | Good (collapsible sections) | None | +| Mobile-friendly tables | Some wide tables | Some wide tables | Both need review | +| Code block syntax highlighting | Good (```typescript) | Good (```typescript) | None | +| Broken link detection | Not automated | Not automated | Both need CI check | + +--- + +## 8. Unused Generation Capabilities + +### Codecs Available But Not in docs:all + +Three of the 14 unused codecs could directly fill gaps: + +| Codec | Would Generate | Fills Gap For | +| -------------- | -------------------------------------- | --------------------------------------- | +| `architecture` | ARCHITECTURE.md with Mermaid diagrams | docs/ARCHITECTURE.md data flow diagrams | +| `changelog` | CHANGELOG-GENERATED.md | Release history (new content) | +| `patterns` | Full pattern catalog with detail pages | docs/INDEX.md codec reference table | + +### New Codecs Needed + +| Proposed Codec | Content Type | Source Data | Fills Gap For | +| -------------------- | ------------------------------------------- | -------------------------------------------------------------- | ----------------------------------------------- | +| `guides` or `how-to` | Step-by-step procedural guides | Feature file Rule: blocks + new annotation type | SESSION-GUIDES, getting-started | +| `decision-trees` | Mermaid flowchart decision trees | New annotation or Rule: block extension | "Which command?" trees | +| `integration` | CI/CD setup recipes | New annotation type or config | VALIDATION CI section, PROCESS-GUARD pre-commit | +| `error-guide` | Error diagnosis + fix walkthrough | Existing error-catalog + new "fix" annotations | PROCESS-GUARD error fixes | +| ~~`cli-recipes`~~ | ~~CLI command sequences with explanations~~ | **Done (WP-6)** -- `CliRecipeGenerator` consuming `CLI_SCHEMA` | PROCESS-API recipes | + +--- + +## 9. Website Sync Script Gaps + +### 9.1 Blocking: docs-generated/ Source is Empty + +**Priority: P0 (blocks website build)** + +After consolidation, `syncGenerated()` reads from `docs-generated/` which is now empty. +Business rules, taxonomy, and reference-sample content is now in `docs-live/`. + +**Required changes to `sync-content.mjs`:** + +1. Remove `docsGenerated` from REQUIRED_SOURCES (or make optional) +2. Update `REQUIRED_SOURCE_FILES` to read BUSINESS-RULES.md and TAXONOMY.md from `docsLive` +3. Update `syncGenerated()` to read from `docs-live/` subdirectories: + - `docs-live/business-rules/` instead of `docs-generated/business-rules/` + - `docs-live/taxonomy/` instead of `docs-generated/taxonomy/` + - `docs-live/BUSINESS-RULES.md` instead of `docs-generated/BUSINESS-RULES.md` + - `docs-live/TAXONOMY.md` instead of `docs-generated/TAXONOMY.md` + - `docs-live/reference/REFERENCE-SAMPLE.md` instead of `docs-generated/docs/REFERENCE-SAMPLE.md` +4. Update `getSyncedRouteForSourceFile()` to resolve new paths + +### 9.2 Missing: New docs-live/ Content Not Synced + +**Priority: P1 (content exists but not published)** + +| Content | Source | Proposed Website Section | +| -------------------------- | --------------------------------------- | -------------------------------------------- | +| Validation rules (3 files) | docs-live/validation/ | Generated Reference > Validation | +| Reference docs (4 files) | docs-live/reference/ | Generated Reference > Architecture Reference | +| Top-level indexes | docs-live/INDEX.md, VALIDATION-RULES.md | Generated Reference root | + +### 9.3 Future: Replacing Manual Docs Sections + +**Priority: P2 (after quality parity)** + +When generated docs reach quality parity with manual docs for specific sections, +the sync script should be updated to read from `docs-live/` instead of `docs/`: + +| Manual Section | Replacement Source | Readiness | +| ------------------ | --------------------------------- | -------------------------- | +| reference/taxonomy | docs-live/TAXONOMY.md + taxonomy/ | Ready now | +| guides/ (all 5) | New generated guides | Needs new codec | +| reference/ (all 5) | docs-live/ equivalents | Needs quality improvements | + +--- + +## 10. Recommended Work Packages + +### WP-1: Fix Website Sync Script (P0) + +**Type:** Implementation session +**Scope:** libar-dev-website repo +**Effort:** Small (1 session) +**Spec alignment:** Consequence of DocsLiveConsolidation (Phase 37, completed). +No new delivery-process spec needed -- this is a website-repo fix. + +Update `sync-content.mjs` and `content-manifest.mjs` to: + +- Read business-rules, taxonomy from `docs-live/` instead of `docs-generated/` +- Add sync functions for validation/, reference/ subdirectories +- Remove `docsGenerated` from required sources +- Add new website sections for validation rules and reference docs + +**Key files to modify:** + +- `libar-dev-website/scripts/sync-content.mjs` (lines 78-83, 93-114, 456-503) +- `libar-dev-website/scripts/content-manifest.mjs` (add new sections) + +### WP-2: Enhance Generated Index (P1) + +**Type:** Design + Implementation +**Scope:** delivery-process repo +**Effort:** Small (1-2 sessions) +**Spec alignment:** Maps to DocsConsolidationStrategy Phase 6 (Index navigation update, pending). +Update the existing deliverable status when implementing. + +Improve `docs-live/INDEX.md` to include: + +- Audience-based reading orders (New User, Developer, Team Lead) +- Document roles matrix +- Codec reference table +- Cross-references between manual and generated docs + +**Approach:** Extend IndexCodec or create NavigationCodec that reads pattern metadata +to generate audience-appropriate navigation. + +### WP-3: Add Architecture Generator to docs:all (P1) + +**Type:** Implementation session +**Scope:** delivery-process repo +**Effort:** Small (1 session) +**Spec alignment:** Extends Phase 4 (Architecture decomposition, complete). Phase 4 +decomposed the manual ARCHITECTURE.md; this adds the generated Mermaid equivalent. + +The `architecture` codec already exists in `docs:all-preview`. Add it to `docs:all` +and configure output to `docs-live/`. This provides Mermaid architecture diagrams +that partially replace the manual ARCHITECTURE.md data flow diagrams. + +### WP-4: Add Changelog Generator to docs:all (P2) + +**Type:** Implementation session +**Scope:** delivery-process repo +**Effort:** Small (1 session) +**Spec alignment:** New work, not covered by DocsConsolidationStrategy. Consider +adding as a new deliverable if a spec is created. + +The `changelog` codec exists. Add to `docs:all`, configure output to `docs-live/`. +New content for the website (no manual equivalent to replace). + +### WP-5: Create Error Guide Codec (P2) + +**Type:** Design + Implementation +**Scope:** delivery-process repo +**Effort:** Medium (2-3 sessions) +**Spec alignment:** Maps to DocsConsolidationStrategy Phase 3 (Process Guard +consolidation, pending). The spec says "enhanced ValidationRulesCodec" -- design +session should decide whether to enhance existing codec or create new one. + +Create a codec that generates error diagnosis guides from: + +- Existing validation error catalog data +- New `**Fix:**` and `**Alternative:**` markers in Rule: blocks +- Pre-commit setup instructions from config + +This replaces the manual PROCESS-GUARD.md "Error Messages and Fixes" section. + +**Design questions for session:** + +- Enhance `ValidationRulesCodec` or create separate `ErrorGuideCodec`? +- Convention tag approach: annotate error-handling code in `src/lint/` with + `@libar-docs-convention:process-guard-errors`, or use existing behavior extraction? +- Preamble for Husky/CI setup content that can't come from annotations? + +### WP-6: Create CLI Recipe Codec (P2) + +**Type:** Design + Implementation +**Scope:** delivery-process repo +**Effort:** Medium (2-3 sessions) +**Spec alignment:** Extends ProcessApiHybridGeneration (Phase 43, completed). Phase 43 +generated reference tables from CLI schema; this adds recipe/guide content. The manual +PROCESS-API.md prose was explicitly kept in Phase 43 -- this WP addresses that remainder. + +Create a codec that generates CLI recipe guides from: + +- Process API command metadata (already extracted via `src/cli/cli-schema.ts`) +- New `**Recipe:**` annotation in feature files +- Session type metadata + +This replaces manual PROCESS-API.md "Common Recipes" and "Session Workflow Commands". + +**Design questions for session:** + +- Extend `ProcessApiReferenceGenerator` or create separate recipe generator? +- Where should recipe annotations live? (CLI schema? Feature files? New recipe files?) +- How to handle "Why Use This" motivational prose? (Preamble?) + +### WP-7: Create Procedural Guide Codec (P3) + +**Type:** Design + Implementation +**Scope:** delivery-process repo +**Effort:** Large (3-5 sessions) +**Spec alignment:** Maps to DocsConsolidationStrategy Phase 41 (GHERKIN-PATTERNS.md +restructure, pending) and Phase 39 (Session workflow module generation, pending -- +blocked on ClaudeModuleGeneration Phase 25). Also relates to Phase 5 (Guide trimming). + +**Note on Phase 39:** The session-guides-module-source.feature spec already has +`@libar-docs-claude-module` and `@libar-docs-claude-section:workflow` tags. Once +Phase 25 ships ClaudeModuleCodec, the CLAUDE.md session section auto-generates. +This WP addresses the **public-facing** SESSION-GUIDES.md, not the AI context version. + +Create a codec (or codec family) for generating how-to guides: + +- Session workflow checklists from SESSION-GUIDES feature file Rule: blocks +- Getting-started walkthrough from ANNOTATION-GUIDE content +- Decision trees as Mermaid flowcharts + +This is the largest gap -- SESSION-GUIDES.md (389 lines of checklists) and +GHERKIN-PATTERNS.md (366 lines of authoring guidance) have no generation source. + +**Key Design Decisions for session:** + +- Should procedural content live in Rule: blocks with new markers + (`**Checklist:**`, `**Step:**`), or a separate annotation system? +- Can the existing `session-guides-module-source.feature` Rule: blocks serve + as source for both AI compact AND public guide, using detail levels? +- Phase 41 says "trim to ~250 lines, Step Linting moves to VALIDATION.md" -- + should the remaining ~250 lines become preamble or a separate manual page? + +### WP-8: Decide Methodology Page Disposition (P3) + +**Type:** Design session +**Scope:** delivery-process repo +**Effort:** Small (1 session) +**Spec alignment:** DocsConsolidationStrategy explicitly says "Keep: philosophy and +core thesis" for METHODOLOGY.md. The master spec already decided this stays manual. +Also relates to Phase 42 (README.md rationalization) which trims README and moves +pitch content to website. + +METHODOLOGY.md (238 lines) contains philosophy that cannot be extracted from code. +The master spec already decided to keep it. Design session should confirm and decide: + +1. **Keep as-is** (aligned with master spec) +2. **Encode as invariants** in a feature file for queryability via Process Data API +3. **Merge relevant parts into README.md** as part of Phase 42 + +**Recommendation:** Option 1, with option 2 as enhancement. The philosophy is +inherently editorial, but encoding core thesis as Rule: blocks would make it +queryable (`pnpm process:query -- rules --pattern Methodology`) without replacing +the human-readable prose. + +### WP-9: Quality Polish for Website Publication (P1) + +**Type:** Implementation session +**Scope:** Both repos +**Effort:** Medium (2-3 sessions) +**Spec alignment:** Maps to DocsConsolidationStrategy Phase 38 (Generated doc quality +improvements, pending) and Phase 5 (Guide trimming, pending). Phase 38 specifically +calls out "fix REFERENCE-SAMPLE duplication, enrich Generation compact, add TOC". + +Review all docs-live/ content for website readiness: + +- Fix any wide tables that break mobile layout +- Ensure all Mermaid diagrams render correctly in Starlight +- Add missing cross-references ("See Also" sections) +- Verify all internal links resolve after sync +- Split oversized files (business-rules/generation.md at 4,372 lines) +- Add descriptions to frontmatter for SEO +- Phase 38 items: fix REFERENCE-SAMPLE duplication, enrich Generation compact, add TOC +- Phase 5 items: trim 30 lines of duplicated tag reference from ANNOTATION-GUIDE.md, + trim 67 lines of duplicated preset detail from CONFIGURATION.md + +--- + +## 11. Prioritization Matrix + +### By Impact and Effort + +| Priority | Work Package | Impact | Effort | Blocks | +| -------- | --------------------------- | ------------------------- | -------- | ------------------ | +| **P0** | WP-1: Fix sync script | Unblocks website build | Small | Website deployment | +| ~~P1~~ | ~~WP-2: Enhanced index~~ | **Done** (IndexCodec) | Complete | N/A | +| ~~P1~~ | ~~WP-3: Architecture gen~~ | **Done** | Complete | N/A | +| **P1** | WP-9: Quality polish | Website-ready content | Medium | Website launch | +| ~~P2~~ | ~~WP-4: Changelog gen~~ | **Done** | Complete | N/A | +| ~~P2~~ | ~~WP-5: Error guide codec~~ | **Done** | Complete | N/A | +| ~~P2~~ | ~~WP-6: CLI recipe codec~~ | **Done** | Complete | N/A | +| ~~P3~~ | ~~WP-7: Procedural guide~~ | **Done** | Complete | N/A | +| **P3** | WP-8: Methodology decision | Clarifies hybrid approach | Small | Nothing | + +### Master Spec Phases NOT Covered by Work Packages + +| Phase | Description | Status | +| -------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------- | +| Phase 1 - Taxonomy consolidation | Redirect docs/TAXONOMY.md to generated | Pending -- manual docs/ preserved as reference until quality parity | +| Phase 39 - Session workflow module gen | Generate CLAUDE.md session section | Blocked on Phase 25 (ClaudeModuleCodec). Not actionable yet. | +| Phase 42 - README.md rationalization | Trim to ~150 lines, move pitch to website | Separate initiative, not a docs/ vs docs-live/ gap. | + +### Recommended Execution Order + +``` +Remaining: WP-1 (fix sync) -> WP-9 (quality polish) -> WP-8 (methodology) +All other work packages are complete. +``` + +### Deprecation Roadmap + +| Manual Doc | Can Deprecate After | Prerequisite WPs | +| ------------------- | --------------------------------- | --------------------------------------- | +| TAXONOMY.md | Now (generated version is better) | WP-1 (sync fix) | +| ARCHITECTURE.md | WP-3 + WP-9 | Architecture generator + quality polish | +| PROCESS-GUARD.md | WP-5 | Error guide codec | +| PROCESS-API.md | Done (WP-6 complete) | Trimmed to pointer file | +| ANNOTATION-GUIDE.md | WP-7 (partial) | Guide codec with getting-started | +| VALIDATION.md | WP-5 + WP-7 | Error guide + procedural guides | +| SESSION-GUIDES.md | WP-7 | Procedural guide codec | +| GHERKIN-PATTERNS.md | WP-7 or never | Authoring guide is inherently editorial | +| METHODOLOGY.md | Never (hybrid) | N/A -- keep as manual | +| CONFIGURATION.md | WP-7 (partial) | Guide codec with preset selection | +| INDEX.md | WP-2 | Enhanced index generation | + +### Realistic Target + +Reduce from **11 manual docs to 3** (METHODOLOGY.md, GHERKIN-PATTERNS.md, and a +simplified INDEX.md) after completing WP-1 through WP-7. This eliminates ~80% of +manual maintenance burden while preserving irreducibly editorial content. + +--- + +## 10.5. Spec Coverage Status + +Maps each WP to its delivery-process spec, design status, and code stubs. + +| WP | Pattern | Spec Status | Design Status | Stubs | +| ---- | -------------------------- | ------------ | -------------------------------------------- | ------- | +| WP-1 | N/A (website repo) | Out of scope | N/A | N/A | +| WP-2 | EnhancedIndexGeneration | completed | Design + implementation complete | 3 stubs | +| WP-3 | (master spec deliverable) | completed | Trivial config change done | N/A | +| WP-4 | (master spec deliverable) | completed | Trivial config change done | N/A | +| WP-5 | ErrorGuideCodec | completed | Design complete (6 findings) | 3 stubs | +| WP-6 | CliRecipeCodec | completed | Design + implementation complete | 3 stubs | +| WP-7 | ProceduralGuideCodec | completed | Design complete (8 findings), DD-7/DD-8 done | 5 stubs | +| WP-8 | (master spec: keep manual) | N/A | Already decided | N/A | +| WP-9 | (master spec Phase 38) | pending | Implementation tasks | N/A | + +### Design Session Summary + +All 4 new specs (ErrorGuideCodec, CliRecipeCodec, EnhancedIndexGeneration, +ProceduralGuideCodec) have completed design sessions with findings and code stubs: + +- **ProceduralGuideCodec** design found that no new codec class is needed -- reuses + `createReferenceCodec()` with two `ReferenceDocConfig` entries. Preamble content + authored as markdown in `docs-sources/` and parsed into `SectionBlock[]` at config + load time by a shared `loadPreambleFromMarkdown()` utility (DD-7/DD-8). +- **ErrorGuideCodec** extends the existing `ValidationRulesCodec` with a new + `includeErrorGuide` toggle and convention-tagged annotations on `src/lint/` source. +- **CliRecipeCodec** creates a sibling `CliRecipeGenerator` to `ProcessApiReferenceGenerator`, + both standalone `DocumentGenerator` implementations consuming `CLI_SCHEMA` directly. +- **EnhancedIndexGeneration** creates a new `IndexCodec` registered in `CodecRegistry`, + composing MasterDataset-driven statistics with editorial preamble navigation content. + +**Master spec status:** 11/15 deliverables complete. WP-2 (IndexCodec) implementation +is complete but manual docs/ files are preserved as reference — Phase 1 (taxonomy +consolidation), Phase 5 (guide trimming), and Phase 6 (index navigation) remain +pending until generated docs reach quality parity for manual doc archival. Phase 38 +(generated doc quality improvements) is also pending. + +--- + +## 12. Appendix: File Inventories + +### A. Manual docs/ (11 files, ~4,537 lines) + +| File | Lines | Generatability | +| ------------------- | ----- | ------------------------------------------- | +| INDEX.md | 353 | Partial (navigation is editorial) | +| ANNOTATION-GUIDE.md | 270 | Partial (tags auto, gotchas manual) | +| ARCHITECTURE.md | 1,638 | Partial (pipeline auto, rationale manual) | +| CONFIGURATION.md | 357 | Partial (options auto, rationale manual) | +| GHERKIN-PATTERNS.md | 366 | Low (style guide is editorial) | +| METHODOLOGY.md | 238 | None (philosophy) | +| PROCESS-API.md | ~60 | Complete (pointer file + generated recipes) | +| PROCESS-GUARD.md | 341 | Partial (rules auto, fix guides manual) | +| SESSION-GUIDES.md | 389 | Low (checklists are procedural) | +| TAXONOMY.md | 107 | High (generated version is better) | +| VALIDATION.md | 418 | Partial (rules auto, examples manual) | + +### B. Generated docs-live/ (48 files, ~20,548 lines) + +**Top-level indexes (6 files):** +INDEX.md, PRODUCT-AREAS.md, BUSINESS-RULES.md, DECISIONS.md, TAXONOMY.md, VALIDATION-RULES.md + +**Product areas (7 files):** +ANNOTATION.md, CONFIGURATION.md, CORE-TYPES.md, DATA-API.md, GENERATION.md, PROCESS.md, VALIDATION.md + +**Architecture decisions (7 files):** +adr-001 through adr-006, adr-021 + +**Business rules (7 files):** +annotation.md, configuration.md, core-types.md, data-api.md, generation.md, process.md, validation.md + +**Reference (5 files):** +ARCHITECTURE-CODECS.md, ARCHITECTURE-TYPES.md, PROCESS-API-RECIPES.md, PROCESS-API-REFERENCE.md, REFERENCE-SAMPLE.md + +**Taxonomy (3 files):** +categories.md, format-types.md, metadata-tags.md + +**Validation (3 files):** +error-catalog.md, fsm-transitions.md, protection-levels.md + +**AI modules (10 files in \_claude-md/):** +7 product area overviews + 3 architecture reference compacts + +### C. Website Sections (content-manifest.mjs) + +| Section | Source | Current File Count | +| ---------------------- | ------------------------ | ------------------ | +| Tutorial | External repo (10 parts) | 11 | +| Guides | docs/ manual (5 files) | 5 | +| Reference | docs/ manual (5 files) | 5 | +| Product Areas | docs-live/ (8 files) | 8 | +| Architecture Decisions | docs-live/ (8 files) | 8 | +| Generated Reference | docs-generated/ (STALE) | 0 (broken) | + +### D. Codec Inventory (22 total) + +**In docs:all (9):** adrs, business-rules, taxonomy, validation-rules, reference-docs, product-area-docs, claude-modules, process-api-reference, cli-recipe + +**In docs:all-preview only (14):** patterns, roadmap, milestones, requirements, session, remaining, current, session-plan, session-findings, pr-changes, changelog, traceability, architecture, overview-rdm diff --git a/docs/GHERKIN-PATTERNS.md b/docs/GHERKIN-PATTERNS.md index 91e73a6c..8dfb8bba 100644 --- a/docs/GHERKIN-PATTERNS.md +++ b/docs/GHERKIN-PATTERNS.md @@ -343,165 +343,16 @@ For values with spaces, use the `quoted-value` format where supported: --- -## Step Linting - -`lint-steps` is a static analyzer that catches vitest-cucumber compatibility issues **before tests run**. It uses regex-based state machines (not the `@cucumber/gherkin` parser) to detect patterns that cause cryptic runtime failures. Run it after writing or modifying any `.feature` or `.steps.ts` file: - -```bash -pnpm lint:steps -``` - -12 rules across 3 categories (8 error, 4 warning). For the full validation tool suite, see [VALIDATION.md](./VALIDATION.md). - -### Feature File Rules - -These rules scan `.feature` files without needing a Gherkin parser: - -| Rule ID | Severity | What It Catches | -| ------------------------ | -------- | ------------------------------------------------------------------------ | -| `hash-in-description` | error | `#` at line start inside `"""` block in description — terminates parsing | -| `keyword-in-description` | error | Description line starting with Given/When/Then/And/But — breaks parser | -| `duplicate-and-step` | error | Multiple `And` steps with identical text in same scenario | -| `dollar-in-step-text` | warning | `$` in step text (outside quotes) causes matching issues | -| `hash-in-step-text` | warning | Mid-line `#` in step text (outside quotes) silently truncates the step | - -**`hash-in-description` — the most surprising trap:** - -```gherkin -# BAD — # inside """ block in description terminates parsing -Rule: My Rule - """bash - # This breaks the parser — Gherkin sees a comment, not code - generate-docs --output docs - """ - -# GOOD — move code to a step DocString (safe context) -Scenario: Example usage - Given the following script: - """bash - # Safe inside a real DocString - generate-docs --output docs - """ -``` - -**`keyword-in-description`:** - -```gherkin -# BAD — starts with "Given", parser interprets as a step -Rule: Authentication - Given a valid session, the system should... - -# GOOD — rephrase to avoid reserved keywords at line start -Rule: Authentication - A valid session enables the system to... -``` - -### Step Definition Rules - -These rules scan `.steps.ts` files: - -| Rule ID | Severity | What It Catches | -| ------------------------- | -------- | ---------------------------------------------------------- | -| `regex-step-pattern` | error | Regex pattern in step registration — use string patterns | -| `unsupported-phrase-type` | error | `{phrase}` in step string — use `{string}` instead | -| `repeated-step-pattern` | error | Same pattern registered twice — second silently overwrites | - -**`regex-step-pattern`:** - -```typescript -// BAD — regex pattern throws StepAbleStepExpressionError -Given(/a user with id (\d+)/, (_ctx, id) => { ... }); - -// GOOD — string pattern with Cucumber expression -Given('a user with id {int}', (_ctx, id: number) => { ... }); -``` - -### Cross-File Rules - -These rules pair `.feature` and `.steps.ts` files and cross-check them: - -| Rule ID | Severity | What It Catches | -| ---------------------------------- | -------- | -------------------------------------------------------------------- | -| `scenario-outline-function-params` | error | Function params in ScenarioOutline callback (should use variables) | -| `missing-and-destructuring` | error | Feature has `And` steps but step file does not destructure `And` | -| `missing-rule-wrapper` | error | Feature has `Rule:` blocks but step file does not destructure `Rule` | -| `outline-quoted-values` | warning | Quoted values in Outline steps instead of `` syntax | - -**The Two-Pattern Problem** — `scenario-outline-function-params` + `outline-quoted-values` form a pair: - -```gherkin -# Feature file — BAD (outline-quoted-values) -Scenario Outline: Validate quantity - When I set quantity to "" - # Should be: When I set quantity to - - Examples: - | quantity | - | 5 | -``` - -```typescript -// Step file — BAD (scenario-outline-function-params) -ScenarioOutline('Validate quantity', ({ When }) => { - When('I set quantity to {string}', (_ctx, qty: string) => { - // qty is undefined at runtime — {string} does NOT work in ScenarioOutline - }); -}); - -// GOOD — use variables object -ScenarioOutline('Validate quantity', ({ When }, variables: { quantity: string }) => { - When('I set quantity to ', () => { - const qty = variables.quantity; - }); -}); -``` - -**`missing-and-destructuring`:** - -```typescript -// BAD — And not destructured, causes StepAbleUnknowStepError -describeFeature(feature, ({ Given, When, Then }) => { ... }); - -// GOOD — And is available for feature And steps -describeFeature(feature, ({ Given, When, Then, And }) => { ... }); -``` - -### CLI Reference - -| Flag | Short | Description | Default | -| ------------------ | ----- | -------------------------- | -------- | -| `--strict` | | Treat warnings as errors | false | -| `--format ` | | Output: `pretty` or `json` | `pretty` | -| `--base-dir ` | `-b` | Base directory for paths | cwd | - -**Scan scope** (hardcoded defaults): - -``` -Feature files: tests/features/**/*.feature - delivery-process/specs/**/*.feature - delivery-process/decisions/**/*.feature -Step files: tests/steps/**/*.steps.ts -``` - -**Exit codes:** - -| Code | Meaning | -| ---- | ---------------------------------------------- | -| `0` | No errors (warnings allowed unless `--strict`) | -| `1` | Errors found (or warnings with `--strict`) | - ---- - ## Quick Reference -| Element | Use For | Example Location | -| -------------------- | -------------------------------------- | ----------------------------------------------------- | -| Background DataTable | Deliverables, shared reference data | `delivery-process/specs/process-guard-linter.feature` | -| Rule: | Group scenarios by business constraint | `tests/features/validation/*.feature` | -| Scenario Outline | Same pattern with variations | `tests/features/validation/fsm-validator.feature` | -| DocString `"""` | Code examples, content with pipes | `tests/features/behavior/scanner-*.feature` | -| Section comments `#` | Organize large feature files | Most test features | -| `lint-steps` | Catch vitest-cucumber traps statically | `pnpm lint:steps` | +| Element | Use For | Example Location | +| -------------------- | -------------------------------------- | -------------------------------------------------------- | +| Background DataTable | Deliverables, shared reference data | `delivery-process/specs/process-guard-linter.feature` | +| Rule: | Group scenarios by business constraint | `tests/features/validation/*.feature` | +| Scenario Outline | Same pattern with variations | `tests/features/validation/fsm-validator.feature` | +| DocString `"""` | Code examples, content with pipes | `tests/features/behavior/scanner-*.feature` | +| Section comments `#` | Organize large feature files | Most test features | +| `lint-steps` | Catch vitest-cucumber traps statically | [VALIDATION.md — lint-steps](./VALIDATION.md#lint-steps) | --- diff --git a/docs/PROCESS-API.md b/docs/PROCESS-API.md index e34db6c7..cbd69b6d 100644 --- a/docs/PROCESS-API.md +++ b/docs/PROCESS-API.md @@ -10,419 +10,18 @@ --- -## Why Use This +## Generated References -Traditional approach: read generated Markdown, parse it mentally, hope it's current. This CLI queries the **same annotated sources** that generate those docs — in real time, with typed output. +> This document retains operational reference (JSON envelope, exit codes, piping). +> For full CLI documentation, see the generated references below. -| Approach | Context Cost | Accuracy | Speed | -| ------------------------ | ------------ | --------------------- | ------- | -| Parse generated Markdown | High | Snapshot at gen time | Slow | -| **Data API CLI** | **Low** | Real-time from source | Instant | - -The CLI has two output modes: - -- **Text commands** (6) — formatted for terminal reading or AI context. Use `===` section markers for structure. -- **JSON commands** (12+) — wrapped in a `QueryResult` envelope. Pipeable to `jq`. - -Run `process-api --help` for the full command reference with all flags and 26 available API methods. - ---- - -## Quick Start - -The recommended session startup is three commands: - -```bash -# 1. Project health — progress, active phases, blockers -pnpm process:query -- overview - -# 2. Pre-flight check — catches FSM violations before you start -pnpm process:query -- scope-validate MyPattern implement - -# 3. Curated context — tailored to your session type -pnpm process:query -- context MyPattern --session implement -``` - -Example `overview` output: - -``` -=== PROGRESS === -318 patterns (224 completed, 47 active, 47 planned) = 70% - -=== ACTIVE PHASES === -Phase 24: ProcessStateAPIRelationshipQueries (1 active) -Phase 25: DataAPIStubIntegration (1 active) - -=== BLOCKING === -StepLintExtendedRules blocked by: StepLintVitestCucumber - -=== DATA API — Use Instead of Explore Agents === -pnpm process:query -- - overview, context, scope-validate, dep-tree, list, stubs, files, rules, arch blocking -``` - ---- - -## Session Types - -The `--session` flag tailors output to what you need right now: - -| Type | Includes | When to Use | -| ----------- | -------------------------------------------- | ---------------------------------- | -| `planning` | Pattern metadata and spec file only | Creating a new roadmap spec | -| `design` | Full: metadata, stubs, deps, deliverables | Making architectural decisions | -| `implement` | Focused: deliverables, FSM state, test files | Writing code from an existing spec | - -**Decision tree:** Starting to code? `implement`. Complex decisions? `design`. New pattern? `planning`. Not sure? Run `overview` first. - ---- - -## Session Workflow Commands - -These 6 commands output structured text (not JSON). They are designed for terminal reading and AI context consumption. - -### `overview` - -Executive summary: progress percentage, active phases, blocking patterns, and a CLI cheat sheet. - -```bash -pnpm process:query -- overview -``` - -### `scope-validate` - -**Highest-impact command.** Pre-flight readiness check that prevents wasted sessions. Returns a PASS/BLOCKED/WARN verdict covering: dependency completion, deliverable definitions, FSM transition validity, and design decisions. - -```bash -pnpm process:query -- scope-validate MyPattern implement -``` - -Checks: dependency completion, deliverable definitions, FSM transition validity, design decisions, executable spec location. - -Example output: - -``` -=== SCOPE VALIDATION: DataAPIDesignSessionSupport (implement) === - -=== CHECKLIST === -[PASS] Dependencies completed: 2/2 completed -[PASS] Deliverables defined: 4 deliverable(s) found -[BLOCKED] FSM allows transition: completed → active is not valid. -[WARN] Design decisions recorded: No PDR/AD references found in stubs - -=== VERDICT === -BLOCKED: 1 blocker(s) prevent implement session -``` - -Valid session types for scope-validate: `implement`, `design`. - -### `context` - -Curated context bundle tailored to session type. - -```bash -pnpm process:query -- context MyPattern --session design -``` - -Example output: - -``` -=== PATTERN: ContextAssemblerImpl === -Status: active | Category: pattern -## ContextAssembler — Session-Oriented Context Bundle Builder - -Pure function composition over MasterDataset. -File: src/api/context-assembler.ts - -=== DEPENDENCIES === -[active] ProcessStateAPI (implementation) src/api/process-state.ts -[completed] MasterDataset (implementation) src/validation-schemas/master-dataset.ts - -=== CONSUMERS === -ContextFormatterImpl (active) -ProcessAPICLIImpl (active) - -=== ARCHITECTURE (context: api) === -MasterDataset (completed, read-model) -ProcessStateAPI (active, service) -... -``` - -### `dep-tree` - -Dependency chain with status indicators. Shows what a pattern depends on, recursively. - -```bash -pnpm process:query -- dep-tree MyPattern -pnpm process:query -- dep-tree MyPattern --depth 2 -``` - -### `files` - -File reading list with implementation paths. Use `--related` to include architecture neighbors. - -```bash -pnpm process:query -- files MyPattern -pnpm process:query -- files MyPattern --related -``` - -Example with `--related`: - -``` -=== PRIMARY === -src/cli/process-api.ts - -=== ARCHITECTURE NEIGHBORS === -src/cli/version.ts -src/cli/output-pipeline.ts -src/cli/error-handler.ts -``` - -### `handoff` - -Captures session-end state: deliverable statuses, blockers, and modification date. - -```bash -pnpm process:query -- handoff --pattern MyPattern -pnpm process:query -- handoff --pattern MyPattern --git # include recent commits -pnpm process:query -- handoff --pattern MyPattern --session my-session-id -``` - -Example output: - -``` -=== HANDOFF: DataAPIDesignSessionSupport (review) === -Date: 2026-02-21 | Status: completed - -=== COMPLETED === -[x] Scope validation logic (src/api/scope-validator.ts) -[x] Handoff document generator (src/api/handoff-generator.ts) - -=== BLOCKERS === -None -``` - ---- - -## Pattern Discovery - -These commands output JSON wrapped in a `QueryResult` envelope. - -### `status` - -Status counts and completion percentage. - -```bash -pnpm process:query -- status -``` - -**Output:** `{ counts: { completed, active, planned, total }, completionPercentage, distribution }` - -### `list` - -Filtered pattern listing. Composable with output modifiers and list filters. - -```bash -# All roadmap patterns -pnpm process:query -- list --status roadmap - -# Just names -pnpm process:query -- list --status roadmap --names-only - -# Count only -pnpm process:query -- list --status active --count - -# Specific fields -pnpm process:query -- list --phase 25 --fields patternName,status,file -``` - -See [Output Modifiers](#output-modifiers) and [List Filters](#list-filters) below for all options. - -### `search` - -Fuzzy name search with match scores. Suggests close matches when a pattern is not found. - -```bash -pnpm process:query -- search EventStore -``` - -### `pattern` - -Full detail for one pattern including deliverables, dependencies, and all relationship fields. - -```bash -pnpm process:query -- pattern TransformDataset -``` - -**Warning:** Completed patterns can produce ~66KB of output. Prefer `context --session` for interactive sessions. - -### `stubs` - -Design stubs with target paths and resolution status. - -```bash -pnpm process:query -- stubs MyPattern # stubs for one pattern -pnpm process:query -- stubs --unresolved # only stubs missing target files -``` - -### `decisions` - -AD-N design decisions extracted from stub descriptions. - -```bash -pnpm process:query -- decisions MyPattern -``` - -**Note:** Returns exit code 1 when no decisions are found (unlike `list`/`search` which return empty arrays). - -### `pdr` - -Cross-reference patterns mentioning a PDR number. - -```bash -pnpm process:query -- pdr 1 -``` - -**Note:** Returns exit code 1 when no PDR references are found, same as `decisions`. - -### `rules` - -Business rules and invariants extracted from Gherkin `Rule:` blocks, grouped by product area, phase, and feature. - -```bash -pnpm process:query -- rules -pnpm process:query -- rules --product-area Validation -pnpm process:query -- rules --pattern ProcessGuardDecider -pnpm process:query -- rules --only-invariants -``` - -**Warning:** Unfiltered `rules` output can exceed 600KB. Always use `--pattern` or `--product-area` filters. - -**Output shape:** `{ productAreas: [{ productArea, ruleCount, invariantCount, phases: [{ phase, features: [{ pattern, source, rules }] }] }], totalRules, totalInvariants }` - ---- - -## Architecture Queries - -All architecture queries output JSON. They use `@libar-docs-arch-*` annotations. - -| Subcommand | Description | Example | -| ------------------------ | ------------------------------------------ | ------------------------------ | -| `arch roles` | All arch-roles with pattern counts | `arch roles` | -| `arch context` | All bounded contexts | `arch context` | -| `arch context ` | Patterns in one bounded context | `arch context scanner` | -| `arch layer` | All architecture layers | `arch layer` | -| `arch layer ` | Patterns in one layer | `arch layer domain` | -| `arch neighborhood

` | Uses, usedBy, dependsOn, same-context | `arch neighborhood EventStore` | -| `arch compare ` | Cross-context shared deps + integration | `arch compare scanner codec` | -| `arch coverage` | Annotation completeness across input files | `arch coverage` | -| `arch dangling` | Broken references (names that don't exist) | `arch dangling` | -| `arch orphans` | Patterns with no relationships (isolated) | `arch orphans` | -| `arch blocking` | Patterns blocked by incomplete deps | `arch blocking` | - -```bash -# What patterns are stuck? -pnpm process:query -- arch blocking - -# How well-annotated is the codebase? -pnpm process:query -- arch coverage - -# What does this pattern touch? -pnpm process:query -- arch neighborhood RulesQueryModule -``` - ---- - -## Metadata & Inventory - -### `tags` - -Tag usage report — counts per tag and value across all annotated sources. - -```bash -pnpm process:query -- tags -``` - -### `sources` - -File inventory by type (TypeScript, Gherkin, Stubs, Decisions). - -```bash -pnpm process:query -- sources -``` - -### `unannotated` - -TypeScript files missing the `@libar-docs` opt-in marker. Use `--path` to scope to a directory. - -```bash -pnpm process:query -- unannotated -pnpm process:query -- unannotated --path src/types -``` - -### `query [args...]` - -Execute any of the 26 query API methods directly by name. This is the escape hatch for methods not exposed as dedicated subcommands. - -```bash -pnpm process:query -- query getStatusCounts -pnpm process:query -- query isValidTransition roadmap active -pnpm process:query -- query getPatternsByPhase 18 -pnpm process:query -- query getRecentlyCompleted 5 -``` - -Integer-like arguments are automatically coerced to numbers. Run `process-api --help` for the full list of available API methods. +- **[CLI Reference Tables](../docs-live/reference/PROCESS-API-REFERENCE.md)** — all flags, options, filters, and modifiers +- **[Recipes & Workflow Guide](../docs-live/reference/PROCESS-API-RECIPES.md)** — command descriptions, usage examples, and common recipes --- ## Output Reference -### Global Options - -| Flag | Short | Description | Default | -| ---------------------- | ----- | ------------------------------------ | ---------------------------- | -| `--input ` | `-i` | TypeScript glob pattern (repeatable) | from config or auto-detected | -| `--features ` | `-f` | Gherkin glob pattern (repeatable) | from config or auto-detected | -| `--base-dir

` | `-b` | Base directory | cwd | -| `--workflow ` | `-w` | Workflow config JSON | default | -| `--help` | `-h` | Show help | --- | -| `--version` | `-v` | Show version | --- | - -**Config auto-detection:** If `--input` and `--features` are not provided, the CLI loads defaults from `delivery-process.config.ts` in the current directory. If no config file exists, it falls back to filesystem-based detection. If neither works, `--input` is required. - -### Output Modifiers - -Composable with `list`, `arch context/layer`, and pattern-array `query` methods. - -| Modifier | Description | -| ---------------------- | --------------------------------------------- | -| `--names-only` | Return array of pattern name strings | -| `--count` | Return integer count | -| `--fields ` | Return only specified fields per pattern | -| `--full` | Bypass summarization, return raw patterns | -| `--format ` | `json` (default, pretty-printed) or `compact` | - -Valid fields for `--fields`: `patternName`, `status`, `category`, `phase`, `file`, `source`. - -Precedence: `--count` > `--names-only` > `--fields` > default summarize. - -**Note on summarization:** By default, pattern arrays are summarized to ~100 bytes per pattern (from ~3.5KB raw). Use `--full` to get complete pattern objects. - -### List Filters - -For the `list` subcommand. All filters are composable. - -| Filter | Description | -| ------------------------ | ----------------------------------------------------------- | -| `--status ` | Filter by FSM status (roadmap, active, completed, deferred) | -| `--phase ` | Filter by roadmap phase number | -| `--category ` | Filter by category | -| `--source ` | Filter by source type | -| `--arch-context ` | Filter by architecture context | -| `--product-area ` | Filter by product area | -| `--limit ` | Maximum results | -| `--offset ` | Skip first n results | - ### JSON Envelope All JSON commands wrap output in a `QueryResult` envelope: @@ -462,47 +61,3 @@ On error: ```bash npx tsx src/cli/process-api.ts list --status roadmap --names-only | jq '.data[]' ``` - ---- - -## Common Recipes - -### Starting a Session - -```bash -pnpm process:query -- overview # project health -pnpm process:query -- scope-validate MyPattern implement # pre-flight -pnpm process:query -- context MyPattern --session implement # curated context -``` - -### Finding What to Work On - -```bash -pnpm process:query -- list --status roadmap --names-only # available patterns -pnpm process:query -- arch blocking # stuck patterns -pnpm process:query -- stubs --unresolved # missing implementations -``` - -### Investigating a Pattern - -```bash -pnpm process:query -- search EventStore # fuzzy name search -pnpm process:query -- dep-tree MyPattern --depth 2 # dependency chain -pnpm process:query -- arch neighborhood MyPattern # what it touches -pnpm process:query -- files MyPattern --related # file paths -``` - -### Design Session Prep - -```bash -pnpm process:query -- context MyPattern --session design # full context -pnpm process:query -- decisions MyPattern # design decisions -pnpm process:query -- stubs MyPattern # existing stubs -``` - -### Ending a Session - -```bash -pnpm process:query -- handoff --pattern MyPattern # capture state -pnpm process:query -- handoff --pattern MyPattern --git # include commits -``` diff --git a/docs/PROCESS-GUARD.md b/docs/PROCESS-GUARD.md index 3625322e..600e55d0 100644 --- a/docs/PROCESS-GUARD.md +++ b/docs/PROCESS-GUARD.md @@ -1,5 +1,9 @@ # Process Guard +> **Generated Reference Available:** Comprehensive error guide with rationale, +> alternatives, and integration recipes is generated at +> `docs-live/reference/PROCESS-GUARD-REFERENCE.md`. Run `pnpm docs:all` to regenerate. + > **Quick reference for `lint-process` validation rules, error fixes, and escape hatches.** Process Guard validates delivery workflow changes at commit time. For FSM concepts and state definitions, see [METHODOLOGY.md](./METHODOLOGY.md#fsm-enforced-workflow). diff --git a/docs/TAXONOMY.md b/docs/TAXONOMY.md index 6e580cca..be3b4f71 100644 --- a/docs/TAXONOMY.md +++ b/docs/TAXONOMY.md @@ -1,5 +1,7 @@ # Tag Taxonomy +> **Complete Reference:** The auto-generated [Taxonomy Reference](../docs-live/TAXONOMY.md) contains the full 56-tag catalog with all values and examples. This document explains taxonomy concepts; the generated version is the authoritative lookup. + The taxonomy defines the vocabulary for pattern annotations: what tags exist, their valid values, and how they're parsed. It's 100% TypeScript-defined in `src/taxonomy/`, providing type safety and IDE autocomplete. --- diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md index 957c1e3d..6711ceb2 100644 --- a/docs/VALIDATION.md +++ b/docs/VALIDATION.md @@ -1,12 +1,14 @@ # Validation Tools +> **Generated Reference:** See [VALIDATION-RULES.md](../docs-live/VALIDATION-RULES.md) for auto-generated Process Guard rules extracted from annotated source code. + Quick reference for choosing and running the right validation command. --- ## Which Command Do I Run? -``` +```text Need to check annotation quality? ├─ Yes → lint-patterns │ @@ -91,9 +93,144 @@ pnpm lint:steps --strict - Step definition anti-patterns (regex patterns, `{phrase}` usage, repeated registrations) - Cross-file mismatches (ScenarioOutline param pattern, missing And/Rule destructuring) -12 rules across 3 categories (8 error, 4 warning). +12 rules across 3 categories (9 error, 3 warning). For the full validation tool suite overview, see [Which Command Do I Run?](#which-command-do-i-run) above. + +### Feature File Rules + +These rules scan `.feature` files without needing a Gherkin parser: + +| Rule ID | Severity | What It Catches | +| ------------------------ | -------- | ------------------------------------------------------------------------ | +| `hash-in-description` | error | `#` at line start inside `"""` block in description — terminates parsing | +| `keyword-in-description` | error | Description line starting with Given/When/Then/And/But — breaks parser | +| `duplicate-and-step` | error | Multiple `And` steps with identical text in same scenario | +| `dollar-in-step-text` | warning | `$` in step text (outside quotes) causes matching issues | +| `hash-in-step-text` | warning | Mid-line `#` in step text (outside quotes) silently truncates the step | + +**`hash-in-description` — the most surprising trap:** + +```gherkin +# BAD — # inside """ block in description terminates parsing +Rule: My Rule + """bash + # This breaks the parser — Gherkin sees a comment, not code + generate-docs --output docs + """ + +# GOOD — move code to a step DocString (safe context) +Scenario: Example usage + Given the following script: + """bash + # Safe inside a real DocString + generate-docs --output docs + """ +``` + +**`keyword-in-description`:** + +```gherkin +# BAD — starts with "Given", parser interprets as a step +Rule: Authentication + Given a valid session, the system should... + +# GOOD — rephrase to avoid reserved keywords at line start +Rule: Authentication + A valid session enables the system to... +``` + +### Step Definition Rules + +These rules scan `.steps.ts` files: + +| Rule ID | Severity | What It Catches | +| ------------------------- | -------- | ---------------------------------------------------------- | +| `regex-step-pattern` | error | Regex pattern in step registration — use string patterns | +| `unsupported-phrase-type` | error | `{phrase}` in step string — use `{string}` instead | +| `repeated-step-pattern` | error | Same pattern registered twice — second silently overwrites | + +**`regex-step-pattern`:** + +```typescript +// BAD — regex pattern throws StepAbleStepExpressionError +Given(/a user with id (\d+)/, (_ctx, id) => { ... }); + +// GOOD — string pattern with Cucumber expression +Given('a user with id {int}', (_ctx, id: number) => { ... }); +``` + +### Cross-File Rules + +These rules pair `.feature` and `.steps.ts` files and cross-check them: + +| Rule ID | Severity | What It Catches | +| ---------------------------------- | -------- | -------------------------------------------------------------------- | +| `scenario-outline-function-params` | error | Function params in ScenarioOutline callback (should use variables) | +| `missing-and-destructuring` | error | Feature has `And` steps but step file does not destructure `And` | +| `missing-rule-wrapper` | error | Feature has `Rule:` blocks but step file does not destructure `Rule` | +| `outline-quoted-values` | warning | Quoted values in Outline steps instead of `` syntax | + +**The Two-Pattern Problem** — `scenario-outline-function-params` + `outline-quoted-values` form a pair: + +```gherkin +# Feature file — BAD (outline-quoted-values) +Scenario Outline: Validate quantity + When I set quantity to "" + # Should be: When I set quantity to + + Examples: + | quantity | + | 5 | +``` + +```typescript +// Step file — BAD (scenario-outline-function-params) +ScenarioOutline('Validate quantity', ({ When }) => { + When('I set quantity to {string}', (_ctx, qty: string) => { + // qty is undefined at runtime — {string} does NOT work in ScenarioOutline + }); +}); + +// GOOD — use variables object +ScenarioOutline('Validate quantity', ({ When }, variables: { quantity: string }) => { + When('I set quantity to ', () => { + const qty = variables.quantity; + }); +}); +``` + +**`missing-and-destructuring`:** + +```typescript +// BAD — And not destructured, causes StepAbleUnknowStepError +describeFeature(feature, ({ Given, When, Then }) => { ... }); + +// GOOD — And is available for feature And steps +describeFeature(feature, ({ Given, When, Then, And }) => { ... }); +``` + +### CLI Reference + +| Flag | Short | Description | Default | +| ------------------ | ----- | -------------------------- | -------- | +| `--strict` | | Treat warnings as errors | false | +| `--format ` | | Output: `pretty` or `json` | `pretty` | +| `--base-dir ` | `-b` | Base directory for paths | cwd | + +**Scan scope** (hardcoded defaults): + +``` +Feature files: tests/features/**/*.feature + delivery-process/specs/**/*.feature + delivery-process/decisions/**/*.feature +Step files: tests/steps/**/*.steps.ts +``` + +**Exit codes:** -**Detailed rules and examples:** See [GHERKIN-PATTERNS.md — Step Linting](./GHERKIN-PATTERNS.md#step-linting) +| Code | Meaning | +| ---- | ---------------------------------------------- | +| `0` | No errors (warnings allowed unless `--strict`) | +| `1` | Errors found (or warnings with `--strict`) | --- @@ -273,9 +410,9 @@ See [ARCHITECTURE.md](./ARCHITECTURE.md) for detailed API documentation. ## Related Documentation -| Document | Content | -| -------------------------------------------- | ------------------------------------- | -| [GHERKIN-PATTERNS.md](./GHERKIN-PATTERNS.md) | Step linting rules, examples, and CLI | -| [PROCESS-GUARD.md](./PROCESS-GUARD.md) | FSM rules, error fixes, escapes | -| [TAXONOMY.md](./TAXONOMY.md) | Tag taxonomy concepts and API | -| [ARCHITECTURE.md](./ARCHITECTURE.md) | Programmatic API details | +| Document | Content | +| -------------------------------------------- | -------------------------------------------- | +| [GHERKIN-PATTERNS.md](./GHERKIN-PATTERNS.md) | Gherkin authoring patterns and writing guide | +| [PROCESS-GUARD.md](./PROCESS-GUARD.md) | FSM rules, error fixes, escapes | +| [TAXONOMY.md](./TAXONOMY.md) | Tag taxonomy concepts and API | +| [ARCHITECTURE.md](./ARCHITECTURE.md) | Programmatic API details | diff --git a/package.json b/package.json index 57ecacad..a1b3a7cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@libar-dev/delivery-process", - "version": "1.0.0-pre.1", + "version": "1.0.0-pre.2", "description": "Context engineering toolkit: extract patterns from TypeScript and Gherkin into a queryable delivery state with living docs, architecture graphs, and FSM-enforced workflows.", "type": "module", "sideEffects": false, @@ -98,7 +98,11 @@ "docs:business-rules": "tsx src/cli/generate-docs.ts -g business-rules", "docs:reference": "tsx src/cli/generate-docs.ts -g reference-docs", "docs:product-areas": "tsx src/cli/generate-docs.ts -g product-area-docs", - "docs:all": "pnpm docs:decisions && pnpm docs:product-areas && pnpm docs:taxonomy && pnpm docs:business-rules && pnpm docs:reference", + "docs:claude-modules": "tsx src/cli/generate-docs.ts -g claude-modules", + "docs:process-api-reference": "tsx src/cli/generate-docs.ts -g process-api-reference", + "docs:cli-recipe": "tsx src/cli/generate-docs.ts -g cli-recipe", + "docs:index": "tsx src/cli/generate-docs.ts -g index", + "docs:all": "pnpm docs:decisions && pnpm docs:product-areas && pnpm docs:taxonomy && pnpm docs:business-rules && pnpm docs:validation && pnpm docs:reference && pnpm docs:claude-modules && pnpm docs:process-api-reference && pnpm docs:cli-recipe && pnpm docs:architecture && pnpm docs:changelog && pnpm docs:index", "docs:all-preview": "pnpm docs:patterns && pnpm docs:roadmap && pnpm docs:remaining && pnpm docs:changelog && pnpm docs:architecture && pnpm docs:decisions && pnpm docs:reference && pnpm docs:product-areas && pnpm docs:taxonomy && pnpm docs:validation && pnpm docs:requirements && pnpm docs:current && pnpm docs:milestones && pnpm docs:business-rules", "process:query": "tsx src/cli/process-api.ts", "process:q": "tsx src/cli/process-api.ts", @@ -199,7 +203,6 @@ "dist", "docs", "docs-live", - "docs-generated", "README.md", "LICENSE", "CHANGELOG.md" diff --git a/src/cli/cli-schema.ts b/src/cli/cli-schema.ts new file mode 100644 index 00000000..cbfa527a --- /dev/null +++ b/src/cli/cli-schema.ts @@ -0,0 +1,616 @@ +/** + * @libar-docs + * @libar-docs-pattern CLISchema + * @libar-docs-status completed + * @libar-docs-unlock-reason:Add-recipe-and-narrative-fields-for-CliRecipeCodec + * @libar-docs-implements ProcessApiHybridGeneration + * @libar-docs-arch-context cli + * @libar-docs-arch-layer domain + * @libar-docs-product-area:DataAPI + * + * ## CLI Schema — Single Source of Truth for CLI Reference + * + * Declarative schema defining all CLI options for the process-api command. + * Consumed by: + * - `showHelp()` in process-api.ts (terminal help text) + * - `ProcessApiReferenceGenerator` (generated markdown reference) + * + * This eliminates three-way sync between parser code, help text, and docs. + */ + +// ============================================================================= +// Types +// ============================================================================= + +export interface CLIOptionDef { + /** Flag with value placeholder, e.g., '--input ' */ + readonly flag: string; + /** Short alias, e.g., '-i' */ + readonly short?: string; + /** Human-readable description */ + readonly description: string; + /** Default value display string */ + readonly default?: string; +} + +export interface CLIOptionGroup { + /** Section heading */ + readonly title: string; + /** Singular form of title for column headers in two-column tables */ + readonly singularTitle?: string; + /** Intro prose rendered above the table */ + readonly description?: string; + /** Prose rendered below the table */ + readonly postNote?: string; + /** Option definitions */ + readonly options: readonly CLIOptionDef[]; +} + +/** A single step in a recipe — one CLI command with an explanatory comment. */ +export interface RecipeStep { + readonly command: string; + readonly comment?: string; +} + +/** A complete recipe example — a titled sequence of commands with context. */ +export interface RecipeExample { + readonly title: string; + readonly purpose: string; + readonly steps: readonly RecipeStep[]; + readonly expectedOutput?: string; +} + +/** A group of related recipes under a shared heading. */ +export interface RecipeGroup { + readonly title: string; + readonly description?: string; + readonly recipes: readonly RecipeExample[]; +} + +/** Narrative metadata for a single CLI command. */ +export interface CommandNarrative { + readonly command: string; + readonly description: string; + readonly usageExample: string; + readonly details?: string; + readonly expectedOutput?: string; +} + +/** A group of related command narratives under a shared section heading. */ +export interface CommandNarrativeGroup { + readonly title: string; + readonly description?: string; + readonly commands: readonly CommandNarrative[]; +} + +export interface CLISchema { + readonly globalOptions: CLIOptionGroup; + readonly outputModifiers: CLIOptionGroup; + readonly listFilters: CLIOptionGroup; + readonly sessionOptions: CLIOptionGroup; + readonly recipes?: readonly RecipeGroup[]; + readonly commandNarratives?: readonly CommandNarrativeGroup[]; +} + +// ============================================================================= +// Schema Definition +// ============================================================================= + +export const CLI_SCHEMA: CLISchema = { + globalOptions: { + title: 'Global Options', + postNote: + '**Config auto-detection:** If `--input` and `--features` are not provided, the CLI loads defaults from `delivery-process.config.ts` in the current directory. If no config file exists, it falls back to filesystem-based detection. If neither works, `--input` is required.', + options: [ + { + flag: '--input ', + short: '-i', + description: 'TypeScript glob pattern (repeatable)', + default: 'from config or auto-detected', + }, + { + flag: '--features ', + short: '-f', + description: 'Gherkin glob pattern (repeatable)', + default: 'from config or auto-detected', + }, + { + flag: '--base-dir ', + short: '-b', + description: 'Base directory', + default: 'cwd', + }, + { + flag: '--workflow ', + short: '-w', + description: 'Workflow config JSON', + default: 'default', + }, + { + flag: '--help', + short: '-h', + description: 'Show help', + }, + { + flag: '--version', + short: '-v', + description: 'Show version', + }, + ], + }, + + outputModifiers: { + title: 'Output Modifiers', + singularTitle: 'Output Modifier', + description: 'Composable with `list`, `arch context/layer`, and pattern-array `query` methods.', + postNote: [ + 'Valid fields for `--fields`: `patternName`, `status`, `category`, `phase`, `file`, `source`.', + '', + 'Precedence: `--count` > `--names-only` > `--fields` > default summarize.', + '', + '**Note on summarization:** By default, pattern arrays are summarized to ~100 bytes per pattern (from ~3.5KB raw). Use `--full` to get complete pattern objects.', + ].join('\n'), + options: [ + { + flag: '--names-only', + description: 'Return array of pattern name strings', + }, + { + flag: '--count', + description: 'Return integer count', + }, + { + flag: '--fields ', + description: 'Return only specified fields per pattern', + }, + { + flag: '--full', + description: 'Bypass summarization, return raw patterns', + }, + { + flag: '--format ', + description: '`json` (default, pretty-printed) or `compact`', + }, + ], + }, + + listFilters: { + title: 'List Filters', + singularTitle: 'List Filter', + description: 'For the `list` subcommand. All filters are composable.', + options: [ + { + flag: '--status ', + description: 'Filter by FSM status (roadmap, active, completed, deferred)', + }, + { + flag: '--phase ', + description: 'Filter by roadmap phase number', + }, + { + flag: '--category ', + description: 'Filter by category', + }, + { + flag: '--source ', + description: 'Filter by source type', + }, + { + flag: '--arch-context ', + description: 'Filter by architecture context', + }, + { + flag: '--product-area ', + description: 'Filter by product area', + }, + { + flag: '--limit ', + description: 'Maximum results', + }, + { + flag: '--offset ', + description: 'Skip first n results', + }, + ], + }, + + sessionOptions: { + title: 'Session Types', + description: 'For the `--session` flag used with `context` and `scope-validate`.', + options: [ + { + flag: '--session ', + description: 'Session type: `planning`, `design`, or `implement`', + }, + ], + }, + + // =========================================================================== + // Command Narratives (from docs/PROCESS-API.md) + // =========================================================================== + + commandNarratives: [ + // ---- Session Workflow Commands (6 text commands) ---- + { + title: 'Session Workflow Commands', + description: + 'These 6 commands output structured text (not JSON). They are designed for terminal reading and AI context consumption.', + commands: [ + { + command: 'overview', + description: + 'Executive summary: progress percentage, active phases, blocking patterns, and a CLI cheat sheet.', + usageExample: 'pnpm process:query -- overview', + expectedOutput: [ + '=== PROGRESS ===', + '318 patterns (224 completed, 47 active, 47 planned) = 70%', + '', + '=== ACTIVE PHASES ===', + 'Phase 24: ProcessStateAPIRelationshipQueries (1 active)', + 'Phase 25: DataAPIStubIntegration (1 active)', + '', + '=== BLOCKING ===', + 'StepLintExtendedRules blocked by: StepLintVitestCucumber', + '', + '=== DATA API \u2014 Use Instead of Explore Agents ===', + 'pnpm process:query -- ', + ' overview, context, scope-validate, dep-tree, list, stubs, files, rules, arch blocking', + ].join('\n'), + }, + { + command: 'scope-validate', + description: + '**Highest-impact command.** Pre-flight readiness check that prevents wasted sessions. Returns a PASS/BLOCKED/WARN verdict covering: dependency completion, deliverable definitions, FSM transition validity, and design decisions.', + usageExample: 'pnpm process:query -- scope-validate MyPattern implement', + details: + 'Checks: dependency completion, deliverable definitions, FSM transition validity, design decisions, executable spec location. Valid session types for scope-validate: `implement`, `design`.', + expectedOutput: [ + '=== SCOPE VALIDATION: DataAPIDesignSessionSupport (implement) ===', + '', + '=== CHECKLIST ===', + '[PASS] Dependencies completed: 2/2 completed', + '[PASS] Deliverables defined: 4 deliverable(s) found', + '[BLOCKED] FSM allows transition: completed \u2192 active is not valid.', + '[WARN] Design decisions recorded: No PDR/AD references found in stubs', + '', + '=== VERDICT ===', + 'BLOCKED: 1 blocker(s) prevent implement session', + ].join('\n'), + }, + { + command: 'context', + description: 'Curated context bundle tailored to session type.', + usageExample: 'pnpm process:query -- context MyPattern --session design', + expectedOutput: [ + '=== PATTERN: ContextAssemblerImpl ===', + 'Status: active | Category: pattern', + '## ContextAssembler \u2014 Session-Oriented Context Bundle Builder', + '', + 'Pure function composition over MasterDataset.', + 'File: src/api/context-assembler.ts', + '', + '=== DEPENDENCIES ===', + '[active] ProcessStateAPI (implementation) src/api/process-state.ts', + '[completed] MasterDataset (implementation) src/validation-schemas/master-dataset.ts', + '', + '=== CONSUMERS ===', + 'ContextFormatterImpl (active)', + 'ProcessAPICLIImpl (active)', + '', + '=== ARCHITECTURE (context: api) ===', + 'MasterDataset (completed, read-model)', + 'ProcessStateAPI (active, service)', + '...', + ].join('\n'), + }, + { + command: 'dep-tree', + description: + 'Dependency chain with status indicators. Shows what a pattern depends on, recursively.', + usageExample: 'pnpm process:query -- dep-tree MyPattern', + details: + 'Use `--depth` to limit recursion depth: `pnpm process:query -- dep-tree MyPattern --depth 2`.', + }, + { + command: 'files', + description: + 'File reading list with implementation paths. Use `--related` to include architecture neighbors.', + usageExample: 'pnpm process:query -- files MyPattern --related', + expectedOutput: [ + '=== PRIMARY ===', + 'src/cli/process-api.ts', + '', + '=== ARCHITECTURE NEIGHBORS ===', + 'src/cli/version.ts', + 'src/cli/output-pipeline.ts', + 'src/cli/error-handler.ts', + ].join('\n'), + }, + { + command: 'handoff', + description: + 'Captures session-end state: deliverable statuses, blockers, and modification date.', + usageExample: 'pnpm process:query -- handoff --pattern MyPattern', + details: + 'Use `--git` to include recent commits. Use `--session` to tag the handoff with a session id.', + expectedOutput: [ + '=== HANDOFF: DataAPIDesignSessionSupport (review) ===', + 'Date: 2026-02-21 | Status: completed', + '', + '=== COMPLETED ===', + '[x] Scope validation logic (src/api/scope-validator.ts)', + '[x] Handoff document generator (src/api/handoff-generator.ts)', + '', + '=== BLOCKERS ===', + 'None', + ].join('\n'), + }, + ], + }, + + // ---- Pattern Discovery (8 JSON commands) ---- + { + title: 'Pattern Discovery', + description: 'These commands output JSON wrapped in a `QueryResult` envelope.', + commands: [ + { + command: 'status', + description: 'Status counts and completion percentage.', + usageExample: 'pnpm process:query -- status', + details: + '**Output:** `{ counts: { completed, active, planned, total }, completionPercentage, distribution }`', + }, + { + command: 'list', + description: + 'Filtered pattern listing. Composable with output modifiers and list filters.', + usageExample: 'pnpm process:query -- list --status roadmap --names-only', + details: + 'See Output Modifiers and List Filters for all options. Examples: `list --status active --count`, `list --phase 25 --fields patternName,status,file`.', + }, + { + command: 'search', + description: + 'Fuzzy name search with match scores. Suggests close matches when a pattern is not found.', + usageExample: 'pnpm process:query -- search EventStore', + }, + { + command: 'pattern', + description: + 'Full detail for one pattern including deliverables, dependencies, and all relationship fields.', + usageExample: 'pnpm process:query -- pattern TransformDataset', + details: + '**Warning:** Completed patterns can produce ~66KB of output. Prefer `context --session` for interactive sessions.', + }, + { + command: 'stubs', + description: 'Design stubs with target paths and resolution status.', + usageExample: 'pnpm process:query -- stubs MyPattern', + details: + 'Use `--unresolved` to show only stubs missing target files: `pnpm process:query -- stubs --unresolved`.', + }, + { + command: 'decisions', + description: 'AD-N design decisions extracted from stub descriptions.', + usageExample: 'pnpm process:query -- decisions MyPattern', + details: + '**Note:** Returns exit code 1 when no decisions are found (unlike `list`/`search` which return empty arrays).', + }, + { + command: 'pdr', + description: 'Cross-reference patterns mentioning a PDR number.', + usageExample: 'pnpm process:query -- pdr 1', + details: + '**Note:** Returns exit code 1 when no PDR references are found, same as `decisions`.', + }, + { + command: 'rules', + description: + 'Business rules and invariants extracted from Gherkin `Rule:` blocks, grouped by product area, phase, and feature.', + usageExample: 'pnpm process:query -- rules --pattern ProcessGuardDecider', + details: + '**Warning:** Unfiltered `rules` output can exceed 600KB. Always use `--pattern` or `--product-area` filters. **Output shape:** `{ productAreas: [{ productArea, ruleCount, invariantCount, phases: [{ phase, features: [{ pattern, source, rules }] }] }], totalRules, totalInvariants }`', + }, + ], + }, + + // ---- Architecture Queries (11 subcommands) ---- + { + title: 'Architecture Queries', + description: + 'All architecture queries output JSON. They use `@libar-docs-arch-*` annotations.', + commands: [ + { + command: 'arch roles', + description: 'All arch-roles with pattern counts', + usageExample: 'pnpm process:query -- arch roles', + }, + { + command: 'arch context', + description: 'All bounded contexts', + usageExample: 'pnpm process:query -- arch context', + }, + { + command: 'arch context ', + description: 'Patterns in one bounded context', + usageExample: 'pnpm process:query -- arch context scanner', + }, + { + command: 'arch layer', + description: 'All architecture layers', + usageExample: 'pnpm process:query -- arch layer', + }, + { + command: 'arch layer ', + description: 'Patterns in one layer', + usageExample: 'pnpm process:query -- arch layer domain', + }, + { + command: 'arch neighborhood ', + description: 'Uses, usedBy, dependsOn, same-context', + usageExample: 'pnpm process:query -- arch neighborhood EventStore', + }, + { + command: 'arch compare ', + description: 'Cross-context shared deps + integration', + usageExample: 'pnpm process:query -- arch compare scanner codec', + }, + { + command: 'arch coverage', + description: 'Annotation completeness across input files', + usageExample: 'pnpm process:query -- arch coverage', + }, + { + command: 'arch dangling', + description: "Broken references (names that don't exist)", + usageExample: 'pnpm process:query -- arch dangling', + }, + { + command: 'arch orphans', + description: 'Patterns with no relationships (isolated)', + usageExample: 'pnpm process:query -- arch orphans', + }, + { + command: 'arch blocking', + description: 'Patterns blocked by incomplete deps', + usageExample: 'pnpm process:query -- arch blocking', + }, + ], + }, + + // ---- Metadata & Inventory (4 commands) ---- + { + title: 'Metadata & Inventory', + commands: [ + { + command: 'tags', + description: + 'Tag usage report \u2014 counts per tag and value across all annotated sources.', + usageExample: 'pnpm process:query -- tags', + }, + { + command: 'sources', + description: 'File inventory by type (TypeScript, Gherkin, Stubs, Decisions).', + usageExample: 'pnpm process:query -- sources', + }, + { + command: 'unannotated', + description: + 'TypeScript files missing the `@libar-docs` opt-in marker. Use `--path` to scope to a directory.', + usageExample: 'pnpm process:query -- unannotated --path src/types', + }, + { + command: 'query', + description: + 'Execute any of the 26 query API methods directly by name. This is the escape hatch for methods not exposed as dedicated subcommands.', + usageExample: 'pnpm process:query -- query getStatusCounts', + details: + 'Integer-like arguments are automatically coerced to numbers. Run `process-api --help` for the full list of available API methods. Examples: `query isValidTransition roadmap active`, `query getPatternsByPhase 18`, `query getRecentlyCompleted 5`.', + }, + ], + }, + ], + + // =========================================================================== + // Recipes (from docs/PROCESS-API.md "Common Recipes" section) + // =========================================================================== + + recipes: [ + { + title: 'Common Recipes', + description: 'Frequently-used command sequences for daily workflow.', + recipes: [ + { + title: 'Starting a Session', + purpose: 'The recommended session startup is three commands.', + steps: [ + { + command: 'pnpm process:query -- overview', + comment: 'project health', + }, + { + command: 'pnpm process:query -- scope-validate MyPattern implement', + comment: 'pre-flight', + }, + { + command: 'pnpm process:query -- context MyPattern --session implement', + comment: 'curated context', + }, + ], + }, + { + title: 'Finding What to Work On', + purpose: 'Discover available patterns, blockers, and missing implementations.', + steps: [ + { + command: 'pnpm process:query -- list --status roadmap --names-only', + comment: 'available patterns', + }, + { + command: 'pnpm process:query -- arch blocking', + comment: 'stuck patterns', + }, + { + command: 'pnpm process:query -- stubs --unresolved', + comment: 'missing implementations', + }, + ], + }, + { + title: 'Investigating a Pattern', + purpose: 'Deep-dive into a specific pattern: search, dependencies, neighbors, and files.', + steps: [ + { + command: 'pnpm process:query -- search EventStore', + comment: 'fuzzy name search', + }, + { + command: 'pnpm process:query -- dep-tree MyPattern --depth 2', + comment: 'dependency chain', + }, + { + command: 'pnpm process:query -- arch neighborhood MyPattern', + comment: 'what it touches', + }, + { + command: 'pnpm process:query -- files MyPattern --related', + comment: 'file paths', + }, + ], + }, + { + title: 'Design Session Prep', + purpose: 'Gather full context, design decisions, and stubs before a design session.', + steps: [ + { + command: 'pnpm process:query -- context MyPattern --session design', + comment: 'full context', + }, + { + command: 'pnpm process:query -- decisions MyPattern', + comment: 'design decisions', + }, + { + command: 'pnpm process:query -- stubs MyPattern', + comment: 'existing stubs', + }, + ], + }, + { + title: 'Ending a Session', + purpose: 'Capture session-end state for continuity.', + steps: [ + { + command: 'pnpm process:query -- handoff --pattern MyPattern', + comment: 'capture state', + }, + { + command: 'pnpm process:query -- handoff --pattern MyPattern --git', + comment: 'include commits', + }, + ], + }, + ], + }, + ], +}; diff --git a/src/cli/process-api.ts b/src/cli/process-api.ts index 8bf504e7..92caa9f1 100644 --- a/src/cli/process-api.ts +++ b/src/cli/process-api.ts @@ -50,6 +50,8 @@ import type { TagRegistry } from '../validation-schemas/tag-registry.js'; import { createSuccess, createError, QueryApiError } from '../api/types.js'; import { handleCliError } from './error-handler.js'; import { printVersionAndExit } from './version.js'; +import { CLI_SCHEMA } from './cli-schema.js'; +import type { CLIOptionGroup } from './cli-schema.js'; import { fuzzyMatchPatterns } from '../api/fuzzy-match.js'; import { allPatternNames, @@ -268,7 +270,23 @@ function parseArgs(argv: string[] = process.argv.slice(2)): ProcessAPICLIConfig // Help // ============================================================================= +function formatHelpOptions(group: CLIOptionGroup): string { + return group.options + .map((opt) => { + const short = opt.short !== undefined ? `${opt.short}, ` : ' '; + // Extract bare flag name (without value placeholder) for alignment + const flag = opt.flag.padEnd(24); + return ` ${short}${flag}${opt.description}`; + }) + .join('\n'); +} + function showHelp(): void { + const options = formatHelpOptions(CLI_SCHEMA.globalOptions); + const modifiers = formatHelpOptions(CLI_SCHEMA.outputModifiers); + const filters = formatHelpOptions(CLI_SCHEMA.listFilters); + const sessions = formatHelpOptions(CLI_SCHEMA.sessionOptions); + console.log(` process-api - Query delivery process state from annotated sources @@ -335,32 +353,19 @@ Metadata & Inventory: Options: - -i, --input Glob patterns for TypeScript files (repeatable) - -f, --features Glob patterns for .feature files (repeatable) - -b, --base-dir Base directory (default: cwd) - -w, --workflow Workflow config JSON file - -h, --help Show this help message - -v, --version Show version number +${options} Output Modifiers (composable with any list/query): - --names-only Return array of pattern name strings - --count Return integer count - --fields Return only specified fields per pattern - Valid: patternName, status, category, phase, file, source - --full Bypass summarization, return raw patterns - --format Output format (default: pretty-printed json) +${modifiers} List Filters (for 'list' subcommand): - --status Filter by FSM status (roadmap, active, completed, deferred) - --phase Filter by roadmap phase number - --category Filter by category - --source Filter by source type - --arch-context Filter by architecture context (@libar-docs-arch-context) - --product-area Filter by product area (@libar-docs-product-area) - --limit Maximum results - --offset Skip first n results +${filters} + +Session Types (for 'context' and 'scope-validate'): + +${sessions} Common Recipes: diff --git a/src/config/project-config-schema.ts b/src/config/project-config-schema.ts index 2d62cb61..398f2e73 100644 --- a/src/config/project-config-schema.ts +++ b/src/config/project-config-schema.ts @@ -29,6 +29,7 @@ import { z } from 'zod'; import type { DeliveryProcessProjectConfig } from './project-config.js'; import type { DeliveryProcessInstance } from './types.js'; import { DIAGRAM_SOURCE_VALUES } from '../renderable/codecs/reference.js'; +import { SectionBlockSchema } from '../renderable/schema.js'; /** * Glob pattern validation — replicates the security rules from @@ -170,6 +171,12 @@ const ReferenceDocConfigSchema = z includeTags: z.array(z.string().min(1)).readonly().optional(), // Product area filter (ADR-001): pre-filters all content sources by product area productArea: z.string().min(1).optional(), + // DD-4 (GeneratedDocQuality): render shapes section before conventions + shapesFirst: z.boolean().optional(), + // Exclude patterns by source path prefix (e.g., ephemeral planning specs) + excludeSourcePaths: z.array(z.string().min(1)).readonly().optional(), + // Static preamble sections prepended before all generated content + preamble: z.array(SectionBlockSchema).readonly().optional(), }) .strict(); diff --git a/src/extractor/gherkin-extractor.ts b/src/extractor/gherkin-extractor.ts index 47f38c5c..fb2a5ecb 100644 --- a/src/extractor/gherkin-extractor.ts +++ b/src/extractor/gherkin-extractor.ts @@ -264,6 +264,10 @@ export function extractPatternsFromGherkin( assignIfDefined(directive, 'workflow', metadata.workflow); assignIfDefined(directive, 'risk', metadata.risk); assignIfDefined(directive, 'priority', metadata.priority); + // Claude module generation fields + assignIfDefined(directive, 'claudeModule', metadata.claudeModule); + assignIfDefined(directive, 'claudeSection', metadata.claudeSection); + assignIfNonEmpty(directive, 'claudeTags', metadata.claudeTags); const rawPattern: Record = { id: patternId, @@ -330,6 +334,10 @@ export function extractPatternsFromGherkin( assignIfNonEmpty(rawPattern, 'convention', metadata.convention); // Cross-cutting document inclusion tags assignIfNonEmpty(rawPattern, 'include', metadata.include); + // Claude module generation fields + assignIfDefined(rawPattern, 'claudeModule', metadata.claudeModule); + assignIfDefined(rawPattern, 'claudeSection', metadata.claudeSection); + assignIfNonEmpty(rawPattern, 'claudeTags', metadata.claudeTags); // NOTE: ADR content is now derived from Gherkin Rule: keywords // (Context, Decision, Consequences) instead of parsed markdown. // The rules array is populated below and rendered by the ADR codec. diff --git a/src/generators/built-in/cli-recipe-generator.ts b/src/generators/built-in/cli-recipe-generator.ts new file mode 100644 index 00000000..eb27f8d0 --- /dev/null +++ b/src/generators/built-in/cli-recipe-generator.ts @@ -0,0 +1,188 @@ +/** + * @libar-docs + * @libar-docs-pattern CliRecipeGenerator + * @libar-docs-implements CliRecipeCodec + * @libar-docs-arch-context generator + * @libar-docs-arch-layer application + * @libar-docs-product-area:Generation + * + * ## Standalone Generator for CLI Recipes and Command Narratives + * + * Generates `PROCESS-API-RECIPES.md` from the declarative CLI schema. + * Sibling to `ProcessApiReferenceGenerator` — both implement + * `DocumentGenerator`, both consume `CLI_SCHEMA` directly, neither depends + * on MasterDataset (ADR-006 compliant). + * + * ### When to Use + * + * - When generating workflow recipes and command narrative docs from CLI schema + * - When extending CLI_SCHEMA with new recipe groups or command narratives + */ + +import type { DocumentGenerator, GeneratorContext, GeneratorOutput } from '../types.js'; +import { CLI_SCHEMA } from '../../cli/cli-schema.js'; +import type { RecipeGroup, CommandNarrativeGroup } from '../../cli/cli-schema.js'; +import { heading, paragraph, code, separator, document } from '../../renderable/schema.js'; +import type { SectionBlock } from '../../renderable/schema.js'; +import { renderToMarkdown } from '../../renderable/render.js'; + +// ============================================================================= +// Section Building — Command Narratives +// ============================================================================= + +/** + * Transform a CommandNarrativeGroup into SectionBlock[]. + * + * Each group becomes an H2 heading + optional description. + * Each CommandNarrative becomes an H3 heading (backtick-wrapped command name) + * + description paragraph + usage example code block + optional details + * + optional expected output code block. + */ +function buildNarrativeSections(group: CommandNarrativeGroup): SectionBlock[] { + const sections: SectionBlock[] = []; + + sections.push(heading(2, group.title)); + if (group.description !== undefined) { + sections.push(paragraph(group.description)); + } + + for (const cmd of group.commands) { + sections.push(heading(3, `\`${cmd.command}\``)); + sections.push(paragraph(cmd.description)); + sections.push(code(cmd.usageExample, 'bash')); + if (cmd.details !== undefined) { + sections.push(paragraph(cmd.details)); + } + if (cmd.expectedOutput !== undefined) { + sections.push(paragraph('Example output:')); + sections.push(code(cmd.expectedOutput)); + } + } + + return sections; +} + +// ============================================================================= +// Section Building — Recipes +// ============================================================================= + +/** + * Transform a RecipeGroup into SectionBlock[]. + * + * Each RecipeGroup becomes an H2 heading + optional description + recipe entries. + * Each RecipeExample becomes an H3 heading + purpose paragraph + code block + * with all steps (each rendered as `command # comment` or just `command`). + * If expectedOutput is present, a separate output code block follows. + */ +function buildRecipeSections(group: RecipeGroup): SectionBlock[] { + const sections: SectionBlock[] = []; + + sections.push(heading(2, group.title)); + if (group.description !== undefined) { + sections.push(paragraph(group.description)); + } + + for (const recipe of group.recipes) { + sections.push(heading(3, recipe.title)); + sections.push(paragraph(recipe.purpose)); + + const codeContent = recipe.steps + .map((s) => (s.comment !== undefined ? `${s.command} # ${s.comment}` : s.command)) + .join('\n'); + sections.push(code(codeContent, 'bash')); + + if (recipe.expectedOutput !== undefined) { + sections.push(paragraph('Expected output:')); + sections.push(code(recipe.expectedOutput)); + } + } + + return sections; +} + +// ============================================================================= +// Document Assembly +// ============================================================================= + +/** + * Build the complete recipe document from CLI schema and preamble. + * + * Assembly order: + * 1. Auto-generation notice + * 2. Preamble sections (Why Use This, Quick Start, Session Types) + separator + * 3. Command narrative sections from CLI_SCHEMA.commandNarratives (each group + separator) + * 4. Recipe sections from CLI_SCHEMA.recipes (each group + separator) + */ +function buildRecipeDocument(preamble: readonly SectionBlock[]): string { + const sections: SectionBlock[] = []; + + // 1. Auto-generation notice + sections.push( + paragraph( + '> Auto-generated from CLI schema. See [CLI Reference](./PROCESS-API-REFERENCE.md) for flag tables.' + ) + ); + + // 2. Preamble (editorial prose) + if (preamble.length > 0) { + sections.push(...preamble); + sections.push(separator()); + } + + // 3. Command narratives from schema + if (CLI_SCHEMA.commandNarratives !== undefined) { + for (const group of CLI_SCHEMA.commandNarratives) { + sections.push(...buildNarrativeSections(group)); + sections.push(separator()); + } + } + + // 4. Recipes from schema + if (CLI_SCHEMA.recipes !== undefined) { + for (const group of CLI_SCHEMA.recipes) { + sections.push(...buildRecipeSections(group)); + sections.push(separator()); + } + } + + const doc = document('Process API CLI \u2014 Recipes & Workflow Guide', sections); + return renderToMarkdown(doc); +} + +// ============================================================================= +// Generator +// ============================================================================= + +class CliRecipeGeneratorImpl implements DocumentGenerator { + readonly name = 'cli-recipe'; + readonly description = 'Generate CLI recipe guide and command narratives from schema'; + + private readonly preamble: readonly SectionBlock[]; + + constructor(preamble: readonly SectionBlock[]) { + this.preamble = preamble; + } + + generate(_patterns: readonly unknown[], _context: GeneratorContext): Promise { + const content = buildRecipeDocument(this.preamble); + + return Promise.resolve({ + files: [ + { + path: 'reference/PROCESS-API-RECIPES.md', + content, + }, + ], + }); + } +} + +/** + * Factory function following the createXxxGenerator() convention. + * + * @param preamble - Editorial SectionBlock[] prepended before generated content + * @returns DocumentGenerator instance + */ +export function createCliRecipeGenerator(preamble: readonly SectionBlock[]): DocumentGenerator { + return new CliRecipeGeneratorImpl(preamble); +} diff --git a/src/generators/built-in/codec-generators.ts b/src/generators/built-in/codec-generators.ts index 4de7bcf3..1e9d5f87 100644 --- a/src/generators/built-in/codec-generators.ts +++ b/src/generators/built-in/codec-generators.ts @@ -28,6 +28,10 @@ import { generatorRegistry } from '../registry.js'; import { createCodecGenerator } from '../codec-based.js'; import { createDecisionDocGenerator } from './decision-doc-generator.js'; +import { createProcessApiReferenceGenerator } from './process-api-reference-generator.js'; +import { createCliRecipeGenerator } from './cli-recipe-generator.js'; +import { loadPreambleFromMarkdown } from '../../renderable/load-preamble.js'; +import type { SectionBlock } from '../../renderable/schema.js'; // registerReferenceGenerators is now called from orchestrator.ts with config-provided configs // ═══════════════════════════════════════════════════════════════════════════ @@ -148,6 +152,18 @@ generatorRegistry.register(createCodecGenerator('taxonomy', 'taxonomy')); */ generatorRegistry.register(createCodecGenerator('validation-rules', 'validation-rules')); +/** + * Claude Module Generator + * Generates CLAUDE-MODULES.md index + {section}/{module}.md files + */ +generatorRegistry.register(createCodecGenerator('claude-modules', 'claude-modules')); + +/** + * Index Generator + * Generates INDEX.md navigation hub with editorial preamble + MasterDataset statistics + */ +generatorRegistry.register(createCodecGenerator('index', 'index')); + // ═══════════════════════════════════════════════════════════════════════════ // Decision Document Generator (Pattern-Based, not Codec-Based) // ═══════════════════════════════════════════════════════════════════════════ @@ -159,6 +175,35 @@ generatorRegistry.register(createCodecGenerator('validation-rules', 'validation- */ generatorRegistry.register(createDecisionDocGenerator()); +// ═══════════════════════════════════════════════════════════════════════════ +// Process API Reference Generator (Schema-Based, not Codec-Based) +// ═══════════════════════════════════════════════════════════════════════════ + +/** + * Process API CLI Reference Generator + * Generates PROCESS-API-REFERENCE.md from declarative CLI schema. + * Standalone: does not consume MasterDataset (ADR-006). + */ +generatorRegistry.register(createProcessApiReferenceGenerator()); + +// ═══════════════════════════════════════════════════════════════════════════ +// CLI Recipe Generator (Schema-Based, not Codec-Based) +// ═══════════════════════════════════════════════════════════════════════════ + +/** + * CLI Recipe & Workflow Guide Generator + * Generates PROCESS-API-RECIPES.md from declarative CLI schema. + * Standalone: does not consume MasterDataset (ADR-006). + */ +let cliRecipePreamble: readonly SectionBlock[] = []; +try { + cliRecipePreamble = loadPreambleFromMarkdown('docs-sources/process-api-recipes.md'); +} catch { + // Preamble file may not exist in test environments (e.g., CLI integration tests + // that run generate-docs in a temp directory). Fall back to empty preamble. +} +generatorRegistry.register(createCliRecipeGenerator(cliRecipePreamble)); + // ═══════════════════════════════════════════════════════════════════════════ // Reference Document Generators (Convention-Based, Codec-Driven) // ═══════════════════════════════════════════════════════════════════════════ diff --git a/src/generators/built-in/process-api-reference-generator.ts b/src/generators/built-in/process-api-reference-generator.ts new file mode 100644 index 00000000..7b6b2135 --- /dev/null +++ b/src/generators/built-in/process-api-reference-generator.ts @@ -0,0 +1,113 @@ +/** + * @libar-docs + * @libar-docs-pattern ProcessApiReferenceGenerator + * @libar-docs-status completed + * @libar-docs-implements ProcessApiHybridGeneration + * @libar-docs-arch-context generator + * @libar-docs-arch-layer application + * @libar-docs-product-area:Generation + * + * ## Standalone Generator for Process API CLI Reference + * + * Generates `PROCESS-API-REFERENCE.md` from the declarative CLI schema. + * Does NOT consume MasterDataset (ADR-006 compliant — CLI schema is static + * TypeScript, not annotation-derived data). + */ + +import type { DocumentGenerator, GeneratorContext, GeneratorOutput } from '../types.js'; +import { CLI_SCHEMA } from '../../cli/cli-schema.js'; +import type { CLIOptionDef, CLIOptionGroup } from '../../cli/cli-schema.js'; +import { heading, paragraph, table, separator, document } from '../../renderable/schema.js'; +import type { SectionBlock } from '../../renderable/schema.js'; +import { renderToMarkdown } from '../../renderable/render.js'; + +// ============================================================================= +// Section Building +// ============================================================================= + +function buildOptionSection( + group: CLIOptionGroup, + buildTable: (group: CLIOptionGroup) => { + columns: string[]; + mapRow: (opt: CLIOptionDef) => string[]; + } +): SectionBlock[] { + const sections: SectionBlock[] = []; + sections.push(heading(2, group.title)); + if (group.description !== undefined) { + sections.push(paragraph(group.description)); + } + const { columns, mapRow } = buildTable(group); + sections.push(table(columns, group.options.map(mapRow))); + if (group.postNote !== undefined) { + sections.push(paragraph(group.postNote)); + } + return sections; +} + +// ============================================================================= +// Document Assembly +// ============================================================================= + +function buildReferenceDocument(): string { + const sections: SectionBlock[] = []; + + sections.push( + paragraph( + '> Auto-generated from CLI schema. See [Process API Guide](../../docs/PROCESS-API.md) for usage examples and recipes.' + ) + ); + + const fourCol = (): { columns: string[]; mapRow: (opt: CLIOptionDef) => string[] } => ({ + columns: ['Flag', 'Short', 'Description', 'Default'], + mapRow: (opt) => [ + `\`${opt.flag}\``, + opt.short !== undefined ? `\`${opt.short}\`` : '---', + opt.description, + opt.default ?? '---', + ], + }); + const twoCol = ( + g: CLIOptionGroup + ): { columns: string[]; mapRow: (opt: CLIOptionDef) => string[] } => ({ + columns: [g.singularTitle ?? g.title, 'Description'], + mapRow: (opt) => [`\`${opt.flag}\``, opt.description], + }); + + sections.push(...buildOptionSection(CLI_SCHEMA.globalOptions, fourCol)); + sections.push(separator()); + sections.push(...buildOptionSection(CLI_SCHEMA.outputModifiers, twoCol)); + sections.push(separator()); + sections.push(...buildOptionSection(CLI_SCHEMA.listFilters, twoCol)); + sections.push(separator()); + sections.push(...buildOptionSection(CLI_SCHEMA.sessionOptions, twoCol)); + + const doc = document('Process API CLI Reference', sections); + return renderToMarkdown(doc); +} + +// ============================================================================= +// Generator +// ============================================================================= + +class ProcessApiReferenceGeneratorImpl implements DocumentGenerator { + readonly name = 'process-api-reference'; + readonly description = 'Generate CLI reference tables from declarative schema'; + + generate(_patterns: readonly unknown[], _context: GeneratorContext): Promise { + const content = buildReferenceDocument(); + + return Promise.resolve({ + files: [ + { + path: 'reference/PROCESS-API-REFERENCE.md', + content, + }, + ], + }); + } +} + +export function createProcessApiReferenceGenerator(): DocumentGenerator { + return new ProcessApiReferenceGeneratorImpl(); +} diff --git a/src/generators/built-in/reference-generators.ts b/src/generators/built-in/reference-generators.ts index 3b3acb68..24e50880 100644 --- a/src/generators/built-in/reference-generators.ts +++ b/src/generators/built-in/reference-generators.ts @@ -27,8 +27,9 @@ import { type ReferenceDocConfig, type DiagramScope, } from '../../renderable/codecs/reference.js'; -import { toKebabCase } from '../../utils/string-utils.js'; -import { normalizeStatus } from '../../taxonomy/normalized-status.js'; +import { slugify, toKebabCase } from '../../utils/string-utils.js'; +import { computeStatusCounts } from '../../renderable/utils.js'; +import type { StatusCounts } from '../../validation-schemas/index.js'; // ============================================================================ // Reference Document Configurations @@ -109,26 +110,15 @@ class ReferenceDocGenerator implements DocumentGenerator { _patterns: readonly ExtractedPattern[], context: GeneratorContext ): Promise { - if (!context.masterDataset) { - return Promise.resolve({ - files: [], - errors: [ - { - type: 'generator' as const, - message: `Generator "${this.name}" requires MasterDataset but none was provided.`, - }, - ], - }); - } + const dataset = context.masterDataset; + if (!dataset) return Promise.resolve({ files: [] }); const codec = createReferenceCodec(this.config, { detailLevel: this.detailLevel, generateDetailFiles: false, }); - // Cast needed: Zod codec infers optional props as `T | undefined`, - // but RenderableDocument uses exactOptionalPropertyTypes - const doc = codec.decode(context.masterDataset) as RenderableDocument; + const doc = codec.decode(dataset) as RenderableDocument; // Summary-level output (for _claude-md/) uses modular-claude-md compatible renderer const render = this.detailLevel === 'summary' ? renderToClaudeMdModule : renderToMarkdown; const content = render(doc); @@ -143,14 +133,45 @@ class ReferenceDocGenerator implements DocumentGenerator { // Registration // ============================================================================ +function toGeneratorName(title: string): string { + return slugify(title.replace(/ Reference$/, '')); +} + /** - * Derive a kebab-case name from a title like "Process Guard Reference". + * Shared loop for generating detailed + summary file pairs from reference configs. */ -function toGeneratorName(title: string): string { - return title - .replace(/ Reference$/, '') - .toLowerCase() - .replace(/\s+/g, '-'); +function generateDualOutputFiles( + configs: readonly ReferenceDocConfig[], + dataset: MasterDataset, + pathPrefix: string +): Array<{ path: string; content: string }> { + const files: Array<{ path: string; content: string }> = []; + + for (const config of configs) { + // Detailed output -> {pathPrefix}/{docsFilename} + const detailedCodec = createReferenceCodec(config, { + detailLevel: 'detailed', + generateDetailFiles: false, + }); + const detailedDoc = detailedCodec.decode(dataset) as RenderableDocument; + files.push({ + path: `${pathPrefix}/${config.docsFilename}`, + content: renderToMarkdown(detailedDoc), + }); + + // Summary output -> _claude-md/{section}/{filename} + const summaryCodec = createReferenceCodec(config, { + detailLevel: 'summary', + generateDetailFiles: false, + }); + const summaryDoc = summaryCodec.decode(dataset) as RenderableDocument; + files.push({ + path: `_claude-md/${config.claudeMdSection}/${config.claudeMdFilename}`, + content: renderToClaudeMdModule(summaryDoc), + }); + } + + return files; } /** @@ -172,41 +193,10 @@ class ReferenceDocsGenerator implements DocumentGenerator { _patterns: readonly ExtractedPattern[], context: GeneratorContext ): Promise { - if (!context.masterDataset) { - return Promise.resolve({ - files: [], - errors: [ - { - type: 'generator' as const, - message: `Generator "${this.name}" requires MasterDataset but none was provided.`, - }, - ], - }); - } - - const files: Array<{ path: string; content: string }> = []; - - for (const config of this.configs) { - // Detailed output -> docs/{docsFilename} - const detailedCodec = createReferenceCodec(config, { - detailLevel: 'detailed', - generateDetailFiles: false, - }); - const detailedDoc = detailedCodec.decode(context.masterDataset) as RenderableDocument; - files.push({ path: `docs/${config.docsFilename}`, content: renderToMarkdown(detailedDoc) }); - - // Summary output -> _claude-md/{section}/{filename} - const summaryCodec = createReferenceCodec(config, { - detailLevel: 'summary', - generateDetailFiles: false, - }); - const summaryDoc = summaryCodec.decode(context.masterDataset) as RenderableDocument; - files.push({ - path: `_claude-md/${config.claudeMdSection}/${config.claudeMdFilename}`, - content: renderToClaudeMdModule(summaryDoc), - }); - } + const dataset = context.masterDataset; + if (!dataset) return Promise.resolve({ files: [] }); + const files = generateDualOutputFiles(this.configs, dataset, 'reference'); return Promise.resolve({ files }); } } @@ -230,48 +220,15 @@ class ProductAreaDocsGenerator implements DocumentGenerator { _patterns: readonly ExtractedPattern[], context: GeneratorContext ): Promise { - if (!context.masterDataset) { - return Promise.resolve({ - files: [], - errors: [ - { - type: 'generator' as const, - message: `Generator "${this.name}" requires MasterDataset but none was provided.`, - }, - ], - }); - } + const dataset = context.masterDataset; + if (!dataset) return Promise.resolve({ files: [] }); - const files: Array<{ path: string; content: string }> = []; - - for (const config of this.configs) { - // Detailed output -> product-areas/{docsFilename} - const detailedCodec = createReferenceCodec(config, { - detailLevel: 'detailed', - generateDetailFiles: false, - }); - const detailedDoc = detailedCodec.decode(context.masterDataset) as RenderableDocument; - files.push({ - path: `product-areas/${config.docsFilename}`, - content: renderToMarkdown(detailedDoc), - }); - - // Summary output -> _claude-md/{section}/{filename} - const summaryCodec = createReferenceCodec(config, { - detailLevel: 'summary', - generateDetailFiles: false, - }); - const summaryDoc = summaryCodec.decode(context.masterDataset) as RenderableDocument; - files.push({ - path: `_claude-md/${config.claudeMdSection}/${config.claudeMdFilename}`, - content: renderToClaudeMdModule(summaryDoc), - }); - } + const files = generateDualOutputFiles(this.configs, dataset, 'product-areas'); // Progressive disclosure index files.push({ path: 'PRODUCT-AREAS.md', - content: buildProductAreaIndex(this.configs, context.masterDataset), + content: buildProductAreaIndex(this.configs, dataset), }); return Promise.resolve({ files }); @@ -291,6 +248,12 @@ function buildProductAreaIndex( ): string { const sections: SectionBlock[] = []; + // Use pre-computed byProductArea view (ADR-006: no re-derivation from raw patterns) + const areaStats = new Map(); + for (const [area, patterns] of Object.entries(dataset.byProductArea)) { + areaStats.set(area, computeStatusCounts(patterns)); + } + // Per-area sections with intro prose and live statistics for (const config of configs) { const area = config.productArea; @@ -302,18 +265,12 @@ function buildProductAreaIndex( sections.push(paragraph(`> **${meta.question}**`)); sections.push(paragraph(meta.intro)); - // Live per-area statistics - const areaPatterns = dataset.patterns.filter((p) => p.productArea === area); - if (areaPatterns.length > 0) { - const completed = areaPatterns.filter( - (p) => normalizeStatus(p.status) === 'completed' - ).length; - const active = areaPatterns.filter((p) => normalizeStatus(p.status) === 'active').length; - const planned = areaPatterns.filter((p) => normalizeStatus(p.status) === 'planned').length; - + // Live per-area statistics from pre-computed stats + const stats = areaStats.get(area); + if (stats !== undefined && stats.total > 0) { sections.push( paragraph( - `**${areaPatterns.length} patterns** — ${completed} completed, ${active} active, ${planned} planned` + `**${stats.total} patterns** — ${stats.completed} completed, ${stats.active} active, ${stats.planned} planned` ) ); } @@ -326,7 +283,7 @@ function buildProductAreaIndex( sections.push(separator()); - // Cross-area progress summary table + // Cross-area progress summary table (reuses pre-computed stats) const tableHeaders = ['Area', 'Patterns', 'Completed', 'Active', 'Planned']; const tableRows: string[][] = []; let totalPatterns = 0; @@ -338,23 +295,20 @@ function buildProductAreaIndex( const area = config.productArea; if (area === undefined) continue; - const areaPatterns = dataset.patterns.filter((p) => p.productArea === area); - const completed = areaPatterns.filter((p) => normalizeStatus(p.status) === 'completed').length; - const active = areaPatterns.filter((p) => normalizeStatus(p.status) === 'active').length; - const planned = areaPatterns.filter((p) => normalizeStatus(p.status) === 'planned').length; + const stats = areaStats.get(area) ?? { total: 0, completed: 0, active: 0, planned: 0 }; tableRows.push([ `[${area}](product-areas/${config.docsFilename})`, - String(areaPatterns.length), - String(completed), - String(active), - String(planned), + String(stats.total), + String(stats.completed), + String(stats.active), + String(stats.planned), ]); - totalPatterns += areaPatterns.length; - totalCompleted += completed; - totalActive += active; - totalPlanned += planned; + totalPatterns += stats.total; + totalCompleted += stats.completed; + totalActive += stats.active; + totalPlanned += stats.planned; } tableRows.push([ @@ -437,7 +391,7 @@ export function registerReferenceGenerators( // Individual generators: selective invocation per document for (const config of configs) { const kebabName = toGeneratorName(config.title); - const docsPrefix = config.productArea !== undefined ? 'product-areas' : 'docs'; + const docsPrefix = config.productArea !== undefined ? 'product-areas' : 'reference'; registry.register( new ReferenceDocGenerator( diff --git a/src/generators/orchestrator.ts b/src/generators/orchestrator.ts index 51efe459..9bab2b91 100644 --- a/src/generators/orchestrator.ts +++ b/src/generators/orchestrator.ts @@ -10,25 +10,35 @@ * @libar-docs-used-by CLI, Programmatic API * @libar-docs-usecase "When running full documentation generation pipeline" * @libar-docs-usecase "When merging TypeScript and Gherkin patterns" + * @libar-docs-convention pipeline-architecture * - * ## Documentation Generation Orchestrator - Full Pipeline Coordination + * ## Orchestrator Pipeline Responsibilities * - * Orchestrates the complete documentation generation pipeline: - * Scanner → Extractor → Generators → File Writer + * **Invariant:** The orchestrator is the integration boundary for full docs generation: + * it delegates dataset construction to the shared pipeline, then executes codecs and + * writes files. * - * Extracts business logic from CLI for programmatic use and testing. + * **Rationale:** Splitting orchestration into dataset construction (shared) and output + * execution (orchestrator-owned) keeps Data API and validation consumers aligned on one + * read-model path while preserving generator-specific output handling. + * + * ## Steps 1-8 via buildMasterDataset() + * + * Steps 1-8 (config load, TypeScript/Gherkin scan + extraction, merge, hierarchy + * derivation, workflow load, and `transformToMasterDataset`) are delegated to + * `buildMasterDataset()`. + * + * ## Steps 9-10: Codec Execution and File Writing + * + * After dataset creation, the orchestrator owns Step 9 (codec execution per generator, + * output rendering, additional file fan-out) and Step 10 (path validation, overwrite + * policy, and persisted file writes). * * ### When to Use * * - Running complete documentation generation programmatically * - Integrating doc generation into build scripts * - Testing the full pipeline without CLI overhead - * - * ### Key Concepts - * - * - **Dual-Source Merging**: Combines TypeScript and Gherkin patterns - * - **Generator Registry**: Looks up registered generators by name - * - **Result Monad**: Returns detailed errors for partial failures */ import * as path from 'path'; diff --git a/src/generators/pipeline/build-pipeline.ts b/src/generators/pipeline/build-pipeline.ts index 7983b252..f6a355f4 100644 --- a/src/generators/pipeline/build-pipeline.ts +++ b/src/generators/pipeline/build-pipeline.ts @@ -6,17 +6,35 @@ * @libar-docs-implements ProcessAPILayeredExtraction * @libar-docs-product-area DataAPI * @libar-docs-uses PatternScanner, GherkinScanner, DocExtractor, GherkinExtractor, MasterDataset + * @libar-docs-convention pipeline-architecture * - * ## PipelineFactory - Shared Pipeline Orchestration + * ## Shared Pipeline Factory Responsibilities * - * Shared factory that executes the 8-step scan-extract-merge-transform pipeline. - * Replaces inline pipeline orchestration in CLI consumers. + * **Invariant:** `buildMasterDataset()` is the shared factory for Steps 1-8 of the + * architecture pipeline and returns `Result` without + * process-level side effects. * - * Target: src/generators/pipeline/build-pipeline.ts - * See: ADR-006 (Single Read Model Architecture) - * See: DD-1, DD-2 (ProcessAPILayeredExtraction) + * **Rationale:** Centralizing scan/extract/merge/transform flow prevents divergence + * between CLI consumers and preserves a single ADR-006 read-model path. * - * **When to Use:** When any consumer needs a MasterDataset — call buildMasterDataset() instead of wiring the scan-extract-merge-transform pipeline inline. + * ## 8-Step Dataset Build Flow + * + * The factory owns: configuration load, TypeScript scan + extraction, Gherkin scan + + * extraction, merge conflict handling, hierarchy child derivation, workflow load, + * and `transformToMasterDataset` with validation summary. + * + * ## Consumer Architecture and PipelineOptions Differentiation + * + * Three consumers share this factory: `process-api`, `validate-patterns`, and the + * generation orchestrator. `PipelineOptions` differentiates behavior by + * `mergeConflictStrategy` (`fatal` vs `concatenate`), `includeValidation` toggles, + * and `failOnScanErrors` policy without forking pipeline logic. + * + * ### When to Use + * + * - Any consumer needs a MasterDataset without rewriting scan/extract/merge flow + * - CLI consumers require differentiated conflict strategy and validation behavior + * - Orchestrator needs a shared steps 1-8 implementation before codec/file execution */ import * as path from 'path'; @@ -56,6 +74,8 @@ import type { * DD-2: mergeConflictStrategy controls per-consumer conflict handling. * DD-3: exclude, contextInferenceRules support future orchestrator * migration without breaking changes. + * + * @libar-docs-shape master-dataset */ export interface PipelineOptions { readonly input: readonly string[]; @@ -114,6 +134,8 @@ export interface ScanMetadata { /** * Successful pipeline result containing the dataset and validation summary. + * + * @libar-docs-shape master-dataset */ export interface PipelineResult { readonly dataset: RuntimeMasterDataset; diff --git a/src/generators/pipeline/transform-dataset.ts b/src/generators/pipeline/transform-dataset.ts index b98663ed..e47b8c21 100644 --- a/src/generators/pipeline/transform-dataset.ts +++ b/src/generators/pipeline/transform-dataset.ts @@ -144,6 +144,8 @@ export interface ContextInferenceRule { * Extends the Zod-compatible MasterDataset with workflow reference. * LoadedWorkflow contains Maps which aren't JSON-serializable, * so it's kept separate from the Zod schema. + * + * @libar-docs-shape master-dataset */ export interface RuntimeMasterDataset extends MasterDataset { /** Optional workflow configuration (not serializable) */ @@ -152,6 +154,8 @@ export interface RuntimeMasterDataset extends MasterDataset { /** * Raw input data for transformation + * + * @libar-docs-shape master-dataset */ export interface RawDataset { /** Extracted patterns from TypeScript and/or Gherkin sources */ @@ -312,7 +316,7 @@ export function transformToMasterDatasetWithValidation(raw: RawDataset): Transfo // ───────────────────────────────────────────────────────────────────────── const malformedPatterns: MalformedPattern[] = []; - const unknownStatuses: string[] = []; + const unknownStatusSet = new Set(); const danglingReferences: DanglingReference[] = []; // ───────────────────────────────────────────────────────────────────────── @@ -339,9 +343,7 @@ export function transformToMasterDatasetWithValidation(raw: RawDataset): Transfo // Check for unknown status values if (pattern.status && !isKnownStatus(pattern.status)) { - if (!unknownStatuses.includes(pattern.status)) { - unknownStatuses.push(pattern.status); - } + unknownStatusSet.add(pattern.status); } } @@ -366,6 +368,8 @@ export function transformToMasterDatasetWithValidation(raw: RawDataset): Transfo prd: [], }; + const byProductAreaMap: Record = {}; + const relationshipIndex: Record = {}; // Architecture index for diagram generation @@ -424,6 +428,12 @@ export function transformToMasterDatasetWithValidation(raw: RawDataset): Transfo bySource.prd.push(p); } + // ─── Product area grouping ────────────────────────────────────────── + if (pattern.productArea) { + const areaPatterns = (byProductAreaMap[pattern.productArea] ??= []); + areaPatterns.push(p); + } + // ─── Relationship index ──────────────────────────────────────────────── const patternKey = getPatternName(pattern); relationshipIndex[patternKey] = { @@ -641,6 +651,7 @@ export function transformToMasterDatasetWithValidation(raw: RawDataset): Transfo // Build validation summary // ───────────────────────────────────────────────────────────────────────── + const unknownStatuses = [...unknownStatusSet]; const validation: ValidationSummary = { totalPatterns: patterns.length, malformedPatterns, @@ -661,6 +672,7 @@ export function transformToMasterDatasetWithValidation(raw: RawDataset): Transfo byQuarter, byCategory, bySource, + byProductArea: byProductAreaMap, counts, phaseCount: byPhaseMap.size, categoryCount: byCategoryMap.size, diff --git a/src/lint/process-guard/decider.ts b/src/lint/process-guard/decider.ts index 7ae6d694..f9dcb0c0 100644 --- a/src/lint/process-guard/decider.ts +++ b/src/lint/process-guard/decider.ts @@ -9,6 +9,7 @@ * @libar-docs-implements ProcessGuardLinter * @libar-docs-uses FSMValidator, DeriveProcessState, DetectChanges * @libar-docs-depends-on:FSMValidator,DeriveProcessState,DetectChanges + * @libar-docs-convention process-guard-errors * @libar-docs-extract-shapes validateChanges * * ## ProcessGuardDecider - Pure Validation Logic @@ -35,6 +36,86 @@ * 2. **Status Transition** - Transitions must follow PDR-005 FSM * 3. **Scope Creep** - Active specs cannot add new deliverables * 4. **Session Scope** - Modifications outside session scope warn + * + * ### Error Guide Content (convention: process-guard-errors) + * + * ## completed-protection + * + * **Invariant:** Completed specs are immutable without an explicit unlock + * reason. The unlock reason must be at least 10 characters and cannot be + * a placeholder. + * + * **Rationale:** The `completed` status represents verified, accepted work. + * Allowing silent modification undermines the terminal-state guarantee. + * Requiring an unlock reason creates an audit trail and forces the developer + * to justify why completed work needs revisiting. + * + * | Situation | Solution | Example | + * |-----------|----------|---------| + * | Fix typo in completed spec | Add unlock reason tag | `@libar-docs-unlock-reason:Fix-typo-in-FSM-diagram` | + * | Spec needs rework | Create new spec instead | New feature file with `roadmap` status | + * | Legacy import | Multiple transitions in one commit | Set `roadmap` then `completed` | + * + * ## invalid-status-transition + * + * **Invariant:** Status transitions must follow the PDR-005 FSM path. + * The only valid paths are: roadmap to active, roadmap to deferred, + * active to completed, active to roadmap, deferred to roadmap. + * + * **Rationale:** The FSM enforces a deliberate progression through + * planning, implementation, and completion. Skipping states (e.g., + * roadmap to completed) means work was never tracked as active, breaking + * session scoping and deliverable validation. + * + * | Attempted | Why Invalid | Valid Path | + * |-----------|-------------|------------| + * | roadmap to completed | Must go through active | roadmap to active to completed | + * | deferred to active | Must return to roadmap first | deferred to roadmap to active | + * | deferred to completed | Cannot skip two states | deferred to roadmap to active to completed | + * + * ## scope-creep + * + * **Invariant:** Active specs cannot add new deliverables. Scope is locked + * when status transitions to `active`. + * + * **Rationale:** Prevents scope creep during implementation. Plan fully + * before starting; implement what was planned. Adding deliverables mid- + * implementation signals inadequate planning and risks incomplete work. + * + * | Situation | Solution | Example | + * |-----------|----------|---------| + * | Need new deliverable | Revert to roadmap first | Change status to roadmap, add deliverable, then back to active | + * | Discovered work during implementation | Create new spec | New feature file for the discovered work | + * + * ## session-scope + * + * **Invariant:** Files outside the active session scope trigger warnings + * to prevent accidental cross-session modifications. + * + * **Rationale:** Session scoping ensures focused work. Modifying files + * outside the session scope often indicates scope creep or working on + * the wrong task. The warning is informational (not blocking) to allow + * intentional cross-scope changes with `--ignore-session`. + * + * ## session-excluded + * + * **Invariant:** Files explicitly excluded from a session cannot be + * modified in that session. This is a hard error, not a warning. + * + * **Rationale:** Explicit exclusion is a deliberate decision to protect + * certain files from modification during a session. Unlike session-scope + * (warning), exclusion represents a conscious boundary that should not + * be violated without changing the session configuration. + * + * ## deliverable-removed + * + * **Invariant:** Removing a deliverable from an active spec triggers a + * warning to ensure the removal is intentional and documented. + * + * **Rationale:** Deliverable removal during active implementation may + * indicate descoping or completion elsewhere. The warning ensures + * visibility -- the commit message should document why the deliverable + * was removed. */ import { diff --git a/src/lint/process-guard/detect-changes.ts b/src/lint/process-guard/detect-changes.ts index 87533ad2..986daba6 100644 --- a/src/lint/process-guard/detect-changes.ts +++ b/src/lint/process-guard/detect-changes.ts @@ -319,7 +319,7 @@ function escapeRegex(str: string): string { * These directories contain embedded status examples that look like transitions. */ function isGeneratedDocsPath(filePath: string): boolean { - const patterns = ['docs-living/', 'docs-generated/', 'docs/generated/']; + const patterns = ['docs-living/', 'docs-generated/', 'docs/generated/', 'docs-live/']; return patterns.some((p) => filePath.startsWith(p) || filePath.includes(`/${p}`)); } diff --git a/src/renderable/codecs/adr.ts b/src/renderable/codecs/adr.ts index 5207a509..531322d4 100644 --- a/src/renderable/codecs/adr.ts +++ b/src/renderable/codecs/adr.ts @@ -3,12 +3,18 @@ * @libar-docs-core * @libar-docs-pattern AdrDocumentCodec * @libar-docs-status completed + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## ADR Document Codec + * ## AdrDocumentCodec * * Transforms MasterDataset into RenderableDocument for Architecture Decision Records. * Extracts ADRs from patterns with `@libar-docs-adr` tags. * + * **Purpose:** Architecture Decision Records extracted from patterns with @libar-docs-adr tags. + * + * **Output Files:** `DECISIONS.md` (ADR index), `decisions/.md` (category details) + * * ### When to Use * * - When generating Architecture Decision Record documentation diff --git a/src/renderable/codecs/architecture.ts b/src/renderable/codecs/architecture.ts index 0fd796d5..6577871d 100644 --- a/src/renderable/codecs/architecture.ts +++ b/src/renderable/codecs/architecture.ts @@ -8,12 +8,25 @@ * @libar-docs-arch-layer application * @libar-docs-include codec-transformation * @libar-docs-uses MasterDataset, ArchIndex + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## Architecture Diagram Codec + * ## ArchitectureDocumentCodec * * Transforms MasterDataset into a RenderableDocument containing * architecture diagrams (Mermaid) generated from source annotations. * + * **Purpose:** Architecture diagrams (Mermaid) generated from source annotations. Supports component and layered views. + * + * **Output Files:** `ARCHITECTURE.md` (generated architecture diagrams with component inventory) + * + * | Option | Type | Default | Description | + * | --- | --- | --- | --- | + * | diagramType | "component" \| "layered" | "component" | Type of diagram to generate | + * | includeInventory | boolean | true | Include component inventory table | + * | includeLegend | boolean | true | Include legend for arrow styles | + * | filterContexts | string[] | [] | Filter to specific contexts (empty = all) | + * * ### When to Use * * - When generating architecture diagrams from code annotations diff --git a/src/renderable/codecs/business-rules.ts b/src/renderable/codecs/business-rules.ts index 91c7bb9e..e638ef27 100644 --- a/src/renderable/codecs/business-rules.ts +++ b/src/renderable/codecs/business-rules.ts @@ -4,23 +4,38 @@ * @libar-docs-pattern BusinessRulesCodec * @libar-docs-status completed * @libar-docs-unlock-reason:Progressive-disclosure-by-product-area + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## Business Rules Document Codec + * ## BusinessRulesCodec * * Transforms MasterDataset into a RenderableDocument for business rules output. * Generates BUSINESS-RULES.md organized by product area, phase, and feature. * + * **Purpose:** Business rules documentation organized by product area, phase, and feature. Extracts domain constraints from Gherkin Rule: blocks. + * + * **Output Files:** `BUSINESS-RULES.md` (main index), `business-rules/.md` (area details) + * + * | Option | Type | Default | Description | + * | --- | --- | --- | --- | + * | groupBy | "domain" \| "phase" \| "domain-then-phase" | "domain-then-phase" | Primary grouping strategy | + * | includeCodeExamples | boolean | false | Include code examples from DocStrings | + * | includeTables | boolean | true | Include markdown tables from descriptions | + * | includeRationale | boolean | true | Include rationale section per rule | + * | filterDomains | string[] | [] | Filter by domain categories (empty = all) | + * | filterPhases | number[] | [] | Filter by phases (empty = all) | + * | onlyWithInvariants | boolean | false | Show only rules with explicit invariants | + * | includeSource | boolean | true | Include source feature file link | + * | includeVerifiedBy | boolean | true | Include Verified by scenario links | + * | maxDescriptionLength | number | 150 | Max description length in standard mode | + * | excludeSourcePaths | string[] | [] | Exclude patterns by source path prefix | + * * ### When to Use * * - When generating business rules documentation for stakeholders * - When extracting domain constraints without implementation details * - When creating compliance or audit documentation from feature specs * - * ### Purpose - * - * Enable stakeholders to understand domain constraints without reading - * implementation details or full feature files. - * * ### Information Architecture * * ``` @@ -63,7 +78,7 @@ import { document, } from '../schema.js'; import { type BaseCodecOptions, DEFAULT_BASE_OPTIONS, mergeOptions } from './types/base.js'; -import { toKebabCase } from '../../utils/index.js'; +import { toKebabCase, camelCaseToTitleCase } from '../../utils/index.js'; // ═══════════════════════════════════════════════════════════════════════════ // Business Rules Codec Options (co-located with codec) @@ -135,6 +150,13 @@ import { type BusinessRuleAnnotations, extractFirstSentence, } from './helpers.js'; +import { extractTablesAsSectionBlocks } from './convention-extractor.js'; + +// ═══════════════════════════════════════════════════════════════════════════ +// Constants +// ═══════════════════════════════════════════════════════════════════════════ + +const DEFAULT_PRODUCT_AREA = 'Platform'; // ═══════════════════════════════════════════════════════════════════════════ // Types @@ -326,8 +348,7 @@ function collectRulesByProductArea( continue; } - // Determine product area (default to "Platform" if not specified) - const productArea = pattern.productArea ?? 'Platform'; + const productArea = pattern.productArea ?? DEFAULT_PRODUCT_AREA; const productAreaDisplay = formatProductAreaName(productArea); // Determine phase key (use release for DeliveryProcess items without phase) @@ -403,6 +424,15 @@ function getPhaseKey(pattern: ExtractedPattern): string { return 'Uncategorized'; } +const CONTENT_HEADER_PATTERNS = [ + /\*\*Problem:\*\*\s*/, + /\*\*Business Value:\*\*\s*/, + /\*\*Solution:\*\*\s*/, + /\*\*Context:\*\*\s*/, +] as const; + +const NEXT_HEADER_PATTERN = /\n\s*(?:\*\*[A-Z]|\|)/m; + /** * Extract a compact description from the feature * @@ -412,23 +442,14 @@ function getPhaseKey(pattern: ExtractedPattern): string { function extractFeatureDescription(pattern: ExtractedPattern): string { const desc = pattern.directive.description; - // Headers that indicate content follows - const contentHeaders = [ - /\*\*Problem:\*\*\s*/, - /\*\*Business Value:\*\*\s*/, - /\*\*Solution:\*\*\s*/, - /\*\*Context:\*\*\s*/, - ]; - // Try to find content after a header - for (const headerPattern of contentHeaders) { + for (const headerPattern of CONTENT_HEADER_PATTERNS) { const match = headerPattern.exec(desc); if (match) { // Get text after the header const afterHeader = desc.slice(match.index + match[0].length); // Get content up to the next header or table - const nextHeaderPattern = /\n\s*(\*\*[A-Z]|^\|)/m; - const nextHeaderMatch = nextHeaderPattern.exec(afterHeader); + const nextHeaderMatch = NEXT_HEADER_PATTERN.exec(afterHeader); const content = nextHeaderMatch ? afterHeader.slice(0, nextHeaderMatch.index) : afterHeader; // Clean up and extract first sentence @@ -808,7 +829,7 @@ function renderRuleInline( // Tables from rule description if (options.includeTables && rule.description) { - const tableBlocks = extractTables(rule.description); + const tableBlocks = extractTablesAsSectionBlocks(rule.description); for (const tableBlock of tableBlocks) { sections.push(tableBlock); } @@ -849,85 +870,6 @@ function renderRuleInline( return sections; } -/** - * Extract markdown tables from content - */ -function extractTables(content: string): SectionBlock[] { - const sections: SectionBlock[] = []; - const lines = content.split('\n'); - - let inTable = false; - let tableLines: string[] = []; - - for (const line of lines) { - const trimmed = line.trim(); - - if (trimmed.startsWith('|') && trimmed.endsWith('|')) { - inTable = true; - tableLines.push(trimmed); - } else if (inTable) { - // End of table - if (tableLines.length >= 2) { - const tableBlock = parseMarkdownTable(tableLines); - if (tableBlock) { - sections.push(tableBlock); - } - } - inTable = false; - tableLines = []; - } - } - - // Handle table at end of content - if (inTable && tableLines.length >= 2) { - const tableBlock = parseMarkdownTable(tableLines); - if (tableBlock) { - sections.push(tableBlock); - } - } - - return sections; -} - -/** - * Parse markdown table lines into a table SectionBlock - */ -function parseMarkdownTable(lines: string[]): SectionBlock | null { - if (lines.length < 2) return null; - - // Skip separator row (contains only dashes and pipes) - const dataLines = lines.filter((line) => !/^\|[\s-:|]+\|$/.test(line)); - if (dataLines.length < 1) return null; - - // First row is headers - const headerRow = dataLines[0]; - if (!headerRow) return null; - - const headers = headerRow - .split('|') - .map((cell) => cell.trim()) - .filter((cell) => cell.length > 0); - - if (headers.length === 0) return null; - - // Remaining rows are data - const rows: string[][] = []; - for (let i = 1; i < dataLines.length; i++) { - const row = dataLines[i]; - if (!row) continue; - - const cells = row - .split('|') - .map((cell) => cell.trim()) - .filter((cell) => cell.length > 0); - if (cells.length > 0) { - rows.push(cells); - } - } - - return table(headers, rows); -} - // ═══════════════════════════════════════════════════════════════════════════ // Utilities // ═══════════════════════════════════════════════════════════════════════════ @@ -945,13 +887,7 @@ function parseMarkdownTable(lines: string[]): SectionBlock | null { * - ContextInference → Context Inference */ function humanizeFeatureName(name: string): string { - // Insert spaces before uppercase letters that follow lowercase - let humanized = name.replace(/([a-z])([A-Z])/g, '$1 $2'); - // Insert spaces before sequences like "API" followed by lowercase - humanized = humanized.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2'); - // Strip common test suffixes - humanized = humanized.replace(/\s*Testing$/i, ''); - return humanized.trim(); + return camelCaseToTitleCase(name).replace(/\s*Testing$/i, ''); } /** @@ -982,24 +918,8 @@ export function deduplicateScenarioNames( return [...seen.values()]; } -/** - * Format product area name for display - */ function formatProductAreaName(productArea: string): string { - // Handle common product areas - switch (productArea.toLowerCase()) { - case 'platform': - return 'Platform'; - case 'deliveryprocess': - return 'Delivery Process'; - case 'exampleapp': - return 'Example App'; - case 'taxonomy': - return 'Taxonomy'; - default: - // Title case for unknown product areas - return productArea.charAt(0).toUpperCase() + productArea.slice(1); - } + return camelCaseToTitleCase(productArea); } /** diff --git a/src/renderable/codecs/claude-module.ts b/src/renderable/codecs/claude-module.ts new file mode 100644 index 00000000..25f0181d --- /dev/null +++ b/src/renderable/codecs/claude-module.ts @@ -0,0 +1,308 @@ +/** + * @libar-docs + * @libar-docs-pattern ClaudeModuleCodec + * @libar-docs-status active + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation + * + * ## ClaudeModuleCodec + * + * Transforms MasterDataset into RenderableDocuments for CLAUDE.md module generation. + * Filters patterns with `claudeModule` tags and generates compact markdown modules + * suitable for the `_claude-md/` directory structure. + * + * **Purpose:** Generate CLAUDE.md modules from annotated behavior specs. + * + * **Output Files:** One file per claude-module-tagged pattern at `{section}/{module}.md` + * + * ### Content Extraction + * + * - Feature description → skipped (meta-documentation, not operational content) + * - Rule: blocks → H4 sections with invariant + rationale + * - Scenario Outline Examples → decision tables + * - Tables in Rule descriptions → preserved as-is + * + * ### Factory Pattern + * + * Use `createClaudeModuleCodec(options)` for custom options: + * ```typescript + * const codec = createClaudeModuleCodec({ detailLevel: 'detailed' }); + * const doc = codec.decode(dataset); + * ``` + */ + +import { z } from 'zod'; +import { + MasterDatasetSchema, + type MasterDataset, +} from '../../validation-schemas/master-dataset.js'; +import type { ExtractedPattern } from '../../validation-schemas/index.js'; +import type { BusinessRule } from '../../validation-schemas/extracted-pattern.js'; +import { + type RenderableDocument, + type SectionBlock, + heading, + paragraph, + separator, + table, + linkOut, + document, +} from '../schema.js'; +import { type BaseCodecOptions, DEFAULT_BASE_OPTIONS, mergeOptions } from './types/base.js'; +import { RenderableDocumentOutputSchema } from './shared-schema.js'; +import { parseBusinessRuleAnnotations } from './helpers.js'; +import { extractTablesAsSectionBlocks } from './convention-extractor.js'; +import type { ClaudeSectionValue } from '../../taxonomy/claude-section-values.js'; + +const DEFAULT_CLAUDE_SECTION: ClaudeSectionValue = 'core'; + +// ═══════════════════════════════════════════════════════════════════════════ +// Claude Module Codec Options +// ═══════════════════════════════════════════════════════════════════════════ + +/** + * Options for ClaudeModuleCodec + * + * Supports progressive disclosure via detailLevel: + * - "summary": Rules and Examples tables only (compact) + * - "standard": Above + invariant + rationale per rule + * - "detailed": Full content including scenario details + */ +export interface ClaudeModuleCodecOptions extends BaseCodecOptions { + /** Path prefix for "See: Full Documentation" links (default: "docs/") */ + fullDocsPath?: string; + + /** Include rationale section per rule (default: true) */ + includeRationale?: boolean; + + /** Include tables from rule descriptions (default: true) */ + includeTables?: boolean; +} + +/** + * Default options for ClaudeModuleCodec + */ +export const DEFAULT_CLAUDE_MODULE_OPTIONS: Required = { + ...DEFAULT_BASE_OPTIONS, + fullDocsPath: 'docs/', + includeRationale: true, + includeTables: true, +}; + +// ═══════════════════════════════════════════════════════════════════════════ +// Codec Creation +// ═══════════════════════════════════════════════════════════════════════════ + +/** + * Create a ClaudeModuleCodec with custom options. + * + * @param options - Codec configuration options + * @returns Configured Zod codec + */ +export function createClaudeModuleCodec( + options?: ClaudeModuleCodecOptions +): z.ZodCodec { + const opts = mergeOptions(DEFAULT_CLAUDE_MODULE_OPTIONS, options); + + return z.codec(MasterDatasetSchema, RenderableDocumentOutputSchema, { + decode: (dataset: MasterDataset): RenderableDocument => { + return buildClaudeModuleDocument(dataset, opts); + }, + /** @throws Always - this codec is decode-only. See zod-codecs.md */ + encode: (): never => { + throw new Error('ClaudeModuleCodec is decode-only. See zod-codecs.md'); + }, + }); +} + +/** + * Default Claude Module Codec + * + * Transforms MasterDataset → RenderableDocument for CLAUDE.md modules. + * Uses default options with standard detail level. + */ +export const ClaudeModuleCodec = createClaudeModuleCodec(); + +// ═══════════════════════════════════════════════════════════════════════════ +// Document Builder +// ═══════════════════════════════════════════════════════════════════════════ + +/** + * Build the index document listing all generated modules, + * with each module as an additionalFile. + */ +function buildClaudeModuleDocument( + dataset: MasterDataset, + options: Required +): RenderableDocument { + // Filter to patterns with claudeModule set + const modulePatterns = dataset.patterns.filter( + (p) => p.claudeModule !== undefined && p.claudeModule !== '' + ); + + if (modulePatterns.length === 0) { + return document( + 'Claude Modules', + [ + heading(2, 'No Claude Modules Found'), + paragraph('No patterns have `@libar-docs-claude-module` tags.'), + ], + { + purpose: 'Claude module generation index', + } + ); + } + + // Build index sections + const sections: SectionBlock[] = []; + sections.push( + heading(2, 'Generated Modules'), + paragraph(`${modulePatterns.length} module(s) generated from annotated behavior specs.`) + ); + + // Summary table + const rows = modulePatterns.map((p) => [ + p.claudeModule ?? '', + p.claudeSection ?? DEFAULT_CLAUDE_SECTION, + p.name, + `${p.rules?.length ?? 0} rules`, + ]); + sections.push(table(['Module', 'Section', 'Source Pattern', 'Content'], rows)); + + // Build each module as an additional file + const additionalFiles: Record = {}; + for (const pattern of modulePatterns) { + const section = pattern.claudeSection ?? DEFAULT_CLAUDE_SECTION; + const module = pattern.claudeModule ?? pattern.name; + const filePath = `${section}/${module}.md`; + additionalFiles[filePath] = buildModuleFile(pattern, options); + } + + const docOptions: { + purpose: string; + detailLevel: string; + additionalFiles?: Record; + } = { + purpose: 'Claude module generation index', + detailLevel: options.detailLevel, + }; + if (Object.keys(additionalFiles).length > 0) { + docOptions.additionalFiles = additionalFiles; + } + + return document('Claude Modules', sections, docOptions); +} + +// ═══════════════════════════════════════════════════════════════════════════ +// Module File Builder +// ═══════════════════════════════════════════════════════════════════════════ + +/** + * Build a single module file from a pattern. + * Extracts content from Feature description, Rule blocks, and Scenario Outline Examples. + */ +function buildModuleFile( + pattern: ExtractedPattern, + options: Required +): RenderableDocument { + const sections: SectionBlock[] = []; + + // Skip Feature description (Problem/Solution preamble) — it is meta-documentation + // about why the spec exists, not operational content. Only Rule blocks contain + // the actual invariants and guidance needed in _claude-md/ modules. + + // Rule blocks → H4 sections + if (pattern.rules && pattern.rules.length > 0) { + sections.push(separator()); + for (const rule of pattern.rules) { + sections.push(...buildRuleSection(rule, options)); + } + } + + // Scenario Outline Examples → decision tables + if (options.detailLevel !== 'summary') { + const examplesTables = extractExamplesTables(pattern); + if (examplesTables.length > 0) { + sections.push(...examplesTables); + } + } + + // See-also link + if (options.fullDocsPath) { + const slug = pattern.claudeModule ?? pattern.name.toLowerCase(); + const fullPath = `${options.fullDocsPath}${slug.toUpperCase()}.md`; + sections.push(separator()); + sections.push(linkOut(`Full Documentation`, fullPath)); + } + + return document(pattern.name, sections, { + purpose: `Claude module: ${pattern.claudeModule ?? pattern.name}`, + detailLevel: options.detailLevel, + }); +} + +// ═══════════════════════════════════════════════════════════════════════════ +// Content Extractors +// ═══════════════════════════════════════════════════════════════════════════ + +/** + * Build a Rule section (H4 heading + invariant + rationale + tables). + * + * Related: `renderRuleDescription()` in helpers.ts performs the same + * annotation-parse-to-blocks sequence but produces full-detail output + * (includes verifiedBy, codeExamples, remainingContent). This function + * intentionally produces compact output for _claude-md/ modules. + */ +function buildRuleSection( + rule: BusinessRule, + options: Required +): SectionBlock[] { + const sections: SectionBlock[] = []; + + // H2 heading from rule name (renderer offsets to H4 for _claude-md/ modules) + sections.push(heading(2, rule.name)); + + // Parse structured annotations from rule description + const annotations = parseBusinessRuleAnnotations(rule.description); + + if (annotations.invariant) { + sections.push(paragraph(`**Invariant:** ${annotations.invariant}`)); + } + + if (options.includeRationale && annotations.rationale) { + sections.push(paragraph(`**Rationale:** ${annotations.rationale}`)); + } + + // Extract and preserve tables from the rule description + if (options.includeTables) { + const tables = extractTablesAsSectionBlocks(rule.description); + for (const t of tables) { + sections.push(t); + } + } + + return sections; +} + +/** + * Extract Scenario Outline Examples tables from pattern scenarios. + */ +function extractExamplesTables(pattern: ExtractedPattern): SectionBlock[] { + const sections: SectionBlock[] = []; + + if (!pattern.scenarios) return sections; + + for (const scenario of pattern.scenarios) { + if (!scenario.steps) continue; + + for (const step of scenario.steps) { + const dt = step.dataTable; + if (dt && dt.headers.length > 0 && dt.rows.length > 0) { + const rows = dt.rows.map((row) => dt.headers.map((h) => row[h] ?? '')); + sections.push(table([...dt.headers], rows)); + } + } + } + + return sections; +} diff --git a/src/renderable/codecs/composite.ts b/src/renderable/codecs/composite.ts index d4f79348..14236726 100644 --- a/src/renderable/codecs/composite.ts +++ b/src/renderable/codecs/composite.ts @@ -7,13 +7,19 @@ * @libar-docs-arch-role projection * @libar-docs-arch-context renderer * @libar-docs-arch-layer application + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## Composite Document Codec + * ## CompositeCodec * * Assembles reference documents from multiple codec outputs by concatenating * RenderableDocument sections. Enables building documents composed from any * combination of existing codecs. * + * **Purpose:** Assembles documents from multiple child codecs into a single RenderableDocument. + * + * **Output Files:** Configured per-instance (composes child codec outputs) + * * ### When to Use * * - When building reference docs from multiple codec outputs diff --git a/src/renderable/codecs/convention-extractor.ts b/src/renderable/codecs/convention-extractor.ts index 887c27c5..f25a95d6 100644 --- a/src/renderable/codecs/convention-extractor.ts +++ b/src/renderable/codecs/convention-extractor.ts @@ -19,6 +19,7 @@ import type { MasterDataset } from '../../validation-schemas/master-dataset.js'; import type { BusinessRule, ExtractedPattern } from '../../validation-schemas/extracted-pattern.js'; import type { SectionBlock } from '../schema.js'; +import { table } from '../schema.js'; import { parseBusinessRuleAnnotations } from './helpers.js'; // ============================================================================ @@ -111,6 +112,21 @@ export function extractTablesFromDescription(description: string): ConventionTab return tables; } +/** + * Extract markdown tables from description text and return as SectionBlock tables. + * + * Adapter that wraps `extractTablesFromDescription` for codecs that need + * `SectionBlock[]` output instead of `ConventionTable[]`. + */ +export function extractTablesAsSectionBlocks(description: string): SectionBlock[] { + const conventionTables = extractTablesFromDescription(description); + return conventionTables.map((ct) => { + const headers = [...ct.headers]; + const rows = ct.rows.map((row) => headers.map((h) => row[h] ?? '')); + return table(headers, rows); + }); +} + /** * Parse a group of table lines into structured data. * @@ -122,20 +138,14 @@ function parseTableLines(lines: string[]): ConventionTable | null { // Need at least header + 1 data row if (lines.length < 2) return null; - const parseRow = (line: string): string[] => - line - .split('|') - .slice(1, -1) // Remove empty first/last from leading/trailing | - .map((cell) => cell.trim()); - const headerLine = lines[0]; if (!headerLine) return null; - const headers = parseRow(headerLine); + const headers = splitMarkdownTableRow(headerLine); // Detect whether line 2 is a markdown separator row (| --- | --- |) const secondLine = lines[1]; if (!secondLine) return null; - const secondCells = secondLine.split('|').slice(1, -1); + const secondCells = splitMarkdownTableRow(secondLine); const hasSeparator = secondCells.every((cell) => /^[\s:-]+$/.test(cell)); // Data rows start after separator (markdown) or immediately after header (Gherkin) @@ -145,7 +155,7 @@ function parseTableLines(lines: string[]): ConventionTable | null { for (let i = dataStart; i < lines.length; i++) { const dataLine = lines[i]; if (!dataLine) continue; - const cells = parseRow(dataLine); + const cells = splitMarkdownTableRow(dataLine); const row: Record = {}; for (let j = 0; j < headers.length; j++) { const header = headers[j]; @@ -159,6 +169,39 @@ function parseTableLines(lines: string[]): ConventionTable | null { return { headers, rows }; } +/** + * Split a markdown table row into cells while preserving escaped pipe content. + * + * Markdown table rows use `|` as delimiters. Content pipes must be escaped + * as `\|` and should remain part of the parsed cell value. + */ +function splitMarkdownTableRow(line: string): string[] { + const cells: string[] = []; + let current = ''; + + for (let i = 0; i < line.length; i++) { + const char: string = line[i] ?? ''; + const next: string | undefined = line[i + 1]; + + if (char === '\\' && next === '|') { + current += '|'; + i++; + continue; + } + + if (char === '|') { + cells.push(current.trim()); + current = ''; + continue; + } + + current += char; + } + + cells.push(current.trim()); + return cells.slice(1, -1); +} + // ============================================================================ // Rule Content Extraction // ============================================================================ @@ -222,13 +265,17 @@ function extractConventionRulesFromDescription( // Split by ## headings (level 2 only, not ### or deeper) // Allow optional leading whitespace for DocString content const headingPattern = /^\s*## (?!#)(.+)$/gm; - const headings: Array<{ name: string; index: number }> = []; + const headings: Array<{ name: string; index: number; matchEnd: number }> = []; let match; while ((match = headingPattern.exec(description)) !== null) { const captured = match[1]; if (captured) { - headings.push({ name: captured.trim(), index: match.index }); + headings.push({ + name: captured.trim(), + index: match.index, + matchEnd: match.index + match[0].length, + }); } } @@ -244,9 +291,11 @@ function extractConventionRulesFromDescription( if (!heading) continue; const nextIndex = i + 1 < headings.length ? (headings[i + 1]?.index ?? description.length) : description.length; - // Content starts after the heading line - const headingLineEnd = description.indexOf('\n', heading.index); - const contentStart = headingLineEnd >= 0 ? headingLineEnd + 1 : description.length; + // Content starts after the heading match (match includes the full "## Name" line) + // Use matchEnd instead of indexOf('\n', heading.index) because \s* in the regex + // can consume leading newlines, making heading.index point to those newlines + const contentStart = + heading.matchEnd < description.length ? heading.matchEnd + 1 : description.length; const content = description.slice(contentStart, nextIndex).trim(); if (content.length > 0) { @@ -287,6 +336,8 @@ export function extractConventions( ): ConventionBundle[] { if (conventionTags.length === 0) return []; + const tagSet = new Set(conventionTags); + // Build a map of conventionTag -> { sourceDecisions, rules } const bundles = new Map(); @@ -300,7 +351,7 @@ export function extractConventions( if (!pattern.convention || pattern.convention.length === 0) continue; // Check if this pattern has any of the requested convention tags - const matchingTags = pattern.convention.filter((t) => conventionTags.includes(t)); + const matchingTags = pattern.convention.filter((t) => tagSet.has(t)); if (matchingTags.length === 0) continue; // Extract rule content from Gherkin Rule: blocks or TypeScript JSDoc description diff --git a/src/renderable/codecs/index-codec.ts b/src/renderable/codecs/index-codec.ts new file mode 100644 index 00000000..95ea172b --- /dev/null +++ b/src/renderable/codecs/index-codec.ts @@ -0,0 +1,361 @@ +/** + * @libar-docs + * @libar-docs-core + * @libar-docs-pattern IndexCodec + * @libar-docs-status completed + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation + * @libar-docs-implements EnhancedIndexGeneration + * + * ## IndexCodec + * + * **Purpose:** Navigation hub composing editorial preamble with MasterDataset statistics. + * + * **Output Files:** `INDEX.md` (single page, no detail files) + * + * | Option | Type | Default | Description | + * | --- | --- | --- | --- | + * | preamble | SectionBlock[] | [] | Editorial sections (reading paths, document roles, key concepts) | + * | documentEntries | DocumentEntry[] | [] | Static document inventory entries | + * | includeProductAreaStats | boolean | true | Product area statistics table | + * | includePhaseProgress | boolean | true | Phase progress summary | + * | includeDocumentInventory | boolean | true | Unified document inventory | + * | includePackageMetadata | boolean | true | Package metadata header | + * + * ### Design Decisions + * + * - DD-1: New IndexCodec in CodecRegistry (not a ReferenceDocConfig entry) + * - DD-2: Document entries configured statically, not filesystem discovery + * - DD-3: Audience reading paths are full preamble (editorial judgment) + * - DD-4: Key concepts glossary uses preamble + * - DD-5: Standalone codec, not routed through reference codec pipeline + */ + +import { z } from 'zod'; +import { + MasterDatasetSchema, + type MasterDataset, +} from '../../validation-schemas/master-dataset.js'; +import { + type RenderableDocument, + type SectionBlock, + heading, + paragraph, + separator, + table, + document, + code, +} from '../schema.js'; +import { computeStatusCounts, completionPercentage, renderProgressBar } from '../utils.js'; +import { type BaseCodecOptions, DEFAULT_BASE_OPTIONS, mergeOptions } from './types/base.js'; +import { RenderableDocumentOutputSchema } from './shared-schema.js'; + +// ═══════════════════════════════════════════════════════════════════════════ +// Types +// ═══════════════════════════════════════════════════════════════════════════ + +/** + * A document entry for the unified inventory. + * Describes a single document in the navigation index. + */ +export interface DocumentEntry { + readonly title: string; + readonly path: string; + readonly description: string; + readonly audience: string; + readonly topic: string; +} + +/** + * Options for the IndexCodec. + */ +export interface IndexCodecOptions extends BaseCodecOptions { + /** Editorial preamble sections prepended before generated content */ + readonly preamble?: readonly SectionBlock[]; + /** Product area statistics table (default: true) */ + readonly includeProductAreaStats?: boolean; + /** Phase progress summary (default: true) */ + readonly includePhaseProgress?: boolean; + /** Unified document inventory table (default: true) */ + readonly includeDocumentInventory?: boolean; + /** Package metadata header (default: true) */ + readonly includePackageMetadata?: boolean; + /** Document entries for the unified inventory */ + readonly documentEntries?: readonly DocumentEntry[]; +} + +// ═══════════════════════════════════════════════════════════════════════════ +// Defaults +// ═══════════════════════════════════════════════════════════════════════════ + +export const DEFAULT_INDEX_OPTIONS: Required = { + ...DEFAULT_BASE_OPTIONS, + generateDetailFiles: false, + preamble: [], + includeProductAreaStats: true, + includePhaseProgress: true, + includeDocumentInventory: true, + includePackageMetadata: true, + documentEntries: [], +}; + +// ═══════════════════════════════════════════════════════════════════════════ +// Factory +// ═══════════════════════════════════════════════════════════════════════════ + +/** + * Create an IndexCodec with custom options. + * + * DD-1: Registered in CodecRegistry as document type 'index'. + * DD-5: Standalone codec, not a ReferenceDocConfig entry. + */ +export function createIndexCodec( + options?: IndexCodecOptions +): z.ZodCodec { + const opts = mergeOptions(DEFAULT_INDEX_OPTIONS, options); + + return z.codec(MasterDatasetSchema, RenderableDocumentOutputSchema, { + decode: (dataset: MasterDataset): RenderableDocument => { + return buildIndexDocument(dataset, opts); + }, + /** @throws Always - this codec is decode-only. See zod-codecs.md */ + encode: (): never => { + throw new Error('IndexCodec is decode-only. See zod-codecs.md'); + }, + }); +} + +export const IndexCodec = createIndexCodec(); + +// ═══════════════════════════════════════════════════════════════════════════ +// Document Builder +// ═══════════════════════════════════════════════════════════════════════════ + +function buildIndexDocument( + dataset: MasterDataset, + options: Required +): RenderableDocument { + const sections: SectionBlock[] = []; + + // 1. Package metadata header + if (options.includePackageMetadata) { + sections.push(...buildPackageMetadata(dataset)); + sections.push(separator()); + } + + // 2. Preamble (editorial: quick nav, reading paths, document roles, key concepts) + if (options.preamble.length > 0) { + sections.push(...options.preamble); + sections.push(separator()); + } + + // 3. Unified document inventory + if (options.includeDocumentInventory && options.documentEntries.length > 0) { + sections.push(...buildDocumentInventory(options.documentEntries)); + sections.push(separator()); + } + + // 4. Product area statistics + if (options.includeProductAreaStats) { + sections.push(...buildProductAreaStats(dataset)); + sections.push(separator()); + } + + // 5. Phase progress summary + if (options.includePhaseProgress) { + sections.push(...buildPhaseProgress(dataset)); + sections.push(separator()); + } + + // 6. Regeneration commands footer + sections.push(...buildRegenerationFooter()); + + return document('Documentation Index', sections, { + purpose: + 'Navigate the full documentation set for @libar-dev/delivery-process. ' + + 'Use section links for targeted reading.', + }); +} + +// ═══════════════════════════════════════════════════════════════════════════ +// Section Builders +// ═══════════════════════════════════════════════════════════════════════════ + +function buildPackageMetadata(dataset: MasterDataset): SectionBlock[] { + const totalPatterns = dataset.patterns.length; + const counts = computeStatusCounts(dataset.patterns); + + return [ + heading(2, 'Package Metadata'), + table( + ['Field', 'Value'], + [ + ['**Package**', '@libar-dev/delivery-process'], + ['**Purpose**', 'Code-first documentation and delivery process toolkit'], + [ + '**Patterns**', + `${totalPatterns} tracked (${counts.completed} completed, ${counts.active} active, ${counts.planned} planned)`, + ], + ['**Product Areas**', `${Object.keys(dataset.byProductArea).length}`], + ['**License**', 'MIT'], + ] + ), + ]; +} + +/** + * DD-2: Static config, not filesystem discovery. + * Groups entries by topic, renders each group as a table. + */ +function buildDocumentInventory(entries: readonly DocumentEntry[]): SectionBlock[] { + const sections: SectionBlock[] = [heading(2, 'Document Inventory')]; + + // Group by topic + const byTopic = new Map(); + for (const entry of entries) { + const group = byTopic.get(entry.topic) ?? []; + group.push(entry); + byTopic.set(entry.topic, group); + } + + for (const [topic, topicEntries] of byTopic) { + sections.push(heading(3, topic)); + sections.push( + table( + ['Document', 'Description', 'Audience'], + topicEntries.map((e) => [`[${e.title}](${e.path})`, e.description, e.audience]) + ) + ); + } + + return sections; +} + +function buildProductAreaStats(dataset: MasterDataset): SectionBlock[] { + const sections: SectionBlock[] = [heading(2, 'Product Area Statistics')]; + + const rows: string[][] = []; + let totalCompleted = 0; + let totalActive = 0; + let totalPlanned = 0; + let totalAll = 0; + + // Sort product areas alphabetically + const sortedAreas = Object.entries(dataset.byProductArea).sort(([a], [b]) => a.localeCompare(b)); + + for (const [area, patterns] of sortedAreas) { + const counts = computeStatusCounts(patterns); + const pct = completionPercentage(counts); + rows.push([ + area, + String(counts.total), + String(counts.completed), + String(counts.active), + String(counts.planned), + `${renderProgressBar(counts.completed, counts.total, 8)} ${pct}%`, + ]); + totalCompleted += counts.completed; + totalActive += counts.active; + totalPlanned += counts.planned; + totalAll += counts.total; + } + + const totalPct = totalAll > 0 ? Math.round((totalCompleted / totalAll) * 100) : 0; + rows.push([ + '**Total**', + `**${totalAll}**`, + `**${totalCompleted}**`, + `**${totalActive}**`, + `**${totalPlanned}**`, + `**${renderProgressBar(totalCompleted, totalAll, 8)} ${totalPct}%**`, + ]); + + sections.push(table(['Area', 'Patterns', 'Completed', 'Active', 'Planned', 'Progress'], rows)); + + return sections; +} + +function buildPhaseProgress(dataset: MasterDataset): SectionBlock[] { + const sections: SectionBlock[] = [heading(2, 'Phase Progress')]; + + const counts = computeStatusCounts(dataset.patterns); + const pct = completionPercentage(counts); + + sections.push( + paragraph( + `**${counts.total}** patterns total: ` + + `**${counts.completed}** completed (${pct}%), ` + + `**${counts.active}** active, ` + + `**${counts.planned}** planned. ` + + renderProgressBar(counts.completed, counts.total, 20) + ) + ); + + // Status distribution table + sections.push( + table( + ['Status', 'Count', 'Percentage'], + [ + ['Completed', String(counts.completed), `${pct}%`], + [ + 'Active', + String(counts.active), + `${counts.total > 0 ? Math.round((counts.active / counts.total) * 100) : 0}%`, + ], + [ + 'Planned', + String(counts.planned), + `${counts.total > 0 ? Math.round((counts.planned / counts.total) * 100) : 0}%`, + ], + ] + ) + ); + + // Per-phase breakdown if phases exist + if (dataset.byPhase.length > 0) { + sections.push(heading(3, 'By Phase')); + const phaseRows: string[][] = []; + for (const phaseGroup of dataset.byPhase) { + const phaseCounts = computeStatusCounts(phaseGroup.patterns); + const phasePct = completionPercentage(phaseCounts); + phaseRows.push([ + `Phase ${phaseGroup.phaseNumber}`, + String(phaseCounts.total), + String(phaseCounts.completed), + `${phasePct}%`, + ]); + } + sections.push(table(['Phase', 'Patterns', 'Completed', 'Progress'], phaseRows)); + } + + return sections; +} + +function buildRegenerationFooter(): SectionBlock[] { + return [ + heading(2, 'Regeneration'), + paragraph('Regenerate all documentation from annotated sources:'), + code( + [ + 'pnpm docs:all # Regenerate all generated docs', + 'pnpm docs:all-preview # Also generate ephemeral workflow docs', + ].join('\n'), + 'bash' + ), + paragraph('Individual generators:'), + code( + [ + 'pnpm docs:product-areas # Product area docs', + 'pnpm docs:decisions # Architecture decisions', + 'pnpm docs:reference # Reference documents', + 'pnpm docs:business-rules # Business rules', + 'pnpm docs:taxonomy # Taxonomy reference', + 'pnpm docs:validation # Validation rules', + 'pnpm docs:claude-modules # Claude context modules', + 'pnpm docs:process-api-reference # Process API CLI reference', + 'pnpm docs:cli-recipe # CLI recipes & workflow guide', + ].join('\n'), + 'bash' + ), + ]; +} diff --git a/src/renderable/codecs/index.ts b/src/renderable/codecs/index.ts index 225dc7e6..8032fee9 100644 --- a/src/renderable/codecs/index.ts +++ b/src/renderable/codecs/index.ts @@ -196,9 +196,29 @@ export { ValidationRulesCodec, createValidationRulesCodec, type ValidationRulesCodecOptions, + type RuleDefinition, DEFAULT_VALIDATION_RULES_OPTIONS, + RULE_DEFINITIONS, + composeRationaleIntoRules, } from './validation-rules.js'; +// Claude Module (includes ClaudeModuleCodecOptions) +export { + ClaudeModuleCodec, + createClaudeModuleCodec, + type ClaudeModuleCodecOptions, + DEFAULT_CLAUDE_MODULE_OPTIONS, +} from './claude-module.js'; + +// Index (navigation hub with MasterDataset statistics + editorial preamble) +export { + IndexCodec, + createIndexCodec, + type IndexCodecOptions, + type DocumentEntry, + DEFAULT_INDEX_OPTIONS, +} from './index-codec.js'; + // Convention Extractor export { extractConventions, diff --git a/src/renderable/codecs/patterns.ts b/src/renderable/codecs/patterns.ts index 51839cc6..fac8e643 100644 --- a/src/renderable/codecs/patterns.ts +++ b/src/renderable/codecs/patterns.ts @@ -8,12 +8,26 @@ * @libar-docs-arch-layer application * @libar-docs-include codec-transformation,pipeline-stages * @libar-docs-implements PatternRelationshipModel + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## Patterns Document Codec + * ## PatternsDocumentCodec * * Transforms MasterDataset into a RenderableDocument for pattern registry output. * Generates PATTERNS.md and category detail files (patterns/*.md). * + * **Purpose:** Pattern registry with category-based organization. + * + * **Output Files:** `PATTERNS.md` (main index), `patterns/.md` (category details) + * + * | Option | Type | Default | Description | + * | --- | --- | --- | --- | + * | generateDetailFiles | boolean | true | Create category detail files | + * | detailLevel | "summary" \| "standard" \| "detailed" | "standard" | Output verbosity | + * | includeDependencyGraph | boolean | true | Render Mermaid dependency graph | + * | includeUseCases | boolean | true | Show use cases section | + * | filterCategories | string[] | [] | Filter to specific categories (empty = all) | + * * ### When to Use * * - When generating the pattern registry documentation (PATTERNS.md) diff --git a/src/renderable/codecs/planning.ts b/src/renderable/codecs/planning.ts index 3abf7edd..c8f53aa4 100644 --- a/src/renderable/codecs/planning.ts +++ b/src/renderable/codecs/planning.ts @@ -3,19 +3,51 @@ * @libar-docs-core * @libar-docs-pattern PlanningCodecs * @libar-docs-status completed + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## Planning Document Codecs + * ## PlanningChecklistCodec * - * Transforms MasterDataset into RenderableDocuments for planning outputs: - * - PLANNING-CHECKLIST.md (pre-planning questions and DoD) - * - SESSION-PLAN.md (implementation plans for phases) - * - SESSION-FINDINGS.md (retrospective discoveries) + * **Purpose:** Pre-planning questions and Definition of Done validation. + * + * **Output Files:** `PLANNING-CHECKLIST.md` + * + * ### When to Use + * + * - When starting a new implementation session and need pre-flight validation + * - When generating Definition of Done checklists for active phases + * - When checking readiness criteria before transitioning patterns to active + * + * ## SessionPlanCodec + * + * **Purpose:** Implementation plans for coding sessions. + * + * **Output Files:** `SESSION-PLAN.md` * * ### When to Use * - * - When generating planning documentation for implementation sessions - * - When creating pre-planning checklists with Definition of Done - * - When documenting session findings and retrospective discoveries + * - When generating a structured implementation plan for an active coding session + * - When documenting planned deliverables and their execution order + * - When creating session-scoped plans aligned with FSM transitions + * + * ## SessionFindingsCodec + * + * **Purpose:** Retrospective discoveries for roadmap refinement. + * + * **Output Files:** `SESSION-FINDINGS.md` + * + * ### When to Use + * + * - When capturing session retrospective findings across all patterns + * - When surfacing discovered gaps, improvements, risks, and learnings + * - When refining roadmap priorities based on implementation discoveries + * + * ### Finding Sources + * + * - `pattern.discoveredGaps` -- Gap findings + * - `pattern.discoveredImprovements` -- Improvement suggestions + * - `pattern.discoveredRisks` / `pattern.risk` -- Risk findings + * - `pattern.discoveredLearnings` -- Learned insights */ import { z } from 'zod'; diff --git a/src/renderable/codecs/pr-changes.ts b/src/renderable/codecs/pr-changes.ts index 6886c862..900675b6 100644 --- a/src/renderable/codecs/pr-changes.ts +++ b/src/renderable/codecs/pr-changes.ts @@ -3,12 +3,18 @@ * @libar-docs-core * @libar-docs-pattern PrChangesCodec * @libar-docs-status completed + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## PR Changes Document Codec + * ## PrChangesCodec * * Transforms MasterDataset into RenderableDocument for PR-scoped output. * Filters patterns by changed files and/or release version tags. * + * **Purpose:** PR-scoped view filtered by changed files or release version. + * + * **Output Files:** `working/PR-CHANGES.md` + * * ### When to Use * * - When generating PR summaries filtered by changed files diff --git a/src/renderable/codecs/reference.ts b/src/renderable/codecs/reference.ts index 5700ceb0..0724a491 100644 --- a/src/renderable/codecs/reference.ts +++ b/src/renderable/codecs/reference.ts @@ -3,17 +3,65 @@ * @libar-docs-pattern ReferenceDocumentCodec * @libar-docs-status active * @libar-docs-implements CodecDrivenReferenceGeneration + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## Parameterized Reference Document Codec + * ## ReferenceDocumentCodec * * A single codec factory that creates reference document codecs from * configuration objects. Convention content is sourced from * decision records tagged with @libar-docs-convention. * + * **Purpose:** Scoped reference documentation assembling four content layers (conventions, diagrams, shapes, behaviors) into a single document. + * + * **Output Files:** Configured per-instance (e.g., `docs/REFERENCE-SAMPLE.md`, `_claude-md/architecture/reference-sample.md`) + * + * ### 4-Layer Composition (in order) + * + * 1. **Convention content** -- Extracted from `@libar-docs-convention`-tagged patterns (rules, invariants, tables) + * 2. **Scoped diagrams** -- Mermaid diagrams filtered by `archContext`, `archLayer`, `patterns`, or `include` tags + * 3. **TypeScript shapes** -- API surfaces from `shapeSources` globs or `shapeSelectors` (declaration-level filtering) + * 4. **Behavior content** -- Gherkin-sourced patterns from `behaviorCategories` + * + * ### Key Options (ReferenceDocConfig) + * + * | Option | Type | Description | + * | --- | --- | --- | + * | conventionTags | string[] | Convention tag values to extract from decision records | + * | diagramScope | DiagramScope | Single diagram configuration | + * | diagramScopes | DiagramScope[] | Multiple diagrams (takes precedence over diagramScope) | + * | shapeSources | string[] | Glob patterns for TypeScript shape extraction | + * | shapeSelectors | ShapeSelector[] | Fine-grained declaration-level shape filtering | + * | behaviorCategories | string[] | Category tags for behavior pattern content | + * | includeTags | string[] | Cross-cutting content routing via include tags | + * | preamble | SectionBlock[] | Static editorial sections prepended before generated content | + * | productArea | string | Pre-filter all content sources to matching product area | + * | excludeSourcePaths | string[] | Exclude patterns by source path prefix | + * + * ### DiagramScope.diagramType Values + * + * | Type | Description | + * | --- | --- | + * | graph (default) | Flowchart with subgraphs by archContext, custom node shapes | + * | sequenceDiagram | Sequence diagram with typed messages between participants | + * | stateDiagram-v2 | State diagram with transitions from dependsOn relationships | + * | C4Context | C4 context diagram with boundaries, systems, and relationships | + * | classDiagram | Class diagram with archRole stereotypes and typed arrows | + * + * ### ShapeSelector Variants + * + * | Variant | Example | Behavior | + * | --- | --- | --- | + * | group only | `{ group: "api-types" }` | Match shapes by group tag | + * | source + names | `{ source: "src/types.ts", names: ["Config"] }` | Named shapes from file | + * | source only | `{ source: "src/path/*.ts" }` | All tagged shapes from glob | + * * ### When to Use * * - When generating reference documentation from convention-tagged decisions + * - When creating scoped product area documents with live diagrams * - When creating both detailed (docs/) and summary (_claude-md/) outputs + * - When assembling multi-layer documents that combine conventions, diagrams, shapes, and behaviors * * ### Factory Pattern * @@ -31,6 +79,7 @@ import { import { type RenderableDocument, type SectionBlock, + type HeadingBlock, heading, paragraph, separator, @@ -53,10 +102,8 @@ import { RenderableDocumentOutputSchema } from './shared-schema.js'; import { extractConventions, extractConventionsFromPatterns, - extractTablesFromDescription, type ConventionBundle, } from './convention-extractor.js'; -import type { BusinessRuleAnnotations } from './helpers.js'; import { parseBusinessRuleAnnotations, truncateText } from './helpers.js'; import { extractShapesFromDataset, filterShapesBySelectors } from './shape-matcher.js'; import type { ShapeSelector } from './shape-matcher.js'; @@ -72,7 +119,7 @@ import { VALID_TRANSITIONS } from '../../validation/fsm/transitions.js'; import { PROTECTION_LEVELS, type ProtectionLevel } from '../../validation/fsm/states.js'; import type { ProcessStatusValue } from '../../taxonomy/index.js'; import type { ExtractedPattern } from '../../validation-schemas/extracted-pattern.js'; -import { camelCaseToTitleCase } from '../../utils/string-utils.js'; +import { camelCaseToTitleCase, slugify } from '../../utils/string-utils.js'; import type { ExtractedShape } from '../../validation-schemas/extracted-shape.js'; // ============================================================================ @@ -80,7 +127,11 @@ import type { ExtractedShape } from '../../validation-schemas/extracted-shape.js // ============================================================================ /** Content source identifiers for hardcoded domain diagrams */ -export const DIAGRAM_SOURCE_VALUES = ['fsm-lifecycle', 'generation-pipeline'] as const; +export const DIAGRAM_SOURCE_VALUES = [ + 'fsm-lifecycle', + 'generation-pipeline', + 'master-dataset-views', +] as const; /** Discriminated source type for DiagramScope.source */ export type DiagramSource = (typeof DIAGRAM_SOURCE_VALUES)[number]; @@ -129,6 +180,7 @@ export interface DiagramScope { * instead of computing from pattern relationships. * - 'fsm-lifecycle': FSM state transitions with protection levels * - 'generation-pipeline': 4-stage generation pipeline temporal flow + * - 'master-dataset-views': MasterDataset pre-computed view fan-out */ readonly source?: DiagramSource; } @@ -190,6 +242,16 @@ export interface ReferenceDocConfig { * @example ['delivery-process/specs/'] */ readonly excludeSourcePaths?: readonly string[]; + + /** + * Static preamble sections prepended before all generated content. + * Use for editorial intro prose that cannot be expressed as annotations. + * Appears in both detailed and summary outputs. + */ + readonly preamble?: readonly SectionBlock[]; + + /** When true, shapes section renders before conventions (default: false) */ + readonly shapesFirst?: boolean; } // ============================================================================ @@ -225,6 +287,8 @@ export interface ProductAreaMeta { readonly covers: string; /** 2-4 sentence intro explaining what this area does and why it matters */ readonly intro: string; + /** Additional structured content rendered after intro at 'detailed' level only */ + readonly introSections?: readonly SectionBlock[]; /** Live diagram scopes generated from annotation data (overrides auto-generated diagram) */ readonly diagramScopes?: readonly DiagramScope[]; /** Key invariants to surface prominently (curated from executable specs) */ @@ -318,16 +382,67 @@ export const PRODUCT_AREA_META: Readonly> = { }, Generation: { question: 'How does code become docs?', - covers: 'Codecs, generators, rendering, diagrams', + covers: + 'Codecs, generators, orchestrator, rendering, diagrams, progressive disclosure, product areas, RenderableDocument IR', intro: - 'The generation pipeline transforms annotated source code into markdown documents. ' + - 'It follows a four-stage architecture: Scanner → Extractor → Transformer → Codec. ' + - 'Codecs are pure functions — given a MasterDataset, they produce a RenderableDocument ' + - 'without side effects. CompositeCodec composes multiple codecs into a single document.', + 'The generation pipeline transforms annotated source code into markdown documents through a ' + + 'four-stage architecture: Scanner discovers files, Extractor produces `ExtractedPattern` objects, ' + + 'Transformer builds MasterDataset with pre-computed views, and Codecs render to markdown via ' + + 'RenderableDocument IR. Nine specialized codecs handle reference docs, planning, session, reporting, ' + + 'timeline, ADRs, business rules, taxonomy, and composite output — each supporting three detail levels ' + + '(detailed, standard, summary). The Orchestrator runs generators in registration order, producing both ' + + 'detailed `docs-live/` references and compact `_claude-md/` summaries.', + introSections: [ + heading(3, 'Pipeline Stages'), + table( + ['Stage', 'Module', 'Responsibility'], + [ + ['Scanner', '`src/scanner/`', 'File discovery, AST parsing, opt-in via `@libar-docs`'], + [ + 'Extractor', + '`src/extractor/`', + 'Pattern extraction from TypeScript JSDoc and Gherkin tags', + ], + [ + 'Transformer', + '`src/generators/pipeline/`', + 'MasterDataset with pre-computed views for O(1) access (ADR-006)', + ], + [ + 'Codec', + '`src/renderable/`', + 'Pure functions: MasterDataset → RenderableDocument → Markdown', + ], + ] + ), + heading(3, 'Codec Inventory'), + table( + ['Codec', 'Purpose'], + [ + [ + 'ReferenceDocumentCodec', + 'Conventions, diagrams, shapes, behaviors (4-layer composition)', + ], + ['PlanningCodec', 'Roadmap and remaining work'], + ['SessionCodec', 'Current work and session findings'], + ['ReportingCodec', 'Changelog'], + ['TimelineCodec', 'Timeline and traceability'], + ['RequirementsAdrCodec', 'ADR generation'], + ['BusinessRulesCodec', 'Gherkin rule extraction'], + ['TaxonomyCodec', 'Tag registry docs'], + ['CompositeCodec', 'Composes multiple codecs into a single document'], + ] + ), + ], keyInvariants: [ 'Codec purity: Every codec is a pure function (dataset in, document out). No side effects, no filesystem access. Same input always produces same output', + 'Single read model (ADR-006): All codecs consume MasterDataset. No codec reads raw scanner/extractor output. Anti-patterns: Parallel Pipeline, Lossy Local Type, Re-derived Relationship', + 'Progressive disclosure: Every document renders at three detail levels (detailed, standard, summary) from the same codec. Summary feeds `_claude-md/` modules; detailed feeds `docs-live/reference/`', 'Config-driven generation: A single `ReferenceDocConfig` produces a complete document. Content sources compose in fixed order: conventions, diagrams, shapes, behaviors', 'RenderableDocument IR: Codecs express intent ("this is a table"), the renderer handles syntax ("pipe-delimited markdown"). Switching output format requires only a new renderer', + 'Composition order: Reference docs compose four content layers in fixed order. Product area docs compose five layers: intro, conventions, diagrams, shapes, business rules', + 'Shape extraction: TypeScript shapes (`interface`, `type`, `enum`, `function`, `const`) are extracted by declaration-level `@libar-docs-shape` tags. Shapes include source text, JSDoc, type parameters, and property documentation', + 'Generator registration: Generators self-register via `registerGenerator()`. The orchestrator runs them in registration order. Each generator owns its output files and codec configuration', ], keyPatterns: [ 'ADR005CodecBasedMarkdownRendering', @@ -335,6 +450,9 @@ export const PRODUCT_AREA_META: Readonly> = { 'CrossCuttingDocumentInclusion', 'ArchitectureDiagramGeneration', 'ScopedArchitecturalView', + 'CompositeCodec', + 'RenderableDocument', + 'ProductAreaOverview', ], }, Validation: { @@ -515,6 +633,7 @@ export function createReferenceCodec( const sections: SectionBlock[] = []; // Product area filtering: when set, pre-filter and auto-derive content sources + // Preamble is applied inside decodeProductArea() — not here, to avoid dead code if (config.productArea !== undefined) { return decodeProductArea(dataset, config, opts); } @@ -545,11 +664,11 @@ export function createReferenceCodec( } } - if (conventions.length > 0) { - sections.push(...buildConventionSections(conventions, opts.detailLevel)); - } + const conventionBlocks = + conventions.length > 0 ? buildConventionSections(conventions, opts.detailLevel) : []; // 2. Scoped relationship diagrams (normalize singular to array) + const diagramBlocks: SectionBlock[] = []; if (opts.detailLevel !== 'summary') { const scopes: readonly DiagramScope[] = config.diagramScopes ?? (config.diagramScope !== undefined ? [config.diagramScope] : []); @@ -557,22 +676,23 @@ export function createReferenceCodec( for (const scope of scopes) { const diagramSections = buildScopedDiagram(dataset, scope); if (diagramSections.length > 0) { - sections.push(...diagramSections); + diagramBlocks.push(...diagramSections); } } } // 3. Shape extraction: combine shapeSources (coarse) + shapeSelectors (fine) + const shapeBlocks: SectionBlock[] = []; { const allShapes = config.shapeSources.length > 0 ? [...extractShapesFromDataset(dataset, config.shapeSources)] : ([] as ExtractedShape[]); + const seenNames = new Set(allShapes.map((s) => s.name)); // DD-3/DD-6: Fine-grained selector-based filtering if (config.shapeSelectors !== undefined && config.shapeSelectors.length > 0) { const selectorShapes = filterShapesBySelectors(dataset, config.shapeSelectors); - const seenNames = new Set(allShapes.map((s) => s.name)); for (const shape of selectorShapes) { if (!seenNames.has(shape.name)) { seenNames.add(shape.name); @@ -583,7 +703,6 @@ export function createReferenceCodec( // DD-1: Merge include-tagged shapes (additive) if (includeSet !== undefined) { - const seenNames = new Set(allShapes.map((s) => s.name)); for (const pattern of dataset.patterns) { if (pattern.extractedShapes === undefined || pattern.extractedShapes.length === 0) continue; @@ -600,7 +719,7 @@ export function createReferenceCodec( } if (allShapes.length > 0) { - sections.push(...buildShapeSections(allShapes, opts.detailLevel)); + shapeBlocks.push(...buildShapeSections(allShapes, opts.detailLevel)); } } @@ -622,8 +741,22 @@ export function createReferenceCodec( behaviorPatterns.push(...includedBehaviors); } - if (behaviorPatterns.length > 0) { - sections.push(...buildBehaviorSectionsFromPatterns(behaviorPatterns, opts.detailLevel)); + const behaviorBlocks = + behaviorPatterns.length > 0 + ? buildBehaviorSectionsFromPatterns(behaviorPatterns, opts.detailLevel) + : []; + + // Static preamble: editorial sections before generated content + if (config.preamble !== undefined && config.preamble.length > 0) { + sections.push(...config.preamble); + sections.push(separator()); + } + + // DD-4 (GeneratedDocQuality): Assemble in configured order + if (config.shapesFirst === true) { + sections.push(...shapeBlocks, ...conventionBlocks, ...diagramBlocks, ...behaviorBlocks); + } else { + sections.push(...conventionBlocks, ...diagramBlocks, ...shapeBlocks, ...behaviorBlocks); } if (sections.length === 0) { @@ -686,10 +819,17 @@ function decodeProductArea( } const sections: SectionBlock[] = []; - // Pre-filter patterns by product area - const areaPatterns = dataset.patterns.filter((p) => p.productArea === area); + // Static preamble: editorial sections before generated content + if (config.preamble !== undefined && config.preamble.length > 0) { + sections.push(...config.preamble); + sections.push(separator()); + } + + // Pre-computed view: O(1) lookup instead of linear filter + const areaPatterns = dataset.byProductArea[area] ?? []; - // Also collect TypeScript patterns by archContext mapping (for shapes + diagrams) + // Collect TypeScript patterns by explicit archContext tag (for shapes + diagrams) + // Note: archIndex.byContext includes inferred contexts — use explicit filter to match only tagged patterns const archContexts = PRODUCT_AREA_ARCH_CONTEXT_MAP[area] ?? []; const contextSet = new Set(archContexts); const tsPatterns = @@ -697,17 +837,15 @@ function decodeProductArea( ? dataset.patterns.filter((p) => p.archContext !== undefined && contextSet.has(p.archContext)) : []; - // Combined set of all relevant patterns (deduplicated) - const allRelevantNames = new Set([ - ...areaPatterns.map((p) => p.name), - ...tsPatterns.map((p) => p.name), - ]); - // 1. Intro section from ADR-001 metadata with key invariants const meta = PRODUCT_AREA_META[area]; if (meta !== undefined) { sections.push(paragraph(`**${meta.question}** ${meta.intro}`)); + if (meta.introSections !== undefined && opts.detailLevel === 'detailed') { + sections.push(...meta.introSections); + } + if (meta.keyInvariants.length > 0) { sections.push(heading(2, 'Key Invariants')); sections.push(list([...meta.keyInvariants])); @@ -742,7 +880,7 @@ function decodeProductArea( sections.push(...diagramSections); } } - } else if (contextSet.size > 0) { + } else if (archContexts.length > 0) { // Auto-generate fallback — only when archContext mappings exist const autoScope: DiagramScope = { archContext: archContexts, @@ -767,10 +905,12 @@ function decodeProductArea( { const allShapes: ExtractedShape[] = []; const seenNames = new Set(); + const seenPatternNames = new Set(); // Collect shapes from all patterns associated with this area - for (const pattern of dataset.patterns) { - if (!allRelevantNames.has(pattern.name)) continue; + for (const pattern of [...areaPatterns, ...tsPatterns]) { + if (seenPatternNames.has(pattern.name)) continue; + seenPatternNames.add(pattern.name); if (pattern.extractedShapes === undefined || pattern.extractedShapes.length === 0) continue; for (const shape of pattern.extractedShapes) { if (!seenNames.has(shape.name)) { @@ -831,6 +971,15 @@ function decodeProductArea( sections.push(...buildBusinessRulesCompactSection(rulesPatterns, opts.detailLevel)); } + // DD-4 (GeneratedDocQuality): Insert TOC after intro for large product area docs + const tocBlocks = buildTableOfContents(sections); + if (tocBlocks.length > 0) { + const firstSepIdx = sections.findIndex((s) => s.type === 'separator'); + if (firstSepIdx >= 0) { + sections.splice(firstSepIdx + 1, 0, ...tocBlocks); + } + } + if (sections.length === 0) { sections.push( paragraph( @@ -962,13 +1111,6 @@ function buildBehaviorSectionsFromPatterns( ruleBlocks.push(paragraph(annotations.remainingContent)); } - // Extract and render tables from Rule descriptions (Gherkin or markdown) - const ruleTables = extractTablesFromDescription(rule.description); - for (const tbl of ruleTables) { - const rows = tbl.rows.map((row) => tbl.headers.map((h) => row[h] ?? '')); - ruleBlocks.push(table([...tbl.headers], rows)); - } - if (annotations.codeExamples && detailLevel === 'detailed') { for (const example of annotations.codeExamples) { ruleBlocks.push(example); @@ -1024,18 +1166,15 @@ function buildBusinessRulesCompactSection( const sections: SectionBlock[] = []; - // Count totals for header + // Count totals for header (lightweight pass — no annotation parsing) let totalRules = 0; let totalInvariants = 0; - const annotationsCache = new Map(); for (const p of patterns) { if (p.rules === undefined) continue; for (const r of p.rules) { totalRules++; - const ann = parseBusinessRuleAnnotations(r.description); - annotationsCache.set(`${p.name}::${r.name}`, ann); - if (ann.invariant !== undefined) totalInvariants++; + if (r.description.includes('**Invariant:**')) totalInvariants++; } } @@ -1061,7 +1200,7 @@ function buildBusinessRulesCompactSection( const rows: string[][] = []; for (const rule of pattern.rules) { - const ann = annotationsCache.get(`${pattern.name}::${rule.name}`) ?? {}; + const ann = parseBusinessRuleAnnotations(rule.description); // At standard level, skip rules without invariant if (!isDetailed && ann.invariant === undefined) continue; @@ -1086,6 +1225,28 @@ function buildBusinessRulesCompactSection( return sections; } +/** + * Build a table of contents from H2 headings in a sections array. + * + * DD-4 (GeneratedDocQuality): Product area docs can be 100+ KB with many + * sections. A TOC at the top makes browser navigation practical. Only + * generated when there are 3 or more H2 headings (below that, a TOC adds + * noise without navigation value). + */ +function buildTableOfContents(allSections: readonly SectionBlock[]): SectionBlock[] { + const h2Headings = allSections.filter( + (s): s is HeadingBlock => s.type === 'heading' && s.level === 2 + ); + if (h2Headings.length < 3) return []; + + const tocItems = h2Headings.map((h) => { + const anchor = slugify(h.text); + return `[${h.text}](#${anchor})`; + }); + + return [heading(2, 'Contents'), list(tocItems), separator()]; +} + /** * Build sections from extracted TypeScript shapes. * @@ -1663,6 +1824,22 @@ function buildGenerationPipelineSequenceDiagram(): string[] { ]; } +/** Build MasterDataset fan-out diagram from hardcoded domain knowledge */ +function buildMasterDatasetViewsDiagram(): string[] { + return [ + 'graph TB', + ' MD[MasterDataset]', + ' MD --> byStatus["byStatus
(completed / active / planned)"]', + ' MD --> byPhase["byPhase
(sorted, with counts)"]', + ' MD --> byQuarter["byQuarter
(keyed by Q-YYYY)"]', + ' MD --> byCategory["byCategory
(keyed by category name)"]', + ' MD --> bySource["bySource
(typescript / gherkin / roadmap / prd)"]', + ' MD --> counts["counts
(aggregate statistics)"]', + ' MD --> RI["relationshipIndex?
(forward + reverse lookups)"]', + ' MD --> AI["archIndex?
(role / context / layer / view)"]', + ]; +} + /** Build a Mermaid C4 context diagram with system boundaries */ function buildC4Diagram(ctx: DiagramContext, scope: DiagramScope): string[] { const showLabels = scope.showEdgeLabels !== false; @@ -1840,6 +2017,14 @@ export function buildScopedDiagram(dataset: MasterDataset, scope: DiagramScope): separator(), ]; } + if (scope.source === 'master-dataset-views') { + return [ + heading(2, title), + paragraph('Pre-computed view fan-out from MasterDataset (single-pass transform):'), + mermaid(buildMasterDatasetViewsDiagram().join('\n')), + separator(), + ]; + } const ctx = prepareDiagramContext(dataset, scope); if (ctx === undefined) return []; diff --git a/src/renderable/codecs/reporting.ts b/src/renderable/codecs/reporting.ts index 1acfb804..739eedaf 100644 --- a/src/renderable/codecs/reporting.ts +++ b/src/renderable/codecs/reporting.ts @@ -3,19 +3,44 @@ * @libar-docs-core * @libar-docs-pattern ReportingCodecs * @libar-docs-status completed + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## Reporting Document Codecs + * ## ChangelogCodec * - * Transforms MasterDataset into RenderableDocuments for reporting outputs: - * - CHANGELOG-GENERATED.md (Keep a Changelog format) - * - TRACEABILITY.md (Timeline to behavior file coverage) - * - OVERVIEW.md (Project architecture overview) + * **Purpose:** Keep a Changelog format changelog grouped by release version. + * + * **Output Files:** `CHANGELOG.md` + * + * | Option | Type | Default | Description | + * | --- | --- | --- | --- | + * | includeUnreleased | boolean | true | Include unreleased section | + * | includeLinks | boolean | true | Include links | + * | categoryMapping | Record | {} | Map categories to changelog types | + * + * ## TraceabilityCodec + * + * **Purpose:** Timeline to behavior file coverage report. + * + * **Output Files:** `TRACEABILITY.md` + * + * ### When to Use + * + * - When auditing which timeline patterns have associated behavior specifications + * - When checking feature file coverage across roadmap phases + * - When identifying patterns missing executable specs + * + * ## OverviewCodec + * + * **Purpose:** Project architecture and status overview. + * + * **Output Files:** `OVERVIEW.md` * * ### When to Use * - * - When generating changelogs in Keep a Changelog format - * - When creating traceability reports for spec-to-test coverage - * - When building project overview documentation + * - When generating a high-level project dashboard with architecture summary + * - When providing stakeholder-facing status reports + * - When combining completion stats with architecture context */ import { z } from 'zod'; diff --git a/src/renderable/codecs/requirements.ts b/src/renderable/codecs/requirements.ts index 6743b7b4..67d97272 100644 --- a/src/renderable/codecs/requirements.ts +++ b/src/renderable/codecs/requirements.ts @@ -3,12 +3,27 @@ * @libar-docs-core * @libar-docs-pattern RequirementsCodec * @libar-docs-status completed + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## Requirements Document Codec + * ## RequirementsDocumentCodec * * Transforms MasterDataset into RenderableDocument for PRD/requirements output. * Generates PRODUCT-REQUIREMENTS.md and detail files (requirements/*.md). * + * **Purpose:** Product requirements documentation grouped by product area or user role. + * + * **Output Files:** `PRODUCT-REQUIREMENTS.md` (main index), `requirements/.md` (area details) + * + * | Option | Type | Default | Description | + * | --- | --- | --- | --- | + * | generateDetailFiles | boolean | true | Create product area detail files | + * | groupBy | "product-area" \| "user-role" \| "phase" | "product-area" | Primary grouping | + * | filterStatus | NormalizedStatusFilter[] | [] | Filter by status (empty = all) | + * | includeScenarioSteps | boolean | true | Show Given/When/Then steps | + * | includeBusinessValue | boolean | true | Display business value metadata | + * | includeBusinessRules | boolean | true | Show Gherkin Rule: sections | + * * ### When to Use * * - When generating product requirements documentation diff --git a/src/renderable/codecs/session.ts b/src/renderable/codecs/session.ts index ad3fa919..b78d09c3 100644 --- a/src/renderable/codecs/session.ts +++ b/src/renderable/codecs/session.ts @@ -7,26 +7,35 @@ * @libar-docs-arch-context renderer * @libar-docs-arch-layer application * @libar-docs-include codec-transformation + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## Session Document Codec + * ## SessionContextCodec * - * Transforms MasterDataset into RenderableDocuments for session/planning outputs: - * - SESSION-CONTEXT.md (current session context) - * - REMAINING-WORK.md (incomplete work aggregation) + * **Purpose:** Current session context for AI agents and developers. + * + * **Output Files:** `SESSION-CONTEXT.md` (session status), `sessions/phase--.md` (incomplete phase details) * * ### When to Use * - * - When generating session context for Claude Code integration - * - When tracking remaining work and incomplete deliverables - * - When building session handoff documentation + * - When starting a new implementation session and need to see active work status + * - When generating compact context for AI agent consumption (_claude-md/ output) + * - When checking incomplete phases and their deliverable progress * - * ### Factory Pattern + * ## RemainingWorkCodec * - * Use factory functions for custom options: - * ```typescript - * const codec = createSessionContextCodec({ includeRelatedPatterns: true }); - * const remainingCodec = createRemainingWorkCodec({ sortBy: "priority" }); - * ``` + * **Purpose:** Aggregate view of all incomplete work across phases. + * + * **Output Files:** `REMAINING-WORK.md` (summary), `remaining/phase--.md` (phase details) + * + * | Option | Type | Default | Description | + * | --- | --- | --- | --- | + * | includeIncomplete | boolean | true | Include planned items | + * | includeBlocked | boolean | true | Show blocked items analysis | + * | includeNextActionable | boolean | true | Next actionable items section | + * | maxNextActionable | number | 5 | Max items in next actionable | + * | sortBy | "phase" \| "priority" \| "effort" \| "quarter" | "phase" | Sort order | + * | groupPlannedBy | "quarter" \| "priority" \| "level" \| "none" | "none" | Group planned items | */ import { z } from 'zod'; diff --git a/src/renderable/codecs/taxonomy.ts b/src/renderable/codecs/taxonomy.ts index 00479511..2870caed 100644 --- a/src/renderable/codecs/taxonomy.ts +++ b/src/renderable/codecs/taxonomy.ts @@ -3,12 +3,25 @@ * @libar-docs-core * @libar-docs-pattern TaxonomyCodec * @libar-docs-status completed + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## Taxonomy Document Codec + * ## TaxonomyDocumentCodec * * Transforms MasterDataset into a RenderableDocument for taxonomy reference output. * Generates TAXONOMY.md and detail files (taxonomy/*.md). * + * **Purpose:** Taxonomy reference documentation with tag definitions, preset comparison, and format type reference. + * + * **Output Files:** `TAXONOMY.md` (main reference), `taxonomy/.md` (domain details) + * + * | Option | Type | Default | Description | + * | --- | --- | --- | --- | + * | includePresets | boolean | true | Include preset comparison table | + * | includeFormatTypes | boolean | true | Include format type reference | + * | includeArchDiagram | boolean | true | Include architecture diagram | + * | groupByDomain | boolean | true | Group metadata tags by domain | + * * ### When to Use * * - When generating the taxonomy reference documentation (TAXONOMY.md) diff --git a/src/renderable/codecs/timeline.ts b/src/renderable/codecs/timeline.ts index 78faa9d5..4ba2daa7 100644 --- a/src/renderable/codecs/timeline.ts +++ b/src/renderable/codecs/timeline.ts @@ -3,26 +3,46 @@ * @libar-docs-core * @libar-docs-pattern TimelineCodec * @libar-docs-status completed + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## Timeline Document Codec + * ## RoadmapDocumentCodec * - * Transforms MasterDataset into RenderableDocuments for timeline outputs: - * - ROADMAP.md (phase breakdown with progress) - * - COMPLETED-MILESTONES.md (historical completed phases) + * **Purpose:** Development roadmap organized by phase with progress tracking. + * + * **Output Files:** `ROADMAP.md` (main roadmap), `phases/phase--.md` (phase details) + * + * | Option | Type | Default | Description | + * | --- | --- | --- | --- | + * | generateDetailFiles | boolean | true | Create phase detail files | + * | filterStatus | NormalizedStatusFilter[] | [] | Filter by status | + * | includeProcess | boolean | true | Show quarter, effort, team metadata | + * | includeDeliverables | boolean | true | List deliverables per phase | + * | filterPhases | number[] | [] | Filter to specific phases | + * + * ## CompletedMilestonesCodec + * + * **Purpose:** Historical record of completed work organized by quarter. + * + * **Output Files:** `COMPLETED-MILESTONES.md` (summary), `milestones/.md` (quarter details) * * ### When to Use * - * - When generating roadmap documentation by phase - * - When tracking completed milestones and historical progress - * - When building timeline-based project views + * - When documenting project history and completed phases + * - When generating quarterly achievement summaries + * - When tracking velocity by quarter * - * ### Factory Pattern + * ## CurrentWorkCodec * - * Use factory functions for custom options: - * ```typescript - * const codec = createRoadmapCodec({ generateDetailFiles: false }); - * const doc = codec.decode(dataset); - * ``` + * **Purpose:** Active development work currently in progress. + * + * **Output Files:** `CURRENT-WORK.md` (summary), `current/phase--.md` (active phase details) + * + * ### When to Use + * + * - When monitoring active development across all in-progress phases + * - When generating sprint/session status dashboards + * - When checking which patterns are currently being worked on */ import { z } from 'zod'; diff --git a/src/renderable/codecs/validation-rules.ts b/src/renderable/codecs/validation-rules.ts index d48da961..5910a6f0 100644 --- a/src/renderable/codecs/validation-rules.ts +++ b/src/renderable/codecs/validation-rules.ts @@ -3,12 +3,26 @@ * @libar-docs-core * @libar-docs-pattern ValidationRulesCodec * @libar-docs-status completed + * @libar-docs-convention codec-registry + * @libar-docs-product-area:Generation * - * ## Validation Rules Document Codec + * ## ValidationRulesCodec * * Transforms MasterDataset into a RenderableDocument for Process Guard validation * rules reference. Generates VALIDATION-RULES.md and detail files (validation/*.md). * + * **Purpose:** Process Guard validation rules reference with FSM diagrams and protection level matrix. + * + * **Output Files:** `VALIDATION-RULES.md` (main reference), `validation/.md` (category details) + * + * | Option | Type | Default | Description | + * | --- | --- | --- | --- | + * | includeFSMDiagram | boolean | true | Include FSM state diagram | + * | includeCLIUsage | boolean | true | Include CLI usage section | + * | includeEscapeHatches | boolean | true | Include escape hatches section | + * | includeProtectionMatrix | boolean | true | Include protection levels matrix | + * | includeErrorGuide | boolean | true | Include error guide with rationale and alternatives | + * * ### When to Use * * - When generating validation rules reference documentation @@ -75,6 +89,9 @@ export interface ValidationRulesCodecOptions extends BaseCodecOptions { /** Include protection levels matrix (default: true) */ includeProtectionMatrix?: boolean; + + /** Include error guide with rationale and alternatives (default: true) */ + includeErrorGuide?: boolean; } /** @@ -86,6 +103,7 @@ export const DEFAULT_VALIDATION_RULES_OPTIONS: Required +): RuleDefinition[] { + return rules.map((rule) => { + const content = conventionContent.get(rule.id); + if (content) { + const enriched: RuleDefinition = { + ...rule, + rationale: content.rationale, + }; + if (content.alternatives.length > 0) { + enriched.alternatives = content.alternatives; + } + return enriched; + } + return { ...rule, rationale: rule.description }; + }); +} + // ═══════════════════════════════════════════════════════════════════════════ // ValidationRules Document Codec // ═══════════════════════════════════════════════════════════════════════════ @@ -245,7 +298,7 @@ function buildValidationRulesDocument( } // Build additional files for progressive disclosure (if enabled) - const additionalFiles = options.generateDetailFiles ? buildDetailFiles() : {}; + const additionalFiles = options.generateDetailFiles ? buildDetailFiles(options) : {}; const docOpts: { purpose: string; @@ -461,14 +514,16 @@ function buildEscapeHatchesSection(): SectionBlock[] { /** * Build additional validation detail files */ -function buildDetailFiles(): Record { +function buildDetailFiles( + options: Required +): Record { const files: Record = {}; // validation/fsm-transitions.md - Full transition matrix with descriptions files['validation/fsm-transitions.md'] = buildFSMTransitionsDetailDocument(); // validation/error-catalog.md - Full error messages with causes/fixes - files['validation/error-catalog.md'] = buildErrorCatalogDetailDocument(); + files['validation/error-catalog.md'] = buildErrorCatalogDetailDocument(RULE_DEFINITIONS, options); // validation/protection-levels.md - Detailed protection explanations files['validation/protection-levels.md'] = buildProtectionLevelsDetailDocument(); @@ -549,28 +604,27 @@ function buildFSMTransitionsDetailDocument(): RenderableDocument { /** * Build error catalog detail document */ -function buildErrorCatalogDetailDocument(): RenderableDocument { +function buildErrorCatalogDetailDocument( + rules: readonly RuleDefinition[], + options: Required +): RenderableDocument { const sections: SectionBlock[] = []; sections.push( heading(2, 'Error Catalog'), paragraph( - `Complete error messages and fix instructions for all ${RULE_DEFINITIONS.length} validation rules.` + `Complete error messages and fix instructions for all ${rules.length} validation rules.` ) ); // Summary table - const summaryRows = RULE_DEFINITIONS.map((rule) => [ - `\`${rule.id}\``, - rule.severity, - rule.description, - ]); + const summaryRows = rules.map((rule) => [`\`${rule.id}\``, rule.severity, rule.description]); sections.push(table(['Rule ID', 'Severity', 'Description'], summaryRows)); // Detailed breakdown per rule sections.push(heading(2, 'Rule Details')); - for (const rule of RULE_DEFINITIONS) { + for (const rule of rules) { sections.push( heading(3, `\`${rule.id}\``), table( @@ -583,6 +637,18 @@ function buildErrorCatalogDetailDocument(): RenderableDocument { ] ) ); + + // Error guide content (if enabled and rationale exists) + if (options.includeErrorGuide && rule.rationale) { + sections.push(heading(4, 'Why This Rule Exists'), paragraph(rule.rationale)); + + if (rule.alternatives && rule.alternatives.length > 0) { + sections.push( + heading(4, 'Alternative Approaches'), + ...rule.alternatives.map((alt) => paragraph(`- ${alt}`)) + ); + } + } } // Back link diff --git a/src/renderable/generate.ts b/src/renderable/generate.ts index 250b7a5d..c6a09cb0 100644 --- a/src/renderable/generate.ts +++ b/src/renderable/generate.ts @@ -23,7 +23,7 @@ import type { MasterDataset } from '../validation-schemas/master-dataset.js'; import type { RenderableDocument } from './schema.js'; -import { renderDocumentWithFiles, type OutputFile } from './render.js'; +import { renderDocumentWithFiles, renderToClaudeMdModule, type OutputFile } from './render.js'; import { Result } from '../types/result.js'; // Default codec instances @@ -47,6 +47,8 @@ import { ArchitectureDocumentCodec, TaxonomyDocumentCodec, ValidationRulesCodec, + ClaudeModuleCodec, + IndexCodec, } from './codecs/index.js'; // Factory functions for creating codecs with options @@ -70,6 +72,8 @@ import { createArchitectureCodec, createTaxonomyCodec, createValidationRulesCodec, + createClaudeModuleCodec, + createIndexCodec, } from './codecs/index.js'; // Codec options types @@ -93,6 +97,8 @@ import type { ArchitectureCodecOptions, TaxonomyCodecOptions, ValidationRulesCodecOptions, + ClaudeModuleCodecOptions, + IndexCodecOptions, } from './codecs/index.js'; // Shared codec types for type-safe factory invocation @@ -182,10 +188,27 @@ export const DOCUMENT_TYPES = { outputPath: 'VALIDATION-RULES.md', description: 'Process Guard validation rules reference', }, + 'claude-modules': { + outputPath: 'CLAUDE-MODULES.md', + description: 'CLAUDE.md modules generated from annotated behavior specs', + }, + index: { + outputPath: 'INDEX.md', + description: 'Navigation hub with editorial preamble and MasterDataset statistics', + }, } as const; export type DocumentType = keyof typeof DOCUMENT_TYPES; +/** + * Per-document-type renderer overrides. + * Document types not listed here use the default `renderToMarkdown`. + */ +const DOCUMENT_TYPE_RENDERERS: Partial string>> = + { + 'claude-modules': renderToClaudeMdModule, + }; + // ═══════════════════════════════════════════════════════════════════════════ // Codec Options Type // ═══════════════════════════════════════════════════════════════════════════ @@ -227,6 +250,8 @@ export interface CodecOptions { architecture?: ArchitectureCodecOptions; taxonomy?: TaxonomyCodecOptions; 'validation-rules'?: ValidationRulesCodecOptions; + 'claude-modules'?: ClaudeModuleCodecOptions; + index?: IndexCodecOptions; } // ═══════════════════════════════════════════════════════════════════════════ @@ -365,6 +390,8 @@ CodecRegistry.register('business-rules', BusinessRulesCodec); CodecRegistry.register('architecture', ArchitectureDocumentCodec); CodecRegistry.register('taxonomy', TaxonomyDocumentCodec); CodecRegistry.register('validation-rules', ValidationRulesCodec); +CodecRegistry.register('claude-modules', ClaudeModuleCodec); +CodecRegistry.register('index', IndexCodec); // Register all factory functions (used when codec options are provided) CodecRegistry.registerFactory('patterns', createPatternsCodec); @@ -386,6 +413,8 @@ CodecRegistry.registerFactory('business-rules', createBusinessRulesCodec); CodecRegistry.registerFactory('architecture', createArchitectureCodec); CodecRegistry.registerFactory('taxonomy', createTaxonomyCodec); CodecRegistry.registerFactory('validation-rules', createValidationRulesCodec); +CodecRegistry.registerFactory('claude-modules', createClaudeModuleCodec); +CodecRegistry.registerFactory('index', createIndexCodec); // ═══════════════════════════════════════════════════════════════════════════ // Error Types @@ -408,6 +437,24 @@ export interface GenerationError { phase: 'decode' | 'render'; } +// ═══════════════════════════════════════════════════════════════════════════ +// Codec Resolution +// ═══════════════════════════════════════════════════════════════════════════ + +/** + * Resolve the codec for a document type, using a factory if options are provided. + */ +function resolveCodec(type: DocumentType, options?: CodecOptions): DocumentCodec | undefined { + const typeOptions = options?.[type]; + if (typeOptions !== undefined) { + const factory = CodecRegistry.getFactory(type); + if (factory !== undefined) { + return factory(typeOptions); + } + } + return CodecRegistry.get(type); +} + // ═══════════════════════════════════════════════════════════════════════════ // Generation Functions // ═══════════════════════════════════════════════════════════════════════════ @@ -443,18 +490,7 @@ export function generateDocumentSafe( ): Result { const outputPath = DOCUMENT_TYPES[type].outputPath; - // Get options for this specific document type - const typeOptions = options?.[type]; - - // Use factory function if options provided, otherwise use default codec - let codec: DocumentCodec | undefined; - if (typeOptions !== undefined) { - const factory = CodecRegistry.getFactory(type); - if (factory !== undefined) { - codec = factory(typeOptions); - } - } - codec ??= CodecRegistry.get(type); + const codec = resolveCodec(type, options); if (codec === undefined) { return Result.err({ documentType: type, @@ -478,7 +514,8 @@ export function generateDocumentSafe( // Render: RenderableDocument → OutputFile[] (with error handling) try { - const files = renderDocumentWithFiles(doc, outputPath); + const renderer = DOCUMENT_TYPE_RENDERERS[type]; + const files = renderDocumentWithFiles(doc, outputPath, renderer); return Result.ok(files); } catch (err) { return Result.err({ @@ -524,18 +561,7 @@ export function generateDocument( ): OutputFile[] { const outputPath = DOCUMENT_TYPES[type].outputPath; - // Get options for this specific document type - const typeOptions = options?.[type]; - - // Use factory function if options provided, otherwise use default codec - let codec: DocumentCodec | undefined; - if (typeOptions !== undefined) { - const factory = CodecRegistry.getFactory(type); - if (factory !== undefined) { - codec = factory(typeOptions); - } - } - codec ??= CodecRegistry.get(type); + const codec = resolveCodec(type, options); if (codec === undefined) { throw new Error(`No codec registered for document type: ${type}`); } @@ -544,7 +570,8 @@ export function generateDocument( const doc = codec.decode(dataset) as RenderableDocument; // Render: RenderableDocument → OutputFile[] - return renderDocumentWithFiles(doc, outputPath); + const renderer = DOCUMENT_TYPE_RENDERERS[type]; + return renderDocumentWithFiles(doc, outputPath, renderer); } /** diff --git a/src/renderable/index.ts b/src/renderable/index.ts index 32a55f6b..29f6e86d 100644 --- a/src/renderable/index.ts +++ b/src/renderable/index.ts @@ -126,3 +126,9 @@ export { formatBusinessValue, } from './utils.js'; export { groupBy } from '../utils/index.js'; + +// ═══════════════════════════════════════════════════════════════════════════ +// Preamble Loader +// ═══════════════════════════════════════════════════════════════════════════ + +export { loadPreambleFromMarkdown, parseMarkdownToBlocks } from './load-preamble.js'; diff --git a/src/renderable/load-preamble.ts b/src/renderable/load-preamble.ts new file mode 100644 index 00000000..3066e278 --- /dev/null +++ b/src/renderable/load-preamble.ts @@ -0,0 +1,349 @@ +/** + * @libar-docs + * @libar-docs-implements ProceduralGuideCodec + * @libar-docs-arch-context renderer + * @libar-docs-arch-layer domain + * + * ## loadPreambleFromMarkdown — Shared Markdown-to-SectionBlock Parser + * + * Reads a markdown file via `readFileSync` and parses it into a + * `readonly SectionBlock[]` array using a line-by-line state machine. + * + * **Design Decision DD-8:** Preamble content is naturally authored as + * markdown. Converting to inline TypeScript `SectionBlock[]` literals + * is verbose. This shared parser eliminates 540+ lines of inline + * TypeScript per codec config while preserving the same shape. + * + * ### When to Use + * + * - In `delivery-process.config.ts` to load preamble markdown files + * - At config import time (before any codec `decode()` call) + * - When any codec needs static SectionBlock[] from a `.md` file + */ + +import { readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +import type { SectionBlock } from './schema.js'; + +// ============================================================================= +// State Machine Types +// ============================================================================= + +type ParserState = 'idle' | 'in-code-fence' | 'in-table' | 'in-paragraph' | 'in-list'; + +interface CodeFenceAccumulator { + language: string; + lines: string[]; +} + +interface TableAccumulator { + columns: string[]; + rows: string[][]; +} + +interface ListAccumulator { + ordered: boolean; + items: string[]; +} + +// ============================================================================= +// Detection Helpers +// ============================================================================= + +const HEADING_REGEX = /^(#{1,6})\s+(.+)$/; +const SEPARATOR_REGEX = /^(---+|\*\*\*+|___+)$/; +const CODE_FENCE_OPEN_REGEX = /^```(.*)$/; +const CODE_FENCE_CLOSE_REGEX = /^```\s*$/; +const UNORDERED_LIST_REGEX = /^[-*]\s+(.*)$/; +const ORDERED_LIST_REGEX = /^\d+\.\s+(.*)$/; +const TABLE_SEPARATOR_REGEX = /^\|[\s:]*-+[\s:|-]*\|$/; + +/** + * Checks whether a line starts a table (line starts with `|` and the + * following line is a separator row like `|---|---|`). + */ +function isTableStart(line: string, nextLine: string | undefined): boolean { + return line.startsWith('|') && nextLine !== undefined && TABLE_SEPARATOR_REGEX.test(nextLine); +} + +/** + * Parses a table row into its cell values, trimming whitespace. + * Strips leading and trailing `|` characters. + */ +function parseTableRow(line: string): string[] { + // Remove leading and trailing `|`, split by `|`, trim each cell + const stripped = line.replace(/^\|/, '').replace(/\|$/, ''); + return stripped.split('|').map((cell) => cell.trim()); +} + +/** + * Checks whether a line is a list item (unordered or ordered). + */ +function isListItem(line: string): boolean { + return UNORDERED_LIST_REGEX.test(line) || ORDERED_LIST_REGEX.test(line); +} + +/** + * Extracts the text content from a list item line. + * For `- [ ] text`, returns `[ ] text` (preserves GFM checkbox). + */ +function extractListItemText(line: string): string { + const unorderedMatch = UNORDERED_LIST_REGEX.exec(line); + if (unorderedMatch?.[1] !== undefined) { + return unorderedMatch[1]; + } + const orderedMatch = ORDERED_LIST_REGEX.exec(line); + if (orderedMatch?.[1] !== undefined) { + return orderedMatch[1]; + } + return line; +} + +/** + * Checks whether a list item line is ordered (starts with `\d+. `). + */ +function isOrderedListItem(line: string): boolean { + return ORDERED_LIST_REGEX.test(line); +} + +// ============================================================================= +// Flush Helpers +// ============================================================================= + +function flushParagraph(paragraphLines: string[]): SectionBlock { + return { type: 'paragraph', text: paragraphLines.join(' ') }; +} + +function flushCodeFence(acc: CodeFenceAccumulator): SectionBlock { + const content = acc.lines.join('\n'); + if (acc.language === 'mermaid') { + return { type: 'mermaid', content }; + } + if (acc.language.length > 0) { + return { type: 'code', language: acc.language, content }; + } + return { type: 'code', content }; +} + +function flushTable(acc: TableAccumulator): SectionBlock { + return { type: 'table', columns: acc.columns, rows: acc.rows }; +} + +function flushList(acc: ListAccumulator): SectionBlock { + return { type: 'list', ordered: acc.ordered, items: acc.items }; +} + +// ============================================================================= +// Core Parser +// ============================================================================= + +/** + * Parses a markdown string into a `readonly SectionBlock[]` array. + * + * Uses a 5-state line-by-line state machine: + * - `idle` — start state, entered after emitting a block + * - `in-code-fence` — inside ``` delimiters + * - `in-table` — accumulating table rows + * - `in-paragraph` — accumulating paragraph text + * - `in-list` — accumulating list items + * + * @param content - Raw markdown string to parse + * @returns Parsed SectionBlock array + */ +export function parseMarkdownToBlocks(content: string): readonly SectionBlock[] { + const lines = content.split('\n'); + const blocks: SectionBlock[] = []; + + let state: ParserState = 'idle'; + let paragraphLines: string[] = []; + let codeFence: CodeFenceAccumulator = { language: '', lines: [] }; + let tableAcc: TableAccumulator = { columns: [], rows: [] }; + let listAcc: ListAccumulator = { ordered: false, items: [] }; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i] ?? ''; + const nextLine = i + 1 < lines.length ? lines[i + 1] : undefined; + + // ----------------------------------------------------------------- + // State: in-code-fence — collect lines until closing ``` + // ----------------------------------------------------------------- + if (state === 'in-code-fence') { + if (CODE_FENCE_CLOSE_REGEX.test(line)) { + blocks.push(flushCodeFence(codeFence)); + codeFence = { language: '', lines: [] }; + state = 'idle'; + } else { + codeFence.lines.push(line); + } + continue; + } + + // ----------------------------------------------------------------- + // State: in-table — collect rows until line doesn't start with | + // ----------------------------------------------------------------- + if (state === 'in-table') { + if (line.startsWith('|')) { + // Skip separator rows + if (!TABLE_SEPARATOR_REGEX.test(line)) { + tableAcc.rows.push(parseTableRow(line)); + } + continue; + } + // Line doesn't start with | — flush table + blocks.push(flushTable(tableAcc)); + tableAcc = { columns: [], rows: [] }; + state = 'idle'; + // Fall through to process current line in idle + } + + // ----------------------------------------------------------------- + // State: in-list — collect items until line doesn't match list pattern + // ----------------------------------------------------------------- + if (state === 'in-list') { + if (isListItem(line)) { + // Check for list type change (ordered vs unordered) + const currentOrdered = isOrderedListItem(line); + if (currentOrdered !== listAcc.ordered) { + // Flush the current list and start a new one + blocks.push(flushList(listAcc)); + listAcc = { ordered: currentOrdered, items: [extractListItemText(line)] }; + } else { + listAcc.items.push(extractListItemText(line)); + } + continue; + } + // Not a list item — flush list + blocks.push(flushList(listAcc)); + listAcc = { ordered: false, items: [] }; + state = 'idle'; + // Fall through to process current line in idle + } + + // ----------------------------------------------------------------- + // State: in-paragraph — collect lines until blank line + // ----------------------------------------------------------------- + if (state === 'in-paragraph') { + if (line.trim() === '') { + blocks.push(flushParagraph(paragraphLines)); + paragraphLines = []; + state = 'idle'; + continue; + } + // Check if this line starts a new construct (heading, code fence, etc.) + if ( + HEADING_REGEX.test(line) || + SEPARATOR_REGEX.test(line) || + CODE_FENCE_OPEN_REGEX.test(line) || + isTableStart(line, nextLine) || + isListItem(line) + ) { + // Flush paragraph first + blocks.push(flushParagraph(paragraphLines)); + paragraphLines = []; + state = 'idle'; + // Fall through to idle processing + } else { + paragraphLines.push(line); + continue; + } + } + + // ----------------------------------------------------------------- + // State: idle — detect what the current line is + // ----------------------------------------------------------------- + + // Blank line — skip + if (line.trim() === '') { + continue; + } + + // Code fence opening + const codeFenceMatch = CODE_FENCE_OPEN_REGEX.exec(line); + if (codeFenceMatch !== null && !CODE_FENCE_CLOSE_REGEX.test(line)) { + state = 'in-code-fence'; + codeFence = { language: (codeFenceMatch[1] ?? '').trim(), lines: [] }; + continue; + } + + // Heading + const headingMatch = HEADING_REGEX.exec(line); + if (headingMatch?.[1] !== undefined && headingMatch[2] !== undefined) { + blocks.push({ + type: 'heading', + level: headingMatch[1].length as 1 | 2 | 3 | 4 | 5 | 6, + text: headingMatch[2], + }); + continue; + } + + // Separator + if (SEPARATOR_REGEX.test(line)) { + blocks.push({ type: 'separator' }); + continue; + } + + // Table start + if (isTableStart(line, nextLine)) { + state = 'in-table'; + tableAcc = { columns: parseTableRow(line), rows: [] }; + // Skip the separator row (next line) + i++; + continue; + } + + // List item + if (isListItem(line)) { + state = 'in-list'; + listAcc = { ordered: isOrderedListItem(line), items: [extractListItemText(line)] }; + continue; + } + + // Paragraph (default) + state = 'in-paragraph'; + paragraphLines = [line]; + } + + // ----------------------------------------------------------------- + // Flush any remaining state + // ----------------------------------------------------------------- + if (state === 'in-code-fence') { + // Unterminated code fence — still emit what we have + blocks.push(flushCodeFence(codeFence)); + } else if (state === 'in-table') { + blocks.push(flushTable(tableAcc)); + } else if (state === 'in-list') { + blocks.push(flushList(listAcc)); + } else if (state === 'in-paragraph' && paragraphLines.length > 0) { + blocks.push(flushParagraph(paragraphLines)); + } + + return blocks; +} + +// ============================================================================= +// File Loader +// ============================================================================= + +/** + * Reads a markdown file and parses it into a `readonly SectionBlock[]` array. + * + * Uses `readFileSync` (synchronous) — intended to run at config import time, + * not during codec decode. Resolves `filePath` relative to project root + * (`process.cwd()`). + * + * @param filePath - Path to markdown file, relative to project root + * @returns Parsed SectionBlock array suitable for ReferenceDocConfig.preamble + * + * @example + * ```typescript + * const preamble = loadPreambleFromMarkdown('docs-sources/session-workflow-guide.md'); + * // Returns: readonly SectionBlock[] with HeadingBlock, ParagraphBlock, + * // CodeBlock, MermaidBlock, TableBlock, ListBlock, SeparatorBlock + * ``` + */ +export function loadPreambleFromMarkdown(filePath: string): readonly SectionBlock[] { + const absolutePath = resolve(process.cwd(), filePath); + const content = readFileSync(absolutePath, 'utf-8'); + return parseMarkdownToBlocks(content); +} diff --git a/src/scanner/gherkin-ast-parser.ts b/src/scanner/gherkin-ast-parser.ts index 87826173..c437e77c 100644 --- a/src/scanner/gherkin-ast-parser.ts +++ b/src/scanner/gherkin-ast-parser.ts @@ -567,6 +567,9 @@ export function extractPatternTags(tags: readonly string[]): { readonly include?: readonly string[]; readonly extractShapes?: readonly string[]; readonly usecase?: string; + readonly claudeModule?: string; + readonly claudeSection?: string; + readonly claudeTags?: readonly string[]; // Index signature enables registry-driven extensibility: new tags in // buildRegistry() work without updating this return type. readonly [key: string]: unknown; diff --git a/src/taxonomy/claude-section-values.ts b/src/taxonomy/claude-section-values.ts new file mode 100644 index 00000000..85cc77a0 --- /dev/null +++ b/src/taxonomy/claude-section-values.ts @@ -0,0 +1,19 @@ +/** + * Claude section values for CLAUDE.md module generation. + * + * Each value maps to a subdirectory under `_claude-md/` where + * generated modules are written. + * + * @libar-docs + * @see ClaudeModuleGeneration spec (Phase 25) + */ + +export const CLAUDE_SECTION_VALUES = [ + 'core', + 'delivery-process', + 'testing', + 'infrastructure', + 'workflow', +] as const; + +export type ClaudeSectionValue = (typeof CLAUDE_SECTION_VALUES)[number]; diff --git a/src/taxonomy/conventions.ts b/src/taxonomy/conventions.ts index 5b8433ae..799aea69 100644 --- a/src/taxonomy/conventions.ts +++ b/src/taxonomy/conventions.ts @@ -3,8 +3,8 @@ * * Each value maps to a convention domain that can be used to tag * decision records with `@libar-docs-convention:value1,value2`. - * The 11 values correspond to the 11 convention domains extracted - * from the former recipe .feature files. + * Values correspond to convention domains extracted from the former + * recipe .feature files, plus `codec-registry` for auto-generated codec docs. * * @see CodecDrivenReferenceGeneration spec */ @@ -22,6 +22,8 @@ export const CONVENTION_VALUES = [ 'publishing', 'doc-generation', 'taxonomy-rules', + 'codec-registry', + 'process-guard-errors', ] as const; export type ConventionValue = (typeof CONVENTION_VALUES)[number]; diff --git a/src/taxonomy/index.ts b/src/taxonomy/index.ts index cc979d61..e484ac88 100644 --- a/src/taxonomy/index.ts +++ b/src/taxonomy/index.ts @@ -133,5 +133,8 @@ export { // Convention values (reference document generation) export { CONVENTION_VALUES, type ConventionValue } from './conventions.js'; +// Claude section values (CLAUDE.md module generation) +export { CLAUDE_SECTION_VALUES, type ClaudeSectionValue } from './claude-section-values.js'; + // Registry builder export { buildRegistry, type TagRegistry } from './registry-builder.js'; diff --git a/src/taxonomy/registry-builder.ts b/src/taxonomy/registry-builder.ts index a9d40f88..993ed6f9 100644 --- a/src/taxonomy/registry-builder.ts +++ b/src/taxonomy/registry-builder.ts @@ -34,6 +34,7 @@ import { DEFAULT_HIERARCHY_LEVEL, HIERARCHY_LEVELS } from './hierarchy-levels.js import { RISK_LEVELS } from './risk-levels.js'; import { ACCEPTED_STATUS_VALUES, DEFAULT_STATUS } from './status-values.js'; import { CONVENTION_VALUES } from './conventions.js'; +import { CLAUDE_SECTION_VALUES } from './claude-section-values.js'; import { DEFAULT_TAG_PREFIX, DEFAULT_FILE_OPT_IN_TAG } from '../config/defaults.js'; /** @@ -167,6 +168,7 @@ export const METADATA_TAGS_BY_GROUP = { extraction: ['extract-shapes', 'shape'] as const, stub: ['target', 'since'] as const, convention: ['convention'] as const, + claude: ['claude-module', 'claude-section', 'claude-tags'] as const, } as const; // Transform helpers for data-driven Gherkin tag extraction @@ -563,6 +565,26 @@ export function buildRegistry(): TagRegistry { values: [...CONVENTION_VALUES], example: '@libar-docs-convention fsm-rules, testing-policy', }, + // Claude module generation tags (ClaudeModuleGeneration Phase 25) + { + tag: 'claude-module', + format: 'value', + purpose: 'Module identifier for CLAUDE.md module generation (becomes filename)', + example: '@libar-docs-claude-module process-guard', + }, + { + tag: 'claude-section', + format: 'enum', + purpose: 'Target section directory in _claude-md/ for module output', + values: [...CLAUDE_SECTION_VALUES], + example: '@libar-docs-claude-section delivery-process', + }, + { + tag: 'claude-tags', + format: 'csv', + purpose: 'Variation filtering tags for modular-claude-md inclusion', + example: '@libar-docs-claude-tags core-mandatory, delivery-process', + }, ], aggregationTags: [ diff --git a/src/validation-schemas/doc-directive.ts b/src/validation-schemas/doc-directive.ts index 659d6e38..572b6101 100644 --- a/src/validation-schemas/doc-directive.ts +++ b/src/validation-schemas/doc-directive.ts @@ -25,6 +25,7 @@ import { } from '../taxonomy/index.js'; import { asDirectiveTag } from '../types/branded.js'; import type { TagRegistry } from './tag-registry.js'; +import { CLAUDE_SECTION_VALUES } from '../taxonomy/claude-section-values.js'; /** * Position information for a directive in source code @@ -270,6 +271,17 @@ export const DocDirectiveSchema = z /** Convention domains for reference document generation (from @libar-docs-convention CSV tag) */ convention: z.array(z.string()).readonly().optional(), + + // Claude module generation fields (from @libar-docs-claude-* tags) + + /** Module identifier for CLAUDE.md generation (from @libar-docs-claude-module tag) */ + claudeModule: z.string().optional(), + + /** Target section directory in _claude-md/ (from @libar-docs-claude-section tag) */ + claudeSection: z.enum(CLAUDE_SECTION_VALUES).optional(), + + /** Variation filtering tags for modular-claude-md (from @libar-docs-claude-tags CSV tag) */ + claudeTags: z.array(z.string()).readonly().optional(), }) .strict(); diff --git a/src/validation-schemas/extracted-pattern.ts b/src/validation-schemas/extracted-pattern.ts index 11e2ecfc..e57cef25 100644 --- a/src/validation-schemas/extracted-pattern.ts +++ b/src/validation-schemas/extracted-pattern.ts @@ -26,6 +26,7 @@ import { DeliverableSchema, HierarchyLevelSchema } from './dual-source.js'; import { ExtractedShapeSchema } from './extracted-shape.js'; import { slugify } from '../utils/string-utils.js'; import { ADR_STATUS_VALUES } from '../taxonomy/index.js'; +import { CLAUDE_SECTION_VALUES } from '../taxonomy/claude-section-values.js'; // ═══════════════════════════════════════════════════════════════════════════ // Business Rule Schema (Shared Type) @@ -507,6 +508,17 @@ export const ExtractedPatternSchema = z * ``` */ extractedShapes: z.array(ExtractedShapeSchema).readonly().optional(), + + // Claude module generation fields (from @libar-docs-claude-* tags) + + /** Module identifier for CLAUDE.md generation (from @libar-docs-claude-module tag) */ + claudeModule: z.string().optional(), + + /** Target section directory in _claude-md/ (from @libar-docs-claude-section tag) */ + claudeSection: z.enum(CLAUDE_SECTION_VALUES).optional(), + + /** Variation filtering tags for modular-claude-md (from @libar-docs-claude-tags CSV tag) */ + claudeTags: z.array(z.string()).readonly().optional(), }) .strict(); diff --git a/src/validation-schemas/master-dataset.ts b/src/validation-schemas/master-dataset.ts index b5fa0fc8..3e40a99c 100644 --- a/src/validation-schemas/master-dataset.ts +++ b/src/validation-schemas/master-dataset.ts @@ -50,6 +50,8 @@ import { TagRegistrySchema } from './tag-registry.js'; * - completed: implemented, completed * - active: active, partial, in-progress * - planned: roadmap, planned, undefined + * + * @libar-docs-shape master-dataset */ export const StatusGroupsSchema = z.object({ /** Patterns with status 'completed' or 'implemented' */ @@ -64,6 +66,8 @@ export const StatusGroupsSchema = z.object({ /** * Status counts for aggregate statistics + * + * @libar-docs-shape master-dataset */ export const StatusCountsSchema = z.object({ /** Number of completed patterns */ @@ -84,6 +88,8 @@ export const StatusCountsSchema = z.object({ * * Groups patterns by their phase number, with pre-computed * status counts for each phase. + * + * @libar-docs-shape master-dataset */ export const PhaseGroupSchema = z.object({ /** Phase number (e.g., 1, 2, 3, 14, 39) */ @@ -101,6 +107,8 @@ export const PhaseGroupSchema = z.object({ /** * Source-based views for different data origins + * + * @libar-docs-shape master-dataset */ export const SourceViewsSchema = z.object({ /** Patterns from TypeScript files (.ts) */ @@ -137,6 +145,8 @@ export const ImplementationRefSchema = z.object({ * Relationship index for dependency tracking * * Maps pattern names to their relationship metadata. + * + * @libar-docs-shape master-dataset */ export const RelationshipEntrySchema = z.object({ /** Patterns this pattern uses (from @libar-docs-uses) */ @@ -202,6 +212,8 @@ export const ArchIndexSchema = z.object({ * * Contains raw patterns plus pre-computed views and statistics. * This is the primary data structure passed to generators and sections. + * + * @libar-docs-shape master-dataset */ export const MasterDatasetSchema = z.object({ // ───────────────────────────────────────────────────────────────────────── @@ -237,6 +249,9 @@ export const MasterDatasetSchema = z.object({ /** Patterns grouped by source type */ bySource: SourceViewsSchema, + /** Patterns grouped by product area (for O(1) product area lookups) */ + byProductArea: z.record(z.string(), z.array(ExtractedPatternSchema)), + // ───────────────────────────────────────────────────────────────────────── // Aggregate Statistics // ───────────────────────────────────────────────────────────────────────── diff --git a/tests/features/behavior/cli/process-api-reference.feature b/tests/features/behavior/cli/process-api-reference.feature new file mode 100644 index 00000000..352cf968 --- /dev/null +++ b/tests/features/behavior/cli/process-api-reference.feature @@ -0,0 +1,113 @@ +@libar-docs +@libar-docs-pattern:ProcessApiReferenceTests +@libar-docs-implements:ProcessApiHybridGeneration +@libar-docs-status:completed +@libar-docs-product-area:DataAPI +@behavior @cli @process-api-reference +Feature: Process API CLI Reference Generation + + Verifies that the declarative CLI schema drives reference table generation + and stays in sync with the parser implementation. + + Rule: Generated reference file contains all three table sections + + **Invariant:** PROCESS-API-REFERENCE.md contains Global Options, Output Modifiers, + and List Filters tables generated from the CLI schema. + + @acceptance-criteria @happy-path + Scenario: Generated file contains Global Options table + Given the CLI schema is loaded + When the ProcessApiReferenceGenerator produces output + Then the output contains a "Global Options" heading + And the output contains a table with columns "Flag", "Short", "Description", "Default" + And the table has 6 rows for global options + + @acceptance-criteria @happy-path + Scenario: Generated file contains Output Modifiers table + Given the CLI schema is loaded + When the ProcessApiReferenceGenerator produces output + Then the output contains an "Output Modifiers" heading + And the output contains a table with columns "Output Modifier", "Description" + And the table has 5 rows for output modifiers + + @acceptance-criteria @happy-path + Scenario: Generated file contains List Filters table + Given the CLI schema is loaded + When the ProcessApiReferenceGenerator produces output + Then the output contains a "List Filters" heading + And the output contains a table with columns "List Filter", "Description" + And the table has 8 rows for list filters + + @acceptance-criteria @happy-path + Scenario: Generated file includes inter-table prose + Given the CLI schema is loaded + When the ProcessApiReferenceGenerator produces output + Then the output contains the following prose fragments: + | fragment | + | Config auto-detection | + | Precedence | + | composable | + + Rule: CLI schema stays in sync with parser + + **Invariant:** Every flag recognized by parseArgs() has a corresponding + entry in the CLI schema. A missing schema entry means the sync test fails. + + @acceptance-criteria @validation + Scenario: Schema covers all global option flags + Given the CLI schema is loaded + Then the schema global options include all expected flags: + | flag | + | --input | + | --features | + | --base-dir | + | --workflow | + | --help | + | --version | + + @acceptance-criteria @validation + Scenario: Schema covers all output modifier flags + Given the CLI schema is loaded + Then the schema output modifiers include all expected flags: + | flag | + | --names-only | + | --count | + | --fields | + | --full | + | --format | + + @acceptance-criteria @validation + Scenario: Schema covers all list filter flags + Given the CLI schema is loaded + Then the schema list filters include all expected flags: + | flag | + | --status | + | --phase | + | --category | + | --source | + | --arch-context | + | --product-area | + | --limit | + | --offset | + + @acceptance-criteria @validation + Scenario: Schema covers session option + Given the CLI schema is loaded + Then the schema session options include all expected flags: + | flag | + | --session | + + Rule: showHelp output reflects CLI schema + + **Invariant:** The help text rendered by showHelp() includes all options + from the CLI schema, formatted for terminal display. + + @acceptance-criteria @integration + Scenario: Help text includes schema-defined options + Given the CLI schema is loaded + Then all schema groups contain at least one option: + | group | + | globalOptions | + | outputModifiers | + | listFilters | + | sessionOptions | diff --git a/tests/features/behavior/codecs/convention-extractor.feature b/tests/features/behavior/codecs/convention-extractor.feature index 2d47d544..a17d5efe 100644 --- a/tests/features/behavior/codecs/convention-extractor.feature +++ b/tests/features/behavior/codecs/convention-extractor.feature @@ -2,6 +2,7 @@ @behavior @convention-extractor @libar-docs-pattern:ConventionExtractorTesting @libar-docs-status:completed +@libar-docs-unlock-reason:Fix-escaped-pipe-parsing-in-convention-tables @libar-docs-implements:ReferenceDocShowcase @libar-docs-product-area:Generation Feature: Convention Extractor @@ -170,6 +171,15 @@ Feature: Convention Extractor Then the first rule has 1 table And the table has 2 data rows + @edge-case + Scenario: TypeScript table with escaped union pipes preserves full cell values + Given a TypeScript pattern with convention "fsm-rules" and escaped union table description + When extracting conventions for tag "fsm-rules" + Then the first table row has cell "Option" with value "sortBy" + Then the first table row has Type value with escaped unions + Then the first table row has Default value with quotes + And the first table row has cell "Description" with value "Sort order" + @edge-case Scenario: TypeScript description with code examples Given a TypeScript pattern with convention "fsm-rules" and mermaid description diff --git a/tests/features/behavior/codecs/generated-doc-quality.feature b/tests/features/behavior/codecs/generated-doc-quality.feature new file mode 100644 index 00000000..7c24ad1d --- /dev/null +++ b/tests/features/behavior/codecs/generated-doc-quality.feature @@ -0,0 +1,80 @@ +@libar-docs +@behavior @reference-codec +@libar-docs-pattern:GeneratedDocQualityTests +@libar-docs-status:completed +@libar-docs-implements:GeneratedDocQuality +@libar-docs-product-area:Generation +Feature: Generated Documentation Quality Improvements + + Tests for the four quality fixes in GeneratedDocQuality (Phase 38): + duplicate table removal, Generation compact enrichment, types-first + ordering, and product area TOC generation. + + Background: + Given a reference codec test context + + Rule: Behavior-specs renderer does not duplicate convention table content + + **Invariant:** Convention tables appear exactly once in the output — in the convention section. The behavior-specs section shows only metadata. + **Rationale:** DD-4: Duplicate tables waste 500+ lines and agent context tokens. + + @acceptance-criteria @happy-path + Scenario: Convention rule table appears exactly once in generated output + Given a reference config with convention tag "test-conv" and include tag "test-include" + And a pattern with convention content and a table in its rule description + When decoding at detail level "detailed" + Then the table appears exactly once in the document + And the behavior-specs section contains invariant text + And the behavior-specs section does not contain the table + + @acceptance-criteria @validation + Scenario: Behavior-specs show rule metadata without tables + Given a reference config with convention tag "test-conv" and include tag "test-include" + And a pattern with convention content and a table in its rule description + When decoding at detail level "standard" + Then the convention section renders the table + And no table rows are duplicated in the document + + Rule: ARCHITECTURE-TYPES leads with type definitions + + **Invariant:** When shapesFirst is true, shapes render before conventions. + **Rationale:** ARCHITECTURE-TYPES.md should open with type definitions, not orchestrator prose. + + @acceptance-criteria @happy-path + Scenario: Shapes section appears before conventions when shapesFirst is true + Given a reference config with shapesFirst enabled + And a dataset with both convention content and shape content + When decoding at detail level "detailed" + Then the first heading after the title is from the shapes section + And the convention heading appears after the shapes section + + Rule: Product area docs have a generated table of contents + + **Invariant:** Product area docs with 3+ H2 headings include a Contents section with anchor links. + **Rationale:** Large product area docs need browser-navigable TOC for human developers. + + @acceptance-criteria @happy-path + Scenario: Product area doc with multiple sections gets a TOC + Given a product area config for "Generation" + And a dataset with multiple patterns in the Generation area + When decoding at detail level "detailed" + Then the document contains a heading "Contents" + And the Contents section is a list with anchor links + And the Contents heading appears after the intro separator + + Rule: Generation compact is self-sufficient + + **Invariant:** The Generation compact contains codec inventory and pipeline summary at 4+ KB. + **Rationale:** DD-2: A 1.4 KB compact for the largest area means agents have no usable summary. + + @acceptance-criteria @happy-path + Scenario: Generation compact contains enriched content + Given a product area config for "Generation" + And a dataset with Generation area patterns + When decoding at detail level "summary" + Then the rendered output contains all expected terms: + | Term | + | Scanner | + | Codec | + | MasterDataset | + | RenderableDocument | diff --git a/tests/features/behavior/codecs/reference-codec-diagrams.feature b/tests/features/behavior/codecs/reference-codec-diagrams.feature index 8168dc88..1337a9fa 100644 --- a/tests/features/behavior/codecs/reference-codec-diagrams.feature +++ b/tests/features/behavior/codecs/reference-codec-diagrams.feature @@ -101,6 +101,21 @@ Feature: Reference Codec - Diagram Scoping When decoding at detail level "summary" Then the document does not contain a mermaid block + Rule: Hardcoded diagram sources render deterministic output + + **Invariant:** Hardcoded diagram sources render without relationship-scoping input and emit stable, source-specific Mermaid content. + **Rationale:** Domain diagrams such as pipeline and MasterDataset fan-out encode canonical architecture views that should not depend on ad-hoc test dataset shape. + **Verified by:** master-dataset-views source renders expected fan-out nodes + + @happy-path + Scenario: master-dataset-views source produces MasterDataset fan-out diagram + Given a reference config with diagramScope source "master-dataset-views" + And a MasterDataset with arch-annotated patterns in context "lint" + When decoding at detail level "detailed" + Then the document contains a mermaid block + And the mermaid content contains "graph TB" + And the mermaid content contains all of "MasterDataset", "byStatus", "byPhase", and "relationshipIndex" + Rule: Multiple diagram scopes produce multiple mermaid blocks **Invariant:** Each entry in the diagramScopes array produces an independent Mermaid block with its own title and direction, and legacy singular diagramScope remains supported as a fallback. diff --git a/tests/features/behavior/codecs/reference-generators.feature b/tests/features/behavior/codecs/reference-generators.feature index 0981b417..f1e6960f 100644 --- a/tests/features/behavior/codecs/reference-generators.feature +++ b/tests/features/behavior/codecs/reference-generators.feature @@ -23,7 +23,7 @@ Feature: Reference Document Generator Registration @happy-path Scenario: Generators are registered from configs plus meta-generators When registering reference generators - Then 18 generators are registered + Then 20 generators are registered Rule: Product area configs produce a separate meta-generator @@ -55,6 +55,12 @@ Feature: Reference Document Generator Registration Then a generator named "annotation-overview-reference-claude" exists And a generator named "reference-generation-sample-reference-claude" exists + @happy-path + Scenario: Architecture-types generators are registered + When registering reference generators + Then a generator named "architecture-types-reference" exists + And a generator named "architecture-types-reference-claude" exists + Rule: Generator execution produces markdown output **Invariant:** Every registered generator must produce at least one non-empty output file when given matching data. @@ -75,3 +81,11 @@ Feature: Reference Document Generator Registration When running the "annotation-overview-reference" generator Then the output has 1 file And the output file content contains "How do I annotate code?" + + @integration + Scenario: ARCHITECTURE-TYPES generator produces shapes and convention content + Given a MasterDataset with pipeline architecture conventions and master dataset shapes + When running the "architecture-types-reference" generator + Then the output has 1 file + And the output file path starts with "reference/" + And the output file content contains all of "MasterDatasetSchema", "PipelineOptions", "Orchestrator Pipeline Responsibilities", and "graph TB" diff --git a/tests/features/doc-generation/architecture-doc-refactoring.feature b/tests/features/doc-generation/architecture-doc-refactoring.feature new file mode 100644 index 00000000..e62bfd70 --- /dev/null +++ b/tests/features/doc-generation/architecture-doc-refactoring.feature @@ -0,0 +1,201 @@ +@libar-docs +@libar-docs-pattern:ArchitectureDocRefactoringTesting +@libar-docs-status:active +@libar-docs-product-area:Generation +@integration +Feature: Architecture Doc Refactoring Coverage + + Validates that ARCHITECTURE.md retains its full reference content and that + generated documents in docs-live/ coexist alongside it, covering equivalent + content from annotated sources. + + Background: + Given ARCHITECTURE.md on the filesystem + + Rule: Product area sections coexist with generated documents + + **Invariant:** Each architecture section in docs/ARCHITECTURE.md has a corresponding generated document in docs-live/product-areas/ covering equivalent content from annotated sources. + + **Rationale:** Manual and generated docs must coexist during the transition period. Generated docs prove that annotated sources produce equivalent coverage before manual sections are deprecated. + + **Verified by:** Configuration Architecture section retained and generated doc exists, Source Systems section retained and annotation product area exists, Workflow Integration section retained and process product area exists + + @acceptance-criteria @happy-path + Scenario: Configuration Architecture section retained and generated doc exists + When reading the "Configuration Architecture" section + Then the section has content + And file "docs-live/product-areas/CONFIGURATION.md" contains "config resolution" + And file "docs-live/product-areas/CONFIGURATION.md" also contains "preset" + + @happy-path + Scenario: Source Systems section retained and annotation product area exists + When reading the "Source Systems" section + Then the section has content + And file "docs-live/product-areas/ANNOTATION.md" contains "scanner" + And file "docs-live/product-areas/ANNOTATION.md" also contains "tag dispatch" + + @happy-path + Scenario: Workflow Integration section retained and process product area exists + When reading the "Workflow Integration" section + Then the section has content + And file "docs-live/product-areas/PROCESS.md" contains "FSM lifecycle" + And file "docs-live/product-areas/PROCESS.md" also contains "session" + + Rule: Four-Stage Pipeline section retains annotation format examples + + **Invariant:** The Four-Stage Pipeline section contains annotation format examples (e.g., @libar-docs-shape, extract-shapes) and appears before the Source Systems section in document order. + + **Rationale:** Annotation format examples in the pipeline section demonstrate the source-first architecture. Their ordering establishes the conceptual flow: pipeline stages first, then the source systems that feed them. + + **Verified by:** Annotation format examples appear before Source Systems + + @acceptance-criteria @happy-path + Scenario: Annotation format examples appear before Source Systems + When reading the "Four-Stage Pipeline" section + Then the section contains "@libar-docs-shape" + And the section also contains "extract-shapes" + And section "Four-Stage Pipeline" appears before section "Source Systems" + + Rule: Convention extraction produces ARCHITECTURE-CODECS reference document + + **Invariant:** The ARCHITECTURE-CODECS.md reference document is generated from convention-tagged JSDoc in codec source files and contains structured sections for each codec with output file references. + + **Rationale:** Codec documentation must stay synchronized with source code. Convention extraction from JSDoc ensures the reference document reflects actual codec implementations rather than manually maintained descriptions that drift. + + **Verified by:** Session codecs file produces multiple convention sections, Convention sections include output file references, ARCHITECTURE-CODECS document has substantial content from all codec files, Session codec source file has structured JSDoc headings, Convention rule titles match source heading text in generated output + + @acceptance-criteria @happy-path + Scenario: Session codecs file produces multiple convention sections + When reading file "docs-live/reference/ARCHITECTURE-CODECS.md" + Then the file contains each of the following: + """ + SessionContextCodec + RemainingWorkCodec + CurrentWorkCodec + """ + + @happy-path + Scenario: Convention sections include output file references + When reading file "docs-live/reference/ARCHITECTURE-CODECS.md" + Then the file contains "SESSION-CONTEXT.md" + And the file also contains "CURRENT-WORK.md" + + @happy-path + Scenario: ARCHITECTURE-CODECS document has substantial content from all codec files + When reading file "docs-live/reference/ARCHITECTURE-CODECS.md" + Then the file has more than 400 lines + + @happy-path + Scenario: Session codec source file has structured JSDoc headings + When reading file "src/renderable/codecs/session.ts" + Then the file contains each of the following: + """ + ## SessionContextCodec + **Purpose:** + **Output Files:** + """ + + @happy-path + Scenario: Convention rule titles match source heading text in generated output + When reading file "docs-live/reference/ARCHITECTURE-CODECS.md" + Then the file contains "ValidationRulesCodec" + And the file also contains "PatternsDocumentCodec" + + Rule: Full sections coexist with generated equivalents in docs-live + + **Invariant:** Major sections of ARCHITECTURE.md (Unified Transformation, Data Flow Diagrams, Quick Reference) are retained alongside their generated equivalents in docs-live/reference/. + + **Rationale:** Generated reference documents (ARCHITECTURE-TYPES.md, ARCHITECTURE-CODECS.md) provide exhaustive type and codec listings, but the manual sections offer architectural narrative and design rationale that generated docs cannot yet replicate. + + **Verified by:** Unified Transformation Architecture section retained and ARCHITECTURE-TYPES exists, Data Flow Diagrams section retained and ARCHITECTURE-TYPES exists, Quick Reference section retained and ARCHITECTURE-CODECS exists + + @acceptance-criteria @happy-path + Scenario: Unified Transformation Architecture section retained and ARCHITECTURE-TYPES exists + When reading the "Unified Transformation Architecture" section + Then the section contains "MasterDataset" + And file "docs-live/reference/ARCHITECTURE-TYPES.md" exists + + @happy-path + Scenario: Data Flow Diagrams section retained and ARCHITECTURE-TYPES exists + When reading the "Data Flow Diagrams" section + Then the section has content + And file "docs-live/reference/ARCHITECTURE-TYPES.md" exists + + @happy-path + Scenario: Quick Reference section retained and ARCHITECTURE-CODECS exists + When reading the "Quick Reference" section + Then the section has content + And file "docs-live/reference/ARCHITECTURE-CODECS.md" exists + + Rule: MasterDataset shapes appear in ARCHITECTURE-TYPES reference + + **Invariant:** The ARCHITECTURE-TYPES.md reference document contains core MasterDataset types (MasterDataset, RuntimeMasterDataset, RawDataset) and pipeline types (PipelineOptions, PipelineResult) extracted from shape annotations. + + **Rationale:** Type shapes are the structural backbone of the pipeline. Generating their documentation from annotations ensures the reference always matches the actual TypeScript interfaces, eliminating manual drift. + + **Verified by:** Core MasterDataset types appear in ARCHITECTURE-TYPES, Pipeline types appear in ARCHITECTURE-TYPES reference, Unified Transformation section has full MasterDataset content + + @acceptance-criteria @happy-path + Scenario: Core MasterDataset types appear in ARCHITECTURE-TYPES + When reading file "docs-live/reference/ARCHITECTURE-TYPES.md" + Then the file contains each of the following: + """ + MasterDataset + RuntimeMasterDataset + RawDataset + """ + + @happy-path + Scenario: Pipeline types appear in ARCHITECTURE-TYPES reference + When reading file "docs-live/reference/ARCHITECTURE-TYPES.md" + Then the file contains "PipelineOptions" + And the file also contains "PipelineResult" + + @happy-path + Scenario: Unified Transformation section has full MasterDataset content + When reading the "Unified Transformation Architecture" section + Then the section contains "MasterDataset" + And the section also contains "RuntimeMasterDataset" + + Rule: Pipeline architecture convention appears in generated reference + + **Invariant:** Source files in the pipeline layer (orchestrator.ts, build-pipeline.ts) carry the pipeline-architecture convention tag, enabling convention extraction into the ARCHITECTURE-TYPES reference document. + + **Rationale:** Convention tags on pipeline source files are the mechanism that feeds content into generated reference docs. Without these tags, the architecture reference would have no source material to extract. + + **Verified by:** Orchestrator source file has pipeline-architecture convention tag, Build-pipeline source file has pipeline-architecture convention tag + + @acceptance-criteria @happy-path + Scenario: Orchestrator source file has pipeline-architecture convention tag + When reading file "src/generators/orchestrator.ts" + Then the file contains "pipeline-architecture" + + @happy-path + Scenario: Build-pipeline source file has pipeline-architecture convention tag + When reading file "src/generators/pipeline/build-pipeline.ts" + Then the file contains "pipeline-architecture" + + Rule: Full ARCHITECTURE.md retains all sections with substantial content + + **Invariant:** ARCHITECTURE.md retains all major sections (Programmatic Usage, Extending the System, Key Design Patterns) with substantial content and remains under 1700 lines as a comprehensive reference. + + **Rationale:** These sections contain editorial content (usage examples, extension guides, design pattern explanations) that cannot be generated from annotations. They remain manual until procedural guide codecs can replicate their depth. + + **Verified by:** Programmatic Usage section exists in ARCHITECTURE.md, Extending the System section exists in ARCHITECTURE.md, Key Design Patterns section has design pattern content, ARCHITECTURE.md is under 1700 lines as full reference + + @acceptance-criteria @happy-path + Scenario: Programmatic Usage section exists in ARCHITECTURE.md + Then section "Programmatic Usage" exists in ARCHITECTURE.md + + @happy-path + Scenario: Extending the System section exists in ARCHITECTURE.md + Then section "Extending the System" exists in ARCHITECTURE.md + + @happy-path + Scenario: Key Design Patterns section has design pattern content + When reading the "Key Design Patterns" section + Then the section contains "Result" + + @happy-path + Scenario: ARCHITECTURE.md is under 1700 lines as full reference + Then ARCHITECTURE.md has fewer than 1700 lines diff --git a/tests/features/generation/load-preamble.feature b/tests/features/generation/load-preamble.feature new file mode 100644 index 00000000..d4ca1a90 --- /dev/null +++ b/tests/features/generation/load-preamble.feature @@ -0,0 +1,166 @@ +@libar-docs +@libar-docs-pattern:LoadPreambleParser +@libar-docs-status:active +@libar-docs-product-area:Generation +@behavior @load-preamble +Feature: Markdown-to-SectionBlock Parser + + The parseMarkdownToBlocks function converts raw markdown content into + a readonly SectionBlock[] array using a 5-state line-by-line state machine. + This enables preamble content to be authored as markdown files instead of + verbose inline TypeScript object literals. + + **Problem:** + Preamble content authored as inline TypeScript SectionBlock[] literals is + verbose (540+ lines per codec config) and hard to review. + + **Solution:** + A shared parser reads markdown and produces the same SectionBlock[] shape + that codecs expect, enabling markdown authoring with TypeScript type safety. + + Background: + Given a markdown parser test context + + Rule: Headings are parsed into HeadingBlock + + **Invariant:** Lines starting with 1-6 hash characters followed by a space produce HeadingBlock with the correct level and text. + **Rationale:** Headings are the primary structural element in preamble markdown and must map exactly to HeadingBlock level values. + **Verified by:** Single heading is parsed, All heading levels are parsed correctly + + @happy-path @headings + Scenario: Single heading is parsed + Given markdown with a level 2 heading "Getting Started" + When parsing the markdown to blocks + Then block 1 is a heading at level 2 with text "Getting Started" + + @happy-path @headings + Scenario: All heading levels are parsed correctly + Given markdown with all six heading levels + When parsing the markdown to blocks + Then 6 heading blocks are produced with levels 1 through 6 + + Rule: Paragraphs are parsed into ParagraphBlock + + **Invariant:** Consecutive non-empty, non-construct lines produce a single ParagraphBlock with lines joined by spaces. + **Rationale:** Multi-line paragraphs in markdown are a single logical block separated by blank lines. + **Verified by:** Single line paragraph, Multi-line paragraph joined with space + + @happy-path @paragraphs + Scenario: Single line paragraph + Given markdown with a single paragraph line + When parsing the markdown to blocks + Then block 1 is a paragraph with text "This is a simple paragraph." + + @happy-path @paragraphs + Scenario: Multi-line paragraph joined with space + Given markdown with a two-line paragraph + When parsing the markdown to blocks + Then block 1 is a paragraph with joined text + + Rule: Separators are parsed into SeparatorBlock + + **Invariant:** Lines matching exactly three or more dashes, asterisks, or underscores produce SeparatorBlock. + **Rationale:** Horizontal rules serve as visual separators in preamble content and must be faithfully represented. + **Verified by:** Triple dash separator + + @happy-path @separators + Scenario: Triple dash separator + Given markdown with a separator between paragraphs + When parsing the markdown to blocks + Then the result has a paragraph then separator then paragraph + + Rule: Tables are parsed into TableBlock + + **Invariant:** A line starting with pipe followed by a separator row produces TableBlock with columns from the header and rows from subsequent pipe-delimited lines. + **Rationale:** Tables are heavily used in preamble content for structured reference data and must preserve column names and cell values exactly. + **Verified by:** Simple table with header and rows + + @happy-path @tables + Scenario: Simple table with header and rows + Given markdown with a two-column table + When parsing the markdown to blocks + Then block 1 is a table with the expected columns and rows + + Rule: Unordered lists are parsed into ListBlock + + **Invariant:** Lines starting with dash-space or asterisk-space produce ListBlock with ordered=false and string items. + **Rationale:** Unordered lists are common in preamble content for enumerating capabilities or constraints. + **Verified by:** Dash list items, GFM checkbox list items + + @happy-path @lists + Scenario: Dash list items + Given markdown with three dash list items + When parsing the markdown to blocks + Then block 1 is an unordered list with 3 items + + @edge-case @lists + Scenario: GFM checkbox list items + Given markdown with GFM checkbox items + When parsing the markdown to blocks + Then block 1 is an unordered list with checkbox text preserved + + Rule: Ordered lists are parsed into ListBlock + + **Invariant:** Lines starting with a digit followed by period-space produce ListBlock with ordered=true. + **Rationale:** Ordered lists represent sequential steps in procedural guides and must preserve ordering semantics. + **Verified by:** Numbered list items + + @happy-path @lists + Scenario: Numbered list items + Given markdown with three numbered list items + When parsing the markdown to blocks + Then block 1 is an ordered list with 3 items + + Rule: Code blocks are parsed into CodeBlock + + **Invariant:** Fenced code blocks with a language info string produce CodeBlock with the language and content fields. + **Rationale:** Code examples in preamble content must preserve the language annotation for syntax highlighting in generated docs. + **Verified by:** Code block with language, Empty code block + + @happy-path @code + Scenario: Code block with language + Given markdown with a typescript code block + When parsing the markdown to blocks + Then block 1 is a code block with language "typescript" and content + + @edge-case @code + Scenario: Empty code block + Given markdown with an empty code block + When parsing the markdown to blocks + Then block 1 is a code block with empty content + + Rule: Mermaid blocks are parsed into MermaidBlock + + **Invariant:** Code fences with the info string "mermaid" produce MermaidBlock instead of CodeBlock. + **Rationale:** Mermaid diagrams have a dedicated SectionBlock type for specialized rendering in generated docs. + **Verified by:** Mermaid diagram block + + @happy-path @mermaid + Scenario: Mermaid diagram block + Given markdown with a mermaid diagram + When parsing the markdown to blocks + Then block 1 is a mermaid block with graph content + + Rule: Mixed content produces correct block sequence + + **Invariant:** A markdown document with multiple construct types produces blocks in document order with correct types. + **Rationale:** Preamble files combine headings, paragraphs, code blocks, and tables in sequence. The parser must handle transitions between all state machine states correctly. + **Verified by:** Mixed content in sequence + + @happy-path @mixed + Scenario: Mixed content in sequence + Given markdown with heading, paragraph, table, code, and list + When parsing the markdown to blocks + Then 5 blocks are produced in the correct order + + Rule: Bold and inline formatting is preserved in paragraphs + + **Invariant:** Inline markdown formatting such as bold, italic, and code spans are preserved as-is in ParagraphBlock text. + **Rationale:** The parser produces structural blocks. Inline formatting is the responsibility of the markdown renderer, not the block parser. + **Verified by:** Bold text preserved in paragraph + + @edge-case @formatting + Scenario: Bold text preserved in paragraph + Given markdown with bold and code span formatting + When parsing the markdown to blocks + Then block 1 is a paragraph preserving inline formatting diff --git a/tests/steps/behavior/cli/process-api-reference.steps.ts b/tests/steps/behavior/cli/process-api-reference.steps.ts new file mode 100644 index 00000000..220514df --- /dev/null +++ b/tests/steps/behavior/cli/process-api-reference.steps.ts @@ -0,0 +1,310 @@ +/** + * Step definitions for Process API CLI Reference Generation tests (Phase 43) + */ + +import { loadFeature, describeFeature } from '@amiceli/vitest-cucumber'; +import { expect } from 'vitest'; +import { CLI_SCHEMA } from '../../../../src/cli/cli-schema.js'; +import { createProcessApiReferenceGenerator } from '../../../../src/generators/built-in/process-api-reference-generator.js'; +import type { GeneratorContext } from '../../../../src/generators/types.js'; + +// ============================================================================ +// State +// ============================================================================ + +interface TestState { + generatedContent: string | null; +} + +let state: TestState | null = null; + +// ============================================================================ +// Helpers +// ============================================================================ + +function getContent(): string { + if (state?.generatedContent === null || state?.generatedContent === undefined) { + throw new Error('Generated content not available — run generator first'); + } + return state.generatedContent; +} + +function extractTableRows(content: string, afterHeading: string): string[] { + const lines = content.split('\n'); + let inSection = false; + const rows: string[] = []; + + for (const line of lines) { + if (line.startsWith('## ') && line.includes(afterHeading)) { + inSection = true; + continue; + } + if (inSection && line.startsWith('## ')) { + break; + } + if (inSection && line.startsWith('| ') && !line.startsWith('| ---')) { + rows.push(line); + } + } + + // First row is header, rest are data + return rows.slice(1); +} + +function schemaFlagsFor( + group: 'globalOptions' | 'outputModifiers' | 'listFilters' | 'sessionOptions' +): string[] { + return CLI_SCHEMA[group].options.map((opt) => { + // Extract bare flag: '--input ' → '--input' + const match = /^(--[\w-]+)/.exec(opt.flag); + return match !== null ? match[1] : opt.flag; + }); +} + +// ============================================================================ +// Feature +// ============================================================================ + +const feature = await loadFeature('tests/features/behavior/cli/process-api-reference.feature'); + +describeFeature(feature, ({ AfterEachScenario, Rule }) => { + AfterEachScenario(() => { + state = null; + }); + + // ────────────────────────────────────────────────────────────────────── + // Rule: Generated reference file contains all three table sections + // ────────────────────────────────────────────────────────────────────── + + Rule('Generated reference file contains all three table sections', ({ RuleScenario }) => { + RuleScenario('Generated file contains Global Options table', ({ Given, When, Then, And }) => { + Given('the CLI schema is loaded', () => { + state = { generatedContent: null }; + expect(CLI_SCHEMA).toBeDefined(); + }); + + When('the ProcessApiReferenceGenerator produces output', async () => { + const generator = createProcessApiReferenceGenerator(); + const context: GeneratorContext = { + baseDir: process.cwd(), + outputDir: 'docs-live', + registry: {} as GeneratorContext['registry'], + }; + const output = await generator.generate([], context); + state!.generatedContent = output.files[0].content; + }); + + Then('the output contains a {string} heading', (_ctx: unknown, heading: string) => { + expect(getContent()).toContain(`## ${heading}`); + }); + + And( + 'the output contains a table with columns {string}, {string}, {string}, {string}', + (_ctx: unknown, c1: string, c2: string, c3: string, c4: string) => { + const content = getContent(); + expect(content).toContain(`| ${c1} |`); + expect(content).toContain(`| ${c2} |`); + expect(content).toContain(`| ${c3} |`); + expect(content).toContain(`| ${c4} |`); + } + ); + + And('the table has {int} rows for global options', (_ctx: unknown, expectedCount: number) => { + const rows = extractTableRows(getContent(), 'Global Options'); + expect(rows).toHaveLength(expectedCount); + }); + }); + + RuleScenario('Generated file contains Output Modifiers table', ({ Given, When, Then, And }) => { + Given('the CLI schema is loaded', () => { + state = { generatedContent: null }; + }); + + When('the ProcessApiReferenceGenerator produces output', async () => { + const generator = createProcessApiReferenceGenerator(); + const context: GeneratorContext = { + baseDir: process.cwd(), + outputDir: 'docs-live', + registry: {} as GeneratorContext['registry'], + }; + const output = await generator.generate([], context); + state!.generatedContent = output.files[0].content; + }); + + Then('the output contains an {string} heading', (_ctx: unknown, heading: string) => { + expect(getContent()).toContain(`## ${heading}`); + }); + + And( + 'the output contains a table with columns {string}, {string}', + (_ctx: unknown, c1: string, c2: string) => { + const content = getContent(); + expect(content).toContain(`| ${c1} |`); + expect(content).toContain(`| ${c2} |`); + } + ); + + And( + 'the table has {int} rows for output modifiers', + (_ctx: unknown, expectedCount: number) => { + const rows = extractTableRows(getContent(), 'Output Modifiers'); + expect(rows).toHaveLength(expectedCount); + } + ); + }); + + RuleScenario('Generated file contains List Filters table', ({ Given, When, Then, And }) => { + Given('the CLI schema is loaded', () => { + state = { generatedContent: null }; + }); + + When('the ProcessApiReferenceGenerator produces output', async () => { + const generator = createProcessApiReferenceGenerator(); + const context: GeneratorContext = { + baseDir: process.cwd(), + outputDir: 'docs-live', + registry: {} as GeneratorContext['registry'], + }; + const output = await generator.generate([], context); + state!.generatedContent = output.files[0].content; + }); + + Then('the output contains a {string} heading', (_ctx: unknown, heading: string) => { + expect(getContent()).toContain(`## ${heading}`); + }); + + And( + 'the output contains a table with columns {string}, {string}', + (_ctx: unknown, c1: string, c2: string) => { + const content = getContent(); + expect(content).toContain(`| ${c1} |`); + expect(content).toContain(`| ${c2} |`); + } + ); + + And('the table has {int} rows for list filters', (_ctx: unknown, expectedCount: number) => { + const rows = extractTableRows(getContent(), 'List Filters'); + expect(rows).toHaveLength(expectedCount); + }); + }); + + RuleScenario('Generated file includes inter-table prose', ({ Given, When, Then }) => { + Given('the CLI schema is loaded', () => { + state = { generatedContent: null }; + }); + + When('the ProcessApiReferenceGenerator produces output', async () => { + const generator = createProcessApiReferenceGenerator(); + const context: GeneratorContext = { + baseDir: process.cwd(), + outputDir: 'docs-live', + registry: {} as GeneratorContext['registry'], + }; + const output = await generator.generate([], context); + state!.generatedContent = output.files[0].content; + }); + + Then( + 'the output contains the following prose fragments:', + (_ctx: unknown, table: Array<{ fragment: string }>) => { + const content = getContent(); + for (const row of table) { + expect(content).toContain(row.fragment); + } + } + ); + }); + }); + + // ────────────────────────────────────────────────────────────────────── + // Rule: CLI schema stays in sync with parser + // ────────────────────────────────────────────────────────────────────── + + Rule('CLI schema stays in sync with parser', ({ RuleScenario }) => { + RuleScenario('Schema covers all global option flags', ({ Given, Then }) => { + Given('the CLI schema is loaded', () => { + state = { generatedContent: null }; + }); + + Then( + 'the schema global options include all expected flags:', + (_ctx: unknown, table: Array<{ flag: string }>) => { + const flags = schemaFlagsFor('globalOptions'); + for (const row of table) { + expect(flags).toContain(row.flag); + } + } + ); + }); + + RuleScenario('Schema covers all output modifier flags', ({ Given, Then }) => { + Given('the CLI schema is loaded', () => { + state = { generatedContent: null }; + }); + + Then( + 'the schema output modifiers include all expected flags:', + (_ctx: unknown, table: Array<{ flag: string }>) => { + const flags = schemaFlagsFor('outputModifiers'); + for (const row of table) { + expect(flags).toContain(row.flag); + } + } + ); + }); + + RuleScenario('Schema covers all list filter flags', ({ Given, Then }) => { + Given('the CLI schema is loaded', () => { + state = { generatedContent: null }; + }); + + Then( + 'the schema list filters include all expected flags:', + (_ctx: unknown, table: Array<{ flag: string }>) => { + const flags = schemaFlagsFor('listFilters'); + for (const row of table) { + expect(flags).toContain(row.flag); + } + } + ); + }); + + RuleScenario('Schema covers session option', ({ Given, Then }) => { + Given('the CLI schema is loaded', () => { + state = { generatedContent: null }; + }); + + Then( + 'the schema session options include all expected flags:', + (_ctx: unknown, table: Array<{ flag: string }>) => { + const flags = schemaFlagsFor('sessionOptions'); + for (const row of table) { + expect(flags).toContain(row.flag); + } + } + ); + }); + }); + + // ────────────────────────────────────────────────────────────────────── + // Rule: showHelp output reflects CLI schema + // ────────────────────────────────────────────────────────────────────── + + Rule('showHelp output reflects CLI schema', ({ RuleScenario }) => { + RuleScenario('Help text includes schema-defined options', ({ Given, Then }) => { + Given('the CLI schema is loaded', () => { + state = { generatedContent: null }; + }); + + Then( + 'all schema groups contain at least one option:', + (_ctx: unknown, table: Array<{ group: string }>) => { + for (const row of table) { + const group = row.group as keyof typeof CLI_SCHEMA; + expect(CLI_SCHEMA[group].options.length).toBeGreaterThan(0); + } + } + ); + }); + }); +}); diff --git a/tests/steps/behavior/codecs/convention-extractor.steps.ts b/tests/steps/behavior/codecs/convention-extractor.steps.ts index ce8ec961..84c5402e 100644 --- a/tests/steps/behavior/codecs/convention-extractor.steps.ts +++ b/tests/steps/behavior/codecs/convention-extractor.steps.ts @@ -645,6 +645,64 @@ describeFeature(feature, ({ Background, AfterEachScenario, Rule }) => { } ); + RuleScenario( + 'TypeScript table with escaped union pipes preserves full cell values', + ({ Given, When, Then, And }) => { + Given( + 'a TypeScript pattern with convention {string} and escaped union table description', + (_ctx: unknown, tag: string) => { + const description = [ + '## Remaining Work Options', + '', + '| Option | Type | Default | Description |', + '| --- | --- | --- | --- |', + '| sortBy | "phase" \\| "priority" \\| "effort" \\| "quarter" | "phase" | Sort order |', + ].join('\n'); + state!.dataset = createTestMasterDataset({ + patterns: [ + createTestPattern({ + name: 'TsEscapedUnionPattern', + convention: [tag], + description, + filePath: 'src/conventions/escaped-union.ts', + }), + ], + }); + } + ); + + When('extracting conventions for tag {string}', (_ctx: unknown, tag: string) => { + state!.result = extractConventions(state!.dataset!, [tag]); + }); + + Then( + 'the first table row has cell {string} with value {string}', + (_ctx: unknown, header: string, expected: string) => { + const firstRow = state!.result[0]!.rules[0]!.tables[0]!.rows[0]; + expect(firstRow?.[header]).toBe(expected); + } + ); + + And( + 'the first table row has cell {string} with value {string}', + (_ctx: unknown, header: string, expected: string) => { + const firstRow = state!.result[0]!.rules[0]!.tables[0]!.rows[0]; + expect(firstRow?.[header]).toBe(expected); + } + ); + + Then('the first table row has Type value with escaped unions', () => { + const firstRow = state!.result[0]!.rules[0]!.tables[0]!.rows[0]; + expect(firstRow?.Type).toBe('"phase" | "priority" | "effort" | "quarter"'); + }); + + Then('the first table row has Default value with quotes', () => { + const firstRow = state!.result[0]!.rules[0]!.tables[0]!.rows[0]; + expect(firstRow?.Default).toBe('"phase"'); + }); + } + ); + RuleScenario('TypeScript description with code examples', ({ Given, When, Then, And }) => { Given( 'a TypeScript pattern with convention {string} and mermaid description', diff --git a/tests/steps/behavior/codecs/generated-doc-quality.steps.ts b/tests/steps/behavior/codecs/generated-doc-quality.steps.ts new file mode 100644 index 00000000..04fd6a31 --- /dev/null +++ b/tests/steps/behavior/codecs/generated-doc-quality.steps.ts @@ -0,0 +1,433 @@ +/** + * Step definitions for Generated Documentation Quality tests (Phase 38) + */ + +import { loadFeature, describeFeature } from '@amiceli/vitest-cucumber'; +import { expect } from 'vitest'; +import { + type ReferenceCodecState, + initState, + createReferenceCodec, + createTestPattern, + createTestMasterDataset, + findHeadings, + findTables, + findLists, + findParagraphs, + type DetailLevel, + type RenderableDocument, +} from '../../../support/helpers/reference-codec-state.js'; +import { renderToMarkdown } from '../../../../src/renderable/render.js'; + +// ============================================================================ +// State +// ============================================================================ + +let state: ReferenceCodecState | null = null; + +// ============================================================================ +// Feature +// ============================================================================ + +const feature = await loadFeature('tests/features/behavior/codecs/generated-doc-quality.feature'); + +describeFeature(feature, ({ Background, AfterEachScenario, Rule }) => { + AfterEachScenario(() => { + state = null; + }); + + Background(({ Given }) => { + Given('a reference codec test context', () => { + state = initState(); + }); + }); + + // ────────────────────────────────────────────────────────────────────── + // Rule: Behavior-specs renderer does not duplicate convention table content + // ────────────────────────────────────────────────────────────────────── + + Rule( + 'Behavior-specs renderer does not duplicate convention table content', + ({ RuleScenario }) => { + RuleScenario( + 'Convention rule table appears exactly once in generated output', + ({ Given, And, When, Then }) => { + Given( + 'a reference config with convention tag {string} and include tag {string}', + (_ctx: unknown, convTag: string, includeTag: string) => { + state!.config = { + title: 'Test Dedup Document', + conventionTags: [convTag], + shapeSources: [], + behaviorCategories: [], + includeTags: [includeTag], + claudeMdSection: 'test', + docsFilename: 'TEST-DEDUP.md', + claudeMdFilename: 'test-dedup.md', + }; + } + ); + + And('a pattern with convention content and a table in its rule description', () => { + const tableDescription = + '**Invariant:** Values must be canonical.\n\n' + + '**Rationale:** Prevents drift.\n\n' + + '| Value | Meaning |\n| --- | --- |\n| alpha | First |\n| beta | Second |\n\n' + + '**Verified by:** Table validation'; + state!.dataset = createTestMasterDataset({ + patterns: [ + createTestPattern({ + name: 'ConventionWithTable', + convention: ['test-conv'], + include: ['test-include'], + rules: [ + { + name: 'Canonical Values', + description: tableDescription, + scenarioCount: 1, + scenarioNames: ['Table validation'], + }, + ], + }), + ], + }); + }); + + When('decoding at detail level {string}', (_ctx: unknown, level: string) => { + const codec = createReferenceCodec(state!.config!, { + detailLevel: level as DetailLevel, + }); + state!.document = codec.decode(state!.dataset!) as RenderableDocument; + }); + + Then('the table appears exactly once in the document', () => { + const tables = findTables(state!.document!); + const valueTables = tables.filter( + (t) => t.columns.includes('Value') && t.columns.includes('Meaning') + ); + expect(valueTables).toHaveLength(1); + }); + + And('the behavior-specs section contains invariant text', () => { + const paragraphs = findParagraphs(state!.document!); + const hasInvariant = paragraphs.some((p) => + p.text.includes('Values must be canonical') + ); + expect(hasInvariant).toBe(true); + }); + + And('the behavior-specs section does not contain the table', () => { + // The single table should be in convention section only. + // We already verified exactly 1 table with Value/Meaning headers above. + const tables = findTables(state!.document!); + const valueTables = tables.filter( + (t) => t.columns.includes('Value') && t.columns.includes('Meaning') + ); + expect(valueTables).toHaveLength(1); + }); + } + ); + + RuleScenario( + 'Behavior-specs show rule metadata without tables', + ({ Given, And, When, Then }) => { + Given( + 'a reference config with convention tag {string} and include tag {string}', + (_ctx: unknown, convTag: string, includeTag: string) => { + state!.config = { + title: 'Test Dedup Standard', + conventionTags: [convTag], + shapeSources: [], + behaviorCategories: [], + includeTags: [includeTag], + claudeMdSection: 'test', + docsFilename: 'TEST-DEDUP-STD.md', + claudeMdFilename: 'test-dedup-std.md', + }; + } + ); + + And('a pattern with convention content and a table in its rule description', () => { + const tableDescription = + '**Invariant:** Values must be canonical.\n\n' + + '**Rationale:** Prevents drift.\n\n' + + '| Value | Meaning |\n| --- | --- |\n| alpha | First |\n| beta | Second |\n\n' + + '**Verified by:** Table validation'; + state!.dataset = createTestMasterDataset({ + patterns: [ + createTestPattern({ + name: 'ConventionWithTable', + convention: ['test-conv'], + include: ['test-include'], + rules: [ + { + name: 'Canonical Values', + description: tableDescription, + scenarioCount: 1, + scenarioNames: ['Table validation'], + }, + ], + }), + ], + }); + }); + + When('decoding at detail level {string}', (_ctx: unknown, level: string) => { + const codec = createReferenceCodec(state!.config!, { + detailLevel: level as DetailLevel, + }); + state!.document = codec.decode(state!.dataset!) as RenderableDocument; + }); + + Then('the convention section renders the table', () => { + const tables = findTables(state!.document!); + const valueTables = tables.filter( + (t) => t.columns.includes('Value') && t.columns.includes('Meaning') + ); + expect(valueTables.length).toBeGreaterThanOrEqual(1); + }); + + And('no table rows are duplicated in the document', () => { + const markdown = renderToMarkdown(state!.document!); + const alphaMatches = markdown.match(/\| alpha/g); + // Table row should appear exactly once + expect(alphaMatches).toHaveLength(1); + }); + } + ); + } + ); + + // ────────────────────────────────────────────────────────────────────── + // Rule: ARCHITECTURE-TYPES leads with type definitions + // ────────────────────────────────────────────────────────────────────── + + Rule('ARCHITECTURE-TYPES leads with type definitions', ({ RuleScenario }) => { + RuleScenario( + 'Shapes section appears before conventions when shapesFirst is true', + ({ Given, And, When, Then }) => { + Given('a reference config with shapesFirst enabled', () => { + state!.config = { + title: 'Types First Test', + conventionTags: ['test-conv'], + shapeSources: [], + shapeSelectors: [{ group: 'test-shapes' }], + behaviorCategories: [], + shapesFirst: true, + claudeMdSection: 'test', + docsFilename: 'TEST-TYPES.md', + claudeMdFilename: 'test-types.md', + }; + }); + + And('a dataset with both convention content and shape content', () => { + state!.dataset = createTestMasterDataset({ + patterns: [ + createTestPattern({ + name: 'ConventionPattern', + convention: ['test-conv'], + rules: [ + { + name: 'Convention Rule', + description: '**Invariant:** Must follow convention.', + scenarioCount: 0, + scenarioNames: [], + }, + ], + }), + createTestPattern({ + name: 'ShapePattern', + extractedShapes: [ + { + name: 'TestInterface', + kind: 'interface', + sourceText: 'interface TestInterface { id: string }', + lineNumber: 1, + group: 'test-shapes', + exported: true, + }, + ], + }), + ], + }); + }); + + When('decoding at detail level {string}', (_ctx: unknown, level: string) => { + const codec = createReferenceCodec(state!.config!, { + detailLevel: level as DetailLevel, + }); + state!.document = codec.decode(state!.dataset!) as RenderableDocument; + }); + + Then('the first heading after the title is from the shapes section', () => { + const headings = findHeadings(state!.document!); + // Find first H2 heading — should be API Types (shapes) + const h2s = headings.filter((h) => h.level === 2); + expect(h2s.length).toBeGreaterThanOrEqual(2); + expect(h2s[0].text).toBe('API Types'); + }); + + And('the convention heading appears after the shapes section', () => { + const headings = findHeadings(state!.document!); + const h2s = headings.filter((h) => h.level === 2); + const shapesIdx = h2s.findIndex((h) => h.text === 'API Types'); + const convIdx = h2s.findIndex((h) => h.text === 'Convention Rule'); + expect(shapesIdx).toBeLessThan(convIdx); + }); + } + ); + }); + + // ────────────────────────────────────────────────────────────────────── + // Rule: Product area docs have a generated table of contents + // ────────────────────────────────────────────────────────────────────── + + Rule('Product area docs have a generated table of contents', ({ RuleScenario }) => { + RuleScenario( + 'Product area doc with multiple sections gets a TOC', + ({ Given, And, When, Then }) => { + Given('a product area config for {string}', (_ctx: unknown, area: string) => { + state!.config = { + title: `${area} Product Area`, + conventionTags: [], + shapeSources: [], + behaviorCategories: [], + productArea: area, + claudeMdSection: 'test', + docsFilename: `${area.toUpperCase()}.md`, + claudeMdFilename: `${area.toLowerCase()}.md`, + }; + }); + + And('a dataset with multiple patterns in the Generation area', () => { + state!.dataset = createTestMasterDataset({ + patterns: [ + createTestPattern({ + name: 'GenPattern1', + productArea: 'Generation', + convention: ['gen-conv'], + rules: [ + { + name: 'Gen Rule 1', + description: '**Invariant:** First rule.', + scenarioCount: 1, + scenarioNames: ['Verify rule 1'], + }, + ], + }), + createTestPattern({ + name: 'GenPattern2', + productArea: 'Generation', + rules: [ + { + name: 'Gen Rule 2', + description: '**Invariant:** Second rule.', + scenarioCount: 1, + scenarioNames: ['Verify rule 2'], + }, + ], + }), + createTestPattern({ + name: 'GenPattern3', + productArea: 'Generation', + extractedShapes: [ + { + name: 'GenType', + kind: 'interface', + sourceText: 'interface GenType { x: number }', + lineNumber: 1, + exported: true, + }, + ], + }), + ], + }); + }); + + When('decoding at detail level {string}', (_ctx: unknown, level: string) => { + const codec = createReferenceCodec(state!.config!, { + detailLevel: level as DetailLevel, + }); + state!.document = codec.decode(state!.dataset!) as RenderableDocument; + }); + + Then('the document contains a heading {string}', (_ctx: unknown, headingText: string) => { + const headings = findHeadings(state!.document!); + const match = headings.find((h) => h.text === headingText); + expect(match).toBeDefined(); + }); + + And('the Contents section is a list with anchor links', () => { + const lists = findLists(state!.document!); + // Find the list that follows the Contents heading + const hasAnchorLinks = lists.some((l) => + l.items.some((item) => { + const text = typeof item === 'string' ? item : item.text; + return text.includes('](#'); + }) + ); + expect(hasAnchorLinks).toBe(true); + }); + + And('the Contents heading appears after the intro separator', () => { + // Contents should not be the very first section — it comes after intro + const sections = state!.document!.sections; + const contentsIdx = sections.findIndex( + (s) => s.type === 'heading' && s.level === 2 && s.text === 'Contents' + ); + const firstSepIdx = sections.findIndex((s) => s.type === 'separator'); + expect(contentsIdx).toBeGreaterThan(firstSepIdx); + }); + } + ); + }); + + // ────────────────────────────────────────────────────────────────────── + // Rule: Generation compact is self-sufficient + // ────────────────────────────────────────────────────────────────────── + + Rule('Generation compact is self-sufficient', ({ RuleScenario }) => { + RuleScenario('Generation compact contains enriched content', ({ Given, And, When, Then }) => { + Given('a product area config for {string}', (_ctx: unknown, area: string) => { + state!.config = { + title: `${area} Product Area`, + conventionTags: [], + shapeSources: [], + behaviorCategories: [], + productArea: area, + claudeMdSection: 'test', + docsFilename: `${area.toUpperCase()}.md`, + claudeMdFilename: `${area.toLowerCase()}.md`, + }; + }); + + And('a dataset with Generation area patterns', () => { + state!.dataset = createTestMasterDataset({ + patterns: [ + createTestPattern({ + name: 'GenerationCodec', + productArea: 'Generation', + }), + ], + }); + }); + + When('decoding at detail level {string}', (_ctx: unknown, level: string) => { + const codec = createReferenceCodec(state!.config!, { + detailLevel: level as DetailLevel, + }); + state!.document = codec.decode(state!.dataset!) as RenderableDocument; + }); + + Then( + 'the rendered output contains all expected terms:', + (_ctx: unknown, dataTable: Array<{ Term: string }>) => { + const markdown = renderToMarkdown(state!.document!); + for (const row of dataTable) { + expect(markdown).toContain(row.Term); + } + } + ); + }); + }); +}); diff --git a/tests/steps/behavior/codecs/reference-codec-diagrams.steps.ts b/tests/steps/behavior/codecs/reference-codec-diagrams.steps.ts index 1478405f..01bd47f7 100644 --- a/tests/steps/behavior/codecs/reference-codec-diagrams.steps.ts +++ b/tests/steps/behavior/codecs/reference-codec-diagrams.steps.ts @@ -645,6 +645,80 @@ describeFeature(feature, ({ Background, AfterEachScenario, Rule }) => { }); }); + // ────────────────────────────────────────────────────────────────────── + // Rule: Hardcoded diagram sources render deterministic output + // ────────────────────────────────────────────────────────────────────── + + Rule('Hardcoded diagram sources render deterministic output', ({ RuleScenario }) => { + RuleScenario( + 'master-dataset-views source produces MasterDataset fan-out diagram', + ({ Given, And, When, Then }) => { + Given( + 'a reference config with diagramScope source {string}', + (_ctx: unknown, source: string) => { + state!.config = { + title: 'Test Reference Document', + conventionTags: [], + shapeSources: [], + behaviorCategories: [], + diagramScope: { source: source as 'master-dataset-views' }, + claudeMdSection: 'test', + docsFilename: 'TEST-REFERENCE.md', + claudeMdFilename: 'test.md', + }; + } + ); + + And( + 'a MasterDataset with arch-annotated patterns in context {string}', + (_ctx: unknown, context: string) => { + state!.dataset = createTestMasterDataset({ + patterns: [ + createTestPattern({ + name: 'LintRules', + archContext: context, + archRole: 'service', + }), + ], + }); + } + ); + + When('decoding at detail level {string}', (_ctx: unknown, level: string) => { + const codec = createReferenceCodec(state!.config!, { + detailLevel: level as DetailLevel, + }); + state!.document = codec.decode(state!.dataset!) as RenderableDocument; + }); + + Then('the document contains a mermaid block', () => { + const mermaidBlocks = findBlocksByType(state!.document!, 'mermaid'); + expect(mermaidBlocks.length).toBeGreaterThanOrEqual(1); + }); + + And('the mermaid content contains {string}', (_ctx: unknown, text: string) => { + const mermaidBlocks = findBlocksByType(state!.document!, 'mermaid'); + expect(mermaidBlocks.length).toBeGreaterThanOrEqual(1); + const content = mermaidBlocks[0]!.content; + expect(content).toContain(text); + }); + + And( + 'the mermaid content contains all of {string}, {string}, {string}, and {string}', + (_ctx: unknown, text1: string, text2: string, text3: string, text4: string) => { + const mermaidBlocks = findBlocksByType(state!.document!, 'mermaid'); + expect(mermaidBlocks.length).toBeGreaterThanOrEqual(1); + const content = mermaidBlocks[0]!.content; + expect(content).toContain(text1); + expect(content).toContain(text2); + expect(content).toContain(text3); + expect(content).toContain(text4); + } + ); + } + ); + }); + // ────────────────────────────────────────────────────────────────────── // Rule: Multiple diagram scopes produce multiple mermaid blocks // ────────────────────────────────────────────────────────────────────── diff --git a/tests/steps/behavior/codecs/reference-generators.steps.ts b/tests/steps/behavior/codecs/reference-generators.steps.ts index ac5c6f24..86f02a2c 100644 --- a/tests/steps/behavior/codecs/reference-generators.steps.ts +++ b/tests/steps/behavior/codecs/reference-generators.steps.ts @@ -5,6 +5,7 @@ import { loadFeature, describeFeature } from '@amiceli/vitest-cucumber'; import { expect } from 'vitest'; import type { MasterDataset } from '../../../../src/validation-schemas/master-dataset.js'; +import type { ExtractedShape } from '../../../../src/validation-schemas/extracted-shape.js'; import type { GeneratorOutput, GeneratorContext } from '../../../../src/generators/types.js'; import { GeneratorRegistry } from '../../../../src/generators/registry.js'; import { @@ -21,11 +22,22 @@ import { buildRegistry } from '../../../../src/taxonomy/registry-builder.js'; // ============================================================================ /** - * Test configs: 7 product area configs + 1 manual reference config. + * Test configs: 7 product area configs + 2 manual reference configs. * Mirrors the shape of delivery-process.config.ts. */ const TEST_CONFIGS: readonly ReferenceDocConfig[] = [ ...createProductAreaConfigs(), + { + title: 'Architecture Types Reference', + conventionTags: ['pipeline-architecture'], + shapeSources: [], + shapeSelectors: [{ group: 'master-dataset' }], + behaviorCategories: [], + claudeMdSection: 'architecture', + docsFilename: 'ARCHITECTURE-TYPES.md', + claudeMdFilename: 'architecture-types.md', + diagramScopes: [{ title: 'MasterDataset View Fan-out', source: 'master-dataset-views' }], + }, { title: 'Reference Generation Sample', conventionTags: ['taxonomy-rules'], @@ -69,6 +81,17 @@ function makeMinimalContext(dataset: MasterDataset): GeneratorContext { }; } +function createShape(name: string, group?: string): ExtractedShape { + return { + name, + kind: 'interface', + sourceText: `export interface ${name} {}`, + lineNumber: 1, + exported: true, + ...(group !== undefined ? { group } : {}), + }; +} + // ============================================================================ // Feature // ============================================================================ @@ -160,6 +183,20 @@ describeFeature(feature, ({ Background, AfterEachScenario, Rule }) => { }); } ); + + RuleScenario('Architecture-types generators are registered', ({ When, Then, And }) => { + When('registering reference generators', () => { + registerReferenceGenerators(state!.registry, TEST_CONFIGS); + }); + + Then('a generator named {string} exists', (_ctx: unknown, name: string) => { + expect(state!.registry.has(name)).toBe(true); + }); + + And('a generator named {string} exists', (_ctx: unknown, name: string) => { + expect(state!.registry.has(name)).toBe(true); + }); + }); }); // ────────────────────────────────────────────────────────────────────── @@ -238,5 +275,67 @@ describeFeature(feature, ({ Background, AfterEachScenario, Rule }) => { }); } ); + + RuleScenario( + 'ARCHITECTURE-TYPES generator produces shapes and convention content', + ({ Given, When, Then, And }) => { + Given( + 'a MasterDataset with pipeline architecture conventions and master dataset shapes', + () => { + state!.dataset = createTestMasterDataset({ + patterns: [ + createTestPattern({ + name: 'Documentation Generation Orchestrator', + category: 'core', + convention: ['pipeline-architecture'], + description: `## Orchestrator Pipeline Responsibilities + +**Invariant:** Orchestrator owns final generation wiring. + +## Steps 9-10: Codec Execution and File Writing + +Codec decode and file write happen after shared dataset build.`, + }), + createTestPattern({ + name: 'MasterDataset', + category: 'core', + extractedShapes: [ + createShape('MasterDatasetSchema', 'master-dataset'), + createShape('PipelineOptions', 'master-dataset'), + ], + }), + ], + }); + } + ); + + When('running the {string} generator', async (_ctx: unknown, generatorName: string) => { + registerReferenceGenerators(state!.registry, TEST_CONFIGS); + const generator = state!.registry.get(generatorName); + expect(generator).toBeDefined(); + const context = makeMinimalContext(state!.dataset!); + state!.output = await generator!.generate([], context); + }); + + Then('the output has {int} file', (_ctx: unknown, count: number) => { + expect(state!.output!.files).toHaveLength(count); + }); + + And('the output file path starts with {string}', (_ctx: unknown, prefix: string) => { + expect(state!.output!.files[0]!.path.startsWith(prefix)).toBe(true); + }); + + And( + 'the output file content contains all of {string}, {string}, {string}, and {string}', + (_ctx: unknown, text1: string, text2: string, text3: string, text4: string) => { + const content = state!.output!.files[0]!.content; + expect(content).toContain(text1); + expect(content).toContain(text2); + expect(content).toContain(text3); + expect(content).toContain(text4); + } + ); + } + ); }); }); diff --git a/tests/steps/doc-generation/architecture-doc-refactoring.steps.ts b/tests/steps/doc-generation/architecture-doc-refactoring.steps.ts new file mode 100644 index 00000000..222d05ae --- /dev/null +++ b/tests/steps/doc-generation/architecture-doc-refactoring.steps.ts @@ -0,0 +1,446 @@ +/** + * Integration steps for architecture doc refactoring coverage. + */ + +import { loadFeature, describeFeature } from '@amiceli/vitest-cucumber'; +import { expect } from 'vitest'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; + +interface ArchitectureRefactoringState { + architectureContent: string | null; + currentSectionName: string | null; + currentSectionContent: string | null; + currentFileContent: string | null; +} + +function initState(): ArchitectureRefactoringState { + return { + architectureContent: null, + currentSectionName: null, + currentSectionContent: null, + currentFileContent: null, + }; +} + +function getHeadingStart(content: string, heading: string): number { + const escaped = heading.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const headingRegex = new RegExp(`^##\\s+${escaped}\\s*$`, 'm'); + const match = headingRegex.exec(content); + return match?.index ?? -1; +} + +function getSectionContent(content: string, heading: string): string { + const start = getHeadingStart(content, heading); + if (start < 0) return ''; + + const afterStart = content.slice(start); + const nextHeadingMatch = /^##\s+/m.exec(afterStart.slice(1)); + if (!nextHeadingMatch) return afterStart; + + const nextStart = nextHeadingMatch.index + 1; + return afterStart.slice(0, nextStart); +} + +let state: ArchitectureRefactoringState | null = null; + +const feature = await loadFeature( + 'tests/features/doc-generation/architecture-doc-refactoring.feature' +); + +describeFeature(feature, ({ Background, AfterEachScenario, Rule }) => { + AfterEachScenario(() => { + state = null; + }); + + Background(({ Given }) => { + Given('ARCHITECTURE.md on the filesystem', () => { + state = initState(); + const fullPath = path.join(process.cwd(), 'docs/ARCHITECTURE.md'); + state.architectureContent = fs.readFileSync(fullPath, 'utf-8'); + }); + }); + + Rule('Product area sections coexist with generated documents', ({ RuleScenario }) => { + RuleScenario( + 'Configuration Architecture section retained and generated doc exists', + ({ When, Then, And }) => { + When('reading the {string} section', (_ctx: unknown, section: string) => { + state!.currentSectionName = section; + state!.currentSectionContent = getSectionContent(state!.architectureContent!, section); + }); + + Then('the section has content', () => { + expect(state!.currentSectionContent!.length).toBeGreaterThan(0); + }); + + And('file {string} contains {string}', (_ctx: unknown, filePath: string, text: string) => { + const fullPath = path.join(process.cwd(), filePath); + const content = fs.readFileSync(fullPath, 'utf-8'); + expect(content.toLowerCase()).toContain(text.toLowerCase()); + }); + + And( + 'file {string} also contains {string}', + (_ctx: unknown, filePath: string, text: string) => { + const fullPath = path.join(process.cwd(), filePath); + const content = fs.readFileSync(fullPath, 'utf-8'); + expect(content.toLowerCase()).toContain(text.toLowerCase()); + } + ); + } + ); + + RuleScenario( + 'Source Systems section retained and annotation product area exists', + ({ When, Then, And }) => { + When('reading the {string} section', (_ctx: unknown, section: string) => { + state!.currentSectionName = section; + state!.currentSectionContent = getSectionContent(state!.architectureContent!, section); + }); + + Then('the section has content', () => { + expect(state!.currentSectionContent!.length).toBeGreaterThan(0); + }); + + And('file {string} contains {string}', (_ctx: unknown, filePath: string, text: string) => { + const fullPath = path.join(process.cwd(), filePath); + const content = fs.readFileSync(fullPath, 'utf-8'); + expect(content.toLowerCase()).toContain(text.toLowerCase()); + }); + + And( + 'file {string} also contains {string}', + (_ctx: unknown, filePath: string, text: string) => { + const fullPath = path.join(process.cwd(), filePath); + const content = fs.readFileSync(fullPath, 'utf-8'); + expect(content.toLowerCase()).toContain(text.toLowerCase()); + } + ); + } + ); + + RuleScenario( + 'Workflow Integration section retained and process product area exists', + ({ When, Then, And }) => { + When('reading the {string} section', (_ctx: unknown, section: string) => { + state!.currentSectionName = section; + state!.currentSectionContent = getSectionContent(state!.architectureContent!, section); + }); + + Then('the section has content', () => { + expect(state!.currentSectionContent!.length).toBeGreaterThan(0); + }); + + And('file {string} contains {string}', (_ctx: unknown, filePath: string, text: string) => { + const fullPath = path.join(process.cwd(), filePath); + const content = fs.readFileSync(fullPath, 'utf-8'); + expect(content.toLowerCase()).toContain(text.toLowerCase()); + }); + + And( + 'file {string} also contains {string}', + (_ctx: unknown, filePath: string, text: string) => { + const fullPath = path.join(process.cwd(), filePath); + const content = fs.readFileSync(fullPath, 'utf-8'); + expect(content.toLowerCase()).toContain(text.toLowerCase()); + } + ); + } + ); + }); + + Rule('Four-Stage Pipeline section retains annotation format examples', ({ RuleScenario }) => { + RuleScenario( + 'Annotation format examples appear before Source Systems', + ({ When, Then, And }) => { + When('reading the {string} section', (_ctx: unknown, section: string) => { + state!.currentSectionName = section; + state!.currentSectionContent = getSectionContent(state!.architectureContent!, section); + expect(state!.currentSectionContent.length).toBeGreaterThan(0); + }); + + Then('the section contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentSectionContent).toContain(text); + }); + + And('the section also contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentSectionContent).toContain(text); + }); + + And( + 'section {string} appears before section {string}', + (_ctx: unknown, first: string, second: string) => { + const content = state!.architectureContent!; + const firstStart = getHeadingStart(content, first); + const secondStart = getHeadingStart(content, second); + expect(firstStart).toBeGreaterThanOrEqual(0); + expect(secondStart).toBeGreaterThanOrEqual(0); + expect(firstStart).toBeLessThan(secondStart); + } + ); + } + ); + }); + + Rule( + 'Convention extraction produces ARCHITECTURE-CODECS reference document', + ({ RuleScenario }) => { + RuleScenario( + 'Session codecs file produces multiple convention sections', + ({ When, Then }) => { + When('reading file {string}', (_ctx: unknown, filePath: string) => { + const fullPath = path.join(process.cwd(), filePath); + state!.currentFileContent = fs.readFileSync(fullPath, 'utf-8'); + }); + + Then('the file contains each of the following:', (_ctx: unknown, docString: string) => { + for (const line of docString.trim().split('\n')) { + if (line.trim().length > 0) { + expect(state!.currentFileContent).toContain(line.trim()); + } + } + }); + } + ); + + RuleScenario('Convention sections include output file references', ({ When, Then, And }) => { + When('reading file {string}', (_ctx: unknown, filePath: string) => { + const fullPath = path.join(process.cwd(), filePath); + state!.currentFileContent = fs.readFileSync(fullPath, 'utf-8'); + }); + + Then('the file contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentFileContent).toContain(text); + }); + + And('the file also contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentFileContent).toContain(text); + }); + }); + + RuleScenario( + 'ARCHITECTURE-CODECS document has substantial content from all codec files', + ({ When, Then }) => { + When('reading file {string}', (_ctx: unknown, filePath: string) => { + const fullPath = path.join(process.cwd(), filePath); + state!.currentFileContent = fs.readFileSync(fullPath, 'utf-8'); + }); + + Then('the file has more than {int} lines', (_ctx: unknown, minLines: number) => { + const lineCount = state!.currentFileContent!.split('\n').length; + expect(lineCount).toBeGreaterThan(minLines); + }); + } + ); + + RuleScenario('Session codec source file has structured JSDoc headings', ({ When, Then }) => { + When('reading file {string}', (_ctx: unknown, filePath: string) => { + const fullPath = path.join(process.cwd(), filePath); + state!.currentFileContent = fs.readFileSync(fullPath, 'utf-8'); + }); + + Then('the file contains each of the following:', (_ctx: unknown, docString: string) => { + for (const line of docString.trim().split('\n')) { + if (line.trim().length > 0) { + expect(state!.currentFileContent).toContain(line.trim()); + } + } + }); + }); + + RuleScenario( + 'Convention rule titles match source heading text in generated output', + ({ When, Then, And }) => { + When('reading file {string}', (_ctx: unknown, filePath: string) => { + const fullPath = path.join(process.cwd(), filePath); + state!.currentFileContent = fs.readFileSync(fullPath, 'utf-8'); + }); + + Then('the file contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentFileContent).toContain(text); + }); + + And('the file also contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentFileContent).toContain(text); + }); + } + ); + } + ); + + Rule('Full sections coexist with generated equivalents in docs-live', ({ RuleScenario }) => { + RuleScenario( + 'Unified Transformation Architecture section retained and ARCHITECTURE-TYPES exists', + ({ When, Then, And }) => { + When('reading the {string} section', (_ctx: unknown, section: string) => { + state!.currentSectionName = section; + state!.currentSectionContent = getSectionContent(state!.architectureContent!, section); + }); + + Then('the section contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentSectionContent).toContain(text); + }); + + And('file {string} exists', (_ctx: unknown, filePath: string) => { + const fullPath = path.join(process.cwd(), filePath); + expect(fs.existsSync(fullPath)).toBe(true); + }); + } + ); + + RuleScenario( + 'Data Flow Diagrams section retained and ARCHITECTURE-TYPES exists', + ({ When, Then, And }) => { + When('reading the {string} section', (_ctx: unknown, section: string) => { + state!.currentSectionName = section; + state!.currentSectionContent = getSectionContent(state!.architectureContent!, section); + }); + + Then('the section has content', () => { + expect(state!.currentSectionContent!.length).toBeGreaterThan(0); + }); + + And('file {string} exists', (_ctx: unknown, filePath: string) => { + const fullPath = path.join(process.cwd(), filePath); + expect(fs.existsSync(fullPath)).toBe(true); + }); + } + ); + + RuleScenario( + 'Quick Reference section retained and ARCHITECTURE-CODECS exists', + ({ When, Then, And }) => { + When('reading the {string} section', (_ctx: unknown, section: string) => { + state!.currentSectionName = section; + state!.currentSectionContent = getSectionContent(state!.architectureContent!, section); + }); + + Then('the section has content', () => { + expect(state!.currentSectionContent!.length).toBeGreaterThan(0); + }); + + And('file {string} exists', (_ctx: unknown, filePath: string) => { + const fullPath = path.join(process.cwd(), filePath); + expect(fs.existsSync(fullPath)).toBe(true); + }); + } + ); + }); + + Rule('MasterDataset shapes appear in ARCHITECTURE-TYPES reference', ({ RuleScenario }) => { + RuleScenario('Core MasterDataset types appear in ARCHITECTURE-TYPES', ({ When, Then }) => { + When('reading file {string}', (_ctx: unknown, filePath: string) => { + const fullPath = path.join(process.cwd(), filePath); + state!.currentFileContent = fs.readFileSync(fullPath, 'utf-8'); + }); + + Then('the file contains each of the following:', (_ctx: unknown, docString: string) => { + for (const line of docString.trim().split('\n')) { + if (line.trim().length > 0) { + expect(state!.currentFileContent).toContain(line.trim()); + } + } + }); + }); + + RuleScenario('Pipeline types appear in ARCHITECTURE-TYPES reference', ({ When, Then, And }) => { + When('reading file {string}', (_ctx: unknown, filePath: string) => { + const fullPath = path.join(process.cwd(), filePath); + state!.currentFileContent = fs.readFileSync(fullPath, 'utf-8'); + }); + + Then('the file contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentFileContent).toContain(text); + }); + + And('the file also contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentFileContent).toContain(text); + }); + }); + + RuleScenario( + 'Unified Transformation section has full MasterDataset content', + ({ When, Then, And }) => { + When('reading the {string} section', (_ctx: unknown, section: string) => { + state!.currentSectionName = section; + state!.currentSectionContent = getSectionContent(state!.architectureContent!, section); + expect(state!.currentSectionContent.length).toBeGreaterThan(0); + }); + + Then('the section contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentSectionContent).toContain(text); + }); + + And('the section also contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentSectionContent).toContain(text); + }); + } + ); + }); + + Rule('Pipeline architecture convention appears in generated reference', ({ RuleScenario }) => { + RuleScenario( + 'Orchestrator source file has pipeline-architecture convention tag', + ({ When, Then }) => { + When('reading file {string}', (_ctx: unknown, filePath: string) => { + const fullPath = path.join(process.cwd(), filePath); + state!.currentFileContent = fs.readFileSync(fullPath, 'utf-8'); + }); + + Then('the file contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentFileContent).toContain(text); + }); + } + ); + + RuleScenario( + 'Build-pipeline source file has pipeline-architecture convention tag', + ({ When, Then }) => { + When('reading file {string}', (_ctx: unknown, filePath: string) => { + const fullPath = path.join(process.cwd(), filePath); + state!.currentFileContent = fs.readFileSync(fullPath, 'utf-8'); + }); + + Then('the file contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentFileContent).toContain(text); + }); + } + ); + }); + + Rule('Full ARCHITECTURE.md retains all sections with substantial content', ({ RuleScenario }) => { + RuleScenario('Programmatic Usage section exists in ARCHITECTURE.md', ({ Then }) => { + Then('section {string} exists in ARCHITECTURE.md', (_ctx: unknown, heading: string) => { + const idx = getHeadingStart(state!.architectureContent!, heading); + expect(idx).toBeGreaterThanOrEqual(0); + }); + }); + + RuleScenario('Extending the System section exists in ARCHITECTURE.md', ({ Then }) => { + Then('section {string} exists in ARCHITECTURE.md', (_ctx: unknown, heading: string) => { + const idx = getHeadingStart(state!.architectureContent!, heading); + expect(idx).toBeGreaterThanOrEqual(0); + }); + }); + + RuleScenario('Key Design Patterns section has design pattern content', ({ When, Then }) => { + When('reading the {string} section', (_ctx: unknown, section: string) => { + state!.currentSectionName = section; + state!.currentSectionContent = getSectionContent(state!.architectureContent!, section); + expect(state!.currentSectionContent.length).toBeGreaterThan(0); + }); + + Then('the section contains {string}', (_ctx: unknown, text: string) => { + expect(state!.currentSectionContent).toContain(text); + }); + }); + + RuleScenario('ARCHITECTURE.md is under 1700 lines as full reference', ({ Then }) => { + Then('ARCHITECTURE.md has fewer than {int} lines', (_ctx: unknown, limit: number) => { + const lineCount = state!.architectureContent!.split('\n').length; + expect(lineCount).toBeLessThan(limit); + }); + }); + }); +}); diff --git a/tests/steps/generation/load-preamble.steps.ts b/tests/steps/generation/load-preamble.steps.ts new file mode 100644 index 00000000..0bf73e43 --- /dev/null +++ b/tests/steps/generation/load-preamble.steps.ts @@ -0,0 +1,503 @@ +/** + * Load Preamble Parser Step Definitions + * + * BDD step definitions for testing the parseMarkdownToBlocks function: + * - Heading parsing (levels 1-6) + * - Paragraph parsing (single/multi-line) + * - Separator parsing + * - Table parsing + * - List parsing (ordered/unordered/GFM checkbox) + * - Code block parsing + * - Mermaid block parsing + * - Mixed content sequencing + * - Inline formatting preservation + * + * NOTE: Markdown content is hardcoded in step definitions rather than + * using DocStrings because DocStrings containing code fences (```) + * are mishandled by vitest-cucumber. + * + * @libar-docs + */ +import { loadFeature, describeFeature } from '@amiceli/vitest-cucumber'; +import { expect } from 'vitest'; + +import type { SectionBlock } from '../../../src/renderable/schema.js'; +import { parseMarkdownToBlocks } from '../../../src/renderable/load-preamble.js'; + +// ============================================================================= +// State Types +// ============================================================================= + +interface LoadPreambleState { + markdownContent: string; + blocks: readonly SectionBlock[]; +} + +// ============================================================================= +// Module-level state (reset per scenario) +// ============================================================================= + +let state: LoadPreambleState | null = null; + +function initState(): LoadPreambleState { + return { + markdownContent: '', + blocks: [], + }; +} + +// ============================================================================= +// Helper Functions +// ============================================================================= + +function requireState(): LoadPreambleState { + if (!state) throw new Error('State not initialized'); + return state; +} + +function getBlock(index: number): SectionBlock { + const s = requireState(); + const block = s.blocks[index]; + if (!block) throw new Error(`No block at index ${String(index)}`); + return block; +} + +// ============================================================================= +// Feature Definition +// ============================================================================= + +const feature = await loadFeature('tests/features/generation/load-preamble.feature'); + +describeFeature(feature, ({ Background, Rule, AfterEachScenario }) => { + // --------------------------------------------------------------------------- + // Lifecycle Hooks + // --------------------------------------------------------------------------- + + AfterEachScenario(() => { + state = null; + }); + + // --------------------------------------------------------------------------- + // Background + // --------------------------------------------------------------------------- + + Background(({ Given }) => { + Given('a markdown parser test context', () => { + state = initState(); + }); + }); + + // --------------------------------------------------------------------------- + // Rule: Headings are parsed into HeadingBlock + // --------------------------------------------------------------------------- + + Rule('Headings are parsed into HeadingBlock', ({ RuleScenario }) => { + RuleScenario('Single heading is parsed', ({ Given, When, Then }) => { + Given('markdown with a level 2 heading {string}', (_ctx: unknown, _text: string) => { + requireState().markdownContent = '## Getting Started'; + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('block 1 is a heading at level 2 with text {string}', (_ctx: unknown, text: string) => { + const block = getBlock(0); + expect(block.type).toBe('heading'); + if (block.type === 'heading') { + expect(block.level).toBe(2); + expect(block.text).toBe(text); + } + }); + }); + + RuleScenario('All heading levels are parsed correctly', ({ Given, When, Then }) => { + Given('markdown with all six heading levels', () => { + requireState().markdownContent = [ + '# H1', + '## H2', + '### H3', + '#### H4', + '##### H5', + '###### H6', + ].join('\n'); + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('6 heading blocks are produced with levels 1 through 6', () => { + const s = requireState(); + expect(s.blocks).toHaveLength(6); + for (let i = 0; i < 6; i++) { + const block = getBlock(i); + expect(block.type).toBe('heading'); + if (block.type === 'heading') { + expect(block.level).toBe(i + 1); + expect(block.text).toBe(`H${String(i + 1)}`); + } + } + }); + }); + }); + + // --------------------------------------------------------------------------- + // Rule: Paragraphs are parsed into ParagraphBlock + // --------------------------------------------------------------------------- + + Rule('Paragraphs are parsed into ParagraphBlock', ({ RuleScenario }) => { + RuleScenario('Single line paragraph', ({ Given, When, Then }) => { + Given('markdown with a single paragraph line', () => { + requireState().markdownContent = 'This is a simple paragraph.'; + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('block 1 is a paragraph with text {string}', (_ctx: unknown, text: string) => { + const block = getBlock(0); + expect(block.type).toBe('paragraph'); + if (block.type === 'paragraph') { + expect(block.text).toBe(text); + } + }); + }); + + RuleScenario('Multi-line paragraph joined with space', ({ Given, When, Then }) => { + Given('markdown with a two-line paragraph', () => { + requireState().markdownContent = + 'This is the first line\nand this continues the paragraph.'; + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('block 1 is a paragraph with joined text', () => { + const block = getBlock(0); + expect(block.type).toBe('paragraph'); + if (block.type === 'paragraph') { + expect(block.text).toBe('This is the first line and this continues the paragraph.'); + } + }); + }); + }); + + // --------------------------------------------------------------------------- + // Rule: Separators are parsed into SeparatorBlock + // --------------------------------------------------------------------------- + + Rule('Separators are parsed into SeparatorBlock', ({ RuleScenario }) => { + RuleScenario('Triple dash separator', ({ Given, When, Then }) => { + Given('markdown with a separator between paragraphs', () => { + requireState().markdownContent = 'Above\n\n---\n\nBelow'; + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('the result has a paragraph then separator then paragraph', () => { + const s = requireState(); + expect(s.blocks).toHaveLength(3); + expect(s.blocks[0]?.type).toBe('paragraph'); + expect(s.blocks[1]?.type).toBe('separator'); + expect(s.blocks[2]?.type).toBe('paragraph'); + const first = s.blocks[0]; + const last = s.blocks[2]; + if (first?.type === 'paragraph') expect(first.text).toBe('Above'); + if (last?.type === 'paragraph') expect(last.text).toBe('Below'); + }); + }); + }); + + // --------------------------------------------------------------------------- + // Rule: Tables are parsed into TableBlock + // --------------------------------------------------------------------------- + + Rule('Tables are parsed into TableBlock', ({ RuleScenario }) => { + RuleScenario('Simple table with header and rows', ({ Given, When, Then }) => { + Given('markdown with a two-column table', () => { + requireState().markdownContent = [ + '| Name | Status |', + '|------|--------|', + '| Alpha | active |', + '| Beta | pending |', + ].join('\n'); + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('block 1 is a table with the expected columns and rows', () => { + const block = getBlock(0); + expect(block.type).toBe('table'); + if (block.type === 'table') { + expect(block.columns).toEqual(['Name', 'Status']); + expect(block.rows).toHaveLength(2); + expect(block.rows[0]).toEqual(['Alpha', 'active']); + expect(block.rows[1]).toEqual(['Beta', 'pending']); + } + }); + }); + }); + + // --------------------------------------------------------------------------- + // Rule: Unordered lists are parsed into ListBlock + // --------------------------------------------------------------------------- + + Rule('Unordered lists are parsed into ListBlock', ({ RuleScenario }) => { + RuleScenario('Dash list items', ({ Given, When, Then }) => { + Given('markdown with three dash list items', () => { + requireState().markdownContent = '- First item\n- Second item\n- Third item'; + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('block 1 is an unordered list with 3 items', () => { + const block = getBlock(0); + expect(block.type).toBe('list'); + if (block.type === 'list') { + expect(block.ordered).toBe(false); + expect(block.items).toHaveLength(3); + expect(block.items[0]).toBe('First item'); + expect(block.items[1]).toBe('Second item'); + expect(block.items[2]).toBe('Third item'); + } + }); + }); + + RuleScenario('GFM checkbox list items', ({ Given, When, Then }) => { + Given('markdown with GFM checkbox items', () => { + requireState().markdownContent = '- [ ] Unchecked task\n- [x] Checked task'; + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('block 1 is an unordered list with checkbox text preserved', () => { + const block = getBlock(0); + expect(block.type).toBe('list'); + if (block.type === 'list') { + expect(block.ordered).toBe(false); + expect(block.items).toHaveLength(2); + expect(block.items[0]).toBe('[ ] Unchecked task'); + expect(block.items[1]).toBe('[x] Checked task'); + } + }); + }); + }); + + // --------------------------------------------------------------------------- + // Rule: Ordered lists are parsed into ListBlock + // --------------------------------------------------------------------------- + + Rule('Ordered lists are parsed into ListBlock', ({ RuleScenario }) => { + RuleScenario('Numbered list items', ({ Given, When, Then }) => { + Given('markdown with three numbered list items', () => { + requireState().markdownContent = '1. First step\n2. Second step\n3. Third step'; + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('block 1 is an ordered list with 3 items', () => { + const block = getBlock(0); + expect(block.type).toBe('list'); + if (block.type === 'list') { + expect(block.ordered).toBe(true); + expect(block.items).toHaveLength(3); + expect(block.items[0]).toBe('First step'); + expect(block.items[1]).toBe('Second step'); + expect(block.items[2]).toBe('Third step'); + } + }); + }); + }); + + // --------------------------------------------------------------------------- + // Rule: Code blocks are parsed into CodeBlock + // --------------------------------------------------------------------------- + + Rule('Code blocks are parsed into CodeBlock', ({ RuleScenario }) => { + RuleScenario('Code block with language', ({ Given, When, Then }) => { + Given('markdown with a typescript code block', () => { + requireState().markdownContent = '```typescript\nconst x = 1;\nconst y = 2;\n```'; + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then( + 'block 1 is a code block with language {string} and content', + (_ctx: unknown, language: string) => { + const block = getBlock(0); + expect(block.type).toBe('code'); + if (block.type === 'code') { + expect(block.language).toBe(language); + expect(block.content).toContain('const x = 1;'); + expect(block.content).toContain('const y = 2;'); + } + } + ); + }); + + RuleScenario('Empty code block', ({ Given, When, Then }) => { + Given('markdown with an empty code block', () => { + requireState().markdownContent = '```bash\n```'; + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('block 1 is a code block with empty content', () => { + const block = getBlock(0); + expect(block.type).toBe('code'); + if (block.type === 'code') { + expect(block.language).toBe('bash'); + expect(block.content).toBe(''); + } + }); + }); + }); + + // --------------------------------------------------------------------------- + // Rule: Mermaid blocks are parsed into MermaidBlock + // --------------------------------------------------------------------------- + + Rule('Mermaid blocks are parsed into MermaidBlock', ({ RuleScenario }) => { + RuleScenario('Mermaid diagram block', ({ Given, When, Then }) => { + Given('markdown with a mermaid diagram', () => { + requireState().markdownContent = '```mermaid\ngraph LR\n A --> B\n B --> C\n```'; + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('block 1 is a mermaid block with graph content', () => { + const block = getBlock(0); + expect(block.type).toBe('mermaid'); + if (block.type === 'mermaid') { + expect(block.content).toContain('graph LR'); + expect(block.content).toContain('A --> B'); + } + }); + }); + }); + + // --------------------------------------------------------------------------- + // Rule: Mixed content produces correct block sequence + // --------------------------------------------------------------------------- + + Rule('Mixed content produces correct block sequence', ({ RuleScenario }) => { + RuleScenario('Mixed content in sequence', ({ Given, When, Then }) => { + Given('markdown with heading, paragraph, table, code, and list', () => { + requireState().markdownContent = [ + '## Overview', + '', + 'This is a paragraph.', + '', + '| Col A | Col B |', + '|-------|-------|', + '| val1 | val2 |', + '', + '```typescript', + 'const x = 1;', + '```', + '', + '- item one', + '- item two', + ].join('\n'); + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('5 blocks are produced in the correct order', () => { + const s = requireState(); + expect(s.blocks).toHaveLength(5); + + const b0 = s.blocks[0]; + expect(b0?.type).toBe('heading'); + if (b0?.type === 'heading') { + expect(b0.level).toBe(2); + expect(b0.text).toBe('Overview'); + } + + const b1 = s.blocks[1]; + expect(b1?.type).toBe('paragraph'); + if (b1?.type === 'paragraph') { + expect(b1.text).toBe('This is a paragraph.'); + } + + const b2 = s.blocks[2]; + expect(b2?.type).toBe('table'); + if (b2?.type === 'table') { + expect(b2.columns).toEqual(['Col A', 'Col B']); + } + + const b3 = s.blocks[3]; + expect(b3?.type).toBe('code'); + if (b3?.type === 'code') { + expect(b3.language).toBe('typescript'); + } + + const b4 = s.blocks[4]; + expect(b4?.type).toBe('list'); + if (b4?.type === 'list') { + expect(b4.ordered).toBe(false); + expect(b4.items).toHaveLength(2); + } + }); + }); + }); + + // --------------------------------------------------------------------------- + // Rule: Bold and inline formatting is preserved in paragraphs + // --------------------------------------------------------------------------- + + Rule('Bold and inline formatting is preserved in paragraphs', ({ RuleScenario }) => { + RuleScenario('Bold text preserved in paragraph', ({ Given, When, Then }) => { + Given('markdown with bold and code span formatting', () => { + requireState().markdownContent = 'This has **bold** and `code` in it.'; + }); + + When('parsing the markdown to blocks', () => { + const s = requireState(); + s.blocks = parseMarkdownToBlocks(s.markdownContent); + }); + + Then('block 1 is a paragraph preserving inline formatting', () => { + const block = getBlock(0); + expect(block.type).toBe('paragraph'); + if (block.type === 'paragraph') { + expect(block.text).toBe('This has **bold** and `code` in it.'); + } + }); + }); + }); +});