Files
MeshVault/docs/project-status.md
T

226 lines
18 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.
## Explicit grouping extension — implementation worktree status
Implemented confirmed opt-in grouping, stable existing catalog identity, immutable persisted
decisions, and durable collision planning before no-overwrite publication with recovery and
conservative compensation. Default legacy wiring is retained. Final isolated Linux PostgreSQL
run: 483 tests / 2776 assertions / 11 skips; foundation and lint passed (exit 0).
Linux SQLite: 483 tests / 2407 assertions / 44 skips. Remote RED preceded implementation.
Fresh review/integration pending; no commits, pushes, merges or issue closures in this work.
Mutation controls and dedicated concurrent decision tests remain outstanding. See
`.superpowers/shared-contracts/explicit-grouping-report.md` and `docs/explicit-grouping.md`
for exact evidence and filesystem durability limitations. Main-checkout status update is a
parent handoff because this implementer is restricted to MeshVaultSharedContracts writes.
# 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.
## Explicit grouping sibling implementation — 2026-10-18
`MeshVaultSharedContracts` now contains confirmed opt-in grouping, stable identity reuse,
immutable/idempotent decisions, legacy-default wiring, durable collision plans before
filesystem publication, exact-path no-overwrite publication, recovery and conservative
compensation. Not merged or committed; main implementation and issue acceptance unchanged.
Remote disposable PostgreSQL RED then GREEN evidence is recorded in sibling
`.superpowers/shared-contracts/explicit-grouping-report.md`: final **483 tests,
2776 assertions, 11 skips**, foundation and lint exit 0. Linux SQLite additionally passed
483 tests / 2407 assertions / 44 skips. Fresh review, mutation controls and dedicated
concurrent decision-writer tests remain outstanding. Simulated crash-state coverage is
not process-kill/power-loss proof; directory fsync is absent. Uncertain compensation retains
files. Multipart new grouping must select a single created model ID (`create_new` is per-file).
No live DB changes, push, merge, issue closure or M2/M3 completion is claimed.
## 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.
## Integration status — 2026-10-14
Branch `catalog-shared-contracts` fast-forward merged to `main` (commit `46d347b`).
Pushed to origin/main. Previously closed: #6, #7, #8, #9, #11, #23.
**Newly closed:** #28 (catalog core contracts — all three bullets have evidence:
transactional multipart aggregate, shared service contracts consumed by import/metadata/status,
explicit reassignment/rollback/FK evidence). Remaining open: #14, #15, #18, #20, #29, #30, #46, #47.
## Issue/evidence reconciliation — 2026-10-14
This section maps each open issue to existing evidence and remaining gaps.
No partial milestones are closed here; this is a reconciliation snapshot.
| Issue | Title / Scope | Existing Evidence | Remaining Gaps | Milestone |
|-------|---------------|-------------------|----------------|-----------|
| #14 | UI/CSRF protection | HTTP integration tests exist (`tests/Http/AppTest.php`); CSRF token middleware not implemented | CSRF token generation/validation middleware; form integration; SameSite cookie policy | M2 |
| #15 | Scanner / file discovery | `FileEnumerator` + `LocalFilesystem` + `PathSafety` implemented; recursive walk, extension filter, size limits | Incremental scanning (mtime/hash checkpoint); symlink policy beyond escape; watch-mode integration; scan resumption | M2/M3 |
| #18 | Import grouping / manifest | `LegacyGuessedImportGroupingAdapter` isolates first-directory guess; `ImportService` groups by adapter; `ImportWorker` registers files | **Confirmed explicit grouping** (user confirmation); immutable manifest write; source selection policy; grouping override/merge | M3 |
| #20 | Model/file identity & grouping | `CatalogService`/`Repository` provide stable IDs; `ensureModel` reuses folder/name; adapter stateless fresh lookup | Explicit user-confirmed grouping (not guessed); stable model identity across imports; grouping persistence | M3 |
| #24 | Publication recovery | `VerifiedCopier` verifies bytes on copy; `ImportWorker` persists planned name before copy | Crash between publish and suffix save → duplicate suffixed copies; orphaned published files on catalog failure; replay idempotency | M3/M4 |
| #25 | Missing-file replacement/removal | `CatalogService::changeFileStatus` supports Present/Missing/Corrupt; `detachFiles` removes associations | Replace missing file (re-upload); remove missing file (cleanup); missing-file scan/report; UI workflow | M4 |
| #26 | Progress contracts | `ImportJobRepository` tracks item status (Pending/Processing/Completed/Failed); byte totals in job | Progress callbacks during copy/hash/validate; ETA; pause/resume; granular stage reporting | M4 |
| #27 | Retry contracts | `ImportJobRepository::resumeInterrupted` resets Processing→Pending; worker `runOnce` loop | Exponential backoff; max retries per item/job; retry classification (transient vs permanent); dead-letter | M4 |
| #29 | Browse/search | Catalog read methods (`file`, `fileByManagedPath`, `aggregate`, `folderChildren`) | Full-text search; faceted filter (mime, size, date); pagination; sort; saved queries | M5/M6 |
| #30 | Lifecycle/duplicate review | `ModelMetadata` DTO; `changeFileStatus`; `detachFiles`/`attachFiles` | Duplicate detection (hash-based); review queue; merge/split models; archive/restore; retention policy | M5/M7 |
| #46 | Asset watch/build delivery | M1 Docker stack with asset watcher (`dev.sh`, `docker-compose.yml`); Tailwind/Vite | Production asset pipeline; cache busting; CDN integration; build verification | M1 (partial) |
| #47 | Hardening/release | Foundation checks; PHPCS; PHPUnit; Docker test runner; PostgreSQL CI | Security audit; dependency scanning; load testing; release automation; rollback procedure | M8 |
**Legend:** Evidence = code/tests/docs that exist in `main` at `4d10f4f`. Gaps = acceptance criteria not yet satisfied. Milestone = earliest milestone where closure is planned per proposed delivery order.
## 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. **COMPLETED: Design bounded #28 catalog contract with explicit grouping/reassignment and
stable model/file identities** — see `MeshVaultSharedContracts/docs/superpowers/specs/2026-10-14-catalog-explicit-grouping-contract.md`
3. Implement explicit confirmed grouping with `ExplicitImportGroupingAdapter` and persisted decisions.
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.
## Design Phase Complete: Explicit Grouping & Stable Identity (2026-10-14)
The bounded #28 catalog contract for explicit grouping and stable identity has been designed and documented. This extends Tasks 1-4 contracts without breaking them.
**Key Deliverables:**
- **New Interface**: `ExplicitImportGroupingAdapterInterface` with `modelFor()`, `persistDecisions()`, `recoverDecisions()`
- **New Implementation**: `ExplicitImportGroupingAdapter` supporting explicit model_id, folder_path+model_name, and fallback to legacy guessed
- **Database Migration**: `import_jobs_decisions` table for decision persistence
- **Repository Extensions**: `recordGroupingDecision`, `getGroupingDecisions`, `updateItemManagedPath`
- **Catalog Service Extensions**: `findModel`, `listModelsInFolder`, `getOrCreateModel`
- **ImportService Integration**: Optional `$groupingContext` parameter for explicit grouping
- **Worker Atomic Publish**: Temp copy → atomic rename + catalog register in single savepoint (addresses #24 crash gap)
- **Backward Compatibility**: Legacy adapter unchanged; explicit adapter opt-in via container
**Acceptance Criteria Addressed:**
- #18: Confirmed explicit grouping (user confirmation) — via context parameter and decision persistence
- #20: Explicit user-confirmed grouping; stable model identity across imports; grouping persistence — via new adapter and decision table
- #24: Crash between publish and suffix save — via atomic publish-then-register pattern
**Out of Scope (Future):** UI (#14), incremental scanner (#15), missing-file UI (#25), progress/retry contracts (#26/#27), search/facets (#29), duplicate review (#30)
**Next Phase:** RED tests → GREEN implementation per implementation sequence in contract §13.