Skip to content

PR-RPS-5: Improvement Project V1 — engine layer (types + persistence + store + .vrs + D18 primitives)#150

Merged
jukka-matti merged 12 commits into
mainfrom
response-path-system-v1
May 10, 2026
Merged

PR-RPS-5: Improvement Project V1 — engine layer (types + persistence + store + .vrs + D18 primitives)#150
jukka-matti merged 12 commits into
mainfrom
response-path-system-v1

Conversation

@jukka-matti
Copy link
Copy Markdown
Owner

Engine-only PR for ImprovementProject per Response Path System V1 spec §3 D8/D9 + §11 D18. No UI surface yet — that lands in PR-RPS-6.

What this delivers

  • ImprovementProject type tree in @variscout/core with multi-level Y/X/x Goal (D9)
  • IMPROVEMENT_PROJECT_* HubAction kinds (CREATE / UPDATE / ARCHIVE) with locked deep-merge contract
  • ProcessHub.improvementProjects?: ImprovementProject[] hydrated optional field
  • PWA persistence: dedicated Dexie table on schema v1, 3 handlers, joinHub hydration, HUB_PERSIST_SNAPSHOT decomposition
  • Azure persistence: dedicated Dexie table on v10 (clean break, new empty table — no upgrade callback), 3 handlers byte-for-byte symmetric to PWA, AzureHubRepository.dispatch decomposes IP into the dedicated table within a single transaction; hubs.get/list hydrate
  • useImprovementProjectStore Document-layer Zustand store (STORE_LAYER='document', no persist middleware) — 4-method API: setProjectsForHub, getProjectsForHub, upsertProject, removeProject
  • .vrs round-trip tests covering populated, legacy (no field), and empty-array hubs
  • D18 live-document primitives: computeSourceHash + shouldShowDrift (pure logic in @variscout/core) and useLiveProjection (memoized FK→entity hook in @variscout/hooks)

Locked deep-merge contract (IMPROVEMENT_PROJECT_UPDATE)

Documented as JSDoc on the action type and implemented identically in PWA + Azure handlers:

  • objects shallow-merge one level: metadata, goal, signoff, and the four sections keys
  • nested metadata.financialImpact and goal.outcomeGoal also shallow-merge
  • sections shallow-merges per sub-section key — missing keys preserved from existing
  • arrays REPLACE wholesale (metadata.team[], goal.factorControls[], goal.mechanismGoals[], all FK arrays inside sections.*)
  • id, createdAt, hubId, deletedAt, updatedAt excluded from the patch type at compile time
  • updatedAt set by handler to Date.now()

The patch type itself is Partial<Omit<ImprovementProject, 'id' | 'createdAt' | 'hubId' | 'updatedAt' | 'deletedAt' | 'sections'>> & { sections?: Partial<ImprovementProject['sections']> } so partial-sections patches type-check and the documented contract is enforced.

Tests

Package Δ Total
@variscout/core +11 3347
@variscout/stores +10 248
@variscout/hooks +4 1160
@variscout/pwa +10 301
@variscout/azure-app +14 1253

bash scripts/pr-ready-check.sh green. pnpm --filter @variscout/ui build green.

Migration / back-compat

Per spec §8/§9 strict no-back-compat. PWA stays on Dexie v1 (table appended to existing version block); Azure bumps 9 → 10 with a new empty improvementProjects table — no upgrade callback needed; existing dev IDBs get the new table on next open. .vrs files written by older versions import cleanly with improvementProjects undefined (test coverage in serialization/__tests__/roundtrip.test.ts).

Followups deferred (non-blocking)

  • T1 test imports from ../types rather than ../index (precedent issue, low-impact)
  • T4 hubs.get returns plain hub when only archived IPs exist — not reachable from PR-RPS-5; PR-RPS-6 should either avoid the trigger or read archived IPs into the round-trip
  • T5 nextByHub local annotation cosmetic; T7 distinct-hash test for null vs undefined

Plan

docs/superpowers/plans/2026-05-09-response-path-system-v1.md lines 1559–1844. Spec at docs/superpowers/specs/2026-05-09-response-path-system-v1-design.md. Unblocks PR-RPS-6 (6-section IP UI).

