Publish Docs / publish-docs (push) Successful in 1m10sDetails
Mark Stage 3B (list efficiency improvements) as complete with 294 tests passing. Update baseline commit reference, test count, and next recommended branch to Stage 4A (Android app shell).
Add compact/standard view toggle (ListDensity enum) to controller and page, allowing users to switch between a dense single-row layout and the full metadata card view.
Add staleness detection: isStale() flags products not modified in 30+ days with a schedule icon; staleCount() returns the count of stale items in the current filtered view.
Add keyboard navigation: selectNextDraft/selectPreviousDraft with arrow-key wrapping support; page wires up Focus + onKeyEvent for arrow-down/arrow-up.
Update ProductDraftCard with compact layout variant (two-row dense metadata), stale indicator icon, and description snippet in standard mode. Wrap long text in Flexible widgets to prevent overflow.
Increase standard card height from 160px to 180px to accommodate the new description snippet row.
Export ListDensity and ProductSortField from barrel file.
Add 42 new focused tests covering listDensity toggle, staleness boundary conditions, staleCount with filters, keyboard navigation wrapping, and compact card rendering. All 294 tests pass, dart analyze clean.
Validate Docs / validate-docs (push) Successful in 1m4sDetails
Add _refreshSelection() to ProductPublishingController to preserve and refresh selectedDraft by id after all write-triggered reloads. Selection stays on the same product with latest data, or auto-selects first visible item if the original leaves the active filter.
- 11 new post-write consistency tests (234 total)
- dart analyze clean
Publish Docs / publish-docs (push) Successful in 1m5sDetails
Reviewed-on: #2
## publishDraft Implementation Review
### 1. Cleanup Suggestions
**None.** After thorough review:
- **Production code** (39 lines total): Clean, minimal, correct. The `publish_status.dart` import is used by `updateProductStatus`. No dead code, no unused imports. `flutter analyze` reports zero issues.
- **Test code**: The `publishDraft` and `updateProductStatus` groups each have their own local JSON builder helper. The slight duplication is intentional — each is scoped to its group with the right defaults. No cleanup needed.
- **Static analysis**: Both `feature_wordpress` and `kell_web` pass `flutter analyze` with zero issues.
- **Dashboard test stub** (`_StubProductPublishingRepository.publishDraft` still throws `UnimplementedError`): Correct — the dashboard never calls `publishDraft`, so the stub is never exercised. No change needed.
### 2. Test Gaps Worth Adding (optional, not blocking)
| Gap | Priority | Rationale |
|-----|----------|-----------|
| `publishDraft` with 404 (product not found) | Low | Already covered implicitly by `WooCommerceApiClient.updateProduct` error handling, but an explicit 404 test would document the "missing product" scenario |
| `publishDraft` verifies auth header is present | Low | Auth is tested at the `WooCommerceApiClient` level already; adding it here would be redundant |
| `publishDraft` on already-published product (idempotency) | Low | Tests WooCommerce behavior, not our code |
None of these are blocking.
### 3. PR Readiness
**✅ Ready for merge.**
Evidence:
- `flutter analyze` — 0 issues on both packages
- `flutter test` — 99 pass (feature_wordpress), 24 pass (kell_web)
- 2 files changed, ~15 lines of net production code
- No architectural changes, no composition changes, no credential exposure
- Strict package boundaries preserved
- Runtime config via `--dart-define` unchanged