CI's web job runs bare `corepack enable && pnpm install --frozen-lockfile`
with no explicit pnpm version, so without a `packageManager` field corepack
can resolve a different pnpm than the one that generated the lockfile
(lockfileVersion 9, requires pnpm 9+) — that's what broke the first CI run.
Also drops @vite-pwa/sveltekit, left over from an earlier approach abandoned
in favor of the base vite-plugin-pwa plugin (see vite.config.ts) and no
longer imported anywhere.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Phase 0 scaffolding for the frontend: SvelteKit + adapter-static in SPA mode
(fallback index.html, ssr disabled in the root layout — no Node process in
production, Caddy serves build/ directly per docs/PLAN.md), a login page and
auth store backed by /api/v1/auth/{login,me,logout}, an installable-PWA shell
(hand-written manifest, iOS meta/safe-area handling, an install-onboarding
banner), and a Dockerfile whose only job is to produce a buildable /app/build
artifact for deploy/ to consume.
Service worker notes, since the wiring isn't obvious from the diff:
- injectManifest, not generateSW: the caching policy needs to say "never
cache /api/*", which generateSW's declarative config can't express as
precisely as hand-written Workbox routes can.
- Uses the base `vite-plugin-pwa` plugin, not `@vite-pwa/sveltekit`'s
SvelteKit-specific wrapper. That wrapper's injectManifest build expects
SvelteKit's own built-in src/service-worker.{js,ts} convention to have
already transpiled the file — but that native build only permits importing
SvelteKit's own three virtual modules and hard-rejects `workbox-*` imports,
which our SW needs. The base plugin bundles src/service-worker.ts directly
instead, which works. SvelteKit's native service-worker convention is
explicitly disabled (`kit.files.serviceWorker` pointed at a path that
doesn't exist) so the two builds can't collide and silently clobber each
other's output — they do, if both are left enabled, and the failure mode is
silent (the SW builds fine, just precaches nothing).
- workbox-core/precaching/routing/strategies had to be added as direct
devDependencies even though workbox-build depends on them — pnpm doesn't
hoist transitive deps into the top-level node_modules, so the SW bundle
step couldn't resolve them otherwise.
- The SPA fallback index.html doesn't exist yet at service-worker-build time
(adapter-static writes it after all Vite plugins finish), so it can't be
glob-hashed into the precache manifest normally. It gets a synthetic
manifest entry instead, revisioned by a per-build-invocation timestamp
(see the swIndexRevision comment in vite.config.ts) so the cached shell
still invalidates correctly on every deploy.
Full rationale for each choice is inline as comments in vite.config.ts and
apps/web/README.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Prepares the repo for parallel agent work. No application code.
- CLAUDE.md: conventions, branch naming, and the six non-negotiable
invariants from the design (immutable raw bytes, no stored odometers,
SI integers, dual-layer user isolation, secret containment, single
ingestion path). Also records a model-allocation policy: the
orchestrator runs Opus 5, workers default to Sonnet, and Opus is
reserved for review plus the areas where a mistake is silent and
expensive (ingest, wear SQL, auth/RLS, the Bryton protocol client).
And the Gitea Actions gotchas, so nobody rediscovers them:
GITEA_TOKEN cannot push to the container registry, jobs.*.environment
is ignored, and cron needs a workflow_dispatch pair.
- CONTRIBUTING.md: day-to-day flow, worktrees for parallel branches,
review expectations.
- .gitea/workflows/ci.yml: repo hygiene (branch naming, secret scan,
no ride data in git), plus API/web/migration jobs that guard on whether
the code exists yet, so CI is meaningful now and grows into the real
thing rather than being rewritten.
- .gitea/PULL_REQUEST_TEMPLATE.md: forces an honest "how this was
verified" and an invariant checklist.
- scripts/pr.sh, scripts/review.sh: open and inspect PRs via the Gitea API.
- Directory scaffold with placeholder READMEs.
Agents open PRs; humans merge them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>