Test plan

  • pnpm test green in all 6 packages
  • bash scripts/pr-ready-check.sh green
  • pnpm --filter @variscout/ui build green
  • pnpm --filter @variscout/pwa build green
  • pnpm --filter @variscout/azure-app build green
  • Symmetric deep-merge implementation verified (PWA + Azure)
  • HUB_PERSIST_SNAPSHOT decomposition integration tests on both apps
  • .vrs round-trip preserves IPs (rich + minimal + empty + legacy)

🤖 Generated with ruflo

jukka-matti and others added 11 commits May 9, 2026 22:37
…ATE patch + clarify sections deep-merge JSDoc

Co-Authored-By: ruflo <ruv@ruv.net>
…ia HUB_PERSIST_SNAPSHOT

Co-Authored-By: ruflo <ruv@ruv.net>
…mprovementProjects table (v10)

Co-Authored-By: ruflo <ruv@ruv.net>
…spatch fixture

Critical-1: update AzureHubRepository.test.ts fixture to include improvementProjects
on the dispatched hub so the saveProcessHubToIndexedDB assertion actually exercises
the decomposition path (previous fixture had no IPs, making hubWithoutIP === hub
structurally and the assertion vacuously pass).

Critical-2: add AzureHubRepository.snapshot.test.ts — real-Dexie integration tests
(fake-indexeddb/auto) that verify the decomposition contract end-to-end: hub blob
stored without IPs, IPs written to dedicated table, empty/absent IP arrays leave
table empty, and stale IPs absent from the new snapshot are deleted.

Co-Authored-By: ruflo <ruv@ruv.net>
…ections contract + type Azure mocks

`IMPROVEMENT_PROJECT_UPDATE` patch.sections is now `Partial<ImprovementProject['sections']>`
so callers can supply a single sub-section key without TS2739. Matches the JSDoc shallow-merge
contract and the test fixtures in both persistence handler suites.

Azure mock signatures updated to `vi.fn<(hub: ProcessHub) => Promise<void>>()` /
`vi.fn<(action: HubAction) => Promise<void>>()` so mock.calls[0][0] destructuring
(TS2493 / TS2352) resolves correctly.

Added a compile-time test in exhaustiveness.test.ts documenting the partial-sections
contract at the type level.

Co-Authored-By: ruflo <ruv@ruv.net>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mean-beoynd-lite-pwa Ready Ready Preview, Comment May 10, 2026 9:55am
variscout_website Ready Ready Preview, Comment May 10, 2026 9:55am

@jukka-matti jukka-matti merged commit 29ff5a8 into main May 10, 2026
3 checks passed
@jukka-matti jukka-matti deleted the response-path-system-v1 branch May 10, 2026 10:10
jukka-matti added a commit that referenced this pull request May 13, 2026
…80, log shipment

All 10 PRs of Response Path System V1 merged on main 2026-05-09 → 2026-05-13
(#144 / #147 / #148 / #149 / #150 / #151 / #152 / #153 / #154 / #155). This
commit syncs tracking docs that the squash merges left stale:

- docs/roadmap.md: PR-RPS-9 + PR-RPS-10 SHIPPED rows; flip §3 to "10 of 10";
  free up ADR-080 slot from the 8f canvas viewport item (taken by Sustainment)
- docs/decision-log.md: pin "2026-05-13 — RPS V1 SHIPPED — full lifecycle live"
- docs/07-decisions/adr-080-sustainment-auto-fire-pattern.md (new): document
  the Sustainment-shaped lifecycle pattern (auto-fire + Inbox prompt +
  signoff tier gate) as a pattern reference for future response-path
  lifecycles, per plan §PR-RPS-9 ledger line 2231
- docs/07-decisions/index.md: add rows 078 / 079 / 080 (078+079 also weren't
  indexed when shipped)
- Spec + plan frontmatter: draft/active → delivered, last-reviewed 2026-05-13

Co-Authored-By: ruflo <ruv@ruv.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant