mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-09-21 00:21:30 +00:00
* feat(ingestion): shadow-mode parity harness + static dashboard (#923, RFC #909 Ring 2 PKG) Side-car observability for the RFC #909 registry rollout. Callers that dual-run legacy-DAG + `Registry.lookup` feed their result pairs into the harness; the harness diffs each pair via shared `diffResolutions` (#918), aggregates via `aggregateDiffs`, and persists a per-language parity report that the static dashboard can render offline. ## Shipped ### `gitnexus/src/core/ingestion/shadow-harness.ts` (new) ```ts createShadowHarness(): ShadowHarness ``` API: - `enabled` — `true` iff `GITNEXUS_SHADOW_MODE` is truthy at construction. Captured once; later env-var mutations don't flip it. - `record({ language, callsite, legacy, newResult, primary })` — accumulator. No-op when `enabled === false` (near-zero overhead). - `size()` — diagnostic counter. - `snapshot(now?)` — deterministic `ShadowParityReport` from the accumulated diffs. - `persist(outputDir, now?)` — writes BOTH a timestamped `<runId>.json` and a `latest.json` pointer. Creates outputDir if absent. Returns the per-run file path. - `clear()` — resets the accumulator; preserves `enabled`. Activation: `GITNEXUS_SHADOW_MODE` accepts `'true'` / `'1'` / `'yes'` (case-insensitive, trimmed); same truthy convention as `REGISTRY_PRIMARY_<LANG>` from #924. Typos → disabled (fail-safe). Persisted payload (`PersistedShadowReport`) is schema-versioned (`v1`): ```jsonc { "schemaVersion": 1, "runId": "YYYYMMDD-HHMMSS-xxxxxxxx", "generatedAt": "ISO 8601", "primaryByLanguage": { "python": "legacy", ... }, "report": { /* ShadowParityReport from #918 aggregateDiffs */ } } ``` `runId` prefix is the timestamp so files sort chronologically; the entropy suffix prevents collisions within a clock-second. ### `gitnexus/shadow-parity-dashboard/index.html` (new) Minimal static dashboard — one HTML file, zero build step, zero runtime deps. Fetches `./latest.json` and renders: - Overall summary cards (total calls, both agree, disagree, overall parity %) - Per-language table: language tag ("primary: legacy" / "primary: registry" pill) + total / agree / only-legacy / only-new / disagree / both-empty / parity% - Parity cells colored by threshold: ≥95% green, ≥80% amber, <80% red - Light / dark via `prefers-color-scheme` - Empty-state message when no records yet File-serving is static: `cp .gitnexus/shadow-parity/latest.json gitnexus/shadow-parity-dashboard/` + open in a browser. ## Tests (14, all passing) - **Flag detection** (5): default off · truthy variants case-insensitive · falsy / typo → off · record() is no-op when disabled · env flip AFTER construction doesn't enable (constructed-once semantics) - **Record + snapshot** (4): multi-language accumulation · per-language rows with correct outcomes · snapshot determinism · `clear()` resets accumulator + `primaryByLanguage` - **Persistence** (5): mkdir-p on missing outputDir · per-run + latest.json match byte-for-byte · schema v1 payload shape · runId timestamp prefix sorts chronologically · empty report persists gracefully Tests use a per-test tmpdir (`fs.mkdtemp`), cleaned in `afterEach`, so parallel vitest runs don't collide. `GITNEXUS_SHADOW_MODE` is saved + restored per-test. ## What's deliberately NOT in this PR (call-out in harness docstring) - **Dual-run dispatch.** The harness is a side-car — it does NOT invoke either resolution path. Call-processor integration that actually runs both legacy + registry paths lands as a follow-up. Without that integration, `record()` is never called in production today. The harness is tested in isolation with synthetic inputs. - **CI artifact publishing.** Config work to upload `latest.json` + the dashboard HTML per CI run. Tracked separately; the harness + dashboard are ready when the CI job wires in. - **Fixture-level drill-down.** The issue mentions per-fixture AST snippet + evidence trace drill-down. MVP dashboard shows per-language rows only; drill-down extends the static JSON format + the dashboard JS in a focused follow-up. ## Verification - `tsc --noEmit` clean (both `gitnexus-shared` and `gitnexus`) - 14/14 new tests pass - Full scope-resolution / shadow / model / flag suite: **335/335 pass** ## Part of - Parent: #909 - Depends on (code): #917 (registries), #918 (diff + aggregate) - Unblocks Ring 3 language flips: the parity dashboard becomes the checkpoint before flipping `REGISTRY_PRIMARY_<LANG>=true` for a language — once per-language parity stabilizes, the flip ships. * chore: prettier format on shadow-parity-dashboard index.html |
||
|---|---|---|
| .. | ||
| index.html | ||