Skip to content

feat: multi-error validation, node-kind catalog, graph patch-ops#11

Merged
senamakel merged 3 commits into
tinyhumansai:mainfrom
senamakel:feat/multi-error-validation
Jul 15, 2026
Merged

feat: multi-error validation, node-kind catalog, graph patch-ops#11
senamakel merged 3 commits into
tinyhumansai:mainfrom
senamakel:feat/multi-error-validation

Conversation

@senamakel

Copy link
Copy Markdown
Member

What & why

Three additive, host-agnostic capabilities the OpenHuman host needs to make its Flows product agent-friendly (structured editing, a queryable DSL schema, and all-at-once validation). Each is independent and fully tested; nothing changes existing runtime behaviour.

1. validate::validate_all — multi-error validation

validate() stopped at the first structural error, so an author fixing five problems paid five round-trips. Adds validate_all(graph) -> Vec<ValidationError> that accumulates every independent error in one pass; validate() is now redefined as its first element, so the historical fail-fast single-error contract (and every existing test) is byte-for-byte preserved. Also adds ValidationError::code() (stable snake_case id) and node_id() so a host can build a structured, per-node report instead of parsing Display strings.

2. catalog — typed, queryable node-kind contracts

The per-kind config shape lived only in prose in downstream hosts. Adds a host-agnostic NodeKindContract per node kind (config fields, ports, an example node, authoring gotchas) via all_contracts() / contract_for(kind). Strictly model-level — opaque fields (tool_call slug, connection_ref) are described as the engine sees them; NodeKindContract::with_note lets a host layer its own vendor facts without editing the crate (respecting the host-agnostic invariant).

3. graph_ops — structured incremental graph edits

Adds a patch-op layer so a caller can change a WorkflowGraph with a small GraphOp list (add_node, update_node_config [RFC 7386 merge-patch], set_node_name, rename_node [rewires edges], remove_node, add_edge, remove_edge, set_node_position) instead of re-emitting the whole graph. apply_ops applies them in order with precise per-op errors (op 3 (add_edge): …), purely structurally — validate_all runs after.

Testing

  • cargo test --features mock — full lib suite green (adds ~30 tests across the three modules)
  • cargo clippy --all-targets clean; cargo fmt --check clean
  • #![forbid(unsafe_code)] / #![warn(missing_docs)] upheld

Notes

  • Fully additive; no changes to compile/engine/existing validate semantics.
  • Consumed downstream by the OpenHuman host's flows agent-friendliness work (separate PR), which bumps this submodule pointer once merged.

Add validate_all(graph) -> Vec<ValidationError> that collects every
independent structural error in one pass, and redefine validate() as its
first element so the historical fail-fast single-error contract (and all
existing tests) is preserved with zero duplication.

Also add ValidationError::code() (stable snake_case identifier) and
node_id() accessors so a host can build a structured, per-node validation
report instead of parsing Display strings.

A host validating an author's/agent's graph now surfaces all problems at
once — fixing five costs one validate call, not five round-trips.
Add a host-agnostic catalog of NodeKindContract — one per node kind — with
config fields, ports, an example node, and authoring gotchas, exposed via
all_contracts()/contract_for(kind). Makes the free-form per-kind config
shape a machine-readable source of truth instead of prose a downstream host
has to maintain by hand.

Strictly model-level: opaque fields (tool_call slug, connection_ref) are
described as the engine sees them; NodeKindContract::with_note lets a host
layer its own facts (what a slug resolves to, output wrapping, which
triggers dispatch) without editing the crate.
Add a patch-op layer so a caller can change a WorkflowGraph with a small
list of ops instead of re-emitting the whole graph (token-heavy, the tinyhumansai#1
source of dropped-node/mangled-edge regressions).

GraphOp: add_node, update_node_config (RFC 7386 merge patch), set_node_name,
rename_node (rewires edges), remove_node (drops incident edges), add_edge,
remove_edge, set_node_position. apply_ops applies them in order with precise
per-op errors ('op 3 (add_edge): ...'), purely structural — validate_all
runs after. Host-agnostic: no knowledge of config semantics.
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 33 minutes

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

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f9b5cab5-2ca1-482a-a042-6cf3783f035b

📥 Commits

Reviewing files that changed from the base of the PR and between be8ae65 and bc68254.

📒 Files selected for processing (5)
  • src/catalog.rs
  • src/error.rs
  • src/graph_ops.rs
  • src/lib.rs
  • src/validate.rs

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

@senamakel senamakel merged commit f182389 into tinyhumansai:main Jul 15, 2026
2 checks passed

@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: bc68254b07

ℹ️ 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/catalog.rs
Comment on lines +432 to +436
summary: "Passthrough today; no config required.".to_string(),
description: "A passthrough node reserved for structured-output parsing. Requires no \
config."
.to_string(),
config_fields: vec![],

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 Expose output_parser schema fields in the catalog

When a host or authoring agent relies on contract_for("output_parser"), this contract says the node is only a passthrough and exposes no config fields. The executor in src/nodes/integration/output_parser.rs actually reads config.schema, auto_fix, and connection_ref to perform schema validation/repair, so catalog-driven authors have no way to discover the node's primary behavior and will generate parser nodes that just pass data through. Please list those optional fields and update the description/example accordingly.

Useful? React with 👍 / 👎.

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.

1 participant