diff --git a/.gitignore b/.gitignore index 25f8f6f..6cebb1b 100644 --- a/.gitignore +++ b/.gitignore @@ -18,5 +18,3 @@ Thumbs.db client/.godot/ *.user *.suo -modeling/control-flow/node_modules/ -modeling/control-flow/dist/ diff --git a/AGENTS.md b/AGENTS.md index 42898f5..6afcd52 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -27,13 +27,6 @@ - Shared Quartz machinery remains owned by `GameCult/GameCult-Quartz`; do not vendor it here. - Generated output under `quartz-site/public/` is disposable and must not become source truth. -## Control-flow modeling - -- `modeling/control-flow/graph.ts` owns the typed, source-addressed map of the current executable body. Delvehold owns its semantics and provenance; Norn owns rendering behavior only. -- Any change to client, host, protocol, solution/build, or launcher control flow requires review of the affected nodes, edges, owners, and source witnesses. Admit the resulting normalized source hash only after that review. -- Run `scripts/control-flow.ps1 validate` before accepting runtime work. New executable files within the inventoried game-runtime surfaces (`client/`, `src/`, root solution/MSBuild files, and top-level runtime launchers), stale witnesses, broken graph references, and changed inventoried sources must fail this check rather than disappearing from the map. Quartz publishing belongs to the documentation body; the Norn viewer belongs to the modeling tool body. -- Graph inspection is non-mutating. A future control surface must still cross the typed Delvehold command-and-receipt boundary; selection in Norn is never gameplay authority. - ## Lore prose - Use `F:\Projects\Kalsa\workshop\review-council\critics\AI-Isms and Prose.md` as the review brief for Lore prose. Its named patterns are prompts to reread, not forbidden-token rules or quality metrics. diff --git a/Delvehold.sln b/Delvehold.sln index d37728a..a191be1 100644 --- a/Delvehold.sln +++ b/Delvehold.sln @@ -8,15 +8,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Delvehold.WorldHost", "src\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Delvehold.Client", "client\Delvehold.Client.csproj", "{F764A271-81B2-42ED-8D07-BB6C00281029}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Control Flow", "Control Flow", "{612EA672-270E-476C-9B76-B29A1CC6327B}" - ProjectSection(SolutionItems) = preProject - modeling\control-flow\graph.ts = modeling\control-flow\graph.ts - modeling\control-flow\main.tsx = modeling\control-flow\main.tsx - modeling\control-flow\package.json = modeling\control-flow\package.json - modeling\control-flow\verify.ts = modeling\control-flow\verify.ts - scripts\control-flow.ps1 = scripts\control-flow.ps1 - EndProjectSection -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/Delvehold/Documentation/Control Flow Map.md b/Delvehold/Documentation/Control Flow Map.md deleted file mode 100644 index 1228395..0000000 --- a/Delvehold/Documentation/Control Flow Map.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Control Flow Map -description: Typed, source-addressed architecture and execution graph rendered through Norn. -aliases: - - /documentation/control-flow ---- - -# Control Flow Map - -The maintained graph lives in `modeling/control-flow/graph.ts`. It separates two views: - -- **Authority body** names the runtime organs, their owners, and which edges may read, write, construct, dispatch, or render. -- **Control flow** follows executable paths through Godot startup, local projection selection, CultMesh discovery and session establishment, host startup, state seeding, entry admission branches, receipt persistence, response projection, shutdown, and verification. - -Every node and edge carries source witnesses. The source inventory covers the executable game client, host, protocol, root solution and MSBuild files, and top-level runtime launchers with normalized SHA-256 digests. Changing one of those files makes validation fail until the graph is reviewed and the new digest is explicitly admitted. New executable files inside those surfaces also fail the inventory check. Quartz publishing remains part of the documentation body; this Norn view remains part of the modeling-tool body. - -Norn owns graph layout, motion, selection, inspection, and rendering. It does not own the graph's meaning, execute control flow, or issue game commands. - -Run the integrity check and build the viewer: - -```powershell -.\scripts\control-flow.ps1 validate -``` - -Open the interactive Norn view: - -```powershell -.\scripts\control-flow.ps1 view -``` - -The viewer runs at `http://127.0.0.1:4176`. Its process ID and logs live under `artifacts/control-flow/`. diff --git a/Delvehold/Documentation/Implementation Map.md b/Delvehold/Documentation/Implementation Map.md index 9f64aeb..17a96c2 100644 --- a/Delvehold/Documentation/Implementation Map.md +++ b/Delvehold/Documentation/Implementation Map.md @@ -15,7 +15,6 @@ This page describes the body that exists in source. The [[Game Design/index|Game - `Delvehold.Client` is one Godot 4.7.2 C# application. DELVE and HOLD are views inside that application, not separate clients or authorities. - `Delvehold.Protocol` contains the typed CultMesh operation payloads shared by the client and host. It owns no state and performs no simulation. - CultLib revision `334e60f1928b4212a29dd8b0d19b2c099fe6365e` supplies CultCache, CultNet, and CultMesh. Builds reject another revision or a dirty CultLib worktree. The host targets the installed .NET 10 runtime; Godot's C# client targets its supported .NET 8 surface. -- Delvehold owns the semantic [[Control Flow Map|architecture and control-flow graph]] derived from its current source. Norn renders that typed projection and owns presentation behavior only. Selection and inspection are non-mutating; gameplay actions still cross the existing command-and-receipt boundary. ## First live path @@ -32,6 +31,6 @@ The seed state names one workshop, one commons, one dungeon core, one contract, ## Verification layer -`scripts/verify-runtime.ps1` first requires the typed control-flow graph and its Norn viewer to validate, then builds the three projects, starts the host, connects the headless Godot client, rejects an idempotency collision and an invalid projection, restarts the host against the same CultCache, and replays the original enter intent. The smoke compares the complete accepted receipt summary, including its original effective time, across both accepted calls, requires the CultCache state file to remain present, and rejects known canonical-write APIs in client source. +`scripts/verify-runtime.ps1` builds the three projects, starts the host, connects the headless Godot client, rejects an idempotency collision and an invalid projection, restarts the host against the same CultCache, and replays the original enter intent. The smoke compares the complete accepted receipt summary, including its original effective time, across both accepted calls, requires the CultCache state file to remain present, and rejects known canonical-write APIs in client source. Dungeon generation, CultMath randomness, CultGeometry isosurface extraction, gameplay mutation, and the Ghostlight boundary remain subsequent cuts. diff --git a/Delvehold/Documentation/index.md b/Delvehold/Documentation/index.md index f58858f..a02992d 100644 --- a/Delvehold/Documentation/index.md +++ b/Delvehold/Documentation/index.md @@ -7,4 +7,3 @@ The machinery beneath DELVE/HOLD: typed world state, ownership boundaries, clien - [[Authority Map|Authority map]] - [[Implementation Map|Implementation map]] -- [[Control Flow Map|Control-flow map]] diff --git a/README.md b/README.md index fcc1873..6cd6596 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,3 @@ Open the project in the Godot editor with: ```powershell .\scripts\open-godot.ps1 ``` - -Validate the source-addressed control-flow map or open its interactive Norn view: - -```powershell -.\scripts\control-flow.ps1 validate -.\scripts\control-flow.ps1 view -``` diff --git a/modeling/control-flow/graph.ts b/modeling/control-flow/graph.ts deleted file mode 100644 index 24aa3e9..0000000 --- a/modeling/control-flow/graph.ts +++ /dev/null @@ -1,292 +0,0 @@ -import type { - EpiphanyCodeRef, - NornGraphEdge, - NornGraphLink, - NornGraphNode, - NornGraphsState, -} from "@gamecult/norn-viewer"; - -export type AuthorityOwner = - | "godot-client" - | "protocol" - | "world-host" - | "cultlib" - | "verification" - | "developer-tooling" - | "modeling" - | "norn"; - -export type ControlEdgeKind = - | "calls" - | "constructs" - | "signals" - | "discovers" - | "opens-session" - | "sends-intent" - | "dispatches" - | "validates" - | "reads" - | "writes" - | "flushes" - | "returns-receipt" - | "branches" - | "replays" - | "rejects" - | "waits-for" - | "terminates" - | "verifies" - | "renders"; - -export interface OwnedGraphNode extends NornGraphNode { - owner: AuthorityOwner; - runtime: "godot" | "world-host" | "shared" | "tooling" | "external-library"; - code_refs: EpiphanyCodeRef[]; -} - -export interface TypedControlEdge extends NornGraphEdge { - id: string; - kind: ControlEdgeKind; - code_refs: EpiphanyCodeRef[]; -} - -export interface SourceSurface { - path: string; - normalizedSha256: string; - responsibility: string; -} - -const refs = { - client: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "client/Main.cs", symbol, note }), - scene: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "client/Main.tscn", symbol, note }), - project: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "client/project.godot", symbol, note }), - protocol: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "src/Delvehold.Protocol/WorldContracts.cs", symbol, note }), - host: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "src/Delvehold.WorldHost/Program.cs", symbol, note }), - world: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "src/Delvehold.WorldHost/WorldState.cs", symbol, note }), - meshClient: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "@cultlib/src/GameCult.Mesh/CultMeshClient.cs", symbol, note }), - operationServer: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "@cultlib/src/GameCult.Networking/CultNetOperationServer.cs", symbol, note }), - tcp: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "@cultlib/src/GameCult.Networking/CultNetTcpSchemaTransport.cs", symbol, note }), - cache: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "@cultlib/src/GameCult.Mesh/CultMesh.cs", symbol, note }), - verify: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "scripts/verify-runtime.ps1", symbol, note }), - controlFlow: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "scripts/control-flow.ps1", symbol, note }), - openGodot: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "scripts/open-godot.ps1", symbol, note }), - solution: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "Delvehold.sln", symbol, note }), - buildProps: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "Directory.Build.props", symbol, note }), - buildTargets: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "Directory.Build.targets", symbol, note }), - clientProject: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "client/Delvehold.Client.csproj", symbol, note }), - protocolProject: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "src/Delvehold.Protocol/Delvehold.Protocol.csproj", symbol, note }), - hostProject: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "src/Delvehold.WorldHost/Delvehold.WorldHost.csproj", symbol, note }), - graph: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "modeling/control-flow/graph.ts", symbol, note }), - graphVerify: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "modeling/control-flow/verify.ts", symbol, note }), - norn: (symbol: string, note?: string): EpiphanyCodeRef => ({ path: "@norn/web/norn-viewer/src/lib/NornViewer.tsx", symbol, note }), -}; - -const architectureNodes: OwnedGraphNode[] = [ - { id: "arch-godot-project", title: "Godot application", purpose: "Own the one DELVE/HOLD presentation process and scene lifetime.", mechanism: "Godot loads Main.tscn and attaches Main.cs to the root Control.", status: "verified", owner: "godot-client", runtime: "godot", code_refs: [refs.project("run/main_scene"), refs.scene("script = ExtResource")] }, - { id: "arch-main-control", title: "Main projection controller", purpose: "Build the current interface, select DELVE or HOLD presentation, and coordinate world entry.", mechanism: "One Godot Control owns local mode widgets and one application-lifetime CultMesh client.", status: "verified", owner: "godot-client", runtime: "godot", code_refs: [refs.client("public partial class Main")] }, - { id: "arch-cultmesh-client", title: "CultMesh client session owner", purpose: "Discover the stable world authority and reuse its typed operation session.", mechanism: "CultMeshClient owns discovery, transport connectors, reconnection, correlation, and response decoding.", status: "verified", owner: "cultlib", runtime: "external-library", code_refs: [refs.meshClient("public sealed class CultMeshClient")] }, - { id: "arch-world-contract", title: "World-entry wire contract", purpose: "Name the Verse, authority runtime, operation, and typed intent/receipt schemas without owning world state.", mechanism: "Protocol DTOs cross CultMesh; they contain no persistence or simulation authority.", status: "verified", owner: "protocol", runtime: "shared", code_refs: [refs.protocol("public static class DelveholdWorldContract"), refs.protocol("public sealed class WorldEnterIntent"), refs.protocol("public sealed class WorldEnterReceipt")] }, - { id: "arch-world-host", title: "Central world host", purpose: "Own the canonical Delvehold world process, admission boundary, and local persistence lifetime.", mechanism: "A single C# process composes CultMesh storage, TCP ingress, discovery, identity, and typed operations.", status: "verified", owner: "world-host", runtime: "world-host", code_refs: [refs.host("var settings = HostSettings.Parse(args)")] }, - { id: "arch-cultmesh-ingress", title: "CultMesh ingress", purpose: "Bind loopback transport, stable authority identity, Verse catalog, and typed operation dispatch.", mechanism: "TCP schema server carries discovery, session identity, and operation envelopes without owning domain admission.", status: "verified", owner: "cultlib", runtime: "world-host", code_refs: [refs.host("TcpFramedCultNetSchemaServer"), refs.host("CultMeshSessionIdentityServer"), refs.host("CultNetOperationServer")] }, - { id: "arch-entry-admission", title: "World-entry admission", purpose: "Validate projection, serialize idempotency decisions, and author accepted or rejected operation results.", mechanism: "One semaphore protects receipt lookup and creation; the host admits only DELVE or HOLD.", status: "verified", owner: "world-host", runtime: "world-host", code_refs: [refs.host("operationGate"), refs.host("invalid-world-entry"), refs.host("idempotency-key-collision")] }, - { id: "arch-world-state", title: "Canonical first-world state", purpose: "Own the first world identity, revision, and initial fixture identifiers.", mechanism: "WorldHost alone defines and seeds DelveholdWorldState when the canonical record is absent.", status: "verified", owner: "world-host", runtime: "world-host", code_refs: [refs.world("public sealed class DelveholdWorldState"), refs.world("FirstWorld()")] }, - { id: "arch-cultcache", title: "CultCache persistence", purpose: "Persist canonical world state and entry receipts across host lifetimes.", mechanism: "CultMeshNode exposes the typed database/cache; explicit flushes make admitted records durable.", status: "verified", owner: "cultlib", runtime: "world-host", code_refs: [refs.cache("CreateNodeAsync"), refs.host("node.Database.PutAsync"), refs.host("node.FlushAsync")] }, - { id: "arch-runtime-verifier", title: "Verification harness", purpose: "Falsify source-map integrity, connection, rejection, forbidden-writer, and restart-persistence claims.", mechanism: "A bounded PowerShell harness validates the typed map, builds three projects, and drives headless Godot against disposable host state.", status: "verified", owner: "verification", runtime: "tooling", code_refs: [refs.verify("control-flow.ps1"), refs.verify("Invoke-GodotSmoke"), refs.verify("forbiddenClientWriters"), refs.controlFlow("run build"), refs.graphVerify("DELVEHOLD_CONTROL_FLOW_INVALID")] }, - { id: "arch-developer-tooling", title: "Build and launch tooling", purpose: "Give Rider, command-line verification, and the Godot editor one admitted project graph and dependency path.", mechanism: "The conventional solution selects three projects; shared MSBuild files pin CultLib; bounded launchers start the editor and focused checks.", status: "verified", owner: "developer-tooling", runtime: "tooling", code_refs: [refs.solution("Delvehold.Client"), refs.buildProps("CultLibRevision"), refs.buildTargets("VerifyCultLibRevision"), refs.openGodot("Start-Process")] }, - { id: "arch-control-flow-map", title: "Typed control-flow map", purpose: "Publish the admitted, source-addressed semantic graph for review and rendering.", mechanism: "TypeScript narrows owners and edge kinds while carrying source witnesses and the admitted executable-source inventory.", status: "active", owner: "modeling", runtime: "tooling", code_refs: [refs.graph("export const controlFlowMap"), refs.graph("sourceInventory")] }, - { id: "arch-norn-viewer", title: "Norn inspection view", purpose: "Render authority and execution graphs for human inspection without gaining command authority.", mechanism: "The React NornViewer consumes the typed projection and owns layout, motion, selection, and detail presentation only.", status: "verified", owner: "norn", runtime: "tooling", code_refs: [refs.norn("export function NornViewer"), refs.graph("nornState")] }, -]; - -const architectureEdges: TypedControlEdge[] = [ - { id: "arch-edge-project-main", source_id: "arch-godot-project", target_id: "arch-main-control", kind: "constructs", label: "root scene", code_refs: [refs.scene("script = ExtResource")] }, - { id: "arch-edge-main-client", source_id: "arch-main-control", target_id: "arch-cultmesh-client", kind: "constructs", label: "application lifetime", code_refs: [refs.client("new CultMeshClient")] }, - { id: "arch-edge-main-contract", source_id: "arch-main-control", target_id: "arch-world-contract", kind: "sends-intent", label: "typed entry", code_refs: [refs.client("InvokeAsync")] }, - { id: "arch-edge-client-ingress", source_id: "arch-cultmesh-client", target_id: "arch-cultmesh-ingress", kind: "opens-session", label: "CultNet TCP", code_refs: [refs.meshClient("ConnectAsync"), refs.tcp("TcpFramedCultNetSchemaServer")] }, - { id: "arch-edge-ingress-admission", source_id: "arch-cultmesh-ingress", target_id: "arch-entry-admission", kind: "dispatches", label: "delvehold.world/enter", code_refs: [refs.host("Register")] }, - { id: "arch-edge-admission-world", source_id: "arch-entry-admission", target_id: "arch-world-state", kind: "reads", label: "world identity/revision", code_refs: [refs.host("node.Cache.Get")] }, - { id: "arch-edge-admission-cache", source_id: "arch-entry-admission", target_id: "arch-cultcache", kind: "writes", label: "accepted receipts only", code_refs: [refs.host("node.Database.PutAsync(receiptKey, receipt)")] }, - { id: "arch-edge-host-ingress", source_id: "arch-world-host", target_id: "arch-cultmesh-ingress", kind: "constructs", label: "one host lifetime", code_refs: [refs.host("using var server") ] }, - { id: "arch-edge-host-world", source_id: "arch-world-host", target_id: "arch-world-state", kind: "constructs", label: "seed if absent", code_refs: [refs.host("DelveholdWorldState.FirstWorld()")] }, - { id: "arch-edge-host-cache", source_id: "arch-world-host", target_id: "arch-cultcache", kind: "constructs", label: "typed store", code_refs: [refs.host("CultMesh.CreateNodeAsync")] }, - { id: "arch-edge-verifier-app", source_id: "arch-runtime-verifier", target_id: "arch-godot-project", kind: "verifies", label: "headless path", code_refs: [refs.verify("$godot --headless")] }, - { id: "arch-edge-verifier-host", source_id: "arch-runtime-verifier", target_id: "arch-world-host", kind: "verifies", label: "restart and replay", code_refs: [refs.verify("Start-WorldHost 'restart'")] }, - { id: "arch-edge-tooling-client", source_id: "arch-developer-tooling", target_id: "arch-godot-project", kind: "constructs", label: "Godot build and editor", code_refs: [refs.clientProject("Godot.NET.Sdk/4.7.2"), refs.openGodot("--editor")] }, - { id: "arch-edge-tooling-host", source_id: "arch-developer-tooling", target_id: "arch-world-host", kind: "constructs", label: "focused .NET build", code_refs: [refs.hostProject("Delvehold.Protocol"), refs.solution("Delvehold.WorldHost")] }, - { id: "arch-edge-tooling-contract", source_id: "arch-developer-tooling", target_id: "arch-world-contract", kind: "constructs", label: "shared protocol build", code_refs: [refs.protocolProject("GameCult.Caching"), refs.solution("Delvehold.Protocol")] }, - { id: "arch-edge-verifier-map", source_id: "arch-runtime-verifier", target_id: "arch-control-flow-map", kind: "verifies", label: "typed graph and source-inventory integrity", code_refs: [refs.verify("control-flow.ps1') validate"), refs.graphVerify("normalizedSha256")] }, - { id: "arch-edge-norn-map", source_id: "arch-norn-viewer", target_id: "arch-control-flow-map", kind: "renders", label: "non-mutating projection", code_refs: [refs.graph("nornState")] }, -]; - -const dataflowNodes: OwnedGraphNode[] = [ - { id: "flow-client-start", title: "Godot loads Main", purpose: "Instantiate the one client root and begin its scene lifetime.", owner: "godot-client", runtime: "godot", status: "verified", code_refs: [refs.scene("[node name=\"Delvehold\"")] }, - { id: "flow-ready", title: "Ready", purpose: "Build local presentation and begin asynchronous world entry.", owner: "godot-client", runtime: "godot", status: "verified", code_refs: [refs.client("public override void _Ready()")] }, - { id: "flow-build-ui", title: "Build interface", purpose: "Construct title, mode controls, and connection status without touching world truth.", owner: "godot-client", runtime: "godot", status: "verified", code_refs: [refs.client("private void BuildInterface()")] }, - { id: "flow-mode-select", title: "Select local projection", purpose: "Switch visible DELVE/HOLD mode labels and buttons only.", owner: "godot-client", runtime: "godot", status: "verified", code_refs: [refs.client("private void SelectProjection") ] }, - { id: "flow-enter", title: "Begin world entry", purpose: "Parse launch arguments, construct the application client, and invoke typed entry.", owner: "godot-client", runtime: "godot", status: "verified", code_refs: [refs.client("private async Task EnterWorldAsync()")] }, - { id: "flow-discovery", title: "Discover authority", purpose: "Resolve the stable Verse and world-host runtime to the current physical route.", owner: "cultlib", runtime: "external-library", status: "verified", code_refs: [refs.meshClient("RendezvousEndpoints"), refs.meshClient("ConnectOnlineAsync")] }, - { id: "flow-catalog-response", title: "Return Verse catalog", purpose: "Publish the host route and supported document protocol to discovery callers.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("CreateCatalogResponse")] }, - { id: "flow-session-open", title: "Open identity-bound session", purpose: "Establish the reusable CultMesh documents session to the world host.", owner: "cultlib", runtime: "shared", status: "verified", code_refs: [refs.meshClient("ConnectAsync(target, CultMeshProtocols.Documents") ] }, - { id: "flow-send-entry", title: "Send entry intent", purpose: "Correlate one typed WorldEnterIntent under the caller idempotency key.", owner: "cultlib", runtime: "godot", status: "verified", code_refs: [refs.client("InvokeAsync"), refs.meshClient("CultNetOperationRequestMessage")] }, - { id: "flow-host-start", title: "Start world host", purpose: "Parse state/port settings and assemble the authoritative process.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("HostSettings.Parse(args)")] }, - { id: "flow-open-state", title: "Open typed state", purpose: "Create the CultMesh node over the configured CultCache path and registries.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("CreateCultCacheDocumentRegistry"), refs.host("CultMesh.CreateNodeAsync")] }, - { id: "flow-seed-world", title: "Seed world if absent", purpose: "Create the explicit first-world record once, then flush it.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("if (node.Cache.Get(worldKey) is null)"), refs.world("FirstWorld()")] }, - { id: "flow-bind-ingress", title: "Bind CultMesh ingress", purpose: "Start TCP, identity, catalog, and operation handlers before readiness.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("DELVEHOLD_HOST_READY")] }, - { id: "flow-dispatch-entry", title: "Dispatch entry operation", purpose: "Decode the typed payload and route it to host-owned admission.", owner: "cultlib", runtime: "world-host", status: "verified", code_refs: [refs.operationServer("Register"), refs.host("Register")] }, - { id: "flow-acquire-gate", title: "Serialize admission", purpose: "Prevent concurrent receipt lookup and creation from splitting idempotency authority.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("await operationGate.WaitAsync()")] }, - { id: "flow-validate-entry", title: "Validate entry", purpose: "Normalize the caller identity and admit only DELVE or HOLD projections.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("projection != \"delve\" && projection != \"hold\"")] }, - { id: "flow-invalid-reject", title: "Reject invalid entry", purpose: "Return typed rejection without persisting a receipt.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("invalid-world-entry")] }, - { id: "flow-receipt-lookup", title: "Lookup receipt", purpose: "Read the canonical receipt record for this idempotency key.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("node.Cache.Get(receiptKey)")] }, - { id: "flow-replay-accept", title: "Accept exact replay", purpose: "Return the original receipt when caller and projection match.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("Accepted(existing)")] }, - { id: "flow-collision-reject", title: "Reject key collision", purpose: "Return rejection evidence without replacing the original receipt.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("idempotency-key-collision")] }, - { id: "flow-create-receipt", title: "Create entry receipt", purpose: "Author the first accepted receipt from host-owned world identity and revision.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("var receipt = new WorldEnterReceipt")] }, - { id: "flow-persist-receipt", title: "Persist and flush receipt", purpose: "Commit the accepted receipt before reporting acceptance.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("node.Database.PutAsync(receiptKey, receipt)"), refs.host("await node.FlushAsync()")] }, - { id: "flow-return-response", title: "Return operation response", purpose: "Carry provider-authored status and typed receipt back over the reusable session.", owner: "cultlib", runtime: "shared", status: "verified", code_refs: [refs.operationServer("CultNetOperationReply"), refs.meshClient("CultMeshOperationResult")] }, - { id: "flow-show-result", title: "Show result", purpose: "Project the expected provider status into UI text or smoke exit code.", owner: "godot-client", runtime: "godot", status: "verified", code_refs: [refs.client("private void ShowResult")] }, - { id: "flow-client-error", title: "Project client failure", purpose: "Convert discovery, session, or invocation exceptions into a failed local result without inventing world state.", owner: "godot-client", runtime: "godot", status: "verified", code_refs: [refs.client("catch (Exception error)"), refs.client("error.Message, false")] }, - { id: "flow-client-exit", title: "Dispose client", purpose: "Release the application-lifetime CultMesh client with the scene.", owner: "godot-client", runtime: "godot", status: "verified", code_refs: [refs.client("public override void _ExitTree()")] }, - { id: "flow-host-wait", title: "Wait for stop or failure", purpose: "Keep authority alive until Ctrl+C or ingress failure terminates the process.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("Task.WhenAny(stopped.Task, server.BackgroundFailure)")] }, - { id: "flow-host-cancel", title: "Handle operator cancellation", purpose: "Convert Ctrl+C into orderly completion of the host lifetime.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("Console.CancelKeyPress"), refs.host("stopped.TrySetResult()")] }, - { id: "flow-host-failure", title: "Propagate ingress failure", purpose: "Terminate the host by throwing the captured background listener failure.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("if (server.BackgroundFailure.IsCompleted)"), refs.host("throw await server.BackgroundFailure")] }, - { id: "flow-host-terminated", title: "Host process terminates", purpose: "Dispose host-owned resources after orderly cancellation or propagate a fatal ingress error to the process boundary.", owner: "world-host", runtime: "world-host", status: "verified", code_refs: [refs.host("using var node"), refs.host("throw await server.BackgroundFailure")] }, - { id: "flow-smoke", title: "Runtime smoke sequence", purpose: "Drive accepted entry, collision rejection, invalid rejection, restart, and exact receipt replay.", owner: "verification", runtime: "tooling", status: "verified", code_refs: [refs.verify("Invoke-GodotSmoke 'first'"), refs.verify("Invoke-GodotSmoke 'collision'"), refs.verify("Invoke-GodotSmoke 'restart'")] }, - { id: "flow-map-validation", title: "Validate typed map", purpose: "Reject graph, witness, dependency-pin, inventory, or source-digest drift before compiling the runtime.", owner: "verification", runtime: "tooling", status: "verified", code_refs: [refs.verify("control-flow.ps1') validate"), refs.graphVerify("DELVEHOLD_CONTROL_FLOW_INVALID")] }, - { id: "flow-focused-build", title: "Build focused solution", purpose: "Compile the Godot client, protocol, and world host under the admitted CultLib revision.", owner: "developer-tooling", runtime: "tooling", status: "verified", code_refs: [refs.verify("dotnet build"), refs.solution("Delvehold.Client"), refs.buildProps("CultLibRoot"), refs.buildTargets("CultLib must be revision")] }, - { id: "flow-cultlib-admission", title: "Admit CultLib dependency", purpose: "Require the exact CultLib revision and a clean worktree before project references resolve.", owner: "developer-tooling", runtime: "tooling", status: "verified", code_refs: [refs.buildTargets("VerifyCultLibRevision"), refs.buildProps("CultLibRevision")] }, - { id: "flow-revision-reject", title: "Reject CultLib revision", purpose: "Fail the build when the selected CultLib checkout is not the admitted revision.", owner: "developer-tooling", runtime: "tooling", status: "verified", code_refs: [refs.buildTargets("CultLib must be revision")] }, - { id: "flow-dirty-reject", title: "Reject dirty CultLib", purpose: "Fail the build when the selected CultLib worktree contains unadmitted changes.", owner: "developer-tooling", runtime: "tooling", status: "verified", code_refs: [refs.buildTargets("CultLibRoot must be clean")] }, - { id: "flow-open-editor", title: "Open Godot editor", purpose: "Launch the admitted Godot executable against the client project with the selected CultLib worktree.", owner: "developer-tooling", runtime: "tooling", status: "verified", code_refs: [refs.openGodot("Godot_v4.7.2-stable_mono_win64.exe"), refs.openGodot("Start-Process")] }, -]; - -const e = (id: string, source_id: string, target_id: string, kind: ControlEdgeKind, code_refs: EpiphanyCodeRef[], label?: string): TypedControlEdge => ({ id, source_id, target_id, kind, code_refs, label }); - -const dataflowEdges: TypedControlEdge[] = [ - e("flow-edge-start-ready", "flow-client-start", "flow-ready", "calls", [refs.client("_Ready")]), - e("flow-edge-ready-ui", "flow-ready", "flow-build-ui", "calls", [refs.client("BuildInterface();")]), - e("flow-edge-ready-enter", "flow-ready", "flow-enter", "calls", [refs.client("_ = EnterWorldAsync();")]), - e("flow-edge-ui-mode", "flow-build-ui", "flow-mode-select", "signals", [refs.client("_delve.Pressed"), refs.client("_hold.Pressed")]), - e("flow-edge-enter-mode", "flow-enter", "flow-mode-select", "calls", [refs.client("SelectProjection(options.Projection)")]), - e("flow-edge-enter-discovery", "flow-enter", "flow-discovery", "discovers", [refs.client("RendezvousEndpoints")]), - e("flow-edge-discovery-catalog", "flow-discovery", "flow-catalog-response", "calls", [refs.host("CultMeshVerseCatalogRequestMessage")]), - e("flow-edge-catalog-session", "flow-catalog-response", "flow-session-open", "opens-session", [refs.host("authorityRoutes"), refs.meshClient("ConnectAsync")]), - e("flow-edge-session-send", "flow-session-open", "flow-send-entry", "sends-intent", [refs.meshClient("session.SendCultNet(message)")]), - e("flow-edge-host-open", "flow-host-start", "flow-open-state", "calls", [refs.host("CultMesh.CreateNodeAsync")]), - e("flow-edge-open-seed", "flow-open-state", "flow-seed-world", "branches", [refs.host("is null")]), - e("flow-edge-seed-bind", "flow-seed-world", "flow-bind-ingress", "calls", [refs.host("using var server")]), - e("flow-edge-bind-catalog", "flow-bind-ingress", "flow-catalog-response", "calls", [refs.host("CreateCatalogResponse")]), - e("flow-edge-send-dispatch", "flow-send-entry", "flow-dispatch-entry", "dispatches", [refs.operationServer("HandleAsync")]), - e("flow-edge-dispatch-gate", "flow-dispatch-entry", "flow-acquire-gate", "calls", [refs.host("operationGate.WaitAsync")]), - e("flow-edge-gate-validate", "flow-acquire-gate", "flow-validate-entry", "validates", [refs.host("sourceRuntimeId"), refs.host("projection")]), - e("flow-edge-validate-invalid", "flow-validate-entry", "flow-invalid-reject", "rejects", [refs.host("invalid-world-entry")], "invalid caller or projection"), - e("flow-edge-validate-lookup", "flow-validate-entry", "flow-receipt-lookup", "reads", [refs.host("receiptKey")], "valid entry"), - e("flow-edge-lookup-replay", "flow-receipt-lookup", "flow-replay-accept", "replays", [refs.host("Accepted(existing)")], "exact match"), - e("flow-edge-lookup-collision", "flow-receipt-lookup", "flow-collision-reject", "rejects", [refs.host("idempotency-key-collision")], "same key, different input"), - e("flow-edge-lookup-create", "flow-receipt-lookup", "flow-create-receipt", "branches", [refs.host("var receipt = new WorldEnterReceipt")], "missing receipt"), - e("flow-edge-create-persist", "flow-create-receipt", "flow-persist-receipt", "writes", [refs.host("PutAsync(receiptKey, receipt)")]), - e("flow-edge-persist-response", "flow-persist-receipt", "flow-return-response", "returns-receipt", [refs.host("Accepted(receipt)")]), - e("flow-edge-replay-response", "flow-replay-accept", "flow-return-response", "returns-receipt", [refs.host("Accepted(existing)")]), - e("flow-edge-collision-response", "flow-collision-reject", "flow-return-response", "returns-receipt", [refs.host("Rejected(")]), - e("flow-edge-invalid-response", "flow-invalid-reject", "flow-return-response", "returns-receipt", [refs.host("invalid-world-entry")]), - e("flow-edge-response-show", "flow-return-response", "flow-show-result", "calls", [refs.client("CallDeferred(MethodName.ShowResult")]), - e("flow-edge-enter-error", "flow-enter", "flow-client-error", "branches", [refs.client("catch (Exception error)")], "discovery, session, or invocation failure"), - e("flow-edge-error-show", "flow-client-error", "flow-show-result", "calls", [refs.client("error.Message, false")]), - e("flow-edge-show-exit", "flow-show-result", "flow-client-exit", "terminates", [refs.client("GetTree().Quit")], "headless smoke only"), - e("flow-edge-scene-exit", "flow-client-start", "flow-client-exit", "terminates", [refs.client("_ExitTree")], "ordinary scene teardown"), - e("flow-edge-bind-wait", "flow-bind-ingress", "flow-host-wait", "waits-for", [refs.host("Task.WhenAny")]), - e("flow-edge-wait-cancel", "flow-host-wait", "flow-host-cancel", "branches", [refs.host("stopped.Task")], "Ctrl+C"), - e("flow-edge-wait-failure", "flow-host-wait", "flow-host-failure", "branches", [refs.host("server.BackgroundFailure")], "listener failure"), - e("flow-edge-cancel-stop", "flow-host-cancel", "flow-host-terminated", "terminates", [refs.host("stopped.TrySetResult()")], "complete wait and dispose"), - e("flow-edge-failure-stop", "flow-host-failure", "flow-host-terminated", "terminates", [refs.host("throw await server.BackgroundFailure")], "fatal process exit"), - e("flow-edge-smoke-start", "flow-smoke", "flow-host-start", "verifies", [refs.verify("Start-WorldHost")]), - e("flow-edge-smoke-map", "flow-smoke", "flow-map-validation", "calls", [refs.verify("control-flow.ps1') validate")]), - e("flow-edge-map-build", "flow-map-validation", "flow-focused-build", "calls", [refs.verify("dotnet build")]), - e("flow-edge-smoke-client", "flow-smoke", "flow-client-start", "verifies", [refs.verify("$godot --headless")]), - e("flow-edge-smoke-replay", "flow-smoke", "flow-replay-accept", "verifies", [refs.verify("$firstReceipt -ne $restartReceipt")]), - e("flow-edge-smoke-invalid", "flow-smoke", "flow-invalid-reject", "verifies", [refs.verify("invalid-projection")]), - e("flow-edge-smoke-collision", "flow-smoke", "flow-collision-reject", "verifies", [refs.verify("collision")]), - e("flow-edge-build-admission", "flow-focused-build", "flow-cultlib-admission", "validates", [refs.buildTargets("BeforeTargets=\"ResolveProjectReferences\"")]), - e("flow-edge-admission-revision", "flow-cultlib-admission", "flow-revision-reject", "rejects", [refs.buildTargets("found $([System.String]")], "wrong revision"), - e("flow-edge-admission-dirty", "flow-cultlib-admission", "flow-dirty-reject", "rejects", [refs.buildTargets("CultLibStatus")], "dirty worktree"), - e("flow-edge-admission-client", "flow-cultlib-admission", "flow-client-start", "constructs", [refs.clientProject("Godot.NET.Sdk/4.7.2")], "admitted dependency"), - e("flow-edge-admission-host", "flow-cultlib-admission", "flow-host-start", "constructs", [refs.hostProject("OutputType>Exe")], "admitted dependency"), - e("flow-edge-editor-client", "flow-open-editor", "flow-client-start", "constructs", [refs.openGodot("--editor")], "interactive editor projection"), -]; - -const architectureByFlowId: Record = { - "flow-client-start": "arch-godot-project", - "flow-ready": "arch-main-control", - "flow-build-ui": "arch-main-control", - "flow-mode-select": "arch-main-control", - "flow-enter": "arch-main-control", - "flow-discovery": "arch-cultmesh-client", - "flow-catalog-response": "arch-cultmesh-ingress", - "flow-session-open": "arch-cultmesh-client", - "flow-send-entry": "arch-world-contract", - "flow-host-start": "arch-world-host", - "flow-open-state": "arch-cultcache", - "flow-seed-world": "arch-world-state", - "flow-bind-ingress": "arch-cultmesh-ingress", - "flow-dispatch-entry": "arch-cultmesh-ingress", - "flow-acquire-gate": "arch-entry-admission", - "flow-validate-entry": "arch-entry-admission", - "flow-invalid-reject": "arch-entry-admission", - "flow-receipt-lookup": "arch-cultcache", - "flow-replay-accept": "arch-entry-admission", - "flow-collision-reject": "arch-entry-admission", - "flow-create-receipt": "arch-entry-admission", - "flow-persist-receipt": "arch-cultcache", - "flow-return-response": "arch-cultmesh-ingress", - "flow-show-result": "arch-main-control", - "flow-client-error": "arch-main-control", - "flow-client-exit": "arch-main-control", - "flow-host-wait": "arch-world-host", - "flow-host-cancel": "arch-world-host", - "flow-host-failure": "arch-world-host", - "flow-host-terminated": "arch-world-host", - "flow-smoke": "arch-runtime-verifier", - "flow-map-validation": "arch-runtime-verifier", - "flow-focused-build": "arch-developer-tooling", - "flow-cultlib-admission": "arch-developer-tooling", - "flow-revision-reject": "arch-developer-tooling", - "flow-dirty-reject": "arch-developer-tooling", - "flow-open-editor": "arch-developer-tooling", -}; - -const links: NornGraphLink[] = dataflowNodes.map((node) => ({ - dataflow_node_id: node.id, - architecture_node_id: architectureByFlowId[node.id] ?? `unmapped:${node.id}`, - relationship: "owned-by", - code_refs: node.code_refs, -})); - -export const sourceInventory: SourceSurface[] = [ - { path: "Delvehold.sln", normalizedSha256: "19ce0e87a3b8c7d34b957db8fa1c50f25230a849c39de6872afb81746cb1ca65", responsibility: "Rider and focused build project membership" }, - { path: "Directory.Build.props", normalizedSha256: "898df5c1ff8b0bf7110ac2e27aa585d8d241af85b718e53aaefecd9c1fc8098f", responsibility: "shared target and dependency admission defaults" }, - { path: "Directory.Build.targets", normalizedSha256: "fb703044f822d690ff3afdfa82219d43951f740834f533b7988c18e446da41a6", responsibility: "CultLib revision and cleanliness gate" }, - { path: "client/Delvehold.Client.csproj", normalizedSha256: "0a9a92a87761f2a2525a19ac73bad22c621e2640ab91127c17660e111497cf26", responsibility: "Godot client build dependencies" }, - { path: "client/Main.cs", normalizedSha256: "ea636fd09961d93991e28653f237bc1a3f52661101a4311d697b4865ba4ff23f", responsibility: "Godot client control flow" }, - { path: "client/Main.tscn", normalizedSha256: "a1c1d81dfe77e1921a0f42f0c17d7205ca5d0a0e9ec9373382a568a1885c2f55", responsibility: "Godot root scene construction" }, - { path: "client/project.godot", normalizedSha256: "41021e8586c6d4fb0a5412b4cfce3830fb24161605a95c2c31d3db4d663fd1c8", responsibility: "Godot application entry configuration" }, - { path: "scripts/control-flow.ps1", normalizedSha256: "a986cce42706574f97eed37abbc9af073d01d05333e47013e53f1c9c0f8c21e7", responsibility: "typed map validation and Norn viewer lifecycle" }, - { path: "scripts/open-godot.ps1", normalizedSha256: "de789de343d03451d4b203ce9e863cc92754e59ba6251d6581e6f2aebf81b559", responsibility: "interactive Godot editor launch" }, - { path: "scripts/verify-runtime.ps1", normalizedSha256: "5456cef5679644fd2d553a954a04a224a211d6d330f1d2533a2052699a3f7976", responsibility: "executable runtime acceptance flow" }, - { path: "src/Delvehold.Protocol/Delvehold.Protocol.csproj", normalizedSha256: "d7e665c26dedd151551db6285a753034a12bfa616a20420eb1e42225eabe74b6", responsibility: "wire contract dependencies" }, - { path: "src/Delvehold.Protocol/WorldContracts.cs", normalizedSha256: "dfe85fc3ad5ec078a2b8e490284398160fcde46a6f7728d3cbae8b813877cb13", responsibility: "typed world-entry wire contract" }, - { path: "src/Delvehold.WorldHost/Delvehold.WorldHost.csproj", normalizedSha256: "6301967b27a4319dff8631e093a3ed965f64b099222061873949928fe8504693", responsibility: "world-host build dependencies" }, - { path: "src/Delvehold.WorldHost/Program.cs", normalizedSha256: "73933d99fbdad59aa68ab1115426cb63165017201be7206c991c7b3cbf698184", responsibility: "world-host composition and admission control flow" }, - { path: "src/Delvehold.WorldHost/WorldState.cs", normalizedSha256: "fe471c7f22161e96b5a9cf0cd04e87c8f85017bdbcd3836ddf496db1a8dea120", responsibility: "canonical first-world schema and seed" }, -]; - -export const controlFlowMap = { - schema: "delvehold.control_flow_map.v0" as const, - nornRevision: "fa4a46bb13333eb703e97ccea9edc1b70ee109b7" as const, - cultLibRevision: "334e60f1928b4212a29dd8b0d19b2c099fe6365e" as const, - architecture: { nodes: architectureNodes, edges: architectureEdges }, - dataflow: { nodes: dataflowNodes, edges: dataflowEdges }, - links, - sourceInventory, -}; - -export const nornState: NornGraphsState = { - architecture: controlFlowMap.architecture, - dataflow: controlFlowMap.dataflow, - links: controlFlowMap.links, -}; diff --git a/modeling/control-flow/index.html b/modeling/control-flow/index.html deleted file mode 100644 index f66ce6f..0000000 --- a/modeling/control-flow/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - DELVE/HOLD Control Flow - - -
- - - diff --git a/modeling/control-flow/main.tsx b/modeling/control-flow/main.tsx deleted file mode 100644 index 4f004be..0000000 --- a/modeling/control-flow/main.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { StrictMode } from "react"; -import { createRoot } from "react-dom/client"; -import { NornViewer } from "@gamecult/norn-viewer"; -import { nornState } from "./graph"; -import "./style.css"; - -function App() { - return ( - - ); -} - -createRoot(document.getElementById("root")!).render( - - - , -); diff --git a/modeling/control-flow/package-lock.json b/modeling/control-flow/package-lock.json deleted file mode 100644 index 11f6bb1..0000000 --- a/modeling/control-flow/package-lock.json +++ /dev/null @@ -1,1944 +0,0 @@ -{ - "name": "@gamecult/delvehold-control-flow", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@gamecult/delvehold-control-flow", - "version": "0.1.0", - "dependencies": { - "@gamecult/norn-viewer": "file:../../../Norn/web/norn-viewer", - "react": "^19.2.0", - "react-dom": "^19.2.0" - }, - "devDependencies": { - "@types/node": "^24.10.1", - "@types/react": "^19.2.7", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.2", - "tsx": "^4.21.0", - "typescript": "^5.9.3", - "vite": "^7.2.6" - } - }, - "../../../Norn/web/norn-viewer": { - "name": "@gamecult/norn-viewer", - "version": "0.1.0", - "devDependencies": { - "@types/react": "^19.2.2", - "@types/react-dom": "^19.2.2", - "@vitejs/plugin-react": "^5.1.1", - "react": "^19.2.0", - "react-dom": "^19.2.0", - "tsup": "^8.5.0", - "typescript": "^5.9.3", - "vite": "^7.2.4" - }, - "peerDependencies": { - "react": "^19.0.0", - "react-dom": "^19.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", - "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.29.7", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", - "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", - "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.7", - "@babel/helper-compilation-targets": "^7.29.7", - "@babel/helper-module-transforms": "^7.29.7", - "@babel/helpers": "^7.29.7", - "@babel/parser": "^7.29.7", - "@babel/template": "^7.29.7", - "@babel/traverse": "^7.29.7", - "@babel/types": "^7.29.7", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", - "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.8", - "@babel/types": "^7.29.8", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", - "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.29.7", - "@babel/helper-validator-option": "^7.29.7", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", - "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", - "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.29.7", - "@babel/types": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", - "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.29.7", - "@babel/helper-validator-identifier": "^7.29.7", - "@babel/traverse": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", - "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", - "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", - "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", - "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", - "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.29.7", - "@babel/types": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", - "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.29.8" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", - "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", - "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", - "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/parser": "^7.29.7", - "@babel/types": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", - "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.8", - "@babel/helper-globals": "^7.29.7", - "@babel/parser": "^7.29.8", - "@babel/template": "^7.29.7", - "@babel/types": "^7.29.8", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", - "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.29.7", - "@babel/helper-validator-identifier": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", - "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", - "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", - "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", - "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", - "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", - "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", - "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", - "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", - "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", - "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", - "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", - "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", - "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", - "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", - "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", - "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", - "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", - "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", - "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", - "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", - "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", - "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", - "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", - "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", - "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", - "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@gamecult/norn-viewer": { - "resolved": "../../../Norn/web/norn-viewer", - "link": true - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@napi-rs/lzma-linux-x64-gnu": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", - "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^22.20 || ^24.12 || >=25" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.3", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", - "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.63.0.tgz", - "integrity": "sha512-70TeIFezKKy65LgAVyQh+w94/gjWhvPWaLaGGeMEgVrPkQhuj/M5bAYYZzIFUj9Y69oHyTm5Um/R6gcLh4A8JA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.63.0.tgz", - "integrity": "sha512-YC86tYIHK6M1IV+wbzO+Bxk8RCBr6ZyWYgWxUCzaZD8mc8rrFoIJDNzDrkHBYRc/wKdrsIXmm6/F7NzrAO+OrA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.63.0.tgz", - "integrity": "sha512-oI+ECtUcli0y0fi4xpW82GdPIXdTkI8G8DSjG2LRuw09fPAGykaWYH/hXxiKuTxiAjiPSTIIuYUqof5Z2hShWw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.63.0.tgz", - "integrity": "sha512-NwV+1s7TiKrMe4owHyKB/dTLD7ZJD0YEBEhIz+hvav1Cu1GReJjF+rsdNwjzENQeIAbE/CoNiaAc5Vz2h5DPAA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.63.0.tgz", - "integrity": "sha512-tWtHBTu5gOPK4u4Urtk4qAHW3zZ9rQAmbssO8gp7ELvGTGI3aCiq6NqyTQ0PCIg7KbHJF2UkGDDs77YZGxfjCA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.63.0.tgz", - "integrity": "sha512-2qPoJiwTvtHQ27NnYvTnsgk8laXWYuVmNESG8WFZBcEPKLfZ3I27qBJarjVRQtwGeYyRfq5ZowHXih9lm2BItw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.63.0.tgz", - "integrity": "sha512-FQwsTRvLNuHoTdICABJQfbPUSEueISGmnpT06tXTMpfprf5NiKLSXKA0A+w45wJnCmZAnzgqBwbt6ARFuyOi5w==", - "cpu": [ - "arm" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.63.0.tgz", - "integrity": "sha512-BBVTXziw8mY1a4ZbWME9tZyfzqXCDPqaC7Z3heQ29p5dkvXzwL0NwelO8zLa8c3RBKvl3YTuSnBgsBhYBtwjIw==", - "cpu": [ - "arm" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.63.0.tgz", - "integrity": "sha512-w2Iyy9+RqKwx3d9qWMKsJg0FfRBsY0/pXNv0mCQ3ueRvJI6+QAScfD4nrMlzFLs2HNVW6Ew+mtZfDl9b7Ew5/Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.63.0.tgz", - "integrity": "sha512-YK++KtrFRHYE0P6/RtYEAy9t8F37znP+K03RrIuLPYOL6SVlObRumf/0OE4V/h63xL9DwkWbNssZfmA9hawuDA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.63.0.tgz", - "integrity": "sha512-aBfOG6fP7YkkPmTqPwufRJeFyz7WPpECv9XNbnsk9+vg7rxdih0lbtEel7jcRng4LZrrmU3FfitCFyEj4BWDWg==", - "cpu": [ - "loong64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.63.0.tgz", - "integrity": "sha512-LGaHEOeHNAag9VuS1Crs5DFg4RrU9MPi2nVnNJk9DTePx/B6RRYKVmrIXt2h7YOJlwjaFJ6lwtFDliZxScTLrQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.63.0.tgz", - "integrity": "sha512-jClvk+J0FC3b7Udvegiw5/4hErbHtmsNsQgENnKXDWtNCJXsJYZH5WURvu7imDOO38xYml24eeh5x3A04ppwCw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.63.0.tgz", - "integrity": "sha512-0OJlaGK+8+B777Ql5okIpD7ua5Ro9+VB9Ve0OKa28OQJZ1RbuUBVNHK/e3pr4BROqsyPl1JrPO1ZxJseCNffcA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.63.0.tgz", - "integrity": "sha512-Ygsx+HoNH7afwi1bTIXbnTvVnsO+zurPLSYxybV1hHFVU72OWOCl6v05ql/z0hkpAPx+DK7Kn9Bi7MayCcjLTA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.63.0.tgz", - "integrity": "sha512-pDQxtMGb+OvG3fLwR2OkZlSd47hW+kWg4BYMG/++sR6RqorQccwPTDsxda5hPwiIeIErAnCF9ma3SAU06bdQtQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.63.0.tgz", - "integrity": "sha512-0BnUG9mS8I4SSHr3XsxVhuCMEiu+rX61xxZF5vujso4LaiAGFZFxvDjg6Xn6tLPNTUAfuCvQYas4LMQMVsKRSQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.63.0.tgz", - "integrity": "sha512-Adu/VttB1dpPNW+FEacrZ+xVm9tFty84+RrFzsqlFaPxoJB+9XXyDGtp5dCOoBwGBIEVH0To7lExFXEx0BIF4A==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.63.0.tgz", - "integrity": "sha512-NQ3bDvjUbFKmP23671xUlXtKmqVsUBd6M4PQCvbmNtOy06hnQIdKHy8oG/6S3R/S6He1JgPk6A5VT+prAJMYEw==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.63.0.tgz", - "integrity": "sha512-u2eDAl4+0aFvA13GxlGBtTI3SS3sdgwgtV0HyjZ0QaQVCgNE+jqNGey+GtxWiq+wxr/UycAx/OnfJzApCFamvA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.63.0.tgz", - "integrity": "sha512-XvRb5vfW3wAZQ+ZUG21AnHHDKtNcw99eigzEhjr//NZ3u7SoBaPP0seSc7FgP7p1epAEdAoZckMW9WY/+4w70w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.63.0.tgz", - "integrity": "sha512-iZPmniy4kNBf5yo2RezbkYNNK5HPbXE9+g+twnbqSng7dtLEJy1SKoxiE/ni4FDacjyuZpEeb9U054N4EoKHYw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.63.0.tgz", - "integrity": "sha512-mFBBd+LF37fnE8JnYUOH+imj0aPFPK30vpar4ehJkgnLj9sZn8ZxiRENmLtgIwxK7TC8klF6N57fxdNBwQoqOA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.63.0.tgz", - "integrity": "sha512-ujeqEY3B+zbGn3Z4Q03cUBG/LGWnBJncVT36WER31LcOsQk9+1dmINKKtvmmfChUvRbK1G0R8OhMWFgHgaZtAw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.63.0.tgz", - "integrity": "sha512-hncn90N4sOky0L2LKE5oESKLbxCPeVo4eLA2LSMoDzM+879ml4WSr+Rr4DWknNIVVvS1Hirkc9hx02W6YxS8rQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "node_modules/@types/estree": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", - "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "24.13.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", - "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.18.0" - } - }, - "node_modules/@types/react": { - "version": "19.2.18", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", - "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.2.5", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.5.tgz", - "integrity": "sha512-fMPwH9v7r/pp43yUd2/Mbiex5KouJwwR3dzHkhLREUC6764VyDsqxhAxv6OFEYR1RhjOyD1naqba8ECDBe7ZQg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.2.0" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz", - "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.29.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-rc.3", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.18.0" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.11.19", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.19.tgz", - "integrity": "sha512-Grytf1xOxOEMTGRwx6rLGKkTabd4vMg3VrKdj/7joCmV0qgh4QwMMO6xh34YEXQqirAuUdgQGa5orJQQ+69RBw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/browserslist": { - "version": "4.28.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", - "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.11.12", - "caniuse-lite": "^1.0.30001809", - "electron-to-chromium": "^1.5.402", - "node-releases": "^2.0.53", - "update-browserslist-db": "^1.3.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001810", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", - "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.415", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.415.tgz", - "integrity": "sha512-958V+Kbhtgz+SxXeEVKBjrlKRBIDAYvUJfwhjxMZ5S6ut9jAl7l9ZKBkBrvjyjZE36PabLUo2L8kEeV5O4vgJg==", - "dev": true, - "license": "ISC" - }, - "node_modules/esbuild": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", - "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.2", - "@esbuild/android-arm": "0.28.2", - "@esbuild/android-arm64": "0.28.2", - "@esbuild/android-x64": "0.28.2", - "@esbuild/darwin-arm64": "0.28.2", - "@esbuild/darwin-x64": "0.28.2", - "@esbuild/freebsd-arm64": "0.28.2", - "@esbuild/freebsd-x64": "0.28.2", - "@esbuild/linux-arm": "0.28.2", - "@esbuild/linux-arm64": "0.28.2", - "@esbuild/linux-ia32": "0.28.2", - "@esbuild/linux-loong64": "0.28.2", - "@esbuild/linux-mips64el": "0.28.2", - "@esbuild/linux-ppc64": "0.28.2", - "@esbuild/linux-riscv64": "0.28.2", - "@esbuild/linux-s390x": "0.28.2", - "@esbuild/linux-x64": "0.28.2", - "@esbuild/netbsd-arm64": "0.28.2", - "@esbuild/netbsd-x64": "0.28.2", - "@esbuild/openbsd-arm64": "0.28.2", - "@esbuild/openbsd-x64": "0.28.2", - "@esbuild/openharmony-arm64": "0.28.2", - "@esbuild/sunos-x64": "0.28.2", - "@esbuild/win32-arm64": "0.28.2", - "@esbuild/win32-ia32": "0.28.2", - "@esbuild/win32-x64": "0.28.2" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.18", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", - "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-releases": { - "version": "2.0.53", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", - "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", - "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.26", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", - "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.17", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/react": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", - "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", - "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", - "license": "MIT", - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.8" - } - }, - "node_modules/react-refresh": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", - "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.63.0.tgz", - "integrity": "sha512-T5vnZ2y4QqC3/4P+w2+JO+Q/OVdnPsv4XcSYJYMEn0R9/jjl5AgLwO9LAZMzP2lN71O6pypn91rB7lDstUkfrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.9" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@napi-rs/lzma-linux-x64-gnu": "1.5.1", - "@rollup/rollup-android-arm-eabi": "4.63.0", - "@rollup/rollup-android-arm64": "4.63.0", - "@rollup/rollup-darwin-arm64": "4.63.0", - "@rollup/rollup-darwin-x64": "4.63.0", - "@rollup/rollup-freebsd-arm64": "4.63.0", - "@rollup/rollup-freebsd-x64": "4.63.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.63.0", - "@rollup/rollup-linux-arm-musleabihf": "4.63.0", - "@rollup/rollup-linux-arm64-gnu": "4.63.0", - "@rollup/rollup-linux-arm64-musl": "4.63.0", - "@rollup/rollup-linux-loong64-gnu": "4.63.0", - "@rollup/rollup-linux-loong64-musl": "4.63.0", - "@rollup/rollup-linux-ppc64-gnu": "4.63.0", - "@rollup/rollup-linux-ppc64-musl": "4.63.0", - "@rollup/rollup-linux-riscv64-gnu": "4.63.0", - "@rollup/rollup-linux-riscv64-musl": "4.63.0", - "@rollup/rollup-linux-s390x-gnu": "4.63.0", - "@rollup/rollup-linux-x64-gnu": "4.63.0", - "@rollup/rollup-linux-x64-musl": "4.63.0", - "@rollup/rollup-openbsd-x64": "4.63.0", - "@rollup/rollup-openharmony-arm64": "4.63.0", - "@rollup/rollup-win32-arm64-msvc": "4.63.0", - "@rollup/rollup-win32-ia32-msvc": "4.63.0", - "@rollup/rollup-win32-x64-gnu": "4.63.0", - "@rollup/rollup-win32-x64-msvc": "4.63.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", - "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tsx": { - "version": "4.23.12", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.12.tgz", - "integrity": "sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.28.0" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/update-browserslist-db": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", - "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/vite": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", - "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.27.0 || ^0.28.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - } - } -} diff --git a/modeling/control-flow/package.json b/modeling/control-flow/package.json deleted file mode 100644 index ae11cb8..0000000 --- a/modeling/control-flow/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@gamecult/delvehold-control-flow", - "private": true, - "version": "0.1.0", - "type": "module", - "scripts": { - "validate": "tsx verify.ts", - "build": "npm run validate && tsc --noEmit && vite build", - "dev": "vite" - }, - "dependencies": { - "@gamecult/norn-viewer": "file:../../../Norn/web/norn-viewer", - "react": "^19.2.0", - "react-dom": "^19.2.0" - }, - "devDependencies": { - "@types/node": "^24.10.1", - "@types/react": "^19.2.7", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.2", - "tsx": "^4.21.0", - "typescript": "^5.9.3", - "vite": "^7.2.6" - } -} diff --git a/modeling/control-flow/style.css b/modeling/control-flow/style.css deleted file mode 100644 index a4db184..0000000 --- a/modeling/control-flow/style.css +++ /dev/null @@ -1,18 +0,0 @@ -:root { - color-scheme: dark; - font-family: Inter, ui-sans-serif, system-ui, sans-serif; - background: #080706; -} - -html, -body, -#root { - width: 100%; - height: 100%; - margin: 0; - overflow: hidden; -} - -* { - box-sizing: border-box; -} diff --git a/modeling/control-flow/tsconfig.json b/modeling/control-flow/tsconfig.json deleted file mode 100644 index dc189e9..0000000 --- a/modeling/control-flow/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "useDefineForClassFields": true, - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "allowJs": false, - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "module": "ESNext", - "moduleResolution": "Bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx" - }, - "include": ["*.ts", "*.tsx"] -} diff --git a/modeling/control-flow/verify.ts b/modeling/control-flow/verify.ts deleted file mode 100644 index f468661..0000000 --- a/modeling/control-flow/verify.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { createHash } from "node:crypto"; -import { execFileSync } from "node:child_process"; -import { existsSync, readFileSync, readdirSync, statSync } from "node:fs"; -import { dirname, relative, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; -import { controlFlowMap } from "./graph"; - -const mapRoot = dirname(fileURLToPath(import.meta.url)); -const repoRoot = resolve(mapRoot, "../.."); -const failures: string[] = []; -const witnessedLocalPaths = new Set(); -const nornRoot = process.env.DELVEHOLD_NORN_ROOT ?? resolve(repoRoot, "../Norn"); -const cultLibRoot = process.env.DELVEHOLD_CULTLIB_ROOT ?? resolve(repoRoot, "../CultLib-aetheria-authority"); - -validateDependency("Norn", nornRoot, controlFlowMap.nornRevision); -validateDependency("CultLib", cultLibRoot, controlFlowMap.cultLibRevision); -const buildProps = readFileSync(resolve(repoRoot, "Directory.Build.props"), "utf8"); -if (!buildProps.includes(`${controlFlowMap.cultLibRevision}`)) { - failures.push("The control-flow CultLib pin disagrees with Directory.Build.props."); -} - -const architectureIds = validateGraph("architecture", controlFlowMap.architecture); -const dataflowIds = validateGraph("dataflow", controlFlowMap.dataflow); -const linkKeys = new Set(); -for (const link of controlFlowMap.links) { - const key = `${link.dataflow_node_id}::${link.architecture_node_id}`; - if (linkKeys.has(key)) failures.push(`Duplicate cross-link '${key}'.`); - linkKeys.add(key); - if (!dataflowIds.has(link.dataflow_node_id)) failures.push(`Cross-link '${key}' has no dataflow node.`); - if (!architectureIds.has(link.architecture_node_id)) failures.push(`Cross-link '${key}' has no architecture node.`); - validateRefs(`cross-link '${key}'`, link.code_refs ?? []); -} - -const expectedSources = collectExecutableSources(); -const inventoriedSources = new Set(controlFlowMap.sourceInventory.map((source) => normalize(source.path))); -for (const path of expectedSources) { - if (!inventoriedSources.has(path)) failures.push(`Executable source '${path}' is missing from sourceInventory.`); -} -for (const path of inventoriedSources) { - if (!expectedSources.has(path)) failures.push(`sourceInventory contains stale or out-of-scope path '${path}'.`); - if (!witnessedLocalPaths.has(path)) failures.push(`Inventoried source '${path}' is not cited by any graph node, edge, or cross-link.`); -} - -for (const source of controlFlowMap.sourceInventory) { - const absolute = resolve(repoRoot, source.path); - if (!existsSync(absolute)) { - failures.push(`Inventoried source '${source.path}' does not exist.`); - continue; - } - const actual = normalizedSha256(readFileSync(absolute, "utf8")); - if (actual !== source.normalizedSha256) { - failures.push(`Source drift '${source.path}': expected ${source.normalizedSha256}, actual ${actual}. Review the graph, then admit the new hash.`); - } -} - -if (failures.length > 0) { - console.error("DELVEHOLD_CONTROL_FLOW_INVALID"); - for (const failure of failures) console.error(`- ${failure}`); - process.exit(1); -} - -console.log(`DELVEHOLD_CONTROL_FLOW_VALID architecture=${architectureIds.size}/${controlFlowMap.architecture.edges.length} dataflow=${dataflowIds.size}/${controlFlowMap.dataflow.edges.length} links=${controlFlowMap.links.length} sources=${expectedSources.size}`); - -function validateGraph( - name: string, - graph: typeof controlFlowMap.architecture, -): Set { - const nodeIds = new Set(); - const edgeIds = new Set(); - for (const node of graph.nodes) { - if (!node.id.trim() || !node.title.trim() || !node.purpose.trim() || !node.owner) { - failures.push(`${name} node '${node.id || ""}' lacks required typed identity, title, purpose, or owner.`); - } - if (nodeIds.has(node.id)) failures.push(`Duplicate ${name} node '${node.id}'.`); - nodeIds.add(node.id); - validateRefs(`${name} node '${node.id}'`, node.code_refs); - } - for (const edge of graph.edges) { - if (edgeIds.has(edge.id)) failures.push(`Duplicate ${name} edge '${edge.id}'.`); - edgeIds.add(edge.id); - if (!nodeIds.has(edge.source_id)) failures.push(`${name} edge '${edge.id}' has missing source '${edge.source_id}'.`); - if (!nodeIds.has(edge.target_id)) failures.push(`${name} edge '${edge.id}' has missing target '${edge.target_id}'.`); - validateRefs(`${name} edge '${edge.id}'`, edge.code_refs); - } - return nodeIds; -} - -function validateRefs(scope: string, refs: readonly { path: string; symbol?: string | null }[]) { - if (refs.length === 0) failures.push(`${scope} has no source witness.`); - for (const ref of refs) { - const normalizedPath = normalize(ref.path); - if (!normalizedPath.startsWith("../") && !normalizedPath.startsWith("@")) witnessedLocalPaths.add(normalizedPath); - const absolute = resolveWitnessPath(normalizedPath); - if (!existsSync(absolute)) { - failures.push(`${scope} references missing source '${ref.path}'.`); - continue; - } - if (ref.symbol && !readFileSync(absolute, "utf8").includes(ref.symbol)) { - failures.push(`${scope} cannot find witness '${ref.symbol}' in '${ref.path}'.`); - } - } -} - -function collectExecutableSources(): Set { - const paths = new Set(); - collect(resolve(repoRoot, "client"), new Set([".cs", ".csproj", ".godot", ".tscn"]), paths); - collect(resolve(repoRoot, "src"), new Set([".cs", ".csproj"]), paths); - collectTopLevel(resolve(repoRoot, "scripts"), new Set([".ps1"]), paths); - collectTopLevel(repoRoot, new Set([".sln", ".props", ".targets"]), paths); - return paths; -} - -function collect(directory: string, extensions: Set, output: Set) { - for (const name of readdirSync(directory)) { - if (["bin", "obj", ".godot"].includes(name)) continue; - const absolute = resolve(directory, name); - if (statSync(absolute).isDirectory()) collect(absolute, extensions, output); - else if (extensions.has(name.slice(name.lastIndexOf(".")))) output.add(normalize(relative(repoRoot, absolute))); - } -} - -function normalizedSha256(content: string): string { - return createHash("sha256").update(content.replace(/\r\n/g, "\n")).digest("hex"); -} - -function collectTopLevel(directory: string, extensions: Set, output: Set) { - for (const name of readdirSync(directory)) { - const absolute = resolve(directory, name); - if (statSync(absolute).isFile() && extensions.has(name.slice(name.lastIndexOf(".")))) { - output.add(normalize(relative(repoRoot, absolute))); - } - } -} - -function resolveWitnessPath(path: string): string { - if (path.startsWith("@cultlib/")) return resolve(cultLibRoot, path.slice("@cultlib/".length)); - if (path.startsWith("@norn/")) return resolve(nornRoot, path.slice("@norn/".length)); - return resolve(repoRoot, path); -} - -function validateDependency(name: string, root: string, expectedRevision: string) { - const git = process.env.DELVEHOLD_GIT ?? "git"; - try { - const actual = execFileSync(git, ["-C", root, "rev-parse", "HEAD"], { encoding: "utf8" }).trim(); - if (actual !== expectedRevision) failures.push(`${name} revision '${actual}' is not admitted '${expectedRevision}'.`); - const status = execFileSync(git, ["-C", root, "status", "--porcelain", "--untracked-files=normal"], { encoding: "utf8" }).trim(); - if (status) failures.push(`${name} worktree '${root}' is dirty.`); - } catch (error) { - failures.push(`Cannot verify ${name} worktree '${root}': ${error instanceof Error ? error.message : String(error)}.`); - } -} - -function normalize(path: string): string { - return path.replaceAll("\\", "/"); -} diff --git a/modeling/control-flow/vite.config.ts b/modeling/control-flow/vite.config.ts deleted file mode 100644 index 542263f..0000000 --- a/modeling/control-flow/vite.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; - -export default defineConfig({ - plugins: [react()], - base: "./", - server: { host: "127.0.0.1", port: 4176, strictPort: true }, -}); diff --git a/scripts/control-flow.ps1 b/scripts/control-flow.ps1 deleted file mode 100644 index 5a9140c..0000000 --- a/scripts/control-flow.ps1 +++ /dev/null @@ -1,84 +0,0 @@ -[CmdletBinding()] -param( - [ValidateSet('validate', 'view')] - [string]$Command = 'validate', - [string]$CultLibRoot = 'F:\Projects\CultLib-aetheria-authority' -) - -$ErrorActionPreference = 'Stop' -$repoRoot = Split-Path $PSScriptRoot -Parent -$NornRoot = Join-Path (Split-Path $repoRoot -Parent) 'Norn' -$viewerRoot = Join-Path $repoRoot 'modeling\control-flow' -$nornViewerRoot = Join-Path $NornRoot 'web\norn-viewer' -$graphSource = Get-Content (Join-Path $viewerRoot 'graph.ts') -Raw -if ($graphSource -notmatch 'nornRevision: "([0-9a-f]{40})"') { - throw 'The typed graph does not declare one Norn revision.' -} -$expectedNornRevision = $Matches[1] -$git = (Get-Command git -ErrorAction Stop).Source -$npm = (Get-Command npm.cmd -ErrorAction Stop).Source -$node = (Get-Command node -ErrorAction Stop).Source -$env:PATH = (Split-Path $node -Parent) + ';' + $env:PATH -$env:npm_config_script_shell = (Get-Command pwsh -ErrorAction Stop).Source -$env:DELVEHOLD_NORN_ROOT = $NornRoot -$env:DELVEHOLD_CULTLIB_ROOT = $CultLibRoot -$env:DELVEHOLD_GIT = $git - -if (-not (Test-Path -LiteralPath (Join-Path $nornViewerRoot 'package.json'))) { - throw "Norn was not found at '$NornRoot'. Clone GameCult/Norn beside Delvehold." -} -$actualNornRevision = (& $git -C $NornRoot rev-parse HEAD).Trim() -if ($actualNornRevision -ne $expectedNornRevision) { - throw "Norn must be revision $expectedNornRevision; found $actualNornRevision." -} -$nornStatus = (& $git -C $NornRoot status --porcelain --untracked-files=normal) -join "`n" -if ($nornStatus.Trim()) { throw 'Norn must be clean before Delvehold consumes it.' } - -if (-not (Test-Path -LiteralPath (Join-Path $nornViewerRoot 'node_modules\.bin\tsup.cmd'))) { - & $npm --prefix $nornViewerRoot ci - if ($LASTEXITCODE -ne 0) { throw 'Norn dependency restore failed.' } -} -Push-Location $nornViewerRoot -try { - & $node '.\node_modules\tsup\dist\cli-default.js' 'src\index.ts' '--format' 'esm,cjs' '--dts' '--external' 'react' '--external' 'react-dom' '--clean' - if ($LASTEXITCODE -ne 0) { throw 'Norn library build failed.' } -} finally { - Pop-Location -} - -if (-not (Test-Path -LiteralPath (Join-Path $viewerRoot 'node_modules\.bin\vite.cmd'))) { - & $npm --prefix $viewerRoot install - if ($LASTEXITCODE -ne 0) { throw 'Delvehold control-flow viewer dependency restore failed.' } -} -& $npm --prefix $viewerRoot run build -if ($LASTEXITCODE -ne 0) { throw 'Typed control-flow validation or Norn viewer build failed.' } - -if ($Command -eq 'validate') { return } - -$runRoot = Join-Path $repoRoot 'artifacts\control-flow' -New-Item -ItemType Directory -Path $runRoot -Force | Out-Null -$logPath = Join-Path $runRoot 'norn-viewer.log' -$errorPath = Join-Path $runRoot 'norn-viewer.error.log' -$pidPath = Join-Path $runRoot 'norn-viewer.pid' -$existingPid = if (Test-Path -LiteralPath $pidPath) { [int](Get-Content $pidPath) } else { 0 } -$existing = if ($existingPid -gt 0) { Get-Process -Id $existingPid -ErrorAction SilentlyContinue } else { $null } -if (-not $existing) { - $process = Start-Process -FilePath $npm -WindowStyle Hidden -PassThru ` - -WorkingDirectory $viewerRoot -ArgumentList @('run', 'dev') ` - -RedirectStandardOutput $logPath -RedirectStandardError $errorPath - Set-Content -Path $pidPath -Value $process.Id - $deadline = [DateTime]::UtcNow.AddSeconds(20) - while ([DateTime]::UtcNow -lt $deadline) { - if ($process.HasExited) { throw "Norn viewer exited. See '$errorPath'." } - try { - $null = Invoke-WebRequest -Uri 'http://127.0.0.1:4176' -UseBasicParsing -TimeoutSec 1 - break - } catch { - Start-Sleep -Milliseconds 150 - } - } - if ([DateTime]::UtcNow -ge $deadline) { throw "Norn viewer did not become ready. See '$logPath'." } -} - -Write-Host "NORN_VIEWER_READY http://127.0.0.1:4176 log=$logPath pid=$(Get-Content $pidPath)" -Start-Process 'http://127.0.0.1:4176' diff --git a/scripts/verify-runtime.ps1 b/scripts/verify-runtime.ps1 index cc93135..47e86a4 100644 --- a/scripts/verify-runtime.ps1 +++ b/scripts/verify-runtime.ps1 @@ -11,9 +11,6 @@ if (-not (Test-Path -LiteralPath $godot)) { throw "Godot 4.7.2 Mono console was not found at '$godot'." } -& (Join-Path $PSScriptRoot 'control-flow.ps1') validate -CultLibRoot $CultLibRoot -if ($LASTEXITCODE -ne 0) { throw 'The typed control-flow map is stale or invalid.' } - dotnet build (Join-Path $repoRoot 'Delvehold.sln') -p:CultLibRoot=$CultLibRoot if ($LASTEXITCODE -ne 0) { throw 'The focused .NET/Godot build failed.' }