Skip to content

Print Mermaid diagram schema names in CLI output - #25

Merged
leynos merged 12 commits into
mainfrom
codex/add-schema-name-printing-for-mermaid-diagrams
Aug 23, 2025
Merged

Print Mermaid diagram schema names in CLI output#25
leynos merged 12 commits into
mainfrom
codex/add-schema-name-printing-for-mermaid-diagrams

Conversation

@leynos

@leynos leynos commented Aug 19, 2025

Copy link
Copy Markdown
Owner

Summary

  • report Mermaid diagram schema names and line numbers during file processing
  • document per-diagram markers in the README
  • verify schema markers with new integration test

Testing

  • make fmt
  • make check-fmt
  • make lint
  • make typecheck
  • make test
  • make markdownlint (fails: Missing link/image reference definitions in .rules/python-pyproject.md)
  • /root/.bun/bin/markdownlint-cli2 README.md
  • make nixie

https://chatgpt.com/codex/tasks/task_e_68a50b770ca08322add66a36388a407b

Summary by Sourcery

Print schema names and line number markers around each Mermaid diagram in the CLI, update parsing to capture metadata, document the new markers in the README, and include an integration test to verify the behavior.

New Features:

  • Report Mermaid diagram schema names and line numbers in CLI output

Enhancements:

  • Update parse_blocks to associate diagrams with line ranges and schema names for processing markers

Documentation:

  • Document per-diagram start and end markers with line numbers and schema in the README

Tests:

  • Add integration test to verify schema and line number markers in CLI output

@sourcery-ai

sourcery-ai Bot commented Aug 19, 2025

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Refactors diagram parsing to produce structured Diagram objects capturing source, line numbers, and schema; updates the CLI to emit per-diagram start/end markers with schema and line bounds; adds an integration test for schema reporting; adjusts unit tests; and documents the new markers in the README.

Sequence diagram for CLI per-diagram processing and reporting

sequenceDiagram
    participant CLI
    participant File
    participant Diagram
    participant Renderer
    actor User
    User->>CLI: Run CLI on Markdown file
    CLI->>File: Read file contents
    CLI->>Diagram: parse_blocks(text)
    loop For each Diagram
        CLI->>CLI: Print --> line {line_start}: {schema}
        CLI->>Renderer: render_block(source, ...)
        Renderer-->>CLI: Render result
        CLI->>CLI: Print <-- line {line_end}: {schema}
    end
Loading

Class diagram for the new Diagram data structure

classDiagram
    class Diagram {
        +str source
        +int line_start
        +int line_end
        +str schema
    }
Loading

File-Level Changes

Change Details Files
Introduce Diagram dataclass and enhance parse_blocks to extract line numbers and schema
  • Define Diagram dataclass with source, line_start, line_end, and schema
  • Iterate BLOCK_RE matches in parse_blocks
  • Compute start/end lines and split first line to derive schema
  • Return list of Diagram objects instead of raw code blocks
nixie/cli.py
Print start/end markers with line numbers and schema during file processing
  • Rename blocks to diagrams and guard empty list
  • Define async process function that prints entry and exit markers
  • Invoke render_block inside process and always print exit marker
  • Assemble tasks list with process calls for each diagram
nixie/cli.py
Add integration test verifying CLI reports diagram schemas and positions
  • Create temp Markdown with two Mermaid diagrams
  • Run main CLI routine and capture stdout
  • Assert markers include correct line numbers and schema once each
  • Ensure markers are emitted in the file order
tests/integration/test_cli_behavior.py
Document per-diagram markers with schema in README
  • Explain -->/ <-- markers include line numbers and schema
  • Show example with both file and diagram boundaries
  • Note that errors appear between the corresponding markers
README.md
Update unit tests for parse_blocks to expect Diagram objects and schema
  • Assert parse_blocks returns objects with correct source list
  • Assert schema field is correctly extracted for each diagram
nixie/unittests/test_parse_blocks.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Aug 19, 2025

Copy link
Copy Markdown
Contributor

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Note

Reviews paused

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Summary by CodeRabbit

  • New Features

    • CLI now renders diagrams sequentially and prints clear per‑diagram markers showing schema and start/end line numbers.
    • Errors for a diagram are reported between its markers; markers go to stdout, renderer messages to stderr.
  • Documentation

    • Updated README to reflect sequential processing and removal of the --concurrency option.
    • Clarified multi‑file output with examples of marker lines and line‑number semantics.
    • Documented that Markdown discovery is case‑sensitive and only includes .md files.

Walkthrough

Summarise the change: switch CLI rendering from concurrent to sequential per‑diagram; add a frozen, slots-enabled Diagram dataclass with positional and schema metadata; emit per‑diagram start/end markers (line numbers + schema) around rendering; update parsing, tests, and README to reflect marker semantics and removed concurrency option.

Changes

