Skip to content

fix(worktree): seed and verify isolated BMAD surfaces - #449

Merged
pbean merged 6 commits into
mainfrom
port/phase-6h-seeding-escalations
Aug 3, 2026
Merged

fix(worktree): seed and verify isolated BMAD surfaces#449
pbean merged 6 commits into
mainfrom
port/phase-6h-seeding-escalations

Conversation

@pbean

@pbean pbean commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • merge-seed the project-local _bmad/ surface into isolated worktrees, per file and without clobbering checkout content, while excluding generated render output
  • re-probe upstream skill and renderer completeness in WorktreeFlow.run_isolated; CRITICAL-escalate only deterministic session stalls, while journaling arbitrary undelivered seeds as worktree-seed-dropped
  • record worktree-opened immediately after assigning the mount path so a provisioning escalation leaves an inspectable location in the journal
  • add focused unit/engine coverage and a real-tmux sandbox E2E for an ignored renderer surface reconstructed inside an isolated worktree

Reference: #433 (Phase 6H).

D-H1 render shield

The render shield is worktree-local and transient. It is added without consulting whether worktree/_bmad exists, so protection does not depend on provisioning order. The only suppression is structural: when /_bmad is already present in the exclude patterns, Git prunes that directory before descending, so a separate /_bmad/render/ line can never be consulted. Omitting that inert line keeps the private exclude precise.

Known gap

Wheel-provided MODULE_SKILLS still have no result-side completeness predicate. This remains explicit rather than being folded into the CRITICAL upstream-skill gate: story worktrees have a determinate dev/review consumer contract for upstream skills, but there is no equivalent required story-session consumer contract for the bundled operator/triage surface. Reusing the deterministic-stall gate would risk refusing healthy runs.

Validation

  • Python 3.13.13 and 3.14.6 ablation matrix: both lanes imported from their own disposable repository copy, collected the same six witnesses, and each paired test failed when its source guard was removed; after restoration both copies matched the original source checksum and passed 6/6
  • uv run pytest tests/test_install.py -q: 329 passed
  • uv run pytest tests/test_engine_worktree.py -q: 56 passed
  • uv run pytest tests/test_stories_e2e.py -q: 14 passed
  • the new stories sandbox E2E crosses the real tmux transport with a scripted fake CLI and consumes zero LLM tokens
  • earlier full suite on this diff: 4022 passed, 24 skipped, with the same four known local-only seeded-fork drift failures in .claude/skills and .agents/skills
  • uv run pyright: 0 errors, warnings, or information
  • trunk check --no-fix: clean
  • git diff --check: clean

Summary by CodeRabbit

  • New Features

    • Automatically provisions required project files, skills, renderer tools, and configuration in isolated worktrees.
    • Added validation for setup completeness before execution.
    • Added journaling for worktree creation, delivered seeds, and undelivered files.
  • Bug Fixes

    • Prevented incomplete environments from starting execution unexpectedly.
    • Prevented existing files from being overwritten during provisioning.
    • Protected provisioned files from accidental commits.
    • Improved renderer and story execution reliability in isolated sessions.
    • Preserved worktrees and recorded escalation details when required setup is missing.

@greptile-apps greptile-apps 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.

pbean has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@pbean, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 69c35359-2f66-4d04-9e82-c599298700f2

📥 Commits

Reviewing files that changed from the base of the PR and between 8f3c1c0 and f23810d.

📒 Files selected for processing (1)
  • tests/test_stories_engine.py

Walkthrough

Worktree provisioning now seeds BMAD content, renderer files, central configuration, and required skills. It verifies delivery, protects seeded paths, journals worktree events, and escalates incomplete required surfaces before adapter dispatch.

Changes

Worktree provisioning and isolated execution

