Implements the plan from the carpenter walkthrough audit: make the
project flow -> final review -> PDF path measurable and safe to gate
CI on.
- projectHydrationService loads a project's geometry/labor/materials/
rentals/packages/calculation in parallel and reports per-resource
timing plus the slowest resource, so hydration SLA breaches are
visible instead of silent
- projectReadiness centralizes the blocking checks final review must
pass before a quote can be sent (name, customer, description,
materials/labor present, zero-price lines)
- pdfSourceSignature detects when a generated PDF is stale relative to
the current project data, so a carpenter doesn't send an outdated
quote
- MaterialLinkReview + new customer-projects match-preview/link
endpoints let a user review and confirm suggested master-material
matches instead of silently auto-linking
- ProjectFlow refactored around the new hydration/readiness utilities;
FinalReview surfaces readiness checks and unlinked material counts
- CI: the carpenter smoke test (full-roof-quote-flow.spec.js) is now
a blocking gate on main, with the rest of the Playwright suite
running best-effort alongside it
- docs/qa/CARPENTER_WALKTHROUGH_RELEASE_GATE.md documents the gate and
the monthly production audit procedure
Co-Authored-By: Claude Sonnet 5 <[email protected]>
The last CI run failed only because GitHub artifact storage quota was
exhausted: backend tests and frontend build were green but their
upload-artifact steps failed the jobs.
- Mark all artifact uploads continue-on-error and cut retention to 3
days (deploy workflows kept artifacts up to 30 days, which is what
filled the quota)
- E2E job builds the frontend itself instead of downloading the
frontend-build artifact, so it no longer depends on artifact storage
- Bump actions/checkout v4->v7, setup-node v4->v6, upload-artifact
v4->v7, download-artifact v4->v8 (Node 20 runtime deprecation) and
CI Node 18 (EOL) -> 22 to match production
- Fix all frontend lint warnings: remove unused imports/state and the
dead Stepper-based form UI in SmartPackageForm (renderStepContent,
parseAndAddMaterialsFromDescription were unreferenced), disable
exhaustive-deps where the effect is intentionally scoped