Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions apps/website/public/queen/models/LICENSE-kenney-hexagon-kit.txt

This file was deleted.

7 changes: 7 additions & 0 deletions apps/website/public/queen/models/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
The field draws no 3D models.

On 2026-09-06 the operator asked for the 3D objects to go: "убери 3D объекты
а то шума много", "замки не красиво смотрятся, а соты мёд пчёлы классно
читается". Every fact is now a cell - its rim, its cap, its colour - so the
Kenney Hexagon Kit (24 GLB, CC0) was removed along with the Space Kit before
it. Nothing here is loaded at runtime.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed apps/website/public/queen/models/hex-dirt.glb
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed apps/website/public/queen/models/hex-grass.glb
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed apps/website/public/queen/models/hex-stone.glb
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed apps/website/public/queen/models/hex-unit-tree.glb
Binary file not shown.
14 changes: 13 additions & 1 deletion apps/website/qa/queen-honesty-contract.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// source facts a regex CAN state. Node 22 needs --experimental-strip-types
// to import the TypeScript module; package.json passes it.
import { readFileSync } from "node:fs";
import { alertCount, alertSpan, beeSilence, buildingPlan, castlePlaces, epicProgress, familyTint, feedCoverage, ringFamily, ringOfEpic, ringSummary, towerStage, wallBetween, ringOfModulePath, epicOfIssue, hexRingCells, foundationCells, foundationOrder, hexCellCount, hexCentres, hexCorners, hexField, hexIndexAt, hexRing, hexRingStart, hexToWorld, honeyTone, layersFromSearch, spiralAxial, spiralIndex, spiralOrder, HEX_R, S_CELL, buildingTint, cellGeometry, countdownFor, eventIdentity, mergeActivity, serverOffsetMs, decisionDetail, fieldShape, moduleColumn, moduleFor, moduleId, pathInTitle, placeCards, rewriteEndpoints, ringOrder, ringTone, roundStrip, skipReasonWords, staleAge, territoryOf, planHash, withOpenIssues } from "../src/components/queenHud.ts";
import { alertCount, alertSpan, beeSilence, buildingPlan, castlePlaces, epicProgress, familyTint, feedCoverage, ringFamily, ringOfEpic, ringSummary, towerStage, wallBetween, ringOfModulePath, epicOfIssue, hexRingCells, foundationCells, foundationOrder, hexCellCount, hexCentres, hexCorners, hexField, hexIndexAt, hexRing, hexRingStart, hexToWorld, honeyTone, layersFromSearch, spiralAxial, spiralIndex, spiralOrder, HEX_R, S_CELL, buildingTint, cellGeometry, countdownFor, eventIdentity, mergeActivity, serverOffsetMs, decisionDetail, fieldShape, moduleColumn, moduleFor, moduleId, pathInTitle, placeCards, rewriteEndpoints, ringOrder, ringTone, roundStrip, skipReasonWords, staleAge, territoryOf, planHash, withOpenIssues, HIVE_TONES, hiveCoverOf, hiveKey, hiveToneOf } from "../src/components/queenHud.ts";

const fails = [];
let checks = 0;
Expand Down Expand Up @@ -177,11 +177,23 @@ check(ringOfModulePath("rings/SR-00") === "SR-00" && ringOfModulePath("rings/RUS
check(epicOfIssue(101, [ksEpic({ number: 9001, children: ksKids(3, 2) }), ksEpic({ number: 9002, children: [] })])?.number === 9001 && epicOfIssue(1, [ksEpic({ children: ksKids(3, 2) })]) === null, "epicOfIssue: the first epic listing the issue among its children, else null");
check(/data-working-age/.test(combSrc) && /kind === "finished" \|\| kind === "error"/.test(combSrc) && !/WORK_WINDOW_MS/.test(combSrc) && /const i = cellOfPath\(title\);/.test(combSrc), "work is a state, not an age: the cell is worked while the issue's LAST wire event is not terminal, and the age rides beside the count (measured 2026-09-06: the wire burst-delivers, newest row 18 min old while the swarm reported working)");
check(/if \(hover >= 0 && hover !== p && cells\[hover\]\) placeDashed/.test(combSrc), "every cell under the pointer lights up, not only the ones carrying a card");
check(!/\.glb/.test(combSrc) && !/LoadAssetContainerAsync/.test(combSrc) && /data-look", "hive"/.test(combSrc) && /CreateLineSystem\("queen-mark"/.test(combSrc), "the hive draws no model at all: no .glb is named, no asset container is loaded, and the Queen at the centre is the mark itself (the user, 2026-09-06)");
const SPACE_KIT = ["platform_small", "machine_generatorLarge", "satelliteDish_large", "hangar_smallA", "hangar_roundA", "structure_closed", "gate_complex", "crater", "hangar_largeA", "rock_crystalsLargeA", "astronautA", "astronautB", "rover", "alien"];
check(SPACE_KIT.every((m) => !combSrc.includes(m)), `the field draws one kit: no space-kit model may be named (${SPACE_KIT.filter((m) => combSrc.includes(m)).join(", ") || "none"})`);
check(/host\.setAttribute\("data-foundation-shape", "outline"\)/.test(combSrc) && /CreateLineSystem\("cells"/.test(combSrc) && !/CreateCylinder\("honey"/.test(combSrc) && !/hex-sand/.test(combSrc), "the cells are outlines: a line system per cell, no honey disc and no filled tile model (the user, 2026-09-06)");
check(/host\.setAttribute\("data-hover-issue"/.test(combSrc) && /queen27-hover-card/.test(combSrc), "a hovered cell names its GitHub issue on the host and in the card");
check(/host\.setAttribute\("data-castle-source", fdNow \? fdNow\.source : "none"\)/.test(combSrc) && /data-castle-stages/.test(combSrc) && /data-castle-unassigned/.test(combSrc), "the castle's testimony on the host comes from the snapshot's source, never a guess; stages and unassigned epics are named (K-2)");
check(HIVE_TONES.t27 === "#FFD45A" && HIVE_TONES.awaiting === "#64DCFF" && HIVE_TONES.manual === "#FF4D5E" && HIVE_TONES.hover === "#FFC24D", "the hive's colour law is exact: yellow T27, neon blue awaiting, red manual, honey only for the hand");
const claimed = new Set([hiveKey("Access Control")]);
check(hiveCoverOf("agent-server/apps/access-control", claimed) === "t27" && hiveCoverOf("agent-server/apps/manual", claimed) === "manual" && hiveCoverOf(null, claimed) === "awaiting" && hiveToneOf("manual")[0] > hiveToneOf("manual")[2], "cover is a claim against the module: T27, manual, or awaiting; no decoration chooses it");
check(/fieldRoot\.rotation\.x = Math\.PI \/ 2/.test(combSrc) && /new ArcRotateCamera\("cam", Math\.PI \/ 2, Math\.PI \/ 2/.test(combSrc) && /data-orientation", "facing"/.test(combSrc), "the comb is a wall facing the player, not a horizontal board (the user, 2026-09-06)");
check(/HIVE_TONES\.hover/.test(combSrc) && /hiveToneOf\(covers\[i\]\)/.test(combSrc) && /queen27-hive-law/.test(combSrc), "hover is honey while cell claims follow the law, and the legend names that law");
check(/fieldRoot\.position\.y = Math\.sin\(nowMs \/ 6400\) \* 7/.test(combSrc), "the wall floats; the drift is small enough not to steal the cell from under the pointer");
check(/camera\.target\.y \+= \(-anchor\.z - camera\.target\.y\) \* k/.test(combSrc) && /const p = planeAt\(x, y\)/.test(combSrc), "zoom and picking use the same vertical wall-plane coordinates");
check(/host\.setAttribute\("data-event-cards", String\(latest\.length\)\)/.test(combSrc) && /const EVENT_CARD_POOL = 12/.test(combSrc) && /new DynamicTexture\(`event-card-\$\{k\}`, 256/.test(combSrc), "the latest wire events become bounded display cards on their cells, capped at a readable twelve");
check(/function useT27Coverage\(\)/.test(src) && /fetch\("t27\/manifest\.json"/.test(src) && /spec\.repo !== "trinity"/.test(src) && /hiveKey\(value\)/.test(src), "yellow is claimed only by trinity rows read from the real T27 manifest, not by an issue label or a guess");
check(/hiveLawT27:\s*"T27 covered"/.test(src) && /hiveLawManual:\s*"manual code"/.test(src) && /hiveLawAwaiting:\s*"awaiting T27"/.test(src) && /hiveLawBees:\s*"bees"/.test(src), "the English colour-law words exist");
check(/hiveLawT27:\s*"покрыто T27"/.test(src) && /hiveLawManual:\s*"ручной код"/.test(src) && /hiveLawAwaiting:\s*"ждёт T27"/.test(src) && /hiveLawBees:\s*"пчёлы"/.test(src), "the Russian colour-law words exist");
check(decisionDetail({ allowed: false, refusal: null }, 0, 1, L) !== "0 executing now", "self-test");

if (fails.length) { for (const f of fails) console.log(" ✗ " + f); console.log(`Queen honesty contract: FAIL (${fails.length})`); process.exit(1); }
Expand Down
100 changes: 100 additions & 0 deletions apps/website/scripts/queen-kie-assets.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env node
// Optional KIE.AI asset front end for the hive display.
//
// Status, 2026-09-06: the supplied key is NOT usable. The API answers
// 401 Unauthorized / "Organization access is disabled", so this repository
// contains no generated cards and the Babylon comb remains pure geometry.
// Run this only after an organization-enabled KIE_API_KEY exists. The key is
// deliberately read from the environment and never written to git.
import { mkdir, writeFile } from "node:fs/promises";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const OUT_DIR = resolve(ROOT, "public/queen/kie");
const API = "https://api.kie.ai/api/v1";

const ASSETS = {
"event-card": "square card face for a dark science-fiction strategy HUD, raised honeycomb cell, deep near-black green background, one subtle honey-yellow border, crisp geometric slots for text, no letters, no numbers, no logos",
"cell-frame": "single hexagonal honeycomb frame for a dark science-fiction strategy game, precise thin luminous rim, near-black green interior, subtle depth and wax material, centered with clear outer margin, no text, no logo",
};

const args = process.argv.slice(2);
const argOf = (name) => {
const at = args.indexOf(`--${name}`);
return at >= 0 && args[at + 1] ? args[at + 1] : null;
};
const asset = argOf("asset") ?? "event-card";
const promptOverride = argOf("prompt");
const seed = Number.parseInt(argOf("seed") ?? "27050", 10);

if (!Object.hasOwn(ASSETS, asset)) {
console.error(`unknown --asset ${asset}; choose ${Object.keys(ASSETS).join(", ")}`);
process.exit(2);
}
if (!Number.isInteger(seed) || seed < 0 || seed > 2_147_483_647) {
console.error("--seed must be an integer from 0 through 2147483647");
process.exit(2);
}

const key = process.env.KIE_API_KEY;
if (!key) {
console.error("KIE_API_KEY is required. Do not paste keys into this script.");
process.exit(2);
}

const headers = { Authorization: `Bearer ${key}`, "Content-Type": "application/json" };
const request = async (url, init = {}) => {
const response = await fetch(url, { ...init, headers: { ...headers, ...(init.headers ?? {}) } });
const text = await response.text();
let body;
try { body = JSON.parse(text); } catch { body = { raw: text }; }
if (!response.ok) {
throw new Error(`KIE ${response.status}: ${typeof body === "object" ? body.msg ?? body.error ?? text : text}`);
}
return body;
};

const created = await request(`${API}/jobs/createTask`, {
method: "POST",
body: JSON.stringify({
model: "bytedance/seedream-v4-text-to-image",
input: {
prompt: promptOverride ?? ASSETS[asset],
image_size: "square_hd",
image_resolution: "1K",
max_images: 1,
seed,
nsfw_checker: true,
},
}),
});
const taskId = created?.data?.taskId ?? created?.result?.task_id ?? created?.task_id;
if (!taskId) throw new Error(`KIE created no task id: ${JSON.stringify(created)}`);
console.log(`KIE task ${taskId}`);

const deadline = Date.now() + 5 * 60_000;
let urls = [];
for (;;) {
await new Promise((r) => setTimeout(r, 4_000));
const record = await request(`${API}/jobs/recordInfo?taskId=${encodeURIComponent(taskId)}`);
const state = record?.data?.state ?? record?.state;
console.log(`state ${state}`);
if (state === "success") {
urls = record?.data?.resultUrls ?? record?.result_urls ?? record?.resultUrls ?? [];
break;
}
if (state === "failed" || Date.now() > deadline) {
throw new Error(`KIE task did not succeed: ${JSON.stringify(record).slice(0, 1000)}`);
}
}
if (urls.length === 0) throw new Error("KIE success carried no resultUrls");

await mkdir(OUT_DIR, { recursive: true });
for (const [n, url] of urls.entries()) {
const image = await fetch(url);
if (!image.ok) throw new Error(`download failed (${image.status})`);
const file = resolve(OUT_DIR, `${asset}-${seed}-${taskId}${n ? `-${n}` : ""}.png`);
await writeFile(file, Buffer.from(await image.arrayBuffer()));
console.log(file);
}
Loading
Loading