Skip to content

feat(cli): add dry-run mode to extract command - #123

Merged
NTCoding merged 6 commits into
mainfrom
issue-45-m4-d4-2-add-dry-run-mode-to-ex
Jan 11, 2026
Merged

NTCoding merged 6 commits into
mainfrom
issue-45-m4-d4-2-add-dry-run-mode-to-ex

Conversation

@NTCoding

@NTCoding NTCoding commented Jan 11, 2026 •

Copy link
Copy Markdown
Owner

User description

Closes #45

Summary

  • Added --dry-run flag to riviere extract command
  • Implemented formatDryRunOutput function that aggregates extracted components by domain and type
  • Output format: domain: Type(count), Type(count) (e.g., orders: api(1), useCase(2))
  • Added 4 comprehensive tests covering single domain with single type, single domain with multiple types, multiple domains with separate breakdowns, and verification that dry-run counts match full extraction

Test plan

  • Unit tests pass with 100% coverage
  • Verify gate passes (lint, typecheck, test)
  • Generated CLI documentation updated
  • Dry-run output format matches specification

🤖 Generated with Claude Code


PR Type

Enhancement, Tests


Description

  • Added --dry-run flag to riviere extract command for preview mode

  • Implemented formatDryRunOutput function aggregating components by domain and type

  • Output format displays domain with component counts: domain: Type(count), Type(count)

  • Added 4 comprehensive tests covering single/multiple domains and type combinations

  • Updated CLI documentation with new --dry-run option


Diagram Walkthrough

flowchart LR
  A["Extract Command"] -->|"--dry-run flag"| B["formatDryRunOutput Function"]
  B -->|"Aggregates by domain & type"| C["Component Counts Output"]
  C -->|"Format: domain: Type(count)"| D["Console Display"]
  A -->|"Normal mode"| E["Full JSON Output"]
Loading

File Walkthrough

Relevant files
Enhancement
extract.ts
Implement dry-run mode with component count aggregation   

packages/riviere-cli/src/commands/extract/extract.ts

  • Added dryRun optional property to ExtractOptions interface
  • Implemented formatDryRunOutput function that aggregates extracted
    components by domain and type, returning formatted strings
  • Added --dry-run option to command definition
  • Added conditional logic to output dry-run format when flag is
    provided, bypassing normal JSON output
  • Imported DraftComponent type from extraction library
+39/-2   
Tests
extract.spec.ts
Add comprehensive dry-run mode test coverage                         

packages/riviere-cli/src/commands/extract/extract.spec.ts

  • Added assertDefined import to test fixtures
  • Added 4 new test cases in 'dry-run mode' describe block
  • Tests cover single domain with single type, multiple types, multiple
    domains, and count verification
  • Implemented helper function parseExtractionOutput for parsing full
    extraction output
  • Validates dry-run counts match full extraction component array length
+262/-1 
Documentation
cli-reference.md
Document dry-run flag in CLI reference                                     

packages/riviere-cli/docs/generated/cli-reference.md

  • Added new "Optional:" section under extract command options
  • Documented --dry-run flag with description "Show component counts per
    domain without full output"
  • Maintained consistent table formatting with existing required options
+5/-0     

Summary by CodeRabbit

  • New Features

    • Added a --dry-run option to the extract command that shows aggregated component counts by domain and type as a concise summary instead of full output.
  • Tests

    • Added comprehensive tests for the dry-run behavior, covering multiple domains/types, total counts, empty results, and output format validation.

✏️ Tip: You can customize this high-level summary in your review settings.

NTCoding and others added 2 commits January 11, 2026 09:51
Add --dry-run flag to riviere extract that shows component counts by domain and type
without writing files. Output format: "domain: Type(count), Type(count)".

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@coderabbitai

coderabbitai Bot commented Jan 11, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a --dry-run mode to the extract command that aggregates extracted DraftComponent items by domain and type and prints a concise domain/type count summary instead of the full JSON extraction output. Includes implementation and tests covering multiple domains and types.

Changes

Cohort / File(s) Summary
Dry-run Feature Implementation
packages/riviere-cli/src/commands/extract/extract.ts
Adds --dry-run CLI option, extends ExtractOptions with dryRun?: boolean, imports DraftComponent, and adds formatDryRunOutput() to aggregate components by domain/type. Command short-circuits to formatted summary when dry-run is used.
Dry-run Test Suite
packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
New tests validating dry-run behavior: counts per domain/type, multi-type handling, multi-domain aggregation, parity with full extraction counts, and empty-extraction behavior; includes parsing/type-guards for CLI output.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hopped through code with eager paws,
Counting domains and types because—
A tiny flag, a gentle run,
Shows the tally, quick and fun.
Configs checked, the rabbit cheers: dry-run wins the cause!

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(cli): add dry-run mode to extract command' clearly and specifically summarizes the main change: adding a dry-run mode feature to the extract CLI command.
Linked Issues check ✅ Passed The PR fully implements all coding requirements from issue #45: adds --dry-run flag, implements formatDryRunOutput aggregating by domain/type, produces specified output format, includes comprehensive test coverage validating output format and count parity.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #45 requirements: extract.ts modifications for the --dry-run flag, formatDryRunOutput implementation, and test file for dry-run functionality validation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

@qodo-code-review

qodo-code-review Bot commented Jan 11, 2026 •

Copy link
Copy Markdown
Contributor

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🟡
🎫 #45
🟢 Add a --dry-run flag to riviere extract to validate configs quickly without full
extraction output.
In dry-run mode, display component counts summarized per domain and per component type
(not the full component list).
When config has multiple domains, dry-run output must show a breakdown for each domain.
Dry-run counts must match the counts from full extraction output.
Provide tests for the dry-run output format and for counts matching full extraction.
⚪ Verification should pass via `nx test riviere-cli`.
Codebase Duplication Compliance
⚪
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jan 11, 2026 •

Copy link
Copy Markdown

Deploying living-architecture with  Cloudflare Pages  Cloudflare Pages

Latest commit: 2f3b05f
Status: ✅  Deploy successful!
Preview URL: https://97dfd413.living-architecture.pages.dev
Branch Preview URL: https://issue-45-m4-d4-2-add-dry-run.living-architecture.pages.dev

View logs

