Skip to content

Commit 5de4962

Browse files
hyperpolymathclaude
andcommitted
UMS tests, benchmarks, sync-server config, and loose ends tracker
- Generator tests (24 tests): A2ML roundtrip, deterministic generation, network topology, power maps, portfolio/campaign codecs, JSON injection safety - Generator benchmarks: 17 Deno.bench cases for all codec operations - Sync-server: Elixir config split (dev/prod/test), Phoenix endpoint with ArangoDB + VerisimDB federation, check_origin:false for dev - Router tests (14 tests): health, CORS, portfolio CRUD, campaign CRUD, error handling, database health — tolerant of DB unavailability (503) - Zig bench harness for FFI solver performance measurement - .gitignore: added .zig-cache/ pattern (dot-prefixed variant) - Removed stale .gitkeep files from tests/ and benches/ - LOOSE-ENDS.md: tracker for quick wins and deferred follow-ups Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f75507c commit 5de4962

File tree

22 files changed

+1339
-55
lines changed

22 files changed

+1339
-55
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ build/
5454

5555
# Zig
5656
zig-cache/
57+
.zig-cache/
5758
zig-out/
5859

5960
# Nix

LOOSE-ENDS.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# IDApTIK Loose Ends
3+
4+
Quick wins and half-finished items to follow up on. Most are 5 minutes or less.
5+
6+
## Documentation Cleanup
7+
8+
- [ ] **WORKPLAN-2026-02-27.md**: Remove Chapel references (Phase 1 line 13, blocker
9+
line 73, risk line 98). Chapel was removed 2026-02-27, replaced by Zig solvers.
10+
- [ ] **shared/OPUS-TODO.adoc**: Update tracking table — at least 2 items already done
11+
(P1 README.adoc files exist; P2 mapBounded implemented with chunkSize=9). Move
12+
completed items to a DONE section.
13+
- [ ] **main-game/docs/immediate-actions/2026-02-22-session-todos.md**: 5 days stale.
14+
Check if 3 PENDING items are still relevant (guard visual knockdown, pole detection
15+
cone, split-screen key bindings). Archive to COMPLETED- prefix if done.
16+
17+
## Build & Code
18+
19+
- [ ] **idaptik-ums/src/abi/Layout.idr**: Excluded from build — Idris2 0.8.0 dependent
20+
type pattern matching bug. Re-test when Idris2 0.9.0 releases.
21+
- [ ] **idaptik-ums/src/abi/Foreign.idr**: Excluded from build — depends on Layout.idr.
22+
Has a TODO for safe callback registration. Unblocked when Layout.idr compiles.
23+
- [ ] **idaptik-ums/main.js**: Hash route `#/editor` is stubbed out (renders
24+
GeneratorDemo regardless). Uncomment App import + render when TEA editor is ready,
25+
or delete the stub if editor is deferred beyond MVP.
26+
- [ ] **Zig solvers**: `ffi/zig/src/visibility.zig` and `wiring.zig` are boilerplate
27+
stubs. Need actual solver implementations (Phase 1 per WORKPLAN).
28+
29+
## Migrations (Sonnet-scale)
30+
31+
- [ ] **1,723 deprecated Js.\* API calls** → migrate to @rescript/core equivalents
32+
(tracked in STATE.scm critical-next-actions)
33+
- [ ] **24 getExn/parseExn calls** in vm/idaptiky → SafeFloat/SafeJson
34+
- [ ] **5 duplicated %raw keyboard handler blocks** → extract to shared utility
35+
- [ ] **Axiom.jl**: Consolidate 2,857-line abstract.jl into 4+ focused files
36+
(see TODO-URGENT-COPROCESSOR-CONSOLIDATION.md)
37+
38+
## Infrastructure
39+
40+
- [ ] **TRANSFER-INSTRUCTIONS.md**: Execute when ready — transfer repo to Joshua's
41+
GitHub, re-add hyperpolymath as admin, set up secrets (GITLAB_TOKEN etc.)
42+
- [ ] **K9-SVC contractiles**: Deferred — add security boundaries for /db/portfolios/*
43+
and /db/campaigns/* when sync server gets real auth/multi-user.
44+
- [ ] **ratatui lru vuln** in escape-hatch: Upgrade available, quick Cargo.toml bump.
45+
46+
## Future Ideas
47+
48+
- [ ] **White paper**: "VerisimDB as Game Engine Persistence Layer" — legitimate
49+
academic/industry topic. VerisimDB's version-controlled hexads, similarity search,
50+
and graph queries for level data are novel. Could target game dev conferences
51+
(GDC, DiGRA) or database workshops (VLDB, SIGMOD industry track). Add to
52+
idaptik-developers docs when ready.
53+
54+
## Panicbot Follow-Up (Separate Repo)
55+
56+
- [ ] Expand panicbot to use all panic-attack subcommands (assault, ambush, amuck,
57+
abduct, axial, diff, a2ml-export) conditionally based on repo contents
58+
- [ ] Design missing panic-attacker subcommands: assassinate, affray, autopsy, attenuate
59+
- [ ] Chapel language support in panic-attacker (roadmap item, no code yet)
60+
- [ ] Panic-attacker scaling: hashing for mass fleet scans while staying USB-portable

idaptik-ums/Justfile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,36 @@ bench-cluster:
5252
done
5353
@echo "✅ Cluster initialized. Use 'epmd -names' to see the Generals."
5454

55+
# =============================================================================
56+
# TESTING
57+
# =============================================================================
58+
59+
# Run all tests: smoke + generator + Zig unit tests
60+
test:
61+
@echo "Running Deno tests (smoke + generator)..."
62+
deno test --allow-read tests/
63+
@echo "Running Zig FFI tests..."
64+
@if command -v zig >/dev/null; then \
65+
(cd ffi/zig && zig build test); \
66+
echo "Zig tests complete."; \
67+
else \
68+
echo "Zig compiler not found. Skipping Zig tests."; \
69+
fi
70+
@echo "All tests complete."
71+
72+
# Run benchmarks: Deno generators + Zig FFI solvers
73+
bench:
74+
@echo "Running Deno benchmarks..."
75+
deno bench --allow-read benches/
76+
@echo "Running Zig FFI benchmarks..."
77+
@if command -v zig >/dev/null; then \
78+
(cd ffi/zig && zig build bench); \
79+
echo "Zig benchmarks complete."; \
80+
else \
81+
echo "Zig compiler not found. Skipping Zig benchmarks."; \
82+
fi
83+
@echo "All benchmarks complete."
84+
5585
# =============================================================================
5686
# MASTER REALITY CHECK
5787
# =============================================================================

idaptik-ums/benches/.gitkeep

Whitespace-only changes.
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// SPDX-License-Identifier: PMPL-1.0-or-later
2+
// Generator module benchmarks for idaptik-level-architect.
3+
//
4+
// Measures throughput of all generator and codec operations.
5+
// Run after `npx rescript build` to ensure compiled modules exist.
6+
//
7+
// Usage:
8+
// deno bench --allow-read benches/generator_bench.mjs
9+
10+
const root = new URL("../", import.meta.url).href;
11+
12+
async function load(relPath) {
13+
return await import(new URL(relPath, root).href);
14+
}
15+
16+
// Pre-load all modules
17+
const A2mlWrapper = await load("src/generator/A2mlWrapper.res.mjs");
18+
const LevelGen = await load("src/generator/LevelGen.res.mjs");
19+
const NetworkGen = await load("src/generator/NetworkGen.res.mjs");
20+
const PowerGen = await load("src/generator/PowerGen.res.mjs");
21+
const BuildingMeta = await load("src/generator/BuildingMeta.res.mjs");
22+
const Portfolio = await load("src/generator/Portfolio.res.mjs");
23+
const CampaignGraph = await load("src/generator/CampaignGraph.res.mjs");
24+
const LevelExport = await load("src/generator/LevelExport.res.mjs");
25+
const LevelImport = await load("src/generator/LevelImport.res.mjs");
26+
const LevelConfigCodec = await load("src/LevelConfigCodec.res.mjs");
27+
28+
// ---------------------------------------------------------------------------
29+
// Fixtures — pre-generate data for codec benchmarks
30+
// ---------------------------------------------------------------------------
31+
32+
const level = LevelGen.generateWithRetry(42);
33+
const topology = NetworkGen.generateTopology(level);
34+
const powerMap = PowerGen.generatePowerMap(level);
35+
const meta = BuildingMeta.generateMeta(42, level.templateName);
36+
37+
const portfolio = Portfolio.addBuilding(
38+
Portfolio.create("Bench Portfolio", "For benchmarking"),
39+
level,
40+
topology,
41+
powerMap,
42+
);
43+
44+
const encodedPortfolio = Portfolio.encodePortfolio(portfolio);
45+
46+
let campaignGraph = CampaignGraph.create("bench-portfolio-1");
47+
campaignGraph = CampaignGraph.addEdge(campaignGraph, "a", "b", "Unlocks", "test", undefined);
48+
campaignGraph = CampaignGraph.addEdge(campaignGraph, "b", "c", "Branches", "branch", undefined);
49+
campaignGraph = CampaignGraph.addEdge(campaignGraph, "c", "d", "DeadEnd", "dead", undefined);
50+
51+
const encodedCampaign = CampaignGraph.encodeCampaignGraph(campaignGraph);
52+
53+
const levelJson = LevelExport.exportToJson(level, topology, powerMap);
54+
const a2mlPayload = JSON.stringify({ id: "bench-42", value: 1 });
55+
const a2mlMeta = A2mlWrapper.fromLevel(42, "Block");
56+
const wrappedA2ml = A2mlWrapper.wrapInA2ml(a2mlPayload, a2mlMeta);
57+
58+
// ---------------------------------------------------------------------------
59+
// Level Generation
60+
// ---------------------------------------------------------------------------
61+
62+
Deno.bench("levelgen:generate", () => {
63+
LevelGen.generate(42);
64+
});
65+
66+
Deno.bench("levelgen:generate-retry", () => {
67+
LevelGen.generateWithRetry(42);
68+
});
69+
70+
// ---------------------------------------------------------------------------
71+
// Network & Power Generation
72+
// ---------------------------------------------------------------------------
73+
74+
Deno.bench("networkgen:topology", () => {
75+
NetworkGen.generateTopology(level);
76+
});
77+
78+
Deno.bench("powergen:powermap", () => {
79+
PowerGen.generatePowerMap(level);
80+
});
81+
82+
// ---------------------------------------------------------------------------
83+
// Building Metadata
84+
// ---------------------------------------------------------------------------
85+
86+
Deno.bench("buildingmeta:generate", () => {
87+
BuildingMeta.generateMeta(42, "Block");
88+
});
89+
90+
// ---------------------------------------------------------------------------
91+
// A2ML Envelope
92+
// ---------------------------------------------------------------------------
93+
94+
Deno.bench("a2ml:wrap", () => {
95+
A2mlWrapper.wrapInA2ml(a2mlPayload, a2mlMeta);
96+
});
97+
98+
Deno.bench("a2ml:unwrap", () => {
99+
A2mlWrapper.unwrapA2ml(wrappedA2ml);
100+
});
101+
102+
// ---------------------------------------------------------------------------
103+
// Portfolio Encoding
104+
// ---------------------------------------------------------------------------
105+
106+
Deno.bench("portfolio:encode", () => {
107+
Portfolio.encodePortfolio(portfolio);
108+
});
109+
110+
Deno.bench("portfolio:decode", () => {
111+
Portfolio.decodePortfolio(encodedPortfolio);
112+
});
113+
114+
// ---------------------------------------------------------------------------
115+
// Campaign Graph Encoding
116+
// ---------------------------------------------------------------------------
117+
118+
Deno.bench("campaign:encode", () => {
119+
CampaignGraph.encodeCampaignGraph(campaignGraph);
120+
});
121+
122+
Deno.bench("campaign:decode", () => {
123+
CampaignGraph.decodeCampaignGraph(encodedCampaign);
124+
});
125+
126+
// ---------------------------------------------------------------------------
127+
// Level Export / Import Full Cycle
128+
// ---------------------------------------------------------------------------
129+
130+
Deno.bench("export:toJson", () => {
131+
LevelExport.exportToJson(level, topology, powerMap);
132+
});
133+
134+
Deno.bench("export:toA2ml", () => {
135+
LevelExport.exportToA2ml(level, topology, powerMap);
136+
});
137+
138+
Deno.bench("import:fromJson", () => {
139+
LevelImport.importFromJson(levelJson);
140+
});
141+
142+
// ---------------------------------------------------------------------------
143+
// Full Codec Roundtrip (encode → stringify → parse → decode)
144+
// ---------------------------------------------------------------------------
145+
146+
Deno.bench("codec:roundtrip-portfolio", () => {
147+
const enc = Portfolio.encodePortfolio(portfolio);
148+
Portfolio.decodePortfolio(enc);
149+
});
150+
151+
Deno.bench("codec:roundtrip-campaign", () => {
152+
const enc = CampaignGraph.encodeCampaignGraph(campaignGraph);
153+
CampaignGraph.decodeCampaignGraph(enc);
154+
});

idaptik-ums/deno.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
"tasks": {
33
"build": "just build",
44
"dev": "just dev",
5+
"test": "deno test --allow-read tests/",
6+
"bench": "deno bench --allow-read benches/",
57
"audit": "just audit",
68
"fmt": "just fmt",
79
"tauri:dev": "cargo tauri dev"

idaptik-ums/deno.lock

Lines changed: 38 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)