diff --git a/.claude/agent-memory/backend-developer/MEMORY.md b/.claude/agent-memory/backend-developer/MEMORY.md index f20bfabaa..9a980c22a 100644 --- a/.claude/agent-memory/backend-developer/MEMORY.md +++ b/.claude/agent-memory/backend-developer/MEMORY.md @@ -193,12 +193,13 @@ Key files added/modified: - `server/src/errors/AppError.ts` — added CircularDependencyError (409) CPM Dependency Math (ADR-014): -| Type | Forward ES | Backward LF | -|------|-----------|-------------| -| FS | PredEF + LL | SucLS - LL | -| SS | PredES + LL | (SucLS - LL) + predDur | -| FF | (PredEF + LL) - succDur | SucLF - LL | -| SF | (PredES + LL) - succDur | (SucLF - LL) + predDur | + +| Type | Forward ES | Backward LF | +| ---- | ----------------------- | ---------------------- | +| FS | PredEF + LL | SucLS - LL | +| SS | PredES + LL | (SucLS - LL) + predDur | +| FF | (PredEF + LL) - succDur | SucLF - LL | +| SF | (PredES + LL) - succDur | (SucLF - LL) + predDur | Engine is a pure function with injectable `today` parameter for testability. Cascade mode uses BFS from anchor to collect all downstream successors. diff --git a/.claude/agent-memory/e2e-test-engineer/MEMORY.md b/.claude/agent-memory/e2e-test-engineer/MEMORY.md index fa5b9e16c..501de0af1 100644 --- a/.claude/agent-memory/e2e-test-engineer/MEMORY.md +++ b/.claude/agent-memory/e2e-test-engineer/MEMORY.md @@ -4,7 +4,7 @@ ## Topic files -- [general-e2e-patterns.md](general-e2e-patterns.md) — cross-cutting waits/timing, viewport timeouts, strict-mode anti-patterns, DataTable migration fallout, Gantt touch, breadcrumbs, print, dashboard cards, key file locations. +- [general-e2e-patterns.md](general-e2e-patterns.md) — cross-cutting waits/timing, viewport timeouts, strict-mode anti-patterns, DataTable migration fallout, Gantt touch, breadcrumbs, print, dashboard cards, headless-shell PDF-iframe limitation → CSP header+console verification pattern (blob-fetch leg removed, connect-src pitfall), key file locations. - [e2e-pom-patterns.md](e2e-pom-patterns.md) — Page Object Model conventions and stable-locator strategies. - [e2e-parallel-isolation.md](e2e-parallel-isolation.md) — `testPrefix` fixture, parallel-safe data isolation, serial-mode tests. - [known-flakes-and-regressions.md](known-flakes-and-regressions.md) — triaged log of flaky tests, pre-existing CI failures, and production regressions caught by E2E. **Check this before re-triaging a failure.** @@ -23,8 +23,11 @@ - [story-1876-deposit-refunds.md](story-1876-deposit-refunds.md) — deposit `entryType` refunds; DataTable hidden-column read pattern (`getColumnCellText`), table+card dual-DOM visible-filter pitfall. - [story-1877-contact-fields-attachment-typing.md](story-1877-contact-fields-attachment-typing.md) — budget-source contact fields, household settings singleton (needs `mode:'serial'`, not just try/finally), document-link attachment typing; route-mock last-registered-runs-first ordering hazard; sandbox lint/tsc caveats. - [story-1879-report-wizard.md](story-1879-report-wizard.md) — Bank Report Wizard POM/spec; Blocker bug #1886 (budgetSources envelope crash blocks all progress past step 1) + compile errors/missing i18n keys found via `tsc`; source-report E2E seeding pattern (WI budget → invoice-budget-line link). +- [story-1891-wizard-followup.md](story-1891-wizard-followup.md) — expandable invoice rows, CSP `blob:` frame-src hardened preview check (SUPERSEDED TWICE — `page.frames()` proof, then in-page blob fetch → now header+console-only, see general-e2e-patterns.md), deposit budget-source tagging; 2 filed bugs (#1892 full-exclusion display, #1893 missing deposit-default heuristic); sandbox CAN now build+boot the full container stack (see `sandbox-live-verification.md`) but browser binary download is still network-policy-blocked. +- [sandbox-live-verification.md](sandbox-live-verification.md) — **dhi.io build access is sandbox-dependent, re-check each session**: this session successfully built `cornerstone:e2e` and booted the full container stack (app+OIDC+proxy all healthy), a first — but Playwright's own browser binary download (`playwright.download.prss.microsoft.com`/`cdn.playwright.dev`) is blocked by network policy, and Ubuntu's `chromium-browser` apt package is a non-functional snap stub (no snapd) — no way found yet to get an actual live browser run in this sandbox class. ## Open follow-ups to flag to orchestrator - No Paperless-ngx testcontainer exists yet (story-epic08-e2e.md) — all Paperless E2E coverage is `page.route()` mocked, not real integration. Add the container when Paperless work resumes. -- Full containerized E2E verification is not possible in sandboxes without `dhi.io` (Docker Hardened Images) registry credentials — building `cornerstone:e2e` fails with `401 Unauthorized`. This is an environment limitation, not a code issue; verification in such sandboxes must fall back to static checks (lint/prettier/tsc-diff/`playwright --list`) plus post-merge CI observation. +- **Filed bugs from Story #1891, unresolved**: #1892 (fully-excluding all budget lines on an invoice removes it from the report wizard's step-3 list instead of showing €0.00 — display-only, PDF/claim unaffected) and #1893 (deposit budget-source auto-default 0/1/>1-source heuristic is entirely unimplemented — `InvoiceDepositsSection.tsx` never receives the invoice's budget lines). +- Containerized E2E verification capability varies by sandbox instance — **do not assume the old "no dhi.io creds" note still applies**; re-attempt `docker build -t cornerstone:e2e .` each session before falling back to static-only verification. See `sandbox-live-verification.md` for the current state and the remaining browser-binary blocker. diff --git a/.claude/agent-memory/e2e-test-engineer/general-e2e-patterns.md b/.claude/agent-memory/e2e-test-engineer/general-e2e-patterns.md index 227c2e146..1da173d16 100644 --- a/.claude/agent-memory/e2e-test-engineer/general-e2e-patterns.md +++ b/.claude/agent-memory/e2e-test-engineer/general-e2e-patterns.md @@ -18,6 +18,7 @@ metadata: - After `fill(query)` in a search box, add `page.waitForURL(url => url.searchParams.get('q') === query)` BEFORE `waitForResponse` — confirms the debounce fired and React committed state. Don't call `waitForLoaded()` after the response for search — it can resolve on stale DOM from a WebKit clear-event race; let the assertion's own retry converge. - Dashboard reload: register `waitForResponse('/api/users/me/preferences')` BEFORE reload, but prefer `page.waitForLoadState('networkidle')` AFTER the heading is visible for "dismissed card stays hidden" — LocaleContext's GET resolves first and `usePreferences`'s second GET (which applies hiddenCards) arrives later. - Count assertions with parallel workers sharing one DB are fragile — use `>=` / `not.toContain(name)` instead of exact equality. +- **One-shot `page.frames().find(...)` (or any raw one-shot read of live browsing-context state) right after a "done" signal (overlay hidden, attribute set) is a race, not a proof.** `frame.url()` only reflects a navigation that has already completed — there's a real gap between the DOM signaling "done" and the nested browsing context actually finishing navigation. Wrap it in `await expect(async () => {...}).toPass({timeout: N})`, re-deriving the expected value on every retry (don't capture it once before the poll — a value that can legitimately change mid-wait, e.g. a regenerated blob URL, needs re-reading each attempt). Found via CI PR #1894 (`ReportWizardPage.assertFrameActuallyNavigated`) — see story-1891-wizard-followup.md for the full writeup and the "zero console messages alongside the failure" diagnostic that proved it was a timing race, not the CSP guard it was built to detect. ## Viewport timeouts (Playwright projects) @@ -94,6 +95,63 @@ After `setLanguage(page,'de')` + `page.goto()`, always `page.reload()` before as AreaPicker has two DOM states: unselected (input visible, `placeholder="Select an area"`) vs selected (`[class*="selectedDisplay"]` visible, input gone). After selection, URL gets `?areaId=`; clearing removes it. Use `waitForResponse` BEFORE selection. +## Headless Chromium shell has no PDF viewer plugin — `