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:
Lumen Stage1 2026-08-30 23:25:35 -05:00
commit c0bfd413ff
100 changed files with 9863 additions and 0 deletions

View file

View file

@ -0,0 +1,5 @@
# tests/device-matrix
Manual protocols per ARCHITECTURE-VALIDATION.md §4 (19×4).
Stage 1: directory exists with .gitkeep; no feature code yet per IMPLEMENTATION-CONTRACT.md Stage 1. See IMPLEMENTATION-CONTRACT.md §4 responsibilities and §6 B-1…B-7.

0
tests/e2e/.gitkeep Normal file
View file

5
tests/e2e/README.md Normal file
View file

@ -0,0 +1,5 @@
# tests/e2e
Headless/offline harness.
Stage 1: directory exists with .gitkeep; no feature code yet per IMPLEMENTATION-CONTRACT.md Stage 1. See IMPLEMENTATION-CONTRACT.md §4 responsibilities and §6 B-1…B-7.

View file

View file

@ -0,0 +1,5 @@
# tests/integration
Full update lifecycle mocked transport + fault injection 9 stages, exp2 model.
Stage 1: directory exists with .gitkeep; no feature code yet per IMPLEMENTATION-CONTRACT.md Stage 1. See IMPLEMENTATION-CONTRACT.md §4 responsibilities and §6 B-1…B-7.

0
tests/unit/.gitkeep Normal file
View file

5
tests/unit/README.md Normal file
View file

@ -0,0 +1,5 @@
# tests/unit
Verifier, ClockService, readiness predicate, escaping, floor forward-tolerant.
Stage 1: directory exists with .gitkeep; no feature code yet per IMPLEMENTATION-CONTRACT.md Stage 1. See IMPLEMENTATION-CONTRACT.md §4 responsibilities and §6 B-1…B-7.

View file

@ -0,0 +1,70 @@
import { describe, it, expect } from "vitest";
import { readdirSync, existsSync } from "node:fs";
import { join } from "node:path";
function walkFiles(dir: string, exts = [".ts", ".js"]): string[] {
const out: string[] = [];
function walk(d: string) {
if (!existsSync(d)) return;
for (const e of readdirSync(d, { withFileTypes: true })) {
const p = join(d, e.name);
if (e.isDirectory()) walk(p);
else if (exts.some((ext) => p.endsWith(ext))) out.push(p);
}
}
walk(dir);
return out;
}
describe("architectural boundaries — Stage 1 gate (B-1…B-7)", () => {
it("src/ contains no feature code yet (only READMEs/.gitkeep)", () => {
const tsFiles = walkFiles("src", [".ts"]);
// Stage 1 must have zero feature .ts files — directories exist but are empty
expect(tsFiles).toEqual([]);
});
it("directory structure matches IMPLEMENTATION-CONTRACT.md §4", () => {
const requiredDirs = [
"src/platform/idb",
"src/platform/cache",
"src/platform/sw",
"src/storage",
"src/data",
"src/sync/transport",
"src/sync/verifier",
"src/domain/emergency",
"src/domain/schedule",
"src/domain/map",
"src/domain/festival",
"src/domain/readiness",
"src/domain/clock",
"src/domain/favorites",
"src/ui/components",
"src/ui/views",
"src/ui/router",
"src/ui/render",
"src/app",
"src/emergency-baseline",
"public",
"content",
"pipeline",
"tests/unit",
"tests/integration",
"tests/device-matrix",
];
for (const d of requiredDirs) expect(existsSync(d), `missing dir ${d}`).toBe(true);
});
it("forbidden v1 scope is not present (§2 — mesh/accounts/auth)", () => {
const allFiles = [...walkFiles("src"), ...walkFiles("tests")].join("\n");
expect(allFiles).not.toMatch(/mesh/i);
expect(allFiles).not.toMatch(/auth/i);
});
it("eslint boundaries config exists and lists B-1…B-7 elements", async () => {
// eslint check is via lint job; dynamic import of .js config has no types
// @ts-expect-error — no types for flat config
const cfg: unknown = await import("../../eslint.config.js");
expect(cfg).toBeDefined();
});
});