Files
manage/openspec/changes/archive/2026-07-09-per-instance-hook-scoping/sync-report.md
Developer 29650ca512 chore(per-instance-hook-scoping): archive verified+synced change
Move to openspec/changes/archive/2026-07-09-per-instance-hook-scoping/
(R100 renames preserved). 9 artifacts. Canonical openspec/specs/
service-instance-scoping/ remains. Resolves multi-instance wrong-data bug
(hooks now scope by instance.id; instance switcher re-scopes).
Carry-overs: fetchBackupDashboard untouched (design decision 5); subquery
scoping for runs/alerts (schema asymmetry).
2026-07-10 00:17:51 +00:00

12 KiB

Sync Report — per-instance-hook-scoping

Phase: sync · Change: per-instance-hook-scoping · 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). The flat spec.md was left in place as the authoritative planning artifact.

Status: SYNCED. A new canonical domain openspec/specs/service-instance-scoping/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 per-instance-hook-scoping change shipped a complete but flat openspec/changes/per-instance-hook-scoping/spec.md (21 requirements, PI-101 … PI-121) with no per-domain delta spec under openspec/changes/per-instance-hook-scoping/specs/<domain>/. sdd-sync requires a domain delta spec; the flat spec alone does not satisfy the canonical-merge contract (native status engine reported specs: partial, blockedReasons: "domain specs are missing or partial" + "Legacy flat spec is present without domain specs").

Verify already returned PASS (verdict in verify-report.md; all five gates green — backend pytest 368 passed, ruff clean, frontend npm run build exit 0, npm run lint 0 errors, npx vitest run 46 files / 165 tests passed). Functional coverage was 21/21 requirements satisfied against source. The verify report's single CRITICAL was an archive blocker (17 unchecked task checkboxes + missing apply-progress.md); per the dispatch brief, apply-progress.md has since been reconciled and that 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 specopenspec/changes/per-instance-hook-scoping/specs/service-instance-scoping/spec.md — using a pure ## ADDED Requirements structure that preserves the exact requirement IDs (PI-101 … PI-121) and body text (including the per-requirement GIVEN/WHEN/THEN scenarios) 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 storeopenspec/specs/service-instance-scoping/spec.md — the actual sync target. Because the canonical service-instance-scoping 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 carry identical requirement bodies (delta under ## ADDED Requirements; canonical under ## Requirements), verified identical for the requirement region.

Domain name service-instance-scoping was chosen (per the dispatch brief) because it names the cross-cutting concern the change establishes: observability and backup service-type tabs/hooks must scope to the operator-selected instance. It is distinct from the existing canonical domains (web-ui, prometheus-charting, service-storage, service-credential-testing), none of which were touched.

2. Structured status & actionContext findings

The native gentle-pi.sdd-status reports state: blocked, artifactStore: openspec, taskProgress: 17/17 complete, applyState: blocked, and blockedReasons citing missing domain specs + legacy flat spec present without domain specs. These blockers are artifact-hygiene, not implementation gaps: the code is committed (3bc7ce5), all five gates are green, and 21/21 requirements pass against source. This sync resolves the missing-domain-spec condition; the remaining applyState/checkbox hygiene is an archive-phase concern.

  • artifactStore: openspec; change root openspec/changes/per-instance-hook-scoping/.
  • Artifacts present: proposal.md, spec.md (flat), design.md, tasks.md, verify-report.md, apply-progress.md.
  • verify: PASS (verify-report verdict; gates green at 3bc7ce5).
  • 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-instance-scoping domain is distinct from the existing web-ui, prometheus-charting, service-storage, and service-credential-testing canonical domains; all four were left untouched.

Post-sync structural change: openspec/changes/per-instance-hook-scoping/specs/service-instance-scoping/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-instance-scoping openspec/changes/per-instance-hook-scoping/specs/service-instance-scoping/spec.md openspec/specs/service-instance-scoping/spec.md NEW domain## ADDED Requirements copied into canonical as a new spec
  • Canonical file created: openspec/specs/service-instance-scoping/spec.md (21 requirements).
  • Change-side delta created: openspec/changes/per-instance-hook-scoping/specs/service-instance-scoping/spec.md (21 requirements, all ## ADDED Requirements).

4. Requirement delta (ADDED / MODIFIED / REMOVED)

  • ADDED (21) — all to the new service-instance-scoping domain (canonical did not exist pre-change). IDs and text preserved verbatim from the verified flat spec.md. Grouped logically:
    • Frontend hooks (serviceId param + queryKey) — PI-101, PI-102, PI-103, PI-104, PI-105, PI-106, PI-107
    • API client functions (serviceId → query param) — PI-108, PI-109
    • Backend backup endpoints (service_id filter) — PI-110, PI-111, PI-112
    • Tabs pass instance.id (TODO comments removed) — PI-113, PI-114, PI-115, PI-116
    • Non-regression (dashboard widgets, global hooks untouched) — PI-117
    • Backward compatibility — PI-118
    • Test + build greenness — PI-119, PI-120, PI-121
  • 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-instance-scoping domain does not overlap the existing web-ui, prometheus-charting, service-storage, or service-credential-testing 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 for this sync beyond the explicit reconciliation instruction in the dispatch brief.
  • 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.
  • Canonical isolation: the existing openspec/specs/web-ui/spec.md, openspec/specs/prometheus-charting/spec.md, openspec/specs/service-storage/spec.md, and openspec/specs/service-credential-testing/spec.md were not modified — verified untouched (see §6).

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 3bc7ce5):

Check Command Result
Canonical store populated ls openspec/specs/service-instance-scoping/spec.md present ✓
Change-side domain spec present ls openspec/changes/per-instance-hook-scoping/specs/service-instance-scoping/spec.md present ✓
Requirement-ID parity (flat ↔ delta ↔ canonical) grep -oE 'PI-[0-9]+' all three files, sort -u 21 == 21 == 21, identical IDs PI-101…PI-121 ✓
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,prometheus-charting,service-storage,service-credential-testing}/ empty (not modified) ✓
No edits outside openspec git status --porcelain (filtered) only the three new OpenSpec files added; no source files touched ✓
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] Task-checkbox / apply-progress hygiene. At verify time, 17 implementation task checkboxes were unchecked and apply-progress.md was missing. Per the dispatch brief, apply-progress.md has been reconciled (native status now reports 17/17 complete); sdd-archive should re-scan the native status engine to confirm apply: done / applyProgress: present and tick any remaining unchecked boxes before moving the change to archive.
  2. [INFO, NB-1] Spec↔design wording mismatch on PI-109 / PI-110. The flat spec literally lists fetchBackupDashboard / get_backup_dashboard as in-scope for a new service param, while design decision 5 and tasks 1.5/1.9 deliberately exclude them (dashboard widget path; PI-117 risk). The implementation correctly follows the design. This delta/canonical preserved the flat spec text verbatim (PI-109 / PI-110 still mention the dashboard variants) per the sync fidelity rule (do not rewrite verified requirements during sync). If sdd-archive wants spec and design to agree, it can amend in a follow-up change; no functional defect.
  3. [INFO, NB-2] Weak hook-test assertion (PI-121). The useBackups.test.ts "different keys" assertion (expect(a).not.toBe(b) on renderHook result refs) is tautology-prone. The wiring is correct in source and the tab test is strong; recommend strengthening the hook test in a future pass. Non-blocking.
  4. [INFO] Stale generated .pi-map.md files still reference the pre-change signatures (e.g. list_backup_jobs(self) without service_id). Generated artifacts, not deliverable source; reconcile via project_map_patch / project_map_validate when convenient.

sdd-archive (clean). Confirm the native status re-scan reports specs: done / sync: ready / archive: ready, then move the change to openspec/changes/archive/YYYY-MM-DD-per-instance-hook-scoping, 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/per-instance-hook-scoping/specs/service-instance-scoping/spec.mdchange-side domain delta (## ADDED Requirements), 21 requirements PI-101…PI-121.
  • openspec/specs/service-instance-scoping/spec.mdcanonical spec (new domain), 21 requirements.
  • openspec/changes/per-instance-hook-scoping/sync-report.md — this report.