Skip to content

feat(extract-config): add module-level extends support - #129

Merged
NTCoding merged 18 commits into
mainfrom
issue-128-m5-d5-0-add-extends-support-to
Jan 11, 2026
Merged

NTCoding merged 18 commits into
mainfrom
issue-128-m5-d5-0-add-extends-support-to

Conversation

@NTCoding

@NTCoding NTCoding commented Jan 11, 2026 •

Copy link
Copy Markdown
Owner

User description

Closes #128

Summary

  • Adds module-level extends property to extraction config schema
  • Enables inheriting component rules from npm packages or file paths
  • Local rules override inherited rules via nullish coalescing
  • Implements resolveConfig function in riviere-extract-ts
  • Adds createConfigLoader in riviere-cli for concrete resolution

Test plan

  • Schema validates configs with extends property
  • Unit tests for package resolution
  • Unit tests for file path resolution
  • Unit tests for override merging
  • 100% test coverage

Closes #128

🤖 Generated with Claude Code


PR Type

Enhancement


Description

  • Add extends support to extraction config schema for rule inheritance

  • Implement resolveConfig function to merge inherited and local rules

  • Create createConfigLoader for npm package and file path resolution

  • Update extractor to use resolved configs with complete rule definitions


Diagram Walkthrough

flowchart LR
  A["Unresolved Config<br/>with extends"] -->|resolveConfig| B["Config Loader"]
  B -->|load base module| C["Base Module Rules"]
  C -->|merge with overrides| D["Resolved Config<br/>with complete rules"]
  D -->|extractComponents| E["Extracted Components"]
Loading

File Walkthrough

Relevant files
Enhancement
8 files
types.ts
Split Module into ModuleConfig and resolved Module types 
+34/-0   
extraction-config.schema.json
Add extends property with conditional rule validation       
+14/-1   
index.ts
Export createResolvedConfig fixture function                         
+3/-1     
resolve-config.ts
Implement config resolution with extends inheritance         
+73/-0   
index.ts
Export resolveConfig and ConfigLoader type                             
+3/-0     
extractor.ts
Update to use ResolvedExtractionConfig type                           
+4/-4     
config-loader.ts
Implement config loader for npm and file resolution           
+98/-0   
extract.ts
Integrate config resolution into extract command                 
+10/-5   
Tests
6 files
validation-extends.spec.ts
Add comprehensive tests for extends validation                     
+105/-0 
validation-fixtures.ts
Add createResolvedConfig fixture helper function                 
+5/-1     
validation.spec.ts
Add test for createResolvedConfig validation                         
+5/-0     
resolve-config.spec.ts
Add tests for config resolution and rule merging                 
+166/-0 
extractor.spec.ts
Update tests to use ResolvedExtractionConfig                         
+12/-12 
config-loader.spec.ts
Add comprehensive tests for config loader                               
+207/-0 

Summary by CodeRabbit

  • New Features

    • Config inheritance (extends) and runtime config resolution in extraction; CLI supports resolved extraction configs and improved CLI commands.
    • New public validation and resolution utilities exposed for consumer use.
    • SchemaModal exposes download-name validation.
  • Documentation

    • Added anti-pattern guidance (cross-package test fixtures, coverage-ignore justification), string-based error-detection guidance, and expanded JSDoc expectations.
  • Tests

    • Extensive new and updated tests for config loading, inheritance/resolution, validation, and error handling.
  • Bug Fixes / UX

    • Many generic errors replaced with specific error classes for clearer diagnostics.

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

Add extends property to extraction config schema allowing modules
to inherit component rules from npm packages or file paths.
Local rules override inherited rules.

Schema changes:
- Add extends property with conditional validation
- Split types: ModuleConfig (unresolved) vs Module (resolved)
- Validation for extends syntax

Implementation:
- resolveConfig in riviere-extract-ts handles inheritance
- createConfigLoader in riviere-cli provides Node.js resolution
- Support for both npm package names and relative file paths

Tests:
- Schema validation for extends syntax
- Config resolution with package and file extends
- Override behavior (local rules take precedence)
- Error handling for missing extends targets
- 100% coverage

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@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: 4d4b151
Status: ✅  Deploy successful!
Preview URL: https://71154977.living-architecture.pages.dev
Branch Preview URL: https://issue-128-m5-d5-0-add-extend.living-architecture.pages.dev

View logs

@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
⚪
Arbitrary file read

Description: The createConfigLoader resolves file-based extends via resolve(configDir, source) without
restricting traversal (e.g., ../), enabling arbitrary local file reads if a malicious
config is supplied.
config-loader.ts [89-97]

