fix(library)!: make manifest-declared flows portable across Colang versions#2185
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
2310548 to
f72f3e2
Compare
c23f5a4 to
b05380f
Compare
abf6536 to
be38ebc
Compare
b05380f to
33729cf
Compare
be38ebc to
938e50e
Compare
33729cf to
26ce747
Compare
Greptile SummaryThis PR normalizes vendor action names to
|
| Filename | Overview |
|---|---|
| nemoguardrails/library/sensitive_data_detection/flows.v1.co | Retrieval block now uses $config.bot_messages["inform answer unknown"][0]; this key is NOT defined in this file and must come from user config or another loaded library. |
| nemoguardrails/library/gliner/flows.v1.co | Retrieval block changed to use $config.bot_messages["refuse to respond"][0] + create event BotMessage, but "refuse to respond" is not defined in this file. |
| nemoguardrails/library/gcp_moderate_text/flows.co | Converted from Colang 1 to Colang 2 (flow / await CallGcpnlpApiAction / abort); underscore in abusive_or_harmful flow name matches defined bot flow. |
| nemoguardrails/library/gcp_moderate_text/flows.v1.co | New file: Colang 1 equivalent of the GCP moderation flows using call_gcpnlp_api and stop. |
| nemoguardrails/llm/filters.py | Replaces space-separated old action names with PascalCase forms the Colang 2 runtime emits in ActionFinished events. |
| nemoguardrails/library/regex/flows.co | Renames DetectRegexMatchAction to DetectRegexPatternAction, matching the registered action name detect_regex_pattern. |
| nemoguardrails/library/autoalign/flows.co | Fixes the only remaining lowercase action invocation: autoalign_factcheck_output_api to AutoalignFactcheckOutputApiAction. |
| tests/rails/llm/test_library_flow_files.py | New regression gate: parses flow files in both dialects, checks declared flow names, flags lowercase action invocations, and verifies action resolver consistency. |
| tests/test_runtime_flow_gate_equivalence.py | Extends equivalence test: adds retrieval RailSpecs, context_bloat cases, GCP detailed-moderation block cases, and injection-detection parametrized test. |
| nemoguardrails/library/injection_detection/flows.co | Colang 2 rewrite with correct $ prefixes, $system.config, elif, readable detection joins, and abort at correct indent level. |
| nemoguardrails/library/context_bloat_detection/flows.v1.co | Retrieval block uses direct BotMessage event to avoid re-entry; message key is defined in the same file. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Library Rail Loaded] --> B{Colang Dialect?}
B -->|Colang 1 - flows.v1.co| C[execute snake_case_action]
B -->|Colang 2 - flows.co| D[await CamelCaseAction]
C --> E{Action resolves?}
D --> F{Action resolves?}
E -->|YES| G[Outcome: RailOutcome]
E -->|NO - old space-separated name| H[Runtime Error]
F -->|YES - dispatcher normalizes PascalCase| G
F -->|NO - lowercase await is a flow ref| I[Silent wrong flow call]
G --> J{is_blocked?}
J -->|YES - Colang 2| K[bot X Y Z + abort]
J -->|YES - Colang 1 INPUT/OUTPUT| L[bot X Y Z + stop]
J -->|YES - Colang 1 RETRIEVAL| M[create event BotMessage + stop]
J -->|NO - is_transform| N[Modify context variable]
style H fill:#f66
style I fill:#f66
style M fill:#6f6
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Library Rail Loaded] --> B{Colang Dialect?}
B -->|Colang 1 - flows.v1.co| C[execute snake_case_action]
B -->|Colang 2 - flows.co| D[await CamelCaseAction]
C --> E{Action resolves?}
D --> F{Action resolves?}
E -->|YES| G[Outcome: RailOutcome]
E -->|NO - old space-separated name| H[Runtime Error]
F -->|YES - dispatcher normalizes PascalCase| G
F -->|NO - lowercase await is a flow ref| I[Silent wrong flow call]
G --> J{is_blocked?}
J -->|YES - Colang 2| K[bot X Y Z + abort]
J -->|YES - Colang 1 INPUT/OUTPUT| L[bot X Y Z + stop]
J -->|YES - Colang 1 RETRIEVAL| M[create event BotMessage + stop]
J -->|NO - is_transform| N[Modify context variable]
style H fill:#f66
style I fill:#f66
style M fill:#6f6
Reviews (5): Last reviewed commit: "fix(llm): filter vendor actions from Col..." | Re-trigger Greptile
938e50e to
4abf429
Compare
26ce747 to
cb7c03c
Compare
3c696d7 to
6a88f13
Compare
|
@greptileai any pending issues? |
|
All four inline review threads are resolved. The GCP The one loose end: at the end of the Everything else looks good to merge. |
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>
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>
Keep GCP detailed moderation and Colang 2 injection detection fail-closed, while preserving readable injection messages. Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
Match Colang 2 finished-event action names so internal vendor action results stay out of generated history Signed-off-by: Pouyanpi <13303554+Pouyanpi@users.noreply.github.com>
6a88f13 to
1e2ca85
Compare
Description
Several packaged library flows either fail to parse under Colang 2 or invoke
action names the runtime cannot resolve. This PR normalizes vendor action
names, repairs the broken Colang 2 flows, adds the missing GCP Colang 1 variant,
and adds a cross-dialect regression gate. Parameterized Colang 2 flows remain
exempt from Colang 1 presence.
It also fixes blocked retrieval rails that re-enter retrieval instead of
terminating, preserves GCP's action-owned fail-closed verdict, and covers
context-bloat allow, block, and transform outcomes.
Compatibility: custom Colang 1 flows using the old space-separated Cleanlab,
Fiddler, or GCP action names must switch to their snake_case names. users enabling the shipped rail flows are unaffected because the bundled flows are updated together.
Impact
packaged Colang dialects instead of failing on invalid syntax or unresolved
names.
and registered action names during tests rather than at user runtime.
Colang flows remain responsible only for response presentation.
unavailable.
Stack
pouyanpi/rail-library-stack-3-manifest-contractdeveloppouyanpi/rail-library-stack-4-builtinspouyanpi/rail-library-stack-4b-flow-gatepouyanpi/rail-library-stack-5-lazy-actionsRelated Issue(s)
Verification
AI Assistance
Codex assisted with implementation analysis, validation, stack restructuring,
and this draft. Check the disclosure box after human review.
Checklist