Layer / File(s) Summary
BMAD seed provisioning and completeness
src/bmad_loop/worktree_flow.py, tests/test_install.py
Provisioning resolves required skills, seeds BMAD content without clobbering files, validates renderer and configuration delivery, and updates worktree exclusions.
Seed delivery verification
src/bmad_loop/worktree_flow.py, tests/test_install.py
Seed checks cover files, directories, globs, hook configurations, containment, symlinks, and partial delivery.
Execution journaling and escalation
src/bmad_loop/worktree_flow.py, tests/test_engine_worktree.py, tests/test_stories_engine.py, tests/test_stories_e2e.py
Execution deduplicates seeds, records worktree and delivery events, rechecks stories support, escalates missing required surfaces before adapter dispatch, and validates isolated renderer execution.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant WorktreeFlow
  participant Provisioning
  participant Journal
  participant AdapterSession
  WorktreeFlow->>Provisioning: create worktree and seed required surfaces
  Provisioning-->>WorktreeFlow: return completeness and delivery results
  WorktreeFlow->>Journal: record worktree-opened and undelivered seeds
  alt required support is incomplete
    WorktreeFlow->>Journal: record escalation
  else required support is complete
    WorktreeFlow->>AdapterSession: dispatch isolated story
  end
Loading

Possibly related issues

  • Issue 414 — The changes extend worktree path handling and seed completeness checks for BMAD, skills, and renderer content.

Possibly related PRs

Poem

A rabbit seeds the _bmad tree,
Checks each path with care and glee.
Missing skills pause the run,
Journals mark what was undone.
Complete worktrees hop to tmux.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 summarizes the main changes: seeding and verifying isolated BMAD surfaces in worktrees.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch port/phase-6h-seeding-escalations

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.

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/bmad_loop/worktree_flow.py (1)

814-856: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse escalate_unit for the two new escalation blocks.

Both blocks repeat the exact body of escalate_unit (lines 1036-1048): set Phase.ESCALATED, journal story-escalated, call gates.notify with the same title and resume suffix, _save, then _pause. Three copies of the same sequence will drift. escalate_unit already raises through _pause, so the call sites keep their control flow.

♻️ Proposed refactor
-            task.phase = Phase.ESCALATED
-            self.journal.append("story-escalated", story_key=task.story_key, reason=reason)
-            gates.notify(
-                self.policy,
-                self.run_dir,
-                f"CRITICAL escalation: {task.story_key}",
-                f"{reason} — resolve, then `bmad-loop resume {self.state.run_id}`",
-            )
-            self._save()
-            self._pause(reason, task.story_key)
+            self.escalate_unit(task, reason)  # always raises RunPaused

