Skip to content

Add manifest evaluation resource budgets (#651) - #670

Open
leynos wants to merge 2 commits into
mainfrom
issue-651-add-resource-budgets-to-manifest-template-evaluation
Open

Add manifest evaluation resource budgets (#651)#670
leynos wants to merge 2 commits into
mainfrom
issue-651-add-resource-budgets-to-manifest-template-evaluation

Conversation

@leynos

@leynos leynos commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add one shared manifest budget across rendering, expressions, macros, when, and lazy foreach expansion.
  • Enforce operator-controlled limits for fuel, output, source, cardinality, and aggregate expansion, with redacted diagnostics and bounded telemetry.
  • Document the policy and cover boundary, query, configuration, property, and BDD behaviour.

Closes #651

References

Bound template rendering, expressions, macro expansion, and `foreach`
processing with shared fuel, byte, source, cardinality, and expansion limits.
Keep trusted operator ceilings authoritative while allowing project settings to
narrow them, and expose bounded redacted diagnostics and telemetry.

Document the policy and cover its limits across unit, property, query, BDD,
localization, and configuration metadata tests.
@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 16 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available. Your 98 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Team

Run ID: 0683ccb2-8434-4012-9e72-e23fb0e660a7

📥 Commits

Reviewing files that changed from the base of the PR and between f1ca131 and d9b2dd3.

⛔ Files ignored due to path filters (3)
  • src/snapshots/cli/netsuke__cli__parser__tests__help_en_us.snap is excluded by !**/*.snap
  • src/snapshots/cli/netsuke__cli__parser__tests__help_es_es.snap is excluded by !**/*.snap
  • tests/snapshots/ortho_config_metadata_snapshot_tests__release_help_documentation_metadata_is_stable.snap is excluded by !**/*.snap
📒 Files selected for processing (85)
  • Cargo.toml
  • build.rs
  • docs/adr-018-bound-manifest-template-evaluation.md
  • docs/contents.md
  • docs/netsuke-design.md
  • docs/users-guide.md
  • locales/ar/messages.ftl
  • locales/cs/messages.ftl
  • locales/cy/messages.ftl
  • locales/da/messages.ftl
  • locales/de/messages.ftl
  • locales/el/messages.ftl
  • locales/en-GB/messages.ftl
  • locales/en-US/messages.ftl
  • locales/es-419/messages.ftl
  • locales/es-ES/messages.ftl
  • locales/fa/messages.ftl
  • locales/fi/messages.ftl
  • locales/fr/messages.ftl
  • locales/gd/messages.ftl
  • locales/he/messages.ftl
  • locales/hi/messages.ftl
  • locales/hu/messages.ftl
  • locales/id/messages.ftl
  • locales/it/messages.ftl
  • locales/ja/messages.ftl
  • locales/ko/messages.ftl
  • locales/nb/messages.ftl
  • locales/nl/messages.ftl
  • locales/pl/messages.ftl
  • locales/pt-BR/messages.ftl
  • locales/pt-PT/messages.ftl
  • locales/ro/messages.ftl
  • locales/ru/messages.ftl
  • locales/sv/messages.ftl
  • locales/th/messages.ftl
  • locales/tr/messages.ftl
  • locales/uk/messages.ftl
  • locales/vi/messages.ftl
  • locales/zh-Hans/messages.ftl
  • locales/zh-Hant/messages.ftl
  • src/cli/command.rs
  • src/cli/config.rs
  • src/cli/discovery.rs
  • src/cli/discovery_helper_proptests.rs
  • src/cli/discovery_layers.rs
  • src/cli/discovery_merge_layers.rs
  • src/cli/discovery_telemetry.rs
  • src/cli/manifest_budget_config.rs
  • src/cli/manifest_budget_policy.rs
  • src/cli/merge.rs
  • src/cli/merge_input.rs
  • src/cli/mod.rs
  • src/cli/parser_tests.rs
  • src/cli_l10n.rs
  • src/cli_policy.rs
  • src/localization/keys.rs
  • src/manifest/budget/mod.rs
  • src/manifest/budget/writer.rs
  • src/manifest/expand.rs
  • src/manifest/expand/evaluation.rs
  • src/manifest/expand/mod.rs
  • src/manifest/expand_test_cases/foreach_property_cases.rs
  • src/manifest/jinja_macros/mod.rs
  • src/manifest/jinja_macros/telemetry.rs
  • src/manifest/mod.rs
  • src/manifest/parse_with_config.rs
  • src/manifest/query.rs
  • src/manifest/registration.rs
  • src/manifest/render.rs
  • src/manifest/render_command_list_tests.rs
  • src/manifest/tests/budget.rs
  • src/manifest/tests/mod.rs
  • src/runner/generation.rs
  • src/runner/graph.rs
  • src/runner/graph_generation.rs
  • src/runner/help_query.rs
  • src/runner/mod.rs
  • tests/bdd/fixtures/mod.rs
  • tests/bdd/steps/manifest/mod.rs
  • tests/build_module_slice_ui_tests.rs
  • tests/data/manifest_budget_foreach.yml
  • tests/data/manifest_budget_loop.yml
  • tests/data/manifest_budget_ordinary.yml
  • tests/features/manifest.feature

Warning

Your free Security trial is over. An organization admin can upgrade to Advanced for continuous pull request security review or dismiss this notice.


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

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

@leynos

leynos commented Sep 5, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph.

If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message in a code block that I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced.

src/manifest/tests/budget.rs

Comment on lines +28 to +37

fn rendered_value_at_limit_succeeds() -> Result<()> {
    let yaml = concat!(
        "netsuke_version: 1.0.0\n",
        "targets:\n",
        "  - name: exact\n",
        "    command: '{{ \"x\" * 16 }}'\n",
    );
    from_str_with_limits(yaml, small_limits())?;
    Ok(())
}

❌ New issue: Code Duplication
The module contains 5 functions with similar structure: compact_loop_runs_out_of_fuel_before_allocating_requested_output,foreach_at_the_configured_cardinality_succeeds,foreach_stops_at_the_configured_cardinality,rendered_value_at_limit_succeeds and 1 more functions

@leynos

leynos commented Sep 5, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph.

If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message in a code block that I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced.

src/manifest/jinja_macros/mod.rs

Comment on lines +289 to +300

) -> Result<String, Error> {
    let budget = ManifestBudget::default();
    render_template_at(
        env,
        &budget,
        &TemplateRenderRequest {
            template,
            context,
            stage: ManifestBudgetStage::Render,
        },
    )
}

❌ New issue: Code Duplication
The module contains 2 functions with similar structure: render_template,render_template_with_budget

@coderabbitai

This comment was marked as resolved.

@leynos

leynos commented Sep 5, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph.

If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message in a code block that I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced.

src/manifest/budget/mod.rs

Comment on lines +237 to +248

    pub(crate) fn new(limits: ManifestBudgetLimits) -> Result<Self> {
        let validated_limits = limits.validate()?;
        Ok(Self {
            state: Rc::new(ManifestBudgetState {
                rendered_bytes: Cell::new(validated_limits.rendered_manifest_bytes),
                source_bytes: Cell::new(validated_limits.source_bytes),
                expanded_entries: Cell::new(validated_limits.expanded_entries),
                fuel: Cell::new(validated_limits.manifest_fuel),
            }),
            limits: validated_limits,
        })
    }

❌ New issue: Code Duplication
The module contains 4 functions with similar structure: ManifestBudget.charge_expanded_entry,ManifestBudget.charge_source,ManifestBudget.default,ManifestBudget.new

@coderabbitai

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

Delegate the test-only wrapper to the budget-aware rendering entry point so
both paths construct the same request while retaining a fresh default budget.
@leynos
leynos marked this pull request as ready for review September 5, 2026 22:43

@sourcery-ai sourcery-ai 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.

Sorry @leynos, your pull request is larger than the review limit of 150,000 diff characters

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-05T22:47:27.862314Z d9b2dd3 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

codescene-access[bot]

This comment was marked as outdated.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d9b2dd34b3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cli/command.rs
Comment on lines +93 to +95
/// Maximum `MiniJinja` instructions for one manifest evaluation.
#[arg(long, value_name = "FUEL", default_value_t = 1_000_000)]
pub manifest_evaluation_fuel: u64,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Honour manifest-budget CLI overrides

When any --manifest-* option is supplied, Clap stores it in Cli, but cli_overrides_from_matches never inserts any of the seven new fields into the CLI merge layer; apply_config then replaces the parsed values with the merged defaults or file/environment values. Consequently an operator invocation such as --manifest-fuel 1000 silently runs with a much larger ceiling, defeating the command-line resource restriction.

Useful? React with 👍 / 👎.

Comment on lines +52 to +53
if is_project_scope_layer(path.as_deref(), project_key.as_deref()) {
project_budget_request = take_project_manifest_budget_request(&mut value);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Clamp budgets from the whole project config chain

When the project .netsuke.toml uses extends, only the layer whose path exactly matches .netsuke.toml has its budget fields extracted for monotonic reconciliation. An inherited file is still controlled by the project but remains a normal high-precedence file layer, so a checkout can put an enlarged manifest_fuel or byte ceiling in base.toml and extend it, bypassing the documented rule that project configuration cannot widen operator defaults.

Useful? React with 👍 / 👎.

ManifestBudgetStage::Source,
)
.map_err(|exhaustion| exhaustion.into_error(ErrorKind::WriteFailure))?;
register_macro(env, def, idx).with_context(|| {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Pass the shared budget into expression macro wrappers

When a manifest macro is called from a bare foreach or when expression, it uses the global-function fallback in invocation.rs, whose capture_macro(...).render_captured(()) creates a fresh MiniJinja state and materializes the macro result as a String. This registration path never gives that wrapper the ManifestBudget, so macro-body fuel is not charged to the caller's state and macro output bypasses both rendered-value and aggregate byte writers; a compact expression macro can therefore allocate large output or multiply instruction work despite the new limits.

Useful? React with 👍 / 👎.

Comment on lines +105 to +107
fields
.remove(name)
.and_then(|value| serde_json::from_value(value).ok())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject malformed project budget values

When a project budget key has the wrong TOML type or an out-of-range numeric representation, take_limit removes the key and discards the deserialization error through .ok(). The remaining layer then passes normal schema validation and Netsuke silently uses another ceiling instead of reporting the invalid configuration, making operator-visible configuration mistakes indistinguishable from an omitted restriction.

Useful? React with 👍 / 👎.

@codescene-access codescene-access Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No quality gates enabled for this code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add resource budgets to manifest template evaluation

1 participant