Skip to content

Address design feedback#13

Merged
leynos merged 7 commits intomainfrom
codex/action-feedback-on-design-review
Jul 13, 2025
Merged

Address design feedback#13
leynos merged 7 commits intomainfrom
codex/action-feedback-on-design-review

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Jul 13, 2025

Summary

  • explain netsuke IR's decoupling from Ninja
  • note deterministic build graph generation
  • clarify manifest validation error
  • expand action dedupe hashing rules
  • document diag-json option and graph visualiser
  • describe interpreter defaults and Windows behaviour
  • specify glob determinism
  • add security note for shell() filter
  • fix typos and naming details in the design doc
  • clarify how ins and outs placeholders are expanded and escaped

Testing

  • make fmt
  • make lint
  • make test
  • make markdownlint
  • make nixie

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

Summary by Sourcery

Update the design document to address various design feedback and clarify core behaviors

Documentation:

  • Clarify that the IR is fully decoupled from Ninja and guarantee deterministic build graph generation
  • Expand the action deduplication rules to include fully resolved command text, interpreter, and depfile options
  • Clarify manifest validation errors with a RecipeConflict error when rule, command, and script fields are mutually exclusive
  • Detail how {{ins}} and {{outs}} placeholders are expanded, escaped, and replaced with Ninja’s $in/$out
  • Describe script interpreter defaults (including Windows defaulting to PowerShell) and support for shebang lines
  • Note that glob results are sorted and symlinks followed for determinism
  • Document the --diag-json flag and the graph visualizer’s HTML viewer option
  • Explain that using shell() marks templates impure and disables caching of rendered YAML between stages
  • Fix typos, naming conventions (e.g., netsuke_version, filter naming), and table formatting in the design doc

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Jul 13, 2025

Reviewer's Guide

Update the netsuke design document to cover IR decoupling from Ninja and deterministic build graph generation, refine placeholder handling and action hashing, clarify interpreter and Windows script behavior, tighten manifest validation, and document new options and security notes alongside naming and typo corrections.

Class diagram for updated NetsukeManifest structure

classDiagram
    class NetsukeManifest {
        +String netsuke_version
        +HashMap<String, serde_yaml::Value> vars
        ...
    }
Loading

Class diagram for IR Action deduplication and hashing

classDiagram
    class Action {
        +String command_text
        +String interpreter
        +HashMap<String, Value> local_vars
        +Option<Depfile> depfile
        +hash(): String
    }
    Action : hash() uses command_text, interpreter, local_vars, depfile
Loading

Class diagram for Recipe enum validation

classDiagram
    class Recipe {
        <<enum>>
        +Rule
        +Command
        +Script
    }
    class RecipeConflictError {
        +String message
    }
    Recipe <|-- RecipeConflictError : emits on mutual exclusivity violation
Loading

Class diagram for placeholder expansion and escaping

classDiagram
    class CommandTemplate {
        +expand_ins_outs()
        +shell_escape()
    }
    CommandTemplate : expand_ins_outs() expands {{ins}} and {{outs}} to shell-escaped lists
    CommandTemplate : shell_escape() applies to all other interpolations
Loading

Class diagram for script interpreter selection and Windows behavior

classDiagram
    class Script {
        +String content
        +Option<String> interpreter
        +bool has_shebang()
        +get_interpreter()
    }
    Script : get_interpreter() returns shebang, manifest interpreter, or default
    Script : On Windows, default is powershell -Command
Loading

Class diagram for glob function determinism

classDiagram
    class GlobFunction {
        +glob(pattern: &str): Result<Vec<String>, Error>
    }
    GlobFunction : returns lexicographically sorted results
    GlobFunction : follows symlinks
Loading

Class diagram for shell() filter and caching behavior

classDiagram
    class ShellFilter {
        +apply()
        +impure: bool
    }
    ShellFilter : impure disables template caching between stages
Loading

File-Level Changes

Change Details Files
Document IR decoupling from Ninja and deterministic pipeline
  • Remove Ninja-specific syntax from the IR
  • Describe byte-for-byte reproducible build.ninja output
  • Highlight IR as stable contract for future backends
docs/netsuke-design.md
Clarify placeholder expansion and shell-escaping
  • Explain how {{ins}}/{{outs}} expand to space-separated, shell-escaped lists
  • Detail replacement of lists with $in/$out in generated Ninja files
  • Ensure non-ins/outs interpolations use automatic shell escaping
docs/netsuke-design.md
Expand action dedupe hashing criteria
  • Include fully resolved command text in hash
  • Add interpreter, local vars, and depfile options to dedupe key
docs/netsuke-design.md
Specify script interpreter defaults and Windows behavior
  • Support shebang lines and optional interpreter field (default /bin/sh -e)
  • Default to PowerShell on Windows unless overridden
  • Wrap multi-line scripts in interpreter invocation appropriately
docs/netsuke-design.md
Enforce manifest validation and RecipeConflict error
  • Validate mutual exclusivity of rule, command, and script
  • Emit RecipeConflict error with descriptive message on invalid manifests
docs/netsuke-design.md
Define glob determinism and mark shell() impure
  • Return glob results sorted lexicographically with symlink following
  • Document shell() filter as impure and disable template caching between stages
docs/netsuke-design.md
Document diag-json flag and graph visualiser
  • Add --diag-json for JSON-serialized error chains
  • Explain netsuke graph --html embedding Dagre.js viewer
docs/netsuke-design.md
Align naming conventions and fix typos
  • Rename Netsuke_version to netsuke_version
  • Standardize filters to snake_case and adjust version_compare default
  • Correct table formatting and minor naming errors
docs/netsuke-design.md

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
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 13, 2025

Warning

Rate limit exceeded

@leynos has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 3 minutes and 21 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 1f12f0d and b920a80.

📒 Files selected for processing (1)
  • docs/netsuke-design.md (16 hunks)

Summary by CodeRabbit

  • Documentation
    • Enhanced and clarified documentation on manifest schema, IR semantics, command construction, error handling, and CLI behaviour.
    • Added sequence and class diagrams to illustrate pipeline stages and manifest structure.
    • Updated field names, filter naming conventions, and corrected typos for improved accuracy.
    • Expanded explanations on script handling, command interpolation, and error reporting.
    • Described new CLI features, including enhanced graph output options and a diagnostic JSON flag.

Summary by CodeRabbit

  • Documentation

    • Improved and clarified documentation for manifest schema, IR generation, command and script handling, error reporting, CLI behaviour, and determinism.
    • Updated field names, filter naming conventions, and corrected typos for consistency and accuracy.
    • Expanded explanations on determinism, script execution, command security, and error handling.
  • New Features

    • Added a --diag-json flag to output error chains as JSON for editor and CI integration.
    • Enhanced the graph subcommand to support DOT output and HTML visualisation via an embedded Dagre.js viewer.
  • Bug Fixes

    • Corrected field and filter names, typos, and clarified error handling scenarios.
    • Enforced exclusivity of rule, command, and script fields in targets with explicit RecipeConflict error.

Walkthrough

