Files
MeshVault/docs/project-status.md
T
Cline a829d6e8c6 feat: catalog shared contracts (Tasks 1-4)
Task 1: Establish catalog identity and atomic file ownership
- CatalogService, CatalogServiceInterface, ModelMetadata DTO
- PdoCatalogRepository with atomic operations, savepoint support
- FOR UPDATE file locks in ascending order, FOR NO KEY UPDATE for metadata
- FK-compatible lock composition documented (spec §6)

Task 2: M3 import & indexing engine delivery layer
- ImportService, ImportWorker with durable collision handling
- SpaceChecker, StreamingHasher, VerifiedCopier, StlValidator
- FileEnumerator, LocalFilesystem, PathSafety
- Console command wiring via ContainerWiringTest

Task 3: Importer integration and repair
- LegacyGuessedImportGroupingAdapter isolates first-directory guessing
- ImportService uses adapter; ImportWorker uses CatalogServiceInterface
- Null owners remain null; DomainException mapped to CATALOG_CONFLICT
- SQL failure after registration/path update with caller sentinel rollback

Task 4: PostgreSQL contention evidence and bounded acceptance
- 6 new PostgresCatalogContractsTest cases with independent sessions
- Generated schemas, 250ms lock timeouts, 5s statement timeouts
- Ascending file locks, FOR SHARE contention, stale-owner rejection
- Rollback/retry, nested transaction survival, root creation contention
- Negative controls: replay FOR UPDATE removal (11 failures), metadata FOR UPDATE (4 FK KEY SHARE timeouts)
- Fresh Docker PostgreSQL 17 / PHP 8.4.26: 473 tests, 2718 assertions, 10 skips, exit 0

All local: 474 tests, 2347 assertions, 54 skips, foundation/lint clean.
2026-10-13 19:41:03 -05:00

141 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Acceptance reconciliation — 2026-10-12
Baseline: `c1ef2ee`. This review compares the live Gitea acceptance criteria with
source, tests, and recorded runtime evidence. Implementation is not milestone
acceptance. The earlier assessment understated remaining M2/M3 work.
## Catalog-core Task 4 evidence — 2026-10-13
Tasks 1–3 were approved at handoff (371 tests / 2032 assertions / 22 skips,
local lint clean). Task 4 adds six PostgreSQL cases using independent sessions,
generated schemas, 250ms lock timeouts and 5s statement timeouts. Execution-time
parameter recording establishes ascending file locks for reversed input;
FOR SHARE contention establishes same-owner no-op locking. Tests also establish
stale-owner rejection, rollback/retry, nested transaction survival, lower-lock
release after savepoint rollback, and explicit/legacy root creation contention
including disjoint folders. No deadlock was induced and no automatic retry added.
- Fresh Windows PHP 8.3.35: foundation checks pass; full PHPUnit **377 tests,
2032 assertions, 28 skips**, exit 0; standard PHPCS lint exit 0. These are the
Composer script commands invoked directly with the required PHP executable.
- Fresh isolated Docker PostgreSQL 17 / PHP 8.4.26: `sh bin/test-postgres.sh`
ran full Composer tests and lint successfully: **377 tests, 2160 assertions,
7 skips**. Final log:
`keith@192.168.2.23:/tmp/meshvault-catalog-tests-Ov96uNzU/pg-run-3.log`.
- Initial PG run (`pg-run-1.log` in the same directory): 377 tests / 2140
assertions / 4 errors / 7 skips. All four errors were SQLite-only trigger DDL
in the later-update rollback fixture. A PostgreSQL trigger function now tests
the same earlier-write condition; `pg-run-2.log` first confirmed the fix.
New concurrency cases passed against the approved implementation; no production
locking gap or new-case red/mutation run is claimed.
- Transfer included current uncommitted source, excluding vendor, node_modules,
.git, .superpowers, environment files, secrets and key files. Dockerfile.test
installs dependencies. Dedicated disposable containers/network used no host DB
ports or persistent volumes; test containers were gone after final cleanup.
Neither `/tmp/MeshVault`, the historical PG workspace nor development data was
modified. SSH calls exceeded the tool's 30s wait; subsequent log reads verified
completion and the script's tests-and-lint success marker.
Independent whole-slice review approved the bounded implementation with no blocking
findings, reran local tests/lint and checked the PostgreSQL log and matching source
hashes. The user authorized local integration into main, not a push. No issue closure
is implied; broader #28 metadata/lifecycle contracts and the M2/M3 gaps remain open.
## Historical evidence
- Fresh Windows run: `composer test` — 291 tests, 1801 assertions, 22 skips; exit 0.
`composer lint` — exit 0. Expected HTTP failure-path logs are not test failures.
- Recorded isolated Linux/PostgreSQL 17 run: 291 tests, 1863 assertions, 7 skips;
tests and lint exit 0. Not rerun for this review. See `postgres-tests.md`.
- M1 runtime evidence is historical: local task reports document HTTP/FPM behavior,
database volume survival across down/up, runtime-user permission checks, and asset
watch/build delivery. Those ignored reports are not public repository artifacts.
- Source-derived recovery risks below need executable regression tests; they are
not claims that a new crash experiment was run.
## Issue disposition
Tracker reconciliation completed: #6, #7, #8, #9, #11 and #23 were closed with
evidence comments. All other reviewed issues remain open with gap comments. The
closure-candidate labels below describe the audit recommendation that led to those
changes; issue states were rechecked through the live API afterward.
| Issues | Assessment and outstanding acceptance |
| --- | --- |
| #6–9, #11 | Closure candidates: Compose, application skeleton, config, assets and logging have implementation, tests and historical runtime evidence. Preserve that evidence in issue comments. |
| #10 | Wrappers implemented; complete migration/seed command smoke coverage remains to be reconciled. |
| #12 | Phinx runs production migrations through PG fixtures; direct migration rollback/clean-start acceptance remains separate from fixture teardown. |
| #13 | Folder schema exists; review root representation, hierarchy invariants and deletion behavior against the issue before closing. |
| #14 | Models exist; full specified metadata and timestamp semantics need reconciliation. |
| #15 | Multipart files and indexed hashes exist; source mtime and explicit format metadata are missing, and lifecycle naming needs reconciliation. |
| #16 | Tags/join table exist; model category assignment is absent and root category name uniqueness is not guaranteed by nullable-parent uniqueness. |
| #17 | Thumbnail rows exist; exactly-one-primary invariant and demonstrated separate storage remain missing. |
| #18 | Jobs/items/counters/claims exist; confirmed manifest, attempts, resulting-file reference, duplicate decisions and relationships remain incomplete. |
| #19 | Backup intent exists; executable consistent backup/restore guidance and clean-environment restore drill are missing. |
| #20 | Scanner exists; configured source mounts, destination exclusion, immutable manifest and explicit grouping preview/confirmation are incomplete. |
| #21 | Space check exists; required/available byte reporting and production safety-margin configuration remain incomplete. |
| #22 | STL validator is covered; one combined extension allowlist does not implement the requested separate supplementary-file policies. |
| #23 | Closure candidate: streaming hashing, mutation checks and persisted indexed hashes are implemented and covered. |
| #24 | Verified copier exists; nested hierarchy and crash-safe collision publication/reconciliation remain incomplete in worker integration. |
| #25 | Queue/worker/locking exist; confirmed grouping and full replay/retry guarantees remain incomplete. |
| #26 | Repository progress exists; caller-facing polling, full state distinctions and worker handling of empty jobs remain incomplete. |
| #27 | Failures persist; supported retry with attempt history and persisted-message redaction remain incomplete. |
| #28 | Identity/aggregate baseline plus shared importer, raw expected-metadata and status contracts are implemented in the uncommitted shared-contracts slice. Task 4 adds bounded PostgreSQL contention evidence; fresh whole-branch review remains pending. Explicit confirmed import grouping is not implemented. Not complete. |
## Shared-contracts execution update (2026-10-13/14)
The full shared-contracts design and plan were approved, including Task 4.
Local PHP 8.3.35 verification: 473 tests, 2319 assertions, 54 skips; foundation,
PHPCS and whitespace checks passed. Skipped PostgreSQL tests are not local lock
evidence. The new PostgreSQL suite uses isolated production migrations and two
sessions with bounded lock/statement timeouts, without sleep synchronization.
Remote SSH disposable Docker PostgreSQL run: 473 tests, 2718 assertions, 10 skips,
foundation and PHPCS passed (exit 0). Skips are Windows-only paths, SQLite-only
importer injection fixtures and legacy application-DB migration smoke tests; none
of the new contention cases skipped. Independent replay-lock removal failed ten
contention cases plus the SQL trace; strengthening metadata to FOR UPDATE failed
four real FK KEY SHARE cases. Restored source passed the full suite and lint.
Exact source hashes/logs are recorded in the Task 4 execution report. Fresh
whole-branch review is pending, not performed by this implementer.
Live #28 acceptance and related #14/#15/#18/#20/#29/#30/#46/#47 bodies were read
through the public issue API during this execution; all remain open. #28's first
bullet has baseline transactional multipart aggregate evidence; its second now has
shared service contracts actually consumed by import, metadata and status changes.
Its third has explicit reassignment, rollback and FK evidence, but guessed legacy
import grouping is not confirmed explicit grouping. #14/#15/#18 dependencies are
not waived. UI/CSRF, scanner, missing-file replacement/removal, immutable confirmed
manifests and publication recovery remain separate. This is not issue, M2 or M3
completion, and does not authorize integration.
## Important implementation findings
- `LegacyGuessedImportGroupingAdapter` now isolates the importer's first-directory
association guessing. `ensureModel()` reuses folder/name identities. Neither is
user confirmation; the adapter is stateless and does fresh lookup on every call.
The M3 ledger's directory-grouping decision does not supersede live #20 criteria.
- The scanner retains relative paths, but job creation discards them. The worker
constructs destinations from a model folder and basename, flattening deeper paths.
- The worker persists a planned name before copying, but saves a collision suffix
only after publication. A crash in between can lead to a second suffixed copy on
replay. Existing successful-collision tests do not establish this crash boundary.
- A catalog failure after publication can leave a file on disk and a terminal failed
item. Source validation also precedes adoption of an already published copy.
- Item size can be replaced during planning while scanned job byte totals remain
unchanged. Failure text is persisted from exception messages without general
redaction. Progress and retry need workflow-level contracts, not just counters.
## Proposed next delivery order
1. Complete issue/evidence reconciliation without closing partial milestones.
2. Design a bounded #28 catalog contract with explicit grouping/reassignment and
stable model/file identities; retain PHP/PDO/Phinx and the existing repositories.
3. Extend #18/#20 with immutable, confirmed manifests and safe source selection.
4. Resolve #24/#25 publication recovery before calling imports restart-safe.
5. Add progress and retry contracts (#26/#27), then M4 CRUD/removal/downloads and
serialized folder/model moves. Complete schema prerequisites as their contracts
are settled, using new migrations rather than rewriting applied migrations.
M5 metadata, M6 browse/search, M7 lifecycle/duplicate review and M8 hardening/release
remain ahead. No production readiness or percentage-complete claim is implied.