Skip to content

feat(rails): load enabled rail plugins end to end#2187

Closed
Pouyanpi wants to merge 34 commits into
pouyanpi/rail-library-stack-5-lazy-actionsfrom
pouyanpi/rail-library-stack-6-hardening
Closed

feat(rails): load enabled rail plugins end to end#2187
Pouyanpi wants to merge 34 commits into
pouyanpi/rail-library-stack-5-lazy-actionsfrom
pouyanpi/rail-library-stack-6-hardening

Conversation

@Pouyanpi

@Pouyanpi Pouyanpi commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Description

Load enabled rail plugins through the complete configuration and runtime path.
Index packaged plugin flow sources by Colang version, include plugin-declared
configuration fields when constructing RailsConfig, and load only flows from
plugins explicitly enabled by configuration.

Stack 3 defines how a catalog can be extended with named plugin entry points;
this PR carries that explicit enablement through configuration construction and
runtime flow loading. Discovery and activation stay separate: installing a
plugin does not make its config fields or flows active by default.

Add an end-to-end example plugin suite covering disabled plugins, enabled
configuration projection, flow loading, configured-surface parameters,
collisions, unknown plugins, cache resets, and both Colang dialects. Static
catalog discovery remains cheap and does not import action modules.

Impact

  • An installed rail plugin remains inert until its name is explicitly enabled
    in the application configuration.
  • Enabled plugins contribute typed configuration fields and the correct Colang
    flow source to the same paths used by built-in rails.
  • Disabled plugins do not alter RailsConfig, load flow files, or import action
    modules.
  • Missing plugins, duplicate providers, manifest collisions, and cache resets
    have deterministic, tested behavior.
  • Applications that do not enable plugins retain the existing built-in catalog
    and runtime behavior.

Stack

Layer Branch Base PR
Stack 3 pouyanpi/rail-library-stack-3-manifest-contract develop #2157
Stack 4 pouyanpi/rail-library-stack-4-builtins Stack 3 #2181
Stack 4b pouyanpi/rail-library-stack-4b-flow-gate Stack 4 #2185
Stack 5 pouyanpi/rail-library-stack-5-lazy-actions Stack 4b #2186
Stack 6 pouyanpi/rail-library-stack-6-hardening Stack 5 #2187

Related Issue(s)

Verification

AI Assistance

  • No AI tools were used.
  • AI tools were used; a human reviewed and can explain every change (tool: ___).

Checklist

  • I've read the CONTRIBUTING guidelines.
  • This PR links to a triaged issue assigned to me.
  • My PR title follows the project commit convention.
  • I've updated the documentation if applicable.
  • I've added tests if applicable.
  • I've noted any verification beyond CI and any checks I couldn't run.
  • I did not update generated changelog files manually.
  • I addressed all CodeRabbit, Greptile, and other review comments, or replied with why no change is needed.
  • @mentions of the person or team responsible for reviewing proposed changes.

@github-actions github-actions Bot added status: needs triage New issues that have not yet been reviewed or categorized. size: L labels Jul 17, 2026
@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.10526% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
nemoguardrails/rails/llm/config.py 91.66% 4 Missing ⚠️
nemoguardrails/manifests/catalog.py 92.59% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@Pouyanpi
Pouyanpi force-pushed the pouyanpi/rail-library-stack-5-lazy-actions branch from 6231c7a to 92f2417 Compare July 20, 2026 07:18
@Pouyanpi
Pouyanpi force-pushed the pouyanpi/rail-library-stack-6-hardening branch from 54f8534 to 517ca08 Compare July 20, 2026 07:18
Pouyanpi added 22 commits July 20, 2026 14:32
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Mirror the manifests package layout under tests/manifests/ (test_manifest,
test_catalog, test_schema, test_init) and refocus the rails/llm shim tests on
re-export identity and the discovery helpers. Adds coverage for RailCatalog
discovery and plugin entry-point loading, the config schema primitives, and the
package-level accessors, which were previously untested.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
The parser now supports only:

name
name $key=value
name $key=value $other="quoted value"

Changes include:

- No parenthesized parameter parsing.
- Exact $name=value; spaces around = rejected.
- No bare-value escaping or shell quote concatenation.
- Parenthesized custom flows remain uninterpreted and ignored by manifest discovery.
- Linear parsing, control rejection, duplicate detection, quote fidelity, and value-free errors retained.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Remove unused compatibility aliases and convenience APIs before the manifest contract is published. Document the retained public models, catalog accessors, import helpers, and configured-surface grammar.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Make each declared public flow name globally owned by one manifest, expose exact owner lookup for downstream selection, and reject duplicate claims across built-ins and plugins.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Restore the exact pre-migration F5 and Polygraf schema descriptions, align AlignScore privacy metadata with its declared service, and stop advertising the flow-specific hallucination warning as a portable execution surface.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Declare the missing Clavata input/output wrappers, context-bloat input/retrieval execution contracts, and jailbreak heuristic surface. Keep directionless Clavata dispatch and hallucination presentation flows out of the portable surface catalog.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Space-separated action names (call cleanlab api, call fiddler safety on
user message, call fiddler safety on bot message, call fiddler
faithfulness, call gcpnlp api) can never be invoked from Colang 2:
CamelCaseAction invocations normalize to snake_case and the dispatcher
has no alias support. Rename them to the snake_case forms the Colang 2
flows already call, updating v1 flows, docs, log filters, and the
runtime flow gate equivalence fixtures.

Breaking change: custom Colang 1 flows that execute the old spaced
names must switch to the snake_case names.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
None of these had ever been executed under Colang 2:

- injection_detection/flows.co did not parse: variables were missing
  the $ sigil and the file used Colang 1 idioms (else if, {{ }}
  interpolation, $config instead of $system.config). Rewritten to the
  library's Colang 2 idiom, mirroring flows.v1.co semantics.
- regex/flows.co awaited DetectRegexMatchAction, which normalizes to
  the unregistered detect_regex_match; the registered action is
  detect_regex_pattern.
- gcp_moderate_text shipped Colang 1 content in flows.co and had no
  flows.v1.co at all; moved the v1 content to flows.v1.co and authored
  a proper Colang 2 flows.co.
- activefence/flows.v1.co had one flow definition indented by a stray
  space (cosmetic; the parser still registered it).

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Pouyanpi added 12 commits July 20, 2026 14:33
Library rail tests run Colang 1 almost exclusively, so broken Colang 2
flow files shipped silently. Gate every manifest-declared rail: both
dialect files must parse, define the declared flow names (a declared
flow whose Colang 2 definition is parameterized is exempt from Colang 1
presence, since Colang 1 has no parameterized flows), and invoke only
actions the dispatcher can resolve.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
flows.co line 44 awaited autoalign_factcheck_output_api by its
registered snake_case name; a lowercase name after await is a flow
reference in Colang 2, so the invocation resolved to a nonexistent flow.
Use the CamelCase Action form like the sibling flows in the same file.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
A lowercase name after await/start parses as a flow reference, so
awaiting an action by its snake_case registered name fails only at
runtime. Flag any awaited lowercase name that matches a registered
action; this caught the autoalign factcheck defect and matches the
mistake pattern seen in inbound rail PRs.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Emit configured terminal BotMessage events when retrieval rails block so their responses do not re-enter retrieval indefinitely. Preserve the predefined-message output-rail bypass and cover each affected retrieval flow end to end.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Exercise allow, block, and transform verdicts for both context-bloat input and retrieval flows using the backend-neutral RailOutcome contract.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Pin the projected RailsConfig schema to its pre-migration contract, verify defaults and requirement/privacy consistency, and ensure each flow invokes only actions declared by its owning manifest. Include a reproducible snapshot generator for intentional schema changes.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Require every declared portable surface to have an end-to-end flow-gate equivalence case, and complete the matrix for Polygraf input, output, retrieval, and transform surfaces.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Require every declared public flow to map to a portable surface or an explicit exception, every surface action to declare RailOutcome, and the manifest surface set to match the runtime flow-gate matrix exactly.

Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
@Pouyanpi
Pouyanpi force-pushed the pouyanpi/rail-library-stack-5-lazy-actions branch from 92f2417 to b373750 Compare July 20, 2026 12:34
@Pouyanpi
Pouyanpi force-pushed the pouyanpi/rail-library-stack-6-hardening branch from 517ca08 to 59f33e4 Compare July 20, 2026 12:34
@Pouyanpi
Pouyanpi force-pushed the pouyanpi/rail-library-stack-5-lazy-actions branch from b373750 to f959ca3 Compare July 20, 2026 15:49
@Pouyanpi Pouyanpi closed this Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: L status: needs triage New issues that have not yet been reviewed or categorized.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant