Move to openspec/changes/archive/2026-07-09-grafana-metric-gateway/ (R100 renames preserved). 9 artifacts. Canonical openspec/specs/ prometheus-charting/ (30 reqs, first non-additive sync) remains. Carry-overs in archive-report: SC-106 stale component name (cosmetic); partial revert of prometheus-direct-charting per new network constraint.
16 KiB
Archive Report — grafana-metric-gateway
Phase: archive · Change:
grafana-metric-gateway· Repo:/home/user/manageMode: file-backed (artifactStore: openspec). No source-code edits; only OpenSpec artifacts were touched. Not committed — the parent/orchestrator owns the archive commit. No push, nogh.
Status: ARCHIVED. All eight lifecycle phases are complete (proposal → spec → design → tasks →
apply → verify → sync → archive). Every archive precondition is verified PASS (see §2). The
canonical openspec/specs/prometheus-charting/spec.md (updated by sdd-sync with the project's
first non-additive delta — 16 MODIFIED + 3 ADDED) remains in place as the durable end-state spec and
is not moved (archive never moves canonical specs). The change folder was moved to
openspec/changes/archive/2026-07-09-grafana-metric-gateway/ via git mv to preserve history.
0. Archive disposition
- Disposition:
archived. The parent explicitly requested thegit mvand owns the commit, so the move is executed here and left staged for the parent's explicit-path commit. - Archive convention: OpenSpec SDD archive contract for
openspecmode — completed file-backed sync → write the in-folder archive report → move the change folder toopenspec/changes/archive/YYYY-MM-DD-{change}/. No standalone manifest/index exists underopenspec/(onlyconfig.yaml,changes/,specs/), so the folder move is the archive mechanism. Norules.archiveoverride exists inopenspec/config.yaml. - Target archived path:
openspec/changes/archive/2026-07-09-grafana-metric-gateway/ - Archive date:
2026-07-09(ISO). - Canonical spec left in place (not moved):
openspec/specs/prometheus-charting/spec.md— 30 requirements (SC-101 … SC-130). Verified present and untouched after the move. openspec/specs/web-ui/spec.mdandopenspec/specs/service-storage/spec.mdalso left untouched (the other canonical domains).- Audit-trail integrity: the change folder was moved as a whole, including the legacy flat
spec.md, the per-domain deltaspecs/prometheus-charting/spec.md,apply-progress.md,verify-report.md, andsync-report.md, which travel with the record. Nothing was silently deleted or rewritten.
1. Native sdd-status read & discrepancy statement
The native gentle-pi.sdd-status engine supplied by the parent reports non-actionable state for
this archive because it was resolved without a change context: changeName: null,
artifacts: all missing, applyState: blocked, dependencies.archive: blocked,
blockedReasons: ["Change selection is ambiguous: grafana-metric-gateway, per-instance-hook-scoping, service-credential-tester."], isNonAuthoritative: false. This is a parent-resolution artifact:
the engine auto-detected three active changes and could not pick one. The ambiguity does not
reflect the state of grafana-metric-gateway, which this archive task was explicitly assigned.
Discrepancy with the parent's authoritative confirmed state — RESOLVED in favor of the parent.
The parent physically verified (and this executor re-confirmed directly against the filesystem in
§2) that all 33 tasks are ticked, apply-progress.md exists and records the work, the verify report
confirms functional completion, and the sync report confirms a SYNCED canonical domain. Per the
archive contract's non-authoritative-store carve-out guidance and the parent's explicit instruction,
the stale archive: blocked / "ambiguous" labels are disregarded and the archive proceeds.
Direct filesystem re-validation (§2) is the source of truth for this report.
2. Archive preconditions (validated directly against the filesystem)
| Precondition | Evidence | Result |
|---|---|---|
| Verify report present | verify-report.md |
✓ verdict PASS (functionally complete) |
Verify clearly passing — no unresolved FAIL/BLOCKED/CRITICAL |
the sole CRITICAL was a reconcilable task-hygiene gap (33 unchecked boxes + missing apply-progress.md), now resolved; GM-115 was PARTIAL on enumerated test-coverage only (non-critical), treated as closed per parent confirmation (15/16 PASS → 16/16) |
✓ |
| Sync report present & successful | sync-report.md → Status: SYNCED |
✓ |
| Canonical spec exists (sync target, updated) | openspec/specs/prometheus-charting/spec.md (30 requirements, SC-101 … SC-130) |
✓ |
| Change-side domain delta exists | specs/prometheus-charting/spec.md (16 MODIFIED + 3 ADDED) |
✓ |
| Delta op-class = non-additive (MODIFIED + ADDED; no REMOVED) | MODIFIED=16, ADDED=3, REMOVED=0, RENAMED=0 | ✓ |
| Requirement-ID parity | canonical 30 = 27 retained + 3 ADDED; contiguous SC-101 … SC-130, no gaps/dupes | ✓ |
| proposal / design / tasks artifacts present | all populated | ✓ |
Final Task Completion Gate — zero unchecked - [ ] |
grep -nE '^\s*- \[ \]' tasks.md → NONE; grep -cE '^\s*- \[x\]' → 33 |
✓ |
apply-progress.md present & records the work |
present; status "complete — all 33 tasks done", 2 slices documented | ✓ |
No active same-domain (prometheus-charting) collision |
sameDomainActiveChanges: [], collisions: [] (per sync-report §2); only this change carries a prometheus-charting delta |
✓ |
Stale-checkbox reconciliation note. At verify time, all 33 implementation/verification checkboxes
(Slice 1 §1.1–1.16, Slice 2 §2.1–2.11, Integration §3.1–3.6) were unchecked and apply-progress.md
did not exist. That condition was reconciled before archive: the boxes are now all ticked and
apply-progress.md was authored documenting the two landed slices (df80c68, 7e91e7f) and the
gate results. apply-progress.md plus the verify report prove every previously-unchecked task
complete. No archive-time mechanical checkbox repair was needed — the gate now passes on the
persisted tasks.md as-is. No partial-archive approval applies.
3. Artifacts read (archive preflight)
openspec/changes/grafana-metric-gateway/proposal.mdopenspec/changes/grafana-metric-gateway/spec.md(flat, authoritative planning artifact — 16 requirements GM-101 … GM-116)openspec/changes/grafana-metric-gateway/specs/prometheus-charting/spec.md(change-side domain delta)openspec/changes/grafana-metric-gateway/design.mdopenspec/changes/grafana-metric-gateway/tasks.mdopenspec/changes/grafana-metric-gateway/apply-progress.mdopenspec/changes/grafana-metric-gateway/verify-report.mdopenspec/changes/grafana-metric-gateway/sync-report.mdopenspec/specs/prometheus-charting/spec.md(canonical, sync target — verified present and untouched)openspec/config.yaml(rules: proposal/tasks; norules.archiveoverride)- House-style reference:
openspec/changes/archive/2026-07-08-prometheus-direct-charting/archive-report.md
The legacy flat
spec.mdis not the only spec artifact: a per-domain delta (specs/prometheus-charting/spec.md) and a canonical spec both exist, so the "legacy flat spec as the only artifact" archive-block condition does not apply. The flat spec travels with the archived folder as part of the audit trail.
4. Domains synced & requirement delta
| Domain | Change-side delta | Canonical | Action |
|---|---|---|---|
prometheus-charting |
specs/prometheus-charting/spec.md |
openspec/specs/prometheus-charting/spec.md |
MODIFIED + ADDED — 16 requirement blocks replaced in place by exact ID; 3 new requirements appended |
- MODIFIED (16) — transport & naming requirements replaced in place by exact SC- ID: SC-101,
SC-102, SC-103, SC-104, SC-105, SC-107, SC-109, SC-111, SC-112, SC-114, SC-115, SC-116, SC-121,
SC-122, SC-125, SC-126. These switch the data source from direct Prom (
/api/v1/query[_range]) to the GrafanaPOST /api/ds/querygateway, and re-scope the "no grafana references" requirements to "no grafana service type" (transport refs now allowed). - ADDED (3) — fresh canonical IDs continuing the SC- sequence: SC-128 (
get_prometheus_statusvalidates the full gateway path), SC-129 (startup logs old-shape prometheus config without crashing), SC-130 (Grafana is the sanctioned transport for the prometheus service). - PRESERVED (11) — unchanged in canonical, not in the delta: SC-106, SC-108, SC-110, SC-113, SC-117, SC-118, SC-119, SC-120, SC-123, SC-124, SC-127.
- REMOVED (0) · RENAMED (0) — nothing destructive.
This is the project's first non-additive canonical sync. The MODIFIED-heavy delta was approved in the parent dispatch (explicitly identified as "the project's first non-additive sync," with the exact SC-xxx to modify enumerated). See §7.
5. Final lifecycle status (all 8 phases done)
| Phase | Status | Evidence |
|---|---|---|
| Proposal | ✅ done | proposal.md |
| Spec | ✅ done | flat spec.md (16) + domain delta specs/prometheus-charting/spec.md (16 MODIFIED + 3 ADDED) |
| Design | ✅ done | design.md |
| Tasks | ✅ done | tasks.md — 33/33 checked, zero - [ ] |
| Apply | ✅ done | 2 slices delivered (commits df80c68 slice-1 backend, 7e91e7f slice-2 frontend renames) |
| Verify | ✅ PASS | verify-report.md — 15/16 PASS, GM-115 PARTIAL-on-coverage (closed per parent; effectively 16/16); gates green |
| Sync | ✅ done | sync-report.md — SYNCED; canonical prometheus-charting domain MODIFIED + ADDED (now 30 requirements) |
| Archive | ✅ done | this report + folder move performed |
6. Gate results (per verify-report / apply-progress)
| Gate | Command | Result |
|---|---|---|
| Backend tests | cd backend && PYTHONPATH=src python3 -m pytest -q |
PASS — 331 passed (2 pre-existing warnings) |
| Backend lint | cd backend && PYTHONPATH=src python3 -m ruff check src tests |
PASS — All checks passed |
| Frontend build | cd frontend && npm run build |
PASS — exit 0 (pre-existing chunk-size advisory) |
| Frontend lint | cd frontend && npm run lint |
PASS — 0 errors (1 pre-existing unrelated warning) |
| Frontend tests | cd frontend && npx vitest run |
PASS — 151 passed / 44 files |
7. Carry-over follow-ups & non-blocking notes (recorded for the record)
- [COSMETIC — deferred fix] Preserved SC-106 still names
PrometheusChartWidget. SC-106 was explicitly listed as PRESERVED (not MODIFIED) in this change's "Canonical delta intent", so it was left verbatim in the canonical spec. It reads: "…preserved in the rebrandedPrometheusChartWidget." This change renames that component toMetricChartWidget(GM-111), so the component name in that one canonical block is now stale. The intent — recharts renderer (line chart, multi-series, axes, tooltip,mergeSeries, color tokens) reused unchanged — remains true. This is purely a cosmetic carry-over; a future change may refresh the name if desired. Not blocking. - [INFO — first non-additive sync] The first non-additive canonical sync is complete. 16
MODIFIED + 3 ADDED + 0 REMOVED were applied to
openspec/specs/prometheus-charting/spec.mdby exact-ID block replacement. All 16 MODIFIED headers matched the canonical spec exactly (zero mismatches); the canonical spec now has 30 requirements (SC-101 … SC-130, contiguous). No destructive REMOVED requirements were used, so no destructive-removal guard was triggered. The MODIFIED-heavy delta was approved in the parent dispatch. - [INFO — partial revert of
prometheus-direct-charting] This change partially reverts the archivedprometheus-direct-charting(2026-07-08). A new network constraint surfaced afterprometheus-direct-chartingshipped: the Prometheus instance is not directly reachable from the Manage backend (firewalled / different network / no auth proxy); Grafana is the only reachable surface. This change undoes that change's direct-Prom transport and Grafana removal (re-routing all metric queries through Grafana'sPOST /api/ds/querydatasource proxy, restoring thenormalize_grafana_framesnormalizer recovered from git commit65bae95), while preserving its durable gauge/mean/LineSeriesChart/rendering work. It is a justified reversal based on new information, not a fourth flip of preference. The canonicalprometheus-chartingdomain now reflects the gateway transport (Grafana = transport; Prometheus = logical source). Theprometheusservice type remains the sole metric surface — nografanaservice type is reintroduced. - [VERIFY carry-over] GM-115 was PARTIAL in verify on enumerated test-coverage only (no
startup-validation test; no status 401/403 →
auth_failedtest). Functional code is correct and green; the parent confirmed this as closed (effectively 16/16). The new SC-128 (status gateway path) and SC-129 (startup validation) canonicalize this behavior; two small follow-up tests may be added in a future change. - [INFO]
normalize_prometheus_matrixis intentionally retained as dead production code (future-proof for a possibledirect_urlpath); canonicalized by the MODIFIED SC-102. - [INFO] Stale generated
.pi-map.mdartifacts still reference oldPrometheus*Widgetnames; not deliverable source (ignored by tsc/vite/eslint) — regenerate viaproject_map_patch/project_map_validateat the orchestrator's convenience. Not touched by this archive. - [INFO] The working tree carries unrelated dirty/untracked items not owned by this archive:
a whitespace-only uncommitted modification to
frontend/src/pages/ServicesPage.tsx(predating/ orthogonal to this change) and untracked.pi-tmp/*scratch files (other-change strays). Per discipline these were left untouched.
8. Residual risks & destructive-merge statement
- Destructive sync / merge: none destructive. Zero REMOVED requirements; the 16 MODIFIED blocks replaced transport/naming requirements in place by exact ID with the durable behavior preserved. The MODIFIED-heavy non-additive delta was approved in the parent dispatch (explicit "first non-additive sync" identification + enumerated SC-xxx). No destructive-removal guard was triggered.
- Backend / data-contract impact: none new beyond the documented operator migration. All
Prometheus metric queries are gated behind Grafana's
/api/ds/querywith zero direct-Prom HTTP residue inwidgets/sources.py. Old-shapeprometheusservices (withbase_url) warn on startup and returngrafana_url is requirederrors until reconfigured — the intended degraded state, with the required operator action documented in the CHANGELOG. The{series}/{value}widget data shapes are preserved. Archive touched only OpenSpec docs + the folder move. - No critical verification issues remain (CRITICAL issues are non-overridable; the one verify CRITICAL was the reconcilable checkbox/apply-progress gap, now resolved).
- No browser/visual smoke was performed (out of scope); recharts rendering is structurally tested only.
- Memory observation IDs: none —
artifactStore: openspec; traceability lives in the filesystem archive + canonical spec.
9. Move performed
git mv openspec/changes/grafana-metric-gateway openspec/changes/archive/2026-07-09-grafana-metric-gateway
- All 9 artifacts confirmed present at the archived path:
proposal.md,spec.md,specs/prometheus-charting/spec.md(delta),design.md,tasks.md,apply-progress.md,verify-report.md,sync-report.md,archive-report.md(this file). - Canonical
openspec/specs/prometheus-charting/spec.mdremains in place (verified untouched after the move).openspec/specs/web-ui/spec.mdandopenspec/specs/service-storage/spec.mdalso untouched. - Renames were left staged (R100 detection preserved) for the parent's explicit-path commit.
git restore --stagedwas not run after thegit mv(a prior archive agent did so and discarded rename detection).
Appendix — Files written/moved by this archive (OpenSpec only; no source code)
- Written:
openspec/changes/grafana-metric-gateway/archive-report.md(this file) — at the active path before the move; travels with the move into the archive. - Moved (via
git mv): the entireopenspec/changes/grafana-metric-gateway/directory →openspec/changes/archive/2026-07-09-grafana-metric-gateway/. - Left in place (durable canonical):
openspec/specs/prometheus-charting/spec.md. - Not committed / not pushed — the parent owns the commit with explicit paths.