Skip to content

Fix PMO UI white-screen on load + Windows-broken Playwright utils - #112

Merged
DaveGerson merged 14 commits into
masterfrom
fix/pmo-white-screen-and-e2e-paths
Jul 7, 2026
Merged

Fix PMO UI white-screen on load + Windows-broken Playwright utils#112
DaveGerson merged 14 commits into
masterfrom
fix/pmo-white-screen-and-e2e-paths

Conversation

@DaveGerson

Copy link
Copy Markdown
Owner

Summary

Found while running the e2e sweep after the PR #109 landing:

  • bd-091 (P1): SpecsPanel crashed the entire PMO UI at mount — blank page at /pmo/. The spec-queue router owns GET /api/v1/pmo/specs and returns a bare list[SpecDraftResponse], but the panel expected {specs: [...]}; the resulting undefined.find threw during render with no error boundary. Fixed with defensive shape coercion + regression tests (both shapes).
  • bd-b6f (P2): Playwright e2e utils resolved output dirs via new URL(...).pathnameC:\C:\… on Windows, killing the whole suite at import. Fixed with fileURLToPath.

Still open: bd-m0b — specs goto('/') escapes the /pmo/ baseURL path, so the Playwright suite (936/939 failing, not in CI) needs a navigation fix before it's meaningful.

Verification

  • vitest 12/12 (2 new regression tests)
  • Headless probe against live baton serve: board renders fully (brand visible, zero page errors) vs. blank page before.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VMHTtWVqejqqnSQFGXsnLL

DaveGerson and others added 14 commits July 6, 2026 12:27
… recursion, policy visibility (bd-6z9)

- audit_coverage_requirement now matches pack:* presets risk-gated to HIGH/CRITICAL
- single recursive sub_team collector shared by coverage and mismatch checks
- headless audit_missing defect made actionable (outcome parity with interactive path)
- policy validation failures logged + surfaced in score_warnings instead of swallowed
- _IMPLEMENT_PHASE_KEYS derived from phase_roles.IMPLEMENT_PHASE_NAMES (adds draft)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkNUh7JHsR4yJ6KTEhNmbm
…bd-5mq)

- _upsert_plan: INSERT OR REPLACE -> ON CONFLICT(task_id) DO UPDATE excluding release_id
- legacy JSON->SQLite migrator binds all plan columns instead of 10

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkNUh7JHsR4yJ6KTEhNmbm
…trict-backend errors (bd-85c)

- resume() saves execution state after the resolver loop, mirroring siblings
- _audit_step_agents returns first EXISTING dir's audit, not first dir with problems
- execute CLI maps UnknownTeamBackendError to a clean user error (no traceback)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkNUh7JHsR4yJ6KTEhNmbm
- active-task sqlite probe resolves BATON_DB_PATH first, matching bead_cmd precedence
- planner_validation details carry plan_selection (active-task vs fallback-first-found)
  with a human-readable caveat when validating a fallback guess

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkNUh7JHsR4yJ6KTEhNmbm
…up missing roots (bd-j9f)

- per-pack OSError isolation mirroring the registry guard from 129bac4
- +.md stem fallback no longer satisfies declarations with known non-md extensions
- repeated --knowledge-root paths yield a single missing-root issue

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkNUh7JHsR4yJ6KTEhNmbm
…c40)

Matches forge_plan/forge_regenerate: PlanQualityError -> 422 via
plan_quality_error_detail before the generic 500 fallback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkNUh7JHsR4yJ6KTEhNmbm
…2hs)

Mirrors next_actions()' diff-based conditional save: the post-loop save in
start() existed only to persist team_readiness mutations from the resolver
loop, so skip it when nothing changed. Restores the OCC contract of one
version bump per start (test_occ_start_after_plan_save expects version 2);
team plans still persist readiness diagnostics (covered by existing
test_team_report_written_with_readiness_diagnostics, verified to fail if
the save is removed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkNUh7JHsR4yJ6KTEhNmbm
…knowledge doctor hardening (bd-ftd)

- api-reference: 422 plan_quality_error rows for all three forge routes
  (forge/plan and forge/regenerate were never documented after 3e67452)
  plus a shared Plan Quality Errors subsection with the detail shape
- cli-reference: new Diagnostics section for baton doctor (previously
  undocumented) incl. plan_selection semantics and BATON_DB_PATH; knowledge
  doctor unreadable-pack, non-.md shadow rule, --knowledge-root de-dup
- doc-audit: append 2026-07-06 sync entry

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkNUh7JHsR4yJ6KTEhNmbm
…bt clearance

Resolves sqlite_backend.py as the union of manager-mode (manager_mode
column) and the fix wave's ON CONFLICT(task_id) DO UPDATE upsert that
preserves release_id; extends migrate.py's legacy plans INSERT with
manager_mode for parity. doc-audit.md keeps both appended entries.

Storage/release/manager suites green post-merge (71+82+9+150).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkNUh7JHsR4yJ6KTEhNmbm
FallbackClassifier's talent-agent probe constructs HeadlessClaude during
classification regardless of BATON_PLAN_REVIEW, colliding with these
tests' HeadlessClaude mocks. Pin task_classifier=KeywordClassifier(),
matching the pattern documented in tests/e2e/test_manager_mode_planning.py.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkNUh7JHsR4yJ6KTEhNmbm
… just injection (bd-pz4 part 1)

The classified_phases Review/Audit guarantee fired only when RiskStage
itself injected a safety agent; a pre-rostered reviewer/auditor produced
no phase slot, force-landed in Implement, and was filtered — tripping the
review_missing/audit_missing gates. Mirror the gate's own presence
predicate (REVIEWER_AGENTS from router, same source as validation.py).
compliance-audit golden regenerated: auditor now lands in a proper Audit
phase instead of leaving a vestigial single-member team step.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkNUh7JHsR4yJ6KTEhNmbm
… part 2)

The explicit-complexity path built phases via KeywordClassifier._select_phases
(strips Review at medium) but kept the static DEFAULT_AGENTS roster (includes
code-reviewer), producing reviewer-on-roster/no-Review-phase plans that the
review_missing gate correctly hard-blocks. Filter reviewer-class agents
(keeping auditor) from draft.resolved_agents when the override phase list has
no Review phase — condition is phase-presence-driven, so heavy complexity
keeps both. Gate, enrichment net, and fan-out guard untouched.

Fixes both tests/e2e/test_manager_mode_planning.py failures; e2e 18/18.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WkNUh7JHsR4yJ6KTEhNmbm
… bd-b6f)

Two bugs found while standing up the pmo-ui e2e suite:

- SpecsPanel white-screened the ENTIRE app at mount: GET /api/v1/pmo/specs
  is owned by the spec-queue router and returns a bare
  list[SpecDraftResponse], but loadSpecs did setSpecs(res.specs) —
  undefined — and the next render's specs.find threw with no error
  boundary above, leaving #root empty at /pmo/. Coerce the response
  shape defensively; regression test covers both shapes. The deeper
  product question (SpecsPanel's Spec entity has no backing endpoint)
  stays open in bd-091's notes; suite-wide goto('/') baseURL bug is
  tracked separately in bd-m0b.

- e2e/utils/{screenshots,audit-reporter}.ts resolved their output dirs
  via new URL(...).pathname, which on Windows yields "/C:/…" and
  path.resolve mangles it into "C:\C:\…" — mkdirSync threw at import
  time and killed the whole Playwright run. Use fileURLToPath.

Verified: vitest 12/12 (2 new); rebuilt dist; headless probe against
live `baton serve` now renders the full board (brand visible,
rootLen 165958, zero page errors) where it previously rendered a
blank page.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VMHTtWVqejqqnSQFGXsnLL
@DaveGerson
DaveGerson merged commit 09f8098 into master Jul 7, 2026
1 check passed
@DaveGerson
DaveGerson deleted the fix/pmo-white-screen-and-e2e-paths branch July 7, 2026 01:02
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