Apply the same replacement to the renderer-surface block.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/bmad_loop/worktree_flow.py` around lines 814 - 856, Replace the
duplicated escalation sequences in the absent_skills and short_surface blocks
with calls to the existing escalate_unit helper. Pass each block’s computed
reason and task.story_key so the helper preserves the existing phase update,
journaling, notification, save, and pause behavior, leaving the surrounding
detection logic unchanged.
tests/test_install.py (1)

6693-6708: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider the project fixture for the provision_worktree tests.

These tests call provision_worktree against a plain tmp_path directory that is not a git repository. The shield write then takes the silent skip arm of _worktree_local_exclude, so the exclude behavior is never exercised for the non-monkeypatched cases. The coding guidelines ask tests to use the conftest sandbox fixtures, especially project, instead of hand-rolled temporary repositories.

As per coding guidelines: "Use conftest sandbox fixtures, especially project, rather than hand-rolling temporary repositories or touching the template repository."

Also applies to: 6782-6796

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_install.py` around lines 6693 - 6708, Update the affected
provision_worktree tests, including
test_render_shield_is_omitted_when_root_shield_subsumes_it and the related case
near the referenced lines, to use the conftest project fixture instead of
constructing repositories with tmp_path and _write_worktree_renderer_surface.
Pass the fixture’s repository/worktree paths into provision_worktree while
preserving each test’s existing assertions and setup behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_stories_e2e.py`:
- Around line 679-683: The .gitignore updates must ensure appended patterns
start on a new line. In tests/test_stories_e2e.py lines 679-683, normalize the
existing text to end with a newline before appending BMAD_SCRIPTS_SEED_REL and
CENTRAL_CONFIG_REL; in tests/test_engine_worktree.py lines 194-199, update
ignore_before_commit to add a newline to existing only when it is non-empty and
lacks one.

---

Nitpick comments:
In `@src/bmad_loop/worktree_flow.py`:
- Around line 814-856: Replace the duplicated escalation sequences in the
absent_skills and short_surface blocks with calls to the existing escalate_unit
helper. Pass each block’s computed reason and task.story_key so the helper
preserves the existing phase update, journaling, notification, save, and pause
behavior, leaving the surrounding detection logic unchanged.

In `@tests/test_install.py`:
- Around line 6693-6708: Update the affected provision_worktree tests, including
test_render_shield_is_omitted_when_root_shield_subsumes_it and the related case
near the referenced lines, to use the conftest project fixture instead of
constructing repositories with tmp_path and _write_worktree_renderer_surface.
Pass the fixture’s repository/worktree paths into provision_worktree while
preserving each test’s existing assertions and setup behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 24796a27-45fc-4ca7-ade8-e26691fb736c

📥 Commits

Reviewing files that changed from the base of the PR and between f512288 and f8d5d15.

📒 Files selected for processing (4)
  • src/bmad_loop/worktree_flow.py
  • tests/test_engine_worktree.py
  • tests/test_install.py
  • tests/test_stories_e2e.py

Comment thread tests/test_stories_e2e.py

@greptile-apps greptile-apps 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.

pbean has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@pbean

pbean commented Aug 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: 3e0f8e59ac

ℹ️ 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/worktree_flow.py Outdated
Comment on lines +264 to +265
if contained(dst, worktree) and (_is_file(dst) or _is_dir(dst)):
continue

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 Inspect descendants before marking directory seeds delivered

When a seed_files or glob entry names a directory and provisioning copies at least one child but refuses another (for example, a child symlink resolving outside the repo), the destination directory now exists, so this condition marks the entire entry delivered. Consequently run_isolated emits no worktree-seed-dropped event even though the session is missing part of the requested config—the exact partial-copy case this new result-side check needs to expose.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in 0fb7c23. worktree_seed_undelivered now verifies destination type and containment for every usable source descendant, including directory visits, so a partial literal or glob directory seed is reported as worktree-seed-dropped. Added regression coverage for both seed_files and seed_globs; both witnesses failed on 3e0f8e5 and pass on the new head. Fresh CI is green.

Comment thread src/bmad_loop/worktree_flow.py Outdated
Comment on lines +151 to +155
dst_scripts = worktree.joinpath(*BMAD_SCRIPTS_SEED_REL.split("/"))
return any(
(_is_file(src) or _is_dir(src)) and not _is_file(dst_scripts.joinpath(*rel.split("/")))
for rel, src in _walk_traversable_files(scripts)
)

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 Limit renderer completeness to files the renderer requires

For a renderer-backed project, this walks every file under _bmad/scripts, not just the required renderer unit. If an unrelated script—or config_utils.py when render_skill.py no longer imports it—is symlinked outside the repo or otherwise cannot be copied, the required renderer entry/config can still be fully usable, but this returns true and run_isolated CRITICAL-escalates before dispatch. The check should follow the same content-keyed required-file predicate used by renderer preflight rather than treating every sibling script as mandatory.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in 0fb7c23. _bmad_scripts_seed_incomplete now checks only RENDERER_SCRIPT_UNIT_REL entries accepted by _renderer_unit_required, matching the preflight’s content-keyed contract. Added regression coverage for an unused config_utils.py and an unrelated sibling script; both witnesses failed on 3e0f8e5 and pass on the new head. Fresh CI is green.

@greptile-apps greptile-apps 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.

pbean has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@pbean

pbean commented Aug 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: 0fb7c231ac

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

def _required_worktree_skills(repo_root: Path, tree: str) -> tuple[str, ...]:
"""Every upstream skill the dev/review sessions in ``tree`` may invoke."""
resolved = resolve_review_layers(repo_root, tree)
return tuple(dict.fromkeys((*BASE_SKILLS, *(resolved.skills() if resolved else ()))))

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 Restrict the fatal gate to active review skills

Because BASE_SKILLS is explicitly a copy-if-present superset, including obsolete standalone reviewers and the merged reviewer, returning all of it here also feeds those inactive skills into base_skills_seed_incomplete and the fatal pre-dispatch gate. For example, a modern project whose resolved layers invoke only bmad-review but retain an old bmad-review-edge-case-hunter symlink to a shared install will pass preflight, fail to copy only that unused skill, and then be escalated even though the session never invokes it. Keep the broad set for best-effort copying, but construct the fatal completeness set from the resolved primitive and actually required review layers rather than every present catalog entry.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in e263866. Provisioning now uses the broad BASE_SKILLS plus resolved required/advisory set only for best-effort copying, while base_skills_seed_incomplete gates the selected primitive plus resolved.required. Unknown resolution mirrors missing_base_skills exactly: a present merged reviewer is required, otherwise the standalone fallback reviewers are required. Added modern obsolete-symlink, advisory-copy/nonfatal, and merged/standalone fallback regressions; the affected witnesses failed on 0fb7c23 and pass on the new head. Fresh CI run 30850459542 is green across Linux and Windows.

@greptile-apps greptile-apps 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.

pbean has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_install.py`:
- Around line 6751-6771: Add the existing POSIX/symlink skip marker before
test_base_skills_seed_incomplete_ignores_inactive_catalog_symlink, and apply the
same marker to
test_base_skills_seed_incomplete_preserves_unknown_review_fallback, so both
symlink-dependent catalogue tests are skipped on Windows while retaining their
current behavior on supported platforms.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 451bf4ec-6840-43ea-8688-019c13aaea3f

📥 Commits

Reviewing files that changed from the base of the PR and between f8d5d15 and e263866.

📒 Files selected for processing (4)
  • src/bmad_loop/worktree_flow.py
  • tests/test_engine_worktree.py
  • tests/test_install.py
  • tests/test_stories_e2e.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/test_stories_e2e.py
  • tests/test_engine_worktree.py
  • src/bmad_loop/worktree_flow.py

Comment thread tests/test_install.py
@pbean

pbean commented Aug 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: e263866d8e

ℹ️ 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/worktree_flow.py Outdated
Comment on lines +192 to +193
if (_is_file(src) or _is_dir(src))
and not _is_file(worktree_skill.joinpath(*rel.split("/")))

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 Gate only files the active skill actually consumes

When an otherwise required skill contains an unreferenced auxiliary file or symlink that provisioning cannot copy—for example, a README symlinked to a shared install—this predicate marks the skill incomplete and run_isolated CRITICAL-pauses before dispatch. missing_base_skills only makes the review skill's SKILL.md and the primitive's defined markers and renderer sources mandatory, so absence of an unrelated descendant does not prove the session will stall; restrict the fatal completeness check to that same required-file contract while leaving other descendants best-effort.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in 8f3c1c0. base_skills_seed_incomplete now gates only the active contract: SKILL.md for the selected primitive and required reviewers, plus defined primitive markers and renderer snapshot sources. Unreferenced descendants remain best-effort. Stories mode separately re-runs missing_stories_support against the mounted worktree so missing or stale folder+id routers still pause. Added regressions for unreferenced auxiliary symlinks and required marker/snapshot omissions. Clean full suite: 4036 passed, 30 skipped.

Comment on lines +268 to +269
if _is_file(src):
return _is_file(dst)

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 Treat escaped seed sources as undelivered

When a seed points through an out-of-repo symlink but the worktree already contains a file at that path, provisioning refuses the escaped source, yet this arm reports delivery solely because the destination is a file. For example, a tracked stale config in the worktree suppresses worktree-seed-dropped even though the main checkout's current shared config was never copied, so the session silently uses different configuration; reject escaped sources before accepting destination existence.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in 8f3c1c0. Delivery now rejects a top-level source outside repo_root before accepting any stale destination, and recursive directory verification applies the same containment rule to every visited file and directory. Regressions cover a stale top-level destination plus nested escaped file and directory sources. Clean full suite: 4036 passed, 30 skipped.