Update the Netsuke design documentation to clarify and expand details on manifest schema, IR generation, command and script handling, error reporting, CLI behaviour, and determinism. Correct field names, enforce recipe field exclusivity, standardise naming conventions, and describe new CLI features and output formats.

Changes

File(s) Change Summary
docs/netsuke-design.md Clarify manifest schema, IR semantics, command/script handling, error handling, CLI features, and naming conventions. Add diagrams, enforce exclusivity, update technology summary, and describe deterministic output and new CLI flags.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Netsuke CLI
    participant Manifest Parser
    participant IR Generator
    participant Ninja Synthesiser
    participant Ninja (Subprocess)

    User->>Netsuke CLI: Invoke build/graph/other subcommand
    Netsuke CLI->>Manifest Parser: Parse manifest (validate fields, enforce exclusivity)
    Manifest Parser->>IR Generator: Produce backend-agnostic IR (expand commands, resolve scripts)
    IR Generator->>Ninja Synthesiser: Generate build.ninja (replace macros, shell-escape paths)
    Ninja Synthesiser->>Ninja (Subprocess): Invoke ninja for actual build
    Ninja (Subprocess)-->>User: Output build results

    alt Error occurs
        Netsuke CLI-->>User: Emit error (optionally as JSON with --diag-json)
    end
Loading

Possibly related PRs

Poem

In the land of Netsuke, docs shine anew,
With commands now escaped and the schema in view.
Errors get JSON, graphs show with flair,
Deterministic builds—byte-perfect and rare!
So raise a shell-quoted toast,
To clarity, precision, and design we boast!
🎉🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/action-feedback-on-design-review

🪧 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.
    • Explain this complex logic.
    • 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. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

Documentation and Community

  • 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.

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey @leynos - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `docs/netsuke-design.md:1189` </location>
<code_context>
-  using tools like Graphviz. This allows users to visually inspect their build
-  dependencies, which is invaluable for understanding and debugging complex
-  projects.
+  with the graph tool, `ninja -t graph`.3 This outputs the complete build
+  dependency graph in the DOT language. The result can be piped through `dot
+  -Tsvg` or displayed via `netsuke graph --html` using an embedded Dagre.js
</code_context>

<issue_to_address>
Possible stray '.3' after 'ninja -t graph'; clarify or remove.

'.3' seems to be an unintended typo; please clarify its purpose or remove it.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
  run the Netsuke pipeline up to Stage 4 (IR Generation) and then invoke Ninja
  with the graph tool, `ninja -t graph`.3 This outputs the complete build
  dependency graph in the DOT language. The result can be piped through `dot
  -Tsvg` or displayed via `netsuke graph --html` using an embedded Dagre.js
=======
  run the Netsuke pipeline up to Stage 4 (IR Generation) and then invoke Ninja
  with the graph tool, `ninja -t graph`. This outputs the complete build
  dependency graph in the DOT language. The result can be piped through `dot
  -Tsvg` or displayed via `netsuke graph --html` using an embedded Dagre.js
>>>>>>> REPLACE

</suggested_fix>

### Comment 2
<location> `docs/netsuke-design.md:83` </location>
<code_context>
+   Netsuke's pipeline is **deterministic**. Given the same `Netsukefile` and
+   environment variables, the generated `build.ninja` will be byte-for-byte
+   identical. This property is essential for reproducible builds and makes the
+   output suitable for caching or source control.
+
 ### 1.3 The Static Graph Mandate
</code_context>

<issue_to_address>
Paragraph exceeds 80 columns; please wrap to 80 columns as per guidelines.

The added paragraph about determinism is not wrapped to 80 columns. Please reformat it so that no line exceeds 80 characters, in accordance with the documentation style guide.
</issue_to_address>

### Comment 3
<location> `docs/netsuke-design.md:674` </location>
<code_context>
 | `snake_case` / `camel_case` / `kebab-case` | Rename helpers                                                       |
-| `shell_escape`                             | POSIX-quote for safe `$()` usage                                     |
+
+All built-in filters use `snake_case`. The `camel_case` helper is provided in
+place of `camelCase` so naming remains consistent with `snake_case` and `kebab-
+case`.
</code_context>

<issue_to_address>
Paragraph exceeds 80 columns; please wrap to 80 columns.

The paragraph about built-in filters and naming conventions is not wrapped to 80 columns. Please adjust the formatting.
</issue_to_address>

### Comment 4
<location> `docs/netsuke-design.md:699` </location>
<code_context>
 | `grep`, `sed`, `awk`, `cut`, `wc`, `tr`               | filters      | Canonical wrappers implemented via `shell()` for convenience     |

+Using `shell()` marks the template as *impure* and disables caching of the
+rendered YAML between Stage&nbsp;2 and Stage&nbsp;3. This avoids accidental
+reuse of results that depend on external commands.
+
</code_context>

<issue_to_address>
Line exceeds 80 columns; please wrap to 80 columns.

The line about rendered YAML and caching is longer than 80 columns. Please wrap it to comply with the documentation guidelines.
</issue_to_address>

### Comment 5
<location> `docs/netsuke-design.md:865` </location>
<code_context>
-   Ninja's variables (`$in`, `$out`).
+   `ir::Action`, write a corresponding Ninja `rule` statement. The input and
+   output lists stored in the action replace the `ins` and `outs` placeholders.
+   These lists are then rewritten as Ninja's `$in` and `$out`

    When an action's `recipe` is a script, the generated rule wraps the script
</code_context>

<issue_to_address>
Line exceeds 80 columns; please wrap to 80 columns.

The line about rewriting lists as Ninja's variables is longer than 80 columns. Please wrap it.
</issue_to_address>

