Skip to content

fix(workflows): keep integer number inputs exact instead of rounding them - #5027

Merged
mnriem merged 1 commit into
github:mainfrom
kartsan03:fix/workflow-integer-input-precision
Oct 19, 2026
Merged

mnriem merged 1 commit into
github:mainfrom
kartsan03:fix/workflow-integer-input-precision

Conversation

@kartsan03

Copy link
Copy Markdown
Contributor

Description

Workflow inputs declared as type: number go through float() in WorkflowEngine._coerce_input (src/specify_cli/workflows/engine.py), even when the value is already an integer, or an integer string from --input. Integers above 2**53, such as 64-bit ids or nanosecond timestamps, are rounded before any step sees them. The run still completes, so the wrong value is written without any error. An enum that lists such an integer also rejects its own default, because the default is rounded before the enum check.

This PR tries int() first for strings and integers. Decimal and exponent strings and native floats keep the existing float path. The boolean rejection, the error messages and the enum check are unchanged. docs/reference/workflows.md gets a short paragraph on how number inputs are converted.

I haven't seen a user report of this. It came up while reading the input coercion code.

Repro: a workflow with one number input, record_id, and a shell step echo {{ inputs.record_id }} > record-id.txt, run with specify workflow run <yaml> --json:

Case main (e5714c6) This PR
--input record_id=1792234567890123456 exit 0; writes and persists 1792234567890123520 exit 0; writes and persists 1792234567890123456
YAML default 1792234567890123456 exit 0; writes and persists 1792234567890123520 exit 0; writes and persists 1792234567890123456
Same default with enum: [1792234567890123456] exit 1: Input 'record_id' value 1792234567890123520 not in allowed values: [1792234567890123456]. exit 0; writes and persists 1792234567890123456

Testing

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest
  • Tested with a sample project (if applicable)

New tests:

  • tests/test_workflows.py: integers and integer strings at and above 2**53 keep their exact value, decimal and exponent strings and floats convert as before, booleans and non-finite values are still rejected, and the enum check compares the exact value.
  • tests/specify_cli/workflows/test_command_run.py: the three repro cases above through the real specify workflow run, checking the written file and the persisted run state.

With only src/ reverted to main, 12 of the 27 new cases fail; with the fix all 27 pass.

Full suite on Linux, Python 3.13: 12436 passed, 377 skipped (uv sync --extra test, then uv run pytest, 16m).

Ruff 0.15.0 (ruff check src tests) passes.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (fill in the disclosure below)

AI disclosure: Two agents, both autonomous. Codex CLI (model: gpt-6.1-sol, reasoning effort xhigh, autonomous, sandboxed and offline) found this while reading the workflow input code, wrote the reproduction, and generated the fix, tests and docs paragraph. Claude Code (model: claude-opus-5-5, autonomous) reviewed the change, reran the tests against main and the fix, reran the repro with the real specify CLI, ran the full suite and lint, and drafted this description. Commits carry Assisted-by: trailers.

…them

`type: number` inputs went through float(), so integers above 2**53
(64-bit ids, nanosecond timestamps) were rounded before any step saw
them, and an enum default holding such an integer failed validation
against its own rounded value. Try int() first for strings and ints,
and keep the float path for decimal and exponent forms.

Assisted-by: Codex CLI (model: gpt-6.1-sol, autonomous)
Assisted-by: Claude Code (model: claude-opus-5-5, autonomous)
@kartsan03
kartsan03 requested a review from mnriem as a code owner October 19, 2026 17:23
@mnriem
mnriem requested a max review from Copilot October 19, 2026 17:25
@mnriem mnriem added the triage-can-wait Verdict: valid and in-scope but deprioritized; held behind the evidence gate label Oct 19, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The localized fix preserves existing validation and includes focused unit and CLI regression coverage.

No open issues 🎉

What changed in this PR

Preserves exact integer workflow inputs, preventing silent rounding of large identifiers and timestamps.

Changes:

  • Parse integers before using floating-point conversion.
  • Add precision, validation, enum, and CLI regression tests.
  • Document number-input conversion rules.

Tests were not rerun; validation uses the supplied regression evidence. Review generated by GitHub Copilot (model unknown, autonomous).

File Description
tests/​test_workflows.py Covers precision, accepted forms, rejection, and enums.
tests/​specify_cli/​workflows/​test_command_run.py Checks exact values in shell output and persisted state.
src/​specify_cli/​workflows/​engine.py Preserves integers during number-input coercion.
docs/​reference/​workflows.md Explains numeric conversion behavior.

Review effort: Max

@mnriem
mnriem merged commit 338b776 into github:main Oct 19, 2026
16 checks passed
@mnriem

mnriem commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage-can-wait Verdict: valid and in-scope but deprioritized; held behind the evidence gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants