Skip to content

fix(copilot): stamp the resolved name into edit_workflow draft graphs - #189

Closed
sx4im wants to merge 3 commits into
tinyhumansai:mainfrom
sx4im:fix-8453-edit-workflow-draft-name
Closed

sx4im wants to merge 3 commits into
tinyhumansai:mainfrom
sx4im:fix-8453-edit-workflow-draft-name

Conversation

@sx4im

@sx4im sx4im commented Nov 3, 2026 •

Copy link
Copy Markdown

Summary

edit_workflow resolved the workflow name (the name argument, else the base graph's name, else "Untitled workflow") but never wrote it into the edited graph itself. The name traveled alongside the graph to the draft write-back and the proposal, so the durable draft kept the base graph's name, and a later save_workflow persisted that stale name onto the flow.

API Or Behavior Changes

Behavior fix only: the draft graph written by edit_workflow now carries the resolved name in graph.name. No API shape changes.

Tests

New regression tests in crates/tinyflows-copilot/src/tools/draft_edit_tests.rs: the resolved name lands in the draft graph, the draft-name fallback works when no name arg is given, and edit -> save_workflow persists the name end to end. All three failed before the fix and pass after it.

  • cargo fmt --check
  • cargo clippy --all-targets -- -D warnings
  • cargo clippy --all-targets --all-features -- -D warnings (blocked by disk quota on this machine, unrelated to the change)
  • cargo build --all-targets (covered by the clippy run above)
  • cargo build --all-targets --all-features (blocked, same as above)
  • cargo test (cargo test -p tinyflows-copilot: 84/84 pass)
  • cargo test --all-features (blocked, same as above)

Documentation

Not needed: the behavior now matches the documented contract (the name parameter is already described as "Name for the resulting proposed flow").

Fixes tinyhumansai/openhuman#8453

Summary by CodeRabbit

  • Bug Fixes
    • Workflow names are now correctly saved when editing a workflow. An explicitly provided name is retained, and edits without a new name keep the draft’s existing name.
    • The saved workflow displays the resolved name after the edit is complete.

edit_workflow resolved the workflow name but never wrote it into
edited.name, so the durable draft kept the base graph's name and a later
save_workflow persisted that stale name.

Fixes tinyhumansai/openhuman#8453

Co-authored-by: Saim Shafique <128062316+sx4im@users.noreply.github.com>
@tinysweeper

tinysweeper Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Tiny Sweeper review

Reviewed head: 8de2b4f33fc5d7ff4b1f588c39ae8cb347344245

Findings

No active actionable findings.

Advisory notes

  • medium: Document the changed name fallback in the description ((pull request description))
    Problem: The diff makes two behaviour changes, not one.
    Suggested fix:
    Behavior fix only: the draft graph written by `edit_workflow` now carries the resolved name in `graph.name`. No API shape changes. The fallback used when no `name` argument is given also changed: it is now the base **graph's** name (`draft.graph.name` / `flow.graph.name`), not the draft or flow record's top-level name, so a record name that has lagged behind its graph can no longer be stamped into the graph. The two only differ once they have diverged, which is what the staleness-chain tests cover.
    

Resolved this pass

  • Restore edited_from_flow for draft-based edits
  • Restore edited_from_flow for draft-based edits
  • Restore edited_from_flow for draft-based edits
  • Restore edited_from_flow for draft-based edits

Verdict: Ready for maintainer review · Priority: medium
Coverage: Reviewed 2 of 2 files.

Diagnostics and supporting details

Full summary

Pull request purpose (title): fix(copilot): stamp the resolved name into edit_workflow draft graphs. The pull request addresses tinyhumansai/openhuman#8453: `edit_workflow` resolved a workflow name but never wrote it into the edited graph, so the name only travelled alongside the graph into the draft write-back and the proposal; the durable draft kept the base graph's name, and a later `save_workflow` persisted that stale name onto the flow. The change makes the edited graph mutable and stamps the resolved name into `edited.name` after the ops are applied and before structural validation and both write-back paths, and it also changes the fallback used when no `name` argument is supplied to come from the base graph / flow graph rather than the draft or flow record metadata. A new sibling test module covers the explicit-name case, the graph-name fallback, the "Untitled workflow" fallback, edit→save round trips, two edit→save→edit→save staleness chains, and the flow-linked draft next-step hint. On this revision the critique lane's previously reported loss of the draft branch's `edited_from_flow` assignment is reported fixed, with a test covering the next-step hint; one gap remains, reported by the critique lane: a flow-based edit whose flow graph carries no `name` resolves to "Untitled workflow" rather than the flow's real name. The description lane also notes the PR description does not mention the fallback-source change.

Review snapshot

Change surface Files Review signal Count
Production 1 Active findings 0
Tests 1 Noted findings 1
Documentation 0 Resolved findings 4
Configuration 0 Pending checks/questions 0

Completeness: Complete
Test assessment: Test coverage is assessed from changed tests and lane evidence; execution is not claimed without trusted check data.

What changed

In `crates/tinyflows-copilot/src/tools/draft_edit.rs`, the result of `tinyflows::graph_ops::apply_ops` is bound as `let mut edited`, and a new statement sets `edited.name = name.clone()` before structural validation of the result and before the draft write-back and proposal paths, so the resolved name is carried in the graph itself rather than only alongside it. The draft branch keeps `edited_from_flow = draft.flow_id.clone();` but now resolves its default name from `graph.name.clone()` instead of `draft.name`; the flow branch resolves it from `flow.graph.name.clone()` instead of `flow.name`. The same file registers a new `#[cfg(test)]`/`#[path]` module pointing at `draft_edit_tests.rs`. The new `crates/tinyflows-copilot/src/tools/draft_edit_tests.rs` provides graph/args/proposal helpers and regression tests over the in-memory host fake, including one asserting a flow-linked draft edit's `next` hint points at `save_workflow` rather than `create_workflow`.

Features

  • Modified — Stamp resolved workflow name into the edited graph before validation and write-back: The draft graph produced by `edit_workflow` now carries the resolved name in `graph.name` instead of the base graph's name, and a subsequent `save_workflow` no longer persists a stale name onto the flow. The stamp is applied once, ahead of structural validation and both the draft write-back and the proposal path. (crates/tinyflows-copilot/src/tools/draft_edit.rs, crates/tinyflows-copilot/src/tools/draft_edit.rs impl Tool for EditWorkflowTool {)
  • Modified — Resolve fallback name from the base graph / flow graph instead of the draft or flow record: When no `name` argument is given, the fallback comes from the base graph's name in both branches rather than the draft record's metadata name or the flow's top-level name, on the stated rationale that those record names can go stale relative to the graph. The critique lane reports one remaining gap from this: for a flow-based edit whose flow graph carries no `name`, the flow's real top-level name is dropped and the proposal/draft graph becomes "Untitled workflow". (crates/tinyflows-copilot/src/tools/draft_edit.rs)
  • Added — Regression test module for edit_workflow name resolution, staleness, and next-step hint: Adds a sibling `_tests.rs` module registered under `#[cfg(test)]` with `#[path]`, covering the explicit-name draft graph case, the graph-name fallback over a stale draft metadata name, the "Untitled workflow" fallback, an edit→save round trip, two edit→save→edit→save staleness chains over flow and draft records, and the flow-linked draft case that pins the proposal's `next` hint to `save_workflow`. (crates/tinyflows-copilot/src/tools/draft_edit_tests.rs)

Tests

  • unit — Asserts that when `edit_workflow` is called with an explicit `name` argument, the durable draft graph's `name` field equals that resolved name rather than the base graph's empty name.: Targets the core behavior of the fix; the tests lane reports the assertions would fail if the stamp were removed. (crates/tinyflows-copilot/src/tools/draft_edit_tests.rs)
  • unit — Asserts that with no `name` argument, a draft whose record metadata name is "Drafty" but whose graph name is "Graphy" yields "Graphy" in the written draft graph.: Pins the changed fallback source: it asserts the graph name wins over the draft record's metadata name, which is the behavior introduced by this revision. (crates/tinyflows-copilot/src/tools/draft_edit_tests.rs)
  • unit — Asserts that with no `name` argument and an empty graph name, the written draft graph is "Untitled workflow" even when the draft record itself is named.: Pins the fallback chain's terminal case, including that a stale draft metadata name does not leak into the graph. (crates/tinyflows-copilot/src/tools/draft_edit_tests.rs)
  • integration — Drives a flow-based edit with a name, a save without a name argument, a second flow-based edit with no name, and another save, asserting the later edit's proposal name comes from the graph ("Renamed") rather than the stale flow record name and that the second save keeps the graph name.: Exercises the flow-branch fallback across repeated edits and saves, including that a stale flow top-level name is not used or written back. (crates/tinyflows-copilot/src/tools/draft_edit_tests.rs)
  • integration — Drives a draft-based edit, save, second draft-based edit, and second save where the draft metadata carries a stale name and the graph carries the current name, asserting the proposal name stays "Current Name" and the final saved flow graph keeps it.: Exercises the draft-branch fallback across repeated edits and saves via the proposal payload. (crates/tinyflows-copilot/src/tools/draft_edit_tests.rs)

Before merge

None.

Agent review details

critique

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Positive: The name-stamping fix and the graph-name fallback are reported otherwise sound, and the previously reported loss of `edited_from_flow` on the draft branch is reported fixed, with its regression test present.
  • Lane summary: The naming fix (stamping the resolved name into `edited.name` and falling back to the base graph's name) is otherwise sound and the previously reported loss of `edited_from_flow` on the draft branch is fixed — the assignment and its regression test are both present. One remaining gap: for a flow-based edit whose flow graph carries no `name` (the shape the existing `edit_workflow` tests already build with `put_flow("flow-1", "Digest", false, valid_graph())`), the fallback drops the flow's real name and the proposal/draft graph becomes "Untitled workflow". _The code index is behind this pull request (indexed at `3fad50bf17c5`), so retrieved context may be out of date._

security

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Positive: The security lane reports the name-fallback change and the `edited.name` stamp consistent with the new tests, the earlier `edited_from_flow` regression fixed and covered, both touched files within the 500-line limit, and no new defects.
  • Lane summary: The name-fallback change and the `edited.name` stamp are consistent with the new tests, and the earlier `edited_from_flow` regression for draft-based edits is now fixed (`edited_from_flow = draft.flow_id.clone();` is back and covered by `draft_edit_linked_to_flow_points_next_step_at_save_workflow`). Both touched files stay within the 500-line limit and the new test file follows the sibling `_tests.rs` convention; I found no new defects. _The code index is behind this pull request (indexed at `3fad50bf17c5`), so retrieved context may be out of date._

tests

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Positive: The added tests are in a `_tests.rs` file declared with `#[cfg(test)]`/`#[path]` as the repository requires, pin each branch with assertions reported to fail if the stamp or the fallback source regresses, and cover the restored `edited_from_flow` behavior; no new defect found in the changed code or tests.
  • Lane summary: edit_workflow now stamps the resolved name into the edited graph and derives the fallback name from the base graph/flow graph instead of stale draft/flow metadata; the new draft_edit_tests.rs pins each branch (draft base, flow base, empty→"Untitled workflow", edit→save round trips) with assertions that fail if the name is not stamped or the fallback source regresses. The earlier concern about `edited_from_flow` being dropped for draft-based edits is fixed in the current head and is now covered by draft_edit_linked_to_flow_points_next_step_at_save_workflow, which fails on the create_workflow hint if that assignment is lost. I found no new defect in the changed code or its tests. _The code index is behind this pull request (indexed at `3fad50bf17c5`), so retrieved context may be out of date._

commits

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Positive: The commits lane reports no sensitive content in the committed files.
  • Lane summary: No sensitive content in committed files. (1 earlier finding(s) still open) _The code index is behind this pull request (indexed at `3fad50bf17c5`), so retrieved context may be out of date._

description

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Positive: The description lane reports the diff does what the title says and that the earlier `edited_from_flow` regression on the draft branch is fixed and tested, while noting the description never mentions that the no-`name`-argument fallback changed from the draft/flow record's name to the base graph's name.
  • Lane summary: The diff does what the title says — the resolved name is stamped into the edited graph before the draft write-back — and the earlier `edited_from_flow` regression on the draft branch is fixed (the assignment is back at line 172 and a test now covers the next-step hint). The description is incomplete, though: it never mentions that the fallback used when no `name` argument is given changed from the draft/flow record's name to the base graph's name, which is a second, independent behaviour change in the same hunk. _The code index is behind this pull request (indexed at `3fad50bf17c5`), so retrieved context may be out of date._
Evidence and run details
  • Models: ladder/vectors-oai3, deepseek-v4.1-flash
  • Spend: $0.014039
  • Tokens: 398560 input · 64008 output · 57856 cached · 371 embedding
  • Updated: 2026-11-03T16:49:04Z
Head State Pass summary
cd226ca65071 ready for maintainer review 0 active finding(s), 0 resolved finding(s) (at 2026-11-03T15:56:06Z)
3fad50bf17c5 changes requested 1 active finding(s), 0 resolved finding(s) (at 2026-11-03T16:32:50Z)
8de2b4f33fc5 ready for maintainer review 0 active finding(s), 4 resolved finding(s) (at 2026-11-03T16:49:04Z)

tinysweeper 0.1.2

@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Warning

Review limit reached

  • Run on-demand review

This review includes 2 billable files and costs up to $0.50.

Or wait 8 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f606dddc-26fa-4c2b-983f-9358b10bffb5
Commits

Reviewing files that changed from the base of the PR and between cd226ca and 8de2b4f.

Files selected for processing: 2
  • crates/tinyflows-copilot/src/tools/draft_edit.rs
  • crates/tinyflows-copilot/src/tools/draft_edit_tests.rs
Walkthrough

The edit operation now assigns the resolved workflow name to the edited graph before validation and write-back. Regression tests cover explicit names, fallback to the draft name, and persistence of the name after saving.

Changes: Workflow name in draft edits

Layer / File(s) Summary
Assign and verify the resolved name
crates/tinyflows-copilot/src/tools/draft_edit.rs, crates/tinyflows-copilot/src/tools/draft_edit_tests.rs
The edit operation sets the resolved name on the edited graph before validation and write-back. Tests cover an explicit name, fallback to the draft name, and persistence after saving.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: senamakel

Merge Risk: Low · previous review cd226

Editing without a name can replace a workflow graph’s name with stale metadata. Correct the fallback or accept this limited risk.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: writing the resolved workflow name into edit_workflow draft graphs.
Linked Issues check Passed Issue #8453 has one active coding requirement: edit_workflow must write the resolved workflow name into the edited graph before writing the draft and building the proposal, and edit-to-save behavior…
Out of Scope Changes check Passed The whole-PR diff against the merge base contains three kinds of change, all tied to #8453:
- draft_edit.rs: the single behavior change (edited.name stamp) plus its explanatory comment. The `let m…
Full details: Linked Issues check

Explanation

Issue #8453 has one active coding requirement: edit_workflow must write the resolved workflow name into the edited graph before writing the draft and building the proposal, and edit-to-save behavior must be covered by tests.

Evidence at head (cd226ca):

  • crates/tinyflows-copilot/src/tools/draft_edit.rs: edited is now bound as mut, and edited.name = name.clone(); runs after apply_ops and before validate_all and the draft write-back. The write-back and proposal use the same edited binding, so they carry the resolved name. The name fallback order (name argument, base graph name, "Untitled workflow") is unchanged code that feeds name.
  • crates/tinyflows-copilot/src/tools/draft_edit_tests.rs (new, registered as edit_tests) covers three cases:
    • edit_workflow_writes_resolved_name_into_draft_graph: explicit name arg reaches draft.graph["name"].
    • edit_workflow_falls_back_to_draft_name_when_no_name_arg: with no name arg, the draft name is written into the graph.
    • edit_then_save_persists_resolved_name_in_flow_graph: edit followed by save_workflow persists the name to flow.graph.name.

The issue also asks to release the module and bump openhuman's record and test gate. These steps are non-coding and are outside this repository change, so they are not assessed.

Limit: I did not re-read the full write-back function body. The conclusion relies on the diff, which shows the stamp placed before validation and on the unchanged use of edited in the write-back.

Full details: Out of Scope Changes check

Explanation

The whole-PR diff against the merge base contains three kinds of change, all tied to #8453:

  • draft_edit.rs: the single behavior change (edited.name stamp) plus its explanatory comment. The let mut binding is required for that change.
  • draft_edit.rs: a #[cfg(test)] #[path = "draft_edit_tests.rs"] mod edit_tests; registration. This only wires the regression tests.
  • draft_edit_tests.rs: new regression tests for the name behavior. These support the issue's test requirement.

No unrelated code, API shape change, or other file change appears in the reviewed diff. The PR description states that the API shape is unchanged, and the diff agrees.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 1 functions across 2 files.

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

A rabbit checks the workflow name,
Then watches edits write the same.
Draft and saved graph keep it clear,
A tidy name from start to here.
One hop, one test, all names appear.

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4a18eb9b-50bf-428b-a2f9-003fccbec95e
Commits

Reviewing files that changed from the base of the PR and between 674929a and cd226ca.

Files selected for processing: 2
  • crates/tinyflows-copilot/src/tools/draft_edit.rs
  • crates/tinyflows-copilot/src/tools/draft_edit_tests.rs

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@tinysweeper tinysweeper 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.

tinysweeper found nothing blocking. Approving.

Diagnostics

Total spend: $0.0111

@tinysweeper tinysweeper Bot added the priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. label Nov 3, 2026

@coderabbitai coderabbitai 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.

  • Fix comments: Fix CodeRabbit comments on this PR

The draft/flow metadata name can go stale: save_workflow without a name
arg advances the flow's graph but not its top-level name, so a later
edit resolved the stale record name and (since the #8453 stamp) baked it
into the durable graph, clobbering the current name on the next save.
Fall back to the base graph's name instead, per the issue's resolution
order (name arg, else graph name, else Untitled workflow).

Co-authored-by: Saim Shafique <128062316+sx4im@users.noreply.github.com>

@tinysweeper tinysweeper 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.

Requesting changes: 1 lane(s) blocking, worst finding is high.

Fix or reply to the findings below and push. The next review clears this automatically once they are gone — you should not need to dismiss anything by hand.

Diagnostics

Total spend: $0.0087

(graph, draft.name)
// Fall back to the base GRAPH's name — the draft metadata name
// can go stale and would then be stamped into the graph itself.
let default_name = graph.name.clone();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

priority high critique confident

Restore edited_from_flow for draft-based edits

The diff removes `edited_from_flow = draft.flow_id.clone();` from the draft branch while leaving the comment that says it exists ("A draft may already be linked to a saved flow — carry that through so the proposal echoes it.") and while the sibling `flow_id` branch still sets `edited_from_flow = Some(flow.id.clone());`. The consequence is reachable on the most common iteration path: call `edit_workflow { flow_id: "f1", ops: [...] }` (seeds draft d1 linked to f1 and correctly returns `flow_id: "f1"` plus "persist with save_workflow { flow_id, draft_id }"), then call `edit_workflow { draft_id: d1, ops: [...] }`. In that second call `edited_from_flow` stays `None`, so `build_proposal` omits the `flow_id` from the payload and the `next` hint flips to "Edits live on draft … (not yet linked to a saved flow) … persist with create_workflow, or save_workflow { flow_id, draft_id } once a flow exists." — actively steering the agent to mint a duplicate flow instead of saving back onto f1.

[RULE] dropped-assignment ·

@tinysweeper tinysweeper Bot added priority: p1 Next. Wrong behaviour a user will hit, or a security weakness behind a condition. and removed priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. labels Nov 3, 2026
The CodeRabbit follow-up changed the draft branch's name fallback from
draft.name to the base graph's name (correct), but also deleted the
'edited_from_flow = draft.flow_id.clone();' line it was never asked to
touch. Draft-based edits on flow-linked drafts then left edited_from_flow
as None, pointing the proposal's next-step hint at create_workflow instead
of save_workflow.

Restore the line with its original comment, keeping the corrected
(graph, default_name) fallback. Adds a regression test asserting a
flow-linked draft edit's next-step hint references save_workflow.

Co-authored-by: Saim Shafique <128062316+sx4im@users.noreply.github.com>

@tinysweeper tinysweeper 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.

The previously-blocking findings are resolved. Clearing the changes request.

Diagnostics

Total spend: $0.0140

@tinysweeper tinysweeper Bot added priority: p2 Soon. Real but survivable — a rough edge, a gap, a thing that will bite later. and removed priority: p1 Next. Wrong behaviour a user will hit, or a security weakness behind a condition. labels Nov 3, 2026
@sx4im

sx4im commented Nov 5, 2026

Copy link
Copy Markdown
Author

Closing this PR as I am narrowing my contribution focus to other repos.

@sx4im sx4im closed this Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: p2 Soon. Real but survivable — a rough edge, a gap, a thing that will bite later.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tinyflows edit_workflow stores the draft without the resolved workflow name in graph.name

1 participant