This commit is contained in:
parent
8e71537d57
commit
fcc18ddcc8
96 changed files with 8074 additions and 214 deletions
56
pipeline/emergency.ts
Normal file
56
pipeline/emergency.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* Emergency unified derivation — floor + dataset section from same source sheet.
|
||||
* Ensures no drift (ARCH 10.3, ARCH 13.1).
|
||||
* Trace: ADR-007, SPIKE-06, IMPLEMENTATION-CONTRACT.md §14, ARCHITECTURE-DESIGN.md:345, §10.3
|
||||
*/
|
||||
import type { EmergencySource } from "./types.js";
|
||||
import type { EmergencyFloor } from "../src/emergency-baseline/types.js";
|
||||
import { FLOOR_SIZE_BUDGET } from "../src/emergency-baseline/types.js";
|
||||
import { canonicalJson } from "./canonical-json.js";
|
||||
import { sha256HexOfString } from "./hash.js";
|
||||
import { checkFloorSize } from "./budgets.js";
|
||||
|
||||
export function deriveEmergencyFloor(
|
||||
source: EmergencySource,
|
||||
opts: { floorVersion: string; generatedAt: string },
|
||||
): { floor: EmergencyFloor; bytes: number; sha256: string } {
|
||||
// Summaries per ARCH 13.1 T1 floor contents — derive from same source
|
||||
const floor: EmergencyFloor = {
|
||||
floor: true,
|
||||
floorVersion: opts.floorVersion,
|
||||
emergencySchemaVersion: source.emergencySchemaVersion,
|
||||
generatedAt: opts.generatedAt,
|
||||
sourceContentVersion: source.contentVersion,
|
||||
services: source.services,
|
||||
address: source.address,
|
||||
musterPoints: source.locations.musterPoints.map((m) => ({ name: m.name })),
|
||||
exits: source.locations.exits.map((e) => ({ name: e.name })),
|
||||
aedSummary:
|
||||
source.locations.aeds.length > 0
|
||||
? `AEDs: ${source.locations.aeds.length} locations`
|
||||
: "AED on site",
|
||||
procedures: source.procedures.map((p) => ({ id: p.id, title: p.title, steps: [...p.steps] })),
|
||||
};
|
||||
const json = canonicalJson(floor);
|
||||
const bytes = new TextEncoder().encode(json).length;
|
||||
const check = checkFloorSize(bytes);
|
||||
if (!check.ok) throw new Error(check.reason);
|
||||
if (bytes > FLOOR_SIZE_BUDGET) throw new Error(`floor exceeds 16KB budget: ${bytes}`);
|
||||
const sha256 = sha256HexOfString(json);
|
||||
return { floor, bytes, sha256 };
|
||||
}
|
||||
|
||||
export function validateEmergencySource(
|
||||
source: EmergencySource,
|
||||
): { ok: true } | { ok: false; reason: string } {
|
||||
if (!source) return { ok: false, reason: "emergency source missing" };
|
||||
if (!Number.isInteger(source.emergencySchemaVersion) || source.emergencySchemaVersion < 1)
|
||||
return { ok: false, reason: "emergencySchemaVersion must be integer >=1" };
|
||||
if (!Number.isInteger(source.contentVersion) || source.contentVersion < 1)
|
||||
return { ok: false, reason: "contentVersion must be integer >=1" };
|
||||
if (typeof source.updatedAt !== "string" || Number.isNaN(Date.parse(source.updatedAt)))
|
||||
return { ok: false, reason: "updatedAt must be ISO8601" };
|
||||
if (source.section !== "emergency") return { ok: false, reason: "section must be emergency" };
|
||||
// services/address/procedures presence checked via runtime validation in gates; keep light here
|
||||
return { ok: true };
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue