Skip to content

fix(verify,diagnostics): dw3-dw5 ledger sweeps (DW-40 … DW-94) - #760

Merged
pbean merged 18 commits into
pbean/dw-s3-resolve-context-parkfrom
pbean/dw-s4-sweep-dw3-dw5
Sep 4, 2026
Merged

fix(verify,diagnostics): dw3-dw5 ledger sweeps (DW-40 … DW-94)#760
pbean merged 18 commits into
pbean/dw-s3-resolve-context-parkfrom
pbean/dw-s4-sweep-dw3-dw5

Conversation

@pbean

@pbean pbean commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

What

Fourth of five stacked PRs draining Wave 2's deferred-work ledger. Closes DW-40, DW-53, DW-54,
DW-56 … DW-63, DW-67, DW-74 … DW-77, DW-80, DW-84, DW-86, DW-87, DW-89, DW-91, DW-93, DW-94

(24 entries) — the dw3/dw4/dw5 sweep batches.

Why

The tail of the ledger: the entries the later sweep passes reached once the earlier slices had
settled the contracts they depend on. Several are documentation-of-record for decisions taken
during Wave 2's review (DW-91, DW-93) rather than code changes.

How

  • Authoritative re-arm outcome (DW-40) and the verify command fault contract (DW-53,
    DW-54).
  • Root-divergence fixture hardening (DW-56 … DW-63) — eight entries in verify.py's test
    fixtures.
  • Diagnostic journal sanitization (DW-76, DW-77, DW-80, DW-84) and session artifact JSON
    hardening
    (DW-86, DW-89).
  • Adapter task-directory confinement (DW-74); session artifact and resolve context contract
    docs (DW-67, DW-75, DW-87); run lifecycle resume exclusion (DW-94).

Testing

uv run pytest -q -n logical, uv run pyright, and trunk check --all --no-fix all clean at
this tip. Negative assertions ablated before being trusted.

Changelog

Entries land under ## [Unreleased] in CHANGELOG.md.


Stack (merge bottom-up): S1 → S2 → S3 → S4 (this) → S5. Base is S3, not main.

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 375956d5-9b9b-46b3-ac81-fd70bb185275

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pbean

pbean commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 2, 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-09-04T03:16:46.222281Z afe18c1 Manual request
ℹ️ 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.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 9ae77d60f0

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@pbean
pbean force-pushed the pbean/dw-s4-sweep-dw3-dw5 branch from 9ae77d6 to 387e394 Compare September 2, 2026 23:38
@pbean

pbean commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 387e3949ff

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- `git diff --check` -- expected: no whitespace errors.
- `git diff -- _bmad-output/implementation-artifacts/deferred-work.md` -- expected: empty.

## Auto Run Result

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Remove the committed run artifact

Remove this generated implementation record from the commit: its Auto Run Result, verification transcript, and review-triage log are session/run artifacts rather than durable documentation, and the repository explicitly prohibits committing these records. Keeping it tracked also bypasses the _bmad-output/ ignore rule and leaves transient execution history in the source tree.

AGENTS.md reference: AGENTS.md:L71-L71

Useful? React with 👍 / 👎.

@pbean
pbean force-pushed the pbean/dw-s4-sweep-dw3-dw5 branch from 387e394 to d540f15 Compare September 3, 2026 00:37
@pbean

pbean commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: d540f15d3c

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@pbean
pbean force-pushed the pbean/dw-s4-sweep-dw3-dw5 branch from d540f15 to a7bce9f Compare September 3, 2026 01:12
@pbean

pbean commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: a7bce9f610

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@pbean
pbean force-pushed the pbean/dw-s4-sweep-dw3-dw5 branch from a7bce9f to 85d587a Compare September 3, 2026 01:31
@pbean

pbean commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 85d587a5e4

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/bmad_loop/runs.py Outdated
state = load_state(run_dir)
current_engine = read_pid_identity(run_dir)
current_liveness = engine_liveness(run_dir)
rival_published_engine = current_liveness != "dead" and current_engine != addressed_engine

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Avoid treating an unverifiable PID as a new engine

When the recorded PID still exists but its process identity cannot be read, alive_and_ours() returns false earlier in _stop_run_once and the local pid is replaced with None, while this later read returns current_liveness == "unknown" and retains the recorded PID in current_engine. This condition therefore always identifies the unchanged engine as a rival, returns None, and makes stop_run() retry forever. Preserve the original PID-file tuple for the generation comparison so an unverifiable engine does not create an infinite stop loop.

Useful? React with 👍 / 👎.

Comment on lines +631 to +634
validate_adapter_artifact_paths(
task_dir,
(task_dir / "messages.json",),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Validate OpenCode heartbeat and breadcrumb paths

When a reused OpenCode task directory contains a symlink, hardlink, FIFO, or device named heartbeat.json, resultless-stops.jsonl, or session-lifecycle.jsonl, this validates only messages.json even though the inherited _ResultFileMixin later writes all three omitted files. The heartbeat overwrite can truncate a linked external file, and diagnostic appends can modify or block on redirected entries, so include every adapter-written task artifact in this pre-write validation as the generic adapter does.

Useful? React with 👍 / 👎.

@pbean
pbean force-pushed the pbean/dw-s4-sweep-dw3-dw5 branch 2 times, most recently from 5ca7732 to bd3b74a Compare September 3, 2026 02:53
@pbean

pbean commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: bd3b74a363

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@pbean
pbean force-pushed the pbean/dw-s4-sweep-dw3-dw5 branch from bd3b74a to 768516c Compare September 3, 2026 03:39
@pbean

pbean commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@pbean
pbean force-pushed the pbean/dw-s4-sweep-dw3-dw5 branch from 953fa94 to 85a1038 Compare September 3, 2026 22:40
@pbean

pbean commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: 85a1038677

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@pbean
pbean force-pushed the pbean/dw-s4-sweep-dw3-dw5 branch from 85a1038 to ec60b45 Compare September 4, 2026 01:27
@pbean

pbean commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ec60b45883

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/bmad_loop/tui/app.py Outdated
resolution_recorded=False,
)
except RearmError as e:
with state_lock(run_dir):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep lifecycle-lock waits off the TUI event thread

When a concurrent CLI resume has acquired this lock but has not yet published its PID, the preceding liveness check passes and this synchronous modal callback blocks here. _prepare_resume_locked holds the same lock across configuration, skill, profile, and Git preflight, and the POSIX lock wait is unbounded, so the Textual event loop can stop repainting and accepting input for an extended period. Acquire the lock and perform the re-arm in a worker, or use a nonblocking acquisition and report the contention.

Useful? React with 👍 / 👎.

@pbean
pbean force-pushed the pbean/dw-s4-sweep-dw3-dw5 branch from ec60b45 to afe18c1 Compare September 4, 2026 02:58
@pbean

pbean commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: afe18c17f3

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

t added 18 commits September 3, 2026 20:31
…59, DW-60, DW-61, DW-62, DW-63 via bmad-loop
…POSIX-only imports

Two rows fake a non-Windows `sys.platform` to pin the POSIX half of a gate.
The faked branch reaches `import fcntl`, which does not exist on Windows, so
they raise ModuleNotFoundError there rather than testing anything. They
predate this series; the sweep only extended `diagnostics.collect` far enough
to reach that import. Skip them off POSIX — the Linux legs still hold the row.

The replacement-directory row deleted the run dir and recreated it, assuming
the new directory would land on a different inode. A filesystem is free to
reuse the inode it just released, and CI's does: `os.path.samestat` then reads
the replacement as the very directory the composer claimed, the guard
correctly stays silent, and the row failed on an empty warning. Allocate the
replacement while the original is still live — two directories that exist at
once cannot share an inode — then rename it into place.
Second site with the same version-dependent premise as the resolve row: a
hardcoded `getrecursionlimit() * 20` that 3.13 cannot decode but 3.14 parses
iteratively, so the row failed on "DID NOT RAISE" rather than on the
degradation it exists to pin. Take the depth from the conftest probe.
… not as cleared

`_stop_run_once` clears its local `pid` on every path that declines to signal
— gone, reused, or an identity it cannot read — and then compared the
post-delivery pid file against that cleared tuple. An engine whose pid exists
but whose identity cannot be read (win32 ERROR_ACCESS_DENIED) is `"unknown"`,
not `"dead"`, so the unchanged file read as a rival that had just published a
new engine, `_stop_run_once` answered "retry", and `stop_run` — unbounded by
design, so a real rival is always sent the stop — never returned.

Keep the tuple as read for the generation compare. A rival is a CHANGED pid
file, nothing else; the unverifiable engine then takes the fallback the
pre-split `stop_run` always took for it. The test wraps `_stop_run_once` so
the livelock reddens instead of hanging the suite.
… writing

`OpencodeHttpAdapter.start_session` refused a redirected `messages.json` — its
own file — but not a symlinked, hardlinked, FIFO or device `heartbeat.json`,
`resultless-stops.jsonl` or `session-lifecycle.jsonl`, all written by the
inherited `_ResultFileMixin`. A reused task directory carrying one of those
let the heartbeat overwrite truncate a linked external file and the breadcrumb
appends block on or redirect into it, which GenericAdapter already refuses.

The three names move into `generic.RESULT_FILE_ARTIFACTS`, handed to
`validate_adapter_artifact_paths` by both adapters, so a fourth mixin write
cannot reach one adapter's validation and miss the other's. The test is
parametrized over that tuple for the same reason.
The per-run state lock DW-94/DW-93 added to `delete_run`/`archive_run` is
new in this branch — on main neither took a lock — and `file_lock` raises a
plain `OSError` when the acquisition fails. That escaped `cmd_clean`'s
per-candidate handler and aborted the whole invocation: later candidates
were never processed, and runs the loop had already mutated vanished from a
report only emitted after the loop.

`file_lock` now raises a typed `LockUnavailableError` for a failed
acquisition alone (never the locked body, never the lock-file create), and
`cmd_clean` catches it beside the lifecycle races, classifying the run by
what actually happened and continuing. Typed rather than a bare `OSError`
so `UnconfinedWriteError` — also an `OSError` — is never folded into
"left untouched".

`clean` acquires with `wait_for_lock=False`: `fcntl.flock` never times out,
so waiting was unbounded on POSIX, and a lock someone else holds already
means what `clean` reports anyway. The flag is threaded through
`state_lock` and defaults to blocking, leaving every other caller unchanged.
The entry ran 13 lines against 5- and 9-line neighbours, carrying DW ids, the
exception taxonomy and root-cause narration that belong in docstrings and git
history. Keep the what and the user-facing why in 5 lines.
…shboard

`_do_rearm` took the run's state lock blocking, on Textual's message loop —
no `@work`, and its sole caller is the synchronous `push_screen` dismiss
callback. On POSIX that wait is unbounded (`fcntl.flock` never times out), and
the realistic holder is a rival `resume`, which keeps the lock across config,
skills, profiles and a git preflight bounded only by `[limits] git_timeout_s`
(120s by default) while publishing its pid last, so the modal's
`_engine_possibly_live` gate reads dead for that whole window. Measured: 3.00s
against a 3s holder, 8.00s against an 8s holder.

Acquire with `blocking=False` and report the contention as a toast. The new
`except LockUnavailableError` arm MUST precede the existing
`except (RearmError, OSError, runs.StateRootError)`: the error is an `OSError`
subclass, so the reverse order makes it dead code and files contention as
"re-arm failed". Waiting bought nothing anyway — the post-lock liveness
re-check refuses a re-arm against a live rival.

The `finally`'s residue echo is skipped on contention: a refused acquisition
ran nothing, so any record appended in that window belongs to the holder.
@pbean
pbean force-pushed the pbean/dw-s4-sweep-dw3-dw5 branch from afe18c1 to f125d52 Compare September 4, 2026 03:31
@pbean
pbean merged commit c47333d into main Sep 4, 2026
11 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