@qodo-code-review

qodo-code-review Bot commented Jan 11, 2026 •

Copy link
Copy Markdown
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Optimize dry-run to avoid full extraction

The current dry-run implementation is inefficient as it performs a full
component extraction. It should be optimized to perform a faster, count-only
analysis to meet the feature's performance goals.

Examples:

packages/riviere-cli/src/commands/extract/extract.ts [141-149]
      const components = extractComponents(project, sourceFilePaths, config)

      if (options.dryRun) {
        const lines = formatDryRunOutput(components)
        for (const line of lines) {
          console.log(line)
        }
        return
      }

Solution Walkthrough:

Before:

// file: packages/riviere-cli/src/commands/extract/extract.ts

export function createExtractCommand(): Command {
  return new Command('extract')
    // ...
    .action((options: ExtractOptions) => {
      // ...
      const components = extractComponents(project, sourceFilePaths, config);

      if (options.dryRun) {
        const lines = formatDryRunOutput(components);
        for (const line of lines) {
          console.log(line);
        }
        return;
      }

      console.log(JSON.stringify(formatSuccess(components)));
    });
}

After:

// file: packages/riviere-cli/src/commands/extract/extract.ts

export function createExtractCommand(): Command {
  return new Command('extract')
    // ...
    .action((options: ExtractOptions) => {
      // ...
      // The `extractComponents` function is modified to accept a dry-run option
      // and perform a more efficient, count-only analysis.
      if (options.dryRun) {
        const componentCounts = extractComponents(project, sourceFilePaths, config, { dryRun: true });
        const lines = formatDryRunOutput(componentCounts); // The formatter might need adjustment
        for (const line of lines) {
          console.log(line);
        }
        return;
      }

      const components = extractComponents(project, sourceFilePaths, config, { dryRun: false });
      console.log(JSON.stringify(formatSuccess(components)));
    });
}
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a significant design flaw where the implementation contradicts the feature's stated performance goal of being fast, as it performs a full, potentially slow, extraction.

Medium
General
✅ Sort domains for deterministic output
Suggestion Impact:The commit introduces a sorted list of domain entries (sortedDomains) and iterates over that instead of iterating directly over the map, ensuring deterministic alphabetical domain ordering in the output.

code diff:

+  const sortedDomains = [...countsByDomain.entries()].sort(([a], [b]) => a.localeCompare(b))
   const lines: string[] = []
-  for (const [domain, typeCounts] of countsByDomain) {
+  for (const [domain, typeCounts] of sortedDomains) {

Sort the domains alphabetically before formatting the dry-run output to ensure
it is always reproducible and easy to scan, rather than relying on map insertion
order.

packages/riviere-cli/src/commands/extract/extract.ts [53-58]

-for (const [domain, typeCounts] of countsByDomain) {
+for (const domain of [...countsByDomain.keys()].sort((a, b) => a.localeCompare(b))) {
+  const typeCounts = countsByDomain.get(domain)!
   const typeStrings = [...typeCounts.entries()]
     .sort(([a], [b]) => a.localeCompare(b))
     .map(([type, count]) => `${type}(${count})`)
   lines.push(`${domain}: ${typeStrings.join(', ')}`)
 }

[Suggestion processed]

Suggestion importance[1-10]: 6

__

Why: This suggestion correctly identifies that the output order is non-deterministic and proposes sorting the domains to ensure consistent, reproducible output, which is important for a CLI tool.

Low
Add explicit default for flag

Set an explicit default value of false for the --dry-run flag. This ensures the
options.dryRun property is always a boolean, avoiding potential undefined
values.

packages/riviere-cli/src/commands/extract/extract.ts [82]

-.option('--dry-run', 'Show component counts per domain without full output')
+.option('--dry-run', 'Show component counts per domain without full output', false)
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion improves code clarity and type safety by setting an explicit default value for the --dry-run option, ensuring options.dryRun is always a boolean.

Low
Simplify nested map population logic

Simplify the logic for populating the nested countsByDomain map by using a more
direct approach to initialize the nested map for each domain. This improves
conciseness and readability.

packages/riviere-cli/src/commands/extract/extract.ts [39-60]

 function formatDryRunOutput(components: DraftComponent[]): string[] {
   const countsByDomain = new Map<string, Map<string, number>>()
 
   for (const component of components) {
-    const existingTypeCounts = countsByDomain.get(component.domain)
-    const typeCounts = existingTypeCounts ?? new Map<string, number>()
-    if (existingTypeCounts === undefined) {
+    let typeCounts = countsByDomain.get(component.domain)
+    if (!typeCounts) {
+      typeCounts = new Map<string, number>()
       countsByDomain.set(component.domain, typeCounts)
     }
     const currentCount = typeCounts.get(component.type) ?? 0
     typeCounts.set(component.type, currentCount + 1)
   }
 
   const lines: string[] = []
   for (const [domain, typeCounts] of countsByDomain) {
     const typeStrings = [...typeCounts.entries()]
       .sort(([a], [b]) => a.localeCompare(b))
       .map(([type, count]) => `${type}(${count})`)
     lines.push(`${domain}: ${typeStrings.join(', ')}`)
   }
   return lines
 }
  • Apply / Chat
Suggestion importance[1-10]: 3

__

Why: The suggestion offers a minor simplification to the map population logic, which can slightly improve code readability, but it does not change the functionality.

Low
  • Update

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @packages/riviere-cli/src/commands/extract/extract.spec.ts:
- Around line 370-444: The test "produces counts matching full extraction
component array length" uses an uncommon array clear pattern by assigning
ctx.consoleOutput.length = 0; change this to a more idiomatic clear (e.g.,
ctx.consoleOutput = [] or ctx.consoleOutput.splice(0)) in that spec to improve
clarity; additionally add a new unit test (e.g., "handles empty extraction
results") that sets up a config/path which yields zero components, runs
createProgram().parseAsync([... '--dry-run']), and asserts that
ctx.consoleOutput is empty or contains the expected "no results" message to
cover the edge case.

In @packages/riviere-cli/src/commands/extract/extract.ts:
- Around line 39-60: formatDryRunOutput builds countsByDomain as a Map but
iterates it in insertion order, causing non-deterministic domain output; to fix,
when producing lines iterate over the domains in sorted order (e.g., use
[...countsByDomain.entries()].sort(([domainA], [domainB]) =>
domainA.localeCompare(domainB)) or Array.from(countsByDomain.keys()).sort()) so
that the for-loop that currently reads "for (const [domain, typeCounts] of
countsByDomain)" instead processes domains alphabetically before formatting
typeStrings.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a377d40 and 7f0a4d4.

⛔ Files ignored due to path filters (1)
  • packages/riviere-cli/docs/generated/cli-reference.md is excluded by !**/generated/**
📒 Files selected for processing (2)
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Follow eslint configuration rules defined in eslint.config.mjs for all linting

Files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
**/*.{ts,tsx,js,jsx,css,scss,html}

📄 CodeRabbit inference engine (CLAUDE.md)

All UI and UX design must conform to global brand guidelines in /docs/brand/ (logo, colors, typography, icons)

Files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Do not log sensitive data (passwords, tokens, PII) in any code
Validate and sanitize all external input

Files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use cross-project imports with package names (e.g., import { X } from '@living-architecture/[pkg-name]') rather than relative paths

Files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
🧠 Learnings (22)
📓 Common learnings
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement integration tests for end-to-end extraction from TypeScript code to JSON output
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 88
File: packages/riviere-cli/src/commands/extract/extract.ts:109-114
Timestamp: 2026-01-09T20:08:44.180Z
Learning: Applies to packages/riviere-cli/src/commands/extract/**/*.{ts,tsx} : CLI extraction commands should only catch and format expected validation errors as structured JSON. System-level exceptions (disk I/O failures, OOM, AST parse errors) should fail loudly with stack traces for debugging rather than being wrapped in try-catch and converted to JSON errors. This follows the fail-fast principle: validate inputs explicitly, then let unexpected failures surface clearly.
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.ts : Use `living-architecture/riviere-extract-ts` TypeScript extractor with ts-morph for AST parsing when implementing TypeScript extraction for architecture schema components
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Implement extraction logic as pure functions with no side effects
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.{json,ts} : Define extraction configuration using the JSON Schema from `living-architecture/riviere-extract-config` DSL
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement unit tests for each predicate type in isolation with positive and negative cases
📚 Learning: 2026-01-08T22:20:13.250Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.ts : Use `living-architecture/riviere-extract-ts` TypeScript extractor with ts-morph for AST parsing when implementing TypeScript extraction for architecture schema components

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-09T20:08:44.180Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 88
File: packages/riviere-cli/src/commands/extract/extract.ts:109-114
Timestamp: 2026-01-09T20:08:44.180Z
Learning: In packages/riviere-cli/src/commands/extract/**/*.{ts,tsx}, CLI extraction commands should only catch and format expected validation errors as structured JSON. Do not wrap or convert system-level exceptions (e.g., disk I/O failures, OOM, AST parse errors) into JSON errors; instead, fail loudly with stack traces to aid debugging. Follow fail-fast principles: validate inputs explicitly, and surface unexpected failures clearly.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T22:20:13.250Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.{json,ts} : Define extraction configuration using the JSON Schema from `living-architecture/riviere-extract-config` DSL

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Implement extraction logic as pure functions with no side effects

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T07:05:01.766Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-conventions/CLAUDE.md:0-0
Timestamp: 2026-01-08T07:05:01.766Z
Learning: Import and use the default extraction config from `living-architecture/riviere-extract-conventions/default-config` in extraction tooling to detect all 6 component types

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement integration tests for end-to-end extraction from TypeScript code to JSON output

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T22:20:13.250Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.ts : Use the Rivière Builder Node.js library to programmatically construct the schema graph when implementing custom extraction code

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Use glob pattern matching for module-based organization of extraction rules

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Reject invalid extraction configs at load time, not during extraction phase

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-06T23:01:34.751Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-config/CLAUDE.md:0-0
Timestamp: 2026-01-06T23:01:34.751Z
Learning: Applies to packages/riviere-extract-config/**/*.ts : Extraction config schema is the source of truth for valid structures. TypeScript types must mirror the schema definition to maintain consistency

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: All extraction rules should come from validated ExtractionConfig provided by riviere-extract-config

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement unit tests for each predicate type in isolation with positive and negative cases

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Use ts-morph's in-memory file system (`useInMemoryFileSystem: true`) for fast isolated tests

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T06:46:00.609Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 66
File: packages/riviere-extract-conventions/src/eslint/require-component-decorator.spec.ts:19-21
Timestamp: 2026-01-08T06:46:00.609Z
Learning: In test files using typescript-eslint/rule-tester's RuleTester.run(), ensure there is an explicit it() block with at least one expect() assertion (e.g., expect(rule).toBeDefined()) to satisfy sonarjs/no-empty-test-file and sonarjs/assertions-in-tests lint rules, which don’t recognize RuleTester's internal test blocks. Apply this pattern to all spec.ts test files to maintain consistency and pass lint checks.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : Test edge cases for collections: empty collections, single elements, duplicates, nested structures, circular references, large collections, and mixed types

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : Test domain-specific edge cases: valid email formats, URL protocols/ports, international phone numbers, Unicode addresses, currency rounding, percentages over 100%

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : One concept per test. Each test verifies one behavior. If you need 'and' in your test name, split it into separate tests

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : Test violated domain constraints: uniqueness violations, missing relationships, ordering violations, range breaches, state inconsistencies, format mismatches, and temporal ordering

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : Test edge cases for dates/times: leap years, daylight saving transitions, timezone boundaries, midnight, end of day, year boundaries, invalid dates, and epoch edge cases

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T08:54:09.466Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 96
File: apps/docs/.vitepress/theme/eclairLinkHandler.spec.ts:229-249
Timestamp: 2026-01-10T08:54:09.466Z
Learning: In jsdom test environments, window.location.assign cannot be spied on due to TypeError: Cannot redefine property. Use Object.defineProperty to mock the entire window.location object, replacing it with a controlled mock, and restore the original in afterEach. Ensure to clean up the mock after each test to avoid side effects.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-09T20:08:30.350Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 88
File: packages/riviere-cli/src/commands/extract/extract.spec.ts:33-38
Timestamp: 2026-01-09T20:08:30.350Z
Learning: In test files, keep type guard implementations like isExtractionOutput(value: unknown): value is ExtractionOutput focused on narrowing types for TypeScript. Do not perform comprehensive runtime shape validation in type guards; rely on explicit test assertions (e.g., expect(result).toMatchObject(...)) for shape checks. This keeps type guards simple and rely on assertion-based tests for thorough validation.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
🧬 Code graph analysis (1)
packages/riviere-cli/src/commands/extract/extract.spec.ts (2)
packages/riviere-cli/src/command-test-fixtures.ts (3)
  • TestContext (62-66)
  • createTestContext (68-74)
  • setupCommandTest (76-93)
packages/riviere-cli/src/cli.ts (1)
  • createProgram (44-78)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: main
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (8)
packages/riviere-cli/src/commands/extract/extract.spec.ts (4)

11-14: LGTM! Import addition supports test assertions.

The assertDefined helper is appropriately used in the count parity test to guard against undefined values during regex matching and dry-run output validation.


193-237: LGTM! Test validates single domain/single type dry-run output.

The test correctly verifies the basic dry-run functionality: extracting a single useCase component and asserting the output format matches "orders: useCase(1)".


239-297: LGTM! Test validates multiple component types in dry-run output.

The test correctly verifies alphabetical sorting of component types in the output format: "orders: api(1), useCase(2)".


299-368: LGTM! Test validates multi-domain dry-run output.

The test correctly verifies separate breakdown per domain. Using toContain for each domain appropriately allows flexible ordering.

packages/riviere-cli/src/commands/extract/extract.ts (4)

16-18: LGTM! Import additions support dry-run functionality.

Adding extractComponents and the DraftComponent type is necessary for the dry-run formatting logic. Follows the coding guideline to use cross-project imports with package names.


24-27: LGTM! Interface extension matches CLI option.

The dryRun optional property appropriately captures the new --dry-run flag state.


82-82: LGTM! CLI option clearly describes dry-run behavior.

The option description accurately conveys the dry-run mode's purpose: showing counts without full output.


143-149: LGTM! Early return prevents full JSON output in dry-run mode.

The conditional logic correctly short-circuits to output only the dry-run summary when the flag is provided, aligning with the PR's acceptance criteria.

Comment thread packages/riviere-cli/src/commands/extract/extract.spec.ts Outdated
Comment thread packages/riviere-cli/src/commands/extract/extract.ts
- Sort domains alphabetically in formatDryRunOutput for deterministic output
- Use splice(0) instead of length = 0 for array clearing

Addresses CodeRabbit feedback on PR #123

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Comment thread packages/riviere-cli/src/commands/extract/extract.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @packages/riviere-cli/src/commands/extract/extract.spec.ts:
- Around line 189-445: Add a new test in the "dry-run mode" suite that creates
an empty src (or a module config that matches no files) and asserts the expected
dry-run behavior (decide and assert whether ctx.consoleOutput contains nothing
or a line like "domain: ... (0)" per project convention), referencing the same
test helpers (createProgram(), ctx.consoleOutput, setupCommandTest(ctx)) so it
runs with the other cases; and in the parity test that computes dryRunCount (the
test that uses parseExtractionOutput(), assertDefined(), and regex
match(/\((\d+)\)/g)), tighten the parsing by validating each parsed numeric
string converts to a finite number (e.g., check Number.isFinite(num) after
Number(num)) before summing and throw/assert if any parse yields NaN/Infinity to
avoid silently summing invalid values.

In @packages/riviere-cli/src/commands/extract/extract.ts:
- Around line 39-61: formatDryRunOutput uses localeCompare() which can vary by
environment; replace both uses (the domain sort at sortedDomains and the type
sort when building typeStrings) with a deterministic code-point comparator such
as (a, b) => (a < b ? -1 : a > b ? 1 : 0) so sorting is stable and
environment-independent — update the two .sort calls that currently use ([a],
[b]) => a.localeCompare(b) to use the code-point comparator instead.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f0a4d4 and a479d66.

📒 Files selected for processing (2)
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Follow eslint configuration rules defined in eslint.config.mjs for all linting

Files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
**/*.{ts,tsx,js,jsx,css,scss,html}

📄 CodeRabbit inference engine (CLAUDE.md)

All UI and UX design must conform to global brand guidelines in /docs/brand/ (logo, colors, typography, icons)

Files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Do not log sensitive data (passwords, tokens, PII) in any code
Validate and sanitize all external input

Files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use cross-project imports with package names (e.g., import { X } from '@living-architecture/[pkg-name]') rather than relative paths

Files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
🧠 Learnings (28)
📓 Common learnings
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement integration tests for end-to-end extraction from TypeScript code to JSON output
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 88
File: packages/riviere-cli/src/commands/extract/extract.ts:109-114
Timestamp: 2026-01-09T20:08:44.180Z
Learning: Applies to packages/riviere-cli/src/commands/extract/**/*.{ts,tsx} : CLI extraction commands should only catch and format expected validation errors as structured JSON. System-level exceptions (disk I/O failures, OOM, AST parse errors) should fail loudly with stack traces for debugging rather than being wrapped in try-catch and converted to JSON errors. This follows the fail-fast principle: validate inputs explicitly, then let unexpected failures surface clearly.
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.ts : Use `living-architecture/riviere-extract-ts` TypeScript extractor with ts-morph for AST parsing when implementing TypeScript extraction for architecture schema components
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Implement extraction logic as pure functions with no side effects
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.{json,ts} : Define extraction configuration using the JSON Schema from `living-architecture/riviere-extract-config` DSL
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement unit tests for each predicate type in isolation with positive and negative cases
📚 Learning: 2026-01-08T22:20:13.250Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.ts : Use `living-architecture/riviere-extract-ts` TypeScript extractor with ts-morph for AST parsing when implementing TypeScript extraction for architecture schema components

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-09T20:08:44.180Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 88
File: packages/riviere-cli/src/commands/extract/extract.ts:109-114
Timestamp: 2026-01-09T20:08:44.180Z
Learning: In packages/riviere-cli/src/commands/extract/**/*.{ts,tsx}, CLI extraction commands should only catch and format expected validation errors as structured JSON. Do not wrap or convert system-level exceptions (e.g., disk I/O failures, OOM, AST parse errors) into JSON errors; instead, fail loudly with stack traces to aid debugging. Follow fail-fast principles: validate inputs explicitly, and surface unexpected failures clearly.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T22:20:13.250Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.{json,ts} : Define extraction configuration using the JSON Schema from `living-architecture/riviere-extract-config` DSL

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement integration tests for end-to-end extraction from TypeScript code to JSON output

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Implement extraction logic as pure functions with no side effects

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T07:05:01.766Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-conventions/CLAUDE.md:0-0
Timestamp: 2026-01-08T07:05:01.766Z
Learning: Import and use the default extraction config from `living-architecture/riviere-extract-conventions/default-config` in extraction tooling to detect all 6 component types

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Use glob pattern matching for module-based organization of extraction rules

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T22:20:13.250Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.ts : Use the Rivière Builder Node.js library to programmatically construct the schema graph when implementing custom extraction code

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Reject invalid extraction configs at load time, not during extraction phase

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-06T23:01:34.751Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-config/CLAUDE.md:0-0
Timestamp: 2026-01-06T23:01:34.751Z
Learning: Applies to packages/riviere-extract-config/**/*.ts : Extraction config schema is the source of truth for valid structures. TypeScript types must mirror the schema definition to maintain consistency

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-07T08:54:48.071Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/workflow/code-review.md:0-0
Timestamp: 2026-01-07T08:54:48.071Z
Learning: Applies to docs/workflow/**/*.{ts,tsx,js,jsx} : Review usage of `/* v8 ignore next -- preserve */` coverage skip directives. This is only acceptable for unreachable code needed to satisfy the compiler. Most cases should be solved by extracting code or writing tests to mock behavior.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : Test domain-specific edge cases: valid email formats, URL protocols/ports, international phone numbers, Unicode addresses, currency rounding, percentages over 100%

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-07T08:54:48.071Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/workflow/code-review.md:0-0
Timestamp: 2026-01-07T08:54:48.071Z
Learning: Applies to docs/workflow/**/*.{ts,tsx,js,jsx,!(**/*.test.ts,**/*.test.tsx,**/*.test.js,**/*.spec.ts,**/*.spec.tsx,**/*.spec.js)} : All production code (not test files) must align with architecture boundaries and layering requirements as defined in @/docs/architecture/overview.md and @/docs/conventions/codebase-structure.md

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: All extraction rules should come from validated ExtractionConfig provided by riviere-extract-config

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement unit tests for each predicate type in isolation with positive and negative cases

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Use ts-morph's in-memory file system (`useInMemoryFileSystem: true`) for fast isolated tests

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : Test edge cases for collections: empty collections, single elements, duplicates, nested structures, circular references, large collections, and mixed types

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : Test edge cases for strings: empty string, whitespace only, very long strings, Unicode/emojis, special characters, SQL/HTML injection patterns, and case sensitivity

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-09T20:08:30.350Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 88
File: packages/riviere-cli/src/commands/extract/extract.spec.ts:33-38
Timestamp: 2026-01-09T20:08:30.350Z
Learning: In test files, keep type guard implementations like isExtractionOutput(value: unknown): value is ExtractionOutput focused on narrowing types for TypeScript. Do not perform comprehensive runtime shape validation in type guards; rely on explicit test assertions (e.g., expect(result).toMatchObject(...)) for shape checks. This keeps type guards simple and rely on assertion-based tests for thorough validation.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : Test edge cases for null and undefined: null input, undefined input, missing optional properties, and explicit undefined vs missing key

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-07T23:24:27.966Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-07T23:24:27.966Z
Learning: Never sacrifice readability to satisfy linting rules or file length limits. When hitting max-lines limits, refactor by extracting duplicated code into shared modules, extracting test fixtures into shared fixtures, using `it.each` or `describe.each` for parameterized tests, or splitting into multiple focused files

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/vitest.config.mts : Enforce 100% code coverage using Vitest with v8 coverage and thresholds configured in vitest.config.mts

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T12:57:19.167Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 67
File: packages/riviere-extract-ts/tsconfig.spec.json:5-22
Timestamp: 2026-01-08T12:57:19.167Z
Learning: In tsconfig.spec.json files, use expanded types array ["vitest/globals", "vitest/importMeta", "vite/client", "node", "vitest"] for complete test type coverage. Include patterns should cover .test and .spec files, config files (vitest.config.ts/mts, vite.config.ts/mts), multiple extensions (.ts, .tsx, .js, .jsx), and .d.ts files to ensure proper TypeScript coverage across the testing environment.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-08T06:46:00.609Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 66
File: packages/riviere-extract-conventions/src/eslint/require-component-decorator.spec.ts:19-21
Timestamp: 2026-01-08T06:46:00.609Z
Learning: In test files using typescript-eslint/rule-tester's RuleTester.run(), ensure there is an explicit it() block with at least one expect() assertion (e.g., expect(rule).toBeDefined()) to satisfy sonarjs/no-empty-test-file and sonarjs/assertions-in-tests lint rules, which don’t recognize RuleTester's internal test blocks. Apply this pattern to all spec.ts test files to maintain consistency and pass lint checks.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : One concept per test. Each test verifies one behavior. If you need 'and' in your test name, split it into separate tests

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : Test violated domain constraints: uniqueness violations, missing relationships, ordering violations, range breaches, state inconsistencies, format mismatches, and temporal ordering

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
📚 Learning: 2026-01-10T08:54:09.466Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 96
File: apps/docs/.vitepress/theme/eclairLinkHandler.spec.ts:229-249
Timestamp: 2026-01-10T08:54:09.466Z
Learning: In jsdom test environments, window.location.assign cannot be spied on due to TypeError: Cannot redefine property. Use Object.defineProperty to mock the entire window.location object, replacing it with a controlled mock, and restore the original in afterEach. Ensure to clean up the mock after each test to avoid side effects.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.spec.ts
🧬 Code graph analysis (1)
packages/riviere-cli/src/commands/extract/extract.spec.ts (1)
packages/riviere-cli/src/command-test-fixtures.ts (3)
  • TestContext (62-66)
  • createTestContext (68-74)
  • setupCommandTest (76-93)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (5)
packages/riviere-cli/src/commands/extract/extract.spec.ts (1)

11-15: Good addition: assertDefined reduces null/undefined noise in tests.

packages/riviere-cli/src/commands/extract/extract.ts (4)

24-27: ExtractOptions.dryRun?: boolean is the right shape for Commander.


83-83: CLI option wiring for --dry-run is clear and discoverable.


144-150: Dry-run short-circuit preserves fail-fast behavior for unexpected exceptions.
You’re not wrapping the extraction path in broad try/catch, so disk/AST/system failures still surface loudly with stack traces (aligned with CLI learnings). Based on learnings, packages/riviere-cli/src/commands/extract/extract.ts:109-114.


16-18: No action needed. DraftComponent is properly exported from @living-architecture/riviere-extract-ts (defined in extractor.ts line 17, re-exported in index.ts lines 2-3) and the CLI import is correct. Both the export and import were added together in this change set, ensuring consistency.

Comment thread packages/riviere-cli/src/commands/extract/extract.spec.ts Outdated
Move dry-run mode tests to dedicated test file to keep each file
under the 400-line limit. Add empty extraction edge case test.

Co-Authored-By: Claude Opus 4.5 <[email protected]>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts:
- Around line 322-354: Replace the locally redefined DraftComponent with the
exported type from the extract package: remove the local DraftComponent
interface and add an import for it from
'@living-architecture/riviere-extract-ts' (use "import { type DraftComponent }
from '@living-architecture/riviere-extract-ts'"); keep the test-local
ExtractionOutput, and ensure isExtractionOutput and parseExtractionOutput still
reference DraftComponent via the imported type so type guards and parsing
behavior remain unchanged.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a479d66 and 0fa5388.

📒 Files selected for processing (1)
  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Follow eslint configuration rules defined in eslint.config.mjs for all linting

Files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
**/*.{ts,tsx,js,jsx,css,scss,html}

📄 CodeRabbit inference engine (CLAUDE.md)

All UI and UX design must conform to global brand guidelines in /docs/brand/ (logo, colors, typography, icons)

Files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Do not log sensitive data (passwords, tokens, PII) in any code
Validate and sanitize all external input

Files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use cross-project imports with package names (e.g., import { X } from '@living-architecture/[pkg-name]') rather than relative paths

Files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement integration tests for end-to-end extraction from TypeScript code to JSON output
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 88
File: packages/riviere-cli/src/commands/extract/extract.ts:109-114
Timestamp: 2026-01-09T20:08:44.180Z
Learning: Applies to packages/riviere-cli/src/commands/extract/**/*.{ts,tsx} : CLI extraction commands should only catch and format expected validation errors as structured JSON. System-level exceptions (disk I/O failures, OOM, AST parse errors) should fail loudly with stack traces for debugging rather than being wrapped in try-catch and converted to JSON errors. This follows the fail-fast principle: validate inputs explicitly, then let unexpected failures surface clearly.
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.ts : Use `living-architecture/riviere-extract-ts` TypeScript extractor with ts-morph for AST parsing when implementing TypeScript extraction for architecture schema components
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Implement extraction logic as pure functions with no side effects
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.{json,ts} : Define extraction configuration using the JSON Schema from `living-architecture/riviere-extract-config` DSL
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement unit tests for each predicate type in isolation with positive and negative cases
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement integration tests for end-to-end extraction from TypeScript code to JSON output

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement unit tests for each predicate type in isolation with positive and negative cases

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Use ts-morph's in-memory file system (`useInMemoryFileSystem: true`) for fast isolated tests

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-09T20:08:44.180Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 88
File: packages/riviere-cli/src/commands/extract/extract.ts:109-114
Timestamp: 2026-01-09T20:08:44.180Z
Learning: In packages/riviere-cli/src/commands/extract/**/*.{ts,tsx}, CLI extraction commands should only catch and format expected validation errors as structured JSON. Do not wrap or convert system-level exceptions (e.g., disk I/O failures, OOM, AST parse errors) into JSON errors; instead, fail loudly with stack traces to aid debugging. Follow fail-fast principles: validate inputs explicitly, and surface unexpected failures clearly.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Implement extraction logic as pure functions with no side effects

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T22:20:13.250Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.ts : Use `living-architecture/riviere-extract-ts` TypeScript extractor with ts-morph for AST parsing when implementing TypeScript extraction for architecture schema components

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T22:20:13.250Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.{json,ts} : Define extraction configuration using the JSON Schema from `living-architecture/riviere-extract-config` DSL

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Use glob pattern matching for module-based organization of extraction rules

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-06T23:01:34.751Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-config/CLAUDE.md:0-0
Timestamp: 2026-01-06T23:01:34.751Z
Learning: Applies to packages/riviere-extract-config/**/*.ts : Extraction config schema is the source of truth for valid structures. TypeScript types must mirror the schema definition to maintain consistency

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Reject invalid extraction configs at load time, not during extraction phase

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-09T20:08:30.350Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 88
File: packages/riviere-cli/src/commands/extract/extract.spec.ts:33-38
Timestamp: 2026-01-09T20:08:30.350Z
Learning: In test files, keep type guard implementations like isExtractionOutput(value: unknown): value is ExtractionOutput focused on narrowing types for TypeScript. Do not perform comprehensive runtime shape validation in type guards; rely on explicit test assertions (e.g., expect(result).toMatchObject(...)) for shape checks. This keeps type guards simple and rely on assertion-based tests for thorough validation.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T06:46:00.609Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 66
File: packages/riviere-extract-conventions/src/eslint/require-component-decorator.spec.ts:19-21
Timestamp: 2026-01-08T06:46:00.609Z
Learning: In test files using typescript-eslint/rule-tester's RuleTester.run(), ensure there is an explicit it() block with at least one expect() assertion (e.g., expect(rule).toBeDefined()) to satisfy sonarjs/no-empty-test-file and sonarjs/assertions-in-tests lint rules, which don’t recognize RuleTester's internal test blocks. Apply this pattern to all spec.ts test files to maintain consistency and pass lint checks.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-10T08:54:09.466Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 96
File: apps/docs/.vitepress/theme/eclairLinkHandler.spec.ts:229-249
Timestamp: 2026-01-10T08:54:09.466Z
Learning: In jsdom test environments, window.location.assign cannot be spied on due to TypeError: Cannot redefine property. Use Object.defineProperty to mock the entire window.location object, replacing it with a controlled mock, and restore the original in afterEach. Ensure to clean up the mock after each test to avoid side effects.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: main
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (3)
packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts (3)

1-12: LGTM!

The imports are well-organized and follow Node.js conventions with the node: protocol.


195-269: Verify test isolation with console output mutation.

This test clears ctx.consoleOutput between extraction runs (line 247) to isolate the two command invocations. Ensure the test fixture properly resets state between tests to avoid cross-test contamination.

The count aggregation logic is sound and effectively validates that dry-run counts match full extraction.


18-193: LGTM!

The test cases comprehensively cover the dry-run functionality across various scenarios: single/multiple types, single/multiple domains, and empty extraction. The test structure is consistent and assertions are clear.

Also applies to: 271-319

Comment thread packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts Outdated
NTCoding and others added 2 commits January 11, 2026 10:23
- Replace localeCompare() with code-point comparator for deterministic sorting
- Import DraftComponent from riviere-extract-ts instead of redefining locally

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @packages/riviere-cli/src/commands/extract/extract.ts:
- Around line 47-69: The nested Map initialization in formatDryRunOutput can be
simplified: instead of separately getting existingTypeCounts, creating
typeCounts, and conditionally setting it, ensure countsByDomain has a Map for
component.domain by using a single lookup-or-create pattern (e.g., retrieve
countsByDomain.get(component.domain) and if falsy create and set a new Map) and
then operate on that Map; update the loop that builds countsByDomain in
formatDryRunOutput to use this simplified initialization so typeCounts is always
a Map when incrementing the count for component.type.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0fa5388 and 2f3b05f.

📒 Files selected for processing (2)
  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Follow eslint configuration rules defined in eslint.config.mjs for all linting

Files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
**/*.{ts,tsx,js,jsx,css,scss,html}

📄 CodeRabbit inference engine (CLAUDE.md)

All UI and UX design must conform to global brand guidelines in /docs/brand/ (logo, colors, typography, icons)

Files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Do not log sensitive data (passwords, tokens, PII) in any code
Validate and sanitize all external input

Files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use cross-project imports with package names (e.g., import { X } from '@living-architecture/[pkg-name]') rather than relative paths

Files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
🧠 Learnings (25)
📓 Common learnings
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 88
File: packages/riviere-cli/src/commands/extract/extract.ts:109-114
Timestamp: 2026-01-09T20:08:44.180Z
Learning: Applies to packages/riviere-cli/src/commands/extract/**/*.{ts,tsx} : CLI extraction commands should only catch and format expected validation errors as structured JSON. System-level exceptions (disk I/O failures, OOM, AST parse errors) should fail loudly with stack traces for debugging rather than being wrapped in try-catch and converted to JSON errors. This follows the fail-fast principle: validate inputs explicitly, then let unexpected failures surface clearly.
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement integration tests for end-to-end extraction from TypeScript code to JSON output
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.ts : Use `living-architecture/riviere-extract-ts` TypeScript extractor with ts-morph for AST parsing when implementing TypeScript extraction for architecture schema components
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Implement extraction logic as pure functions with no side effects
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement unit tests for each predicate type in isolation with positive and negative cases
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.{json,ts} : Define extraction configuration using the JSON Schema from `living-architecture/riviere-extract-config` DSL
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Use glob pattern matching for module-based organization of extraction rules
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Use ts-morph's in-memory file system (`useInMemoryFileSystem: true`) for fast isolated tests
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement integration tests for end-to-end extraction from TypeScript code to JSON output

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Implement unit tests for each predicate type in isolation with positive and negative cases

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.test.{ts,tsx} : Use ts-morph's in-memory file system (`useInMemoryFileSystem: true`) for fast isolated tests

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-09T20:08:44.180Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 88
File: packages/riviere-cli/src/commands/extract/extract.ts:109-114
Timestamp: 2026-01-09T20:08:44.180Z
Learning: In packages/riviere-cli/src/commands/extract/**/*.{ts,tsx}, CLI extraction commands should only catch and format expected validation errors as structured JSON. Do not wrap or convert system-level exceptions (e.g., disk I/O failures, OOM, AST parse errors) into JSON errors; instead, fail loudly with stack traces to aid debugging. Follow fail-fast principles: validate inputs explicitly, and surface unexpected failures clearly.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Implement extraction logic as pure functions with no side effects

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T22:20:13.250Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.ts : Use `living-architecture/riviere-extract-ts` TypeScript extractor with ts-morph for AST parsing when implementing TypeScript extraction for architecture schema components

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Reject invalid extraction configs at load time, not during extraction phase

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: Applies to packages/riviere-extract-ts/**/*.{ts,tsx} : Use glob pattern matching for module-based organization of extraction rules

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T22:20:13.250Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.{json,ts} : Define extraction configuration using the JSON Schema from `living-architecture/riviere-extract-config` DSL

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-06T23:01:34.751Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-config/CLAUDE.md:0-0
Timestamp: 2026-01-06T23:01:34.751Z
Learning: Applies to packages/riviere-extract-config/**/*.ts : Extraction config schema is the source of truth for valid structures. TypeScript types must mirror the schema definition to maintain consistency

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T07:05:01.766Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-conventions/CLAUDE.md:0-0
Timestamp: 2026-01-08T07:05:01.766Z
Learning: Applies to packages/riviere-extract-conventions/**/*.ts : Use `Custom(type)` decorator to annotate components with custom types not covered by standard decorators

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T19:36:17.306Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/codebase-structure.md:0-0
Timestamp: 2026-01-08T19:36:17.306Z
Learning: Applies to docs/conventions/**/*.{ts,tsx} : Use living-architecture/[pkg-name] for imports from other workspace projects, not relative paths like ../../packages/[pkg-name].

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T22:20:13.250Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*.{ts,tsx} : Apply decorators from `living-architecture/riviere-extract-conventions` to mark all classes as architectural components

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-09T20:08:30.350Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 88
File: packages/riviere-cli/src/commands/extract/extract.spec.ts:33-38
Timestamp: 2026-01-09T20:08:30.350Z
Learning: In test files, keep type guard implementations like isExtractionOutput(value: unknown): value is ExtractionOutput focused on narrowing types for TypeScript. Do not perform comprehensive runtime shape validation in type guards; rely on explicit test assertions (e.g., expect(result).toMatchObject(...)) for shape checks. This keeps type guards simple and rely on assertion-based tests for thorough validation.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T06:46:00.609Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 66
File: packages/riviere-extract-conventions/src/eslint/require-component-decorator.spec.ts:19-21
Timestamp: 2026-01-08T06:46:00.609Z
Learning: In test files using typescript-eslint/rule-tester's RuleTester.run(), ensure there is an explicit it() block with at least one expect() assertion (e.g., expect(rule).toBeDefined()) to satisfy sonarjs/no-empty-test-file and sonarjs/assertions-in-tests lint rules, which don’t recognize RuleTester's internal test blocks. Apply this pattern to all spec.ts test files to maintain consistency and pass lint checks.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-10T08:54:09.466Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 96
File: apps/docs/.vitepress/theme/eclairLinkHandler.spec.ts:229-249
Timestamp: 2026-01-10T08:54:09.466Z
Learning: In jsdom test environments, window.location.assign cannot be spied on due to TypeError: Cannot redefine property. Use Object.defineProperty to mock the entire window.location object, replacing it with a controlled mock, and restore the original in afterEach. Ensure to clean up the mock after each test to avoid side effects.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts
📚 Learning: 2026-01-08T07:05:01.766Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-conventions/CLAUDE.md:0-0
Timestamp: 2026-01-08T07:05:01.766Z
Learning: Import and use the default extraction config from `living-architecture/riviere-extract-conventions/default-config` in extraction tooling to detect all 6 component types

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T22:20:13.250Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/architecture/overview.md:0-0
Timestamp: 2026-01-08T22:20:13.250Z
Learning: Applies to docs/architecture/**/*extract*.ts : Use the Rivière Builder Node.js library to programmatically construct the schema graph when implementing custom extraction code

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-07T08:54:48.071Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/workflow/code-review.md:0-0
Timestamp: 2026-01-07T08:54:48.071Z
Learning: Applies to docs/workflow/**/*.{ts,tsx,js,jsx,!(**/*.test.ts,**/*.test.tsx,**/*.test.js,**/*.spec.ts,**/*.spec.tsx,**/*.spec.js)} : All production code (not test files) must align with architecture boundaries and layering requirements as defined in @/docs/architecture/overview.md and @/docs/conventions/codebase-structure.md

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-07T08:54:48.071Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/workflow/code-review.md:0-0
Timestamp: 2026-01-07T08:54:48.071Z
Learning: Applies to docs/workflow/**/*.{ts,tsx,js,jsx} : Review usage of `/* v8 ignore next -- preserve */` coverage skip directives. This is only acceptable for unreachable code needed to satisfy the compiler. Most cases should be solved by extracting code or writing tests to mock behavior.

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : Test domain-specific edge cases: valid email formats, URL protocols/ports, international phone numbers, Unicode addresses, currency rounding, percentages over 100%

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : Test violated domain constraints: uniqueness violations, missing relationships, ordering violations, range breaches, state inconsistencies, format mismatches, and temporal ordering

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-10T10:14:32.627Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-10T10:14:32.627Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{ts,tsx,js,jsx} : Test edge cases for dates/times: leap years, daylight saving transitions, timezone boundaries, midnight, end of day, year boundaries, invalid dates, and epoch edge cases

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-08T17:19:17.148Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-extract-ts/CLAUDE.md:0-0
Timestamp: 2026-01-08T17:19:17.148Z
Learning: All extraction rules should come from validated ExtractionConfig provided by riviere-extract-config

Applied to files:

  • packages/riviere-cli/src/commands/extract/extract.ts
🧬 Code graph analysis (1)
packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts (2)
packages/riviere-cli/src/command-test-fixtures.ts (3)
  • TestContext (62-66)
  • createTestContext (68-74)
  • setupCommandTest (76-93)
packages/riviere-cli/src/cli.ts (1)
  • createProgram (44-78)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: main
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (12)
packages/riviere-cli/src/commands/extract/extract.ts (5)

16-18: LGTM!

The import correctly adds DraftComponent type following the cross-project import guidelines.


24-27: LGTM!

The optional dryRun field properly extends the interface to support the new flag.


39-45: LGTM!

The code-point comparator ensures deterministic sorting, addressing the requirement for deterministic dry-run output. The v8 ignore directive is appropriate for this trivial comparison utility.


91-91: LGTM!

The CLI option is properly documented and follows Commander.js conventions.


152-158: LGTM!

The conditional dry-run path correctly short-circuits to emit formatted summary output instead of full JSON, meeting the acceptance criteria. The early return prevents any unintended side effects.

packages/riviere-cli/src/commands/extract/extract.dry-run.spec.ts (7)

1-14: LGTM!

Imports are clean and follow cross-project import guidelines. The test setup properly uses the shared test fixtures.


19-63: LGTM!

This test correctly validates the basic dry-run output format for a single domain and component type. The test setup, execution, and assertion are clear and focused.


65-123: LGTM!

This test properly verifies that multiple component types within a single domain are aggregated and formatted correctly, with types sorted as expected (api(1), useCase(2)).


125-194: LGTM!

This test effectively validates that multiple domains produce separate output lines, meeting the multi-domain acceptance criterion.


196-270: Excellent verification of count parity.

This test cleverly validates the critical acceptance criterion that "dry-run counts must match counts from full extraction" by:

  1. Running full extraction and counting components
  2. Running dry-run and parsing count patterns
  3. Asserting the totals match

This ensures the dry-run summary is accurate and not just cosmetic.


272-320: LGTM!

This test properly verifies the edge case where no components are extracted, ensuring no output is produced. This prevents confusing empty domain lines.


323-345: LGTM!

The helper functions follow the established learning to keep type guards minimal and focused on type narrowing rather than comprehensive validation. The parseExtractionOutput function provides clear error messages for debugging.

Based on learnings: Type guards are kept simple and focused on type narrowing, with validation delegated to test assertions.

Comment thread packages/riviere-cli/src/commands/extract/extract.ts
@NTCoding
NTCoding merged commit 696d4ba into main Jan 11, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[M4-D4.2] Add dry-run mode to extract command

1 participant