c9201a004c
New canonical openspec/specs/service-storage/spec.md (28 reqs SS-101..128). Change-side delta + sync-report. web-ui + prometheus-charting canonicals untouched.
167 lines
11 KiB
Markdown
167 lines
11 KiB
Markdown
# Sync Report — `service-storage-harness`
|
||
|
||
> Phase: **sync** · Change: `service-storage-harness` · Repo: `/home/user/manage`
|
||
> Mode: file-backed (`artifactStore: openspec`). No source-code edits; only OpenSpec artifacts were
|
||
> written. Not committed (parent owns the commit). The change folder was **not** moved (that is
|
||
> `sdd-archive`'s job).
|
||
|
||
**Status: SYNCED.** A new canonical domain `openspec/specs/service-storage/spec.md` was created
|
||
from the verified change, and the change-side domain delta spec that unblocks the native status
|
||
engine's `sync`/`archive` gates is also in place.
|
||
|
||
---
|
||
|
||
## 1. Executive summary
|
||
|
||
The `service-storage-harness` change shipped a **complete but flat** `openspec/changes/service-storage-harness/spec.md`
|
||
(28 requirements, SS-101 … SS-128) with **no** per-domain delta spec under
|
||
`openspec/changes/service-storage-harness/specs/<domain>/`. `sdd-sync` requires a domain delta
|
||
spec; the flat spec alone does not satisfy the canonical-merge contract.
|
||
|
||
Verify already returned **PASS** (verdict in `verify-report.md`; all four gates green — backend
|
||
`pytest` 322 passed, `ruff` clean, frontend `npm run build` exit 0, `npm run lint` 0 errors).
|
||
Functional coverage was **28/28 fully PASS**. The verify report's single CRITICAL was an **archive**
|
||
blocker (30 unchecked task checkboxes + missing `apply-progress.md`); `apply-progress.md` now exists
|
||
and reconciles the 35 tasks (the task tracker condition does **not** block `sdd-sync` of the green
|
||
code).
|
||
|
||
This sync **reconciles** the flat-spec-vs-domain-spec gap:
|
||
|
||
1. Authored the missing **change-side domain delta spec** —
|
||
`openspec/changes/service-storage-harness/specs/service-storage/spec.md` — using a clean
|
||
`## ADDED Requirements` structure that preserves the exact requirement IDs (SS-101 … SS-128) and
|
||
text from the verified flat `spec.md`. This is what flips the native status engine's `specs`
|
||
artifact from partial → done.
|
||
2. **Synced** the end-state into the **canonical store** —
|
||
`openspec/specs/service-storage/spec.md` — the actual sync target. Because the canonical
|
||
`service-storage` domain did not previously exist, the native helper rule applies: *when the
|
||
canonical spec does not exist, the change spec becomes the new canonical spec.* The two files
|
||
therefore carry identical requirement bodies (delta under `## ADDED Requirements`; canonical
|
||
under `## Requirements`).
|
||
|
||
Domain name **`service-storage`** was chosen (per the dispatch brief) because it covers the full
|
||
new model: the lifecycle-only `ServiceDataHarness` layer, the qBittorrent store + client + widget
|
||
stack, and the MediaIndex migration that established the per-service storage pattern. It is distinct
|
||
from the existing canonical domains `web-ui` (MUI→shadcn migration) and `prometheus-charting`
|
||
(direct Prometheus metric visualization), neither of which was **touched**.
|
||
|
||
## 2. Structured status & actionContext findings
|
||
|
||
The native `gentle-pi.sdd-status` passed by the parent reports `changeName: null` with
|
||
`blockedReasons: ["Change selection is ambiguous: mobile-responsive-parity, service-storage-harness,
|
||
services-as-hub-ia."]` because the engine auto-detected three active changes. This sync task was
|
||
**explicitly assigned** `service-storage-harness`; the ambiguity is a parent-resolution artifact
|
||
and does not block this phase (`isNonAuthoritative: false`).
|
||
|
||
- `artifactStore: openspec`; change root `openspec/changes/service-storage-harness/`.
|
||
- Artifacts present: `proposal.md`, `spec.md`, `design.md`, `tasks.md`, `verify-report.md`,
|
||
`apply-progress.md`.
|
||
- `verify: PASS` (verify-report verdict; gates green at `c9404f0`).
|
||
- `actionContext`: `mode: repo-local`, `workspaceRoot: /home/user/manage`,
|
||
`allowedEditRoots: ["/home/user/manage"]`, `warnings: []`. All three files written are inside the
|
||
authoritative workspace / allowed edit roots. ✓
|
||
- `relationships.sameDomainActiveChanges: []`, `collisions: []` — **no active same-domain
|
||
collisions**, so no archive/sync ordering decision was required.
|
||
- The new `service-storage` domain is distinct from the existing `web-ui` and `prometheus-charting`
|
||
canonical domains; both were left untouched.
|
||
|
||
**Post-sync structural change:** `openspec/changes/service-storage-harness/specs/service-storage/spec.md`
|
||
now exists (`hasDomainSpecs` → true), resolving the missing-domain-spec condition that gated sync.
|
||
The flat `spec.md` is intentionally **left in place** as the authoritative planning artifact the
|
||
work was built against (the archive convention keeps flat specs too); it no longer triggers the
|
||
"flat spec without domain specs" condition now that a domain delta sits alongside it.
|
||
|
||
## 3. Domains synced & canonical files updated
|
||
|
||
| Domain | Change-side delta (source) | Canonical (sync target) | Action |
|
||
|---|---|---|---|
|
||
| `service-storage` | `openspec/changes/service-storage-harness/specs/service-storage/spec.md` | `openspec/specs/service-storage/spec.md` | **NEW domain** — `## ADDED Requirements` copied into canonical as a new spec |
|
||
|
||
- **Canonical file created:** `openspec/specs/service-storage/spec.md` (28 requirements).
|
||
- **Change-side delta created:** `openspec/changes/service-storage-harness/specs/service-storage/spec.md`
|
||
(28 requirements, all `## ADDED Requirements`).
|
||
|
||
## 4. Requirement delta (ADDED / MODIFIED / REMOVED)
|
||
|
||
- **ADDED (28)** — all to the new `service-storage` domain (canonical did not exist pre-change).
|
||
IDs and text preserved verbatim from the verified flat `spec.md`. Grouped logically:
|
||
- *ServiceDataHarness (lifecycle layer)* — SS-101, SS-102, SS-103, SS-104
|
||
- *QbittorrentSampleStore* — SS-105, SS-106, SS-107
|
||
- *QbittorrentClient* — SS-108, SS-109, SS-110
|
||
- *qBittorrent widget source adapter* — SS-111, SS-112, SS-113, SS-114, SS-115
|
||
- *qBittorrent frontend widgets* — SS-116, SS-117, SS-118
|
||
- *MediaIndex migration onto harness* — SS-119, SS-120, SS-121, SS-122, SS-123, SS-124
|
||
- *Cascade-delete wiring* — SS-125, SS-126
|
||
- *Test and build greenness* — SS-127, SS-128
|
||
- **MODIFIED (0)** — none (new domain; no pre-existing canonical requirements to replace).
|
||
- **REMOVED (0)** — none.
|
||
- **RENAMED (0)** — none (RENAMED is intentionally unsupported by the native delta helper; not used).
|
||
|
||
## 5. Guardrails, approvals & destructive-sync assessment
|
||
|
||
- **Same-domain collisions:** none (`sameDomainActiveChanges: []`, `collisions: []`). The new
|
||
`service-storage` domain does not overlap the existing `web-ui` or `prometheus-charting`
|
||
canonical domains. No ordering decision was needed.
|
||
- **Destructive sync:** **not applicable.** There are zero REMOVED requirements and zero large
|
||
MODIFIED blocks (new domain; everything is ADDED). No destructive-sync parent approval was
|
||
required beyond the explicit reconciliation instruction in the task.
|
||
- **Legacy flat spec:** detected pre-sync; resolved by adding the domain delta spec alongside it
|
||
(the block condition is specifically "flat spec *without* domain specs"). The flat spec was left
|
||
in place as a planning artifact.
|
||
- **`web-ui` / `prometheus-charting` canonical isolation:** the existing
|
||
`openspec/specs/web-ui/spec.md` (MUI→shadcn rework) and `openspec/specs/prometheus-charting/spec.md`
|
||
(direct Prometheus charting) were **not modified** — verified untouched by `git status`. The three
|
||
domains are independent.
|
||
|
||
## 6. Validation / checks performed (file-backed, read-only)
|
||
|
||
Run from `/home/user/manage` (no source edits, no test re-runs — those are owned by verify and were
|
||
already green at `c9404f0`):
|
||
|
||
| Check | Command | Result |
|
||
|---|---|---|
|
||
| Canonical store populated | `ls openspec/specs/service-storage/spec.md` | present ✓ |
|
||
| Change-side domain spec present | `ls openspec/changes/service-storage-harness/specs/service-storage/spec.md` | present ✓ |
|
||
| Requirement-ID parity (flat ↔ delta ↔ canonical) | `grep -oE 'SS-[0-9]+'` all three files, `sort -u` | **28 == 28 == 28**, identical IDs SS-101…SS-128 ✓ |
|
||
| Body-text parity (delta ↔ canonical) | `diff` of the `^### Requirement:` region of both files | **identical** ✓ |
|
||
| Delta is pure ADDED | count `## ADDED/MODIFIED/REMOVED/RENAMED Requirements` | ADDED=1, MODIFIED=0, REMOVED=0, RENAMED=0 ✓ (no destructive sync) |
|
||
| Other canonicals untouched | `git status --porcelain openspec/specs/web-ui openspec/specs/prometheus-charting` | empty (not modified) ✓ |
|
||
| No edits outside openspec | `git status --porcelain` (filtered) | only `openspec/specs/service-storage/`, `openspec/changes/service-storage-harness/specs/`, and this report added ✓ |
|
||
| Markdown validity | write-time lint | all three files "Markdown clean" ✓ |
|
||
|
||
## 7. Carry-over items for the archive summary
|
||
|
||
These verify-phase findings are non-blocking for sync and should land in the archive summary:
|
||
|
||
1. **[CRITICAL-process, archive-only] Unchecked task checkboxes.** At verify time, 30
|
||
implementation/verification task checkboxes (§1.1–5.5) were unchecked and `apply-progress.md`
|
||
was missing. `apply-progress.md` now exists (created after the verify pass, reconciling all 35
|
||
tasks). `sdd-archive` should re-scan the native status engine to confirm `tasks: done` /
|
||
`applyProgress: present` before moving the change to archive, and tick any remaining unchecked
|
||
boxes if needed.
|
||
2. **[WARNING] Slice 2 over the 400-line review budget** (~644 source insertions vs the 400-line
|
||
budget / ~350–400 forecast). Additive feature slice (3 widgets + `LineSeriesChart` extraction +
|
||
tests); boundary is exactly the qBit-widget feature, no scope creep. No `size:exception`
|
||
recorded; non-blocking — record the actual in the archive summary.
|
||
3. **[INFO] `LineSeriesChart.test.tsx` is smoke-only** (asserts mount, not rendered `<Line>` series).
|
||
Non-blocking coverage note.
|
||
4. **[INFO] Stale generated `.pi-map.md`** files predate the new modules (`service_data.py`,
|
||
`qbittorrent_store.py`, `clients/qbittorrent.py`, `Qbittorrent*.tsx`, `LineSeriesChart.tsx`);
|
||
not deliverable source. Regenerate via `project_map_patch` / `project_map_validate`.
|
||
|
||
## 8. Next recommended phase
|
||
|
||
→ **`sdd-archive`** (clean). Confirm the native status re-scan reports `specs: done` / `sync: ready`
|
||
/ `archive: ready`, then move the change to
|
||
`openspec/changes/archive/2026-07-09-service-storage-harness`, carrying over the items in §7 into
|
||
the archive summary. Do **not** commit or push — the parent owns the commit with explicit paths.
|
||
|
||
---
|
||
|
||
### Appendix — Files written by this sync (OpenSpec only; no source code)
|
||
|
||
- `openspec/changes/service-storage-harness/specs/service-storage/spec.md` — **change-side
|
||
domain delta (`## ADDED Requirements`), 28 requirements SS-101…SS-128.**
|
||
- `openspec/specs/service-storage/spec.md` — **canonical spec (new domain), 28 requirements.**
|
||
- `openspec/changes/service-storage-harness/sync-report.md` — this report.
|