Comment thread src/bmad_loop/worktree_flow.py Outdated
Comment on lines +490 to +491
if seeded_bmad:
skipped = [rel for rel in skipped if not _is_under_bmad(rel)]

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 Preserve unrelated _bmad no-op seed reports

When internal BMAD seeding copies any file, this removes every skipped user-authored seed beneath _bmad, even if the copied file is unrelated. For example, a tracked _bmad/config.toml seed is a genuine no-op, but if ignored _bmad/scripts files are seeded afterward its entry disappears and run_isolated emits no worktree-seed-skipped event; because the internal no-clobber copy cannot have filled an already occupied skipped entry, retain these reports and remove only the reserved internal sentinels handled immediately below.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in 8f3c1c0. The broad _bmad skipped-entry filter was removed; provisioning now suppresses only the reserved renderer sentinels handled by the dedicated result checks. The regression confirms an unrelated user-seed no-op remains reported even when internal BMAD seeding successfully lands a sibling. Clean full suite: 4036 passed, 30 skipped.

@greptile-apps greptile-apps 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.

pbean has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@pbean

pbean commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

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

🧹 Nitpick comments (1)
tests/test_stories_engine.py (1)

1109-1111: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Pin the per-parameter finding to keep the two branches distinguishable.

STORIES_PROBE_FILE appears in the pause reason for both missing and stale. The assertion therefore passes even if the two shapes collapse into one finding, which is the exact distinction this parametrization exists to hold. Assert the stale marker fragment in the stale branch.

Also confirm the negative assertion adapter.sessions == [] fails when the stories gate is removed, as the guidelines require for refusal tests.

♻️ Proposed change to pin each finding shape
     assert summary.paused and adapter.sessions == []
-    assert STORIES_PROBE_FILE in (engine.state.paused_reason or "")
+    reason = engine.state.paused_reason or ""
+    assert STORIES_PROBE_FILE in reason
+    # the tracked-but-stale worktree copy is reported by MARKER, the untracked one
+    # by absence — a collapse of the two shapes must not pass this test.
+    assert (STORIES_PROBE_TEXT in reason) is (checkout_probe == "stale")
     assert Path(engine.state.tasks["1"].worktree_path).is_dir()

As per coding guidelines: "For tests asserting that something is refused or absent, remove the gating code and verify the test fails before trusting the negative assertion."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_stories_engine.py` around lines 1109 - 1111, The parametrized
pause-reason test must distinguish the missing and stale branches instead of
asserting only the shared STORIES_PROBE_FILE marker. Update the stale case
around the paused-reason assertions to require its stale-specific marker, while
preserving the missing-case expectation; additionally verify the refusal
assertion adapter.sessions == [] is meaningful by removing the stories gate and
confirming that the test fails without it.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/test_stories_engine.py`:
- Around line 1109-1111: The parametrized pause-reason test must distinguish the
missing and stale branches instead of asserting only the shared
STORIES_PROBE_FILE marker. Update the stale case around the paused-reason
assertions to require its stale-specific marker, while preserving the
missing-case expectation; additionally verify the refusal assertion
adapter.sessions == [] is meaningful by removing the stories gate and confirming
that the test fails without it.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b0987e9e-59e6-4692-98bb-c6a3a9683066

📥 Commits

Reviewing files that changed from the base of the PR and between e263866 and 8f3c1c0.

📒 Files selected for processing (3)
  • src/bmad_loop/worktree_flow.py
  • tests/test_install.py
  • tests/test_stories_engine.py

@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: 8f3c1c0982

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

@greptile-apps greptile-apps 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.

pbean has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@pbean
pbean merged commit f7e17e4 into main Aug 3, 2026
10 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