Skip to content

fix(remote): accept autonomous lifecycle reports - #70

Merged
dnth merged 5 commits into
dnth:mainfrom
pranaypratyush:fm/fm-remote-reply-autonomous-status
Aug 30, 2026
Merged

dnth merged 5 commits into
dnth:mainfrom
pranaypratyush:fm/fm-remote-reply-autonomous-status

Conversation

@pranaypratyush

Copy link
Copy Markdown

Intent

Repair the remote-secondmate reply adapter so it accepts autonomous material lifecycle status lines permitted by the generated secondmate charter without weakening correlation checks for replies to marked parent requests.

Accept autonomous working, needs-decision, blocked, paused, done, failed, and matching resolved lifecycle reports without corr= as status input. Only a status line carrying the exact correlation token for a marked parent request may resolve that pending reply. A mixed delta with autonomous blocked/resolved lines and a valid correlated done reply must ingest each valid line once in order, resolve only the matching expectation, advance from the captured prefix to the new cursor, acknowledge the captured generation, and re-arm normally.

Preserve bounded printable-line validation, allowed lifecycle verbs, exact correlation-based pending-reply resolution, safe data/*.md document-pointer fetching, idempotent ingest, prefix/cursor continuity, durable acknowledgement, re-arm behavior, and rejection boundaries for unknown verbs, malformed or non-printable input, unsafe or unbounded content, unsafe document pointers, prefix discontinuity, duplicate capture, and mismatched correlation.

Keep the repair limited to the existing adapter and colocated executable regression tests using isolated fixtures. Do not inspect, modify, stop, restart, or send to the live nsm-5950x route or any private fleet record. Do not broaden into FNM discovery, wrapper management, remote routing, or general status-protocol redesign. Do not merge a PR.

Acceptance coverage must include autonomous-only, correlated-only, mixed, idempotent replay, and rejected-input behavior through the real remote-reply adapter interface.
Firstmate-Validation-Generation: 829c5ec05fc152f31d15921e5257d6ce

What Changed

  • Allow bounded, permitted remote lifecycle status lines to ingest without a correlation token, while retaining status-line deduplication and document-pointer rewriting.
  • Parse only standalone exact corr=<16hex> tokens when resolving pending parent replies, preventing corr-like text or mismatched tokens from resolving expectations.
  • Extend remote-reply adapter coverage and documentation for autonomous, correlated, mixed, replayed, and rejected lifecycle reports.

Risk Assessment

✅ Low: The tightly scoped change preserves adapter durability while separating autonomous lifecycle ingestion from canonical exact-token pending-reply resolution.

Testing

Inspected the target diff and kept the worktree clean. Focused adapter and pending-reply suites passed, covering capture, autonomous and correlated ingestion, exact uppercase correlation resolution, replay idempotency, cursor continuity, acknowledgement/re-arm, document-pointer handling, and rejected lifecycle input. The persisted-state transcript shows autonomous corr-like text remained awaiting_report while the exact uppercase corr field resolved only its matching request and advanced the durable cursor.

Evidence: Manual mixed-delta adapter transcript
REMOTE-REPLY ADAPTER: MIXED DELTA

Adapter CLI output:
ingested: ios appended=6 offset=294

Persisted parent lifecycle log (arrival order):
     1	blocked [key=remote-build]: waiting for approval
     2	done: notcorr=0bd78e582c7d5bdd remains autonomous
     3	done: not-corr=0bd78e582c7d5bdd remains autonomous
     4	done: not[corr=0bd78e582c7d5bdd] remains autonomous
     5	resolved [key=remote-build]: approval arrived
     6	done [corr=22AC646247A6CAE2]: build completed

Pending autonomous correlation (0bd78e582c7d5bdd): awaiting_report
Pending exact uppercase correlation (22AC646247A6CAE2): resolved

Durable cursor:
schema=fm-remote-reply-cursor.v1
offset=294
prefix_sha256=afd6481fbd004156a26412e745baf9718a0aa65ae85995ff161083f606ab8951

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 2 issues found → auto-fixed (3) ✅
  • 🚨 bin/fm-procevent-remote-reply.sh:250 - A valid lifecycle line such as done: notcorr=0123456789abcdef passes the new validation, then the corr= substring is extracted and resolves pending request 0123456789abcdef. This violates the required exact-token correlation invariant; enforce token boundaries in the shared pending-reply matcher (which also protects reconciliation) and cover this adapter path.
  • ⚠️ docs/remote-secondmates.md:191 - The changed operator contract now permits autonomous lifecycle deltas, but the script index still describes this adapter as relaying only “correlated” deltas. Update that index to describe lifecycle ingestion with exact-correlated pending-reply resolution.

🔧 Fix: Enforce exact remote reply correlation boundaries
3 issues (2 errors, 1 warning) still open:

  • 🚨 bin/fm-pending-reply-lib.sh:141 - The intent requires that “Only a status line carrying the exact correlation token for a marked parent request may resolve that pending reply.” The changed matcher at this hunk accepts any non-word character before corr=, so done: not-corr=&lt;pending-id&gt; is ingested, extracted as corr=&lt;pending-id&gt;, and resolves the request even though the field is not-corr, not corr. Tighten the shared matcher (and adapter extraction) to recognize only permitted correlation-field delimiters, preserving reconciliation protection.
  • 🚨 bin/fm-pending-reply-lib.sh:141 - Lifecycle validation explicitly accepts uppercase hexadecimal correlation values, and the adapter canonicalizes them to lowercase before resolution, but the new exact matcher compares the raw status text case-sensitively. Thus done [corr=ABCDEF0123456789]: ... is valid and names the stored lowercase request, yet it is appended without resolving it. Preserve token boundaries while matching canonical hexadecimal IDs case-insensitively.
  • ⚠️ docs/scripts.md:80 - The script index still describes this adapter as relaying only “correlated” deltas, which is now false because autonomous lifecycle deltas are intentionally ingested. Update the row to distinguish lifecycle-delta ingestion from exact-correlated pending-reply resolution.

🔧 Fix: Harden remote reply correlation parsing
1 error still open:

  • 🚨 bin/fm-pending-reply-lib.sh:140 - done: not[corr=&lt;pending-id&gt;] is not a reply passes lifecycle validation, then this splitter turns the bracketed substring into standalone corr=&lt;pending-id&gt;. Both adapter ingestion and later reconciliation therefore resolve the pending request, despite no exact correlation field being present. Recognize correlation fields only at admissible status-token boundaries, and add this adapter-path regression.

🔧 Fix: Require whole-token remote reply correlations
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • bash tests/fm-remote-reply.test.sh
  • bash tests/fm-pending-reply.test.sh
  • Manual isolated mixed-delta ingest through bin/fm-remote-delta-read.sh and bin/fm-procevent-remote-reply.sh ingest ios
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-08-29T13:19:21.506173Z b821cd8 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@dnth dnth left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Review: approve — clean, scoped, and it closes a real hole

Reviewed against upstream kunchenguid#2618 ("preserve pending replies and defer remote reposts", merged 2026-08-19 @ a693f40) and this fork's current pain (two pending-reply-missed lapses on 2026-08-30).

What this does right:

  1. Closes a substring false-resolution hole. The old fm_pending_reply_text_has_corr matched the correlation token as any substring — a status line containing notcorr=<hex> in prose could resolve a marked parent request. The new exact-token extraction (corr=<16hex> as a standalone token, [corr=…]:, or (corr=…), canonicalized) matches only genuine status tokens, and the new adversarial tests prove all four corr-like decoy forms (notcorr=, not-corr=, not.corr=, not[corr=]) ingest without resolving. Correlation security is strictly stronger.
  2. Unblocks autonomous lifecycle reports. Requiring corr= on every line meant ordinary working:/paused:/blocked: reports from a secondmate were rejected outright — the exact condition behind our recent pending-reply-missed storms. Verb allow-list, bounded-printable checks, and one-shot deduplicated append are all preserved.
  3. Fail-closed ordering. payload_lines_valid validates the whole delta before any append — no partial-append when a later line is invalid.
  4. Order-preserving mixed-delta semantics. Autonomous + correlated lines in one delta ingest in order, resolve only the exact matching request, advance the cursor, and re-arm. Wrong correlation never resolves. Idempotent replay, continuity-break escalation, and retirement refusal paths all retained and still tested.
  5. No riders. Six files, all in-scope; docs (architecture.md, remote-secondmates.md, scripts.md) updated consistently with the code.

Notes for the record:

  • vs upstream kunchenguid#2618 (11 files): this is the fork-adapted subset covering the pending-reply correlation contract. The remote-repost-deferral half of kunchenguid#2618 is largely absorbed by this fork's durable steering inbox (#68); if any residue matters it is a small follow-up, not a blocker.
  • 15/15 checks green.

This is the form #69 should have been. Recommend merge.

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.

2 participants