Cohort / File(s) Summary
CLI parsing & rendering
nixie/cli.py
Add Diagram dataclass (source, line_start, line_end, schema) and UNKNOWN_SCHEMA. Implement _extract_schema and change parse_blocks(text)list[Diagram]. Add diagram_markers context manager. Remove concurrency primitives and related helpers. Update check_file, render_block, _render_diagram, _run_mermaid_cli, and main to process diagrams sequentially and to emit per‑diagram markers.
Documentation
README.md
Update usage to remove --concurrency option and document sequential processing. Clarify Markdown discovery (.md case‑sensitive). Describe multi‑file output with per‑diagram bracketed markers (--> line N: schema, <-- line M: schema), line-numbering rules, and stdout/stderr behaviour for rendering errors.
Unit tests — parsing
nixie/unittests/test_parse_blocks.py
Update tests to expect Diagram objects with source, schema, line_start, line_end. Add cases for empty/whitespace schema mapping to UNKNOWN_SCHEMA and assert positional metadata.
Unit tests — markers
nixie/unittests/test_diagram_markers.py
Add tests for diagram_markers ensuring start/end prints use flush=True and end marker prints even on exceptions.
Unit tests — rendering & verbose
nixie/unittests/test_render_diagram.py, nixie/unittests/test_verbose.py
Remove semaphore usage and assertions. Update calls to _render_diagram, _run_mermaid_cli, and render_block to match signatures without semaphore.
Integration tests — CLI output & helpers
tests/integration/test_cli_behavior.py, tests/integration/conftest.py, tests/integration/test_gitignore_paths.py, tests/integration/test_no_args.py
Remove asyncio/semaphore imports and parameters from tests and fixtures. Update calls to main() and test doubles to pass only paths. Add test_cli_reports_diagram_schemas to assert per‑diagram markers and ordering in stdout.

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant CLI as nixie.check_file
  participant P as parse_blocks
  participant R as render_block

  U->>CLI: invoke CLI on file(s)
  CLI->>P: parse_blocks(file_text)
  P-->>CLI: [Diagram{source, line_start, line_end, schema}]*
  alt no diagrams
    CLI-->>U: exit success
  else diagrams found
    loop For each Diagram (sequential)
      CLI->>CLI: print "--> line X: schema" (stdout, flush)
      CLI->>R: render_block(diagram.source)
      note right of R #F7F7D9: render output/errors → stderr\nmay interleave with stdout markers
      R-->>CLI: render result / exception
      CLI->>CLI: print "<-- line Y: schema" (stdout, flush)
    end
    CLI-->>U: exit with aggregated status
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

Arrows mark where blocks begin,
Schemas named and lines within.
Process straight, no races run,
Mark the start — then mark when done.
Tests will count each little one.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/add-schema-name-printing-for-mermaid-diagrams

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

sourcery-ai[bot]

This comment was marked as resolved.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

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

⚠️ Outside diff range comments (1)
nixie/unittests/test_parse_blocks.py (1)

1-39: Add a unit test for skipping Mermaid config/comment lines

Add a focused unit test that ensures schema detection skips '%%' config lines and obtains the actual diagram schema.

Proposed new test (place after existing tests):

def test_parse_blocks_skips_config_lines() -> None:
    content = """```mermaid
%%{init: {'theme': 'forest'}}%%
sequenceDiagram
A->>B: hello
```"""
    diagrams = parse_blocks(content)
    assert [d.schema for d in diagrams] == ["sequenceDiagram"]
    assert [d.source for d in diagrams] == ["%%{init: {'theme': 'forest'}}%%\nsequenceDiagram\nA->>B: hello"]
    assert [d.line_start for d in diagrams] == [2]
    assert [d.line_end for d in diagrams] == [5]
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

💡 Knowledge Base configuration:

  • Jira integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a8051ee and eabbd99.

📒 Files selected for processing (4)
  • README.md (1 hunks)
  • nixie/cli.py (3 hunks)
  • nixie/unittests/test_parse_blocks.py (1 hunks)
  • tests/integration/test_cli_behavior.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.py

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.py: Python changes must pass tests (unit and behavioral) before completion/commit
Python code must pass lint checks (make lint)
Python code must adhere to formatting standards (make check-fmt/make fmt)
Python code must pass type checking (make typecheck)
Follow core Python 3.13 style conventions per .rules/python-00.md
Apply best practices for context managers per .rules/python-context-managers.md
Follow generator and iterator patterns per .rules/python-generators.md
Follow function return conventions per .rules/python-return.md
Apply Python typing best practices per .rules/python-typing.md

**/*.py: Name Python files in snake_case (e.g., http_client.py, task_queue.py)
Classes must use PascalCase
Variables and functions must use snake_case
Module-level constants use UPPER_SNAKE_CASE
Prefix non-exported helpers or internal APIs with a single underscore
Use typing everywhere; maintain full static type coverage with Pyright
Use TypedDict or @DataClass for structured data; prefer @DataClass(slots=True) for internal-only
Avoid Any; use Unknown, generics, or cast() with justification if Any is used
Be explicit with return types for all public functions and class methods (e.g., -> None, -> str)
Favor immutability (prefer tuples to lists; use frozendict or types.MappingProxyType where appropriate)
Use # pyright: ignore sparingly and include an explanation when used
Avoid side effects at import time; modules should not modify global state or perform actions on import
Never hardcode secrets in source code
Write NumPy-style docstrings for public functions, classes, and modules
Add inline comments to explain non-obvious logic or decisions

**/*.py: Use context managers to encapsulate setup/teardown for resources (files, locks, connections) instead of manual management
Use @contextmanager from contextlib for straightforward, linear setup/teardown without persistent internal state
Implement a class-based context manager (enter/exit) when there is internal sta...

Files:

  • tests/integration/test_cli_behavior.py
  • nixie/cli.py
  • nixie/unittests/test_parse_blocks.py

⚙️ CodeRabbit Configuration File

**/*.py: - Keep cyclomatic complexity ≤ 12

  • Follow single responsibility and CQRS (command/query segregation)
  • Docstrings must follow the numpy style guide. Use a single-line summary for private functions and methods, and full structured docs for all public interfaces.
  • Move conditionals with >2 branches to predicate/helper functions
  • Avoid eval, exec, pickle, monkey-patching, ctypes, unsafe shell
  • Every module must begin with a triple-quoted docstring explaining its purpose, utility, and usage, including example calls if appropriate.
  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar
  • Lint suppressions:
    • Blanket # noqa, file-level skips, and categories are forbidden
    • Only narrow in-line disables (# noqa: XYZ) are permitted, and must be accompanied by FIXME: or a ticket link, and used only as a last resort.
  • Use pytest fixtures for shared setup (conftest.py or fixtures/)
  • Replace duplicate tests with @pytest.mark.parametrize
  • Prefer pytest-mock or unittest.mock for stubs/mocks
  • Use assert …, "message" over bare asserts
  • Reflect all API/behaviour changes in docs/ and update roadmap on completion
  • Files must not exceed 400 logical lines:
    • Decompose large modules into subpackages
    • Split large match/case or dispatch tables by domain and collocate with targets if appropriate
    • Move bulky data (fixtures, templates) to external files for parsing at runtime
  • Mutable defaults and shadowed built-ins are forbidden
  • All code must have clear type hints using modern style (A | B, list[str], class Foo[A]:, type Bar = int, etc.), with ABC imports drawn from the correct stdlib module.

Files:

  • tests/integration/test_cli_behavior.py
  • nixie/cli.py
  • nixie/unittests/test_parse_blocks.py
tests/integration/test_*.py

📄 CodeRabbit Inference Engine (.rules/python-00.md)

Place integration tests under tests/integration/ with files prefixed with test_

Files:

  • tests/integration/test_cli_behavior.py
{**/unittests/test_*.py,tests/integration/test_*.py}

