30 KiB
Implementation Status
Last updated: 2026-09-11
Resume Here
Before changing code, read this document, AGENTS.md, and the linked source-of-truth documentation. Then confirm the current baseline with:
npm test
For persistence or Redis-backed changes, also run the isolated integration suite after setting TEST_DATABASE_URL to the *_test database and TEST_REDIS_URL to the test Redis instance:
TEST_DATABASE_URL='postgresql://...' TEST_REDIS_URL='redis://...' npm run test:integration
The current local container runtime is OrbStack. If Docker commands point at a stale host, run:
unset DOCKER_HOST
docker context use orbstack
Completed
Workspace And Database
- Npm workspace with the API and shared contracts/validation packages.
- PostgreSQL Compose service on local port
5433; API port3000is registered in.local/project-ports.json. - Redis Compose service on local port
6380supports distributed login throttling. - Drizzle schema and migrations:
0000_core_inventory: users, sellers, categories, condition profiles, conditions, products, and physical inventory items.0001_auth_sessions: hashed server-side sessions, expiry, revocation, IP address, and user agent.0002_session_csrf_tokens: session-bound hashed CSRF tokens.0003_security_audit_events: private append-only authentication security events.0004_password_reset_tokens: hashed, one-time password recovery tokens.0005_mfa_methods: protected TOTP method records and lifecycle state.0006_listings: listing records and lifecycle enum.0007_listing_image_count: persisted image prerequisite for publication.0008_inventory_images: item-owned image metadata and processing state.0009_remove_listing_image_count: publication no longer stores a listing-level image snapshot.
- Isolated integration tests require a database name ending in
_testand truncate only that database's tables.- Local-only
npm run provision:admincreates the first Admin User and linked Seller atomically. It requiresINITIAL_ADMIN_EMAIL,INITIAL_ADMIN_PASSWORD, andINITIAL_SELLER_NAME, hashes the password with scrypt, and refuses once any User exists.
- Local-only
Domain And Persistence
- Product identity requires name, category, and seller.
- Products receive seller-scoped, normalized slugs; duplicate names receive a numeric suffix.
- Each Inventory Item is a separate physical copy.
- Inventory condition must belong to the Product category.
- Inventory lifecycle supports
ACTIVE,SOLD, andARCHIVED; sold and archived items are locked against ordinary edits. - Repositories for products, inventory items, conditions, users, and sessions use Drizzle/PostgreSQL.
- Listing persistence supports draft creation, seller-scoped lookup, status updates, and inventory-item history.
API And Authentication
- Fastify app bootstrap and
GET /healthresponse. - Admin Product endpoints:
GET /api/v1/admin/productsPOST /api/v1/admin/products
- Admin Inventory endpoint:
POST /api/v1/admin/inventory
- Authentication endpoints:
POST /api/v1/auth/loginPOST /api/v1/auth/logoutGET /api/v1/auth/me
- Login uses asynchronous scrypt password verification. Session tokens are random, stored only as SHA-256 hashes, and never returned in JSON.
- Session cookie settings are
HttpOnly,SameSite=Strict, path/, andSecurein production. - Login is limited to five attempts per client IP every 15 minutes and returns
429 AUTH_RATE_LIMITEDwithRetry-Afteronce exhausted. Redis atomically coordinates the limit across API processes. - Login sets a separate same-site CSRF cookie. Authenticated state-changing routes require its matching
x-csrf-tokenheader, validated against the session-bound hash. GET /api/v1/auth/sessionsreturns safe metadata for the current user's active sessions and marks the current session.DELETE /api/v1/auth/sessions/:idrevokes an owned session;DELETE /api/v1/auth/sessionsrevokes all other sessions while retaining the current one. Revoking the current session clears both cookies.- Active sessions renew
last_activity_atafter five minutes, avoiding a database write on every authenticated request. - Authentication events are retained separately from inventory activity.
LOGIN_SUCCESS,LOGIN_FAILURE,SESSION_CREATED, andSESSION_REVOKEDinclude the known actor where available, plus safe request context. Passwords and session/CSRF tokens or hashes are never recorded. - Password recovery uses generic
POST /api/v1/auth/forgot-passwordresponses to prevent account enumeration. Opaque tokens are delivered only through the SMTP adapter, stored only as hashes, expire after one hour, are consumed once, and revoke existing sessions after a password reset. - API startup requires
SMTP_URL,SMTP_FROM, andPASSWORD_RESET_URL; configure these local values before starting the server. - Existing admin routes validate the authenticated session and derive seller ownership server-side.
- Request schemas live in
packages/validation; admin response DTOs live inpackages/contracts. - MFA enrollment, verification, disable, protected secret handling, login verification, and audit events are implemented.
- Admin listing creation and lifecycle routes are implemented:
POST /api/v1/admin/listingsGET /api/v1/admin/listingsGET /api/v1/admin/listings/:idPOST /api/v1/admin/listings/:id/publishPOST /api/v1/admin/listings/:id/unpublishPOST /api/v1/admin/listings/:id/pendingPOST /api/v1/admin/listings/:id/archive
- Listing publication is seller-scoped, CSRF-protected, and gated by persisted identity, price, physical inventory, condition, and image prerequisites.
- Listing publication rejects physical inventory in
SOLDorARCHIVEDstatus with a conflict response. - Listing reads are seller-scoped and return only admin listing DTO fields.
- Item-owned image metadata can be added through a seller-scoped, CSRF-protected admin route; publication uses the persisted image count.
- Public search is available at
GET /api/v1/public/searchthrough a normalized SearchService boundary with pagination, price filters, text matching, and sold-item visibility controls. - Public search also supports active category and condition lookup options, URL-backed filters, and allowlisted recent/price sorting.
- Public search responses include
itemspluspaginationmetadata (page,limit,total, andtotalPages); pending listings are visible by default and sold listings require an explicit filter. - Public product pages are available at
GET /api/v1/public/products/:slug; responses use a public DTO and require an active physical item with an available or pending listing. - Public listing collection and detail reads are available at
GET /api/v1/public/listingsandGET /api/v1/public/listings/:id; collection responses include pagination metadata and detail reads hide internal inventory identity. - Public listing detail responses include safe condition labels, latest market value, and public image URLs; unavailable image states are rendered accessibly in the gallery.
- Public listing and product detail responses and pages now surface the seller's display name and configured public contact methods (email/phone) from seller settings, covering the contact-method portion of the documented public detail requirement.
- Public inventory collection and detail reads are available at
GET /api/v1/public/inventoryandGET /api/v1/public/inventory/:id; responses join only active physical items to available or pending listings and exclude private item notes. - The public seller directory is available at
GET /api/v1/public/sellers; it returns only sellers with visible inventory and exposes display identity without user or contact fields. - The web workspace now has a Vue/Vite public catalog shell with Vue Router, a catalog API service, search composable, loading/error/empty states, and responsive search-first styling.
- The web catalog now provides keyboard-accessible listing cards with stable
/listings/:idlinks, a public listing detail page, and service-level detail loading/error handling. - Catalog search and pagination are synchronized to the browser URL (
qandpage) with accessible previous/next controls; the web port5173is declared in the project port registry. - The web catalog includes a stable
/products/:slugproduct detail route with API-backed loading, not-found/error states, and semantic product facts. - The visual design foundation is centralized in web tokens with light/dark/system runtime theme support; the fixture composition has moved to Storybook at port
6006with the accessibility addon and component stories for available, pending, and sold states. ImageStorage, traversal-safe local storage, multipart upload transport, binary signature validation, and worker-backed derivative processing are implemented.- Derivative orchestration now defines thumbnail, medium, and large WebP storage outputs behind an injected renderer; the concrete worker-backed renderer remains.
- The worker owns an image derivative job runner with explicit processing, completion, and failure outcomes backed by persistent PostgreSQL job records.
- Image metadata limits are enforced in the service boundary: supported MIME types, 10 MiB default file size, and 10,000-pixel maximum dimensions.
- Acquisition, sales, dashboard, pricing observations, market valuations, audited sale voiding, and manual market-value overrides are implemented with seller-scoped API and admin UI workflows.
- Seller-scoped bulk archive is implemented through the CSRF-protected
POST /api/v1/admin/bulkroute; it validates active inventory lifecycle transitions and never substitutes for the dedicated sale workflow.
Verified Baseline
| Suite | Current coverage |
|---|---|
| Domain | Product requirements and inventory lifecycle rules |
| Application | Product slug allocation, condition compatibility, password verification/recovery, session issuance, activity renewal, management, and audit events |
| HTTP | Product and inventory creation, validation, authentication/recovery, CSRF, rate limiting, and session management |
| Integration | PostgreSQL catalog/session/audit/password recovery persistence and Redis-shared login throttling |
Verified locally: npm test passes 178 tests with no failures (24 domain, 84 application, and 70 HTTP); worker tests, web tests, web build, Storybook build, Storybook interaction/accessibility checks, integration tests, and authenticated E2E workflows also pass when their required local services and credentials are available.
Public Seller Description
- Sellers can save, edit, and clear an optional public description in Settings.
- Descriptions are trimmed plain text, limited to 2,000 characters server-side, and stored in existing seller settings JSON without a migration.
- Public listing and product detail pages render the description as escaped text with line breaks; public DTOs expose only the allowlisted field.
- Dark-theme coverage also exposed and fixed insufficient status badge text contrast for Available, Pending, and Sold.
- Coverage includes validation/partial-update/clearing tests, public HTTP contracts, PostgreSQL repository reads, settings edit/clear interactions, both public page integrations, and absent/plain-text/dark-theme component stories.
- Validation: 166 API tests, 23 isolated PostgreSQL/Redis integration tests, 10 web tests, production web build, Storybook build, and Storybook interaction/accessibility runner (32 suites / 84 tests).
Public Browsing Accessibility
- Public gallery labels use API image descriptions, controls wrap at narrow widths, and failed API image URLs have an accurate accessible fallback.
- Long detail text and seller contacts reflow, read-only condition badges no longer add inactive buttons to keyboard navigation, and detail loading/errors expose announcement roles.
- Added keyboard, 320px reflow, 200% text enlargement, and detail-state regression stories. Browser review and its native-zoom/screen-reader limitations are recorded in
docs/ACCESSIBILITY.md. - Validation: 166 API tests, 10 web tests, production web build, Storybook build, and 32 Storybook suites / 93 tests. This frontend-only slice changes no persistence or API contracts.
Public Navigation Accessibility
- Catalog cards use router links; catalog and detail pages have descriptive titles and named, focused main landmarks on entry.
- Async responses and query updates preserve user focus. Filtered catalog URLs survive the explicit return link and browser Back; return destinations are restricted to the catalog.
- Added three public browser navigation tests and return-path validation coverage; updated page/card Storybook interactions.
- Validation: 166 API tests, 11 web tests, 3 public Playwright tests, production web build, Storybook build, and 32 Storybook suites / 93 tests. No API or persistence changes.
- Screen-reader speech and native browser zoom remain manual review items; this slice verifies browser focus and title behavior.
Clear Public Contact Methods
- Settings now sends explicit empty strings when a seller clears email or phone; help text explains removal. Omitted API fields still retain existing values.
- Validation accepts empty/whitespace-only email as removal while rejecting invalid non-empty addresses. Both public detail repositories expose absent/cleared contacts as null.
- HTTP coverage exercises real settings-service merging, validation, persistence reads and unchanged fields; PostgreSQL integration coverage verifies clear-one/clear-both behavior for listing and product detail projections.
- Storybook covers clearing contacts while retaining the description and rendering seller information without contact links.
- Validation: 167 API tests, 23 isolated integration tests, 11 web tests, production web build, Storybook build, and 32 Storybook suites / 95 tests. No migration required.
Settings Error Recovery
- Settings only exposes its form after a successful load. Failed reads offer Retry instead of editable defaults.
- Keyboard retry restores focus to the description field on success or Retry on repeated failure.
- Saving announces progress and disables fields/submission while in flight; failed saves retain edits and allow retry without reloading.
- Storybook covers loading, load errors, successful/repeated retry, save failure/retry, saving/disabled states, mobile retry and dark-theme save recovery.
- Validation: 167 API tests, 11 web tests, production web build, Storybook build, and 32 Storybook suites / 102 tests. Frontend-only change; no API or persistence changes.
Saved Views Error Recovery
- Failed list reads no longer show an empty-list message or create form; Retry restores keyboard focus on success or repeated failure.
- Create/delete actions clear stale feedback, announce progress, and block conflicting actions. Create failures preserve drafts; delete failures preserve the view and focus; successful deletion announces completion and focuses the list heading.
- Storybook covers populated/empty/loading/error states, load retries, create/delete recovery, invalid JSON, pending disabled states, mobile retry and dark-theme recovery.
- Validation: 167 API tests, 11 web tests, production web build, Storybook build, and 32 Storybook suites / 113 tests. Frontend-only change; API and persistence unchanged.
Image Manager Error Recovery
- Loaded images and alt-text drafts survive action failures and refreshes. Initial-load errors offer Reload; refresh errors retain the gallery with writes disabled until reload succeeds.
- Every action reconciles metadata even on failure, exposing partial multi-upload/reorder success without replaying mutations. Pending actions block overlapping writes and file drops.
- Added page/component stories covering load/retry, edit/delete failure and retry, successful deletion followed by refresh failure, pending/disabled states, partial upload failure, mobile and dark-theme recovery.
- Dark-theme coverage also fixed destructive-button contrast by separating its solid background token from error-text color.
- Validation: 167 API tests, 11 web tests, production web build, Storybook build, and 32 Storybook suites / 124 tests. No API or persistence changes.
Atomic Image Reordering
- Move up/down now calls a single authenticated, CSRF-protected
POST /api/v1/admin/images/:id/moveoperation. The server derives the adjacent image from current persisted order. - The repository locks the owning Inventory Item and its images, applies the domain move rule, and commits contiguous positions in one transaction. Ties are resolved deterministically; boundary moves are no-ops; primary state is preserved.
- Tests cover invalid requests, ownership, CSRF, missing images, boundary moves, tied positions, rollback after the first write, concurrent moves, and UI success/failure recovery.
- Validation: 171 API tests, 26 isolated PostgreSQL/Redis integration tests, 11 web tests, production web build, Storybook build, and 32 Storybook suites / 126 tests. No migration required.
Image Update Validation
- Legacy order updates require a non-negative PostgreSQL integer; alt-text updates require trimmed text up to 1,000 characters or explicit null. Missing/extra/mistyped fields are rejected before persistence.
- Domain validation protects non-HTTP service callers as well. Authentication, CSRF and seller ownership remain unchanged.
- The alt-text editor shows its limit, trims saved drafts, prevents oversized input and gives associated accessible feedback for oversized pre-existing text.
- Validation: 174 API tests, 26 isolated integration tests, 11 web tests, production web build, Storybook build, and 32 Storybook suites / 128 tests. No migration required.
Latest Vertical Slice: Server-Derived Upload Dimensions
- Multipart uploads ignore client dimensions and persist inspected width/height plus actual buffer length. An injected Sharp inspector validates metadata and decoding before storage, metadata writes or job creation.
- Existing MIME signatures, 10 MiB byte limit and 10,000-pixel dimension bounds remain enforced; decoder work is pixel-bounded. JSON metadata registration retains its separate existing contract.
- Tests use actual JPEG/PNG/WebP data and cover forged/missing dimensions, forged byte counts, oversized dimensions, signature-only images and truncated pixel data whose header remains readable.
- Validation: 178 API tests, 26 isolated integration tests, 11 web tests, production web build, Storybook build, and 32 Storybook suites / 128 tests. Existing Sharp dependency reused; no migration or visual changes.
Next bounded slice: enforce the configured per-item image count limit. docs/IMAGES.md requires configurable image counts and Settings exposes the limit, but image creation currently checks only individual-file metadata. Enforce the seller's limit atomically for uploads/metadata registration, reject excess images clearly, and cover concurrent uploads and UI feedback.
Next Milestone
Complete production configuration and operational maturity around the implemented vertical slices.
- Configure and validate an approved external pricing provider and provider-specific mapping data.
- Expand broader accessibility/manual coverage and address any remaining integration edge cases.
Acceptance criteria: production provider credentials are secret-managed, migrations and backups are exercised in the target environment, and CI runs integration, authenticated E2E, web, build, Storybook build, and Storybook interaction/accessibility gates.
CI also runs the worker suite, production dependency audit, and deployment/restore script contract checks.
Overall Roadmap
Work through one bounded vertical slice at a time. The linked documentation remains authoritative when this roadmap is less detailed.
Completed vertical slices include authentication, listings and image processing, acquisitions, sales and audited corrections, dashboard metrics/alerts, pricing observations and quality handling, provider mappings, durable pricing refresh jobs, public search/detail/image states, bulk operations, exports, settings, Saved Views, admin workflows, CI integration/E2E gates, production Docker packaging, rollback/health checks, PostgreSQL backup verification, restore drill scripts, image-storage restore support, and deployment smoke checks.
Remaining roadmap areas are approved external provider credentials/adapters, broader accessibility/manual coverage, and deployment-specific NAS/TLS validation.
Known Gaps
- No initial User/Seller is provisioned in the development database yet. Run
npm run provision:adminafter setting its required local.envvariables. - Listings are partially implemented: draft creation, seller-scoped reads, publication gating, lifecycle writes, archive behavior, sold/archived inventory checks, and item-owned image metadata are complete; storage-backed processing remains.
- The provider abstraction, fixture provider, HTTP provider adapter, Product mapping workflow, durable refresh queue, worker execution, polling contract, retry policy, and completed-job purge operation are implemented. Production readiness still requires approved external provider credentials and provider-specific mapping data.
- API and worker production startup now reject fixture pricing, missing provider endpoints, and non-HTTPS provider endpoints before opening runtime connections.
- Pricing refresh requests now enqueue seller-scoped jobs and expose a safe
GET /api/v1/admin/jobs/:idpolling contract instead of doing provider work inline. - Product-level provider mappings now persist seller-scoped
PRODUCT/SEARCHrelationships and support active listing and controlled disabling. - Pricing refresh enqueue now resolves its provider from an active Product mapping and rejects unmapped Products explicitly.
- Local development and CI can enable a deterministic fixture provider for end-to-end refresh coverage; production provider adapters remain explicitly configured deployment boundaries.
- Pricing refresh jobs have a bounded three-attempt retry policy with exponential backoff. The worker schedules completed-job cleanup using configurable retention days and cleanup interval settings.
- Bulk archive, asynchronous bulk pricing refresh, and Product-level bulk tag updates are implemented through the seller-scoped API boundary. Inventory
SOLDremains intentionally exclusive to the audited sale workflow. - Admin inventory JSON export is implemented at
GET /api/v1/admin/exports/inventory.jsonand serializes seller-scoped admin DTOs as a downloadable attachment. - Admin inventory CSV export is implemented at
GET /api/v1/admin/exports/inventory.csvwith escaped spreadsheet-safe fields and seller-scoped admin DTOs. - Admin inventory Excel-compatible export is implemented at
GET /api/v1/admin/exports/inventory.xlsusing the XML workbook format and seller-scoped admin DTOs. - Seller-scoped admin settings are implemented through
GET/PATCH /api/v1/admin/settingswith strict category allowlists and server-side partial-update merging. - Seller-scoped saved-view CRUD is implemented through the documented admin API with validated filter maps and repository-level ownership checks.
- Large inventory JSON exports can be enqueued through
POST /api/v1/admin/exports/inventory.json/jobs, polled throughGET /api/v1/admin/exports/jobs/:id, and downloaded after completion; the worker owns claim, completion, and failure processing. - Completed asynchronous inventory JSON exports can be downloaded through
GET /api/v1/admin/exports/jobs/:id/download. - PostgreSQL restore verification and image snapshot restore scripts are implemented and covered by shell tests as part of the deployment drill workflow.
npm audit --omit=devcurrently reports zero production vulnerabilities. Re-run the audit after dependency changes and review development-dependency findings separately before production releases.- Authenticated E2E coverage now verifies both the core catalog workflow and the Settings, Saved Views, and export-controls workflow.
- Production dependency audit currently reports zero vulnerabilities with
npm audit --omit=dev. - Public catalog sorting now supports recently added, recently updated, name A-Z, name Z-A, price low-to-high, and price high-to-low through a URL-synchronized atomic sort control. Broader inventory filter parity and market-value sorting remain.
- Public catalog filtering now supports URL-synchronized set, event, and tag text filters through a reusable atomic text-filter control and the shared search API.
- Public catalog filtering now supports explicit Available, Pending, Sold, and All status modes plus a 30-day Newly added toggle through the shared search API and atomic controls.
- The admin workspace now includes a responsive guided inventory workflow stepper linking Product, Sources, Copy, Images, Pricing, and List stages, with progress derived from loaded admin state.
- Product identification is now an extracted
ProductIdentityStepmolecule with empty/filled Storybook states, while preserving the existing create-product API workflow. - Source mapping is now an extracted
ProviderMappingStepmolecule with Product/Provider/PRODUCT-vs-SEARCH mapping states, while preserving existing mapping loading and save behavior. - Physical inventory creation is now an extracted
InventoryCopyStepmolecule with Product and condition selection states, while preserving the existing seller-scoped create-copy API workflow. - Image management is now surfaced as an extracted
InventoryImagesStepmolecule with missing-image status and direct links to the existing upload/processing manager route. - Pricing is now an extracted
PricingReviewStepmolecule covering observations, provider refresh, and reasoned manual overrides while preserving existing pricing API behavior. - Review and listing is now an extracted
ReviewListStepmolecule covering physical-copy selection and asking-price confirmation while preserving existing draft creation and publication lifecycle behavior. - The guided inventory workflow now has extracted Product, Source Mapping, Physical Copy, Images, Pricing, and Review/List frontend stages, each with colocated Storybook coverage.
- Public catalog sorting now supports latest manual/calculated market value low-to-high and high-to-low, with null values placed last.
- Public listing detail now shows market-value freshness and suppresses asking price for sold listings, with Storybook coverage for sold and valued states.
- Public catalog filters now collapse behind an accessible mobile disclosure, show an active-filter count, and provide a reset action while preserving URL synchronization.
- The admin image manager now supports multi-file upload with a drag-and-drop dropzone, per-image alt-text editing, primary selection, up/down reordering, and per-image retry/delete actions targeted at the correct image instead of the first uploaded image.
- The guided inventory workflow is now a true single-step-at-a-time wizard: the stepper is clickable, only the active stage's panel is shown, Back/Next controls advance between stages, and the active stage persists across reloads through local storage.
- Listing management (publish/mark pending) is now a dedicated
/admin/listingsscreen with its own navigation entry; the guided workflow overview links to it and only tracks listing creation and a lightweight count for wizard completion. - Sale recording/voiding and acquisition recording are now dedicated
/admin/salesand/admin/acquisitionsscreens with their own navigation entries; the guided workflow overview links to both instead of embedding their forms and history inline. - The guided wizard now manages focus and announces step changes: selecting a stage (via the stepper or Back/Next) moves keyboard/assistive-technology focus to that stage's labeled region and updates a live-region status announcement, with Storybook interaction coverage.
- Seller-scoped latest market valuations are now readable through
GET /api/v1/admin/valuations. - Physical inventory management (bulk archive, bulk pricing refresh, bulk tag updates, market valuations, and pricing job retry) is now a dedicated
/admin/inventoryscreen with its own navigation entry; the guided workflow overview links to it and only tracks a lightweight inventory count for wizard completion. - Storybook now installs a lightweight router mirroring the app's named routes plus a mobile-viewport-forcing test-runner hook, enabling isolated page stories (including the public catalog) that use
useRoute/useRouteror narrow-viewport CSS breakpoints. - The public catalog now has its own Storybook coverage, including an interaction test proving the mobile filter disclosure is keyboard-operable and correctly hides/reveals filter controls via
aria-expanded. This review also found and fixed a real color-contrast failure in the catalog error-state text. ListingDetailPage,ProductDetailPage, andAdminImagePagenow have Storybook coverage. Adding it surfaced and fixed a color-contrast bug shared by all three: the "Back to catalog" link, pagination controls, and the selected image-gallery thumbnail were using the non-text-safe--color-interactivetoken instead of--color-interactive-text.- Per-item image limits are now enforced atomically for seller image creation and uploads, using
inventory.maxImagesPerItem(default 10); concurrent inserts are serialized on the physical inventory item and returnIMAGE_COUNT_LIMIT_REACHEDat the configured cap.
Local Commands
npm install
npm run db:up
npm run db:migrate
npm run provision:admin
npm test
The Compose database requires a local .env created from .env.example. To prepare the test database once after bringing PostgreSQL up:
docker compose exec -T postgres sh -c 'createdb -U "$POSTGRES_USER" pokemon_inventory_test'
Then migrate it using its TEST_DATABASE_URL value as DATABASE_URL, and run integration tests with both TEST_DATABASE_URL and TEST_REDIS_URL set. See README.md for the environment-file prerequisites.
Suggested Resume Prompt
Read docs/IMPLEMENTATION-STATUS.md and continue the next bounded milestone. Verify the existing baseline first, follow AGENTS.md, and keep the change focused with tests.