Referred Code
export function createConfigLoader(configDir: string): ConfigLoader {
  return (source: string): Module => {
    const filePath = isPackageReference(source)
      ? resolvePackagePath(source)
      : resolve(configDir, source)

    const config = loadConfigFile(filePath, source)
    return extractModuleFromConfig(config)
  }
Ticket Compliance
🟡
🎫 #128
🟢 Add module-level extends property to the extraction config schema and implement it in
riviere-extract-ts.
When a module has extends: "@living-architecture/riviere-extract-conventions", config
loading inherits component rules from that package’s src/default-extraction.config.json.
When a module has extends: "./shared/base.json", config loading inherits component rules
from that file path (relative to the config).
When a module has extends and also local component rules, local rules override inherited
rules.
When extends is used, name and path are still required locally; validation must fail if
missing.
If an `extends` reference cannot be resolved, a clear error message is shown.
Add unit tests for package resolution, file path resolution, and override merging.
⚪ Add an integration test proving a config with extends loads correctly and extraction
works.
Achieve 100% test coverage.
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: 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: Robust Error Handling and Edge Case Management

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

Status:
Weak config validation: parseConfigContent accepts any non-null object as ExtendedConfig and
extractModuleFromConfig returns config.modules?.[0] without validating required rules, so
malformed extended configs may pass parsing and fail later without clear context.

Referred Code
function isExtendedConfig(value: unknown): value is ExtendedConfig {
  return typeof value === 'object' && value !== null
}

function parseConfigContent(content: string): ExtendedConfig {
  const parsed: unknown = parseYaml(content)
  if (!isExtendedConfig(parsed)) {
    throw new Error('Invalid extended config format')
  }
  return parsed
}

function extractModuleFromConfig(config: ExtendedConfig): Module {
  const firstModule = config.modules?.[0]
  if (firstModule !== undefined) {
    return firstModule
  }

  return {
    name: 'extended',
    path: '**',


 ... (clipped 8 lines)

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:
Path disclosure risk: Thrown errors include resolved filesystem paths (e.g., File not found: ${filePath}), which
may expose internal directory structure if surfaced to end users in non-local contexts.

Referred Code
function loadConfigFile(filePath: string, source: string): ExtendedConfig {
  if (!existsSync(filePath)) {
    throw new Error(
      `Cannot resolve extends reference '${source}'. ` + `File not found: ${filePath}`,
    )
  }

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:
Arbitrary file read: createConfigLoader resolves non-package extends values via resolve(configDir, source) and
then reads the resulting path, which permits extends to escape configDir (e.g., ../..) and
read arbitrary files if the config is untrusted.

Referred Code
export function createConfigLoader(configDir: string): ConfigLoader {
  return (source: string): Module => {
    const filePath = isPackageReference(source)
      ? resolvePackagePath(source)
      : resolve(configDir, source)

    const config = loadConfigFile(filePath, source)
    return extractModuleFromConfig(config)
  }

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

@NTCoding NTCoding changed the title [M5-D5.0] Add extends support to extraction config schema feat(extract-config): add module-level extends support Jan 11, 2026
@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
Improve package resolution via package.json

Instead of hardcoding the config path to src/default-extraction.config.json for
package resolution, use a field like exports in the target package's
package.json. This change decouples the loader from the internal structure of
convention packages.

Examples:

packages/riviere-cli/src/commands/extract/config-loader.ts [55-66]
function resolvePackagePath(packageName: string): string {
  try {
    const packageJsonPath = require.resolve(`${packageName}/package.json`)
    const packageDir = dirname(packageJsonPath)
    const defaultConfigPath = resolve(packageDir, 'src/default-extraction.config.json')
    if (existsSync(defaultConfigPath)) {
      return defaultConfigPath
    }
    throw new Error(
      `Package '${packageName}' does not contain 'src/default-extraction.config.json'. ` +

 ... (clipped 2 lines)

Solution Walkthrough:

Before:

// packages/riviere-cli/src/commands/extract/config-loader.ts
function resolvePackagePath(packageName: string): string {
  try {
    const packageJsonPath = require.resolve(`${packageName}/package.json`);
    const packageDir = dirname(packageJsonPath);
    
    // Path is hardcoded, coupling the tool to the package's internal structure.
    const defaultConfigPath = resolve(packageDir, 'src/default-extraction.config.json');

    if (existsSync(defaultConfigPath)) {
      return defaultConfigPath;
    }
    throw new Error(
      `Package '${packageName}' does not contain 'src/default-extraction.config.json'.`
    );
  } catch (error) {
    // ...
  }
}

After:

// packages/riviere-cli/src/commands/extract/config-loader.ts
function resolvePackagePath(packageName: string): string {
  try {
    const packageJsonPath = require.resolve(`${packageName}/package.json`);
    const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));

    // Read a custom field from package.json to find the config file.
    // This decouples the implementation from the package's file structure.
    const configSubPath = packageJson.riviere?.config || packageJson.exports?.['./riviere-config'];
    if (!configSubPath) {
      throw new Error(`Package '${packageName}' does not export a Riviere config.`);
    }

    const packageDir = dirname(packageJsonPath);
    return resolve(packageDir, configSubPath);
  } catch (error) {
    // ...
  }
}
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a design weakness where the config path is hardcoded in config-loader.ts, creating tight coupling, and proposes a significantly more robust and flexible solution using package.json that aligns with ecosystem best practices.

Medium
General
Gracefully handle config resolution errors

Add a try/catch block around the resolveConfig call in the extract command. This
will catch configuration resolution errors, format them for the CLI, and prevent
the application from crashing with an unhandled exception.

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

 const configDir = dirname(resolve(options.config))
 const configLoader = createConfigLoader(configDir)
-const resolvedConfig = resolveConfig(unresolvedConfig, configLoader)
+let resolvedConfig: ResolvedExtractionConfig
+try {
+  resolvedConfig = resolveConfig(unresolvedConfig, configLoader)
+} catch (error) {
+  console.log(
+    JSON.stringify(
+      formatError(CliErrorCode.ValidationError, (error as Error).message)
+    )
+  )
+  process.exit(1)
+}
 
 const sourceFilePaths = resolvedConfig.modules
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly points out a potential unhandled exception and proposes adding a try/catch block to gracefully handle configuration resolution errors, which is crucial for a robust CLI tool.

Medium
Report all missing rules at once

Modify resolveModule to check for all required rules simultaneously and report
all missing rules in a single error message. This improves user experience by
avoiding the need to fix configuration errors one by one.

packages/riviere-extract-ts/src/resolve-config.ts [61-73]

-function requireRule(
-  rule: ComponentRule | undefined,
-  ruleName: string,
-  moduleName: string,
-): ComponentRule {
-  if (rule === undefined) {
+function resolveModule(moduleConfig: ModuleConfig, loader?: ConfigLoader): Module {
+  const extendsSource = moduleConfig.extends
+  if (extendsSource !== undefined) {
+    return resolveModuleWithExtends(moduleConfig, extendsSource, loader)
+  }
+
+  const componentRuleNames: (keyof Module)[] = [
+    'api',
+    'useCase',
+    'domainOp',
+    'event',
+    'eventHandler',
+    'ui',
+  ]
+  const missingRules = componentRuleNames.filter((name) => moduleConfig[name] === undefined)
+
+  if (missingRules.length > 0) {
     throw new Error(
-      `Module '${moduleName}' is missing required rule '${ruleName}'. ` +
-        `Either provide the rule or use extends to inherit from a base config.`,
+      `Module '${moduleConfig.name}' is missing required rules: ${missingRules.join(', ')}. ` +
+        `Either provide the rules or use extends to inherit from a base config.`,
     )
   }
-  return rule
+
+  return moduleConfig as Module
 }
 
+// ...
+
+// The requireRule function is no longer needed and can be removed.
+

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 7

__

Why: This suggestion correctly identifies a user experience issue with error reporting and proposes a good solution to report all missing rules at once, which is more efficient for the user.

Medium
Preserve original error for better debugging

Improve the error message in resolvePackagePath by including the original error
from require.resolve. This will provide more context and aid in debugging
package resolution issues.

packages/riviere-cli/src/commands/extract/config-loader.ts [55-76]

 function resolvePackagePath(packageName: string): string {
   try {
     const packageJsonPath = require.resolve(`${packageName}/package.json`)
     const packageDir = dirname(packageJsonPath)
     const defaultConfigPath = resolve(packageDir, 'src/default-extraction.config.json')
     if (existsSync(defaultConfigPath)) {
       return defaultConfigPath
     }
     throw new Error(
       `Package '${packageName}' does not contain 'src/default-extraction.config.json'. ` +
         `Ensure the package exports a default extraction config.`,
     )
   } catch (error) {
     if (error instanceof Error && error.message.includes('does not contain')) {
       throw error
     }
     throw new Error(
       `Cannot resolve package '${packageName}'. ` +
-        `Ensure the package is installed in node_modules.`,
+        `Ensure the package is installed in node_modules. ` +
+        `Original error: ${(error as Error).message}`,
     )
   }
 }
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: This is a valid suggestion that improves error handling by including the original error message, which enhances the debugging experience for users.

Low
  • Update

- Extract predicate validation logic to dedicated function
- Reduce cyclomatic complexity in resolveConfig
- Split test fixtures into separate file for reusability
- Update anti-patterns documentation
- Clean up import organization

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

coderabbitai Bot commented Jan 11, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds module-level "extends" support for extraction configs with schema, types, validation, resolver, CLI loader, and extractor integration. Introduces many domain-specific error classes, centralizes test assertion errors, updates tests, docs, linting, scripts, and Vitest coverage configuration. No unrelated runtime behavior changes.

Changes

Cohort / File(s) Summary
Schema & Types
packages/riviere-extract-config/extraction-config.schema.json, packages/riviere-extract-config/src/types.ts
Add optional extends to module schema with conditional requirements; introduce Module/ModuleConfig/ResolvedExtractionConfig and predicate/type additions.
Validation & Parsing
packages/riviere-extract-config/src/validation.ts, .../validation-fixtures.ts, .../validation-extends.spec.ts, .../validation.spec.ts, packages/riviere-extract-config/src/index.ts
New validation API (isValidExtractionConfig, ValidationResult), ExtractionConfigValidationError, AJV error mapping, formatter, and updated tests/fixtures expecting structured validation errors.
Config Resolution (library)
packages/riviere-extract-ts/src/resolve-config.ts, .../resolve-config.spec.ts, .../test-fixtures.ts, .../index.ts
Add exported ConfigLoader type and resolveConfig to expand extends (package/file resolution, merge overrides, require-rule checks); unit tests and re-exports updated.
Config Loader (CLI)
packages/riviere-cli/src/commands/extract/config-loader.ts, .../config-loader.spec.ts
New createConfigLoader(configDir) resolving package or local extends sources, parsing YAML/JSON into Module, error mapping to specific error classes; comprehensive tests added.
CLI Integration & Helpers
packages/riviere-cli/src/cli.ts, packages/riviere-cli/src/commands/extract/extract.ts, packages/riviere-cli/src/output.ts, packages/riviere-cli/src/command-test-fixtures.ts
Add parsePackageJson and createProgram; extract command now uses createConfigLoader + resolveConfig; introduce TestAssertionError/MockError test fixtures and JSDoc lint expansion.
Extractor API & Tests
packages/riviere-extract-ts/src/extractor.ts, .../extractor.spec.ts, .../test-fixtures.ts
Public API now consumes ResolvedExtractionConfig; add exported DraftComponent; tests and fixtures migrated to resolved configs.
Error Taxonomy & Tests
multiple files (e.g., packages/riviere-cli/src/errors.ts, packages/riviere-extract-ts/src/errors.ts, packages/riviere-builder/src/errors.ts, apps/eclair/src/errors.ts)
Introduce many domain-specific error classes and replace generic Error throws across CLI, builder, extractor, and Éclair; extensive unit tests added for new errors.
Test Helpers & Fixtures
multiple *.spec.ts, */*-fixtures.ts across packages
Standardize TestAssertionError/MockError usage across tests; update many specs to import and assert against these types.
Client app (Éclair)
apps/eclair/src/errors.ts, apps/eclair/src/App.tsx, apps/eclair/src/components/..., apps/eclair/src/contexts/*
Add Eclair error hierarchy (GraphError, ContextError, LayoutError, SchemaError, DOMError, CSSModuleError); swap generic Errors to typed errors; export/use typed helpers and update tests.
Schema / Component ID
packages/riviere-schema/src/validation.ts, packages/riviere-schema/src/component-id.ts, packages/riviere-schema/src/index.ts
Add RiviereSchemaValidationError and InvalidComponentIdError; parse functions throw structured validation errors; exports updated.
Docs & Linting
docs/conventions/anti-patterns.md, docs/conventions/review-feedback-checks.md, eslint.config.mjs
Add anti-pattern guidance (sharing fixtures, lazy coverage-ignore, string-based error detection); broaden JSDoc enforcement and add test-specific lint rule discouraging Error in tests.
Scripts & Config
scripts/get-pr-feedback.sh, apps/eclair/vitest.config.mts, packages/riviere-cli/vitest.config.mts
Update PR feedback script to include SonarCloud link; adjust Vitest coverage reporter to include repo/project root.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI (extract command)
    participant Loader as ConfigLoader (createConfigLoader)
    participant Resolver as resolveConfig
    participant FS as Package/Filesystem
    participant Extractor as extractComponents

    CLI->>Loader: createConfigLoader(configDir)
    CLI->>Resolver: resolveConfig(unresolvedConfig, Loader)
    Resolver->>Resolver: iterate modules
    alt module has extends
        Resolver->>Loader: loader(extends source)
        Loader->>FS: resolve package or read relative file
        FS-->>Loader: base module config
        Loader-->>Resolver: base module
        Resolver->>Resolver: merge base module with local overrides
    else no extends
        Resolver->>Resolver: validate required rule fields present
    end
    Resolver-->>CLI: ResolvedExtractionConfig
    CLI->>Extractor: extractComponents(project, files, resolvedConfig)
    Extractor-->>CLI: DraftComponent[]
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I hopped through configs, found an "extends" trace,

I fetched base rules from package and local place,
Merged with gentle paws, let overrides embrace,
Tests thumped their feet to guard each error case,
Now extracts hum softly — a rabbit's tidy grace.

🚥 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 PR title 'feat(extract-config): add module-level extends support' accurately summarizes the main feature being added: module-level extends support to the extraction config.
Linked Issues check ✅ Passed The PR implements all acceptance criteria from issue #128: schema validation for extends, package and file path resolution, local rule override merging, validation failures for missing name/path, and error handling for unresolved references.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing module-level extends support or improving error handling. Documentation updates, linting config changes, and test assertion improvements are reasonable supporting changes.

✏️ 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.

Inline createMinimalModule to eliminate unused export detected by knip.

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: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/riviere-cli/src/output.ts (1)

10-18: ErrorOutput.error.code should match formatError’s CliErrorCode (or vice-versa).

Option A (preferred): tighten the output type to the enum/union
 export interface ErrorOutput {
   success: false
   error: {
-    code: string
+    code: CliErrorCode
     message: string
     suggestions: string[]
   }
 }

If the output contract intentionally allows arbitrary string codes, then change formatError(code: CliErrorCode, ...) to formatError(code: string, ...) instead.

Also applies to: 34-53

🤖 Fix all issues with AI agents
In @packages/riviere-cli/src/commands/extract/config-loader.ts:
- Around line 25-31: The parseConfigContent function throws a generic Error when
isExtendedConfig(parsed) fails; improve it to provide specific diagnostics by
including the invalid parsed value and/or validation failures: enhance
parseConfigContent to capture the raw parsed object from parseYaml and, when
isExtendedConfig returns false, throw an Error that contains a short message
plus JSON.stringify(parsed, null, 2) or a list of missing/invalid fields (you
can add a small helper validator or extend isExtendedConfig to return error
details) so callers see what part of the ExtendedConfig is malformed.
- Around line 21-23: The isExtendedConfig type guard only checks for a non-null
object and must be strengthened to validate the actual ExtendedConfig shape:
update isExtendedConfig to assert required keys and types (e.g., check presence
and types of fields like <list the real required properties if known> or at
minimum required properties such as config.mode, config.source, config.output
etc.), return false for invalid shapes, and throw/propagate a clear, descriptive
error at config load time if validation fails; alternatively integrate the
official schema validator from @living-architecture/riviere-extract-config to
validate the parsed config against the extraction schema and surface explicit
validation errors so loaders using isExtendedConfig (function name
isExtendedConfig) never accept arbitrary objects.
- Around line 67-75: Replace brittle string matching in the catch block with a
robust custom error type or error code: define a specific error (e.g.,
MissingPackageError or set error.code = 'MISSING_PACKAGE') where the package
resolution logic (the resolver that may throw for packageName) detects the "does
not contain" condition, then here in config-loader.ts catch check error
instanceof MissingPackageError or error.code === 'MISSING_PACKAGE' instead of
error.message.includes(...), rethrow that custom error unchanged and convert any
other errors into the generic `Cannot resolve package '${packageName}'` Error to
preserve existing behaviour.
- Line 59: The code currently hardcodes the internal file path via
defaultConfigPath = resolve(packageDir, 'src/default-extraction.config.json');
change this to resolve the package export instead—use the package export
specifier (e.g.
'@living-architecture/riviere-extract-conventions/default-config') and locate it
with the module resolver (require.resolve(...) in CJS or
import.meta.resolve/await import.resolve if ESM) to set defaultConfigPath;
update the assignment that references defaultConfigPath and remove the direct
packageDir + src path usage so the loader relies on the package export
entrypoint.
- Around line 89-98: The loader returned by createConfigLoader currently loads
extended configs via loadConfigFile and then blindly calls
extractModuleFromConfig without validating the loaded object; update
loadConfigFile (or add a helper invoked by it) to validate any extended config
against the extraction config schema (the same schema used in extract.ts) when
loadConfigFile receives an extended config, and throw or return a descriptive
error if validation fails so createConfigLoader (which uses isPackageReference,
resolvePackagePath, resolve, loadConfigFile, extractModuleFromConfig) only ever
transforms a config that passes schema validation.

In @packages/riviere-cli/src/output.ts:
- Around line 3-8: The SuccessOutput<T> contract declares warnings as always
present but the docs call them optional; update the type to match the docs by
changing the property on SuccessOutput<T> to warnings?: string[] and do the same
for the other related output interfaces referenced around lines 20-31, then
audit any formatter/serializer that consumes SuccessOutput (search for usages of
SuccessOutput or functions that produce CLI output) to tolerate undefined
warnings (e.g., default to an empty array when formatting) so runtime behavior
stays safe.
📜 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 122a864 and c3e2723.

📒 Files selected for processing (21)
  • docs/conventions/anti-patterns.md
  • eslint.config.mjs
  • packages/riviere-cli/src/cli.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/output.ts
  • packages/riviere-extract-config/extraction-config.schema.json
  • packages/riviere-extract-config/src/index.ts
  • packages/riviere-extract-config/src/types.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-ts/src/predicates/evaluate-predicate.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
💤 Files with no reviewable changes (1)
  • packages/riviere-extract-config/src/index.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{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/cli.ts
  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/predicates/evaluate-predicate.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.ts
  • packages/riviere-cli/src/output.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/cli.ts
  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/predicates/evaluate-predicate.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.ts
  • packages/riviere-cli/src/output.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/cli.ts
  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/predicates/evaluate-predicate.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.ts
  • packages/riviere-cli/src/output.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/cli.ts
  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/predicates/evaluate-predicate.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.ts
  • packages/riviere-cli/src/output.ts
packages/riviere-extract-ts/**/*.{ts,tsx}

📄 CodeRabbit inference engine (packages/riviere-extract-ts/CLAUDE.md)

packages/riviere-extract-ts/**/*.{ts,tsx}: Use ts-morph for TypeScript AST parsing instead of other parsers
Implement extraction logic as pure functions with no side effects
Compose detection rules via and/or logic for predicates
Reject invalid extraction configs at load time, not during extraction phase
Use glob pattern matching for module-based organization of extraction rules

Files:

  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-ts/src/predicates/evaluate-predicate.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
packages/riviere-extract-config/**/*.ts

📄 CodeRabbit inference engine (packages/riviere-extract-config/CLAUDE.md)

Extraction config schema is the source of truth for valid structures. TypeScript types must mirror the schema definition to maintain consistency

Files:

  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-extract-config/src/types.ts
🧠 Learnings (61)
📓 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/**/*.{ts,tsx} : Use glob pattern matching for module-based organization of extraction rules
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-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
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/**/*.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: 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
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-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
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
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
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: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted
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: All validation of extraction config must occur at config load time, not during extraction. Invalid configs should fail fast with clear error messages that include paths and descriptive information
📚 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: 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.

Applied to files:

  • packages/riviere-cli/src/cli.ts
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-cli/src/output.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 ts-morph for TypeScript AST parsing instead of other parsers

Applied to files:

  • packages/riviere-cli/src/cli.ts
  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-ts/src/index.ts
  • eslint.config.mjs
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.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/cli.ts
  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/predicates/evaluate-predicate.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-cli/src/output.ts
📚 Learning: 2026-01-02T11:58:27.018Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-cli/CLAUDE.md:0-0
Timestamp: 2026-01-02T11:58:27.018Z
Learning: After modifying CLI commands, run `nx generate-docs riviere-cli` to regenerate CLI reference documentation

Applied to files:

  • packages/riviere-cli/src/cli.ts
  • packages/riviere-cli/src/output.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/cli.ts
  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/predicates/evaluate-predicate.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.ts
  • packages/riviere-cli/src/output.ts
📚 Learning: 2026-01-02T11:58:27.018Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-cli/CLAUDE.md:0-0
Timestamp: 2026-01-02T11:58:27.018Z
Learning: When modifying CLI commands in the riviere-cli tool, update the corresponding workflow prompts in docs/workflow/ directory (step-1 through step-6) to keep the extraction workflow in sync

Applied to files:

  • packages/riviere-cli/src/cli.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/cli.ts
  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/extraction-config.schema.json
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.ts
  • packages/riviere-cli/src/output.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/cli.ts
  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/extraction-config.schema.json
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • eslint.config.mjs
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.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/cli.ts
  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/extraction-config.schema.json
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • eslint.config.mjs
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.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-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/extraction-config.schema.json
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.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-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/extraction-config.schema.json
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • eslint.config.mjs
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.ts
  • packages/riviere-cli/src/output.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-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/extraction-config.schema.json
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.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-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/extraction-config.schema.json
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.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-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-config/extraction-config.schema.json
  • packages/riviere-extract-config/src/validation-fixtures.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • eslint.config.mjs
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
  • packages/riviere-extract-config/src/types.ts
📚 Learning: 2026-01-08T22:39:00.431Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 84
File: packages/riviere-extract-ts/src/extractor.ts:168-187
Timestamp: 2026-01-08T22:39:00.431Z
Learning: In ts-morph usage within the riviere-extract-ts package, MethodDeclaration.getName() always returns a string (never undefined) because methods cannot be anonymous in TypeScript. Only ClassDeclaration.getName() and FunctionDeclaration.getName() can return undefined. Therefore, remove undefined guards for MethodDeclaration when implementing createMethodComponent, and only keep guards for components that can actually be undefined (class/function components). Apply this guidance to all .ts files under packages/riviere-extract-ts/ (i.e., **/packages/riviere-extract-ts/**/*.ts).

Applied to files:

  • packages/riviere-extract-ts/src/resolve-config.ts
  • packages/riviere-extract-ts/src/index.ts
  • packages/riviere-extract-ts/src/predicates/evaluate-predicate.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-ts/src/extractor.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: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted

Applied to files:

  • packages/riviere-extract-config/extraction-config.schema.json
  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-extract-config/src/types.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} : Compose detection rules via and/or logic for predicates

Applied to files:

  • packages/riviere-extract-config/extraction-config.schema.json
  • packages/riviere-extract-ts/src/predicates/evaluate-predicate.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • eslint.config.mjs
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-config/src/types.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*-fixtures.ts : Create `<module>-fixtures.ts` fixture files alongside `<module>.spec.ts` to reduce duplication when multiple tests share similar setup data or differ only in specific values being tested.

Applied to files:

  • docs/conventions/anti-patterns.md
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-ts/src/extractor.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/apps/*/src/**/*.test.ts : Test fixtures used across multiple test files may be grouped in shared locations (e.g., test-fixtures.ts), but otherwise test files should be co-located with the code they test.

Applied to files:

  • docs/conventions/anti-patterns.md
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Avoid anti-patterns documented in `docs/conventions/anti-patterns.md`

Applied to files:

  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: When hitting max-lines limits, split files into focused modules (e.g., `foo.spec.ts` and `foo.edge-cases.spec.ts`), extract duplicated code into shared modules, or use parameterized tests with `it.each` or `describe.each` instead of removing tests or compressing code.

Applied to files:

  • docs/conventions/anti-patterns.md
  • packages/riviere-extract-ts/src/extractor.spec.ts
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Do not pass empty strings into parameters of type string. Empty strings indicate missing values and should trigger errors, use optional types, or reconsider the design. Avoid test cases that verify empty string as a valid expected scenario for string parameters.

Applied to files:

  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for string inputs: empty string, whitespace-only strings, very long strings (10K+ characters), Unicode (emojis, RTL text, combining characters), special characters (quotes, backslashes, null bytes), SQL/HTML/script injection patterns, and leading/trailing whitespace.

Applied to files:

  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-04T16:47:43.968Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 0
File: :0-0
Timestamp: 2026-01-04T16:47:43.968Z
Learning: JSDoc documentation is only required on public-facing library methods that people who install the packages will use. Do not suggest JSDoc for internal code, test fixtures, or test helpers.

Applied to files:

  • docs/conventions/anti-patterns.md
  • eslint.config.mjs
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Avoid implementation coupling in tests. Test behavior, not implementation details. Instead of asserting on mock call arguments with exact SQL, assert on the observable result (e.g., expect(result.user.name).toBe('Alice')).

Applied to files:

  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test violated domain constraints: uniqueness violations (duplicate IDs, emails), missing required relationships (orphaned records), ordering violations (events out of sequence), range breaches (age -1, quantity 1000000), state inconsistencies (shipped but not paid), format mismatches (expected JSON, got XML), and temporal ordering (end before start).

Applied to files:

  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for collections (arrays, objects, maps): empty collections, single element, duplicates, nested structures, circular references, very large collections (performance), sparse arrays, and mixed types.

Applied to files:

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

Applied to files:

  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test domain-specific edge cases: email (valid formats, plus signs, subdomains), URLs (protocols, ports, special characters, relative paths), phone numbers (international formats, extensions), addresses (Unicode, multi-line, missing components), currency (rounding, different currencies, zero amounts), percentages (0%, 100%, over 100%).

Applied to files:

  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-fast over silent fallbacks. Never use fallback chains (`value ?? backup ?? 'unknown'`). If data should exist, validate and throw a clear error.

Applied to files:

  • docs/conventions/anti-patterns.md
📚 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: All validation of extraction config must occur at config load time, not during extraction. Invalid configs should fail fast with clear error messages that include paths and descriptive information

Applied to files:

  • packages/riviere-extract-config/src/validation.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-extract-config/src/types.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 (*.spec.ts, *.test.ts), type guards like `isExtractionOutput(value: unknown): value is ExtractionOutput` should focus on narrowing types for TypeScript rather than comprehensive validation. Actual shape validation is handled through explicit test assertions (e.g., `expect(result).toMatchObject(...)`). This keeps type guards simple while maintaining thorough validation through assertion-based testing.

Applied to files:

  • packages/riviere-extract-config/src/validation.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/config-loader.spec.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/predicates/evaluate-predicate.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-extract-ts/src/extractor.spec.ts
  • packages/riviere-extract-config/src/types.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/config-loader.spec.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-extract-ts/src/extractor.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/config-loader.spec.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-ts/src/test-fixtures.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • eslint.config.mjs
  • packages/riviere-extract-ts/src/extractor.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/config-loader.spec.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-config/src/validation-extends.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/packages/*/vitest.config.ts : Each package must include a vitest.config.ts file with 100% coverage thresholds for test configuration.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Applies to **/vitest.config.ts : When creating new projects with tests, add vitest.config.ts with 100% coverage as the default

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-extract-config/src/validation.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/apps/*/vitest.config.ts : Each app must include a vitest.config.ts file with 100% coverage thresholds for test configuration.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.spec.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-extract-ts/src/extractor.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/config-loader.spec.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-extract-ts/src/extractor.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/config-loader.spec.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-extract-ts/src/resolve-config.spec.ts
  • packages/riviere-extract-config/src/validation-extends.spec.ts
  • packages/riviere-extract-ts/src/extractor.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/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • packages/riviere-cli/src/commands/extract/extract.ts
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Follow eslint configuration rules defined in `eslint.config.mjs` for all linting

Applied to files:

  • eslint.config.mjs
📚 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} : Check lint rules (eslint.config.mjs) before providing feedback to ensure suggestions don't contradict lint rules. Never suggest using banned keywords like 'as' or 'let'.

Applied to files:

  • eslint.config.mjs
📚 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:

  • eslint.config.mjs
📚 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} : Enforce the ESLint rule `require-component-decorator` to ensure all classes are annotated with component decorators

Applied to files:

  • eslint.config.mjs
  • packages/riviere-extract-config/src/types.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:

  • eslint.config.mjs
📚 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 must comply with anti-patterns guidelines defined in @/docs/conventions/anti-patterns.md. Violations are hard failures unless documented exceptions exist.

Applied to files:

  • eslint.config.mjs
📚 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: For custom architectural conventions not covered by standard decorators, implement custom enforcement through ESLint rules or CI checks

Applied to files:

  • eslint.config.mjs
📚 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: Configure ESLint to enforce component decorators on classes using the `require-component-decorator` rule from `living-architecture/riviere-extract-conventions/eslint-plugin`

Applied to files:

  • eslint.config.mjs
📚 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:

  • eslint.config.mjs
  • packages/riviere-extract-ts/src/extractor.ts
  • packages/riviere-extract-config/src/types.ts
  • packages/riviere-cli/src/output.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-extract-ts/src/extractor.ts
  • packages/riviere-extract-config/src/types.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: The `find` field in extraction config describes user intent (what components to extract), not the implementation strategy. For example, `find: "methods"` means "I want methods as architectural components", not "find classes then extract methods"

Applied to files:

  • packages/riviere-extract-ts/src/extractor.ts
📚 Learning: 2026-01-06T08:11:15.403Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 53
File: packages/riviere-extract-config/vitest.config.mts:20-20
Timestamp: 2026-01-06T08:11:15.403Z
Learning: In packages/riviere-extract-config/vitest.config.mts, the explicit tuple type assertion for the reporter configuration (`as ['text', ['lcov', { projectRoot: string }]]`) is necessary because vitest's CoverageReporter type requires the exact tuple shape; neither inference nor 'as const' produces a compatible type.

Applied to files:

  • packages/riviere-extract-ts/src/extractor.spec.ts
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Assert specific values, not types. Use `expect(result).toEqual(['First.', ' Second.'])` not `expect(result).toBeDefined()`. Specific assertions catch specific bugs.

Applied to files:

  • packages/riviere-extract-ts/src/extractor.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: Extraction config must support exactly eight predicate types that can be composed with and/or logic to filter architectural components

Applied to files:

  • packages/riviere-extract-config/src/types.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: The `where` field in extraction config describes filter predicates that qualify components. Predicates must directly match the extraction target (e.g., `hasDecorator` for decorated items, `inClassWith` for methods within qualifying classes)

Applied to files:

  • packages/riviere-extract-config/src/types.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 `DomainOp`, `APIEndpoint`, or `EventHandler` method-level decorators to mark individual methods as components

Applied to files:

  • packages/riviere-cli/src/output.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 `Ignore` decorator to exclude classes or methods from architectural extraction analysis

Applied to files:

  • packages/riviere-cli/src/output.ts
🧬 Code graph analysis (7)
packages/riviere-extract-ts/src/resolve-config.ts (2)
packages/riviere-extract-ts/src/index.ts (2)
  • ConfigLoader (6-6)
  • resolveConfig (6-6)
packages/riviere-extract-config/src/types.ts (5)
  • Module (84-93)
  • ExtractionConfig (99-102)
  • ResolvedExtractionConfig (108-111)
  • ModuleConfig (68-78)
  • ComponentRule (61-61)
packages/riviere-extract-config/src/validation.spec.ts (2)
packages/riviere-extract-config/src/validation.ts (1)
  • isValidExtractionConfig (16-18)
packages/riviere-extract-config/src/validation-fixtures.ts (2)
  • createMinimalConfig (42-44)
  • createResolvedConfig (46-48)
packages/riviere-extract-ts/src/test-fixtures.ts (2)
packages/riviere-extract-config/src/validation-fixtures.ts (2)
  • createMinimalModule (29-40)
  • createResolvedConfig (46-48)
packages/riviere-extract-config/src/types.ts (2)
  • Module (84-93)
  • ResolvedExtractionConfig (108-111)
packages/riviere-extract-config/src/validation-extends.spec.ts (2)
packages/riviere-extract-config/src/index.ts (1)
  • validateExtractionConfig (4-4)
packages/riviere-extract-config/src/validation-fixtures.ts (1)
  • createMinimalModule (29-40)
packages/riviere-extract-ts/src/extractor.ts (2)
packages/riviere-extract-ts/src/index.ts (2)
  • extractComponents (2-2)
  • DraftComponent (2-2)
packages/riviere-extract-config/src/types.ts (1)
  • ResolvedExtractionConfig (108-111)
packages/riviere-extract-ts/src/extractor.spec.ts (3)
packages/riviere-extract-ts/src/test-fixtures.ts (1)
  • createResolvedConfig (18-20)
packages/riviere-extract-config/src/validation-fixtures.ts (1)
  • createResolvedConfig (46-48)
packages/riviere-extract-config/src/types.ts (1)
  • ResolvedExtractionConfig (108-111)
packages/riviere-cli/src/commands/extract/extract.ts (4)
packages/riviere-cli/src/commands/extract/config-loader.ts (1)
  • createConfigLoader (89-98)
packages/riviere-extract-ts/src/resolve-config.ts (1)
  • resolveConfig (18-26)
packages/riviere-extract-ts/src/index.ts (2)
  • resolveConfig (6-6)
  • extractComponents (2-2)
packages/riviere-extract-ts/src/extractor.ts (1)
  • extractComponents (61-67)
⏰ 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). (4)
  • GitHub Check: main
  • GitHub Check: browser-tests (firefox)
  • GitHub Check: browser-tests (webkit)
  • GitHub Check: Cloudflare Pages

Comment thread packages/riviere-cli/src/commands/extract/config-loader.ts Outdated
Comment thread packages/riviere-cli/src/commands/extract/config-loader.ts Outdated
Comment thread packages/riviere-cli/src/commands/extract/config-loader.ts Outdated
Comment thread packages/riviere-cli/src/commands/extract/config-loader.ts
Comment thread packages/riviere-cli/src/commands/extract/config-loader.ts
Comment thread packages/riviere-cli/src/commands/extract/config-loader.ts
Comment thread packages/riviere-cli/src/output.ts
Replace string-based error detection with instanceof check using new
PackageConfigNotFoundError class. Enhance isExtendedConfig type guard
to validate modules array structure. Add source parameter to
parseConfigContent for better error context.

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: 4

🤖 Fix all issues with AI agents
In @packages/riviere-cli/src/commands/extract/config-loader.spec.ts:
- Around line 20-74: Add a regression test to assert that Windows absolute paths
are treated as file paths (not packages) by isPackageReference: in
packages/riviere-cli/src/commands/extract/config-loader.spec.ts add a test that
calls isPackageReference('C:\\\\project\\\\base.json') and expects false (and/or
that createConfigLoader('/project') resolves that path as a file when passed a
Windows absolute path). If isPackageReference currently uses a string-prefix
check, change it to use Node's path.isAbsolute(...) to detect absolute file
paths (ensuring Windows drive-letter paths return false from
isPackageReference).

In @packages/riviere-cli/src/commands/extract/config-loader.ts:
- Around line 31-51: The error-reporting in parseConfigContent can itself throw
when creating the preview with JSON.stringify; wrap the stringify in a safe
try/catch (or use a non-throwing fallback like util.inspect or a replacer that
converts BigInt to string) so that isExtendedConfig failures always produce the
intended Error; modify parseConfigContent to build preview via a safeSerialize
helper (try JSON.stringify(parsed, null, 2) inside try/catch and on error fall
back to String(parsed) or util.inspect(parsed, {depth:1})) and use that preview
in the thrown Error.
- Around line 77-99: isPackageReference() misdetects Windows absolute paths and
resolvePackagePath() uses bare require which fails in ESM; update
isPackageReference to treat any absolute path as non-package by using
path.isAbsolute(source) (keep the existing dot-prefix check), and change
resolvePackagePath to use createRequire(import.meta.url) from the 'module'
package (import createRequire) to obtain a local require function before calling
require.resolve(`${packageName}/package.json`), leaving the existing
dirname/resolve/existsSync logic and error handling intact.
📜 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 9f18341 and a843636.

📒 Files selected for processing (2)
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
🧠 Learnings (38)
📓 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/**/*.{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-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
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} : Reject invalid extraction configs at load time, not during extraction phase
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/**/*.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: 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-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
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} : Compose detection rules via and/or logic for predicates
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
📚 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/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.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/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*-fixtures.ts : Create `<module>-fixtures.ts` fixture files alongside `<module>.spec.ts` to reduce duplication when multiple tests share similar setup data or differ only in specific values being tested.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.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/config-loader.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/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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/packages/*/vitest.config.ts : Each package must include a vitest.config.ts file with 100% coverage thresholds for test configuration.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Applies to **/vitest.config.ts : When creating new projects with tests, add vitest.config.ts with 100% coverage as the default

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/apps/*/vitest.config.ts : Each app must include a vitest.config.ts file with 100% coverage thresholds for test configuration.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: When hitting max-lines limits, split files into focused modules (e.g., `foo.spec.ts` and `foo.edge-cases.spec.ts`), extract duplicated code into shared modules, or use parameterized tests with `it.each` or `describe.each` instead of removing tests or compressing code.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.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/config-loader.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/config-loader.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/config-loader.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.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/config-loader.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/config-loader.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/config-loader.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 (*.spec.ts, *.test.ts), type guards like `isExtractionOutput(value: unknown): value is ExtractionOutput` should focus on narrowing types for TypeScript rather than comprehensive validation. Actual shape validation is handled through explicit test assertions (e.g., `expect(result).toMatchObject(...)`). This keeps type guards simple while maintaining thorough validation through assertion-based testing.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx} : Parse, don't validate. Use Zod schemas at system boundaries to parse external data once. Don't scatter `isX(unknown): x is T` type guards throughout the codebase.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-Fast Error Handling: Validate and throw clear errors instead of using fallback chains. Error format: `Expected [X]. Got [Y]. Context: [debugging info]`

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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} : Avoid dangerous fallback values that hide bugs. Do not use `??` or `||` operators without clear reason for providing defaults. If a value is required, make it required rather than guessing at defaults. Exceptions: optional parameters with documented defaults, configuration with explicit optional semantics, and test data with placeholder values.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-fast over silent fallbacks. Never use fallback chains (`value ?? backup ?? 'unknown'`). If data should exist, validate and throw a clear error.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-06T08:11:15.403Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 53
File: packages/riviere-extract-config/vitest.config.mts:20-20
Timestamp: 2026-01-06T08:11:15.403Z
Learning: In packages/riviere-extract-config/vitest.config.mts, the explicit tuple type assertion for the reporter configuration (`as ['text', ['lcov', { projectRoot: string }]]`) is necessary because vitest's CoverageReporter type requires the exact tuple shape; neither inference nor 'as const' produces a compatible type.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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: All validation of extraction config must occur at config load time, not during extraction. Invalid configs should fail fast with clear error messages that include paths and descriptive information

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Never parse error message strings to determine error types or extract information using `.message.includes()`, `.message.startsWith()`, or regex patterns on `error.message`. Use typed custom error classes instead.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : When parsing strings in exception messages is 100% unavoidable (e.g., due to third-party library limitations), document the exception with justification, reference tracking issue, and note that upstream fix was requested.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.ts
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx} : Use Zod for runtime validation. In TypeScript, use Zod schemas for parsing external data, API responses, and user input. Type inference from schemas keeps types and validation in sync.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.ts
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Applies to **/*.{ts,tsx} : Use cross-project imports with package names (e.g., `import { X } from 'living-architecture/[pkg-name]'`) rather than relative paths

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/packages/*/package.json : When importing from another project, add explicit workspace dependencies to package.json using the format "living-architecture/[pkg-name]": "workspace:*" and run pnpm install.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.ts
🧬 Code graph analysis (2)
packages/riviere-cli/src/commands/extract/config-loader.spec.ts (1)
packages/riviere-cli/src/commands/extract/config-loader.ts (1)
  • createConfigLoader (112-121)
packages/riviere-cli/src/commands/extract/config-loader.ts (3)
packages/riviere-extract-config/src/types.ts (1)
  • Module (84-93)
packages/riviere-extract-ts/src/resolve-config.ts (1)
  • ConfigLoader (10-10)
packages/riviere-extract-ts/src/index.ts (1)
  • ConfigLoader (6-6)
⏰ 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). (5)
  • GitHub Check: browser-tests (firefox)
  • GitHub Check: browser-tests (webkit)
  • GitHub Check: browser-tests (chromium)
  • GitHub Check: main
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (4)
packages/riviere-cli/src/commands/extract/config-loader.ts (1)

112-121: Clean, minimal loader API; nice fit with resolveConfig’s ConfigLoader hook.

The createConfigLoader(configDir) => (source) => Module shape is easy to wire into config resolution, and the separation (resolvePackagePath / loadConfigFile / extractModuleFromConfig) keeps responsibilities clear.

packages/riviere-cli/src/commands/extract/config-loader.spec.ts (3)

11-19: Mock lifecycle looks good.

Resetting mocks before each test and restoring after each keeps suites isolated.


76-175: Extraction behavior tests are solid (modules[0] vs top-level defaults).

Covers “prefer module entry” and “fill missing rules with { notUsed: true }” well.


177-215: Package resolution tests may be environment-coupled; consider mocking module resolution.

These tests assume require.resolve('@living-architecture/riviere-extract-conventions/package.json') works in the test runtime and that the package layout contains src/default-extraction.config.json. If CI/package manager layout changes, this suite could become flaky; mocking the resolver boundary (or injecting it) would make this deterministic.

Comment thread packages/riviere-cli/src/commands/extract/config-loader.ts Outdated
Comment thread packages/riviere-cli/src/commands/extract/config-loader.ts Outdated
NTCoding and others added 3 commits January 11, 2026 14:57
Adds review feedback check for .message.includes() and similar
patterns. Hard fail - no decisions based on error message content.

Explicitly calls out that `error instanceof Error && error.message.includes()`
is still string-based detection and not allowed.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add ESLint rule banning `new Error()` to enforce use of custom error
classes with semantic names throughout the codebase.

Changes:
- Add no-restricted-syntax rule for NewExpression[callee.name="Error"]
- Create custom error classes in each package (errors.ts files)
- Replace all `throw new Error()` with specific error types
- Add MockError for test mocking scenarios
- Add comprehensive tests for all new error classes

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Export custom error classes so consumers can catch them:
- ExtractionConfigValidationError from riviere-extract-config
- RiviereSchemaValidationError, InvalidComponentIdError from riviere-schema
- Make TestAssertionError internal (not exported)

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: 19

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/riviere-schema/src/component-id.ts (1)

81-88: ComponentId.parse must reject empty segments and validate all four parts are non-empty.

Currently, parse('a:b:c:') succeeds because the check only validates parts.length !== 4 and name !== undefined, but an empty string is not undefined. This violates the documented format domain:module:type:name where each segment must be present.

Additionally, InvalidComponentIdError is not exported from the package entrypoint (src/index.ts), forcing downstream code to use a deep import to catch the error. Export it alongside ComponentId so consumers can properly handle validation failures via @living-architecture/riviere-schema.

Proposed fix
 static parse(id: string): ComponentId {
-  const parts = id.split(':')
-  const name = parts[3]
-  if (parts.length !== 4 || name === undefined) {
-    throw new InvalidComponentIdError(id)
+  const trimmed = id.trim()
+  const parts = trimmed.split(':')
+  if (parts.length !== 4 || parts.some((p) => p.length === 0)) {
+    throw new InvalidComponentIdError(id)
+  }
+  const name = parts[3]!
+  return new ComponentId(name, trimmed)
 }
-  return new ComponentId(name, id)
 }

In src/index.ts:

 export {
-  ComponentId, type ComponentIdParts 
+  ComponentId, InvalidComponentIdError, type ComponentIdParts 
 } from './component-id'
apps/eclair/src/features/comparison/ComparisonPage.detailedChanges.spec.tsx (1)

20-39: Extract duplicated test helper to shared fixture file.

The stubFileReaderWithMultipleContents function is duplicated in both ComparisonPage.spec.tsx (lines 64-83) and this file. Consider extracting it to a shared test fixture file such as comparison-test-fixtures.ts to eliminate duplication.

Based on learnings, create fixture files alongside spec files to reduce duplication when multiple tests share similar setup data.

packages/riviere-cli/src/commands/builder/add-component.ts (1)

105-125: Don’t use MissingRequiredOptionError for invalid --api-type.

Line 110-112 throws “missing required option” even when --api-type is present but invalid; that’s misleading for users and makes error handling harder downstream. Consider a dedicated InvalidApiTypeError (or reuse an existing “invalid value” error) and keep MissingRequiredOptionError strictly for absence.

🤖 Fix all issues with AI agents
In @apps/eclair/src/errors.spec.ts:
- Around line 1-151: Add edge-case tests to errors.spec.ts that instantiate each
error class (EclairError, GraphError, RenderingError, LayoutError, ContextError,
CSSModuleError, DOMError, SchemaError) with empty string, whitespace-only
string, a very long string (e.g., 1000+ chars), Unicode (emoji/RTL/combining
chars), and special characters (quotes/backslashes), and assert the .message and
.name behave as expected; for ContextError and CSSModuleError include tests
where hook/provider/class/module names contain special/unicode characters and
verify the constructed message matches the precise formatted string.

In @apps/eclair/src/lib/riviereTestFixtures.ts:
- Around line 26-31: Duplicate class TestAssertionError is declared locally;
instead import the existing TestAssertionError from the shared test-assertions
module and remove the local class declaration. Update the top-of-file imports to
import TestAssertionError and delete the local class TestAssertionError {
constructor(...) { ... } } so all code uses the single canonical
TestAssertionError type.

In @apps/eclair/src/test-assertions.ts:
- Around line 1-6: The TestAssertionError class is duplicated across multiple
test modules; extract it into a shared test utilities package (e.g., export
class TestAssertionError from a new @living-architecture/test-utils) and replace
the local definitions with imports from that package. Create and publish (or add
as a workspace package) the shared module exporting TestAssertionError, update
each test consumer to import { TestAssertionError } instead of redefining it,
and add the new package as a devDependency/workspace dependency in consuming
package.json files and their test build configs.

In @apps/eclair/src/test/setup.ts:
- Line 6: TestAssertionError is duplicated across multiple test modules; remove
the duplicates and consolidate into a single shared test utility that exports
the TestAssertionError class, then update all places that currently define their
own TestAssertionError to import the shared export instead; ensure the shared
module exports the class (named TestAssertionError), preserves its
constructor/signature and any custom properties, update imports in test fixtures
and specs to reference the new shared export, and run tests to verify no type or
import mismatches remain.

In @packages/riviere-builder/src/builder-near-matches.spec.ts:
- Around line 6-11: TestAssertionError is duplicated across multiple test files;
extract it into a single shared test utility and import it instead of
redefining; create a test-utils.ts (or a shared test-utils package) that exports
class TestAssertionError and update local declarations (e.g., in
builder-near-matches.spec.ts) to import { TestAssertionError } from that module,
then remove the duplicate class definitions from the other test files and
replace them with imports.

In @packages/riviere-cli/src/cli.ts:
- Around line 28-42: Update the JSDoc for parsePackageJson to accurately
document the thrown error: replace the generic "@throws Error" with "@throws
{InvalidPackageJsonError}" and add a short description like "when package.json
is invalid or missing version" so callers see that parsePackageJson throws
InvalidPackageJsonError; reference the parsePackageJson function and the
InvalidPackageJsonError type in the docblock.
- Around line 34-42: The parsePackageJson function narrows pkg with a type-guard
but still accesses pkg.version from an unknown; after the initial guard (typeof
pkg !== 'object' || pkg === null || !('version' in pkg')) cast pkg to a concrete
shape like Record<string, unknown> (or an intermediate type) before checking
typeof pkg.version and returning it, so the access is explicit and robust
against future TS narrowing changes; update references inside parsePackageJson
accordingly (pkg, pkg.version, and the InvalidPackageJsonError checks).

In @packages/riviere-cli/src/command-test-fixtures.ts:
- Around line 18-23: TestAssertionError is duplicated across multiple files;
extract it into a single shared test utility module (e.g., export class
TestAssertionError in a new package or shared file) and replace the inline class
definitions with imports; update each location referencing the class
(TestAssertionError in command-test-fixtures.ts, test-assertions.ts,
default-config-fixtures.ts, riviere-graph-fixtures.ts) to import the shared
TestAssertionError and remove the local definition so all code uses the single
exported implementation.

In @packages/riviere-cli/src/commands/builder/add-component.spec.ts:
- Line 14: The test is using the test fixture MockError instead of the real
Error class, which makes the instanceof Error branch of getErrorMessage
untested; update the spec to instantiate and throw a real Error (use new
Error(...)) where MockError is used (references: getErrorMessage, MockError in
add-component.spec.ts) and replace the other occurrence mentioned (line ~355)
similarly so the test validates the production instanceof Error behavior.

In @packages/riviere-cli/src/commands/builder/finalize.spec.ts:
- Around line 57-69: The assertion helpers assertFinalizeSuccess and
assertFinalizeError throw generic TestAssertionError messages; include a short
serialized preview of the received value in those error messages to make
failures actionable. Update assertFinalizeSuccess(value: unknown) and
assertFinalizeError(value: unknown) to, on failure, call TestAssertionError with
a message like "Expected FinalizeSuccessOutput — received: <preview>" (use
JSON.stringify with a try/catch and fallback to String(value) and truncate the
preview if too long). Ensure only the message changes—keep the same type guard
checks and return value behavior.
- Around line 50-55: The test file duplicates the TestAssertionError class;
remove the local class definition in finalize.spec.ts and import the shared
TestAssertionError exported from command-test-fixtures (use the exported symbol
name TestAssertionError), updating the file's imports accordingly so all tests
use the single shared TestAssertionError helper.

In @packages/riviere-cli/src/commands/builder/init-options.spec.ts:
- Around line 29-34: Remove the duplicated local TestAssertionError class and
import the shared one instead: delete the local class definition named
TestAssertionError and add TestAssertionError to the existing import list from
command-test-fixtures in this file so the shared definition is used (update the
existing import statement to include TestAssertionError).

In @packages/riviere-cli/src/commands/extract/config-loader.ts:
- Around line 92-111: The code uses require.resolve directly in
resolvePackagePath (and the other similar site at lines ~122-129), which is
unsafe in ESM and can resolve from the CLI instead of the user project; replace
direct require.resolve with a require created via createRequire() anchored to
the config file/directory: import { createRequire } from 'module', call
createRequire(pathToConfigOrDir) to get a local require, then use that
localRequire.resolve(`${packageName}/package.json`) to find the package.json and
continue as before (keep the same PackageConfigNotFoundError /
PackageResolveError handling); apply the same change to the other occurrence
referenced in the review.
- Around line 51-90: isTopLevelRulesConfig currently treats arrays and arbitrary
objects as valid; tighten it to only accept plain non-array objects by adding an
Array.isArray check, and in parseConfigContent, instead of synthesizing the
"extended" Module directly, run the parsed value through parseExtractionConfig
(and resolveConfig if needed) to validate rule shapes and construct a Module
from the validated config (use parseExtractionConfig/resolveConfig to produce a
module shape or throw ConfigSchemaValidationError), referencing
isTopLevelRulesConfig, parseConfigContent, parseExtractionConfig, resolveConfig,
TopLevelRulesConfig and Module to locate where to apply the checks and
validation.

In @packages/riviere-cli/src/errors.ts:
- Around line 111-116: The InternalSchemaValidationError currently has no debug
context; update the constructor of class InternalSchemaValidationError to accept
an optional context parameter (e.g., configSource: string or details: unknown),
include that context in the error message passed to super (or append it to a new
readonly property like this.context), and set this.name as before; ensure any
code that throws new InternalSchemaValidationError is updated or can pass
undefined so existing behavior remains compatible.

In @packages/riviere-extract-conventions/src/default-config-fixtures.ts:
- Around line 13-18: The TestAssertionError class is duplicated across multiple
modules; remove the local definitions and centralize it by creating or using a
single shared export (e.g., export class TestAssertionError) in a common
test-utilities module, then update each file that currently defines
TestAssertionError to import { TestAssertionError } from that shared module
(replace the local constructor/this.name assignment with the import). Ensure the
shared module exports the same class shape (constructor(message: string) {
super(message); this.name = 'TestAssertionError' }) and update any package
build/test configs so the new test-utilities package is available as a dev/test
dependency.

In @packages/riviere-extract-ts/src/resolve-config.ts:
- Around line 12-13: Document the ConfigLoader contract by expanding the
ConfigLoader type comment to state which errors it may throw (e.g.,
PackageResolveError, ConfigFileNotFoundError), require that it returns a fully
resolved Module including all component rules, and enumerate the validation
responsibilities (schema validation, required fields present, and component rule
resolution). Reference the ConfigLoader type and the Module return type
explicitly and mention that callers expect these specific errors for error
handling and that the loader must perform validation and normalization before
returning the Module.

In @packages/riviere-query/src/riviere-graph-fixtures.ts:
- Around line 12-17: TestAssertionError is duplicated across multiple packages;
extract the class into a shared test utilities module (e.g., add/export
TestAssertionError from @living-architecture/test-utils or a new shared tests
package), remove the local definitions (e.g., the TestAssertionError class in
riviere-graph-fixtures), and update all call sites to import {
TestAssertionError } from the shared module (replace local declarations in
apps/eclair/src/test-assertions.ts,
packages/riviere-cli/src/command-test-fixtures.ts,
packages/riviere-extract-conventions/src/default-config-fixtures.ts, and
packages/riviere-query/src/riviere-graph-fixtures.ts with the centralized
import).

In @packages/riviere-schema/src/component-id.ts:
- Around line 11-19: The InvalidComponentIdError class needs to fix its
prototype and capture the stack so instanceof checks and stack traces work
across targets: inside the constructor of InvalidComponentIdError (and after
calling super) call Object.setPrototypeOf(this,
InvalidComponentIdError.prototype) and, if available, use
Error.captureStackTrace(this, InvalidComponentIdError) to populate the stack;
keep the existing message and name assignment.

Comment thread apps/eclair/src/errors.spec.ts
Comment thread apps/eclair/src/lib/riviereTestFixtures.ts
Comment thread apps/eclair/src/test-assertions.ts
Comment thread apps/eclair/src/test/setup.ts
Comment thread packages/riviere-builder/src/builder-near-matches.spec.ts
Comment thread packages/riviere-cli/src/commands/extract/config-loader.ts
Comment thread packages/riviere-cli/src/errors.ts
Comment thread packages/riviere-extract-conventions/src/default-config-fixtures.ts
Comment thread packages/riviere-extract-ts/src/resolve-config.ts
Comment thread packages/riviere-schema/src/component-id.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-query/src/riviere-graph-fixtures.ts:
- Around line 12-17: The TestAssertionError class is duplicated; extract the
class into a shared test utilities module (e.g., export TestAssertionError from
a new or existing package such as @living-architecture/test-utils), remove the
local class declarations (including the one named TestAssertionError in this
file), export it from the shared package, and update all consumers to import {
TestAssertionError } from that shared package instead of redeclaring the class
so all references (TestAssertionError) use the centralized implementation.

In @packages/riviere-schema/src/index.ts:
- Around line 3-6: Add documentation for RiviereSchemaValidationError to
README.md describing that parseRiviereGraph throws this specific error when
schema validation fails, what fields/details it contains, and recommended
consumer handling (catch by class, inspect validation payload). Add a unit test
in schema.spec.ts that imports RiviereSchemaValidationError and calls
parseRiviereGraph with an invalid graph, then asserts the thrown error is an
instance of RiviereSchemaValidationError (e.g., using instanceof or
framework-specific matchers) and optionally checks its validation payload rather
than only matching the error message.
📜 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 5459156 and 5052eeb.

📒 Files selected for processing (3)
  • packages/riviere-extract-config/src/index.ts
  • packages/riviere-query/src/riviere-graph-fixtures.ts
  • packages/riviere-schema/src/index.ts
🧰 Additional context used
📓 Path-based instructions (5)
packages/riviere-extract-config/**/*.ts

📄 CodeRabbit inference engine (packages/riviere-extract-config/CLAUDE.md)

Extraction config schema is the source of truth for valid structures. TypeScript types must mirror the schema definition to maintain consistency

Files:

  • packages/riviere-extract-config/src/index.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • packages/riviere-extract-config/src/index.ts
  • packages/riviere-schema/src/index.ts
  • packages/riviere-query/src/riviere-graph-fixtures.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-extract-config/src/index.ts
  • packages/riviere-schema/src/index.ts
  • packages/riviere-query/src/riviere-graph-fixtures.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-extract-config/src/index.ts
  • packages/riviere-schema/src/index.ts
  • packages/riviere-query/src/riviere-graph-fixtures.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-extract-config/src/index.ts
  • packages/riviere-schema/src/index.ts
  • packages/riviere-query/src/riviere-graph-fixtures.ts
🧠 Learnings (32)
📓 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/**/*.{ts,tsx} : Use glob pattern matching for module-based organization of extraction rules
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-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
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: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.
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
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: 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-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
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
📚 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-extract-config/src/index.ts
  • packages/riviere-schema/src/index.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-extract-config/src/index.ts
  • packages/riviere-query/src/riviere-graph-fixtures.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-extract-config/src/index.ts
  • packages/riviere-query/src/riviere-graph-fixtures.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-extract-config/src/index.ts
📚 Learning: 2026-01-11T14:38:35.637Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.

Applied to files:

  • packages/riviere-extract-config/src/index.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-extract-config/src/index.ts
  • packages/riviere-schema/src/index.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 `Ignore` decorator to exclude classes or methods from architectural extraction analysis

Applied to files:

  • packages/riviere-extract-config/src/index.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-extract-config/src/index.ts
  • packages/riviere-query/src/riviere-graph-fixtures.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-extract-config/src/index.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 ts-morph for TypeScript AST parsing instead of other parsers

Applied to files:

  • packages/riviere-extract-config/src/index.ts
  • packages/riviere-query/src/riviere-graph-fixtures.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: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted

Applied to files:

  • packages/riviere-extract-config/src/index.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: All validation of extraction config must occur at config load time, not during extraction. Invalid configs should fail fast with clear error messages that include paths and descriptive information

Applied to files:

  • packages/riviere-extract-config/src/index.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-extract-config/src/index.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-schema/src/index.ts
📚 Learning: 2026-01-02T11:58:30.913Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-schema/CLAUDE.md:0-0
Timestamp: 2026-01-02T11:58:30.913Z
Learning: Do not include riviere-schema in breaking change commits (`!` or `BREAKING CHANGE`) - this automatically bumps the major version

Applied to files:

  • packages/riviere-schema/src/index.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 `DomainOp`, `APIEndpoint`, or `EventHandler` method-level decorators to mark individual methods as components

Applied to files:

  • packages/riviere-schema/src/index.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-schema/src/index.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-schema/src/index.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-query/src/riviere-graph-fixtures.ts
📚 Learning: 2026-01-06T08:11:15.403Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 53
File: packages/riviere-extract-config/vitest.config.mts:20-20
Timestamp: 2026-01-06T08:11:15.403Z
Learning: In packages/riviere-extract-config/vitest.config.mts, the explicit tuple type assertion for the reporter configuration (`as ['text', ['lcov', { projectRoot: string }]]`) is necessary because vitest's CoverageReporter type requires the exact tuple shape; neither inference nor 'as const' produces a compatible type.

Applied to files:

  • packages/riviere-query/src/riviere-graph-fixtures.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-query/src/riviere-graph-fixtures.ts
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Assertions must match test titles. If the test claims to verify 'different IDs', assert on the actual ID values—not just count or existence.

Applied to files:

  • packages/riviere-query/src/riviere-graph-fixtures.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: 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.

Applied to files:

  • packages/riviere-query/src/riviere-graph-fixtures.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Avoid implementation coupling in tests. Test behavior, not implementation details. Instead of asserting on mock call arguments with exact SQL, assert on the observable result (e.g., expect(result.user.name).toBe('Alice')).

Applied to files:

  • packages/riviere-query/src/riviere-graph-fixtures.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/apps/*/src/**/*.test.ts : Test fixtures used across multiple test files may be grouped in shared locations (e.g., test-fixtures.ts), but otherwise test files should be co-located with the code they test.

Applied to files:

  • packages/riviere-query/src/riviere-graph-fixtures.ts
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: When hitting max-lines limits, split files into focused modules (e.g., `foo.spec.ts` and `foo.edge-cases.spec.ts`), extract duplicated code into shared modules, or use parameterized tests with `it.each` or `describe.each` instead of removing tests or compressing code.

Applied to files:

  • packages/riviere-query/src/riviere-graph-fixtures.ts
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Use Arrange-Act-Assert structure in tests: (1) Set up test data, (2) Execute the behavior, (3) Verify the outcome.

Applied to files:

  • packages/riviere-query/src/riviere-graph-fixtures.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*-fixtures.ts : Create `<module>-fixtures.ts` fixture files alongside `<module>.spec.ts` to reduce duplication when multiple tests share similar setup data or differ only in specific values being tested.

Applied to files:

  • packages/riviere-query/src/riviere-graph-fixtures.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test violated domain constraints: uniqueness violations (duplicate IDs, emails), missing required relationships (orphaned records), ordering violations (events out of sequence), range breaches (age -1, quantity 1000000), state inconsistencies (shipped but not paid), format mismatches (expected JSON, got XML), and temporal ordering (end before start).

Applied to files:

  • packages/riviere-query/src/riviere-graph-fixtures.ts
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Assert specific values, not types. Use `expect(result).toEqual(['First.', ' Second.'])` not `expect(result).toBeDefined()`. Specific assertions catch specific bugs.

Applied to files:

  • packages/riviere-query/src/riviere-graph-fixtures.ts
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-Fast Error Handling: Validate and throw clear errors instead of using fallback chains. Error format: `Expected [X]. Got [Y]. Context: [debugging info]`

Applied to files:

  • packages/riviere-query/src/riviere-graph-fixtures.ts
🧬 Code graph analysis (1)
packages/riviere-query/src/riviere-graph-fixtures.ts (3)
apps/eclair/src/test-assertions.ts (1)
  • TestAssertionError (1-6)
packages/riviere-cli/src/command-test-fixtures.ts (1)
  • TestAssertionError (18-23)
packages/riviere-extract-conventions/src/default-config-fixtures.ts (1)
  • TestAssertionError (13-18)
⏰ 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 (4)
packages/riviere-extract-config/src/index.ts (2)

2-11: Export hygiene: ensure type-only exports stay type-only.

Nice to see type ValidationError / type ValidationResult exported with type (avoids runtime export bloat). Just ensure ExtractionConfigValidationError is a runtime value export from ./validation (and not accidentally marked type-only), otherwise this will compile but fail at runtime for consumers.


1-11: Removal of fixture exports is safe; no downstream usages detected.

The removal of createMinimalConfig and createMinimalModule re-exports does not cause breaking changes—these symbols are unused throughout the codebase. Test fixtures appear to be in the dedicated validation-fixtures.ts file. Adding ExtractionConfigValidationError to the public API is correct and aligns with the validation-first pattern: it allows downstream code to catch validation failures at load time with clear error information.

packages/riviere-query/src/riviere-graph-fixtures.ts (1)

152-152: LGTM!

Using TestAssertionError provides a distinct error type for test assertion failures, making it easier to distinguish from generic errors and improving error handling specificity.

packages/riviere-schema/src/index.ts (1)

9-9: Export is correct and well-implemented.

InvalidComponentIdError is properly documented and its throwing behavior is validated by tests. The error message follows the fail-fast convention with context (the invalid ID and expected format). However, the test suite validates implicit error throwing but lacks an explicit example showing consumers how to import and catch this error—consider adding a test case that demonstrates the catch pattern if this error is intended for external consumers.

Comment thread packages/riviere-query/src/riviere-graph-fixtures.ts
Comment thread packages/riviere-schema/src/index.ts
- Use createRequire() anchored to config directory for ESM-safe package resolution
- Fix isTopLevelRulesConfig() to reject arrays
- Add test coverage for useRequiredGraph error path
- Export useRequiredGraph for testability

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/eclair/src/App.tsx (1)

19-29: Good specialization + clearer failure mode for “graph missing”, but consider relocating the hook
Exporting useRequiredGraph() and throwing GraphError when graph === null is a nice upgrade in consistency and debuggability. However, exporting it from App.tsx couples a reusable hook to an app-entry module—consider moving it to apps/eclair/src/contexts/GraphContext.tsx (or a hooks/ module) and re-exporting from there to keep layering clean.

🤖 Fix all issues with AI agents
In @packages/riviere-cli/src/commands/extract/config-loader.ts:
- Around line 58-93: parseConfigContent currently calls resolveConfig(config)
without a ConfigLoader, causing nested "extends" to fail; update
parseConfigContent to accept a loader parameter (e.g., configLoader:
ConfigLoader) and pass it into resolveConfig as resolveConfig(config,
configLoader). Update any callers of parseConfigContent to provide the same
loader (or thread the loader through from where parseConfigContent is invoked),
ensuring parseExtractionConfig and the subsequent code paths remain unchanged
except for the added loader argument so nested/extended modules can be resolved
correctly.
📜 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 5052eeb and 1269284.

📒 Files selected for processing (3)
  • apps/eclair/src/App.spec.tsx
  • apps/eclair/src/App.tsx
  • packages/riviere-cli/src/commands/extract/config-loader.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:

  • apps/eclair/src/App.tsx
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • apps/eclair/src/App.spec.tsx
**/*.{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:

  • apps/eclair/src/App.tsx
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • apps/eclair/src/App.spec.tsx
**/*.{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:

  • apps/eclair/src/App.tsx
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • apps/eclair/src/App.spec.tsx
**/*.{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:

  • apps/eclair/src/App.tsx
  • packages/riviere-cli/src/commands/extract/config-loader.ts
  • apps/eclair/src/App.spec.tsx
🧠 Learnings (39)
📓 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/**/*.{ts,tsx} : Use glob pattern matching for module-based organization of extraction rules
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: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.
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-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
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
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: 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-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
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
📚 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/config-loader.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/config-loader.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/config-loader.ts
📚 Learning: 2026-01-11T14:38:35.637Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.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/config-loader.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/config-loader.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/config-loader.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/config-loader.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/config-loader.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 (*.spec.ts, *.test.ts), type guards like `isExtractionOutput(value: unknown): value is ExtractionOutput` should focus on narrowing types for TypeScript rather than comprehensive validation. Actual shape validation is handled through explicit test assertions (e.g., `expect(result).toMatchObject(...)`). This keeps type guards simple while maintaining thorough validation through assertion-based testing.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx} : Parse, don't validate. Use Zod schemas at system boundaries to parse external data once. Don't scatter `isX(unknown): x is T` type guards throughout the codebase.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.ts
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-Fast Error Handling: Validate and throw clear errors instead of using fallback chains. Error format: `Expected [X]. Got [Y]. Context: [debugging info]`

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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} : Avoid dangerous fallback values that hide bugs. Do not use `??` or `||` operators without clear reason for providing defaults. If a value is required, make it required rather than guessing at defaults. Exceptions: optional parameters with documented defaults, configuration with explicit optional semantics, and test data with placeholder values.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-fast over silent fallbacks. Never use fallback chains (`value ?? backup ?? 'unknown'`). If data should exist, validate and throw a clear error.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-06T08:11:15.403Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 53
File: packages/riviere-extract-config/vitest.config.mts:20-20
Timestamp: 2026-01-06T08:11:15.403Z
Learning: In packages/riviere-extract-config/vitest.config.mts, the explicit tuple type assertion for the reporter configuration (`as ['text', ['lcov', { projectRoot: string }]]`) is necessary because vitest's CoverageReporter type requires the exact tuple shape; neither inference nor 'as const' produces a compatible type.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Never parse error message strings to determine error types or extract information using `.message.includes()`, `.message.startsWith()`, or regex patterns on `error.message`. Use typed custom error classes instead.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : When parsing strings in exception messages is 100% unavoidable (e.g., due to third-party library limitations), document the exception with justification, reference tracking issue, and note that upstream fix was requested.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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: All validation of extraction config must occur at config load time, not during extraction. Invalid configs should fail fast with clear error messages that include paths and descriptive information

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx} : Use Zod for runtime validation. In TypeScript, use Zod schemas for parsing external data, API responses, and user input. Type inference from schemas keeps types and validation in sync.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test violated domain constraints: uniqueness violations (duplicate IDs, emails), missing required relationships (orphaned records), ordering violations (events out of sequence), range breaches (age -1, quantity 1000000), state inconsistencies (shipped but not paid), format mismatches (expected JSON, got XML), and temporal ordering (end before start).

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.ts
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Applies to **/*.{ts,tsx} : Use cross-project imports with package names (e.g., `import { X } from 'living-architecture/[pkg-name]'`) rather than relative paths

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.ts
  • apps/eclair/src/App.spec.tsx
📚 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/config-loader.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/config-loader.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: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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} : Check lint rules (eslint.config.mjs) before providing feedback to ensure suggestions don't contradict lint rules. Never suggest using banned keywords like 'as' or 'let'.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.ts
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Do not modify root configuration files (eslint.config.mjs, tsconfig.base.json, nx.json, vite.config, vitest.config.mts); provide suggested changes and ask the user before modifying

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.ts
  • apps/eclair/src/App.spec.tsx
📚 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/apps/*/package.json : When importing from another project, add explicit workspace dependencies to package.json using the format "living-architecture/[pkg-name]": "workspace:*" and run pnpm install.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/packages/*/package.json : When importing from another project, add explicit workspace dependencies to package.json using the format "living-architecture/[pkg-name]": "workspace:*" and run pnpm install.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/apps/*/vitest.config.ts : Each app must include a vitest.config.ts file with 100% coverage thresholds for test configuration.

Applied to files:

  • apps/eclair/src/App.spec.tsx
📚 Learning: 2026-01-08T06:46:05.503Z
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:05.503Z
Learning: In test files using typescript-eslint/rule-tester's RuleTester.run(), include an explicit it() block with an 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.

Applied to files:

  • apps/eclair/src/App.spec.tsx
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Use Arrange-Act-Assert structure in tests: (1) Set up test data, (2) Execute the behavior, (3) Verify the outcome.

Applied to files:

  • apps/eclair/src/App.spec.tsx
📚 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:

  • apps/eclair/src/App.spec.tsx
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Avoid implementation coupling in tests. Test behavior, not implementation details. Instead of asserting on mock call arguments with exact SQL, assert on the observable result (e.g., expect(result.user.name).toBe('Alice')).

Applied to files:

  • apps/eclair/src/App.spec.tsx
🧬 Code graph analysis (2)
apps/eclair/src/App.tsx (2)
apps/eclair/src/contexts/GraphContext.tsx (1)
  • useGraph (131-137)
apps/eclair/src/errors.ts (1)
  • GraphError (14-19)
apps/eclair/src/App.spec.tsx (3)
apps/eclair/src/App.tsx (1)
  • useRequiredGraph (21-29)
apps/eclair/src/contexts/GraphContext.tsx (1)
  • GraphProvider (70-129)
apps/eclair/src/errors.ts (1)
  • GraphError (14-19)
⏰ 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). (4)
  • GitHub Check: main
  • GitHub Check: browser-tests (firefox)
  • GitHub Check: browser-tests (webkit)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (6)
apps/eclair/src/App.tsx (1)

1-7: Import formatting-only change
No functional impact here.

apps/eclair/src/App.spec.tsx (2)

10-16: Import additions look fine
No concerns with importing useRequiredGraph and GraphError for behavioral testing.


179-209: Tests are correctly structured and don't require console.error handling adjustments.

The tests assert on both error type and message as expected. The Vitest configuration does not enforce console.error as a test failure, and no such handling is configured in the test setup. These tests appropriately validate behavior (error type and message) rather than implementation details, following the repo's testing conventions.

Likely an incorrect or invalid review comment.

packages/riviere-cli/src/commands/extract/config-loader.ts (3)

1-30: LGTM! Clean imports and type definitions.

The imports follow workspace conventions using @living-architecture/ package names, and the TopLevelRulesConfig interface appropriately models the simplified config format with optional component rules.


32-56: LGTM! Typed errors and focused type guards.

The custom PackageConfigNotFoundError follows the pattern of using typed error classes. The type guards (hasModulesArray and isTopLevelRulesConfig) perform minimal validation for type narrowing, with comprehensive validation handled downstream by schema validators per established patterns.


95-134: LGTM! Robust package resolution and clean factory pattern.

The implementation is well-structured:

  • isPackageReference provides a clear heuristic for distinguishing package names from file paths
  • resolvePackagePath correctly uses createRequire anchored to the config directory for ESM-safe resolution
  • Error handling properly distinguishes between "package not found" and "package found but missing config"
  • The factory function is clean and focused

The use of resolve(configDir, 'package.json') as the anchor point for createRequire (line 100) is clever—it doesn't require the file to exist, just uses the directory as the resolution starting point.

Comment thread packages/riviere-cli/src/commands/extract/config-loader.ts
Add tests to verify ContextError is thrown with correct type and
message when context hooks are used outside their providers:
- ExportContext: useExport outside ExportProvider
- GraphContext: useGraph outside GraphProvider

Addresses SonarCloud coverage for error throw statements.

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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/eclair/src/contexts/GraphContext.spec.tsx (1)

163-181: Combine redundant tests into a single assertion.

Both tests verify the same error condition (useGraph outside provider) with identical setup. The first checks the error type, the second checks the message. They can be combined into a single test that verifies both properties, eliminating duplicate console mocking and render calls.

♻️ Combine into a single test
-  it('throws ContextError when useGraph called outside provider', () => {
-    const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
-
-    expect(() => {
-      render(<TestConsumer />)
-    }).toThrow(ContextError)
-
-    consoleError.mockRestore()
-  })
-
-  it('throws with descriptive message when useGraph called outside provider', () => {
+  it('throws ContextError with descriptive message when useGraph called outside provider', () => {
     const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
 
-    expect(() => {
+    let thrownError: Error | undefined
+    try {
       render(<TestConsumer />)
-    }).toThrow('useGraph must be used within a GraphProvider')
+    } catch (error) {
+      thrownError = error as Error
+    }
+
+    expect(thrownError).toBeInstanceOf(ContextError)
+    expect(thrownError?.message).toBe('useGraph must be used within a GraphProvider')
 
     consoleError.mockRestore()
   })
📜 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 1269284 and a1bbe5b.

📒 Files selected for processing (2)
  • apps/eclair/src/contexts/ExportContext.spec.tsx
  • apps/eclair/src/contexts/GraphContext.spec.tsx
🧰 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:

  • apps/eclair/src/contexts/ExportContext.spec.tsx
  • apps/eclair/src/contexts/GraphContext.spec.tsx
**/*.{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:

  • apps/eclair/src/contexts/ExportContext.spec.tsx
  • apps/eclair/src/contexts/GraphContext.spec.tsx
**/*.{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:

  • apps/eclair/src/contexts/ExportContext.spec.tsx
  • apps/eclair/src/contexts/GraphContext.spec.tsx
**/*.{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:

  • apps/eclair/src/contexts/ExportContext.spec.tsx
  • apps/eclair/src/contexts/GraphContext.spec.tsx
🧠 Learnings (8)
📓 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/**/*.{ts,tsx} : Use glob pattern matching for module-based organization of extraction rules
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: 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-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
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: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.
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
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
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*.ts : Use the Rivière Builder Node.js library to programmatically construct the schema graph when implementing custom extraction code
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: All validation of extraction config must occur at config load time, not during extraction. Invalid configs should fail fast with clear error messages that include paths and descriptive information
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: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted
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.
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-Fast Error Handling: Validate and throw clear errors instead of using fallback chains. Error format: `Expected [X]. Got [Y]. Context: [debugging info]`

Applied to files:

  • apps/eclair/src/contexts/ExportContext.spec.tsx
  • apps/eclair/src/contexts/GraphContext.spec.tsx
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test violated domain constraints: uniqueness violations (duplicate IDs, emails), missing required relationships (orphaned records), ordering violations (events out of sequence), range breaches (age -1, quantity 1000000), state inconsistencies (shipped but not paid), format mismatches (expected JSON, got XML), and temporal ordering (end before start).

Applied to files:

  • apps/eclair/src/contexts/ExportContext.spec.tsx
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test domain-specific edge cases: email (valid formats, plus signs, subdomains), URLs (protocols, ports, special characters, relative paths), phone numbers (international formats, extensions), addresses (Unicode, multi-line, missing components), currency (rounding, different currencies, zero amounts), percentages (0%, 100%, over 100%).

Applied to files:

  • apps/eclair/src/contexts/ExportContext.spec.tsx
📚 Learning: 2026-01-08T06:46:05.503Z
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:05.503Z
Learning: In test files using typescript-eslint/rule-tester's RuleTester.run(), include an explicit it() block with an 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.

Applied to files:

  • apps/eclair/src/contexts/ExportContext.spec.tsx
📚 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:

  • apps/eclair/src/contexts/GraphContext.spec.tsx
📚 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:

  • apps/eclair/src/contexts/GraphContext.spec.tsx
📚 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:

  • apps/eclair/src/contexts/GraphContext.spec.tsx
🧬 Code graph analysis (2)
apps/eclair/src/contexts/ExportContext.spec.tsx (1)
apps/eclair/src/errors.ts (1)
  • ContextError (44-49)
apps/eclair/src/contexts/GraphContext.spec.tsx (1)
apps/eclair/src/errors.ts (1)
  • ContextError (44-49)
⏰ 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). (4)
  • GitHub Check: browser-tests (webkit)
  • GitHub Check: browser-tests (firefox)
  • GitHub Check: main
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (3)
apps/eclair/src/contexts/GraphContext.spec.tsx (1)

19-19: LGTM!

The ContextError import is correctly added and necessary for the updated test assertions.

apps/eclair/src/contexts/ExportContext.spec.tsx (2)

10-10: LGTM: Correct import of new error type.

The import correctly uses the @ alias and brings in the ContextError class needed for the new test assertions.


128-138: Consider consolidating error validation tests.

Both tests validate the same error condition (using useExport outside the provider) but check different aspects—one validates the error type, the other validates the message. While the current approach is clear and valid, consolidating them would reduce redundancy and improve test organization.

♻️ Proposed consolidation
- it('throws ContextError when useExport is used outside ExportProvider', () => {
-   expect(() => {
-     render(<TestConsumer />)
-   }).toThrow(ContextError)
- })
-
- it('throws with descriptive message when used outside provider', () => {
-   expect(() => {
-     render(<TestConsumer />)
-   }).toThrow('useExport must be used within a ExportProvider')
- })
+ it('throws ContextError with descriptive message when used outside provider', () => {
+   const renderOutsideProvider = () => render(<TestConsumer />)
+   
+   expect(renderOutsideProvider).toThrow(ContextError)
+   expect(renderOutsideProvider).toThrow('useExport must be used within a ExportProvider')
+ })
⛔ Skipped due to learnings
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : One concept per test. Each test verifies one behavior. If you need 'and' in your test name, split it into multiple tests.
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.
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:05.503Z
Learning: In test files using typescript-eslint/rule-tester's RuleTester.run(), include an explicit it() block with an 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.
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-Fast Error Handling: Validate and throw clear errors instead of using fallback chains. Error format: `Expected [X]. Got [Y]. Context: [debugging info]`

NTCoding and others added 2 commits January 11, 2026 17:12
Update tests to verify error classes are thrown with correct types,
not just matching messages. This ensures custom error class
constructors are covered:

- ConfigFileNotFoundError, InvalidConfigFormatError,
  ConfigSchemaValidationError, PackageResolveError (riviere-cli)
- InvalidComponentIdError (riviere-schema)
- RiviereSchemaValidationError (riviere-schema)
- ExtractionConfigValidationError (riviere-extract-config)

Addresses SonarCloud coverage for error class definitions.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add SchemaError tests for invalid date format validation
- Add LayoutError tests for DomainConnectionDiff missing domains
- Add LayoutError class assertions in GraphRenderingSetup tests
- Add v8 ignore comments for unreachable defensive code in:
  - compareGraphs.ts (Map.get after Map.set)
  - SchemaModal.tsx (CSS module and button disabled guards)
  - GraphRenderingSetup.ts (D3 callback error guards)

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: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/riviere-schema/src/component-id.spec.ts (1)

49-70: Consider reducing redundancy in error assertions.

The tests correctly verify both error type and message, but each test invokes ComponentId.parse() twice. Consider capturing the error once to improve efficiency:

♻️ Optional refactor to reduce redundant function calls
 it('throws InvalidComponentIdError on invalid format with too few segments', () => {
-  expect(() => ComponentId.parse('orders:checkout')).toThrow(InvalidComponentIdError)
-  expect(() => ComponentId.parse('orders:checkout')).toThrow(
-    "Invalid component ID format: 'orders:checkout'. Expected 'domain:module:type:name'",
-  )
+  let error: Error | undefined
+  try {
+    ComponentId.parse('orders:checkout')
+  } catch (e) {
+    error = e as Error
+  }
+  expect(error).toBeInstanceOf(InvalidComponentIdError)
+  expect(error?.message).toBe(
+    "Invalid component ID format: 'orders:checkout'. Expected 'domain:module:type:name'"
+  )
 })

Apply the same pattern to the other two test cases.

Additionally, consider adding tests for edge cases like empty segments ("orders::domainop:place-order"), whitespace-only segments, and special characters to strengthen validation coverage.

apps/eclair/src/components/SchemaModal/SchemaModal.tsx (2)

16-48: Module-level initialization with throws prevents graceful error handling.

The jsonViewStyles object is initialized at module level (lines 25-48) by calling getStyle, which can throw CSSModuleError. If a CSS class is missing at runtime, the error will be thrown during module load—before React error boundaries can catch it—potentially making the entire module unloadable and breaking the app.

While the v8 ignore comment indicates this is defensive and should only happen during development, runtime safeguards are valuable. Consider one of these alternatives:

  1. Lazy initialization: Move jsonViewStyles into a function called during render
  2. Safe fallback: Return a default/empty class name instead of throwing
  3. Remove the check: If CSS modules are guaranteed to be validated at build time
♻️ Alternative: Lazy initialization
-const jsonViewStyles = {
-  container: getStyle('jsonContainer'),
-  basicChildStyle: getStyle('jsonBasicChild'),
-  label: getStyle('jsonLabel'),
-  clickableLabel: getStyle('jsonClickableLabel'),
-  nullValue: getStyle('jsonNull'),
-  undefinedValue: getStyle('jsonUndefined'),
-  numberValue: getStyle('jsonNumber'),
-  stringValue: getStyle('jsonString'),
-  booleanValue: getStyle('jsonBoolean'),
-  otherValue: getStyle('jsonOther'),
-  punctuation: getStyle('jsonPunctuation'),
-  expandIcon: getStyle('jsonExpandIcon'),
-  collapseIcon: getStyle('jsonCollapseIcon'),
-  collapsedContent: getStyle('jsonCollapsedContent'),
-  childFieldsContainer: getStyle('jsonChildFields'),
-  quotesForFieldNames: true,
-  noQuotesForStringValues: false,
-  stringifyStringValues: false,
-  ariaLables: {
-    collapseJson: 'Collapse JSON node',
-    expandJson: 'Expand JSON node',
-  },
-}
+function getJsonViewStyles() {
+  return {
+    container: getStyle('jsonContainer'),
+    basicChildStyle: getStyle('jsonBasicChild'),
+    label: getStyle('jsonLabel'),
+    clickableLabel: getStyle('jsonClickableLabel'),
+    nullValue: getStyle('jsonNull'),
+    undefinedValue: getStyle('jsonUndefined'),
+    numberValue: getStyle('jsonNumber'),
+    stringValue: getStyle('jsonString'),
+    booleanValue: getStyle('jsonBoolean'),
+    otherValue: getStyle('jsonOther'),
+    punctuation: getStyle('jsonPunctuation'),
+    expandIcon: getStyle('jsonExpandIcon'),
+    collapseIcon: getStyle('jsonCollapseIcon'),
+    collapsedContent: getStyle('jsonCollapsedContent'),
+    childFieldsContainer: getStyle('jsonChildFields'),
+    quotesForFieldNames: true,
+    noQuotesForStringValues: false,
+    stringifyStringValues: false,
+    ariaLables: {
+      collapseJson: 'Collapse JSON node',
+      expandJson: 'Expand JSON node',
+    },
+  }
+}

Then update line 231:

-<JsonView data={graph} shouldExpandNode={shouldExpandNode} style={jsonViewStyles} />
+<JsonView data={graph} shouldExpandNode={shouldExpandNode} style={getJsonViewStyles()} />

114-126: Consider more robust date validation.

formatGeneratedDate only checks that a non-empty string exists before the 'T' separator, but doesn't validate the actual date format. Invalid dates like "INVALID-DATET10:30:00Z" would pass this check.

Since this is for display and the data comes from generated schemas (which should produce valid ISO strings), the current validation may be sufficient. However, for more robust error detection, consider parsing the date:

♻️ More robust validation
 function formatGeneratedDate(isoDateString: string | undefined): string {
   if (isoDateString === undefined) {
     return 'Unknown'
   }
   const parts = isoDateString.split('T')
   const datePart = parts[0]
   if (datePart === undefined || datePart === '') {
     throw new SchemaError(
       `Invalid ISO date string: "${isoDateString}". Expected format like "2024-01-15T10:30:00Z".`,
     )
   }
+  // Validate the date part is actually a valid date
+  const dateObj = new Date(datePart)
+  if (Number.isNaN(dateObj.getTime())) {
+    throw new SchemaError(
+      `Invalid ISO date string: "${isoDateString}". Date part "${datePart}" is not a valid date.`,
+    )
+  }
   return datePart
 }
🤖 Fix all issues with AI agents
In @apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx:
- Around line 105-119: The generated date validation tests only cover one
empty-date case; add explicit edge-case tests inside the describe('generated
date validation') block using createTestGraph() and renderSchemaModalWithGraph()
to assert correct behavior for: a) missing 'T' separator (e.g., '2024-01-15') —
expect the component to render the date string, b) multiple 'T' separators
(e.g., '2024-01-15TT10:30:00Z') — expect a SchemaError or the existing 'Invalid
ISO date string' error, c) empty string ('') — expect a SchemaError, and d)
time-only strings like 'T' or '10:30:00Z' — expect a SchemaError; ensure each
test uses the same patterns as existing tests (expect(() =>
renderSchemaModalWithGraph(graph)).toThrow(... ) or screen.getByText(...)) and
references formatGeneratedDate behavior indirectly by exercising the component.

In @apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx:
- Around line 400-421: Rename and clarify the existing test in
DomainConnectionDiff.spec.tsx to state it checks for a missing domain (not
“position”), update the expectation to assert the LayoutError (or its
descriptive message) when a connection references a missing target domain using
createMinimalDiff and render(<DomainConnectionDiff diff={diff} />); then add a
symmetric test named like "throws LayoutError when connection references missing
source domain" that constructs a diff with a missing source (e.g., source:
'nonexistent-source', target: 'payments') and asserts that rendering
DomainConnectionDiff throws LayoutError.
- Around line 378-422: Remove the redundant test that only asserts the error
type and consolidate into a single test that both verifies the thrown error is a
LayoutError and that its message is "Edge references missing position";
specifically, delete the first it(...) that asserts only toThrow(LayoutError)
and update the remaining test for the missing position case to capture the
render call (e.g., const fn = () => render(<DomainConnectionDiff diff={diff}
/>)) and then assert expect(fn).toThrow(LayoutError) and
expect(fn).toThrow('Edge references missing position'), keeping identifiers like
DomainConnectionDiff, createMinimalDiff and LayoutError to locate the test.

In @packages/riviere-cli/src/commands/extract/config-loader.spec.ts:
- Around line 26-111: Add edge-case tests to the createConfigLoader test suite
to cover malformed JSON, path traversal, special characters in paths, and file
read errors: write tests that (1) mock existsSync to true and readFileSync to
return malformed JSON and assert it throws InvalidConfigFormatError; (2) call
createConfigLoader('./') with inputs like '../../../etc/passwd' and
Windows-style backslashes and assert the loader either throws
ConfigFileNotFoundError or a security-related error (ensuring the resolved path
does not escape the project root); (3) pass paths containing Unicode, spaces,
and special characters and assert correct resolution or safe rejection; and (4)
mock readFileSync to throw (e.g., EACCES) and assert the loader surfaces an
error (expect a thrown error), referencing createConfigLoader,
InvalidConfigFormatError, and ConfigFileNotFoundError to locate the relevant
code paths.
- Around line 224-242: The test currently only asserts result.api; update the
test that calls createConfigLoader('/project') and
loader('@living-architecture/riviere-extract-conventions') to also assert that
the returned Module includes all six component keys with defaults of notUsed:
true for those not specified. Specifically, after the existing
expect(result.api) assertion, add assertions that result.{componentName} (for
the other five component types plus any top-level types expected by the Module
shape) exist and equal an object with notUsed: true, referencing the same result
variable and the createConfigLoader/loader call to locate the code to modify.

In @packages/riviere-schema/src/schema.spec.ts:
- Around line 141-142: Capture the thrown error from a single call to
parseRiviereGraph(input) and assert both its type and message on that captured
error instead of calling parseRiviereGraph twice; e.g., invoke
parseRiviereGraph(input) inside a try/catch (or use Jest’s function-capturing
pattern to get the error), store the error, then assert it is an instance of
RiviereSchemaValidationError and that its message matches /Invalid
RiviereGraph/.
- Around line 104-105: The test currently calls parseRiviereGraph(input) twice;
capture the thrown error once and assert both its type and message on that
single error object: call parseRiviereGraph(input) inside a try/catch (or use
Jest's toThrowError to get the thrown error) and then assert error is instance
of RiviereSchemaValidationError and that error.message matches /Invalid
RiviereGraph/ (referencing parseRiviereGraph and RiviereSchemaValidationError).
- Around line 122-123: The test currently uses a permissive regex
(/version|Invalid RiviereGraph/i) so it passes if either term appears; update
the second assertion in the spec that calls parseRiviereGraph to assert the
error mentions "version" specifically (e.g., expect(() =>
parseRiviereGraph(input)).toThrow(/version/i)) or, if you want both terms
present, use a stricter regex that requires both substrings in any order (e.g.,
match "version" and "Invalid RiviereGraph" together) while still expecting
RiviereSchemaValidationError from parseRiviereGraph.
📜 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 a1bbe5b and d527978.

📒 Files selected for processing (10)
  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
  • apps/eclair/src/features/comparison/compareGraphs.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.spec.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.spec.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • packages/riviere-extract-config/src/validation.spec.ts
  • apps/eclair/src/features/comparison/compareGraphs.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.spec.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
**/*.{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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • packages/riviere-extract-config/src/validation.spec.ts
  • apps/eclair/src/features/comparison/compareGraphs.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.spec.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
**/*.{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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • packages/riviere-extract-config/src/validation.spec.ts
  • apps/eclair/src/features/comparison/compareGraphs.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.spec.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
**/*.{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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • packages/riviere-extract-config/src/validation.spec.ts
  • apps/eclair/src/features/comparison/compareGraphs.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.spec.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
packages/riviere-extract-config/**/*.ts

📄 CodeRabbit inference engine (packages/riviere-extract-config/CLAUDE.md)

Extraction config schema is the source of truth for valid structures. TypeScript types must mirror the schema definition to maintain consistency

Files:

  • packages/riviere-extract-config/src/validation.spec.ts
🧠 Learnings (42)
📓 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/**/*.{ts,tsx} : Use glob pattern matching for module-based organization of extraction rules
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: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.
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-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
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: 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
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-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
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} : Compose detection rules via and/or logic for predicates
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: All validation of extraction config must occur at config load time, not during extraction. Invalid configs should fail fast with clear error messages that include paths and descriptive information
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: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted
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
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for dates and times: leap years (Feb 29), daylight saving transitions, timezone boundaries, midnight (00:00:00), end of day (23:59:59), year boundaries, invalid dates (Feb 30, Month 13), Unix epoch edge cases, and far future/past dates.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test violated domain constraints: uniqueness violations (duplicate IDs, emails), missing required relationships (orphaned records), ordering violations (events out of sequence), range breaches (age -1, quantity 1000000), state inconsistencies (shipped but not paid), format mismatches (expected JSON, got XML), and temporal ordering (end before start).

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • packages/riviere-schema/src/component-id.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • apps/eclair/src/features/comparison/compareGraphs.ts
  • packages/riviere-schema/src/schema.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • packages/riviere-cli/src/commands/extract/config-loader.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-extract-config/src/validation.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.spec.ts
📚 Learning: 2026-01-11T14:38:35.637Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.

Applied to files:

  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/schema.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: 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.

Applied to files:

  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.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-extract-config/src/validation.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-extract-config/src/validation.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-extract-config/src/validation.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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-extract-config/src/validation.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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: All validation of extraction config must occur at config load time, not during extraction. Invalid configs should fail fast with clear error messages that include paths and descriptive information

Applied to files:

  • packages/riviere-extract-config/src/validation.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: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted

Applied to files:

  • packages/riviere-extract-config/src/validation.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-extract-config/src/validation.spec.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*-fixtures.ts : Create `<module>-fixtures.ts` fixture files alongside `<module>.spec.ts` to reduce duplication when multiple tests share similar setup data or differ only in specific values being tested.

Applied to files:

  • packages/riviere-extract-config/src/validation.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.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-extract-config/src/validation.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.spec.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.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-extract-config/src/validation.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.spec.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.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-extract-config/src/validation.spec.ts
  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.spec.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.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/config-loader.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 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/config-loader.spec.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test domain-specific edge cases: email (valid formats, plus signs, subdomains), URLs (protocols, ports, special characters, relative paths), phone numbers (international formats, extensions), addresses (Unicode, multi-line, missing components), currency (rounding, different currencies, zero amounts), percentages (0%, 100%, over 100%).

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • packages/riviere-schema/src/component-id.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for string inputs: empty string, whitespace-only strings, very long strings (10K+ characters), Unicode (emojis, RTL text, combining characters), special characters (quotes, backslashes, null bytes), SQL/HTML/script injection patterns, and leading/trailing whitespace.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 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/packages/*/vitest.config.ts : Each package must include a vitest.config.ts file with 100% coverage thresholds for test configuration.

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.spec.ts
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Applies to **/vitest.config.ts : When creating new projects with tests, add vitest.config.ts with 100% coverage as the default

Applied to files:

  • packages/riviere-cli/src/commands/extract/config-loader.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/config-loader.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: 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-schema/src/component-id.spec.ts
  • packages/riviere-schema/src/schema.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: Applies to packages/riviere-extract-conventions/**/*.ts : Use `UseCase`, `Event`, or `UI` class-level decorators to mark the class itself as a component

Applied to files:

  • packages/riviere-schema/src/component-id.spec.ts
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for number inputs: zero, negative numbers, very large/small numbers (near MAX/MIN_SAFE_INTEGER), decimal precision (0.1 + 0.2), NaN, Infinity/-Infinity, and boundary values (off-by-one at limits).

Applied to files:

  • packages/riviere-schema/src/component-id.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Assertions must match test titles. If the test claims to verify 'different IDs', assert on the actual ID values—not just count or existence.

Applied to files:

  • packages/riviere-schema/src/component-id.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 Learning: 2026-01-02T11:58:30.913Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: packages/riviere-schema/CLAUDE.md:0-0
Timestamp: 2026-01-02T11:58:30.913Z
Learning: Do not include riviere-schema in breaking change commits (`!` or `BREAKING CHANGE`) - this automatically bumps the major version

Applied to files:

  • packages/riviere-schema/src/schema.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 ts-morph for TypeScript AST parsing instead of other parsers

Applied to files:

  • packages/riviere-schema/src/schema.spec.ts
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-Fast Error Handling: Validate and throw clear errors instead of using fallback chains. Error format: `Expected [X]. Got [Y]. Context: [debugging info]`

Applied to files:

  • packages/riviere-schema/src/schema.spec.ts
  • apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.spec.ts
  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for collections (arrays, objects, maps): empty collections, single element, duplicates, nested structures, circular references, very large collections (performance), sparse arrays, and mixed types.

Applied to files:

  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test null and undefined inputs: null input, undefined input, missing optional properties, and explicit undefined vs missing key.

Applied to files:

  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 Learning: 2026-01-08T06:46:05.503Z
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:05.503Z
Learning: In test files using typescript-eslint/rule-tester's RuleTester.run(), include an explicit it() block with an 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.

Applied to files:

  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Avoid implementation coupling in tests. Test behavior, not implementation details. Instead of asserting on mock call arguments with exact SQL, assert on the observable result (e.g., expect(result.user.name).toBe('Alice')).

Applied to files:

  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Use Arrange-Act-Assert structure in tests: (1) Set up test data, (2) Execute the behavior, (3) Verify the outcome.

Applied to files:

  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Assert specific values, not types. Use `expect(result).toEqual(['First.', ' Second.'])` not `expect(result).toBeDefined()`. Specific assertions catch specific bugs.

Applied to files:

  • apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
🧬 Code graph analysis (6)
apps/eclair/src/components/SchemaModal/SchemaModal.tsx (1)
apps/eclair/src/errors.ts (2)
  • CSSModuleError (54-59)
  • SchemaError (74-79)
apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx (2)
apps/eclair/src/components/SchemaModal/SchemaModal.tsx (1)
  • SchemaModal (57-237)
apps/eclair/src/errors.ts (1)
  • SchemaError (74-79)
apps/eclair/src/features/comparison/compareGraphs.ts (1)
apps/eclair/src/errors.ts (1)
  • GraphError (14-19)
apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.ts (1)
apps/eclair/src/errors.ts (2)
  • LayoutError (34-39)
  • RenderingError (24-29)
packages/riviere-cli/src/commands/extract/config-loader.spec.ts (2)
packages/riviere-cli/src/commands/extract/config-loader.ts (1)
  • createConfigLoader (126-134)
packages/riviere-cli/src/errors.ts (4)
  • ConfigFileNotFoundError (99-109)
  • InvalidConfigFormatError (71-84)
  • ConfigSchemaValidationError (64-69)
  • PackageResolveError (86-97)
apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.spec.ts (2)
apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.ts (1)
  • extractCoordinates (35-44)
apps/eclair/src/errors.ts (1)
  • LayoutError (34-39)
⏰ 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). (4)
  • GitHub Check: Cloudflare Pages
  • GitHub Check: browser-tests (webkit)
  • GitHub Check: browser-tests (firefox)
  • GitHub Check: main
🔇 Additional comments (20)
apps/eclair/src/features/comparison/compareGraphs.ts (3)

4-4: LGTM! Domain-specific error import added.

The import of GraphError enhances error specificity for graph operations and aligns with the new error hierarchy introduced in this PR.


207-217: LGTM! Defensive check with appropriate coverage annotation.

The defensive undefined check at lines 213-215 correctly handles TypeScript's type system constraints while documenting that this code path should be unreachable in practice. The v8 coverage directive appropriately excludes this defensive code from coverage metrics.


214-214: LGTM! Error type upgraded to domain-specific GraphError.

Replacing generic Error with GraphError improves error specificity and enables more precise error handling for graph operations.

apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.spec.ts (1)

12-12: LGTM! Error type assertions correctly updated.

The test updates properly reflect the implementation's use of LayoutError for coordinate validation failures. The assertions now check for the specific error type rather than generic errors, which improves type safety and error handling clarity.

Optional: Consider validating error messages

For more thorough testing, you could also validate the error message content:

-expect(() => extractCoordinates(nodes, 'x')).toThrow(LayoutError)
+expect(() => extractCoordinates(nodes, 'x')).toThrow(
+  new LayoutError('Node 1 missing layout x coordinate')
+)

This ensures both the error type and message remain correct, though the current type-only validation is acceptable.

Also applies to: 102-102, 121-121, 124-124, 143-143

apps/eclair/src/features/full-graph/components/ForceGraph/GraphRenderingSetup.ts (4)

14-16: LGTM! Specialized error types imported.

The introduction of LayoutError and RenderingError improves error handling by distinguishing coordinate/layout issues from node lookup failures, making debugging easier.


35-43: LGTM! Error handling improved with specific type.

Using LayoutError instead of a generic Error for missing coordinates is appropriate and aligns with the domain-specific error class strategy.


183-190: LGTM! Defensive check with appropriate error type.

The RenderingError correctly categorizes node lookup failures. The v8 ignore comment appropriately marks this as defensive code since links should only reference valid node IDs.


302-368: LGTM! Comprehensive defensive error handling.

The multiple defensive checks properly distinguish between:

  • RenderingError: Node lookup failures in the position map (lines 316, 322)
  • LayoutError: Missing coordinates after layout computation (lines 328, 334, 364)

Error messages include helpful debugging context (available nodes, JSON dumps). The v8 ignore comments correctly mark these as defensive paths that shouldn't execute in normal D3 simulation flow.

Note on v8 ignore comment format: The @preserve directive in the v8 ignore comments (e.g., line 314) is non-standard. Standard format is /* v8 ignore next N */. While the current format likely works, consider removing @preserve if coverage reporting encounters issues:

-/* v8 ignore next 3 -- @preserve defensive: D3 callback, position map built from same nodes */
+/* v8 ignore next 3 -- defensive: D3 callback, position map built from same nodes */
packages/riviere-schema/src/component-id.spec.ts (1)

1-3: LGTM! Import correctly extended for error-type assertions.

The addition of InvalidComponentIdError to the imports is necessary and correct for the type-specific error assertions added below.

packages/riviere-schema/src/schema.spec.ts (1)

10-12: LGTM: Imports correctly include the new error type.

The imports properly include RiviereSchemaValidationError for testing the specific error class thrown by parseRiviereGraph.

packages/riviere-extract-config/src/validation.spec.ts (3)

7-7: LGTM!

The import of ExtractionConfigValidationError improves type safety and enables more specific test assertions for validation failures.


345-346: LGTM!

Excellent improvement. Asserting the specific ExtractionConfigValidationError type instead of a generic Error makes the test more precise and ensures the correct error type is thrown on validation failures.


25-27: Test is valid—validator schema accepts both unresolved and resolved config shapes.

The validator schema accepts ResolvedExtractionConfig because Module is a superset of ModuleConfig (required fields in resolved configs satisfy optional-field requirements in unresolved configs). This test confirms the schema's permissiveness. Consider a more descriptive test name: "returns true when config has all modules fully resolved" or similar.

apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx (2)

2-2: LGTM: Import formatting

The import formatting changes are purely cosmetic and maintain consistency.

Also applies to: 5-5


10-10: LGTM: Error type import

The LayoutError import is necessary for the new error-handling tests and uses the correct import pattern.

packages/riviere-cli/src/commands/extract/config-loader.spec.ts (1)

58-61: Consider consolidating error assertions to avoid redundant loader calls.

Multiple tests call the loader twice—once to check the error type and again to verify the message. While harmless, this is inefficient.

♻️ Example refactor to reduce redundancy
-expect(() => loader('./missing.json')).toThrow(ConfigFileNotFoundError)
-expect(() => loader('./missing.json')).toThrow(
-  "Cannot resolve extends reference './missing.json'",
-)
+expect(() => loader('./missing.json'))
+  .toThrow(ConfigFileNotFoundError)
+  .toThrow("Cannot resolve extends reference './missing.json'")

Or use a try-catch to capture the error once:

try {
  loader('./missing.json')
  expect.fail('Expected error to be thrown')
} catch (error) {
  expect(error).toBeInstanceOf(ConfigFileNotFoundError)
  expect(error).toHaveProperty('source', './missing.json')
  expect(error).toHaveProperty('message', expect.stringContaining("Cannot resolve extends reference './missing.json'"))
}

Also applies to: 70-71, 80-81, 90-91, 108-109

⛔ Skipped due to 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: 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: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.
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.
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
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.
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: When hitting max-lines limits, split files into focused modules (e.g., `foo.spec.ts` and `foo.edge-cases.spec.ts`), extract duplicated code into shared modules, or use parameterized tests with `it.each` or `describe.each` instead of removing tests or compressing code.
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test domain-specific edge cases: email (valid formats, plus signs, subdomains), URLs (protocols, ports, special characters, relative paths), phone numbers (international formats, extensions), addresses (Unicode, multi-line, missing components), currency (rounding, different currencies, zero amounts), percentages (0%, 100%, over 100%).
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
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-Fast Error Handling: Validate and throw clear errors instead of using fallback chains. Error format: `Expected [X]. Got [Y]. Context: [debugging info]`
apps/eclair/src/components/SchemaModal/SchemaModal.tsx (2)

12-14: LGTM! Error imports are correct.

The new error class imports follow the project's error hierarchy pattern.


94-108: LGTM! Defensive check with clear error message.

The SchemaError provides a descriptive message for the defensive case where graphName is undefined. While the button is disabled in the UI (line 168), this guard prevents issues from programmatic calls or race conditions.

apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx (2)

16-16: LGTM! Error import is correct.


27-31: LGTM! Test helper is appropriate for its use case.

The helper function is well-suited for testing error throws, where the render result isn't needed. The hardcoded values (graphName, isOpen, onClose) are reasonable defaults for these specific tests.

Comment thread apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
Comment thread apps/eclair/src/features/comparison/DomainConnectionDiff.spec.tsx
Comment thread packages/riviere-cli/src/commands/extract/config-loader.spec.ts
Comment thread packages/riviere-cli/src/commands/extract/config-loader.spec.ts
Comment thread packages/riviere-schema/src/schema.spec.ts
Comment thread packages/riviere-schema/src/schema.spec.ts
Comment thread packages/riviere-schema/src/schema.spec.ts
- Remove unjustified v8 ignore comments from SchemaModal.tsx
- Extract validateDownloadGraphName function for testability
- Export getStyle function for testability
- Add SchemaModal.cssModule.spec.ts to test CSSModuleError path
- Add validateDownloadGraphName tests for SchemaError path
- Add anti-pattern rule for lazy coverage ignore comments

Coverage ignore comments must be fully justified - "hard to test"
or "button is disabled" are not valid excuses.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
When SonarCloud quality gate fails, the script now shows a direct
link to the coverage breakdown page, making it easier to identify
which files need additional test coverage.

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: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/eclair/src/components/SchemaModal/SchemaModal.tsx (1)

116-128: Improved error handling, but consider more defensive date parsing.

The change to use SchemaError with a descriptive message is a good improvement. However, the date parsing could be more defensive:

  1. The split('T') operation is not guaranteed to return a non-empty array.
  2. While you check datePart === undefined, using optional chaining would be more idiomatic: const datePart = parts[0]?.trim().
  3. Consider checking for valid date format more thoroughly (e.g., using regex or Date validation) if this function processes untrusted input.

Given that graph.metadata.generated should be validated earlier in the pipeline, the current implementation may be acceptable, but defensive parsing is recommended.

♻️ More defensive date parsing
 function formatGeneratedDate(isoDateString: string | undefined): string {
   if (isoDateString === undefined) {
     return 'Unknown'
   }
   const parts = isoDateString.split('T')
-  const datePart = parts[0]
-  if (datePart === undefined || datePart === '') {
+  const datePart = parts[0]?.trim()
+  if (!datePart) {
     throw new SchemaError(
       `Invalid ISO date string: "${isoDateString}". Expected format like "2024-01-15T10:30:00Z".`,
     )
   }
   return datePart
 }
🤖 Fix all issues with AI agents
In @apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts:
- Around line 13-21: Add a positive test that mocks the full CSS module so
importing './SchemaModal' succeeds and exports are usable, and consolidate the
two failing tests into one that asserts the thrown error is an instance of
CSSModuleError and that its message contains the missing class name;
specifically, create/reset module state between tests (use vi.resetModules or a
separate test file), add a success case that provides all required class keys
when importing './SchemaModal', and replace the two existing negative tests with
a single assertion that import('./SchemaModal') rejects with CSSModuleError and
that the error message includes 'jsonBasicChild' (or make the expected class
name configurable if order is nondeterministic).

In @apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx:
- Around line 107-121: Tests duplicate validation of graph.metadata.generated;
consolidate the two cases into one test that asserts both the thrown type
(SchemaError) and the error message ('Invalid ISO date string') when rendering
via renderSchemaModalWithGraph, and replace the two single-case tests with a
table-driven test that iterates invalid inputs (""; "2024-01-15";
"2024-T01-15T10:30:00Z"; "T"; "  T10:30:00Z"; " 2024-01-15 T10:30:00Z") by
assigning each to graph.metadata.generated and expecting
renderSchemaModalWithGraph(graph) to throw SchemaError with the message; also
add a positive case where graph.metadata.generated = "2024-01-15T10:30:00Z" and
assert renderSchemaModalWithGraph(graph) does not throw and yields/contains the
formatted date part "2024-01-15".

In @apps/eclair/src/components/SchemaModal/SchemaModal.tsx:
- Around line 16-22: The getStyle function is currently exported but appears to
be an internal helper; remove the export modifier from getStyle in SchemaModal
(change "export function getStyle" to "function getStyle") and update any
internal references to it within the module; if any external files import
getStyle, instead export a stable public API or update those callers to use the
public component API; leave the CSSModuleError and 'SchemaModal.module.css'
usage intact so the function still throws when a style is missing.

In @scripts/get-pr-feedback.sh:
- Line 157: The SONAR_PROJECT_KEY extraction uses grep without limiting matches,
so duplicate sonar.projectKey entries would be concatenated; update the command
that sets SONAR_PROJECT_KEY to pass the grep -m1 flag to stop after the first
match (keep the rest of the pipeline: cut -d'=' -f2 | tr -d '[:space:]') so only
the first project key is used.
- Line 165: The printed SonarCloud URL uses SONAR_PROJECT_KEY directly which can
break with special characters; encode SONAR_PROJECT_KEY before insertion and use
the encoded variable in the printf that builds the URL (replace the direct
$SONAR_PROJECT_KEY in the printf with the encoded variable). A simple approach
is to compute ENCODED_SONAR_PROJECT_KEY via jq's @uri filter (e.g., pass
SONAR_PROJECT_KEY into jq to produce a URI-encoded string) and then reference
ENCODED_SONAR_PROJECT_KEY and PR_NUMBER in the existing printf call.
📜 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 d527978 and e4d3289.

📒 Files selected for processing (5)
  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
  • docs/conventions/anti-patterns.md
  • scripts/get-pr-feedback.sh
🧰 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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
**/*.{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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
**/*.{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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
**/*.{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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
🧠 Learnings (31)
📓 Common learnings
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: 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: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.
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
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
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 the Rivière Builder Node.js library to programmatically construct the schema graph when implementing custom extraction code
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
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-config/CLAUDE.md:0-0
Timestamp: 2026-01-06T23:01:34.751Z
Learning: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted
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: All validation of extraction config must occur at config load time, not during extraction. Invalid configs should fail fast with clear error messages that include paths and descriptive information
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
📚 Learning: 2026-01-06T18:02:51.422Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 58
File: scripts/get-pr-feedback.sh:45-55
Timestamp: 2026-01-06T18:02:51.422Z
Learning: In shell scripts that call GraphQL APIs (e.g., scripts/get-pr-feedback.sh and similar), prefer using sed-based interpolation for GraphQL variables instead of gh api graphql's -f/-F flags. Rationale: sed-based interpolation is typically simpler and more robust in Bash contexts, avoids JSON encoding pitfalls, and keeps the script portable. Implement by building the GraphQL query as a string and substituting variables with sed or parameter expansion, ensuring proper escaping. If you must use -f/-F, provide clear justification in a comment.

Applied to files:

  • scripts/get-pr-feedback.sh
📚 Learning: 2026-01-06T18:13:47.289Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 58
File: scripts/reply-to-thread.sh:1-12
Timestamp: 2026-01-06T18:13:47.289Z
Learning: In shell scripts across the repository (e.g., scripts/reply-to-thread.sh), keep the code simple by not adding explicit preflight tool-availability checks for external commands (like gh or jq) when those tools would fail on first use anyway. Such checks add boilerplate without changing behavior. If you must guard against missing tools, prefer a minimal, early startup check or rely on the script failing naturally at the point of use.

Applied to files:

  • scripts/get-pr-feedback.sh
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for dates and times: leap years (Feb 29), daylight saving transitions, timezone boundaries, midnight (00:00:00), end of day (23:59:59), year boundaries, invalid dates (Feb 30, Month 13), Unix epoch edge cases, and far future/past dates.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test domain-specific edge cases: email (valid formats, plus signs, subdomains), URLs (protocols, ports, special characters, relative paths), phone numbers (international formats, extensions), addresses (Unicode, multi-line, missing components), currency (rounding, different currencies, zero amounts), percentages (0%, 100%, over 100%).

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test violated domain constraints: uniqueness violations (duplicate IDs, emails), missing required relationships (orphaned records), ordering violations (events out of sequence), range breaches (age -1, quantity 1000000), state inconsistencies (shipped but not paid), format mismatches (expected JSON, got XML), and temporal ordering (end before start).

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for string inputs: empty string, whitespace-only strings, very long strings (10K+ characters), Unicode (emojis, RTL text, combining characters), special characters (quotes, backslashes, null bytes), SQL/HTML/script injection patterns, and leading/trailing whitespace.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for number inputs: zero, negative numbers, very large/small numbers (near MAX/MIN_SAFE_INTEGER), decimal precision (0.1 + 0.2), NaN, Infinity/-Infinity, and boundary values (off-by-one at limits).

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for collections (arrays, objects, maps): empty collections, single element, duplicates, nested structures, circular references, very large collections (performance), sparse arrays, and mixed types.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • docs/conventions/anti-patterns.md
📚 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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Do not pass empty strings into parameters of type string. Empty strings indicate missing values and should trigger errors, use optional types, or reconsider the design. Avoid test cases that verify empty string as a valid expected scenario for string parameters.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test null and undefined inputs: null input, undefined input, missing optional properties, and explicit undefined vs missing key.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
📚 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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*-fixtures.ts : Create `<module>-fixtures.ts` fixture files alongside `<module>.spec.ts` to reduce duplication when multiple tests share similar setup data or differ only in specific values being tested.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Assertions must match test titles. If the test claims to verify 'different IDs', assert on the actual ID values—not just count or existence.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Avoid implementation coupling in tests. Test behavior, not implementation details. Instead of asserting on mock call arguments with exact SQL, assert on the observable result (e.g., expect(result.user.name).toBe('Alice')).

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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/apps/*/vitest.config.ts : Each app must include a vitest.config.ts file with 100% coverage thresholds for test configuration.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-Fast Error Handling: Validate and throw clear errors instead of using fallback chains. Error format: `Expected [X]. Got [Y]. Context: [debugging info]`

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Avoid anti-patterns documented in `docs/conventions/anti-patterns.md`

Applied to files:

  • docs/conventions/anti-patterns.md
📚 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/apps/*/src/**/*.test.ts : Test fixtures used across multiple test files may be grouped in shared locations (e.g., test-fixtures.ts), but otherwise test files should be co-located with the code they test.

Applied to files:

  • docs/conventions/anti-patterns.md
📚 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 must comply with anti-patterns guidelines defined in @/docs/conventions/anti-patterns.md. Violations are hard failures unless documented exceptions exist.

Applied to files:

  • docs/conventions/anti-patterns.md
📚 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/**/*.{test.ts,test.tsx,test.js,test.jsx,spec.ts,spec.tsx,spec.js,spec.jsx} : All test files must comply with testing standards defined in @/docs/conventions/testing.md. Test files must not contain any code comments - comments are banned and a hard failure.

Applied to files:

  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: When hitting max-lines limits, split files into focused modules (e.g., `foo.spec.ts` and `foo.edge-cases.spec.ts`), extract duplicated code into shared modules, or use parameterized tests with `it.each` or `describe.each` instead of removing tests or compressing code.

Applied to files:

  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-fast over silent fallbacks. Never use fallback chains (`value ?? backup ?? 'unknown'`). If data should exist, validate and throw a clear error.

Applied to files:

  • docs/conventions/anti-patterns.md
📚 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/packages/*/vitest.config.ts : Each package must include a vitest.config.ts file with 100% coverage thresholds for test configuration.

Applied to files:

  • docs/conventions/anti-patterns.md
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : No code comments. Comments are a failure to express intent in code. If you need a comment to explain what code does, the code isn't clear enough—refactor it.

Applied to files:

  • docs/conventions/anti-patterns.md
🧬 Code graph analysis (2)
apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts (1)
apps/eclair/src/errors.ts (1)
  • CSSModuleError (54-59)
apps/eclair/src/components/SchemaModal/SchemaModal.tsx (1)
apps/eclair/src/errors.ts (2)
  • CSSModuleError (54-59)
  • SchemaError (74-79)
🪛 LanguageTool
docs/conventions/anti-patterns.md

[style] ~177-~177: To elevate your writing, try using a synonym here.
Context: ...fy it's truly unreachable** - Not just "hard to test" or "unlikely to happen" ### ❌...

(HARD_TO)

⏰ 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). (4)
  • GitHub Check: main
  • GitHub Check: browser-tests (webkit)
  • GitHub Check: browser-tests (firefox)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (6)
docs/conventions/anti-patterns.md (1)

134-220: Excellent documentation additions—clear, actionable, and well-aligned with team practices.

Both new anti-pattern sections follow the established pattern and provide concrete guidance:

  • "Sharing test fixtures" clearly distinguishes raw test data from reusable test utilities (line 165)
  • "Lazy Coverage Ignore Comments" provides practical examples of invalid vs. justified ignore comments, a full table of test-instead scenarios, and valid-use cases

The guidance is consistent with the project's learnings on testing standards and code-quality expectations.

apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts (1)

1-11: LGTM!

The mock setup correctly simulates missing CSS classes by only providing jsonContainer. This will trigger validation errors when the component tries to access other required classes like jsonBasicChild.

apps/eclair/src/components/SchemaModal/SchemaModal.tsx (3)

24-30: LGTM! Good defensive programming.

The assertion function correctly narrows the type and provides a clear error message. The error message appropriately indicates this is a programmer error ("Button should be disabled"), which aligns with the UI logic that disables the download button when graphName is undefined (line 170).

This defensive check is valuable for catching logic errors during development and refactoring.


32-55: LGTM! Module-level validation aligns with fail-fast principles.

The jsonViewStyles initialization validates all required CSS classes at module import time. This fail-fast approach ensures CSS module issues are caught immediately when the module loads, rather than later during rendering.

This design aligns with the fail-fast error handling guidelines and makes CSS configuration errors visible early in the development cycle.


101-110: LGTM! Good refactoring to extract validation.

Extracting the graphName validation into a dedicated assertion function improves code clarity and testability. The download logic remains unchanged and correct.

apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx (1)

8-10: LGTM! Helper function reduces duplication.

The new imports and renderSchemaModalWithGraph helper function simplify test setup for the generated date validation tests. The helper appropriately encapsulates common rendering logic.

Also applies to: 18-18, 29-33

Comment thread apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
Comment thread apps/eclair/src/components/SchemaModal/SchemaModal.spec.tsx
Comment thread apps/eclair/src/components/SchemaModal/SchemaModal.tsx Outdated
Comment thread scripts/get-pr-feedback.sh
Comment thread scripts/get-pr-feedback.sh
SonarCloud couldn't resolve coverage paths because they were relative
to the package directory instead of the repo root. Adding projectRoot
to the lcov reporter config fixes the path resolution.

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 @apps/eclair/vitest.config.mts:
- Line 1: The file currently imports both a default "path" from 'node:path' and
a named "resolve" from 'path', causing redundancy; pick one style and
consolidate imports—either remove the named "resolve" import and call
path.resolve wherever resolve is used, or remove the default "path" import and
keep the named "resolve" import (replacing any path.resolve uses with resolve);
update the import line accordingly and adjust all usages of resolve/path in the
file to match the chosen import style.
📜 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 e4d3289 and c03bcb4.

📒 Files selected for processing (1)
  • apps/eclair/vitest.config.mts
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
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: 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-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
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.
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
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
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
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 integration tests for end-to-end extraction from TypeScript code to JSON output
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: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted
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: All validation of extraction config must occur at config load time, not during extraction. Invalid configs should fail fast with clear error messages that include paths and descriptive information
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: All extraction rules should come from validated ExtractionConfig provided by riviere-extract-config
📚 Learning: 2026-01-06T08:11:15.403Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 53
File: packages/riviere-extract-config/vitest.config.mts:20-20
Timestamp: 2026-01-06T08:11:15.403Z
Learning: In packages/riviere-extract-config/vitest.config.mts, the explicit tuple type assertion for the reporter configuration (`as ['text', ['lcov', { projectRoot: string }]]`) is necessary because vitest's CoverageReporter type requires the exact tuple shape; neither inference nor 'as const' produces a compatible type.

Applied to files:

  • apps/eclair/vitest.config.mts
📚 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:

  • apps/eclair/vitest.config.mts
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Applies to **/vitest.config.ts : When creating new projects with tests, add vitest.config.ts with 100% coverage as the default

Applied to files:

  • apps/eclair/vitest.config.mts
📚 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:

  • apps/eclair/vitest.config.mts
📚 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/packages/*/vitest.config.ts : Each package must include a vitest.config.ts file with 100% coverage thresholds for test configuration.

Applied to files:

  • apps/eclair/vitest.config.mts
📚 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/apps/*/vitest.config.ts : Each app must include a vitest.config.ts file with 100% coverage thresholds for test configuration.

Applied to files:

  • apps/eclair/vitest.config.mts
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Do not modify root configuration files (eslint.config.mjs, tsconfig.base.json, nx.json, vite.config, vitest.config.mts); provide suggested changes and ask the user before modifying

Applied to files:

  • apps/eclair/vitest.config.mts
📚 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:

  • apps/eclair/vitest.config.mts
📚 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:

  • apps/eclair/vitest.config.mts
📚 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:

  • apps/eclair/vitest.config.mts
⏰ 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). (5)
  • GitHub Check: browser-tests (firefox)
  • GitHub Check: browser-tests (webkit)
  • GitHub Check: main
  • GitHub Check: browser-tests (chromium)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
apps/eclair/vitest.config.mts (1)

25-25: LGTM! Type annotation is correct.

The explicit tuple type assertion for the reporter configuration is necessary for vitest's type system and correctly specifies the nested LCOV reporter with projectRoot option.

Based on learnings, this explicit tuple type assertion is required because vitest's CoverageReporter type requires the exact tuple shape.

Comment thread apps/eclair/vitest.config.mts
Same fix as eclair - SonarCloud needs paths relative to repo root.

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/vitest.config.mts:
- Around line 1-5: The config uses __dirname to build repoRoot (symbol repoRoot)
in an ESM .mts file, which may be undefined under ESM; replace the __dirname
dependency by computing the module directory from import.meta.url (via file URL
-> path dirname) or otherwise ensure your bundler/vitest loader provides
__dirname, update repoRoot to use that value, and run the vitest config loader
locally to verify coverage paths are stable and imports still resolve.
📜 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 c03bcb4 and 2b9d5b8.

📒 Files selected for processing (1)
  • packages/riviere-cli/vitest.config.mts
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
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: 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: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.
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
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
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
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
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 integration tests for end-to-end extraction from TypeScript code to JSON output
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: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted
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.
📚 Learning: 2026-01-06T08:11:15.403Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 53
File: packages/riviere-extract-config/vitest.config.mts:20-20
Timestamp: 2026-01-06T08:11:15.403Z
Learning: In packages/riviere-extract-config/vitest.config.mts, the explicit tuple type assertion for the reporter configuration (`as ['text', ['lcov', { projectRoot: string }]]`) is necessary because vitest's CoverageReporter type requires the exact tuple shape; neither inference nor 'as const' produces a compatible type.

Applied to files:

  • packages/riviere-cli/vitest.config.mts
📚 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/vitest.config.mts
📚 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/vitest.config.mts
📚 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/vitest.config.mts
📚 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/packages/*/vitest.config.ts : Each package must include a vitest.config.ts file with 100% coverage thresholds for test configuration.

Applied to files:

  • packages/riviere-cli/vitest.config.mts
📚 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/vitest.config.mts
📚 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 ts-morph for TypeScript AST parsing instead of other parsers

Applied to files:

  • packages/riviere-cli/vitest.config.mts
📚 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/vitest.config.mts
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Applies to **/vitest.config.ts : When creating new projects with tests, add vitest.config.ts with 100% coverage as the default

Applied to files:

  • packages/riviere-cli/vitest.config.mts
📚 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/vitest.config.mts
📚 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/apps/*/vitest.config.ts : Each app must include a vitest.config.ts file with 100% coverage thresholds for test configuration.

Applied to files:

  • packages/riviere-cli/vitest.config.mts
⏰ 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). (4)
  • GitHub Check: browser-tests (webkit)
  • GitHub Check: browser-tests (firefox)
  • GitHub Check: main
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
packages/riviere-cli/vitest.config.mts (1)

20-20: No changes needed. The type assertion is appropriate and necessary for vitest's CoverageReporter type constraints. The projectRoot option is supported by vitest's v8 coverage provider's lcov reporter in version 4.0.8. This configuration matches the vitest documentation and is consistent with other packages in the codebase.

Comment thread packages/riviere-cli/vitest.config.mts
Test both error type and message in a single test - they represent one
error condition.

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 @docs/conventions/testing.md:
- Around line 317-325: The example calls loadConfig('nonexistent.json') twice;
change it to call the function once, capture the thrown error (e.g., via
try/catch into a variable), then assert both the error type (instanceof
ConfigurationError) and message on that captured error so the test invokes
loadConfig only once and checks both conditions.
📜 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 2b9d5b8 and db957a7.

📒 Files selected for processing (1)
  • docs/conventions/testing.md
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
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: 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: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.
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
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
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
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
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: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted
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.
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test domain-specific edge cases: email (valid formats, plus signs, subdomains), URLs (protocols, ports, special characters, relative paths), phone numbers (international formats, extensions), addresses (Unicode, multi-line, missing components), currency (rounding, different currencies, zero amounts), percentages (0%, 100%, over 100%).

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Assertions must match test titles. If the test claims to verify 'different IDs', assert on the actual ID values—not just count or existence.

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test violated domain constraints: uniqueness violations (duplicate IDs, emails), missing required relationships (orphaned records), ordering violations (events out of sequence), range breaches (age -1, quantity 1000000), state inconsistencies (shipped but not paid), format mismatches (expected JSON, got XML), and temporal ordering (end before start).

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Never parse error message strings to determine error types or extract information using `.message.includes()`, `.message.startsWith()`, or regex patterns on `error.message`. Use typed custom error classes instead.

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-08T23:16:02.639Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/software-design.md:0-0
Timestamp: 2026-01-08T23:16:02.639Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : Fail-Fast Error Handling: Validate and throw clear errors instead of using fallback chains. Error format: `Expected [X]. Got [Y]. Context: [debugging info]`

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for collections (arrays, objects, maps): empty collections, single element, duplicates, nested structures, circular references, very large collections (performance), sparse arrays, and mixed types.

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: Applies to docs/conventions/**/*.{ts,tsx,js,jsx} : When parsing strings in exception messages is 100% unavoidable (e.g., due to third-party library limitations), document the exception with justification, reference tracking issue, and note that upstream fix was requested.

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for number inputs: zero, negative numbers, very large/small numbers (near MAX/MIN_SAFE_INTEGER), decimal precision (0.1 + 0.2), NaN, Infinity/-Infinity, and boundary values (off-by-one at limits).

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : One concept per test. Each test verifies one behavior. If you need 'and' in your test name, split it into multiple tests.

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-10T10:14:57.499Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T10:14:57.499Z
Learning: Follow `docs/conventions/testing.md` for all testing practices

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : When testing cleanup functions and resource management (timers, event listeners, subscriptions), verify the cleanup mechanism was called using spies. Always restore spies in the same test or in `afterEach` to prevent leaks between tests.

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-08T06:46:05.503Z
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:05.503Z
Learning: In test files using typescript-eslint/rule-tester's RuleTester.run(), include an explicit it() block with an 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.

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Assert specific values, not types. Use `expect(result).toEqual(['First.', ' Second.'])` not `expect(result).toBeDefined()`. Specific assertions catch specific bugs.

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Test names describe outcomes, not actions. Use the pattern: '[outcome] when [condition]' (e.g., 'returns empty array when input is null', not 'test null input'). The test name IS the specification.

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Use Arrange-Act-Assert structure in tests: (1) Set up test data, (2) Execute the behavior, (3) Verify the outcome.

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Avoid implementation coupling in tests. Test behavior, not implementation details. Instead of asserting on mock call arguments with exact SQL, assert on the observable result (e.g., expect(result.user.name).toBe('Alice')).

Applied to files:

  • docs/conventions/testing.md
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: When hitting max-lines limits, split files into focused modules (e.g., `foo.spec.ts` and `foo.edge-cases.spec.ts`), extract duplicated code into shared modules, or use parameterized tests with `it.each` or `describe.each` instead of removing tests or compressing code.

Applied to files:

  • docs/conventions/testing.md
⏰ 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). (5)
  • GitHub Check: browser-tests (firefox)
  • GitHub Check: main
  • GitHub Check: browser-tests (webkit)
  • GitHub Check: browser-tests (chromium)
  • GitHub Check: Cloudflare Pages

Comment thread docs/conventions/testing.md
WebKit caches modules differently, causing separate import() calls in
successive tests to have different behavior. Combined the type and
message assertions into a single test on the same promise.

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 @apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts:
- Around line 13-19: Refactor the failing-path test so you only await
import('./SchemaModal') once by wrapping it in try/catch, capture the caught
error, then assert it is an instance of CSSModuleError and that error.message
contains 'jsonBasicChild'; additionally add a separate happy-path test named
like "imports successfully when required CSS classes are present" that ensures
import('./SchemaModal') resolves when the CSS module includes the required class
(mock or provide a fixture including 'jsonBasicChild') and assert the module
loads without throwing.
📜 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 db957a7 and ea1f71f.

📒 Files selected for processing (1)
  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
🧠 Learnings (15)
📓 Common learnings
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: 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: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.
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-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
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
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
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
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: packages/riviere-extract-config/CLAUDE.md:0-0
Timestamp: 2026-01-06T23:01:34.751Z
Learning: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted
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: All validation of extraction config must occur at config load time, not during extraction. Invalid configs should fail fast with clear error messages that include paths and descriptive information
📚 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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*-fixtures.ts : Create `<module>-fixtures.ts` fixture files alongside `<module>.spec.ts` to reduce duplication when multiple tests share similar setup data or differ only in specific values being tested.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Assertions must match test titles. If the test claims to verify 'different IDs', assert on the actual ID values—not just count or existence.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test violated domain constraints: uniqueness violations (duplicate IDs, emails), missing required relationships (orphaned records), ordering violations (events out of sequence), range breaches (age -1, quantity 1000000), state inconsistencies (shipped but not paid), format mismatches (expected JSON, got XML), and temporal ordering (end before start).

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for collections (arrays, objects, maps): empty collections, single element, duplicates, nested structures, circular references, very large collections (performance), sparse arrays, and mixed types.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test null and undefined inputs: null input, undefined input, missing optional properties, and explicit undefined vs missing key.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-11T11:17:09.320Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.320Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test domain-specific edge cases: email (valid formats, plus signs, subdomains), URLs (protocols, ports, special characters, relative paths), phone numbers (international formats, extensions), addresses (Unicode, multi-line, missing components), currency (rounding, different currencies, zero amounts), percentages (0%, 100%, over 100%).

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : One concept per test. Each test verifies one behavior. If you need 'and' in your test name, split it into multiple tests.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-11T11:17:09.319Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/testing.md:0-0
Timestamp: 2026-01-11T11:17:09.319Z
Learning: Applies to docs/conventions/**/*.{spec,test}.{js,ts,jsx,tsx} : Systematically test edge cases for string inputs: empty string, whitespace-only strings, very long strings (10K+ characters), Unicode (emojis, RTL text, combining characters), special characters (quotes, backslashes, null bytes), SQL/HTML/script injection patterns, and leading/trailing whitespace.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
📚 Learning: 2026-01-11T11:04:34.655Z
Learnt from: CR
Repo: NTCoding/living-architecture PR: 0
File: docs/conventions/anti-patterns.md:0-0
Timestamp: 2026-01-11T11:04:34.655Z
Learning: When hitting max-lines limits, split files into focused modules (e.g., `foo.spec.ts` and `foo.edge-cases.spec.ts`), extract duplicated code into shared modules, or use parameterized tests with `it.each` or `describe.each` instead of removing tests or compressing code.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts
🧬 Code graph analysis (1)
apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts (1)
apps/eclair/src/errors.ts (1)
  • CSSModuleError (54-59)
⏰ 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). (4)
  • GitHub Check: browser-tests (firefox)
  • GitHub Check: browser-tests (webkit)
  • GitHub Check: main
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (2)
apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts (2)

1-4: LGTM!

Imports are standard and correctly structured for a Vitest test file.


6-11: LGTM!

Mock setup correctly simulates missing CSS classes to test error handling. The comment clearly documents the intent.

The function is only used internally within SchemaModal.tsx.

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 @apps/eclair/src/components/SchemaModal/SchemaModal.tsx:
- Around line 24-30: The error message in validateDownloadGraphName ties
validation logic to UI ("Button should be disabled..."); update the thrown
SchemaError in validateDownloadGraphName to be UI-agnostic and purely about the
missing input (e.g., "graphName is required to download" or similar), leaving
any UI hints to the UI layer; ensure you only change the message string in
validateDownloadGraphName while keeping the TypeScript assertion signature and
SchemaError usage intact.
📜 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 ea1f71f and 4d4b151.

📒 Files selected for processing (1)
  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
🧰 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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
**/*.{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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
**/*.{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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
**/*.{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:

  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
🧠 Learnings (2)
📓 Common learnings
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: 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: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: packages/riviere-cli/src/commands/extract/config-loader.ts:31-39
Timestamp: 2026-01-11T14:38:35.637Z
Learning: In packages/riviere-cli/src/commands/extract/config-loader.ts, the isExtendedConfig type guard intentionally performs minimal validation (checks for non-null object and validates modules is an array if present) because comprehensive validation is handled downstream by the schema validator. The type guard's purpose is basic type narrowing to support both module-array and top-level-rules formats, not comprehensive validation. This follows the layered validation pattern where type guards are minimal and schema validation occurs at system boundaries.
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-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
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
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
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
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: 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-config/CLAUDE.md:0-0
Timestamp: 2026-01-06T23:01:34.751Z
Learning: Extraction config schemas must define all six required component types per module: api, useCase, domainOp, event, eventHandler, and ui. Unused component types must be explicitly marked with `notUsed: true` rather than omitted
📚 Learning: 2026-01-11T18:47:09.232Z
Learnt from: NTCoding
Repo: NTCoding/living-architecture PR: 129
File: apps/eclair/src/components/SchemaModal/SchemaModal.cssModule.spec.ts:13-19
Timestamp: 2026-01-11T18:47:09.232Z
Learning: Encourage using const for declarations by default in TypeScript/JavaScript files and only use let when a variable must be reassigned. Do not rely on var. This improves immutability and clarity. If a variable needs mutation (e.g., counters in loops, reassigned values), use let, but prefer const whenever possible and refactor reassigned logic to avoid mutations where feasible.

Applied to files:

  • apps/eclair/src/components/SchemaModal/SchemaModal.tsx
🧬 Code graph analysis (1)
apps/eclair/src/components/SchemaModal/SchemaModal.tsx (1)
apps/eclair/src/errors.ts (2)
  • CSSModuleError (54-59)
  • SchemaError (74-79)
⏰ 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). (4)
  • GitHub Check: browser-tests (webkit)
  • GitHub Check: main
  • GitHub Check: browser-tests (firefox)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (3)
apps/eclair/src/components/SchemaModal/SchemaModal.tsx (3)

12-22: Improved error typing with domain-specific error classes.

The introduction of CSSModuleError provides better error context than a generic Error and aligns with the PR's goal of centralizing domain-specific error handling.


101-110: Good refactoring for testability.

Extracting the validation into a named function improves testability and makes the download logic clearer. The TypeScript assertion ensures graphName is a string at line 107.


116-128: Consistent error handling with SchemaError.

Replacing the generic Error with SchemaError maintains consistency with the domain-specific error handling pattern introduced across the codebase. The validation logic correctly handles both undefined input and invalid ISO date formats.

Comment on lines +24 to +30
export function validateDownloadGraphName(graphName: string | undefined): asserts graphName is string {
if (graphName === undefined) {
throw new SchemaError(
'Cannot download: graphName is required. Button should be disabled when graphName is undefined.',
)
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider making the error message UI-agnostic.

The validation function correctly uses a TypeScript assertion signature and provides good defensive programming. However, the error message mentions "Button should be disabled when graphName is undefined," which couples the validation logic to the current UI implementation.

♻️ Consider this alternative
 export function validateDownloadGraphName(graphName: string | undefined): asserts graphName is string {
   if (graphName === undefined) {
     throw new SchemaError(
-      'Cannot download: graphName is required. Button should be disabled when graphName is undefined.',
+      'Cannot download: graphName is required.',
     )
   }
 }

This makes the error message independent of UI implementation details while still conveying the validation requirement.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function validateDownloadGraphName(graphName: string | undefined): asserts graphName is string {
if (graphName === undefined) {
throw new SchemaError(
'Cannot download: graphName is required. Button should be disabled when graphName is undefined.',
)
}
}
export function validateDownloadGraphName(graphName: string | undefined): asserts graphName is string {
if (graphName === undefined) {
throw new SchemaError(
'Cannot download: graphName is required.',
)
}
}
🤖 Prompt for AI Agents
In @apps/eclair/src/components/SchemaModal/SchemaModal.tsx around lines 24 - 30,
The error message in validateDownloadGraphName ties validation logic to UI
("Button should be disabled..."); update the thrown SchemaError in
validateDownloadGraphName to be UI-agnostic and purely about the missing input
(e.g., "graphName is required to download" or similar), leaving any UI hints to
the UI layer; ensure you only change the message string in
validateDownloadGraphName while keeping the TypeScript assertion signature and
SchemaError usage intact.

@sonarqubecloud

Copy link
Copy Markdown

@NTCoding
NTCoding merged commit baf2e9c 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.

[M5-D5.0] Add extends support to extraction config schema

1 participant