# P2 Design: Parity & Resilience Polish **Purpose:** Defines scope, boundaries, and acceptance criteria for P2 work before implementation begins. **Owner:** Development Team **Last Updated:** 2025-12-22 **Status:** design-only (no implementation) **Baseline:** `v1.0.11-p0-p1.4-complete` --- ## Purpose This document defines the **scope, boundaries, and acceptance criteria** for P2 work **before any implementation begins**. It ensures P2: - Does not violate established invariants - Has clear "done" criteria - Can be executed incrementally - Maintains the stability achieved in P0/P1.4/P1.5 --- ## P2 Scope Definition ### What P2 Includes **P2.6 — Type Safety Cleanup** - Replace TypeScript `any` with `unknown`/generics where appropriate - Improve type safety without changing runtime behavior - Maintain backward compatibility **P2.7 — System Invariants Documentation** - Document all enforced invariants - Explain "why" behind policy-as-code - Create onboarding reference for contributors **P2.x — Parity & Resilience Polish** - P2.1: Schema versioning strategy (iOS explicit versioning) - P2.2: Combined edge case tests (iOS: DST + duplicate delivery + cold start) - P2.3: Android combined edge case tests (achieve parity with iOS P2.2) ### What P2 Excludes - **No new features** — P2 is polish, not expansion - **No architectural changes** — Core structure remains unchanged - **No breaking API changes** — Backward compatibility required - **No new platforms** — Focus on existing iOS/Android/Web - **No new dependencies** — Minimize external additions --- ## Invariants That Must Not Be Violated ### 1. Packaging Invariants (P0) **Enforced by:** `verify.sh` → `check_package()` - `npm pack --dry-run` must not contain forbidden files: - `xcuserdata/`, `*.xcuserstate`, `DerivedData/` - `ios/App/`, `.DS_Store`, `*.swp`, `*.swo`, `*.orig`, `*.rej` - `package.json.files` whitelist must remain authoritative - `.npmignore` is secondary (belt-and-suspenders only) **P2 Constraint:** Any P2 changes must not introduce new forbidden file patterns or break packaging checks. --- ### 2. Core Module Purity (P1.4) **Enforced by:** `verify.sh` → `check_core_source()` + `check_core_artifacts()` - `src/core/` must not import: - Node builtins (`fs`, `path`, `os`, `child_process`, etc.) - Platform-specific modules (`@capacitor/*`, `react`, `capacitor`) - `package.json.exports['./core']` must exist and point to valid artifacts - Core types must remain platform-agnostic **P2 Constraint:** P2.6 type safety work must not introduce platform dependencies into core. --- ### 3. CI Authority (P0) **Enforced by:** `ci/README.md` (policy-as-code contract) - `./ci/run.sh` is the **only** supported CI entrypoint - All gates (release, merge, automation) must call `./ci/run.sh` - `npm run build` must not be called directly in gates **P2 Constraint:** P2 work must not bypass CI or create alternative entrypoints. --- ### 4. Export Correctness (P0) **Enforced by:** `verify.sh` → `check_build()` - `package.json.exports["./web"]` paths must match actual build artifacts - `package.json.exports["./core"]` paths must match actual build artifacts - All exported paths must exist after build **P2 Constraint:** P2.6 type changes must not break export paths or artifact generation. --- ### 5. Documentation Structure (P1.5) **Enforced by:** `docs/00-INDEX.md` (index-first rule) - New docs must be linked from `docs/00-INDEX.md` or placed in `_archive/`/`_reference/` - Progress docs are authoritative (no drift) - Archive structure standardized (`docs/_archive/`) **P2 Constraint:** P2.7 SYSTEM_INVARIANTS.md must be added to index and follow drift guard format. --- ### 6. Baseline Tag Integrity **Baseline:** `v1.0.11-p0-p1.4-complete` - This tag represents a known-good architectural baseline - All invariants enforced in tooling - Documentation structure established **P2 Constraint:** P2 work must not invalidate the baseline or require rollback to it. --- ## P2 Work Items (Detailed) ### P2.6: Type Safety Cleanup **Goal:** Replace `any` with `unknown`/generics where appropriate, improving type safety without changing runtime behavior. **Scope:** - Audit all `any` usages in `src/` (excluding test files initially) - Categorize by risk: - **Low risk:** Type guards with `unknown`, generic constraints - **Medium risk:** API boundaries, error handling - **High risk:** Core module types, public interfaces - Prioritize: Core module → Public interfaces → Internal code **Constraints:** - Must not break existing TypeScript compilation - Must not change runtime behavior - Must maintain backward compatibility - Must pass all existing tests **Acceptance Criteria:** - [x] Zero `any` in `src/core/` (except where truly necessary, documented) - [x] Public interfaces (`src/definitions.ts`, `src/index.ts`) use `unknown`/generics - [x] All changes pass `npm run build` and `npm test` - [x] No new type errors introduced - [x] Existing tests pass unchanged **Exit Criteria:** - [x] Type safety improved measurably (grep `any` count reduced to zero except documented exception) - [x] No runtime behavior changes - [x] All CI checks pass - [x] Documentation updated (changelog, status, test runs) **Status:** ✅ Complete (2025-12-22) --- ### P2.7: System Invariants Documentation **Goal:** Create a single authoritative document that names, explains, and references all enforced invariants. **Scope:** - Document all invariants listed in "Invariants That Must Not Be Violated" above - For each invariant: - **What:** Clear statement of the invariant - **Why:** Rationale (why it exists, what it prevents) - **How:** How it's enforced (tooling, process, documentation) - **Where:** References to enforcing code/docs - Include onboarding guidance for new contributors **Constraints:** - Must reference existing policy-as-code (not duplicate it) - Must be added to `docs/00-INDEX.md` under "Policy & Contracts" - Must follow drift guard format (Purpose, Owner, Last Updated, Status) **Acceptance Criteria:** - [ ] `docs/SYSTEM_INVARIANTS.md` created with all invariants documented - [ ] Each invariant has: What, Why, How, Where - [ ] Document added to `docs/00-INDEX.md` - [ ] Drift guard header present - [ ] References to enforcing code are accurate and up-to-date **Exit Criteria:** - Single source of truth for all invariants - New contributors can understand "what not to break" - Document is discoverable via index --- ### P2.x: Parity & Resilience Polish **Goal:** Address remaining parity gaps and add resilience tests for edge cases. #### P2.1: Schema Versioning Strategy **Current State:** - Android: Room migrations (explicit versioning) - iOS: CoreData auto-migration (implicit, may need explicit strategy) **Scope:** - Define explicit schema versioning strategy for iOS - Document migration contract (what changes require version bumps) - Add version tracking to CoreData model (metadata or attribute) - Ensure Android and iOS versioning strategies are equivalent in practice - **Clarification:** Schema version is a logical contract, not a forced migration trigger. CoreData auto-migration remains authoritative; version mismatches are logged, not blocked. **Constraints:** - Must not break existing data - Must support forward compatibility - Must be testable - Must not interfere with CoreData auto-migration **Acceptance Criteria:** - [ ] iOS schema versioning strategy documented (with explicit "logical contract" clarification) - [ ] Version tracking implemented in CoreData model (metadata or attribute) - [ ] Migration contract defined (when to bump versions) - [ ] Version check utility added (logs version on init, does not block) - [ ] Tests verify version handling (if version tracking implemented) - [ ] Parity matrix updated (schema versioning: ✅ Explicit) --- #### P2.2: Combined Edge Case Tests **Current State:** - Individual edge cases tested (DST, duplicate delivery, cold start) - Combined scenarios not explicitly tested **Scope:** - Create test scenarios that combine multiple edge cases: - DST boundary + duplicate delivery + cold start - Rollover + migration + recovery - Network failure + rollover + cold start - Ensure idempotency and correctness in combined scenarios **Constraints:** - Must not duplicate existing test coverage unnecessarily - Must be runnable in CI (or clearly marked as manual) - Must be deterministic **Acceptance Criteria:** - [ ] At least 3 combined edge case test scenarios - [ ] Tests verify idempotency in combined scenarios - [ ] Tests pass in CI or are clearly documented as manual - [ ] Test results logged in `docs/progress/03-TEST-RUNS.md` --- #### P2.3: Android Combined Edge Case Tests **Current State:** - iOS: ✅ Automated combined edge case tests (P2.2 complete) - Android: ⚠️ Manual emulator scripts only, no automated combined scenarios **Scope:** - Enable Android test infrastructure (currently disabled in `build.gradle`) - Create test helpers (in-memory Room database, test data injection) - Add automated combined edge case tests mirroring iOS P2.2: - DST boundary + duplicate delivery + cold start - Rollover + duplicate delivery + cold start - Schema version + cold start recovery (optional) - Use CI-compatible testing framework (JUnit + Robolectric or pure unit tests) **Constraints:** - Must be CI-compatible (JVM-compatible, no emulator required) - Must use modern AndroidX testing framework (not deprecated APIs) - Tests only, no production code changes - Must not break existing functionality **Acceptance Criteria:** - [ ] Android test infrastructure enabled and CI-compatible - [ ] Test helpers created (database factory, data injection) - [ ] At least 2 combined test scenarios implemented (3 if time permits) - [ ] Tests verify idempotency in combined scenarios - [ ] Tests pass in CI (or clearly documented as manual) - [ ] Parity matrix updated with direct test references - [ ] Test results logged in `docs/progress/03-TEST-RUNS.md` **See:** `docs/progress/P2.3-DESIGN.md` for detailed design and execution plan. --- ## P2 Execution Strategy ### Phase Ordering **Recommended sequence (P2.6/P2.7 already complete):** 1. **P2.1 First (Doc-first approach)** - Write documentation first - Then add minimal code (logging/metadata) - Update parity matrix immediately after - **Checkpoint:** Run `./ci/run.sh`, update progress docs, only then proceed 2. **P2.2 Second (Tests)** - Start with 2 scenarios - Add 3rd only if time/energy allows - Label tests explicitly as resilience/combined-scenarios - **Checkpoint:** Run `./ci/run.sh`, update progress docs **Previous phases (complete):** - **P2.7** — Document invariants before making changes ✅ - **P2.6** — Type safety cleanup ✅ ### Incremental Approach - Each P2 item can be completed independently - No dependencies between P2.6, P2.7, and P2.x - Each item has its own acceptance criteria - Can pause/resume at any item boundary ### Testing Strategy - **P2.6:** Existing tests must pass unchanged - **P2.7:** Documentation review (no code changes) - **P2.x:** New tests required, existing tests must pass --- ## P2 "Done" Criteria ### Overall P2 Completion P2 is complete when: 1. **All P2 items completed** (P2.6, P2.7, P2.x) 2. **All invariants preserved** (verified by CI) 3. **All acceptance criteria met** (per item) 4. **Documentation updated** (progress docs, index, changelog) 5. **Baseline tag created** (if desired: `v1.0.11-p2-complete`) ### Individual Item Completion Each P2 item is complete when: - [ ] Acceptance criteria met - [ ] CI passes (`./ci/run.sh`) - [ ] No invariant violations - [ ] Documentation updated (if applicable) - [ ] Progress docs updated --- ## Risk Mitigation ### Risk: Breaking Existing Functionality **Mitigation:** - All changes must pass existing tests - Incremental approach (one file/feature at a time) - CI gates prevent regressions ### Risk: Violating Invariants **Mitigation:** - P2.7 documents invariants first - CI enforces invariants automatically - Design review before implementation ### Risk: Scope Creep **Mitigation:** - Clear "what P2 excludes" section - Acceptance criteria defined upfront - Can pause/resume at item boundaries ### Risk: Documentation Drift **Mitigation:** - P2.7 creates invariant documentation - Progress docs updated per item - Index updated per P1.5 rules --- ## Success Metrics ### Quantitative - **P2.6:** `any` usage count reduced (target: 50%+ reduction in `src/core/` and public interfaces) - **P2.7:** All invariants documented (target: 100% coverage) - **P2.x:** Combined edge case tests added (target: 3+ scenarios) ### Qualitative - **Type safety:** Code is more maintainable, fewer runtime type errors possible - **Documentation:** New contributors understand invariants quickly - **Resilience:** Edge cases are better understood and tested --- ## Dependencies ### External Dependencies - None — P2 is self-contained polish work ### Internal Dependencies - **P2.7 → P2.6/P2.x:** Invariant documentation helps validate other work - **P2.6 → P2.x:** Type improvements may help P2.x implementation ### Blocking Dependencies - None — P2 can start immediately after P1.5 --- ## Timeline Estimate **P2.7:** 2-4 hours (documentation only) **P2.6:** 8-16 hours (incremental type cleanup) **P2.x:** 16-32 hours (varies by item complexity) **Total:** 26-52 hours (can be spread over multiple sessions) **Note:** These are estimates. Actual time depends on codebase complexity and test coverage. --- ## Next Steps (After Design Approval) 1. **Review this design** — Ensure scope and constraints are correct 2. **Approve invariants list** — Confirm nothing is missing 3. **Prioritize P2 items** — Decide execution order 4. **Begin P2.7** — Document invariants first (recommended) 5. **Execute incrementally** — One item at a time, pause/resume as needed --- **Last Updated:** 2025-12-22 **Status:** Design-Only (No Implementation) **Next Action:** Review and approve design before proceeding