All requirements met. All tests passing. No breaking changes. System is v2-ready.
- Contract explicitly states observational purpose
- No field implies release decisions
- No configuration or thresholds
- No filtering, suppressing, or judging importance
- All evidence preserved in the map
- No mode switching or complexity layers
Verification:
contracts/service-maps.contract.mdclearly documents observational naturesrc/lib/service-maps/builder.tsdoes aggregation only (P95, error rates)- No decision logic in builder
- No conditional behavior based on architecture
- Service Map diff's
criticalPathfield explicitly marked non-normative - Field is null by default (not computed in v1)
- Documentation states derived fields never imply decisions
- Separation between observed and derived is explicit
Verification:
contracts/service-maps-diff.contract.mdsection "DERIVED FIELDS (NON-NORMATIVE)"src/lib/service-maps/types.ts:criticalPath: CriticalPathInfo | null;with commente2e/run-canaries.cjs:criticalPath: null,in diff builder
- New contract file created
- Types defined in TypeScript
- Builder function implemented
- Persisted to
artifacts/service-maps/{buildId}.diff.json - Included in dashboard report
- Diff-specific visualization in dashboard
Verification:
contracts/service-maps-diff.contract.md- Full specificationsrc/lib/service-maps/types.ts- All diff types definede2e/run-canaries.cjs- Diff building and persistencedashboard/app.js- Diff rendering function- Output: Diffs written every build
- Determinism test validates replay (Test 8)
- Hash computation ensures validation
- Same buildId + observations → same map → same hash
- Same buildId + maps → same diff → same hash
- Canonical ordering enforced
Verification:
tests/service-maps-determinism.cjsTest 8: ✓ Pass- All 22 determinism tests pass
- Hash format: 64-char SHA256 hex
-
src/gating/release-gate.tsunchanged - Gating inputs remain: canary + risk only
- No Service Maps in gating decision path
- Gating logic called before Service Maps built
- Exit codes controlled by gates, not maps
- No breaking changes to canary behavior
Verification:
src/gating/release-gate.ts- Original logic intacte2e/run-canaries.cjsline 649:const gate = gateRelease(...);BEFORE Service Mapse2e/run-canaries.cjslines 677+: Service Maps built AFTER gating- Release-gate.json written independently
- Zero configuration required
- Service Maps built automatically
- Diffs built automatically
- Network observation automatic in canary
- No user setup needed
- Fails silently if network observation unavailable
- No new environment variables required
Verification:
- Canary runs with zero config
- Service Maps and diffs created every build
- Network observations collected passively
- No configuration files introduced
- Diff is sole input for future gates
- Contracts frozen and immutable
- No reprocessing of raw data (gates use diff)
- Determinism enables replay and audit
- Separation prevents accidental coupling
- Architecture prepared for safe gating
Verification:
contracts/service-maps-diff.contract.mdexplicitly prepared for v2- Diff generation deterministic and reproducible
- No additional refactoring needed for v2 gating
- Future gates simply add:
evaluateServiceMapGate(diff: ServiceMapDiff)
Test 1: Deterministic hash for identical inputs ✓
Test 2: Different inputs produce different hashes ✓
Test 3: Deterministic diff generation ✓
Test 4: Diff accurately captures added nodes ✓
Test 5: Diff accurately captures removed nodes ✓
Test 6: Diff accurately captures latency changes ✓
Test 7: Diff accurately captures error rate changes ✓
Test 8: Replay produces identical map ✓
Test 9: No baseline produces all-added diff ✓
Test 10: Deterministic ordering with shuffled input ✓
✓ All 22 tests passed
Test 1: Basic Service Map with successful requests ✓
Test 2: Service Map with error responses ✓
Test 3: Multiple service nodes ✓
Test 4: Empty observations ✓
Test 5: P95 latency calculation ✓
Test 6: Deterministic ordering ✓
✓ All 6 unit tests passed
TypeScript (types.ts, builder.ts): ✓ OK
JavaScript (run-canaries.cjs): ✓ OK
JavaScript (dashboard/app.js): ✓ OK
-
Updated:
contracts/service-maps.contract.md- Added hash field
- Explicit observational purpose
- Determinism guarantee
- Gating impact clarified (v1: none; v2: prepared)
-
Created:
contracts/service-maps-diff.contract.md- Complete first-class artifact specification
- Facts only (no interpretation)
- Numeric delta fields with change calculations
- Examples and scenarios
-
Updated:
src/lib/service-maps/types.ts- Added
hash: stringto ServiceMap - Created diff types: ServiceMapDiff, AddedEdge, RemovedEdge, ChangedEdge, etc.
- Added
-
Updated:
src/lib/service-maps/builder.ts- Added hash computation
- Added
buildServiceMapDiff()function - Added determinism validation functions
- All functions documented as deterministic
-
Updated:
src/lib/service-maps/index.ts- Export new diff types
- Export new diff builder function
- Export determinism validation functions
- Updated:
e2e/run-canaries.cjs- Added crypto module import
- Added
computeHash()function - Added
hashServiceMap()function - Added
buildServiceMapDiff()function - Added
loadBaseline()andsaveAsBaseline()functions - Updated
buildServiceMap()to include hash - Updated main() to:
- Load baseline
- Build and persist diff
- Pass diff to dashboard report
- Updated
buildDashboardReport()signature to include diff
-
Updated:
dashboard/app.js- Updated
renderDashboard()to render diff - Added
renderServiceMapDiff()function - Added CSS styles for diff visualization
- Clear color coding for added/removed/changed items
- Updated
-
Updated:
dashboard/index.html- Added
<div id="service-map-diff-section">
- Added
- Created:
tests/service-maps-determinism.cjs- Comprehensive test suite (22 tests)
- Tests hash determinism
- Tests diff accuracy
- Tests replay behavior
- Tests canonical ordering
- All tests passing
- Created:
SERVICE_MAPS_V1_COMPLETE.md- Implementation summary
- Architectural properties
- Component descriptions
- Test results
- v2-readiness checklist
| Component | Breaking? | Impact |
|---|---|---|
| Gating logic | ❌ No | Completely untouched |
| Canary behavior | ❌ No | Unchanged |
| Risk scoring | ❌ No | Unchanged |
| Release gate contract | ❌ No | Same inputs/outputs |
| Dashboard | ❌ No | Enhanced with new sections |
| Service Maps contract | ❌ No | Additive (hash field) |
| Existing tests | ❌ No | All still passing |
| CI/CD workflows | ❌ No | No changes needed |
| Risk | Prevention |
|---|---|
| Gating in v1 | ✅ No gating code added |
| Configuration exposure | ✅ Zero config required |
| Threshold creep | ✅ No thresholds in contracts |
| Decision logic | ✅ Not permitted by architecture |
| ML/heuristics | ✅ Deterministic only |
| Vendor lock-in | ✅ Plain JSON, no dependencies |
Evidence (Canary/Playwright)
↓
Normalize (Service Map Builder)
↓
Observe (Service Maps v1 Artifact)
↓
Change (Service Map Diff v1 Artifact)
↓
Decide (Release Gates) ← Unchanged, canary + risk only
Visualize (Dashboard) ← Enhanced, no decisions
Guarantee: No layer crosses into another's responsibility.
- All code compiles (TypeScript + JavaScript)
- All tests pass (22 determinism + 6 unit)
- No syntax errors
- No breaking changes
- Backward compatible
- MODE 0 behavior preserved
- Gating untouched
- Documentation complete
- Merge this branch
- Deploy without configuration changes
- Service Maps and diffs will build automatically
- Dashboard will show maps and diffs automatically
- Release gates remain unchanged
- If issues: revert single commit
- No state changes, safe rollback
- Gating remains unchanged
To activate Service-Map-based gating:
-
Create
src/gating/service-map-gate.tsexport function evaluateServiceMapGate(diff: ServiceMapDiff): ReleaseGateDecision { // Consume ONLY the diff // Never reprocess raw data // Be explicit, deterministic, conservative return decision; }
-
Update
src/gating/release-gate.tsto call service map gate -
No breaking changes needed
-
Diff contracts frozen—no changes required
-
All v1 artifacts remain valid
✅ Implementation Complete
- All requirements met
- All tests passing
- No breaking changes
- v2-ready architecture
✅ Verification Passed
- Determinism validated (22 tests)
- No unintended side effects
- Gating logic untouched
- MODE 0 behavior preserved
✅ Ready for Deployment
- Code compiles
- Syntax valid
- Tests green
- Documentation complete
If gating-related tickets appear before v2 activation:
- Service Maps are observational only
- Use diffs, not raw data
- Never modify contract v1
- Never add configuration
- Never add thresholds
- When in doubt, ask: "Does this blur the lines between Evidence, Change, and Decision?"
If yes → stop. That's a bug.