Skip to content

fix(library): make manifest-declared flows portable across Colang versions#2185

Draft
Pouyanpi wants to merge 6 commits into
pouyanpi/rail-library-stack-4-builtinsfrom
pouyanpi/rail-library-stack-4b-flow-gate
Draft

fix(library): make manifest-declared flows portable across Colang versions#2185
Pouyanpi wants to merge 6 commits into
pouyanpi/rail-library-stack-4-builtinsfrom
pouyanpi/rail-library-stack-4b-flow-gate

Conversation

@Pouyanpi

@Pouyanpi Pouyanpi commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Description

Make flows declared by built-in rail manifests executable in each packaged
Colang dialect. Normalize vendor action identifiers so Colang 2 can resolve
them, repair invalid Colang 2 flow syntax, add missing Clavata and GCP flow
variants, and correct the AutoAlign fact-check invocation.

Add a cross-dialect gate that loads packaged flow files, verifies declared
actions resolve, detects actions incorrectly awaited as flows, and exercises
representative runtime outcomes.

Manifests do not replace Colang orchestration in LLMRails. They declare the
portable action contract, while packaged Colang flows continue to own
LLMRails-specific sequencing and presentation. This PR keeps those two layers
aligned across both supported Colang dialects.

both GCP dialects retain the merged action-owned moderation verdict: flows gate
on RailOutcome.is_blocked, use triggered_violation only for presentation,
and fail closed when detailed trigger metadata is absent.

Impact

  • Built-in manifest-declared rails can load and invoke their actions under both
    packaged Colang dialects instead of failing on invalid syntax or unresolved
    names.
  • The gate detects future drift among manifest action references, flow bodies,
    and registered action names during tests rather than at user runtime.
  • ActiveFence and GCP retain backend-neutral action-owned verdicts while their
    Colang flows remain responsible only for response presentation.
  • GCP moderation remains fail-closed even when detailed violation metadata is
    unavailable.
  • No configuration schema or manifest API is added in this layer.

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 pending

Related Issue(s)

  • Fixes #
  • Internal tracking: NGUARD-855
  • Issue assignee: @

Verification

AI Assistance

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

Codex assisted with implementation analysis, validation, stack restructuring,
and this draft. Check the disclosure box after human review.

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

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Pouyanpi
Pouyanpi force-pushed the pouyanpi/rail-library-stack-4-builtins branch from 2310548 to f72f3e2 Compare July 17, 2026 11:58
Pouyanpi added 6 commits July 17, 2026 14:00
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>
Colang 1 ships clavata check input / clavata check output but the
manifest declared only the parameterized clavata check for, which is
Colang 2 only (Colang 1 has no parameterized flows). Add Colang 2
wrapper flows for input and output and declare all three flow names in
the manifest.

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