fix: Respect declared input types for CLI parameters#84
Conversation
Fixes #83 CLI's infer_type() was converting numeric-looking strings (like Discord snowflake IDs) to integers before consulting the workflow's declared input types. This violated the type contract when users declared `type: string`. Root causes fixed: 1. CLI type inference: Added coerce_input_to_declared_type() in prepare_inputs() to convert values back to match declared types 2. Template JSON auto-parsing: Changed resolve_nested() to only parse JSON into containers (dict/list), not primitives Also expanded IR schema to accept Python type aliases (str, int, float, bool, dict, list) alongside JSON Schema types, enabling natural type declarations across different language conventions. Changes: - Add coerce_input_to_declared_type() for bidirectional type coercion - Add helper functions to reduce prepare_inputs() complexity - Fix template resolver to preserve string primitives - Expand IR schema type enum with Python aliases - Add 69 new tests for coercion behavior - Update CLAUDE.md documentation
…eview] Review feedback addressed: 1. Identity check pattern fragility (Warning #1): - Changed _coerce_provided_input() to return (value, was_coerced) tuple - Makes intent explicit and prevents subtle bugs from identity assumptions 2. Type alias normalization (Warning #4): - _normalize_type() now preserves case for unknown types - Supports future custom/user-defined types 3. dict/list to string uses Python repr (Review #2): - _coerce_to_string() now uses json.dumps() for containers - Produces valid JSON strings consistent with coerce_to_declared_type() 4. Env/defaults values not coerced (Review #2): - Apply coercion to values from os.environ, settings_env, and defaults - Ensures "respect declared types" works for all input sources 5. None value handling: - Preserve None values (don't coerce to "None" string) - Optional inputs without defaults correctly resolve to None Also: - Added 4 new tests for env/settings coercion - Documented lenient coercion behavior in docstrings - Created Task 120 for future strict input type validation
Code ReviewThis PR successfully fixes issue #83 by ensuring CLI-provided inputs respect workflow input type declarations. The implementation is well-structured with comprehensive test coverage. ✅ Strengths
|
|
Critical — must fix before merge
Warnings — should be addressed
Suggestions — optional improvements
Test coverage looks solid overall (new unit + integration tests), but I’d add at least one settings/env coercion case to lock in the behavior. |
Review Feedback AddressedThanks for the thorough reviews! Here's what was fixed in commit ccf9a99: From Review #1 (claude[bot])
From Review #2 (spinje)
Additional Fixes
Deferred
All 3711 tests pass, |
Summary
Fixes #83 - Numeric string inputs (like Discord snowflake IDs) were silently coerced to
intdespite being declared astype: stringin workflow inputs.Changes
prepare_inputs(): Addedcoerce_input_to_declared_type()that converts CLI-inferred values to match declared input types (e.g., int → string whentype: string)"1234"from becoming1234str,int,float,bool,dict,list) alongside JSON Schema typesprepare_inputs()complexity from 12 to 7 by extracting_resolve_missing_input()and_coerce_provided_input()Explanation
The bug had two root causes:
infer_type()convertschannel_id="1458..."to an integer before the workflow is loaded, so the declaredtype: stringwas never consultedresolve_nested()converted string values like"42"back to integersThe fix addresses both:
prepare_inputs()now coerces values to match declared types after CLI parsingPython type aliases were added to the IR schema so users can write
type: intortype: strnaturally, especially as we add more code node languages (TypeScript planned).Testing
Run
make testto verify all tests pass.