Stage 1: project foundation (strict TS, lint boundaries B-1..B-7, directory structure, CI, boundary tests)
- dedicated git repo at /home/avi/Projects/Lumen (main)
- TypeScript strict (target ES2022, bundler, exactOptionalPropertyTypes, noUncheckedIndexedAccess)
- ESLint 9 + typescript-eslint strictTypeChecked + eslint-plugin-boundaries for B-1..B-7, no-restricted-globals/syntax for B-1/B-7
- Prettier 3.5
- Structure per IMPLEMENTATION-CONTRACT.md §4 (src/platform/idb|cache|sw, storage, data, sync/{transport,verifier}, domain/{emergency,schedule,map,festival,readiness,clock,favorites}, ui/{components,views,router,render}, app, emergency-baseline, assets, public, content, pipeline, tests, scripts)
- CI: .github/workflows/ci.yml (typecheck + lint + format + test)
- Boundary tests: tests/unit/boundaries.test.ts (4 tests) + scripts/check-boundaries.ts
- No feature code, no PWA/IDB/sync/mesh/accounts per contract Stage 1
This commit is contained in:
commit
c0bfd413ff
100 changed files with 9863 additions and 0 deletions
98
SPIKE-07-BOOTSTRAP.md
Normal file
98
SPIKE-07-BOOTSTRAP.md
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# SPIKE-07 — Installation & Bootstrap
|
||||
|
||||
- **Phase:** Architecture Validation
|
||||
- **Date:** 2026-08-30
|
||||
- **Decisions under test:** ADR-002 (installed-first PWA) and the bootstrap
|
||||
design in ARCH §11/§12 (C-16, C-17).
|
||||
- **Outcome:** confirmed; introduces explicit preparation levels (L0–L2) and
|
||||
the Minimum Safe Experience definition.
|
||||
|
||||
## 1. Intended journey
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["Discovery: QR / link / poster / word of mouth"] --> B["First visit (online): shell loads ~1 MB, SW registers"]
|
||||
B --> C["Install coach (iOS manual steps; Android native prompt)"]
|
||||
C --> D["Preparation: 'Get festival data'"]
|
||||
D --> E["Data acquisition: pointer → manifest → sections (priority order) → assets; resumable"]
|
||||
E --> F["Validation: signature → hashes → schema → atomic activation"]
|
||||
F --> G["OFFLINE READY ✓ confirmation + status chip"]
|
||||
G --> H["Festival use: everything offline; sync opportunistic when online"]
|
||||
|
||||
C -. skip/dismiss .-> D
|
||||
E -. interrupted .-> P["PARTIAL state; resume later"]
|
||||
P --> E
|
||||
```
|
||||
|
||||
Stage persistence: after first visit the shell is cached (SW); after prep each
|
||||
section is staged/committed independently; favorites persist from first
|
||||
creation. No stage depends on completing later stages.
|
||||
|
||||
## 2. Preparation levels (new, normative)
|
||||
|
||||
| Level | Contents | Meaning | Chip state |
|
||||
|---|---|---|---|
|
||||
| **L0** | Shell + embedded emergency floor | "Emergency works, nothing else" | NOT_READY (or BASELINE_ONLY if storage blocked) |
|
||||
| **L1 — Minimum Safe** | L0 + dataset `emergency` section + `schedule` section | Core festival survival: emergency detail + what's on when | PARTIAL → "core ready" note |
|
||||
| **L2 — Full** | L1 + `map` + `info` + all required assets | Complete promise | READY |
|
||||
|
||||
Download order is exactly `emergency → schedule → info → map-base → assets`,
|
||||
so an interrupted prep always yields the highest achievable level. The prep UI
|
||||
names the levels ("Emergency ready", "Schedule ready", "Map ready") so users
|
||||
always know what they have.
|
||||
|
||||
## 3. Failure-point analysis
|
||||
|
||||
| # | Failure | Architecture behavior | User experience |
|
||||
|---|---|---|---|
|
||||
| FP-1 | **User doesn't install** (esp. iOS tab) | Works while open; storage eviction risk after 7 days of tab inactivity (ITP); coach re-surfaces | Coach + honest note: "install to keep your festival data" |
|
||||
| FP-2 | **User closes browser mid-prep** | Staged files + progress persist; nothing activated prematurely | Resume banner next open; prep continues where it stopped |
|
||||
| FP-3 | **Internet lost during prep** | Downloads pause; partial staged data retained; app remains fully usable for installed levels | "Paused — you have Emergency + Schedule so far" |
|
||||
| FP-4 | **Insufficient storage** | `storage.estimate()` pre-check refuses staging if free < 2× package; QuotaExceeded handled | Plain guidance: free space / reinstall; L0/L1 still possible if a full package can't fit — prep offers partial (sections only, skip heavy assets) as degraded option |
|
||||
| FP-5 | **iOS install flow fails / user can't find Add to Home Screen** | Step-by-step coach with images; retry detection (still in tab after coach); fallback: continue in Safari with eviction warning | No dead end: app works in tab, warns about persistence |
|
||||
| FP-6 | **User arrives unprepared** | App boots to whatever exists (L0 floor minimum); honest status; one-tap prep if any connectivity appears; organizer physical fallback for critical info | No blank screen; explicit "what's missing" list |
|
||||
| FP-7 | **User clears browser data / uninstalls PWA** | Everything local is gone; floor returns only after shell reloads from network; RECOVERY state otherwise | Re-prep path; nothing to do offline except reload shell when online |
|
||||
| FP-8 | **Private browsing session** | Storage probes fail early → BASELINE_ONLY mode with explanation; no crash, no fake READY | "Offline saving unavailable in this mode" + install/normal-mode guidance |
|
||||
|
||||
Additional adjudications:
|
||||
- **Prep before install (iOS tab) is allowed** and valuable: data staged in tab
|
||||
storage survives until eviction; install later preserves it (same origin).
|
||||
The coach therefore offers "install first (recommended)" *and* "get data now".
|
||||
- **First-visit ordering:** shell precache completes before prep is offered, so
|
||||
L0 is guaranteed before any dataset work begins.
|
||||
- **Leaving prep early is never punished:** no state is invalidated by
|
||||
abandonment; the worst case is staying at the current level.
|
||||
|
||||
## 4. Minimum Safe Experience (normative)
|
||||
|
||||
For an attendee who **never completed offline preparation**, the app must
|
||||
still provide, in this order of guarantees:
|
||||
|
||||
1. **Always (after any successful shell load):** the emergency floor — dial
|
||||
action, address/coordinates, security contact, muster points, core
|
||||
procedures (L0). This is Ring-0 and requires no storage.
|
||||
2. **If any prep succeeded even partially:** whatever levels completed, each
|
||||
fully functional (L1 core = emergency detail + schedule).
|
||||
3. **Honest status at all times:** the chip and status screen state exactly
|
||||
which levels are met and what to do about the rest.
|
||||
4. **No feature silently pretends:** map/info screens for missing sections show
|
||||
"not downloaded" cards with the prep action, not broken UI.
|
||||
|
||||
Product/ops corollary (cannot be solved by architecture alone): distribution
|
||||
before arrival (OQ-3) and physical fallback info at the venue remain necessary
|
||||
for the unprepared minority.
|
||||
|
||||
## 5. Cross-checks
|
||||
|
||||
- Readiness mapping: L0↔NOT_READY/BASELINE_ONLY, L1↔PARTIAL, L2↔READY
|
||||
(SPIKE-05 taxonomy).
|
||||
- Emergency floor independence from storage (SPIKE-06) makes L0 unconditional.
|
||||
- Install-first persistence reality (SPIKE-01 §3.12) motivates the coach but
|
||||
tab usage is never blocked.
|
||||
|
||||
## 6. Verdict
|
||||
|
||||
**ACCEPT WITH CHANGES.** Bootstrap architecture stands; changes: formal L0–L2
|
||||
levels with the fixed download order, Minimum Safe Experience definition, and
|
||||
the tab-install sequencing rule (allow prep before install). ADR-002 addendum
|
||||
records the levels; no direction change.
|
||||
Loading…
Add table
Add a link
Reference in a new issue