Skip to content

fix(bin): keep the PR block last when registering a no-mistakes clone - #12

Merged
NewAiCoder merged 1 commit into
mainfrom
fm/fm-meta-nm-clone-after-pr
Oct 2, 2026
Merged

NewAiCoder merged 1 commit into
mainfrom
fm/fm-meta-nm-clone-after-pr

Conversation

@NewAiCoder

@NewAiCoder NewAiCoder commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

What Changed

  • fm-nm-watch.sh register-clone now rewrites the task record with awk instead of appending nm_clone= at the end. It drops any existing nm_clone= line, writes nm_clone= before the PR block (pr=, pr_head=, x_request, x_request_ts, x_followups, x_platform, x_reply_max_chars), and keeps the PR block last. This matters because fm_pr_metadata_identity_parse rejects any other line after the first pr=, so registering a clone after a PR existed made the merge poll treat the record as invalid.
  • Added test_register_clone_keeps_pr_block_last to tests/fm-nm-watch.test.sh. It checks that:
    • nm_clone= is the last line when there is no PR block.
    • Registering twice on a record with a PR block leaves nm_clone= present exactly once and pr/pr_head as the last two lines.
    • fm_pr_metadata_identity_parse still accepts the record afterwards.

Risk Assessment

✅ Low: A small, well-bounded fix that keeps nm_clone= ahead of the PR block as fm_pr_metadata_identity_parse requires. A behavioral test covers the with-PR and no-PR cases and repeated registration; the only issue found is an edge case with backslashes in clone paths.

Testing

I ran the fm-nm-watch behavior test on the fix, and the new regression case passes. Run on the base commit, the same case fails with 'the PR block is not last', which reproduces the bug. I also drove the real register-clone script on a task record with a stale nm_clone=, an unrelated line and a full PR block with all five x_* lines. The clone path was recorded exactly once, the PR block stayed last, and the merge-poll validator accepted the record. No UI surface is involved, so there are no screenshots. The test touches only temp directories and throwaway git worktrees, which I removed.

  • Live validation: ✅ go - 3 of 3 scenarios driven live against the product
Scenario Result Live Evidence
Register a clone on a task record with no PR block: nm_clone= is recorded as the last line ✅ pass live tests/fm-nm-watch.test.sh test_register_clone_keeps_pr_block_last, first assertion; ran the real fm-nm-watch.sh
Register a clone on a record that already has pr=/pr_head=, twice: nm_clone= appears exactly once, pr and pr_head stay last, and the merge-poll validator accepts the record ✅ pass live tests/fm-nm-watch.test.sh loop with fm_pr_metadata_identity_parse; the same test fails on base bfc1e2b
Adversarial: stale nm_clone= mid-file, an unrelated line, and a full PR block including x_request, x_request_ts, x_followups, x_platform and x_reply_max_chars ✅ pass live Ad-hoc run of the real register-clone script: output had one nm_clone= placed before pr=, and the x_* lines stayed after pr_head=. The validator printed VALID.
Evidence: Base-commit repro of the bug
base bfc1e2b + new test: 'not ok - the PR block is not last'. Fix 3794160: 'ok - register-clone keeps the PR block last so the merge poll stays valid'.

Pipeline

Updates from git push no-mistakes

⏭️ **intent** - skipped

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 1 info
  • ℹ️ bin/fm-nm-watch.sh:100 - awk -v clone="$path" interprets backslash escape sequences in the value. A valid absolute clone path containing a backslash (e.g. /srv/a\tb) would be written to nm_clone= altered (a tab, not the literal path). The old printf '%s' recorded it verbatim. Pass the path via the environment (FM_NM_CLONE="$path" awk ... ENVIRON["FM_NM_CLONE"]) to keep it byte-exact. Rare in practice.
✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 3 of 3 scenarios driven live against the product
Scenario Result Live Evidence
Register a clone on a task record with no PR block: nm_clone= is recorded as the last line ✅ pass live tests/fm-nm-watch.test.sh test_register_clone_keeps_pr_block_last, first assertion; ran the real fm-nm-watch.sh
Register a clone on a record that already has pr=/pr_head=, twice: nm_clone= appears exactly once, pr and pr_head stay last, and the merge-poll validator accepts the record ✅ pass live tests/fm-nm-watch.test.sh loop with fm_pr_metadata_identity_parse; the same test fails on base bfc1e2b
Adversarial: stale nm_clone= mid-file, an unrelated line, and a full PR block including x_request, x_request_ts, x_followups, x_platform and x_reply_max_chars ✅ pass live Ad-hoc run of the real register-clone script: output had one nm_clone= placed before pr=, and the x_* lines stayed after pr_head=. The validator printed VALID.
  • bash tests/fm-nm-watch.test.sh on the target commit (all four cases pass, including the new test_register_clone_keeps_pr_block_last)
  • The same test file run against a throwaway worktree of base commit bfc1e2b: fails with 'the PR block is not last'
  • Ad-hoc run of real bin/fm-nm-watch.sh register-clone on a record with a stale nm_clone=, an unrelated line, pr=, pr_head= and all five x_* lines, then fm_pr_metadata_identity_parse on the result
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

register-clone appended nm_clone= after the pr= and pr_head= lines, so the merge poll's record validator rejected the task record on every cycle. Insert nm_clone= before the PR block instead.
@NewAiCoder
NewAiCoder force-pushed the fm/fm-meta-nm-clone-after-pr branch from 5d634ca to 3794160 Compare October 1, 2026 23:34
@NewAiCoder NewAiCoder changed the title fix(bin): keep the PR block last when registering an nm clone fix(bin): keep the PR block last when registering a no-mistakes clone Oct 1, 2026
@NewAiCoder
NewAiCoder merged commit 5b9f42c into main Oct 2, 2026
20 of 21 checks passed
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