📄 CodeRabbit Inference Engine (.rules/python-00.md)

{**/unittests/test_*.py,tests/integration/test_*.py}: Use pytest idioms: prefer fixtures, parametrize broadly, avoid unnecessary mocks
Group related tests using classes with method names prefixed by test_
Write tests from a user's perspective; test public behaviour, not internals
Avoid excessive mocking; use doubles only for external services or non-deterministic behaviour

Files:

  • tests/integration/test_cli_behavior.py
  • nixie/unittests/test_parse_blocks.py
**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.md: Markdown files must pass markdown linting (make markdownlint)
Markdown files containing Mermaid diagrams must pass nixie validation (make nixie)

Files:

  • README.md

⚙️ CodeRabbit Configuration File

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • README.md
**/README.md

📄 CodeRabbit Inference Engine (.rules/python-00.md)

Colocate README.md near reusable packages and include usage examples

Files:

  • README.md
**/unittests/test_*.py

📄 CodeRabbit Inference Engine (.rules/python-00.md)

Colocate unit tests with code in an unittests/ subdirectory using files prefixed with test_

Files:

  • nixie/unittests/test_parse_blocks.py
🧬 Code Graph Analysis (2)
tests/integration/test_cli_behavior.py (2)
tests/integration/conftest.py (1)
  • stub_render (12-31)
nixie/cli.py (1)
  • main (439-455)
nixie/unittests/test_parse_blocks.py (1)
nixie/cli.py (1)
  • parse_blocks (80-91)
🔇 Additional comments (3)
nixie/cli.py (1)

20-20: LGTM: adopt dataclasses under a short alias

The alias improves readability in this module and is applied consistently. No issues.

README.md (2)

62-64: Clarify that diagram markers include schema and line numbers

The documentation correctly communicates the new markers. Keep the phrasing—it matches the CLI output and tests.


67-69: Show both start and end markers in the example

The example reads clearly and matches the CLI behaviour and tests.

Comment thread nixie/cli.py Outdated
Comment thread nixie/cli.py
Comment thread nixie/cli.py Outdated
Comment thread nixie/unittests/test_parse_blocks.py
Comment thread nixie/unittests/test_parse_blocks.py
Comment thread README.md
Comment thread tests/integration/test_cli_behavior.py
@leynos

leynos commented Aug 22, 2025

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

  • Printing diagram markers with direct print calls inside concurrent tasks can lead to interleaved output; consider sequencing or using a logging abstraction to ensure the start/end lines always bracket each rendered diagram.
  • The schema detection logic simply splits on the first whitespace, which may mis-handle diagrams with commented or empty first lines—consider a more robust parser or a default placeholder when no explicit schema is found.

@coderabbitai

coderabbitai Bot commented Aug 22, 2025

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@leynos: Looking at the current implementation, neither of the issues have been fully resolved:

1. Concurrent Output Interleaving Issue - Not Resolved

The current code still uses direct print() calls within concurrent tasks:

async def process(diagram: Diagram) -> bool:
    print(f"--> line {diagram.line_start}: {diagram.schema}")
    success = await render_block(diagram.source)
    print(f"<-- line {diagram.line_end}: {diagram.schema}")
    return success

These print() statements execute within asyncio.gather(*tasks), meaning multiple diagrams can still print their start/end markers simultaneously, potentially causing interleaved output like:

--> line 3: sequenceDiagram
--> line 8: classDiagram
<-- line 5: sequenceDiagram
<-- line 10: classDiagram

2. Schema Detection Logic - Not Resolved

The schema detection still uses simple whitespace splitting:

schema = first_line.split()[0] if first_line.split() else "unknown"

This approach has several issues:

  • Comments: A line like %% This is a comment would detect %% as the schema
  • Empty/whitespace lines: While it handles completely empty lines with the else "unknown", it doesn't handle lines with only whitespace
  • No validation: It doesn't verify the detected token is actually a valid Mermaid diagram type

Recommendations

For concurrent output:

  • Use a thread-safe logging mechanism or collect output in a list and print sequentially
  • Consider using asyncio.Lock() around print statements
  • Or collect all diagram results and print them in order after asyncio.gather()

For schema detection:

  • Implement proper parsing that skips comments (%% ...) and empty lines
  • Add validation against known Mermaid diagram types
  • Provide meaningful defaults for edge cases

🏁 Script executed:

#!/bin/bash
# Examine the current implementation in nixie/cli.py to check the concurrent execution and schema detection logic
cat nixie/cli.py

Length of output: 17812


🏁 Script executed:

#!/bin/bash
# Look specifically at the process function and schema detection logic
rg -n -A 10 -B 5 "async def process|schema.*split|print.*-->" nixie/cli.py

Length of output: 662


🏁 Script executed:

#!/bin/bash
# Check if there are any logging configurations or thread-safe printing mechanisms
rg -n -A 5 -B 5 "logging|Logger|print.*lock|concurrent" nixie/cli.py

Length of output: 3190


@leynos: After examining the current implementation, I have good news - both issues have actually been resolved:

1. Concurrent Output Interleaving Issue - ✅ Resolved

The code no longer uses concurrent tasks for diagram processing. Instead, it processes diagrams sequentially within each file:

async def check_file(path: Path, cfg_path: Path | None, semaphore: asyncio.Semaphore) -> bool:
    diagrams = parse_blocks(path.read_text(encoding="utf-8"))
    if not diagrams:
        return True

    with tempfile.TemporaryDirectory() as tmpdir:
        tmp_path = Path(tmpdir)
        all_success = True
        for idx, diagram in enumerate(diagrams, 1):  # Sequential processing
            with diagram_markers(diagram):            # Thread-safe context manager
                try:
                    success = await render_block(...)  # Only the CLI call is async
                except Exception:
                    success = False
            if not success:
                all_success = False
    return all_success

The diagram_markers context manager ensures that start and end markers are always paired correctly:

@contextmanager
def diagram_markers(diagram: Diagram) -> typ.Generator[None, None, None]:
    """Print markers bracketing ``diagram`` processing."""
    print(f"--> line {diagram.line_start}: {diagram.schema}")
    try:
        yield
    finally:
        print(f"<-- line {diagram.line_end}: {diagram.schema}")

2. Schema Detection Logic - ✅ Resolved

The schema detection has been significantly improved with a dedicated _extract_schema function:

def _extract_schema(lines: list[str]) -> str:
    """Return the schema name from ``lines``.

    Mermaid diagrams may start with empty lines or comments beginning with
    ``%%``. Skip these until a meaningful line is found. If no schema can be
    determined, return ``UNKNOWN_SCHEMA``.
    """
    for line in lines:
        stripped = line.strip()
        if not stripped or stripped.startswith("%%"):  # Skip empty lines and comments
            continue
        return stripped.split()[0]
    return UNKNOWN_SCHEMA  # Meaningful default

This robust implementation:

  • Handles comments: Skips lines starting with %%
  • Handles empty/whitespace lines: Skips empty or whitespace-only lines
  • Provides meaningful defaults: Returns UNKNOWN_SCHEMA constant instead of generic "unknown"
  • Processes line by line: Finds the first meaningful line rather than just taking the first line

Both concerns have been thoroughly addressed in the current implementation!

@leynos

leynos commented Aug 22, 2025

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 22, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

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

⚠️ Outside diff range comments (1)
nixie/unittests/test_parse_blocks.py (1)

44-61: Assert line numbers in the empty/whitespace/comment cases

Complete the contract by checking line_start and line_end in these cases.

 diag_empty = parse_blocks(content_empty)
 assert len(diag_empty) == 1
 assert diag_empty[0].schema == UNKNOWN_SCHEMA
 assert diag_empty[0].source == ""
+assert diag_empty[0].line_start == 2
+assert diag_empty[0].line_end == 3

 diag_ws = parse_blocks(content_ws)
 assert len(diag_ws) == 1
 assert diag_ws[0].schema == UNKNOWN_SCHEMA
 assert diag_ws[0].source == "   "
+assert diag_ws[0].line_start == 2
+assert diag_ws[0].line_end == 3

 content_comment = "```mermaid\n%% a comment\nsequenceDiagram\nA->B\n```"
 diag_comment = parse_blocks(content_comment)
 assert diag_comment[0].schema == "sequenceDiagram"
+assert diag_comment[0].line_start == 2
+assert diag_comment[0].line_end == 5
♻️ Duplicate comments (2)
README.md (1)

72-76: State that markers are flushed immediately

Set expectations for log consumers by noting that markers are flushed, which helps bracketing stderr reliably in terminals/CI.

- lines for that diagram. Markers are printed on stdout; messages from
+ lines for that diagram. Markers are printed on stdout and are flushed
+ immediately; messages from
nixie/unittests/test_parse_blocks.py (1)

19-22: Verify line numbers for the single‑block variations

Lock in the documented contract by asserting line_start/line_end for these inputs as well.

 diagrams = parse_blocks(text)
 assert [d.source for d in diagrams] == ["A-->B"]
 assert [d.schema for d in diagrams] == ["A-->B"]
+assert [d.line_start for d in diagrams] == [2]
+assert [d.line_end for d in diagrams] == [3]
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • Jira integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between eabbd99 and dd04fe3.

📒 Files selected for processing (5)
  • README.md (1 hunks)
  • nixie/cli.py (3 hunks)
  • nixie/unittests/test_diagram_markers.py (1 hunks)
  • nixie/unittests/test_parse_blocks.py (3 hunks)
  • tests/integration/test_cli_behavior.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

⚙️ CodeRabbit configuration file