### Comment 6
<location> `docs/netsuke-design.md:978` </location>
<code_context>
+and build the final command string step by step. The placeholders `{{ ins }}
+` and `{{ outs }}` are expanded to space-separated lists of file paths within
+Netsuke itself. Each path is shell escaped using the `shell-quote` API. When the
+command is written to `build.ninja`, these lists are replaced with Ninja's `$in`
+and `$out` macros. After substitution the command is validated with [`shlex`]
+(<https://docs.rs/shlex/latest/shlex/>) to ensure it parses correctly. This
</code_context>

<issue_to_address>
Line exceeds 80 columns; please wrap to 80 columns.

The line about writing to `build.ninja` is longer than 80 columns. Please wrap it.
</issue_to_address>

### Comment 7
<location> `docs/netsuke-design.md:1190` </location>
<code_context>
-  dependencies, which is invaluable for understanding and debugging complex
-  projects.
+  with the graph tool, `ninja -t graph`.3 This outputs the complete build
+  dependency graph in the DOT language. The result can be piped through `dot
+  -Tsvg` or displayed via `netsuke graph --html` using an embedded Dagre.js
+  viewer. Visualising the graph is invaluable for understanding and debugging
</code_context>

<issue_to_address>
Line exceeds 80 columns; please wrap to 80 columns.

The line about the DOT language and piping is not wrapped to 80 columns. Please reformat it.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread docs/netsuke-design.md
Comment thread docs/netsuke-design.md
Comment thread docs/netsuke-design.md
Comment thread docs/netsuke-design.md
Comment thread docs/netsuke-design.md Outdated
Comment thread docs/netsuke-design.md Outdated
Comment thread docs/netsuke-design.md
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 12

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3ff0f82 and 4f88bb2.

📒 Files selected for processing (1)
  • docs/netsuke-design.md (16 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
docs/**/*.md

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • AGENTS.md
**/*.md

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • AGENTS.md

⚙️ CodeRabbit Configuration File

🧠 Learnings (1)
docs/netsuke-design.md (1)
Learnt from: CR
PR: leynos/netsuke#0
File: docs/netsuke-design.md:0-0
Timestamp: 2025-07-12T13:36:08.546Z
Learning: Applies to docs/src/ninja_gen.rs : All command variable substitutions in the Ninja file generator must use the 'shell-quote' crate for shell escaping; do not use simple string formatting (like format!) for command construction.
🪛 LanguageTool
docs/netsuke-design.md

[uncategorized] ~176-~176: Loose punctuation mark.
Context: ...ng identifier for the rule. - command: A single command string to be executed....

(UNLIKELY_OPENING_PUNCTUATION)


[style] ~182-~182: Consider using a more formal/concise alternative here.
Context: ...x/latest/> shlex/). Any interpolation other than ins or outs is automatically shell ...

(OTHER_THAN)


[uncategorized] ~185-~185: Loose punctuation mark.
Context: ...tomatically shell escaped. - script: A multi-line script declared with the Y...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~186-~186: Possible missing comma found.
Context: ...n interpreter. If the first line begins with #! Netsuke executes the script ver...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~187-~187: A comma may be missing after the conjunctive/linking adverb ‘Otherwise’.
Context: ...cript verbatim, respecting the shebang. Otherwise the block is wrapped in the interpret...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)


[style] ~233-~233: Would you like to use the Oxford spelling “deserialization”? The spelling ‘deserialisation’ is also correct.
Context: ...arser validates this exclusivity during deserialisation. If multiple fields are provided, Netsu...

(OXFORD_SPELLING_Z_NOT_S)


[grammar] ~865-~865: Please add a punctuation mark at the end of paragraph.
Context: ...sts are then rewritten as Ninja's $in and $out When an action's recipe is...

(PUNCTUATION_PARAGRAPH_END)


[style] ~942-~942: Would you like to use the Oxford spelling “minimize”? The spelling ‘minimise’ is also correct.
Context: ...oot. This early acknowledgement aims to minimise surprises on CI systems. ### 6.2 The C...

(OXFORD_SPELLING_Z_NOT_S)


[uncategorized] ~979-~979: Possible missing comma found.
Context: ... Ninja's $in and $out macros. After substitution the command is validated with [shlex]...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~1090-~1090: Possible missing comma found.
Context: ...to the specific. For automation use cases Netsuke will support a --diag-json fl...

(AI_HYDRA_LEO_MISSING_COMMA)


[style] ~1091-~1091: Would you like to use the Oxford spelling “serialized”? The spelling ‘serialised’ is also correct.
Context: ...When enabled, the entire error chain is serialised to JSON, allowing editors and CI tools ...

(OXFORD_SPELLING_Z_NOT_S)


[style] ~1192-~1192: Would you like to use the Oxford spelling “Visualizing”? The spelling ‘Visualising’ is also correct.
Context: ...l` using an embedded Dagre.js viewer. Visualising the graph is invaluable for understandi...

(OXFORD_SPELLING_Z_NOT_S)

Comment thread docs/netsuke-design.md
Comment thread docs/netsuke-design.md
Comment thread docs/netsuke-design.md Outdated
Comment thread docs/netsuke-design.md
Comment thread docs/netsuke-design.md
Comment thread docs/netsuke-design.md
Comment thread docs/netsuke-design.md
Comment thread docs/netsuke-design.md
Comment thread docs/netsuke-design.md Outdated
Comment thread docs/netsuke-design.md Outdated
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 13, 2025

@sourcery-ai resolve

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 13, 2025

@sourcery-ai review

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey @leynos - I've reviewed your changes - here's some feedback:

  • Move the Windows PowerShell default into the interpreter section so that all script interpreter behavior (including shebang and OS-specific defaults) is documented together.
  • Use a single placeholder notation ({{ ins }}/{{ outs }}) consistently rather than mixing in {ins} forms to avoid confusion.
  • Standardize on either American or British spelling (e.g. “synthesizes” vs “synthesises”) throughout the document for a consistent style.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Move the Windows PowerShell default into the interpreter section so that all script interpreter behavior (including shebang and OS-specific defaults) is documented together.
- Use a single placeholder notation (`{{ ins }}`/`{{ outs }}`) consistently rather than mixing in `{ins}` forms to avoid confusion.
- Standardize on either American or British spelling (e.g. “synthesizes” vs “synthesises”) throughout the document for a consistent style.

## Individual Comments

### Comment 1
<location> `docs/netsuke-design.md:75` </location>
<code_context>

    The final, validated IR is traversed by a code generator. This generator
-   synthesizes the content of a build.ninja file, translating the IR's nodes
+   synthesises the content of a `build.ninja` file, translating the IR's nodes
    and edges into corresponding Ninja rule and build statements. Once the file
-   is written, Netsuke invokes the ninja executable as a subprocess, passing
</code_context>

<issue_to_address>
Inconsistent spelling: 'synthesises' vs. 'synthesizes'.

Since the rest of the document uses American English, please use 'synthesizes' for consistency.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
   synthesises the content of a `build.ninja` file, translating the IR's nodes
=======
   synthesizes the content of a `build.ninja` file, translating the IR's nodes
>>>>>>> REPLACE

</suggested_fix>

### Comment 2
<location> `docs/netsuke-design.md:232` </location>
<code_context>
-  Only one of `rule`, `command`, or `script` may be specified. The parser
-  validates this exclusivity during deserialisation.
+Only one of `rule`, `command`, or `script` may be specified. The parser
+validates this exclusivity during deserialisation. If multiple fields are
+provided, Netsuke emits a `RecipeConflict` error with the message "rule, command
+and script are mutually exclusive".
</code_context>

<issue_to_address>
Inconsistent spelling: 'deserialisation' vs. 'deserialization'.

Use 'deserialization' to match the rest of the document's American English spelling.

Suggested implementation:

```
Only one of `rule`, `command`, or `script` may be specified. The parser
validates this exclusivity during deserialization. If multiple fields are
provided, Netsuke emits a `RecipeConflict` error with the message "rule, command
and script are mutually exclusive".

```

```
  This union deserializes into the same `Recipe` enum used for rules. The parser
  enforces that only one variant is present, maintaining backward compatibility

```
</issue_to_address>

### Comment 3
<location> `docs/netsuke-design.md:1090` </location>
<code_context>
    the specific.

+For automation use cases, Netsuke will support a `--diag-json` flag. When
+enabled, the entire error chain is serialised to JSON, allowing editors and CI
+tools to annotate failures inline.
+
</code_context>

<issue_to_address>
Inconsistent spelling: 'serialised' vs. 'serialized'.

Please update to 'serialized' to match American English usage throughout the document.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
For automation use cases, Netsuke will support a `--diag-json` flag. When
enabled, the entire error chain is serialised to JSON, allowing editors and CI
tools to annotate failures inline.
=======
For automation use cases, Netsuke will support a `--diag-json` flag. When
enabled, the entire error chain is serialized to JSON, allowing editors and CI
tools to annotate failures inline.
>>>>>>> REPLACE

</suggested_fix>

### Comment 4
<location> `docs/netsuke-design.md:75` </location>
<code_context>

    The final, validated IR is traversed by a code generator. This generator
-   synthesizes the content of a build.ninja file, translating the IR's nodes
+   synthesises the content of a `build.ninja` file, translating the IR's nodes
    and edges into corresponding Ninja rule and build statements. Once the file
-   is written, Netsuke invokes the ninja executable as a subprocess, passing
</code_context>

<issue_to_address>
"synthesises" uses en-gb spelling; en-oxendic (Oxford English) prefers "synthesizes".

Oxford English (en-oxendic) spelling prefers "-ize" endings, so "synthesizes" should be used instead of "synthesises".
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread docs/netsuke-design.md Outdated

The final, validated IR is traversed by a code generator. This generator
synthesizes the content of a build.ninja file, translating the IR's nodes
synthesises the content of a `build.ninja` file, translating the IR's nodes
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.

suggestion (typo): Inconsistent spelling: 'synthesises' vs. 'synthesizes'.

Since the rest of the document uses American English, please use 'synthesizes' for consistency.

Suggested change
synthesises the content of a `build.ninja` file, translating the IR's nodes
synthesizes the content of a `build.ninja` file, translating the IR's nodes

Comment thread docs/netsuke-design.md Outdated
Only one of `rule`, `command`, or `script` may be specified. The parser
validates this exclusivity during deserialisation.
Only one of `rule`, `command`, or `script` may be specified. The parser
validates this exclusivity during deserialisation. If multiple fields are
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.

suggestion (typo): Inconsistent spelling: 'deserialisation' vs. 'deserialization'.

Use 'deserialization' to match the rest of the document's American English spelling.

Suggested implementation:

Only one of `rule`, `command`, or `script` may be specified. The parser
validates this exclusivity during deserialization. If multiple fields are
provided, Netsuke emits a `RecipeConflict` error with the message "rule, command
and script are mutually exclusive".

  This union deserializes into the same `Recipe` enum used for rules. The parser
  enforces that only one variant is present, maintaining backward compatibility

Comment thread docs/netsuke-design.md
Comment on lines +1089 to +1091
For automation use cases, Netsuke will support a `--diag-json` flag. When
enabled, the entire error chain is serialised to JSON, allowing editors and CI
tools to annotate failures inline.
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.

suggestion (typo): Inconsistent spelling: 'serialised' vs. 'serialized'.

Please update to 'serialized' to match American English usage throughout the document.

Suggested change
For automation use cases, Netsuke will support a `--diag-json` flag. When
enabled, the entire error chain is serialised to JSON, allowing editors and CI
tools to annotate failures inline.
For automation use cases, Netsuke will support a `--diag-json` flag. When
enabled, the entire error chain is serialized to JSON, allowing editors and CI
tools to annotate failures inline.

Comment thread docs/netsuke-design.md Outdated

The final, validated IR is traversed by a code generator. This generator
synthesizes the content of a build.ninja file, translating the IR's nodes
synthesises the content of a `build.ninja` file, translating the IR's nodes
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.

suggestion (review_instructions): "synthesises" uses en-gb spelling; en-oxendic (Oxford English) prefers "synthesizes".

Oxford English (en-oxendic) spelling prefers "-ize" endings, so "synthesizes" should be used instead of "synthesises".

Review instructions:

Path patterns: **/*.md

Instructions:
Use en-oxendic spelling and grammar.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (8)
docs/netsuke-design.md (8)

75-83: Wrap Stage 5 paragraph to ≤ 80 columns

Lines 75 – 83 still exceed the mandated 80-column limit. Hard-wrap them without altering content.


575-578: Wrap glob determinism sentence

These lines remain over 80 columns; fold them.


673-675: Wrap filter-naming explanation

Line length still violates MD013. Re-wrap.


697-700: Wrap shell() impurity note

Lines exceed 80 columns; break lines accordingly.


831-835: Wrap action-dedup bullet

Still over 80 columns; re-flow.


973-980: Re-wrap command-generation guidance

Lines exceed 80 columns; fold them.


1090-1092: Limit --diag-json explanation to 80 columns

Line length still violates style guide.


1187-1192: Wrap graph command description

Lines are wider than allowed; re-wrap.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4f88bb2 and 556c370.

📒 Files selected for processing (1)
  • docs/netsuke-design.md (16 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
docs/**/*.md

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • AGENTS.md
**/*.md

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • AGENTS.md

⚙️ CodeRabbit Configuration File

🧠 Learnings (1)
docs/netsuke-design.md (1)
Learnt from: CR
PR: leynos/netsuke#0
File: docs/netsuke-design.md:0-0
Timestamp: 2025-07-12T13:36:08.546Z
Learning: Applies to docs/src/ninja_gen.rs : All command variable substitutions in the Ninja file generator must use the 'shell-quote' crate for shell escaping; do not use simple string formatting (like format!) for command construction.
🪛 LanguageTool
docs/netsuke-design.md

[style] ~75-~75: Would you like to use the Oxford spelling “synthesizes”? The spelling ‘synthesises’ is also correct.
Context: ... by a code generator. This generator synthesises the content of a build.ninja file, tr...

(OXFORD_SPELLING_Z_NOT_S)


[uncategorized] ~176-~176: Loose punctuation mark.
Context: ...ng identifier for the rule. - command: A single command string to be executed....

(UNLIKELY_OPENING_PUNCTUATION)


[style] ~182-~182: Consider using a more formal/concise alternative here.
Context: ...lex/latest/shlex/). Any interpolation other than ins or outs is automatically shell-...

(OTHER_THAN)


[uncategorized] ~184-~184: Loose punctuation mark.
Context: ...automatically shell-escaped. - script: A multi-line script declared with the Y...

(UNLIKELY_OPENING_PUNCTUATION)


[style] ~232-~232: Would you like to use the Oxford spelling “deserialization”? The spelling ‘deserialisation’ is also correct.
Context: ...arser validates this exclusivity during deserialisation. If multiple fields are provided, Netsu...

(OXFORD_SPELLING_Z_NOT_S)


[style] ~941-~941: Would you like to use the Oxford spelling “minimize”? The spelling ‘minimise’ is also correct.
Context: ...oot. This early acknowledgement aims to minimise surprises on CI systems. ### 6.2 The C...

(OXFORD_SPELLING_Z_NOT_S)


[style] ~1090-~1090: Would you like to use the Oxford spelling “serialized”? The spelling ‘serialised’ is also correct.
Context: ...When enabled, the entire error chain is serialised to JSON, allowing editors and CI tools ...

(OXFORD_SPELLING_Z_NOT_S)


[style] ~1191-~1191: Would you like to use the Oxford spelling “Visualizing”? The spelling ‘Visualising’ is also correct.
Context: ...l` using an embedded Dagre.js viewer. Visualising the graph is invaluable for understandi...

(OXFORD_SPELLING_Z_NOT_S)

Comment thread docs/netsuke-design.md Outdated
Comment thread docs/netsuke-design.md Outdated
Comment thread docs/netsuke-design.md
Comment on lines +748 to +752
Importantly, the IR contains **no Ninja-isms**. Placeholders such as `$in`
and `$out` are resolved to plain lists of file paths, and command strings are
expanded before hashing. This deliberate absence of Ninja-specific syntax makes
the IR a stable contract that future back-ends—distributed builders, remote
executors, or otherwise—can consume without modification.
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.

🧹 Nitpick (assertive)

Wrap “no Ninja-isms” paragraph

Lines 748 – 752 surpass 80 columns. Hard-wrap them.

-Importantly, the IR contains **no Ninja-isms**. Placeholders such as `$in`
-and `$out` are resolved to plain lists of file paths, and command strings are
-expanded before hashing. This deliberate absence of Ninja-specific syntax makes
-the IR a stable contract that future back-ends—distributed builders, remote
-executors, or otherwise—can consume without modification.
+Importantly, the IR contains **no Ninja-isms**. Placeholders such as `$in`
+and `$out` are resolved to plain lists of file paths, and command strings
+are expanded before hashing. This deliberate absence of Ninja-specific
+syntax makes the IR a stable contract that future back-ends—distributed
+builders, remote executors, or otherwise—can consume without modification.
📝 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
Importantly, the IR contains **no Ninja-isms**. Placeholders such as `$in`
and `$out` are resolved to plain lists of file paths, and command strings are
expanded before hashing. This deliberate absence of Ninja-specific syntax makes
the IR a stable contract that future back-ends—distributed builders, remote
executors, or otherwise—can consume without modification.
Importantly, the IR contains **no Ninja-isms**. Placeholders such as `$in`
and `$out` are resolved to plain lists of file paths, and command strings
are expanded before hashing. This deliberate absence of Ninja-specific
syntax makes the IR a stable contract that future back-ends—distributed
builders, remote executors, or otherwise—can consume without modification.
🤖 Prompt for AI Agents
In docs/netsuke-design.md around lines 748 to 752, the paragraph containing "no
Ninja-isms" exceeds 80 columns. Reformat this paragraph by inserting line breaks
to hard-wrap the text at or before 80 characters per line, ensuring readability
and adherence to style guidelines.

Comment thread docs/netsuke-design.md
Comment on lines +176 to 183
- `command`: A single command string to be executed. It may include the
placeholders `{{ ins }}` and `{{ outs }}` to represent input and output files.
Netsuke expands these placeholders to space-separated, shell-escaped lists
of file paths before hashing the action. When generating the Ninja rule, the
lists are replaced with Ninja's `$in` and `$out` macros. After interpolation
the command must be parsable by [shlex](https://docs.rs/shlex/latest/shlex/).
Any interpolation other than `ins` or `outs` is automatically shell-escaped.

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.

🧹 Nitpick (assertive)

Enforce 80-column wrap for command bullet

The bullet describing command still breaches the 80-column policy. Re-flow it.

-  - `command`: A single command string to be executed. It may include the
-  placeholders `{{ ins }}` and `{{ outs }}` to represent input and output files.
-  Netsuke expands these placeholders to space-separated, shell-escaped lists
-  of file paths before hashing the action. When generating the Ninja rule, the
-  lists are replaced with Ninja's `$in` and `$out` macros. After interpolation
-  the command must be parsable by [shlex](https://docs.rs/shlex/latest/shlex/).
-  Any interpolation other than `ins` or `outs` is automatically shell-escaped.
+  - `command`: A single command string to be executed. It may include the
+    placeholders `{{ ins }}` and `{{ outs }}` to represent input and output
+    files. Netsuke expands these placeholders to space-separated,
+    shell-escaped lists of file paths before hashing the action. When
+    generating the Ninja rule, the lists are replaced with Ninja's `$in` and
+    `$out` macros. After interpolation, the command must be parsable by
+    [shlex](https://docs.rs/shlex/latest/shlex/). All other interpolations are
+    shell-escaped automatically.
📝 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
- `command`: A single command string to be executed. It may include the
placeholders `{{ ins }}` and `{{ outs }}` to represent input and output files.
Netsuke expands these placeholders to space-separated, shell-escaped lists
of file paths before hashing the action. When generating the Ninja rule, the
lists are replaced with Ninja's `$in` and `$out` macros. After interpolation
the command must be parsable by [shlex](https://docs.rs/shlex/latest/shlex/).
Any interpolation other than `ins` or `outs` is automatically shell-escaped.
- `command`: A single command string to be executed. It may include the
placeholders `{{ ins }}` and `{{ outs }}` to represent input and output
files. Netsuke expands these placeholders to space-separated,
shell-escaped lists of file paths before hashing the action. When
generating the Ninja rule, the lists are replaced with Ninja's `$in` and
`$out` macros. After interpolation, the command must be parsable by
[shlex](https://docs.rs/shlex/latest/shlex/). All other interpolations are
shell-escaped automatically.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~176-~176: Loose punctuation mark.
Context: ...ng identifier for the rule. - command: A single command string to be executed....

(UNLIKELY_OPENING_PUNCTUATION)


[style] ~182-~182: Consider using a more formal/concise alternative here.
Context: ...lex/latest/shlex/). Any interpolation other than ins or outs is automatically shell-...

(OTHER_THAN)

🤖 Prompt for AI Agents
In docs/netsuke-design.md around lines 176 to 183, the bullet describing the
`command` field exceeds the 80-column line length limit. Reformat the text by
breaking long lines into shorter ones, ensuring each line does not exceed 80
characters while maintaining the original meaning and clarity.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 13, 2025

@coderabbitai Please create a class diagram for the item types in a Netsukefile

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 13, 2025

Tip

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

🧩 Analysis chain

I'll help you create a class diagram for the item types in a Netsukefile. Let me first explore the codebase to understand the structure and types defined for the Netsuke manifest.

Based on my exploration of the codebase, here's a comprehensive class diagram for the item types in a Netsukefile:

classDiagram
    class NetsukeManifest {
        +String netsuke_version
        +HashMap&lt;String, Value&gt; vars
        +HashMap&lt;String, Target&gt; targets
        +HashMap&lt;String, Rule&gt; rules
    }

    class Target {
        +Vec&lt;String&gt; ins
        +Vec&lt;String&gt; outs
        +Option&lt;Vec&lt;String&gt;&gt; deps
        +Recipe recipe
        +Option&lt;HashMap&lt;String, Value&gt;&gt; vars
        +Option&lt;String&gt; depfile
        +Option&lt;String&gt; pool
        +Option&lt;String&gt; description
    }

    class Recipe <<enumeration>> {
        +Rule(String)
        +Command(String)
        +Script(Script)
    }

    class Rule {
        +String command
        +Option&lt;String&gt; description
        +Option&lt;String&gt; depfile
        +Option&lt;String&gt; pool
        +Option&lt;String&gt; generator
        +Option&lt;String&gt; restat
        +Option&lt;HashMap&lt;String, Value&gt;&gt; vars
    }

    class Script {
        +String content
        +Option&lt;String&gt; interpreter
        +Option&lt;HashMap&lt;String, Value&gt;&gt; vars
    }

    class Value <<serde_yaml::Value>> {
        +Null
        +Bool(bool)
        +Number(Number)
        +String(String)
        +Sequence(Sequence)
        +Mapping(Mapping)
        +Tagged(Tagged)
    }

    NetsukeManifest ||--o{ Target : contains
    NetsukeManifest ||--o{ Rule : contains
    NetsukeManifest ||--o{ Value : vars
    Target ||--|| Recipe : has
    Recipe ||--o| Script : contains
    Target ||--o{ Value : vars
    Rule ||--o{ Value : vars
    Script ||--o{ Value : vars

    note for Recipe "Mutually exclusive variants:\n- Rule: references a rule by name\n- Command: inline command string\n- Script: embedded script with interpreter"
    note for NetsukeManifest "Top-level manifest structure\nValidates netsuke_version compatibility"
    note for Target "Build target with inputs/outputs\nRecipe field determines how to build"
    note for Script "Supports shebang detection\nDefault interpreter: /bin/sh -e\nWindows default: powershell -Command"
Loading

@leynos, this class diagram shows the main item types that can be defined in a Netsukefile:

  1. NetsukeManifest - The root structure containing global variables, targets, and rules
  2. Target - Individual build targets with inputs, outputs, dependencies, and a recipe
  3. Recipe - An enum defining how to build a target (rule reference, inline command, or script)
  4. Rule - Reusable build rules that can be referenced by targets
  5. Script - Embedded scripts with optional interpreter specification
  6. Value - Generic YAML values used for variables throughout the manifest

The key relationships are:

  • A manifest contains multiple targets and rules
  • Each target has exactly one recipe (mutually exclusive: rule reference, command, or script)
  • Variables can be defined at multiple levels (manifest, target, rule, script)
  • The Recipe enum enforces the exclusivity documented in your PR (RecipeConflict error)

🏁 Script executed:

#!/bin/bash
# Find files that likely contain the manifest/AST structure definitions
fd -e rs | head -20
echo "=== Searching for manifest/AST related files ==="
fd -e rs | grep -E "(ast|manifest|schema|types)" 
echo "=== Searching for NetsukeManifest struct definition ==="
ast-grep --pattern 'struct NetsukeManifest { $$$ }'

Length of output: 366


🏁 Script executed:

#!/bin/bash
# Look for the Recipe enum definition and related types
echo "=== Searching for Recipe enum ==="
ast-grep --pattern 'enum Recipe { $$$ }'
echo "=== Searching for Target struct ==="
ast-grep --pattern 'struct Target { $$$ }'
echo "=== Searching for Rule struct ==="
ast-grep --pattern 'struct Rule { $$$ }'

Length of output: 365


🏁 Script executed:

#!/bin/bash
# Let's examine the main AST/structure files
echo "=== Contents of src/ast.rs ==="
cat src/ast.rs | head -100
echo "=== Searching for all struct definitions in the codebase ==="
ast-grep --pattern 'struct $_ { $$$ }' | head -50

Length of output: 325


🏁 Script executed:

#!/bin/bash
# Get the full structure of the main types
echo "=== Full NetsukeManifest definition ==="
rg -A 20 "struct NetsukeManifest"
echo "=== Full Recipe definition ==="
rg -A 15 "enum Recipe"
echo "=== Target and related types ==="
rg -A 10 "struct Target"

Length of output: 2448


🏁 Script executed:

#!/bin/bash
# Look for any additional type definitions that might be relevant
echo "=== Other enum definitions ==="
rg "^#\[derive.*\]\s*enum" -A 5
echo "=== Serde-related structs for manifest parsing ==="
rg "#\[serde" -A 3 src/ast.rs

Length of output: 298


Let me get the complete structure definitions from the documentation:

Based on the complete structure definitions I found in the documentation, here's a comprehensive class diagram for the item types in a Netsukefile:

classDiagram
    class NetsukeManifest {
        +String netsuke_version
        +HashMap~String, Value~ vars
        +Vec~Rule~ rules
        +Vec~Target~ actions
        +Vec~Target~ targets
        +Vec~String~ defaults
    }
    
    class Target {
        +StringOrList name
        +Recipe recipe
        +StringOrList sources
        +StringOrList deps
        +HashMap~String, Value~ vars
        +Option~String~ depfile
        +Option~String~ pool
        +Option~String~ description
    }
    
    class Recipe {
        <<enumeration>>
        +Command~command: String~
        +Script~script: String~
        +Rule~rule: StringOrList~
    }
    
    class Rule {
        +String name
        +String command
        +Option~String~ description
        +Option~String~ depfile
        +Option~String~ pool
        +Option~String~ generator
        +Option~String~ restat
        +HashMap~String, Value~ vars
    }
    
    class StringOrList {
        <<union type>>
        +String
        +Vec~String~
    }
    
    class Value {
        <<serde_yaml::Value>>
        +Null
        +Bool~bool~
        +Number~Number~
        +String~String~
        +Sequence~Sequence~
        +Mapping~Mapping~
        +Tagged~Tagged~
    }
    
    %% Relationships
    NetsukeManifest ||--o{ Target : "contains actions/targets"
    NetsukeManifest ||--o{ Rule : "contains rules"
    NetsukeManifest ||--o{ Value : "global vars"
    NetsukeManifest ||--o{ String : "defaults"
    
    Target ||--|| Recipe : "has recipe"
    Target ||--|| StringOrList : "name, sources, deps"
    Target ||--o{ Value : "local vars"
    
    Recipe ||--o| String : "command/script content"
    Recipe ||--o| StringOrList : "rule reference"
    
    Rule ||--|| String : "name, command"
    Rule ||--o{ Value : "local vars"
    Rule ||--o| String : "optional fields"
    
    %% Constraints and notes
    note for Recipe "Mutually exclusive variants enforce RecipeConflict:<br/>- Command: inline command string<br/>- Script: embedded script content<br/>- Rule: reference to named rule"
    
    note for NetsukeManifest "Root manifest structure<br/>- netsuke_version for compatibility<br/>- actions: deprecated alias for targets<br/>- defaults: default target names"
    
    note for Target "Build targets with I/O specification<br/>- name: output file(s)<br/>- sources: input file(s)<br/>- deps: order-only dependencies"
    
    note for StringOrList "Flexible string specification<br/>Single string or list of strings<br/>Used for file paths and references"
    
    note for Rule "Reusable command templates<br/>Referenced by name from Recipe::Rule<br/>Support Jinja2 templating with vars"
Loading

@leynos, this class diagram shows all the item types that can be defined in a Netsukefile:

Core Types:

  • NetsukeManifest - Root structure with version, global variables, rules, targets, and defaults
  • Target - Build targets specifying inputs (sources), outputs (name), dependencies (deps), and how to build (recipe)
  • Recipe - Enum defining three mutually exclusive ways to specify build commands
  • Rule - Named, reusable command templates that can be referenced by targets

Supporting Types:

  • StringOrList - Union type allowing either a single string or list of strings for flexible file specification
  • Value - Generic YAML values for variables at all levels

Key Design Features:

  1. Recipe Exclusivity - The Recipe enum enforces that targets use exactly one of: rule reference, inline command, or embedded script
  2. Variable Scoping - Variables can be defined at manifest, rule, and target levels
  3. Flexible I/O - StringOrList allows both single files and file lists for inputs/outputs
  4. Template System - Rules support Jinja2 templating with variable substitution
  5. Backwards Compatibility - actions field is a deprecated alias for targets

This structure supports the deterministic build graph generation and IR decoupling documented in your PR!


🏁 Script executed:

#!/bin/bash
# Get complete Target struct definition
echo "=== Complete Target definition ==="
rg -A 30 "pub struct Target"
echo "=== Complete Rule definition ==="
rg -A 20 "pub struct Rule"
echo "=== StringOrList definition ==="
rg -A 10 "StringOrList"

Length of output: 5878


🏁 Script executed:

#!/bin/bash
# Let's see the full context around these definitions in the design doc
echo "=== Full manifest schema section ==="
rg -B 5 -A 50 "pub struct NetsukeManifest" docs/netsuke-design.md

Length of output: 1541


Perfect! Now I have the complete structure definitions. Here's the accurate class diagram for the item types in a Netsukefile:

classDiagram
    class NetsukeManifest {
        +String netsuke_version
        +HashMap~String, Value~ vars
        +Vec~Rule~ rules
        +Vec~Target~ actions
        +Vec~Target~ targets
        +Vec~String~ defaults
    }
    
    class Target {
        +StringOrList name
        +Recipe recipe
        +StringOrList sources
        +StringOrList deps
        +StringOrList order_only_deps
        +HashMap~String, String~ vars
        +bool phony
        +bool always
    }
    
    class Rule {
        +String name
        +Recipe recipe
        +Option~String~ description
        +Option~String~ deps
    }
    
    class Recipe {
        <<enumeration>>
        +Command~command: String~
        +Script~script: String~
        +Rule~rule: StringOrList~
    }
    
    class StringOrList {
        <<enumeration>>
        +Empty
        +String~String~
        +List~Vec String~
    }
    
    class Value {
        <<serde_yaml::Value>>
        +Null
        +Bool~bool~
        +Number~Number~
        +String~String~
        +Sequence~Sequence~
        +Mapping~Mapping~
        +Tagged~Tagged~
    }
    
    %% Relationships
    NetsukeManifest ||--o{ Rule : "contains rules"
    NetsukeManifest ||--o{ Target : "actions (deprecated)"
    NetsukeManifest ||--o{ Target : "targets"
    NetsukeManifest ||--o{ String : "defaults"
    NetsukeManifest ||--o{ Value : "global vars"
    
    Target ||--|| Recipe : "has recipe"
    Target ||--|| StringOrList : "name, sources, deps, order_only_deps"
    Target ||--o{ String : "local vars"
    
    Rule ||--|| Recipe : "has recipe"
    Rule ||--|| String : "name"
    Rule ||--o| String : "description, deps"
    
    Recipe ||--o| String : "command/script content"
    Recipe ||--o| StringOrList : "rule reference"
    
    %% Styling and annotations
    note for Recipe "Tagged enum with 'kind' field:<br/>- Command: inline command string<br/>- Script: embedded script content<br/>- Rule: reference to named rule<br/><br/>Mutually exclusive - enforces RecipeConflict"
    
    note for NetsukeManifest "Root manifest structure:<br/>- netsuke_version: compatibility check<br/>- vars: global YAML values<br/>- actions: deprecated, use targets<br/>- defaults: default target names"
    
    note for Target "Build target specification:<br/>- name: output file(s)<br/>- sources: input file(s)<br/>- deps: implicit dependencies<br/>- order_only_deps: order-only deps<br/>- phony: always run if requested<br/>- always: run every invocation"
    
    note for StringOrList "Flexible string specification:<br/>- Empty: no values<br/>- String: single value<br/>- List: multiple values<br/><br/>Untagged enum for user convenience"
    
    note for Rule "Reusable command template:<br/>- name: unique identifier<br/>- recipe: how to execute<br/>- description: optional docs<br/>- deps: dependency specification"
Loading

@leynos, this comprehensive class diagram shows all the item types that can be defined in a Netsukefile based on the exact structure definitions from your design documentation:

Key Features Highlighted:

  1. NetsukeManifest - The root structure with both actions (deprecated) and targets collections
  2. Target - Complete with all dependency types (deps, order_only_deps), build flags (phony, always), and local variables
  3. Rule - Simplified structure with name, recipe, and optional metadata
  4. Recipe - Tagged enum enforcing mutual exclusivity of command styles
  5. StringOrList - Untagged enum with Empty, String, and List variants for maximum user flexibility

Notable Design Patterns:

  • Deprecation Handling: actions field maintained for backwards compatibility
  • Flexible I/O: StringOrList allows empty, single, or multiple file specifications
  • Variable Scoping: Different variable types at manifest (YAML Value) vs target (String) levels
  • Build Control: phony and always flags for fine-grained build behavior control
  • Serde Integration: Proper use of #[serde(default)], #[serde(tag)], and #[serde(untagged)] for robust parsing

This structure perfectly supports the deterministic build graph generation, IR decoupling, and manifest validation features documented in your PR!

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 13, 2025

@coderabbitai the diagram is presenting the following error message:

Unable to render rich display

Lexical error on line 53. Unrecognized text.
... NetsukeManifest ||--o{ Rule : "conta
-----------------------^

For more information, see https://docs.github.com/get-started/writing-on-github/working-with-advanced-formatting/creating-diagrams#creating-mermaid-diagrams

Please fix this

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 13, 2025

Tip

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

@leynos, I see the issue! The Mermaid syntax I used has compatibility problems with GitHub's renderer. Let me fix this with a cleaner, more compatible version:

classDiagram
    class NetsukeManifest {
        +String netsuke_version
        +HashMap vars
        +Vec rules
        +Vec actions
        +Vec targets
        +Vec defaults
    }
    class Target {
        +StringOrList name
        +Recipe recipe
        +StringOrList sources
        +StringOrList deps
        +StringOrList order_only_deps
        +HashMap vars
        +bool phony
        +bool always
    }
    class Rule {
        +String name
        +Recipe recipe
        +String description
        +String deps
    }
    class Recipe {
        <<enumeration>>
        Command
        Script
        Rule
    }
    class StringOrList {
        <<enumeration>>
        Empty
        String
        List
    }
    class Value {
        <<serde_yaml>>
        Null
        Bool
        Number
        String
        Sequence
        Mapping
        Tagged
    }
    NetsukeManifest "1" o-- "*" Target
    NetsukeManifest "1" o-- "*" Rule
    NetsukeManifest "1" o-- "*" Value
    Target "1" -- "1" Recipe
    Target "1" -- "1" StringOrList
    Rule "1" -- "1" Recipe
Loading

This simplified version removes the problematic syntax elements:

  • Removed generic type parameters that use tildes
  • Simplified relationship syntax without labels
  • Removed complex cardinality notation that GitHub's parser doesn't support
  • Kept the essential structure and relationships clear

The diagram now shows the core Netsukefile item types and their relationships in a GitHub-compatible format!

Repository owner deleted a comment from coderabbitai Bot Jul 13, 2025
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 13, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 13, 2025

✅ 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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (5)
docs/netsuke-design.md (5)

650-652: Wrap glob determinism sentence

Line length still exceeds policy width.

-  The results are returned sorted lexicographically and symlinks are followed to
-  keep builds deterministic. This function bridges a key feature gap, as Ninja
-  itself does not support globbing.[^3]
+  The results are returned sorted lexicographically, and symlinks are followed
+  to keep builds deterministic.  
+  This function bridges a key feature gap, as Ninja itself does not support
+  globbing.[^3]

772-774: Wrap impurity note

Re-flow to satisfy MD013.

-Using `shell()` marks the template as *impure* and disables caching of the
-rendered YAML between Stage&nbsp;2 and Stage&nbsp;3. This avoids accidental
-reuse of results that depend on external commands.
+Using `shell()` marks the template as *impure* and disables caching of the
+rendered YAML between Stage&nbsp;2 and Stage&nbsp;3.  
+This avoids accidental reuse of results that depend on external commands.

748-750: Wrap filter-naming paragraph

Still > 80 columns.

-All built-in filters use `snake_case`. The `camel_case` helper is provided in
-place of `camelCase` so naming remains consistent with `snake_case` and `kebab-
-case`.
+All built-in filters use `snake_case`.  
+The `camel_case` helper is provided instead of `camelCase` so that naming
+remains consistent with `snake_case` and `kebab-case`.

80-83: Wrap determinism paragraph to ≤ 80 columns

Hard-wrap the four lines below so none exceed the 80-column limit.

-   Netsuke's pipeline is **deterministic**. Given the same `Netsukefile` and
-   environment variables, the generated `build.ninja` will be byte-for-byte
-   identical. This property is essential for reproducible builds and makes the
-   output suitable for caching or source control.
+   Netsuke's pipeline is **deterministic**.  
+   Given the same `Netsukefile` and environment variables, the generated
+   `build.ninja` will be byte-for-byte identical.  
+   This property is essential for reproducible builds and makes the output
+   suitable for caching or source control.

1260-1264: Wrap graph sub-command explanation

Re-flow to respect 80-column limit and keep the paragraph readable.

-  run the Netsuke pipeline up to Stage 4 (IR Generation) and then invoke
-  Ninja with the graph tool, `ninja -t graph`. This outputs the complete build
-  dependency graph in the DOT language. The result can be piped through `dot
-  -Tsvg` or displayed via `netsuke graph --html` using an embedded Dagre.js
-  viewer. Visualising the graph is invaluable for understanding and debugging
+  Run the Netsuke pipeline up to Stage&nbsp;4 (IR Generation) and then invoke
+  Ninja with the graph tool, `ninja -t graph`.  
+  This outputs the complete build dependency graph in the DOT language.  
+  Pipe the result through `dot -Tsvg`, or display it via
+  `netsuke graph --html` using the embedded Dagre.js viewer.  
+  Visualising the graph is invaluable for understanding and debugging
+  complex projects.
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 556c370 and 1f12f0d.

📒 Files selected for processing (1)
  • docs/netsuke-design.md (16 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.md

Instructions used from:

Sources:
⚙️ CodeRabbit Configuration File

🧠 Learnings (1)
docs/netsuke-design.md (2)
Learnt from: CR
PR: leynos/netsuke#0
File: docs/roadmap.md:0-0
Timestamp: 2025-07-12T13:36:28.501Z
Learning: Applies to docs/src/ninja_gen.rs : Mandate its use for all variable substitutions within the `command` strings during Ninja file synthesis to prevent command injection vulnerabilities.
Learnt from: CR
PR: leynos/netsuke#0
File: docs/netsuke-design.md:0-0
Timestamp: 2025-07-12T13:36:08.546Z
Learning: All third-party crate selections (clap, serde_yaml, minijinja, shell-quote, anyhow, thiserror, semver) must be justified and used as specified for their respective components.
🪛 LanguageTool
docs/netsuke-design.md

[style] ~185-~185: Would you like to use the Oxford spelling “summarizes”? The spelling ‘summarises’ is also correct.
Context: ...statement.[^3] The class diagram below summarises the structure of a Netsukefile and th...

(OXFORD_SPELLING_Z_NOT_S)


[uncategorized] ~248-~248: Loose punctuation mark.
Context: ...hat defines a reusable action. - name: A unique string identifier for the rule...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~250-~250: Loose punctuation mark.
Context: ...ng identifier for the rule. - command: A single command string to be executed....

(UNLIKELY_OPENING_PUNCTUATION)


[style] ~256-~256: Consider using a more formal/concise alternative here.
Context: ...lex/latest/shlex/). Any interpolation other than ins or outs is automatically shell-...

(OTHER_THAN)


[uncategorized] ~258-~258: Loose punctuation mark.
Context: ...automatically shell-escaped. - script: A multi-line script declared with the Y...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~265-~265: Possible missing comma found.
Context: ...ping rules. On Windows, scripts default to powershell -Command unless the mani...

(AI_HYDRA_LEO_MISSING_COMMA)


[style] ~1263-~1263: Would you like to use the Oxford spelling “Visualizing”? The spelling ‘Visualising’ is also correct.
Context: ...l` using an embedded Dagre.js viewer. Visualising the graph is invaluable for understandi...

(OXFORD_SPELLING_Z_NOT_S)

🔇 Additional comments (2)
docs/netsuke-design.md (2)

937-939: Wrap rule-writing paragraph

Lines exceed 80 columns.

-   `ir::Action`, write a corresponding Ninja `rule` statement. The input and
-   output lists stored in the action replace the `ins` and `outs` placeholders.
-   These lists are then rewritten as Ninja's `$in` and `$out`.
+   `ir::Action`, write a corresponding Ninja `rule` statement.  
+   The input and output lists stored in the action replace the `ins` and
+   `outs` placeholders. These lists are then rewritten as Ninja's `$in` and
+   `$out`.

Likely an incorrect or invalid review comment.


271-273: Re-wrap internal deserialisation note

Keep every line within 80 columns.

-  Internally, these options deserialize into a shared `Recipe` enum tagged with
-  a `kind` field. Serde aliases ensure manifests that omit the tag continue to
-  load correctly.
+  Internally, these options deserialize into a shared `Recipe` enum tagged
+  with a `kind` field. Serde aliases ensure manifests that omit the tag still
+  load correctly.

Likely an incorrect or invalid review comment.

Comment thread docs/netsuke-design.md Outdated
Comment thread docs/netsuke-design.md Outdated
Comment thread docs/netsuke-design.md
Comment thread docs/netsuke-design.md
leynos and others added 2 commits July 14, 2025 00:25
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@leynos leynos merged commit 245cf41 into main Jul 13, 2025
1 check passed
@leynos leynos deleted the codex/action-feedback-on-design-review branch July 13, 2025 23:31
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