**/*.py: - Keep cyclomatic complexity ≤ 12

  • Follow single responsibility and CQRS (command/query segregation)
  • Docstrings must follow the numpy style guide. Use a single-line summary for private functions and methods, and full structured docs for all public interfaces.
  • Move conditionals with >2 branches to predicate/helper functions
  • Avoid eval, exec, pickle, monkey-patching, ctypes, unsafe shell
  • Every module must begin with a triple-quoted docstring explaining its purpose, utility, and usage, including example calls if appropriate.
  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar
  • Lint suppressions:
    • Blanket # noqa, file-level skips, and categories are forbidden
    • Only narrow in-line disables (# noqa: XYZ) are permitted, and must be accompanied by FIXME: or a ticket link, and used only as a last resort.
  • Use pytest fixtures for shared setup (conftest.py or fixtures/)
  • Replace duplicate tests with @pytest.mark.parametrize
  • Prefer pytest-mock or unittest.mock for stubs/mocks
  • Use assert …, "message" over bare asserts
  • Reflect all API/behaviour changes in docs/ and update roadmap on completion
  • Files must not exceed 400 logical lines:
    • Decompose large modules into subpackages
    • Split large match/case or dispatch tables by domain and collocate with targets if appropriate
    • Move bulky data (fixtures, templates) to external files for parsing at runtime
  • Mutable defaults and shadowed built-ins are forbidden
  • All code must have clear type hints using modern style (A | B, list[str], class Foo[A]:, type Bar = int, etc.), with ABC imports drawn from the correct stdlib module.

Files:

  • nixie/cli.py
  • nixie/unittests/test_diagram_markers.py
  • nixie/unittests/test_parse_blocks.py
  • tests/integration/test_cli_behavior.py
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • README.md
🔇 Additional comments (3)
nixie/unittests/test_parse_blocks.py (1)

27-31: LGTM: multi‑block extraction including line numbers

nixie/cli.py (2)

70-85: LGTM: immutable Diagram with documented fields

Freezing and documenting the dataclass aligns with the immutability and clarity goals.


124-132: LGTM: marker context manager with immediate flush

The context manager brackets work neatly and solves interleaving around stderr output in practice.

Comment thread nixie/cli.py Outdated
Comment thread nixie/unittests/test_diagram_markers.py
Comment thread README.md
Comment thread tests/integration/test_cli_behavior.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (2)
nixie/cli.py (2)

353-355: Write Mermaid source with explicit encoding

Avoid platform-default encodings when writing the .mmd file.

Apply this diff:

-    mmd.write_text(block)
+    mmd.write_text(block, encoding="utf-8")

436-438: Fix invalid isinstance use of PEP 604 unions

isinstance(exc, KeyboardInterrupt | SystemExit) raises TypeError. Use a tuple of types.

Apply this diff:

-        if isinstance(exc, KeyboardInterrupt | SystemExit):
+        if isinstance(exc, (KeyboardInterrupt, SystemExit)):
             raise
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • Jira integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between dd04fe3 and 570d528.

📒 Files selected for processing (5)
  • README.md (3 hunks)
  • nixie/cli.py (3 hunks)
  • nixie/unittests/test_diagram_markers.py (1 hunks)
  • nixie/unittests/test_parse_blocks.py (3 hunks)
  • tests/integration/test_cli_behavior.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Python changes must pass tests (unit and behavioral) before completion/commit
Python code must pass lint checks (make lint)
Python code must adhere to formatting standards (make check-fmt/make fmt)
Python code must pass type checking (make typecheck)
Follow core Python 3.13 style conventions per .rules/python-00.md
Apply best practices for context managers per .rules/python-context-managers.md
Follow generator and iterator patterns per .rules/python-generators.md
Follow function return conventions per .rules/python-return.md
Apply Python typing best practices per .rules/python-typing.md

**/*.py: Name Python files in snake_case (e.g., http_client.py, task_queue.py)
Classes must use PascalCase
Variables and functions must use snake_case
Module-level constants use UPPER_SNAKE_CASE
Prefix non-exported helpers or internal APIs with a single underscore
Use typing everywhere; maintain full static type coverage with Pyright
Use TypedDict or @DataClass for structured data; prefer @DataClass(slots=True) for internal-only
Avoid Any; use Unknown, generics, or cast() with justification if Any is used
Be explicit with return types for all public functions and class methods (e.g., -> None, -> str)
Favor immutability (prefer tuples to lists; use frozendict or types.MappingProxyType where appropriate)
Use # pyright: ignore sparingly and include an explanation when used
Avoid side effects at import time; modules should not modify global state or perform actions on import
Never hardcode secrets in source code
Write NumPy-style docstrings for public functions, classes, and modules
Add inline comments to explain non-obvious logic or decisions

**/*.py: Use context managers to encapsulate setup/teardown for resources (files, locks, connections) instead of manual management
Use @contextmanager from contextlib for straightforward, linear setup/teardown without persistent internal state
Implement a class-based context manager (enter/exit) when there is internal sta...

Files:

  • nixie/unittests/test_diagram_markers.py
  • nixie/cli.py
  • tests/integration/test_cli_behavior.py
  • nixie/unittests/test_parse_blocks.py

⚙️ CodeRabbit configuration file

**/*.py: - Keep cyclomatic complexity ≤ 12

  • Follow single responsibility and CQRS (command/query segregation)
  • Docstrings must follow the numpy style guide. Use a single-line summary for private functions and methods, and full structured docs for all public interfaces.
  • Move conditionals with >2 branches to predicate/helper functions
  • Avoid eval, exec, pickle, monkey-patching, ctypes, unsafe shell
  • Every module must begin with a triple-quoted docstring explaining its purpose, utility, and usage, including example calls if appropriate.
  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar
  • Lint suppressions:
    • Blanket # noqa, file-level skips, and categories are forbidden
    • Only narrow in-line disables (# noqa: XYZ) are permitted, and must be accompanied by FIXME: or a ticket link, and used only as a last resort.
  • Use pytest fixtures for shared setup (conftest.py or fixtures/)
  • Replace duplicate tests with @pytest.mark.parametrize
  • Prefer pytest-mock or unittest.mock for stubs/mocks
  • Use assert …, "message" over bare asserts
  • Reflect all API/behaviour changes in docs/ and update roadmap on completion
  • Files must not exceed 400 logical lines:
    • Decompose large modules into subpackages
    • Split large match/case or dispatch tables by domain and collocate with targets if appropriate
    • Move bulky data (fixtures, templates) to external files for parsing at runtime
  • Mutable defaults and shadowed built-ins are forbidden
  • All code must have clear type hints using modern style (A | B, list[str], class Foo[A]:, type Bar = int, etc.), with ABC imports drawn from the correct stdlib module.

Files:

  • nixie/unittests/test_diagram_markers.py
  • nixie/cli.py
  • tests/integration/test_cli_behavior.py
  • nixie/unittests/test_parse_blocks.py
**/unittests/test_*.py

📄 CodeRabbit inference engine (.rules/python-00.md)

Colocate unit tests with code in an unittests/ subdirectory using files prefixed with test_

Files:

  • nixie/unittests/test_diagram_markers.py
  • nixie/unittests/test_parse_blocks.py
{**/unittests/test_*.py,tests/integration/test_*.py}

📄 CodeRabbit inference engine (.rules/python-00.md)

{**/unittests/test_*.py,tests/integration/test_*.py}: Use pytest idioms: prefer fixtures, parametrize broadly, avoid unnecessary mocks
Group related tests using classes with method names prefixed by test_
Write tests from a user's perspective; test public behaviour, not internals
Avoid excessive mocking; use doubles only for external services or non-deterministic behaviour

Files:

  • nixie/unittests/test_diagram_markers.py
  • tests/integration/test_cli_behavior.py
  • nixie/unittests/test_parse_blocks.py
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

**/*.md: Markdown files must pass markdown linting (make markdownlint)
Markdown files containing Mermaid diagrams must pass nixie validation (make nixie)

Files:

  • README.md

⚙️ CodeRabbit configuration file

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • README.md
**/README.md

📄 CodeRabbit inference engine (.rules/python-00.md)

Colocate README.md near reusable packages and include usage examples

Files:

  • README.md
tests/integration/test_*.py

📄 CodeRabbit inference engine (.rules/python-00.md)

Place integration tests under tests/integration/ with files prefixed with test_

Files:

  • tests/integration/test_cli_behavior.py
🧬 Code graph analysis (3)
nixie/unittests/test_diagram_markers.py (1)
nixie/cli.py (3)
  • cli (541-558)
  • Diagram (72-91)
  • diagram_markers (131-137)
tests/integration/test_cli_behavior.py (2)
tests/integration/conftest.py (1)
  • stub_render (12-31)
nixie/cli.py (1)
  • main (485-501)
nixie/unittests/test_parse_blocks.py (1)
nixie/cli.py (2)
  • cli (541-558)
  • parse_blocks (112-127)
🔍 Remote MCP

Here is the additional concrete context from the PR diff that will be directly relevant to code review:

• README.md updates
– The old --concurrency flag is now documented as “reserved for future use,” and diagrams are processed strictly sequentially within each file to guarantee bracketed start/end markers. The per‐diagram markers now include both line numbers and the schema name, with errors emitted between the markers on stderr while the markers themselves go to stdout (github.com)

• nixie/cli.py changes
– New imports: bisect and dataclasses as dc.
– Added
• @dc.dataclass Diagram (slots-enabled, frozen) with fields
source: str – raw Mermaid text (no backticks)
line_start: int – 1-based start line of the block content
line_end: int – 1-based line of the closing fence
schema: str – first meaningful token or fallback UNKNOWN_SCHEMA
UNKNOWN_SCHEMA: typ.Final[str] = "" constant
_extract_schema(lines: list[str]) -> str helper: skips blank lines and those starting with %%, returns first token or UNKNOWN_SCHEMA if none found
parse_blocks(text: str) -> list[Diagram]:
– Precomputes newline_offsets via re.finditer("\n", text) to avoid O(N²) behavior (github.com)
– Uses bisect.bisect_left on newline_offsets to map block start to line_start
– Calculates line_end = line_start + max(len(lines), 1)
– Extracts schema with _extract_schema and returns a list of Diagram instances (github.com)
@contextmanager diagram_markers(diagram: Diagram): prints
--> line {line_start}: {schema} before processing
<-- line {line_end}: {schema} on exit (even on exception), with flush=True (github.com)
check_file(...) now loops over diagrams sequentially (rather than asyncio.gather), wrapping each call to render_block in diagram_markers and collecting an overall success flag (github.com)

• Test updates
– test_parse_blocks.py:
• Now asserts on Diagram.source, .schema, .line_start, .line_end and use of UNKNOWN_SCHEMA for empty/whitespace-only blocks (github.com)
– Added test_diagram_markers.py:
• Verifies both markers are printed (and flushed) and that the end marker is printed even if an exception occurs within the context (github.com)
– Added integration test test_cli_reports_diagram_schemas:
• Writes a Markdown file with two diagrams, runs the CLI at concurrency=1 to assert the four markers (start/end for each diagram) appear exactly once and in ascending order; repeats at concurrency=2 to ensure markers still appear exactly once (order may vary) (github.com)

These points highlight the new data model (Diagram), schema‐extraction logic, output‐bracketing mechanism, shift to sequential processing for stable output, and the corresponding unit and integration tests that enforce the new behavior.

🔇 Additional comments (15)
nixie/cli.py (5)

20-21: Imports for bisect/dataclasses are appropriate

Keep. These are required by parse_blocks and Diagram.


71-92: Solid immutable Diagram model with clear docs

The frozen, slots-enabled dataclass with explicit attributes and a docstring aligns with the repo’s typing/immutability rules.


94-109: Schema extraction correctly skips blanks and Mermaid comments

The helper handles %% comment/config lines and falls back to UNKNOWN_SCHEMA. Keep this behaviour; it prevents misleading schemas from comment lines.


112-128: Avoid O(N²) line-numbering; off‑by‑one semantics look correct

Precomputing newline offsets and using bisect_left fixes the previous scaling issue. line_start = (#newlines before block) + 1 and line_end = line_start + max(len(lines), 1) match the documented contract.


130-138: Bracket markers with flush=True is correct

Flushing ensures markers surround any stderr reliably and fixes the earlier interleaving concern. Good use of a context manager for DRYness.

nixie/unittests/test_diagram_markers.py (2)

12-22: Assert start/end marker prints with flushing

The test validates both markers and flush=True ordering via assert_has_calls. Good coverage of the happy path.


25-39: Exercise the finally-path to guarantee end marker on exceptions

This test proves <-- line … is emitted even when an exception is raised inside the context. Keep.

README.md (4)

11-12: Align features with sequential processing model

Document sequential per-file diagram processing to match the code, resolving earlier concurrency/ordering concerns.


49-54: Clarify concurrency flag status and discovery semantics

Mark --concurrency as reserved and explain discovery rules. This sets correct user expectations.


61-66: Define start/end line-number semantics explicitly

State that start = first content line, end = closing fence. This matches Diagram.line_start/line_end.


74-78: Specify stdout/stderr streams for markers and CLI errors

Documenting stream behaviour helps CI/log consumers. Good addition.

tests/integration/test_cli_behavior.py (1)

131-181: Integration test robustly verifies per‑diagram schema and line markers

The test asserts exact markers once and ordered at concurrency=1; it also checks single occurrence at concurrency=2. This locks in the CLI contract without depending on ordering under higher concurrency.

nixie/unittests/test_parse_blocks.py (3)

19-22: Validate parsing across fence whitespace variants

Asserting source and schema under minor formatting variations increases confidence in BLOCK_RE and _extract_schema.


27-31: Strengthen multi-block assertions with positions

Asserting line_start/line_end for both diagrams fully validates positional metadata.


44-67: Cover empty, whitespace-only, and comment‑prefixed blocks

These cases validate UNKNOWN_SCHEMA and comment skipping semantics. Keep.

Comment thread nixie/cli.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (3)
nixie/cli.py (3)

469-479: Flush file boundary markers to keep output strictly bracketed

Emit ==>/<== markers with flush=True to preserve ordering relative to per‑diagram markers and stderr in CI logs and TTYs.

Apply this diff:

-            print(f"==> {path}")
+            print(f"==> {path}", flush=True)
             try:
                 success = await check_file(path, cfg_path)
             except Exception as exc:  # noqa: BLE001  pragma: no cover - unexpected
                 # Catch unexpected errors so the CLI can continue processing.
                 print(f"Validation task raised an exception: {exc}")
                 success = False
             if not success:
                 all_success = False
-            print(f"<== {path}")
+            print(f"<== {path}", flush=True)

343-343: Write .mmd using explicit UTF‑8 encoding

Avoid locale‑dependent defaults when writing source files that can include non‑ASCII content.

Apply this diff:

-    mmd.write_text(block)
+    mmd.write_text(block, encoding="utf-8")

421-424: Replace invalid isinstance union with a tuple of types

Found one occurrence that raises a TypeError at runtime. Update as follows:

• nixie/cli.py:422

-        if isinstance(exc, KeyboardInterrupt | SystemExit):
+        if isinstance(exc, (KeyboardInterrupt, SystemExit)):
             raise
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • Jira integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 570d528 and 9a3db1c.

📒 Files selected for processing (8)
  • README.md (3 hunks)
  • nixie/cli.py (9 hunks)
  • nixie/unittests/test_render_diagram.py (3 hunks)
  • nixie/unittests/test_verbose.py (5 hunks)
  • tests/integration/conftest.py (0 hunks)
  • tests/integration/test_cli_behavior.py (4 hunks)
  • tests/integration/test_gitignore_paths.py (2 hunks)
  • tests/integration/test_no_args.py (2 hunks)
💤 Files with no reviewable changes (1)
  • tests/integration/conftest.py
🧰 Additional context used
📓 Path-based instructions (6)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Python changes must pass tests (unit and behavioral) before completion/commit
Python code must pass lint checks (make lint)
Python code must adhere to formatting standards (make check-fmt/make fmt)
Python code must pass type checking (make typecheck)
Follow core Python 3.13 style conventions per .rules/python-00.md
Apply best practices for context managers per .rules/python-context-managers.md
Follow generator and iterator patterns per .rules/python-generators.md
Follow function return conventions per .rules/python-return.md
Apply Python typing best practices per .rules/python-typing.md

**/*.py: Name Python files in snake_case (e.g., http_client.py, task_queue.py)
Classes must use PascalCase
Variables and functions must use snake_case
Module-level constants use UPPER_SNAKE_CASE
Prefix non-exported helpers or internal APIs with a single underscore
Use typing everywhere; maintain full static type coverage with Pyright
Use TypedDict or @DataClass for structured data; prefer @DataClass(slots=True) for internal-only
Avoid Any; use Unknown, generics, or cast() with justification if Any is used
Be explicit with return types for all public functions and class methods (e.g., -> None, -> str)
Favor immutability (prefer tuples to lists; use frozendict or types.MappingProxyType where appropriate)
Use # pyright: ignore sparingly and include an explanation when used
Avoid side effects at import time; modules should not modify global state or perform actions on import
Never hardcode secrets in source code
Write NumPy-style docstrings for public functions, classes, and modules
Add inline comments to explain non-obvious logic or decisions

**/*.py: Use context managers to encapsulate setup/teardown for resources (files, locks, connections) instead of manual management
Use @contextmanager from contextlib for straightforward, linear setup/teardown without persistent internal state
Implement a class-based context manager (enter/exit) when there is internal sta...

Files:

  • nixie/unittests/test_render_diagram.py
  • tests/integration/test_gitignore_paths.py
  • nixie/unittests/test_verbose.py
  • tests/integration/test_no_args.py
  • nixie/cli.py
  • tests/integration/test_cli_behavior.py

⚙️ CodeRabbit configuration file

**/*.py: - Keep cyclomatic complexity ≤ 12

  • Follow single responsibility and CQRS (command/query segregation)
  • Docstrings must follow the numpy style guide. Use a single-line summary for private functions and methods, and full structured docs for all public interfaces.
  • Move conditionals with >2 branches to predicate/helper functions
  • Avoid eval, exec, pickle, monkey-patching, ctypes, unsafe shell
  • Every module must begin with a triple-quoted docstring explaining its purpose, utility, and usage, including example calls if appropriate.
  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar
  • Lint suppressions:
    • Blanket # noqa, file-level skips, and categories are forbidden
    • Only narrow in-line disables (# noqa: XYZ) are permitted, and must be accompanied by FIXME: or a ticket link, and used only as a last resort.
  • Use pytest fixtures for shared setup (conftest.py or fixtures/)
  • Replace duplicate tests with @pytest.mark.parametrize
  • Prefer pytest-mock or unittest.mock for stubs/mocks
  • Use assert …, "message" over bare asserts
  • Reflect all API/behaviour changes in docs/ and update roadmap on completion
  • Files must not exceed 400 logical lines:
    • Decompose large modules into subpackages
    • Split large match/case or dispatch tables by domain and collocate with targets if appropriate
    • Move bulky data (fixtures, templates) to external files for parsing at runtime
  • Mutable defaults and shadowed built-ins are forbidden
  • All code must have clear type hints using modern style (A | B, list[str], class Foo[A]:, type Bar = int, etc.), with ABC imports drawn from the correct stdlib module.

Files:

  • nixie/unittests/test_render_diagram.py
  • tests/integration/test_gitignore_paths.py
  • nixie/unittests/test_verbose.py
  • tests/integration/test_no_args.py
  • nixie/cli.py
  • tests/integration/test_cli_behavior.py
**/unittests/test_*.py

📄 CodeRabbit inference engine (.rules/python-00.md)

Colocate unit tests with code in an unittests/ subdirectory using files prefixed with test_

Files:

  • nixie/unittests/test_render_diagram.py
  • nixie/unittests/test_verbose.py
{**/unittests/test_*.py,tests/integration/test_*.py}

📄 CodeRabbit inference engine (.rules/python-00.md)

{**/unittests/test_*.py,tests/integration/test_*.py}: Use pytest idioms: prefer fixtures, parametrize broadly, avoid unnecessary mocks
Group related tests using classes with method names prefixed by test_
Write tests from a user's perspective; test public behaviour, not internals
Avoid excessive mocking; use doubles only for external services or non-deterministic behaviour

Files:

  • nixie/unittests/test_render_diagram.py
  • tests/integration/test_gitignore_paths.py
  • nixie/unittests/test_verbose.py
  • tests/integration/test_no_args.py
  • tests/integration/test_cli_behavior.py
tests/integration/test_*.py

📄 CodeRabbit inference engine (.rules/python-00.md)

Place integration tests under tests/integration/ with files prefixed with test_

Files:

  • tests/integration/test_gitignore_paths.py
  • tests/integration/test_no_args.py
  • tests/integration/test_cli_behavior.py
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

**/*.md: Markdown files must pass markdown linting (make markdownlint)
Markdown files containing Mermaid diagrams must pass nixie validation (make nixie)

Files:

  • README.md

⚙️ CodeRabbit configuration file

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • README.md
**/README.md

📄 CodeRabbit inference engine (.rules/python-00.md)

Colocate README.md near reusable packages and include usage examples

Files:

  • README.md
🔍 Remote MCP Ref

Relevant facts for review (concise):

  • New Diagram dataclass added (slots, frozen) with fields: source (str), line_start (int), line_end (int), schema (str).
  • parse_blocks now returns list[Diagram], computes line_start/line_end using precomputed newline offsets + bisect to avoid O(N²), and derives schema via _extract_schema. Tests updated to assert positional metadata.
  • _extract_schema skips blank lines and lines starting with "%%", returns first token or UNKNOWN_SCHEMA fallback. UNKNOWN_SCHEMA exported.
  • diagram_markers context manager prints start ("--> line {line_start}: {schema}") before processing and end ("<-- line {line_end}: {schema}") on exit (flush=True), ensuring end marker on exceptions. Unit tests verify both markers and exception behavior.
  • check_file and overall CLI processing changed to process diagrams sequentially per file (for-loop) rather than concurrently; concurrency primitives and CLI option removed. Integration test added to assert per-diagram markers appear exactly once and in ascending order for a file with multiple diagrams.

Tools/sources used:

  • Ref (repository docs/search results) — results mentioning the PR diffs and code changes above.
🔇 Additional comments (9)
tests/integration/test_gitignore_paths.py (1)

30-31: Align integration tests with the new main(paths) API

Calls to main([Path(".")]) read cleanly and match the sequential rendering design. Assertions remain correct.

Also applies to: 50-51

nixie/unittests/test_verbose.py (1)

51-52: Update render_block invocations to match semaphore‑free signature

The changes reflect the public API and the tests continue to assert the intended logging/error behaviours.

Also applies to: 136-137, 165-166, 189-189, 215-216

nixie/unittests/test_render_diagram.py (1)

42-43: Conform tests to updated helpers and allowed‑executable guard

The adjustments to _render_diagram/_run_mermaid_cli signatures and the guard assertion look correct.

Also applies to: 76-77, 90-91

tests/integration/test_no_args.py (1)

30-33: Remove unused concurrency parameter from test doubles

The local fake_main stubs now match main(paths) precisely; exit semantics and captured paths assertions remain sound.

Also applies to: 56-60

tests/integration/test_cli_behavior.py (2)

86-86: Default to sequential main() for deterministic output — good change

Drop the explicit concurrency parameter and rely on the CLI’s sequential default to stabilise marker ordering. This directly removes prior flakiness risk around interleaved output.


113-113: Retain stable file-boundary ordering — good change

Invoke main() without a concurrency argument to keep file boundary markers ordered and repeatable.

README.md (3)

11-12: Document sequential per‑file processing for stable, bracketed output — good

State the guarantee explicitly; aligns the docs with the CLI refactor and the new tests.


69-71: Keep the example concise and aligned with semantics — good

The example matches the “start = first content line inside the fence, end = closing fence” rule and shows the echoed schema.


74-78: Clarify stdout/stderr streams — good

Explicitly document stream usage to aid CI/log consumers. This mirrors the actual behaviour and reduces surprises when stderr is treated specially.

Comment thread nixie/cli.py Outdated
Comment thread README.md Outdated
Comment thread README.md
Comment thread tests/integration/test_cli_behavior.py
Comment thread tests/integration/test_cli_behavior.py
Comment thread tests/integration/test_cli_behavior.py
@leynos

leynos commented Aug 22, 2025

Copy link
Copy Markdown
Owner Author

@coderabbitai pause

@coderabbitai

coderabbitai Bot commented Aug 22, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Reviews paused.

leynos and others added 12 commits August 23, 2025 08:10
Ensure per-diagram markers flush immediately so they bracket stderr reliably and add a unit test to cover the behavior.
- Resolve conflicts in README, nixie/cli.py, and tests
- Drop concurrency scaffolding; keep sequential, bracketed output
- Add --no-sandbox flag and pass through to Puppeteer config
- Reconcile tests to new main(paths, *, no_sandbox=False) signature
- Add minimal local pathspec shim for offline testing

Preserves branch intent (schema + line markers) while incorporating main’s
improvements. CI with real pathspec should ignore the shim.
@leynos
leynos force-pushed the codex/add-schema-name-printing-for-mermaid-diagrams branch from 9fac5c6 to 9d20227 Compare August 23, 2025 07:31
@leynos
leynos merged commit 0f288c8 into main Aug 23, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant