diff --git a/.gitattributes b/.gitattributes index 7f823e21d25b4ad569e5fd8e27ac932829856dae..6a8e7f5b2897dcda8c2bd1009aa0fdc69c1e0406 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,45 +1,4 @@ -*.7z filter=lfs diff=lfs merge=lfs -text -*.arrow filter=lfs diff=lfs merge=lfs -text -*.bin filter=lfs diff=lfs merge=lfs -text -*.bz2 filter=lfs diff=lfs merge=lfs -text -*.ckpt filter=lfs diff=lfs merge=lfs -text -*.ftz filter=lfs diff=lfs merge=lfs -text -*.gz filter=lfs diff=lfs merge=lfs -text -*.h5 filter=lfs diff=lfs merge=lfs -text -*.joblib filter=lfs diff=lfs merge=lfs -text -*.lfs.* filter=lfs diff=lfs merge=lfs -text -*.mlmodel filter=lfs diff=lfs merge=lfs -text -*.model filter=lfs diff=lfs merge=lfs -text -*.msgpack filter=lfs diff=lfs merge=lfs -text -*.npy filter=lfs diff=lfs merge=lfs -text -*.npz filter=lfs diff=lfs merge=lfs -text -*.onnx filter=lfs diff=lfs merge=lfs -text -*.ot filter=lfs diff=lfs merge=lfs -text -*.parquet filter=lfs diff=lfs merge=lfs -text -*.pb filter=lfs diff=lfs merge=lfs -text -*.pickle filter=lfs diff=lfs merge=lfs -text -*.pkl filter=lfs diff=lfs merge=lfs -text -*.pt filter=lfs diff=lfs merge=lfs -text -*.pth filter=lfs diff=lfs merge=lfs -text -*.rar filter=lfs diff=lfs merge=lfs -text -*.safetensors filter=lfs diff=lfs merge=lfs -text -saved_model/**/* filter=lfs diff=lfs merge=lfs -text -*.tar.* filter=lfs diff=lfs merge=lfs -text -*.tar filter=lfs diff=lfs merge=lfs -text -*.tflite filter=lfs diff=lfs merge=lfs -text -*.tgz filter=lfs diff=lfs merge=lfs -text -*.wasm filter=lfs diff=lfs merge=lfs -text -*.xz filter=lfs diff=lfs merge=lfs -text -*.zip filter=lfs diff=lfs merge=lfs -text -*.zst filter=lfs diff=lfs merge=lfs -text -*tfevents* filter=lfs diff=lfs merge=lfs -text -hero.png filter=lfs diff=lfs merge=lfs -text -assets/08_body_graph.png filter=lfs diff=lfs merge=lfs -text -assets/a11oy_avatar.png filter=lfs diff=lfs merge=lfs -text -assets/amaru_avatar.png filter=lfs diff=lfs merge=lfs -text -assets/rosie_avatar.png filter=lfs diff=lfs merge=lfs -text -assets/sentra_avatar.png filter=lfs diff=lfs merge=lfs -text -assets/vessels_avatar.png filter=lfs diff=lfs merge=lfs -text -assets/szl_banner.png filter=lfs diff=lfs merge=lfs -text -assets/group_shot_v1.png filter=lfs diff=lfs merge=lfs -text -roster.png filter=lfs diff=lfs merge=lfs -text +*.svg text eol=lf +*.html text eol=lf +*.json text eol=lf +*.md text eol=lf diff --git a/HONEST_DISCLOSURE.md b/HONEST_DISCLOSURE.md index c52212f9eda01cbb633fdd9e6a911f2036dd4b18..5db572debaca6460950f13cd8c57cd04a64cbd86 100644 --- a/HONEST_DISCLOSURE.md +++ b/HONEST_DISCLOSURE.md @@ -1,25 +1,25 @@ -# What is honest right now — Doctrine v11 +# Honest disclosure -This is the standing honesty disclosure for SZL Holdings. We surface only machine-checked facts as fact; everything else is labeled experimental, conditional, or conjectured. +This static Space is the public Hugging Face front door for SZL Holdings. It +organizes links and describes publication contracts. It is not a model, +benchmark, customer deployment, certification, authorization to operate, or +independent third-party assessment. -**lutar-lean @ tag `lutar-v18.0.0` / `c7c0ba17`:** +## What the running page proves -- **749 declarations · 14 unique axioms · 163 tracked sorries** (112 baseline + 51 Putnam). `lake build` clean. -- **Locked proven set = 5 formulas** (Lean, sorry-free): **F1, F11, F12, F18, F19**. These are the only formulas we surface as "proven." -- **Λ (the trust aggregator) is Conjecture 1** unconditionally. **Unconditional** uniqueness is machine-checked **false** (Round13 `maxAgg_ne_Lambda`). It is proven **CONDITIONAL** on slice-multiplicativity (separability) under {A1,A2,A3,A5}, axiom-free — **CUT-2** (`lambda_unique_of_separable`, PR #202). Λ is never stated as an unconditional theorem. **Byzantine BFT safety is Conjecture 2**, not a theorem. -- **Experimental waves** (proof waves 5–14 + the agentic loop) live in experimental Lean scopes on `main` @ `b910c276`, are **CI-green** with every `#print axioms ⊆ {propext, Classical.choice, Quot.sound}`, but **excluded** from the locked v11 baseline. Through Wave 14: Wave 11 CF-1/2/3/5, Wave 12 CUT-2 + CF-13 + CF-17, Wave 13 replay-root + non-Byzantine vote + HM-bottleneck, Wave 14 CF-18/19/20/21. They are labeled experimental, never folded into the locked five. +- the static route was reachable at the time it was requested; +- the served `deployment.json` identifies a GitHub source revision; +- the declared source files can be compared with that revision and the Hub + commit recorded by the deployment workflow. -**Supply chain:** -- **SLSA L1 build provenance (honest)** on all service images — cosign-signed, verifiable via `cosign verify`. **SLSA L2 is on the roadmap; we do NOT claim L2-verified today.** **No** L2-verified / L3 / FedRAMP / Iron Bank / CMMC is claimed. -- The `szl-mesh` UDS bundle is **cosign-signed** (keyless OIDC). The GitHub attestation for the bundle itself was not minted (token scope); per-image cosign signatures are intact and verifiable. +## What it does not prove -**Receipts:** -- Decision receipts are **DSSE envelopes over a SHA-256 hash chain**. Where a signing key is present (the killinchu engagement surface carries a real ECDSA-P256 cosign key), receipts are **genuinely signed** and verifiable offline. Where no key is present, receipts are **honestly marked unsigned** — never fabricated. +- that every linked model loads or meets its intended quality threshold; +- that every dataset row has passed provenance and license admission; +- that every Space is healthy end to end; +- that a signature establishes accuracy, safety, compliance, or fitness; +- that Hub download events are unique users, customers, or deployments. -**Data honesty:** -- Maritime AIS on the field surface uses a clearly-labeled **sample/replay** dataset, not a live production feed. -- Live public feeds (CVE/NVD, CISA KEV, MITRE ATT&CK, USGS) are honestly attributed where shown. - -**Compliance posture:** Aligned with **EU AI Act Article 12** (record-keeping) + **NIST AI RMF (MANAGE)**. These are alignment statements, not certifications. - -*Built by Stephen P. Lutar Jr. · stephenlutar2@gmail.com · Doctrine v11 LOCKED.* +Each artifact owns its evaluation, provenance, security, and runtime evidence. +Unverified evidence must remain `UNKNOWN`, `PARTIAL`, or `UNAVAILABLE` rather +than being inferred from this organization card. diff --git a/README.md b/README.md index e3a348ccf0c74a1a6624160c54f5908275784edb..987d688a5b3b0c4b5dcf4410a3d7d8c5e36650d9 100644 --- a/README.md +++ b/README.md @@ -1,117 +1,135 @@ --- -title: SZL Holdings — Governed-AI Command Platform +title: SZL Holdings — Governed Decision Infrastructure emoji: 🛡️ colorFrom: gray colorTo: yellow sdk: static -short_description: Governed AI you can prove — signed, verifiable receipts +short_description: Governed AI that can explain, constrain, and verify action pinned: true +license: apache-2.0 --- - -

SZL Holdings — governed, receipted, verifiable

+ +

- live evidence wall - szl-lake - holographic - github org + SZL Holdings — autonomy, under authority

-
-SZL Holdings — Governed AI you can prove +# Governed models, data, and demonstrations -# SZL Holdings +SZL Holdings publishes the model and data layer for systems that must reason, +act within authority, and return evidence another party can verify. -### Governed AI you can prove. +[**Open a11oy**](https://a-11-oy.com) · +[**Inspect evidence**](https://a11oy.net) · +[**View source**](https://github.com/szl-holdings) · +[**Read documentation**](https://holdings.a-11-oy.com/docs-site/) -Models ship with signed training & eval receipts. Surfaces label every value — LIVE, MEASURED, REPORTED, or DEMO. Trust is measured — not asserted. +
-

+--- -[![Proof](https://img.shields.io/badge/proof-verifiable-3af4c8?style=flat-square)](https://a-11-oy.com) -[![Lattice](https://img.shields.io/badge/lattice-8%20locked--proven-5b8dee?style=flat-square)](https://a-11-oy.com/holographic) -[![Λ Conjecture 1](https://img.shields.io/badge/%CE%9B-Conjecture%201-d7b96b?style=flat-square)](https://doi.org/10.5281/zenodo.19944926) -[![SLSA](https://img.shields.io/badge/SLSA-L1%20honest%20%C2%B7%20L2%20attested%20%C2%B7%20L3%20roadmap-7e8aa3?style=flat-square)](https://slsa.dev/spec/v1.0/levels) -[![Trust ceiling](https://img.shields.io/badge/trust%20ceiling-0.97-3af4c8?style=flat-square)](https://a-11-oy.com) -[![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.19944926-d7b96b?style=flat-square)](https://doi.org/10.5281/zenodo.19944926) +## Start here -

+| Need | Canonical artifact | Boundary | +| --- | --- | --- | +| Governed receipt generation | [SZL-Forge-1.5B-ReceiptAgent](https://huggingface.co/SZLHOLDINGS/SZL-Forge-1.5B-ReceiptAgent) | A model artifact; autonomy requires a validating controller | +| Grounded estate navigation | [SZL-Khipu-1.5B](https://huggingface.co/SZLHOLDINGS/SZL-Khipu-1.5B) | Use cited retrieval and verify sources independently | +| Local quantized evaluation | [SZL-Khipu-1.5B-GGUF](https://huggingface.co/SZLHOLDINGS/SZL-Khipu-1.5B-GGUF) | Quantization changes runtime characteristics; evaluate the exact file | +| Receipt and evidence records | [szl-lake](https://huggingface.co/datasets/SZLHOLDINGS/szl-lake) | Records are admitted by their own provenance and license state | +| Public OSINT corpus | [killinchu-osint-corpus](https://huggingface.co/datasets/SZLHOLDINGS/killinchu-osint-corpus) | Public-source research corpus; not an operational intelligence feed | +| Product demonstration | [a11oy Space](https://huggingface.co/spaces/SZLHOLDINGS/a11oy) | A demonstration surface; verify live state and exact source separately | -**[🛡️ Enter a11oy →](https://a-11-oy.com)** · **[Browse 70+ live surfaces →](https://a-11-oy.com/holographic)** · **[Read Conjecture 1 →](https://doi.org/10.5281/zenodo.19944926)** +Download counters are Hub-reported events, not unique users, deployments, +customers, model quality, or revenue. - +## Artifact contract ---- +Every promoted artifact must identify what it is and what evidence exists. -## The one-of-one hook: models that ship with receipts +### Trained weights -Anyone can publish weights. We publish **proof**. Every SZL model carries its training and evaluation receipts in-repo — `training_receipt.signed.json` and `eval_receipt.signed.json`, **Ed25519 signatures over canonical JSON**, verifiable offline against the repo-declared public key. (The a11oy estate's daily operational receipts are a separate rail: DSSE envelopes, sigstore-keyless.) You can verify what a model was trained on and how it scored *before* you download it. That's the honesty doctrine, made checkable. +- exact base model and license lineage; +- weight or adapter hashes; +- clean load and inference receipt; +- held-out and adversarial evaluation; +- restart and reproduction evidence; +- latency, memory, and energy context; +- an explicit autonomy boundary. -- **LIVE** surfaces are live. **MEASURED** numbers are measured. **REPORTED** is reported. **DEMO** is a demo. We label which is which. -- The lattice is **exactly 8 locked-proven formulas** — {F1, F4, F7, F11, F12, F18, F19, F22}. Not 9. Not "soon." -- **Λ is Conjecture 1** — an open conjecture, never a theorem, never marked green. -- Trust tops out at **0.97**, never 100%. A ceiling is honest; certainty is not. +### Datasets ---- +- source and license provenance at row or source-family scope; +- schema, splits, sizes, and validation results; +- privacy, consent, PII, and update policy; +- known omissions, quarantine counts, and intended use. -## Start here +### Kernels and tools -### 🤖 Models — every one ships with signed receipts +- canonical source repository and immutable revision; +- supported hardware and software matrix; +- executable tests and benchmark protocol; +- no implied training receipt or model capability. -**Start with [SZL-Khipu-1.5B](https://huggingface.co/SZLHOLDINGS/SZL-Khipu-1.5B)** — a compact 1.5B model for governed agent navigation, and the fastest way to understand the whole estate: weights, signed receipts, public eval harness, and a local one-liner (`ollama run hf.co/SZLHOLDINGS/SZL-Khipu-1.5B-GGUF:Q4_K_M`) in one repo. +### Spaces -| Model | Base · Task | Traction (MEASURED all-time, 2026-07-21) | Notes | -|---|---|---|---| -| [**SZL-Khipu-1.5B**](https://huggingface.co/SZLHOLDINGS/SZL-Khipu-1.5B) | Qwen2.5 1.5B · governed navigation | **1,391** downloads (day-1: 1.03k) | **Start here.** Signed receipts + public harness; [GGUF →](https://huggingface.co/SZLHOLDINGS/SZL-Khipu-1.5B-GGUF) | -| [**SZL-Forge-1.5B-ReceiptAgent**](https://huggingface.co/SZLHOLDINGS/SZL-Forge-1.5B-ReceiptAgent) | Qwen2 1.5B · receipt agent | **2,026** downloads | Receipt-native sibling forge; signed receipts in-repo | -| [**SZL-Khipu-1.5B-GGUF**](https://huggingface.co/SZLHOLDINGS/SZL-Khipu-1.5B-GGUF) | quantized Khipu | **656** downloads | Q4_K_M · Q5_K_M · Q8_0 · F16; Ollama-ready; receipts travel | +- canonical source and deployment revision; +- pinned dependencies and runtime behavior; +- privacy and retention behavior; +- visible limitations and reproducible local path. -Counters are HF-reported all-time downloads, snapshotted daily → [szl-telemetry TRENDS](https://github.com/szl-holdings/szl-telemetry/blob/telemetry-data/TRENDS.md) (deltas DERIVED). +A model card is not operational proof. A Space in `RUNNING` state proves +transport availability only. A signed receipt establishes integrity and origin +within its stated scope; it does not automatically establish correctness, +safety, or authorization to operate. -### 📊 Datasets — 30 total, receipts on the record +## One governed loop -| Dataset | Downloads | What it is | -|---|---|---| -| [**killinchu-osint-corpus**](https://huggingface.co/datasets/SZLHOLDINGS/killinchu-osint-corpus) | **24,737** `MEASURED all-time 2026-07-21` | OSINT corpus behind the killinchu demo | -| [**a11oy-verifiable-corpus**](https://huggingface.co/datasets/SZLHOLDINGS/a11oy-verifiable-corpus) | **2,282** `MEASURED all-time 2026-07-21` | Verifiable-claims corpus for governed eval | -| [**szl-lake**](https://huggingface.co/datasets/SZLHOLDINGS/szl-lake) | **1,459** `MEASURED all-time 2026-07-21` | The Khipu receipt lake — published signed-receipt chain | +```text +signal → reason → policy → bounded action → receipt → independent verification + ↑ │ + └──────────── verified feedback ───────┘ +``` -### 🌐 Live surfaces +The model proposes. The controller validates authority and evidence. The +runtime executes only within a declared bound. The receipt lets a separate +party inspect what happened. -| Surface | Status | Link | -|---|---|---| -| **a11oy console** — the flagship | `LIVE` | [a-11-oy.com](https://a-11-oy.com) | -| **Holographic** — 70+ live surfaces | `LIVE` | [/holographic](https://a-11-oy.com/holographic) | -| **killinchu** — counter-UAS & maritime C2 demo | `DEMO` | [open →](https://szlholdings-killinchu.hf.space/) | -| **Estate hub** — live index of every Space | `LIVE` | [open →](https://szlholdings-szl-estate-live.static.hf.space) | +## Evidence language ---- +Claims use **PROVED**, **MEASURED**, **REPORTED**, **MODELED**, +**CONJECTURE**, or **ROADMAP**. Runtime status uses **OPERATIONAL**, +**PARTIAL**, **DEGRADED**, **UNAVAILABLE**, or **HISTORICAL**. -## Collections & highlights +Lambda uniqueness remains **Conjecture 1**, not a theorem. No artifact is +promoted solely because it has a card, a counter, a live route, or a filename +that sounds like a model. -
+## Source and support -SZL model & dataset roster +This company front door is source-controlled at +[`szl-holdings/.github`](https://github.com/szl-holdings/.github/tree/main/huggingface/org-card) +and deployed with an exact source-revision manifest. Inspect +[`deployment.json`](https://szlholdings-readme.static.hf.space/deployment.json) +on the running static Space for the served source binding. -
- -- **🤖 Receipt-native models** — SZL-Forge, SZL-Khipu. Weights + signed receipts, together. -- **📊 The lake (30 datasets)** — OSINT, verifiable-claims, and curated corpora. -- **🌐 The a11oy surfaces** — the flagship console plus 70+ holographic surfaces. -- **📐 The lattice** — 8 locked-proven formulas and the Λ conjecture, DOI-anchored. - -*See the pinned models, datasets, and Spaces on this org page to jump straight in.* +- [Security policy](https://github.com/szl-holdings/.github/security/policy) +- [Trust posture](https://github.com/szl-holdings/.github/blob/main/TRUST.md) +- [Support](https://github.com/szl-holdings/.github/blob/main/SUPPORT.md) +- [Honest disclosure](./HONEST_DISCLOSURE.md) ---
-### Governed AI you can prove. - -**[🛡️ a-11-oy.com](https://a-11-oy.com)** · **[Live surfaces](https://a-11-oy.com/holographic)** · **[GitHub](https://github.com/szl-holdings)** · **[DOI 10.5281/zenodo.19944926](https://doi.org/10.5281/zenodo.19944926)** +**Govern · execute · prove** -SLSA: L1 honest · L2 attested · L3 roadmap. Λ = Conjecture 1. Trust ceiling 0.97. Labels honest by default. +[a-11-oy.com](https://a-11-oy.com) · +[a11oy.net](https://a11oy.net) · +[GitHub](https://github.com/szl-holdings)
diff --git a/SPACE_PROVENANCE.json b/SPACE_PROVENANCE.json deleted file mode 100644 index faea4d8657e7a9d5cd57d5a1d12817d47e7f5ed5..0000000000000000000000000000000000000000 --- a/SPACE_PROVENANCE.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "schema": "szl.space-source-attestation/v1", - "observed_at": "2026-07-12T01:54:25Z", - "space": { - "id": "SZLHOLDINGS/README", - "repository_type": "space", - "sdk": "static", - "runtime_stage_observed": "RUNNING", - "artifact_kind": "space-repository-snapshot", - "purpose": "Static organization portfolio and governed-AI entry surface.", - "source_files_reviewed": [ - "README.md", - "HONEST_DISCLOSURE.md", - "index.html", - "js/main.js" - ] - }, - "source_of_record": { - "state": "VERIFIED_HF_SOURCE_OF_RECORD", - "relation": "hf-native-source-of-record", - "platform": "huggingface", - "repository": "SZLHOLDINGS/README", - "artifact_base_revision": "fae3dcb371bce070f1ba4cf0fe1083ad8657117b", - "artifact_base_state": "MEASURED_PRE_ATTESTATION_BASE", - "artifact_base_url": "https://huggingface.co/spaces/SZLHOLDINGS/README/tree/fae3dcb371bce070f1ba4cf0fe1083ad8657117b", - "file_count": 52, - "total_bytes": 11154868, - "tree_sha256": "358d0aaa8224a17883aaaef535ce95d886f09f5fc67ed62eff8a833cfdd6f9a5", - "tree_hash_algorithm": "sha256 of UTF-8 path + NUL + per-file content sha256 + LF, sorted by path; .cache excluded" - }, - "public_github": { - "state": "NO_DIRECT_PUBLIC_SAME_NAME_REPOSITORY_OBSERVED", - "same_name_candidate": "https://github.com/szl-holdings/README", - "same_name_candidate_http_status": 404, - "observation_semantics": "A public 404 does not establish the absence of a private repository.", - "contextual_references": [ - "https://github.com/szl-holdings", - "https://github.com/szl-holdings/governed-receipt-spec", - "https://github.com/szl-holdings/lutar-lean", - "https://github.com/szl-holdings/szl-papers" - ], - "contextual_reference_role": "DOCUMENTATION_RESEARCH_DEPENDENCY_OR_ORGANIZATION_CONTEXT_NOT_BUILD_SOURCE_PARITY" - }, - "claims": { - "full_github_repository_parity": "NOT_CLAIMED", - "reproducible_build": "NOT_CLAIMED", - "binary_provenance": "NOT_CLAIMED", - "serving_process_revision": "NOT_CLAIMED" - }, - "limits": [ - "The attestation overlay cannot self-embed its resulting Hub commit, so artifact_base_revision is the immutable measured pre-overlay tree.", - "Repository-head evidence does not prove the exact serving-process revision during a rolling deployment.", - "Reproducible build, binary provenance, and serving-process identity are not claimed.", - "No claim is made about private repositories or unobserved producer systems." - ] -} diff --git a/SZL_ESTATE_MANAGED.json b/SZL_ESTATE_MANAGED.json deleted file mode 100644 index a302d6a44f9efcedc81f40f7bf9381e1bcdd1505..0000000000000000000000000000000000000000 --- a/SZL_ESTATE_MANAGED.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "canonical_flagship": "https://github.com/szl-holdings/a11oy", - "canonical_github_org": "https://github.com/szl-holdings", - "canonical_rule": "GitHub source, protected CI, release receipts, checksums, and provenance are authoritative. Hugging Face is the managed Hub surface.", - "clone_of": null, - "generation": "3c20fe2a6b0c9c56a045265b194a81e952fc949c", - "managed_at": "2026-07-22T08:49:51.422140+00:00", - "non_destructive": true, - "observed_sha_before_upgrade": "c1727a3c3bf502441e6818d5efcc52a8740f99a8", - "organization": "SZLHOLDINGS", - "repo_id": "SZLHOLDINGS/README", - "repo_type": "space", - "runtime": { - "hardware": { - "current": null, - "requested": null - }, - "requested_hardware": null, - "sdk": "static", - "stage": "RUNNING", - "storage": null - }, - "schema": "szl.hf-estate-managed/v1" -} diff --git a/assets/08_body_graph.png b/assets/08_body_graph.png deleted file mode 100644 index c2b9283277e8f229acea912de198e8dc9de0b4d7..0000000000000000000000000000000000000000 --- a/assets/08_body_graph.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bc9e0dfde31cbd043add80d719cbb975a2d4b11e9115abb3c046e5e51f0ee2e4 -size 169734 diff --git a/assets/a11oy_avatar.png b/assets/a11oy_avatar.png deleted file mode 100644 index aa47b83400cf98b19d3477a138033e28d0ab0acb..0000000000000000000000000000000000000000 --- a/assets/a11oy_avatar.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:28f749cf9e2b88b3f29aad1576eb81607db8902896c2fa6558c22e53a5183373 -size 1268449 diff --git a/assets/action/a11oy.webp b/assets/action/a11oy.webp deleted file mode 100644 index 5e21e9efa98cbdc05845e4d5747bfb7a58e1accf..0000000000000000000000000000000000000000 Binary files a/assets/action/a11oy.webp and /dev/null differ diff --git a/assets/action/a11oy_still.webp b/assets/action/a11oy_still.webp deleted file mode 100644 index 0eebee8d2b76505fb03d426276fb4f05f62d480a..0000000000000000000000000000000000000000 Binary files a/assets/action/a11oy_still.webp and /dev/null differ diff --git a/assets/action/amaru.webp b/assets/action/amaru.webp deleted file mode 100644 index 243a67bc5512fe2d600a7eb3cb3d18bc1495cd27..0000000000000000000000000000000000000000 Binary files a/assets/action/amaru.webp and /dev/null differ diff --git a/assets/action/amaru_still.webp b/assets/action/amaru_still.webp deleted file mode 100644 index 82f82564a8c85914639497c8a70258b643aad75d..0000000000000000000000000000000000000000 Binary files a/assets/action/amaru_still.webp and /dev/null differ diff --git a/assets/action/doug.webp b/assets/action/doug.webp deleted file mode 100644 index ae2a72c4bc4f068be5526372ae99d3dfd7034962..0000000000000000000000000000000000000000 Binary files a/assets/action/doug.webp and /dev/null differ diff --git a/assets/action/doug_still.webp b/assets/action/doug_still.webp deleted file mode 100644 index ce2badfe4768029e4e2cb10c07f2d21f820f9788..0000000000000000000000000000000000000000 Binary files a/assets/action/doug_still.webp and /dev/null differ diff --git a/assets/action/rosie.webp b/assets/action/rosie.webp deleted file mode 100644 index 3516066ac7b8bbc619c5b063e90733ac67ce707c..0000000000000000000000000000000000000000 Binary files a/assets/action/rosie.webp and /dev/null differ diff --git a/assets/action/rosie_still.webp b/assets/action/rosie_still.webp deleted file mode 100644 index 5c610d57938dcca02032bc9240b409f40573fcd2..0000000000000000000000000000000000000000 Binary files a/assets/action/rosie_still.webp and /dev/null differ diff --git a/assets/action/sentra.webp b/assets/action/sentra.webp deleted file mode 100644 index 49d86a32549e90440385879ec9b854ea175cb3b1..0000000000000000000000000000000000000000 Binary files a/assets/action/sentra.webp and /dev/null differ diff --git a/assets/action/sentra_still.webp b/assets/action/sentra_still.webp deleted file mode 100644 index cfdf12f5c2d16c43ed3d3256fe8e327e507eb791..0000000000000000000000000000000000000000 Binary files a/assets/action/sentra_still.webp and /dev/null differ diff --git a/assets/action/vessels.webp b/assets/action/vessels.webp deleted file mode 100644 index 55951209b18e57d418cc452c78b3357646b390fe..0000000000000000000000000000000000000000 Binary files a/assets/action/vessels.webp and /dev/null differ diff --git a/assets/action/vessels_still.webp b/assets/action/vessels_still.webp deleted file mode 100644 index f7d6b9a3bc7c4e9829273e7fae669e88cb2e04f7..0000000000000000000000000000000000000000 Binary files a/assets/action/vessels_still.webp and /dev/null differ diff --git a/assets/amaru_avatar.png b/assets/amaru_avatar.png deleted file mode 100644 index c547560163e585df9d811d7da701d83939e28846..0000000000000000000000000000000000000000 --- a/assets/amaru_avatar.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5aa6611082b807115626ea313a5333f96659b9450711e6aa48221e70e9409d3e -size 1301859 diff --git a/assets/emoji/a11oy_emoji.png b/assets/emoji/a11oy_emoji.png deleted file mode 100644 index e02c587ed64930a7b4b245f93a90bf8eefe4d052..0000000000000000000000000000000000000000 Binary files a/assets/emoji/a11oy_emoji.png and /dev/null differ diff --git a/assets/emoji/amaru_emoji.png b/assets/emoji/amaru_emoji.png deleted file mode 100644 index f8fab6301f1cf1cb7007746023c859e03eab6257..0000000000000000000000000000000000000000 Binary files a/assets/emoji/amaru_emoji.png and /dev/null differ diff --git a/assets/emoji/rosie_emoji.png b/assets/emoji/rosie_emoji.png deleted file mode 100644 index bea119f1fd0446aee49ffec18379def6bd95ed12..0000000000000000000000000000000000000000 Binary files a/assets/emoji/rosie_emoji.png and /dev/null differ diff --git a/assets/emoji/sentra_emoji.png b/assets/emoji/sentra_emoji.png deleted file mode 100644 index 6b5c4e19f20d1eb7699c2cbb5975c2013b67faac..0000000000000000000000000000000000000000 Binary files a/assets/emoji/sentra_emoji.png and /dev/null differ diff --git a/assets/emoji/vessels_emoji.png b/assets/emoji/vessels_emoji.png deleted file mode 100644 index 732d1abc283b8234cb17f500b29bc446a8b95c7f..0000000000000000000000000000000000000000 Binary files a/assets/emoji/vessels_emoji.png and /dev/null differ diff --git a/assets/estate-banner-v2.svg b/assets/estate-banner-v2.svg deleted file mode 100644 index 92dbb7ba717aeba8bbafac849f31f74d103568d3..0000000000000000000000000000000000000000 --- a/assets/estate-banner-v2.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - SZL HOLDINGS - GOVERNED · RECEIPTED · VERIFIABLE - every claim carries a checkable receipt — doctrine v11 · Λ = Conjecture 1 (advisory) - diff --git a/assets/estate-command-system.svg b/assets/estate-command-system.svg new file mode 100644 index 0000000000000000000000000000000000000000..419b64f8c94cbc37b38d46305c144a7eb6b89023 --- /dev/null +++ b/assets/estate-command-system.svg @@ -0,0 +1,97 @@ + + SZL Holdings governed decision infrastructure + A dark command-system diagram showing signals passing through policy, bounded action, receipts, and independent verification. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SZL HOLDINGS / CONTROL + EVIDENCE + + + Autonomy, under authority. + Governed decision infrastructure for systems that must explain, + constrain, and verify action. + + + + GOVERN + + EXECUTE + + PROVE + + + + + + + + SIGNAL + + + + POLICY + + + + BOUNDED ACTION + + + + RECEIPT + + + + VERIFY + + + + + + + + + + + + + OUROBOROS GOVERNED LOOP + REASON ↔ REALITY / RECEIPT AT THE CROSSING + + + DECISION SYSTEMS · SOVEREIGN RUNTIME · PORTABLE EVIDENCE + + diff --git a/assets/group_shot_v1.png b/assets/group_shot_v1.png deleted file mode 100644 index 6409c9d79f99057ddc5a7a395f525adc4e1f4469..0000000000000000000000000000000000000000 --- a/assets/group_shot_v1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d60a6bed5ba254414db081cfd928e75d097175aaf720ebf021124a82adf2fff8 -size 581354 diff --git a/assets/mesh_cathedral.jpg b/assets/mesh_cathedral.jpg deleted file mode 100644 index b01309419304fb272fab8d5be0859c4833c71c9b..0000000000000000000000000000000000000000 Binary files a/assets/mesh_cathedral.jpg and /dev/null differ diff --git a/assets/phd_api_badge.png b/assets/phd_api_badge.png deleted file mode 100644 index a04f788fdc17ceaa8c0425d297ceb241485ed299..0000000000000000000000000000000000000000 Binary files a/assets/phd_api_badge.png and /dev/null differ diff --git a/assets/phd_comment_sweep_badge.png b/assets/phd_comment_sweep_badge.png deleted file mode 100644 index 1130177a51cb30ad1289b495276e4b9425ebcc66..0000000000000000000000000000000000000000 Binary files a/assets/phd_comment_sweep_badge.png and /dev/null differ diff --git a/assets/phd_crypto_badge.png b/assets/phd_crypto_badge.png deleted file mode 100644 index 598967b55c5cce15485573c282d721a855b7a971..0000000000000000000000000000000000000000 Binary files a/assets/phd_crypto_badge.png and /dev/null differ diff --git a/assets/phd_frontend_badge.png b/assets/phd_frontend_badge.png deleted file mode 100644 index 139bf5ae46023588379dc085663fa00ec6861b83..0000000000000000000000000000000000000000 Binary files a/assets/phd_frontend_badge.png and /dev/null differ diff --git a/assets/phd_governance_badge.png b/assets/phd_governance_badge.png deleted file mode 100644 index dbf8641844558d9ae8849d5322af2baaac85bc75..0000000000000000000000000000000000000000 Binary files a/assets/phd_governance_badge.png and /dev/null differ diff --git a/assets/phd_math_badge.png b/assets/phd_math_badge.png deleted file mode 100644 index b956c049d4b06aad736208bc5c4bea2ebb4a0d3c..0000000000000000000000000000000000000000 Binary files a/assets/phd_math_badge.png and /dev/null differ diff --git a/assets/phd_secops_badge.png b/assets/phd_secops_badge.png deleted file mode 100644 index 631472afddb2726fb37704b68101cb70c854e452..0000000000000000000000000000000000000000 Binary files a/assets/phd_secops_badge.png and /dev/null differ diff --git a/assets/phd_systems_badge.png b/assets/phd_systems_badge.png deleted file mode 100644 index d1cf45c35118d46f0fbd09a8c7b06371eb7488e1..0000000000000000000000000000000000000000 Binary files a/assets/phd_systems_badge.png and /dev/null differ diff --git a/assets/rosie/rosie-widget.css b/assets/rosie/rosie-widget.css deleted file mode 100644 index b0fd2b4a92526df49c98ce00e11fa015e940d763..0000000000000000000000000000000000000000 --- a/assets/rosie/rosie-widget.css +++ /dev/null @@ -1,388 +0,0 @@ -/* rosie-widget.css — floating operator widget for SZL Holdings surfaces. - Dark-glass Vessels DNA: deep purple glass, gold hairlines, JetBrains Mono. - Rosie's own accent is coral-rose. No external dependencies. */ - -:root { - --rz-coral: #ff7a59; - --rz-coral-soft: rgba(255, 122, 89, 0.18); - --rz-gold: #d4af37; - --rz-gold-dim: rgba(212, 175, 55, 0.55); - --rz-border: rgba(212, 175, 55, 0.18); - --rz-glass: rgba(26, 15, 46, 0.92); - --rz-glass-soft: rgba(45, 27, 94, 0.55); - --rz-purple-deep: #14091f; - --rz-text: #f3ecff; - --rz-text-muted: rgba(243, 236, 255, 0.62); - --rz-ok: #4caf50; - --rz-warn: #e53935; - --rz-font-mono: 'JetBrains Mono', 'Fira Code', ui-monospace, SFMono-Regular, Menlo, monospace; - --rz-font-body: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; - --rz-z: 2147483000; -} - -/* ---- Root container ---- */ -.rz-root { - position: fixed; - right: 20px; - bottom: 20px; - z-index: var(--rz-z); - font-family: var(--rz-font-body); - color: var(--rz-text); - -webkit-font-smoothing: antialiased; -} -.rz-root *, -.rz-root *::before, -.rz-root *::after { - box-sizing: border-box; -} - -/* ---- Floating button (FAB) ---- */ -.rz-fab { - width: 64px; - height: 64px; - border-radius: 50%; - border: 1.5px solid var(--rz-border); - padding: 0; - cursor: pointer; - background: var(--rz-glass); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45), 0 0 22px rgba(255, 122, 89, 0.18); - overflow: hidden; - display: grid; - place-items: center; - position: relative; - transition: transform 0.18s ease, box-shadow 0.18s ease; - animation: rz-breathe 4.5s ease-in-out infinite; -} -.rz-fab:hover { - transform: translateY(-2px) scale(1.04); - box-shadow: 0 10px 34px rgba(0, 0, 0, 0.5), 0 0 30px rgba(255, 122, 89, 0.3); -} -.rz-fab:focus-visible { - outline: 2px solid var(--rz-coral); - outline-offset: 3px; -} -.rz-fab img { - width: 100%; - height: 100%; - object-fit: cover; - object-position: center 28%; - display: block; - pointer-events: none; - user-select: none; -} -/* Fallback monogram if the portrait fails to load */ -.rz-fab .rz-fab-fallback { - font-family: var(--rz-font-mono); - font-size: 22px; - font-weight: 700; - color: var(--rz-coral); -} - -@keyframes rz-breathe { - 0%, 100% { transform: scale(1); } - 50% { transform: scale(1.035); } -} - -/* ---- Notification badge dot ---- */ -.rz-badge { - position: absolute; - top: 2px; - right: 2px; - min-width: 18px; - height: 18px; - padding: 0 5px; - border-radius: 9px; - background: var(--rz-coral); - color: #1a0f2e; - font-family: var(--rz-font-mono); - font-size: 11px; - font-weight: 700; - line-height: 18px; - text-align: center; - border: 2px solid var(--rz-purple-deep); - display: none; -} -.rz-root[data-unread="true"] .rz-badge { display: block; } - -/* ---- Panel ---- */ -.rz-panel { - position: absolute; - right: 0; - bottom: 80px; - width: 360px; - max-height: 520px; - height: 70vh; - display: none; - flex-direction: column; - background: var(--rz-glass); - backdrop-filter: blur(16px); - -webkit-backdrop-filter: blur(16px); - border: 1px solid var(--rz-border); - border-radius: 16px; - box-shadow: 0 18px 60px rgba(0, 0, 0, 0.6); - overflow: hidden; - transform-origin: bottom right; -} -.rz-root[data-open="true"] .rz-panel { - display: flex; - animation: rz-panel-in 0.22s ease; -} -@keyframes rz-panel-in { - from { opacity: 0; transform: translateY(10px) scale(0.98); } - to { opacity: 1; transform: translateY(0) scale(1); } -} - -/* ---- Panel header ---- */ -.rz-head { - display: flex; - align-items: center; - gap: 10px; - padding: 14px 14px 12px; - border-bottom: 1px solid var(--rz-border); - background: linear-gradient(180deg, rgba(255, 122, 89, 0.06), transparent); -} -.rz-head-avatar { - width: 34px; - height: 34px; - border-radius: 50%; - object-fit: cover; - object-position: center 28%; - border: 1px solid var(--rz-border); - flex: none; -} -.rz-head-text { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; } -.rz-eyebrow { - font-family: var(--rz-font-mono); - font-size: 10px; - letter-spacing: 0.16em; - text-transform: uppercase; - color: var(--rz-coral); - display: flex; - align-items: center; - gap: 6px; -} -.rz-eyebrow::before { - content: ''; - width: 14px; - height: 1px; - background: var(--rz-coral); - display: inline-block; -} -.rz-head-name { font-size: 15px; font-weight: 600; color: var(--rz-text); } -.rz-status { - margin-left: auto; - display: flex; - align-items: center; - gap: 6px; - font-family: var(--rz-font-mono); - font-size: 10px; - color: var(--rz-text-muted); -} -.rz-status-dot { - width: 7px; height: 7px; border-radius: 50%; - background: var(--rz-text-muted); -} -.rz-status[data-state="ok"] .rz-status-dot { background: var(--rz-ok); } -.rz-status[data-state="down"] .rz-status-dot { background: var(--rz-warn); } -.rz-close { - background: none; border: none; color: var(--rz-text-muted); - font-size: 20px; line-height: 1; cursor: pointer; padding: 4px 6px; - border-radius: 6px; -} -.rz-close:hover { color: var(--rz-text); background: rgba(255,255,255,0.06); } -.rz-close:focus-visible { outline: 2px solid var(--rz-coral); outline-offset: 1px; } - -/* ---- Thread ---- */ -.rz-thread { - flex: 1; - overflow-y: auto; - padding: 14px; - display: flex; - flex-direction: column; - gap: 10px; - scrollbar-width: thin; - scrollbar-color: var(--rz-gold-dim) transparent; -} -.rz-thread::-webkit-scrollbar { width: 6px; } -.rz-thread::-webkit-scrollbar-thumb { background: var(--rz-gold-dim); border-radius: 3px; } - -.rz-empty { - margin: auto 0; - text-align: center; - color: var(--rz-text-muted); - font-size: 13px; - line-height: 1.55; - padding: 0 8px; -} -.rz-empty strong { color: var(--rz-text); font-weight: 600; } - -.rz-msg { - max-width: 86%; - padding: 9px 12px; - border-radius: 12px; - font-size: 13px; - line-height: 1.5; - word-wrap: break-word; - white-space: pre-wrap; -} -.rz-msg-user { - align-self: flex-end; - background: var(--rz-coral-soft); - border: 1px solid rgba(255, 122, 89, 0.35); - color: var(--rz-text); -} -.rz-msg-rosie { - align-self: flex-start; - background: var(--rz-glass-soft); - border: 1px solid var(--rz-border); -} -.rz-msg-meta { - font-family: var(--rz-font-mono); - font-size: 10px; - color: var(--rz-gold-dim); - margin-top: 5px; - word-break: break-all; -} -.rz-msg code, .rz-mono { - font-family: var(--rz-font-mono); - font-size: 11px; - background: rgba(0,0,0,0.25); - padding: 1px 5px; - border-radius: 4px; -} - -.rz-typing { display: flex; gap: 4px; padding: 4px 2px; } -.rz-typing span { - width: 6px; height: 6px; border-radius: 50%; - background: var(--rz-gold-dim); - animation: rz-bounce 1.2s infinite ease-in-out; -} -.rz-typing span:nth-child(2) { animation-delay: 0.15s; } -.rz-typing span:nth-child(3) { animation-delay: 0.3s; } -@keyframes rz-bounce { - 0%, 60%, 100% { transform: translateY(0); opacity: 0.5; } - 30% { transform: translateY(-4px); opacity: 1; } -} - -/* ---- Input ---- */ -.rz-form { - display: flex; - gap: 8px; - padding: 12px; - border-top: 1px solid var(--rz-border); - background: rgba(10, 5, 20, 0.55); -} -.rz-input { - flex: 1; - background: var(--rz-glass-soft); - border: 1px solid var(--rz-border); - border-radius: 10px; - color: var(--rz-text); - font-family: var(--rz-font-body); - font-size: 13px; - padding: 9px 11px; - resize: none; - max-height: 90px; - outline: none; -} -.rz-input::placeholder { color: var(--rz-text-muted); } -.rz-input:focus { border-color: rgba(255, 122, 89, 0.5); } -.rz-send { - flex: none; - width: 38px; - border: none; - border-radius: 10px; - background: var(--rz-coral); - color: #1a0f2e; - font-size: 16px; - cursor: pointer; - display: grid; - place-items: center; - transition: background 0.15s; -} -.rz-send:hover { background: #ff8e72; } -.rz-send:disabled { opacity: 0.5; cursor: not-allowed; } -.rz-send:focus-visible { outline: 2px solid var(--rz-text); outline-offset: 1px; } - -/* ---- Toasts ---- */ -.rz-toasts { - position: absolute; - right: 0; - bottom: 80px; - width: 300px; - display: flex; - flex-direction: column; - gap: 8px; - pointer-events: none; -} -.rz-root[data-open="true"] .rz-toasts { display: none; } -.rz-toast { - pointer-events: auto; - background: var(--rz-glass); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border: 1px solid var(--rz-border); - border-left: 3px solid var(--rz-coral); - border-radius: 12px; - padding: 11px 12px; - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5); - font-size: 12.5px; - line-height: 1.45; - display: flex; - gap: 9px; - align-items: flex-start; - animation: rz-toast-in 0.28s ease; -} -.rz-toast[data-kind="denial"] { border-left-color: var(--rz-warn); } -.rz-toast[data-kind="build-red"] { border-left-color: var(--rz-warn); } -.rz-toast[data-kind="build-green"] { border-left-color: var(--rz-ok); } -.rz-toast-avatar { - width: 26px; height: 26px; border-radius: 50%; - object-fit: cover; object-position: center 28%; flex: none; - border: 1px solid var(--rz-border); -} -.rz-toast-body { flex: 1; min-width: 0; } -.rz-toast-body .rz-toast-meta { - font-family: var(--rz-font-mono); - font-size: 10px; - color: var(--rz-gold-dim); - margin-top: 4px; - word-break: break-all; -} -.rz-toast-x { - background: none; border: none; color: var(--rz-text-muted); - cursor: pointer; font-size: 15px; line-height: 1; padding: 0 2px; flex: none; -} -.rz-toast-x:hover { color: var(--rz-text); } -@keyframes rz-toast-in { - from { opacity: 0; transform: translateY(14px); } - to { opacity: 1; transform: translateY(0); } -} -.rz-toast.rz-toast-out { animation: rz-toast-out 0.2s ease forwards; } -@keyframes rz-toast-out { - to { opacity: 0; transform: translateY(8px); } -} - -/* ---- Mobile ---- */ -@media (max-width: 480px) { - .rz-panel { - width: calc(100vw - 24px); - height: calc(100vh - 110px); - max-height: none; - right: -8px; - } - .rz-toasts { width: calc(100vw - 40px); } - .rz-fab { width: 56px; height: 56px; } -} - -/* ---- Reduced motion ---- */ -@media (prefers-reduced-motion: reduce) { - .rz-fab { animation: none; } - .rz-fab:hover { transform: none; } - .rz-root[data-open="true"] .rz-panel { animation: none; } - .rz-toast { animation: none; } - .rz-toast.rz-toast-out { animation: none; opacity: 0; } - .rz-typing span { animation: none; } -} diff --git a/assets/rosie/rosie-widget.js b/assets/rosie/rosie-widget.js deleted file mode 100644 index c2a23931e5710000a48f93104338998d72d2d1d9..0000000000000000000000000000000000000000 --- a/assets/rosie/rosie-widget.js +++ /dev/null @@ -1,722 +0,0 @@ -/* rosie-widget.js — floating operator widget for SZL Holdings surfaces. - * Version: 2.0.0 — a11oy LLM/reasoning wired in + quick-action buttons. - * - * Rosie is a persistent, character-led interface to the substrate. She is not a - * destination page. She floats bottom-right, opens to a conversation panel, and - * surfaces notifications (receipt minted, gate denied, build status, doctrine - * drift). She ROUTES questions to the substrate backends — she has no model of - * her own — and is honest when a backend is unreachable. - * - * Routing targets (configured via data-* attributes on the script tag): - * data-a11oy-base -> a11oy: /v1/policy/evaluate, /v1/ledger, /v1/verify, /v1/reason - * data-amaru-base -> amaru: /v1/reason - * data-asset-base -> base URL for the rosie portrait PNG - * data-surface -> name of the host surface (for attribution) - * - * Vanilla JS, no dependencies, embeddable anywhere. - * - * Author: Stephen P. Lutar Jr. - * Wire: a11oy LLM/reasoning → rosie cross-Space helper (Wasichaq-III) - */ -(function () { - 'use strict'; - if (window.__rosieWidgetLoaded) return; - window.__rosieWidgetLoaded = true; - - // ---- Resolve configuration from the script tag's data-* attributes ---- - var script = - document.currentScript || - (function () { - var s = document.querySelectorAll('script[src*="rosie-widget"]'); - return s.length ? s[s.length - 1] : null; - })(); - var ds = (script && script.dataset) || {}; - - function trim(u) { return u ? u.replace(/\/+$/, '') : ''; } - - var CFG = { - a11oyBase: trim(ds.a11oyBase || ''), - amaruBase: trim(ds.amaruBase || ''), - surface: ds.surface || (location.hostname || 'surface'), - assetBase: trim(ds.assetBase || 'https://szlholdings-readme.static.hf.space/assets'), - }; - var PORTRAIT = ds.avatar || CFG.assetBase + '/emoji/rosie_emoji.png'; - - var LS_KEY = 'rosie.state.v1'; - var SS_KEY = 'rosie.thread.v1'; - - // ---- Small DOM helpers ---- - function el(tag, attrs, kids) { - var n = document.createElement(tag); - if (attrs) { - for (var k in attrs) { - if (k === 'class') n.className = attrs[k]; - else if (k === 'text') n.textContent = attrs[k]; - else if (k === 'html') n.innerHTML = attrs[k]; - else if (k.slice(0, 2) === 'on' && typeof attrs[k] === 'function') - n.addEventListener(k.slice(2), attrs[k]); - else if (attrs[k] != null) n.setAttribute(k, attrs[k]); - } - } - (kids || []).forEach(function (c) { - if (c == null) return; - n.appendChild(typeof c === 'string' ? document.createTextNode(c) : c); - }); - return n; - } - function esc(s) { - return String(s).replace(/[&<>"']/g, function (c) { - return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; - }); - } - - // ---- Persistent state ---- - var state = { unread: 0, status: 'unknown' }; - try { - var saved = JSON.parse(localStorage.getItem(LS_KEY) || '{}'); - if (saved && typeof saved === 'object') { - if (typeof saved.unread === 'number') state.unread = saved.unread; - } - } catch (e) {} - function persist() { - try { localStorage.setItem(LS_KEY, JSON.stringify({ unread: state.unread })); } catch (e) {} - } - - var thread = []; - try { - var t = JSON.parse(sessionStorage.getItem(SS_KEY) || '[]'); - if (Array.isArray(t)) thread = t; - } catch (e) {} - function persistThread() { - try { sessionStorage.setItem(SS_KEY, JSON.stringify(thread.slice(-50))); } catch (e) {} - } - - // ---- CSS ---- - var css = [ - '.rz-root{position:fixed;bottom:24px;right:24px;z-index:2147483647;font-family:"Inter",system-ui,sans-serif;font-size:14px;line-height:1.5;}', - '.rz-fab{width:56px;height:56px;border-radius:50%;border:none;cursor:pointer;', - 'background:linear-gradient(135deg,#ff7a59 0%,#c8415d 100%);', - 'box-shadow:0 4px 20px rgba(255,122,89,0.45);display:flex;align-items:center;justify-content:center;', - 'position:relative;transition:transform .18s,box-shadow .18s;outline:none;}', - '.rz-fab:hover{transform:scale(1.08);box-shadow:0 6px 28px rgba(255,122,89,0.6);}', - '.rz-fab:focus-visible{outline:3px solid #ff7a59;outline-offset:3px;}', - '.rz-fab img{width:38px;height:38px;border-radius:50%;object-fit:cover;}', - '.rz-fab-fallback{color:#fff;font-weight:700;font-size:22px;}', - '.rz-badge{position:absolute;top:-4px;right:-4px;min-width:18px;height:18px;', - 'border-radius:9px;background:#c8415d;color:#fff;font-size:11px;font-weight:700;', - 'display:none;align-items:center;justify-content:center;padding:0 4px;border:2px solid #1a0d2e;}', - '[data-unread="true"] .rz-badge{display:flex;}', - '.rz-panel{position:fixed;bottom:92px;right:24px;width:360px;max-width:calc(100vw - 48px);', - 'height:520px;max-height:calc(100vh - 120px);background:#1a0d2e;', - 'border:1px solid rgba(255,122,89,0.25);border-radius:16px;display:none;flex-direction:column;', - 'box-shadow:0 8px 40px rgba(0,0,0,0.6);overflow:hidden;}', - '[data-open="true"] .rz-panel{display:flex;}', - '.rz-head{display:flex;align-items:center;gap:10px;padding:12px 14px;', - 'border-bottom:1px solid rgba(255,122,89,0.18);background:rgba(45,27,94,0.6);}', - '.rz-head-avatar{width:34px;height:34px;border-radius:50%;object-fit:cover;flex-shrink:0;}', - '.rz-head-text{display:flex;flex-direction:column;flex:1;min-width:0;}', - '.rz-eyebrow{font-size:9px;letter-spacing:.12em;color:#ff7a59;font-weight:700;text-transform:uppercase;}', - '.rz-head-name{font-size:13px;font-weight:600;color:#e8e0f0;}', - '.rz-status{display:flex;align-items:center;gap:5px;margin-left:auto;flex-shrink:0;}', - '.rz-status-dot{width:8px;height:8px;border-radius:50%;background:#a090c0;transition:background .3s;}', - '[data-state="ok"] .rz-status-dot{background:#4ade80;}', - '[data-state="down"] .rz-status-dot{background:#f87171;}', - '[data-state="unknown"] .rz-status-dot{background:#a090c0;}', - '.rz-status-label{font-size:11px;color:#a090c0;}', - '.rz-close{background:none;border:none;color:#a090c0;font-size:20px;cursor:pointer;', - 'padding:0 4px;line-height:1;margin-left:6px;border-radius:4px;transition:color .15s;}', - '.rz-close:hover{color:#e8e0f0;}', - - /* Quick action buttons */ - '.rz-quick-actions{display:flex;gap:6px;padding:8px 10px;border-bottom:1px solid rgba(255,122,89,0.12);', - 'background:rgba(26,13,46,0.8);flex-wrap:wrap;}', - '.rz-qa-btn{flex:1;min-width:80px;background:rgba(255,122,89,0.10);border:1px solid rgba(255,122,89,0.25);', - 'color:#ff9c81;font-size:11px;font-family:inherit;border-radius:6px;padding:5px 8px;', - 'cursor:pointer;transition:background .15s,border-color .15s;text-align:center;font-weight:500;', - 'white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}', - '.rz-qa-btn:hover{background:rgba(255,122,89,0.20);border-color:rgba(255,122,89,0.5);color:#fff;}', - '.rz-qa-btn:active{background:rgba(255,122,89,0.30);}', - '.rz-qa-btn:disabled{opacity:0.4;cursor:not-allowed;}', - - '.rz-thread{flex:1;overflow-y:auto;padding:12px 10px;display:flex;flex-direction:column;gap:8px;}', - '.rz-empty{color:#a090c0;font-size:13px;text-align:center;padding:24px 0;}', - '.rz-msg{max-width:88%;padding:8px 12px;border-radius:10px;font-size:13px;word-break:break-word;', - 'white-space:pre-wrap;}', - '.rz-msg-user{align-self:flex-end;background:rgba(255,122,89,0.18);color:#e8e0f0;', - 'border-bottom-right-radius:3px;}', - '.rz-msg-rosie{align-self:flex-start;background:rgba(45,27,94,0.8);color:#e8e0f0;', - 'border-bottom-left-radius:3px;border:1px solid rgba(255,122,89,0.15);}', - '.rz-msg-meta{font-size:10px;color:#a090c0;margin-top:4px;font-family:"JetBrains Mono",monospace;}', - '.rz-typing-wrap{align-self:flex-start;}', - '.rz-typing{display:flex;gap:4px;padding:10px 14px;background:rgba(45,27,94,0.8);', - 'border-radius:10px;border:1px solid rgba(255,122,89,0.15);}', - '.rz-typing span{width:6px;height:6px;border-radius:50%;background:#ff7a59;', - 'animation:rz-bounce 1.2s infinite ease-in-out;}', - '.rz-typing span:nth-child(2){animation-delay:.2s;}', - '.rz-typing span:nth-child(3){animation-delay:.4s;}', - '@keyframes rz-bounce{0%,80%,100%{transform:translateY(0);}40%{transform:translateY(-6px);}}', - '.rz-form{display:flex;align-items:flex-end;gap:6px;padding:10px;border-top:1px solid rgba(255,122,89,0.15);}', - '.rz-input{flex:1;background:rgba(45,27,94,0.5);border:1px solid rgba(255,122,89,0.25);', - 'border-radius:8px;color:#e8e0f0;font-family:inherit;font-size:13px;padding:7px 10px;', - 'resize:none;max-height:90px;outline:none;transition:border-color .15s;}', - '.rz-input:focus{border-color:rgba(255,122,89,0.55);}', - '.rz-input::placeholder{color:#a090c0;}', - '.rz-send{background:#ff7a59;border:none;border-radius:8px;color:#1a0d2e;', - 'font-weight:700;font-size:16px;width:36px;height:36px;cursor:pointer;flex-shrink:0;', - 'display:flex;align-items:center;justify-content:center;transition:background .15s;}', - '.rz-send:hover{background:#ff9c81;}', - '.rz-toasts{position:fixed;bottom:92px;right:24px;display:flex;flex-direction:column;gap:8px;', - 'z-index:2147483646;pointer-events:none;width:320px;max-width:calc(100vw - 48px);}', - '[data-open="true"] ~ .rz-toasts,.rz-root[data-open="true"] .rz-toasts{bottom:calc(520px + 100px);}', - '.rz-toast{display:flex;align-items:flex-start;gap:10px;background:#1a0d2e;', - 'border:1px solid rgba(255,122,89,0.25);border-radius:12px;padding:10px 12px;', - 'box-shadow:0 4px 16px rgba(0,0,0,0.5);pointer-events:all;animation:rz-toast-in .2s ease-out;}', - '@keyframes rz-toast-in{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:none;}}', - '.rz-toast-out{animation:rz-toast-out .2s ease-in forwards;}', - '@keyframes rz-toast-out{to{opacity:0;transform:translateY(10px);}}', - '.rz-toast-avatar{width:28px;height:28px;border-radius:50%;object-fit:cover;flex-shrink:0;}', - '.rz-toast-body{flex:1;min-width:0;}', - '.rz-toast-title{font-size:13px;font-weight:600;color:#e8e0f0;}', - '.rz-toast-text{font-size:12px;color:#a090c0;margin-top:2px;}', - '.rz-toast-meta{font-size:10px;color:#ff9c81;font-family:"JetBrains Mono",monospace;margin-top:2px;}', - '.rz-toast-x{background:none;border:none;color:#a090c0;cursor:pointer;font-size:16px;', - 'padding:0 2px;line-height:1;flex-shrink:0;}', - '[data-kind="receipt"] .rz-toast-title::before{content:"📜 ";}', - '[data-kind="denial"] .rz-toast-title::before{content:"🚫 ";}', - '[data-kind="build-green"] .rz-toast-title::before{content:"✅ ";}', - '[data-kind="build-red"] .rz-toast-title::before{content:"❌ ";}', - '[data-kind="doctrine"] .rz-toast-title::before{content:"⚠️ ";}', - ].join(''); - - var style = document.createElement('style'); - style.textContent = css; - (document.head || document.documentElement).appendChild(style); - - // ---- Build the DOM ---- - var root = el('div', { class: 'rz-root', 'data-open': 'false', 'data-unread': 'false' }); - root.setAttribute('data-rosie', 'widget'); - - // FAB - var fabImg = el('img', { src: PORTRAIT, alt: '', 'aria-hidden': 'true' }); - fabImg.addEventListener('error', function () { - fabImg.style.display = 'none'; - fab.appendChild(el('span', { class: 'rz-fab-fallback', text: 'R' })); - }); - var badge = el('span', { class: 'rz-badge', 'aria-hidden': 'true' }); - var fab = el( - 'button', - { - class: 'rz-fab', - type: 'button', - 'aria-label': 'Open Rosie, the operator assistant', - 'aria-haspopup': 'dialog', - 'aria-expanded': 'false', - }, - [fabImg, badge] - ); - - // Panel header - var headAvatar = el('img', { class: 'rz-head-avatar', src: PORTRAIT, alt: '' }); - var statusDot = el('span', { class: 'rz-status-dot' }); - var statusLabel = el('span', { class: 'rz-status-label', text: 'checking' }); - var statusEl = el('span', { class: 'rz-status', 'data-state': 'unknown' }, [statusDot, statusLabel]); - var closeBtn = el('button', { - class: 'rz-close', type: 'button', 'aria-label': 'Close Rosie', text: '\u00d7', - }); - var head = el('div', { class: 'rz-head' }, [ - headAvatar, - el('div', { class: 'rz-head-text' }, [ - el('span', { class: 'rz-eyebrow', text: 'ROSIE' }), - el('span', { class: 'rz-head-name', text: 'Cross-Space Operator' }), - ]), - statusEl, - closeBtn, - ]); - - // Quick action buttons - var qaReceipt = el('button', { - class: 'rz-qa-btn', type: 'button', title: 'Show last 10 receipts from a11oy ledger', - text: '📜 Last receipt', - onclick: function() { open(); quickAction('receipt'); } - }); - var qaVerify = el('button', { - class: 'rz-qa-btn', type: 'button', title: "Verify this page's receipt chain integrity", - text: '🔐 Verify chain', - onclick: function() { open(); quickAction('verify'); } - }); - var qaPolicy = el('button', { - class: 'rz-qa-btn', type: 'button', title: 'Evaluate a sample policy action', - text: '⚖️ Evaluate policy', - onclick: function() { open(); quickAction('policy'); } - }); - var qaReason = el('button', { - class: 'rz-qa-btn', type: 'button', title: 'Ask a11oy to explain this Space', - text: '🧠 Ask a11oy', - onclick: function() { open(); quickAction('reason'); } - }); - var quickActions = el('div', { class: 'rz-quick-actions' }, [qaReceipt, qaVerify, qaPolicy, qaReason]); - - var threadEl = el('div', { class: 'rz-thread', role: 'log', 'aria-live': 'polite', 'aria-label': 'Conversation with Rosie' }); - - var input = el('textarea', { - class: 'rz-input', rows: '1', placeholder: 'Ask Rosie about the substrate\u2026', - 'aria-label': 'Message to Rosie', - }); - var sendBtn = el('button', { class: 'rz-send', type: 'submit', 'aria-label': 'Send', html: '➤' }); - var form = el('form', { class: 'rz-form' }, [input, sendBtn]); - - var panel = el('div', { - class: 'rz-panel', role: 'dialog', 'aria-label': 'Rosie operator assistant', 'aria-modal': 'false', - }, [head, quickActions, threadEl, form]); - - var toasts = el('div', { class: 'rz-toasts', 'aria-live': 'polite', 'aria-label': 'Rosie notifications' }); - - root.appendChild(toasts); - root.appendChild(panel); - root.appendChild(fab); - - function mount() { - if (!document.body) { document.addEventListener('DOMContentLoaded', mount); return; } - document.body.appendChild(root); - renderThread(); - refreshBadge(); - checkStatus(); - } - mount(); - - // ---- Open / close ---- - var isOpen = false; - function open() { - isOpen = true; - root.setAttribute('data-open', 'true'); - fab.setAttribute('aria-expanded', 'true'); - state.unread = 0; persist(); refreshBadge(); - if (!thread.length) renderThread(); - setTimeout(function () { input.focus(); }, 60); - scrollThread(); - } - function close() { - isOpen = false; - root.setAttribute('data-open', 'false'); - fab.setAttribute('aria-expanded', 'false'); - fab.focus(); - } - function toggle() { isOpen ? close() : open(); } - - fab.addEventListener('click', toggle); - closeBtn.addEventListener('click', close); - document.addEventListener('keydown', function (e) { - if (e.key === 'Escape' && isOpen) { close(); } - }); - - // ---- Thread rendering ---- - function refreshBadge() { - root.setAttribute('data-unread', state.unread > 0 ? 'true' : 'false'); - badge.textContent = state.unread > 9 ? '9+' : String(state.unread || ''); - } - function scrollThread() { - requestAnimationFrame(function () { threadEl.scrollTop = threadEl.scrollHeight; }); - } - function renderThread() { - threadEl.innerHTML = ''; - if (!thread.length) { - var em = el('div', { class: 'rz-empty' }); - em.innerHTML = - 'Hi, I\u2019m Rosie.
' + - 'Ask me anything about the substrate, or use the quick buttons above.' + - '

Surface: ' + esc(CFG.surface) + '' + - (CFG.a11oyBase ? ' \u2022 a11oy wired' : ' \u2022 a11oy not configured') + ''; - threadEl.appendChild(em); - return; - } - thread.forEach(function (m) { threadEl.appendChild(renderMsg(m)); }); - scrollThread(); - } - function renderMsg(m) { - var cls = m.role === 'user' ? 'rz-msg rz-msg-user' : 'rz-msg rz-msg-rosie'; - var node = el('div', { class: cls }); - node.innerHTML = esc(m.text).replace(/\n/g, '
'); - if (m.meta) node.appendChild(el('div', { class: 'rz-msg-meta', text: m.meta })); - if (m.dsse) { - var dsseNode = el('div', { class: 'rz-msg-meta' }); - dsseNode.innerHTML = 'DSSE envelope: ' + esc(m.dsse); - node.appendChild(dsseNode); - } - return node; - } - function pushMsg(role, text, meta, dsse) { - var m = { role: role, text: text, meta: meta || null, ts: Date.now(), dsse: dsse || null }; - thread.push(m); persistThread(); - if (!thread.length) return; - if (threadEl.querySelector('.rz-empty')) threadEl.innerHTML = ''; - threadEl.appendChild(renderMsg(m)); - scrollThread(); - return m; - } - function showTyping() { - var t = el('div', { class: 'rz-msg rz-msg-rosie rz-typing-wrap' }, [ - el('div', { class: 'rz-typing' }, [el('span'), el('span'), el('span')]), - ]); - threadEl.appendChild(t); scrollThread(); - return t; - } - - // ---- Backend status (honest) ---- - function checkStatus() { - if (!CFG.a11oyBase) { setStatus('unknown', 'not configured'); return; } - fetchJson(CFG.a11oyBase + '/v1/health', { method: 'GET' }, 4000) - .then(function () { setStatus('ok', 'substrate online'); }) - .catch(function () { setStatus('down', 'substrate unreachable'); }); - } - function setStatus(s, label) { - state.status = s; - statusEl.setAttribute('data-state', s); - statusLabel.textContent = label; - } - - // ---- Networking ---- - function fetchJson(url, opts, timeoutMs) { - opts = opts || {}; - var ctrl = typeof AbortController !== 'undefined' ? new AbortController() : null; - if (ctrl) opts.signal = ctrl.signal; - opts.headers = Object.assign({ 'Content-Type': 'application/json' }, opts.headers || {}); - opts.credentials = 'include'; - var timer = ctrl ? setTimeout(function () { ctrl.abort(); }, timeoutMs || 12000) : null; - return fetch(url, opts).then(function (r) { - if (timer) clearTimeout(timer); - if (!r.ok) { var e = new Error('HTTP ' + r.status); e.status = r.status; throw e; } - var ct = r.headers.get('content-type') || ''; - return ct.indexOf('application/json') >= 0 ? r.json() : r.text(); - }).catch(function (e) { if (timer) clearTimeout(timer); throw e; }); - } - - // ---- Quick Actions ---- - function disableQA(disabled) { - [qaReceipt, qaVerify, qaPolicy, qaReason].forEach(function(b) { b.disabled = disabled; }); - } - - function quickAction(kind) { - disableQA(true); - var typing = showTyping(); - var done = function() { typing.remove(); disableQA(false); }; - - if (kind === 'receipt') { - pushMsg('user', '\uD83D\uDCDC Show last receipts'); - if (!CFG.a11oyBase) { - done(); - pushMsg('rosie', "a11oy is not configured on this surface. I can't fetch the ledger without it."); - return; - } - fetchJson(CFG.a11oyBase + '/v1/ledger?limit=10', { method: 'GET' }, 14000) - .then(function(data) { - done(); - var items = data.receipts || data.items || data.results || (Array.isArray(data) ? data : null); - if (!items || !items.length) { - pushMsg('rosie', 'No receipts in the ledger yet. The chain is empty.'); return; - } - var top = items[0]; - var hash = top.hash || top.receipt_id || top.id || top.digest; - var root_hash = data.root_hash || data.dag_root || null; - var head_seq = data.head_seq || data.total || null; - var msg = 'Khipu Merkle DAG: ' + items.length + ' receipt(s) returned.'; - if (head_seq != null) msg += '\nHead seq: ' + head_seq; - if (root_hash) msg += '\nRoot hash: ' + root_hash; - msg += '\n\nMost recent receipt:'; - if (top.action) msg += '\n action: ' + top.action; - if (top.timestamp_utc || top.ts || top.timestamp) msg += '\n time: ' + (top.timestamp_utc || top.ts || top.timestamp); - pushMsg('rosie', msg, hash ? 'receipt ' + hash : null); - setStatus('ok', 'ledger \u2713'); - }) - .catch(function(err) { done(); handleNetErr(err); }); - - } else if (kind === 'verify') { - pushMsg('user', '\uD83D\uDD10 Verify this page\u2019s claims'); - if (!CFG.a11oyBase) { - done(); - pushMsg('rosie', "a11oy is not configured on this surface. I can't verify without it."); - return; - } - fetchJson(CFG.a11oyBase + '/v1/verify', { - method: 'POST', - body: JSON.stringify({ surface: CFG.surface, ledger: [] }) - }, 14000) - .then(function(data) { - done(); - var ok = data.verified === true || data.valid === true || data.ok === true; - var dsseSnippet = null; - if (data.envelope || data.dsse) { - var env = data.envelope || data.dsse; - dsseSnippet = 'DSSE payload: ' + (env.payload || '').slice(0, 32) + '...' + - ' | keyid: ' + ((env.signatures || [{}])[0].keyid || '?') + - ' | NOTE: PLACEHOLDER \u2014 signing not yet wired into CI'; - } - pushMsg('rosie', - ok ? 'Chain verified \u2014 the receipts I checked are intact.' - : "Verification did not pass. I'm flagging this so it can be looked at.", - data.hash || data.head ? 'head ' + (data.hash || data.head) : null, - dsseSnippet); - setStatus(ok ? 'ok' : 'down', ok ? 'chain valid' : 'chain invalid'); - }) - .catch(function(err) { done(); handleNetErr(err); }); - - } else if (kind === 'policy') { - var sampleAction = 'deploy-to-production on surface:' + CFG.surface; - pushMsg('user', '\u2696\uFE0F Evaluate policy: ' + sampleAction); - if (!CFG.a11oyBase) { - done(); - pushMsg('rosie', "a11oy is not configured on this surface. I can't evaluate policy without it."); - return; - } - fetchJson(CFG.a11oyBase + '/v1/policy/evaluate', { - method: 'POST', - body: JSON.stringify({ - actionId: 'landing-demo', - action: sampleAction, - surface: CFG.surface, - severity: 'medium', - confidence: 0.9, - witnesses: ['agent-a', 'agent-b'] - }) - }, 14000) - .then(function(data) { - done(); - var decision = (data.decision || data.verdict || (data.allowed === true ? 'allow' : data.allowed === false ? 'deny' : '')).toString().toLowerCase(); - var gate = data.gate || data.gate_id || data.rule || null; - if (decision.indexOf('deny') >= 0) { - pushMsg('rosie', - "Policy would deny that action" + (data.reason ? ': ' + data.reason : '.'), - gate ? 'gate ' + gate : null); - } else if (decision.indexOf('allow') >= 0) { - pushMsg('rosie', - 'Policy would allow that. Operator confirmation still required before anything is signed.', - gate ? 'gate ' + gate : null); - } else { - pushMsg('rosie', 'Policy engine returned:\n' + safeJson(data)); - } - setStatus('ok', 'policy \u2713'); - }) - .catch(function(err) { done(); handleNetErr(err); }); - - } else if (kind === 'reason') { - var q = 'How does this Space (' + CFG.surface + ') work? What are its key capabilities?'; - pushMsg('user', '\uD83E\uDDE0 ' + q); - // Route to a11oy /v1/reason first, fall back to /v1/policy/evaluate as general Q&A - var reasonBase = CFG.amaruBase || CFG.a11oyBase; - var reasonPath = CFG.amaruBase ? '/v1/reason' : '/v1/reason'; - if (!reasonBase) { - done(); - pushMsg('rosie', - "Neither a11oy nor amaru are configured on this surface yet. " + - "Once wired, I'll route your question to the substrate's reasoning engine.\n\n" + - "This surface (" + CFG.surface + ") is part of the SZL Holdings UDS mesh. " + - "Ask me again once the endpoints are live."); - return; - } - fetchJson(reasonBase + reasonPath, { - method: 'POST', - body: JSON.stringify({ prompt: q, surface: CFG.surface, question: q }) - }, 20000) - .then(function(data) { - done(); - var ans = data.answer || data.reasoning || data.text || data.output || data.result || data.response; - pushMsg('rosie', - ans ? String(ans) : 'The reasoning engine responded:\n' + safeJson(data), - data.confidence != null ? 'confidence ' + data.confidence : null); - setStatus('ok', 'reasoning \u2713'); - }) - .catch(function(err) { done(); handleNetErr(err); }); - } - } - - // ---- Routing: decide which substrate endpoint a question goes to ---- - function route(q) { - var s = q.toLowerCase(); - if (/\b(verify|chain|integrity|tamper)\b/.test(s) && CFG.a11oyBase) - return { svc: 'a11oy', path: '/v1/verify', method: 'POST', body: { query: q, surface: CFG.surface } }; - if (/\b(receipt|ledger|minted|hash|history|log|khipu|dag)\b/.test(s) && CFG.a11oyBase) - return { svc: 'a11oy', path: '/v1/ledger', method: 'GET', query: { q: q, limit: 5 } }; - if (/\b(can i|should i|allowed|policy|permit|deny|gate|propose|execute)\b/.test(s) && CFG.a11oyBase) - return { svc: 'a11oy', path: '/v1/policy/evaluate', method: 'POST', body: { action: q, surface: CFG.surface } }; - if (/\b(how|what|explain|describe|reason|why|tell me)\b/.test(s)) { - if (CFG.amaruBase) return { svc: 'amaru', path: '/v1/reason', method: 'POST', body: { prompt: q, surface: CFG.surface } }; - if (CFG.a11oyBase) return { svc: 'a11oy', path: '/v1/reason', method: 'POST', body: { prompt: q, surface: CFG.surface } }; - } - if (CFG.amaruBase) - return { svc: 'amaru', path: '/v1/reason', method: 'POST', body: { prompt: q, surface: CFG.surface } }; - if (CFG.a11oyBase) - return { svc: 'a11oy', path: '/v1/policy/evaluate', method: 'POST', body: { action: q, surface: CFG.surface } }; - return null; - } - - function baseFor(svc) { return svc === 'amaru' ? CFG.amaruBase : CFG.a11oyBase; } - - function handleNetErr(err) { - if (err && err.status) { - pushMsg('rosie', "The substrate answered with an error (" + err.status + "). I won't guess what it meant \u2014 try rephrasing, or check the service."); - } else { - pushMsg('rosie', "I can't reach the substrate right now, so I won't make up an answer. I'll keep trying \u2014 ask me again in a moment."); - setStatus('down', 'substrate unreachable'); - } - } - - function ask(q) { - pushMsg('user', q); - var r = route(q); - if (!r) { - pushMsg('rosie', "I'm not wired to a backend on this surface yet, so I can't answer that honestly. Once a11oy or amaru is configured here, I'll route your question to the substrate."); - return; - } - var typing = showTyping(); - var url = baseFor(r.svc) + r.path; - if (r.query) { - var qs = Object.keys(r.query).map(function (k) { return encodeURIComponent(k) + '=' + encodeURIComponent(r.query[k]); }).join('&'); - url += (url.indexOf('?') >= 0 ? '&' : '?') + qs; - } - var opts = { method: r.method }; - if (r.body && r.method !== 'GET') opts.body = JSON.stringify(r.body); - - fetchJson(url, opts, 14000) - .then(function (data) { - typing.remove(); - renderAnswer(r, data); - setStatus('ok', 'substrate online'); - }) - .catch(function (err) { - typing.remove(); - handleNetErr(err); - }); - } - - // ---- Turn a substrate response into Rosie's voice (no fabrication) ---- - function renderAnswer(r, data) { - if (data == null || (typeof data === 'object' && Object.keys(data).length === 0)) { - pushMsg('rosie', "The substrate responded, but there was nothing to show \u2014 no matching records. That's an honest empty result, not an error."); - return; - } - if (typeof data === 'string') { pushMsg('rosie', data); return; } - - if (r.path === '/v1/ledger') { - var items = data.receipts || data.items || data.results || (Array.isArray(data) ? data : null); - if (!items || !items.length) { - pushMsg('rosie', "No matching receipts in the ledger. Nothing's been minted for that query."); - return; - } - var top = items[0]; - var hash = top.hash || top.receipt_id || top.id || top.digest; - var root_hash = data.root_hash || data.dag_root || null; - var msg = 'Found ' + items.length + ' receipt' + (items.length === 1 ? '' : 's') + '.'; - if (root_hash) msg += '\nKhipu DAG root: ' + root_hash; - if (top.action) msg += '\nMost recent: ' + top.action; - pushMsg('rosie', msg, hash ? 'receipt ' + hash : null); - return; - } - if (r.path === '/v1/verify') { - var ok = data.verified === true || data.valid === true || data.ok === true; - var dsseSnippet = null; - if (data.envelope || data.dsse) { - var env = data.envelope || data.dsse; - dsseSnippet = 'DSSE | keyid: ' + ((env.signatures || [{}])[0].keyid || '?') + - ' | PLACEHOLDER \u2014 signing not yet wired into CI'; - } - pushMsg('rosie', - ok ? 'Chain verified \u2014 the receipts I checked are intact.' - : "Verification did not pass. I'm flagging this so it can be looked at, not hiding it.", - data.hash || data.head ? 'head ' + (data.hash || data.head) : null, - dsseSnippet); - return; - } - if (r.path === '/v1/policy/evaluate') { - var decision = (data.decision || data.verdict || (data.allowed === true ? 'allow' : data.allowed === false ? 'deny' : '') || '').toString().toLowerCase(); - var gate = data.gate || data.gate_id || data.rule || null; - if (decision.indexOf('deny') >= 0 || data.allowed === false) { - pushMsg('rosie', - "That action would be denied by policy" + (data.reason ? ': ' + data.reason : '.') + ' I won\u2019t propose anything the gates reject.', - gate ? 'gate ' + gate : null); - } else if (decision.indexOf('allow') >= 0 || data.allowed === true) { - pushMsg('rosie', - 'Policy would allow that. It still needs an operator to confirm before anything is signed.', - gate ? 'gate ' + gate : null); - } else { - pushMsg('rosie', 'The policy engine returned a decision I should show you directly:\n' + safeJson(data)); - } - return; - } - if (r.svc === 'amaru' || r.path === '/v1/reason') { - var ans = data.answer || data.reasoning || data.text || data.output || data.result || data.response; - pushMsg('rosie', ans ? String(ans) : 'The reasoning engine responded:\n' + safeJson(data), - data.confidence != null ? 'confidence ' + data.confidence : null); - return; - } - pushMsg('rosie', safeJson(data)); - } - function safeJson(o) { - try { var s = JSON.stringify(o, null, 2); return s.length > 800 ? s.slice(0, 800) + '\u2026' : s; } - catch (e) { return String(o); } - } - - // ---- Input handling ---- - form.addEventListener('submit', function (e) { - e.preventDefault(); - var q = input.value.trim(); - if (!q) return; - input.value = ''; - input.style.height = 'auto'; - ask(q); - }); - input.addEventListener('input', function () { - input.style.height = 'auto'; - input.style.height = Math.min(input.scrollHeight, 90) + 'px'; - }); - input.addEventListener('keydown', function (e) { - if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); form.requestSubmit ? form.requestSubmit() : form.dispatchEvent(new Event('submit', { cancelable: true })); } - }); - - // ---- Notifications API ---- - function notify(opts) { - opts = opts || {}; - var kind = opts.kind || 'info'; - var avatar = el('img', { class: 'rz-toast-avatar', src: PORTRAIT, alt: '' }); - var body = el('div', { class: 'rz-toast-body' }); - body.appendChild(el('div', { class: 'rz-toast-title', html: '' + esc(opts.title || 'Rosie') + '' })); - if (opts.body) body.appendChild(el('div', { class: 'rz-toast-text', text: opts.body })); - if (opts.meta) body.appendChild(el('div', { class: 'rz-toast-meta', text: opts.meta })); - - var toast; - function dismiss() { - if (!toast) return; - toast.classList.add('rz-toast-out'); - setTimeout(function () { if (toast && toast.parentNode) toast.parentNode.removeChild(toast); }, 220); - } - var x = el('button', { class: 'rz-toast-x', type: 'button', 'aria-label': 'Dismiss', text: '\u00d7', onclick: dismiss }); - toast = el('div', { class: 'rz-toast', 'data-kind': kind, role: 'status' }, [avatar, body, x]); - toasts.appendChild(toast); - - pushMsg('rosie', (opts.title ? opts.title + (opts.body ? ' \u2014 ' + opts.body : '') : opts.body || ''), opts.meta); - - if (!isOpen) { state.unread = (state.unread || 0) + 1; persist(); refreshBadge(); } - if (!opts.sticky) setTimeout(dismiss, opts.duration || 8000); - return { dismiss: dismiss }; - } - - // ---- Public API ---- - window.Rosie = { - open: open, - close: close, - toggle: toggle, - ask: function (q) { open(); ask(q); }, - notify: notify, - config: CFG, - receiptMinted: function (hash, what) { - return notify({ kind: 'receipt', title: 'New receipt minted', body: what || 'A signed receipt was added to the ledger.', meta: hash ? 'receipt ' + hash : null }); - }, - gateDenied: function (gate, what) { - return notify({ kind: 'denial', title: 'Policy denied an action', body: what || 'A proposed action was rejected by the gates.', meta: gate ? 'gate ' + gate : null }); - }, - build: function (green, detail) { - return notify({ kind: green ? 'build-green' : 'build-red', title: green ? 'Build is green' : 'Build is red', body: detail || '' }); - }, - doctrineDrift: function (detail) { - return notify({ kind: 'doctrine', title: 'Doctrine drift detected', body: detail || 'Something diverged from doctrine. Worth a look.' }); - }, - }; -})(); diff --git a/assets/rosie_avatar.png b/assets/rosie_avatar.png deleted file mode 100644 index a89dd4a35be9cba45fd61721cb3ae36027c1e399..0000000000000000000000000000000000000000 --- a/assets/rosie_avatar.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:82d523fd22bff3144bf647a5f9450180ab9cffcb213173272cf7a946d50a2786 -size 1267913 diff --git a/assets/sentra_avatar.png b/assets/sentra_avatar.png deleted file mode 100644 index 8ec6121f309e2607755c736148c67fbe92506ce0..0000000000000000000000000000000000000000 --- a/assets/sentra_avatar.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a01b83b85d445240848540005b426b7f5bf28c9573fb06df42fe41054299e7f9 -size 1226996 diff --git a/assets/szl_banner.png b/assets/szl_banner.png deleted file mode 100644 index 049bca552b601e1a850961a6f23572b60604a575..0000000000000000000000000000000000000000 --- a/assets/szl_banner.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:99cdc8e3ce6a23d8a148dc1e33f48dd2f50a3836ec4c4bbf29fcb931ec91da99 -size 1200672 diff --git a/assets/vessels_avatar.png b/assets/vessels_avatar.png deleted file mode 100644 index 18b09cfd85dcafe6496eb5732d8aab84214dcd9f..0000000000000000000000000000000000000000 --- a/assets/vessels_avatar.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b83a90b17bd56b7f7b8e172dee54f69d0cd605f938f46236a0089656f2416d62 -size 1323845 diff --git a/css/style.css b/css/style.css deleted file mode 100644 index 693f5dea4cc244f240b17fcdc4e53f5b0383b106..0000000000000000000000000000000000000000 --- a/css/style.css +++ /dev/null @@ -1,89 +0,0 @@ -/* style.css — minimal, mostly defaults. SZL palette: deep purple + gold. */ -:root{ - --purple-deep:#12091f; --purple-mid:#2d1b4e; --gold:#d4af37; --gold-light:#e8cc6a; - --text-main:#e8e0f0; --text-muted:#a090c0; --text-dim:#7060a0; - --font-head:'Cinzel',Georgia,serif; --font-mono:'JetBrains Mono','Fira Code',monospace; -} -*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;} -html,body{height:100%;} -body{ - background:var(--purple-deep);color:var(--text-main); - font-family:'Inter',system-ui,-apple-system,sans-serif;line-height:1.6; - -webkit-font-smoothing:antialiased;overflow-x:hidden; - background-image:radial-gradient(circle at 50% -10%,rgba(61,40,120,0.5),transparent 55%), - radial-gradient(circle at 90% 10%,rgba(212,175,55,0.07),transparent 45%); -} -.skip{position:absolute;left:-9999px;top:0.5rem;z-index:99;padding:.5rem 1rem;background:var(--gold);color:#150b22;font-weight:700;border-radius:4px;} -.skip:focus{left:1rem;} - -/* Header / footer banding */ -.roster-header,.roster-footer{text-align:center;font-family:var(--font-mono);letter-spacing:.18em; - text-transform:uppercase;color:var(--gold-light);padding:1.1rem 1rem .6rem;font-size:clamp(.62rem,1.6vw,.86rem);} -.roster-footer{color:var(--text-muted);padding:.7rem 1rem 1.4rem;font-size:clamp(.56rem,1.4vw,.74rem);} -.roster-footer b{color:var(--gold);} -.tagline{text-align:center;font-family:var(--font-head);color:var(--gold); - font-size:clamp(1.1rem,3vw,1.8rem);padding:.4rem 1rem 0;} -.tagline small{display:block;font-family:var(--font-mono);text-transform:none;letter-spacing:.04em; - font-size:.62rem;color:var(--text-dim);margin-top:.4rem;} - -/* The 3D stage */ -#stage{position:relative;width:100%;height:min(70vh,640px);min-height:420px;} -#roster{display:block;width:100%;height:100%;} -#roster[hidden]{display:none;} -/* When the static grid is the visible child (no JS / no WebGL / org card), - let the stage size to content instead of the fixed canvas height. */ -#stage:has(#fallback:not([hidden])){height:auto;min-height:0;} -#loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center; - font-family:var(--font-mono);color:var(--text-dim);font-size:.8rem;letter-spacing:.1em;} - -/* Holographic hover panel */ -.hover-panel{position:absolute;transform:translate(-50%,-100%);min-width:240px;max-width:300px; - padding:.8rem .9rem;pointer-events:none;opacity:0;transition:opacity .18s ease-out;z-index:40; - background:linear-gradient(180deg,rgba(18,9,31,.92),rgba(18,9,31,.78)); - border:1px solid var(--hc,#d4af37);border-radius:10px; - box-shadow:0 0 24px -4px var(--hc,#d4af37),inset 0 0 18px -8px var(--hc,#d4af37); - backdrop-filter:blur(6px);} -.hover-panel.hp-visible{opacity:1;} -.hover-panel::after{content:'';position:absolute;left:50%;bottom:-7px;transform:translateX(-50%); - width:0;height:0;border:7px solid transparent;border-top-color:var(--hc,#d4af37);} -.hp-name{font-family:var(--font-mono);font-weight:700;font-size:1.05rem;letter-spacing:.08em;} -.hp-role{font-size:.62rem;color:var(--text-muted);margin:.1rem 0 .5rem;} -.hp-head{font-family:var(--font-mono);font-size:.6rem;letter-spacing:.22em;color:var(--text-dim); - border-top:1px solid rgba(255,255,255,.12);padding-top:.4rem;margin-bottom:.4rem;} -.hp-list{list-style:none;display:flex;flex-direction:column;gap:.4rem;} -.hp-line{display:flex;align-items:center;gap:.5rem;font-family:var(--font-mono);font-size:.72rem; - color:var(--text-main);min-height:22px;opacity:.25;} -.hp-line.hp-shown{opacity:1;} -.hp-line.hp-pulse{animation:hp-pulse 1.4s ease-in-out infinite;} -@keyframes hp-pulse{0%,100%{filter:none;}50%{filter:drop-shadow(0 0 5px var(--hc));}} -.sp-icon{display:inline-flex;width:22px;height:22px;flex:0 0 22px;} -.sp-static *{animation:none !important;} -.hp-text{white-space:nowrap;overflow:hidden;} - -/* Accessible focus proxies (visually hidden but focusable) */ -.a11y-heroes{position:absolute;width:1px;height:1px;overflow:hidden;} -.a11y-heroes button{width:1px;height:1px;} -.a11y-hero:focus{position:fixed;left:8px;top:8px;width:auto;height:auto;z-index:200; - padding:.4rem .7rem;background:var(--gold);color:#150b22;border:0;border-radius:4px; - font-family:var(--font-mono);font-size:.7rem;} - -/* SVG fallback grid (WebGL unavailable) */ -#fallback[hidden]{display:none;} -#fallback{max-width:1100px;margin:1rem auto;padding:0 1rem;} -.fb-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:1rem;} -.fb-cell{display:flex;flex-direction:column;align-items:center;text-decoration:none; - background:#0a0e14;border:1px solid rgba(212,175,55,.18);border-radius:14px;padding:.9rem; - transition:transform .2s,border-color .2s;} -.fb-cell:hover,.fb-cell:focus-visible{transform:translateY(-4px);border-color:var(--gold);} -.fb-cell img{width:100%;aspect-ratio:1/1;border-radius:12px;} -.fb-name{font-family:var(--font-head);color:var(--gold);margin-top:.5rem;} -.fb-role{font-family:var(--font-mono);font-size:.6rem;color:var(--text-dim); - text-transform:uppercase;letter-spacing:.06em;text-align:center;} -@media(max-width:900px){.fb-grid{grid-template-columns:repeat(3,1fr);}} -@media(max-width:560px){.fb-grid{grid-template-columns:repeat(2,1fr);}} - -@media(prefers-reduced-motion:reduce){ - .hover-panel{transition:none;} - .hp-line.hp-pulse{animation:none;} - .sp-anim *{animation:none !important;} -} diff --git a/cursor_reinstill.json b/cursor_reinstill.json deleted file mode 100644 index fdac3888cf35b6db361d5536b186bfdb6dfcca5c..0000000000000000000000000000000000000000 --- a/cursor_reinstill.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "space": "SZLHOLDINGS/README", - "kind": "org-card (static)", - "reinstill_session": "OPUS 4.8 Cursor re-instill \u2014 group G", - "shipped_utc": "2026-06-01T03:30:00Z", - "doctrine": "v10", - "doctrine_numbers": { - "declarations": 749, - "unique_axioms": 14, - "tracked_sorries": 163, - "mcp_tools": 12, - "policy_gates": 46, - "anchor_gates": 44, - "raw_axioms": 15, - "sorries_baseline": 112, - "sorries_putnam": 51 - }, - "honesty_note": "749 declarations / 14 unique axioms (15 raw, 1 dup) / 163 tracked sorries (112 baseline + 51 Putnam) per lean_numbers.py @ c7c0ba17. v18 'zero sorry' claim is FALSE. \u039b uniqueness is a Conjecture (CAUCHY_ND sorry). Prior 456/6 re-audit was wrong.", - "integration_mode": "un-doctrine corrections only (additive metadata fix); org card is a static HTML/markdown Space \u2014 Cursor coordination/SDK/AGENTS PRs recorded as provenance.", - "files_corrected": [ - { - "file": "README.md", - "changes": [ - "declarations stated as canonical 749", - "tracked sorries stated as canonical 163 (112 baseline + 51 Putnam)", - "unique axioms 14 (15 raw, 1 dup)", - "11 MCP tools -> 12 MCP tools", - "Doctrine v9 -> Doctrine v10 (footer); retired the earlier 456/6 figures from a stale clone" - ] - }, - { - "file": "index.html", - "changes": [ - "Doctrine v9 -> Doctrine v10 (meta description)", - "Doctrine v9 -> Doctrine v10 (og:description)", - "Doctrine v9 -> Doctrine v10 (footer)" - ] - } - ], - "founder_locked_preserved": [ - "assets/szl_banner.png (HF banner)", - "5 painterly hero avatars: rosie/a11oy/amaru/sentra/vessels _avatar.png", - "animated emoji layer (assets/emoji/*_emoji.png) on org card" - ], - "cursor_prs_recorded": [ - { - "repo": "szl-holdings/.github", - "pr": 74, - "cat": "anatomy", - "title": "feat(anatomy-alive): Perplexity cross-organ integration" - }, - { - "repo": "szl-holdings/szl-brand", - "pr": 40, - "cat": "feature", - "title": "Transform szl-brand into a real Python SDK" - }, - { - "repo": "szl-holdings/.github", - "pr": 86, - "cat": "feature", - "title": "docs(coordination): CURSOR_MASTER_DIRECTIVE \u2014 Series-A" - }, - { - "repo": "szl-holdings/.github", - "pr": 97, - "cat": "doctrine", - "title": "docs(coordination): Cursor master directive FINAL" - }, - { - "repo": "szl-holdings/.github", - "pr": 83, - "cat": "proof", - "title": "feat(coordination): Cursor instillation operational plan" - }, - { - "repo": "szl-holdings/.github", - "pr": 82, - "cat": "feature", - "title": "feat(coordination): CTO+PM consolidated 30-day operational plan" - }, - { - "repo": "szl-holdings/.github", - "pr": 89, - "cat": "feature", - "title": "[CURSOR DIRECTIVE] INSTILL ALL THEORIES \u2014 Tier 0-4" - }, - { - "repo": "szl-holdings/.github", - "pr": 90, - "cat": "feature", - "title": "[CURSOR MASTER] ONE-OF-ONE Directive \u2014 28 PhD agents" - }, - { - "repo": "szl-holdings/.github", - "pr": 73, - "cat": "uds", - "title": "chore(coordination): UDS v0.3.0 release-cut directive" - }, - { - "repo": "szl-holdings/.github", - "pr": 72, - "cat": "anatomy", - "title": "chore(coordination): Cursor Phase 1 \u2014 innovate & evolve" - }, - { - "repo": "szl-holdings/.github", - "pr": 79, - "cat": "doctrine", - "title": "chore(coordination): Cursor full throttle \u2014 all tracks" - }, - { - "repo": "szl-holdings/.github", - "pr": 68, - "cat": "anatomy", - "title": "chore(coordination): P0 directive \u2014 make anatomy real" - }, - { - "repo": "szl-holdings/szl-brand", - "pr": 39, - "cat": "feature", - "title": "Add AGENTS.md with Cursor Cloud development environment" - }, - { - "repo": "szl-holdings/.github", - "pr": 56, - "cat": "feature", - "title": "docs: add AGENTS.md with Cursor Cloud development instructions" - }, - { - "repo": "szl-holdings/.github", - "pr": 81, - "cat": "doctrine", - "title": "fix(docs): repair broken anatomy PDF links in org profile" - } - ], - "cursor_prs_count": 15, - "ip_hold_untouched": [ - "a11oy#57", - "amaru#46", - "sentra#45" - ], - "canonical_ref": "lutar-lean tag lutar-v18.0.0 / c7c0ba17" -} \ No newline at end of file diff --git a/demo.html b/demo.html deleted file mode 100644 index a241c9f189f1f2dabb5dc2372f8f6751532b99d6..0000000000000000000000000000000000000000 --- a/demo.html +++ /dev/null @@ -1,313 +0,0 @@ - - - - - -SZL Holdings — Live Demo Surfaces - - - - - - - - - - - - - -
- -
-
SZL Holdings · Sovereign Agentic Mesh
-

Live Demo Surfaces

-

A public index of every reachable surface in the SZL flagship mesh — five organs, the unified - 4-pane operator shell, the formula corpus, the multi-LLM ensemble vote, and the provenance trail. - Status pills below are live: each card probes its own /healthz in your browser. - Endpoints that aren't live yet show gray — never faked.

-
- Doctrine v11 LOCKED - 749 / 14 / 163 - Λ — Conjecture 1 (NOT a theorem) - SLSA L1 honest (L2 in progress) - Apache-2.0 -
- -
- - -
-

Five Organs — Operator Consoles

/operator on each Space
-
-
- - -
-

Unified 4-Pane Operator Shell

/unified — terrain · panel · cmd-K · receipt tunnel
-
-
- - -
-

Reasoning, Formulas & Ensemble

a11oy frontier surfaces
-
-
- - -
-

Organ-Specific APIs

inspect · cortex · honest · drones · frontier formulas
-
-
- - -
-

Provenance & Releases

GitHub releases · DOIs · MCP gateway
-
-
- - -
-

Mesh Status & Anatomy

live status board · organ anatomy gallery
-
-
- -
-
- Doctrine v11 LOCKED · locked_at c7c0ba17 - 749 declarations / 14 axioms / 163 sorries - Λ = Conjecture 1 (NOT a theorem) - SLSA L1 honest (L2 in progress) - Apache-2.0 -
-

Honest disclosures. The Lean corpus carries 163 open sorry placeholders - across 749 declarations and 14 axioms — these are not closed proofs. The Λ result is Conjecture 1, - explicitly not a theorem. Supply-chain provenance is SLSA Level 1, stated honestly rather than - overclaimed. Some surfaces listed here (frontier formula APIs, certain drone endpoints) may show gray / red - when a parallel build is still in progress — pills reflect real-time probes, never fabricated liveness. - All code is licensed Apache-2.0; the mesh runs without any external CDN (sovereign).

-
Built by Yachay <yachay@szlholdings.dev> · Co-Authored-By: Perplexity Computer Agent · Signed-off-by: Yachay · Change-class: ADDITIVE
-
- -
- - - - diff --git a/deployment.json b/deployment.json new file mode 100644 index 0000000000000000000000000000000000000000..f4d59f151ddaba59478cb9f00203cbab2643001c --- /dev/null +++ b/deployment.json @@ -0,0 +1 @@ +{"claims":{"estate_operational_status":"NOT_INFERRED","model_quality":"NOT_EVALUATED_BY_THIS_SURFACE","source_binding":"MEASURED_AFTER_LIVE_READBACK"},"files":[{"path":".gitattributes","sha256":"ea03f0eb78cadeb1c5656da28f49131c2d367f19f47ba705b1551409d4b509bb","size":73},{"path":"HONEST_DISCLOSURE.md","sha256":"19a6535a4c79f3a5868c5eaf445103e101ebeb3a795826fb014b36b77bb84111","size":1133},{"path":"README.md","sha256":"28b2c3bd1eee4a01b6fd97ba3a699011173c27146ff4d5963a82b6fec9d3a8a4","size":5127},{"path":"assets/estate-command-system.svg","sha256":"b77048f37d55c0463ecd9e05a470259477b67adf72de464714045190991094bc","size":5812},{"path":"index.html","sha256":"4398923dcdcaf37f026cbc9a877a085b7a8b48bef2f0ea0d2b0be932c57b6722","size":17195}],"published_at":"2026-08-01T17:52:17.676948Z","schema":"szl.hf-static-deployment/v1","source":{"manifest":"huggingface/org-card.manifest.json","repository":"szl-holdings/.github","revision":"813ba58892b869b931adc30db428a4a61cedaf4b"},"target":{"live_base_url":"https://szlholdings-readme.static.hf.space","repo_id":"SZLHOLDINGS/README","repo_type":"space"}} diff --git a/hero.png b/hero.png deleted file mode 100644 index ce44d9d13bad35a27d354436b110fe8ec8da3d2c..0000000000000000000000000000000000000000 --- a/hero.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ba95d0433066e591fa2fe7ce5df74621f51f8cb9588345bc69383f9989543951 -size 327424 diff --git a/hero.svg b/hero.svg deleted file mode 100644 index 4fe5067624b4f1c04cb2a7d82ec548ff6451d3e3..0000000000000000000000000000000000000000 --- a/hero.svg +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/index.html b/index.html index 27aa0587101d64a4358a8aed2356e62b282bb1bf..f6769313b2f9e0beca921dc912aa6ab052390539 100644 --- a/index.html +++ b/index.html @@ -1,317 +1,287 @@ - - -SZL Holdings — Governed AI you can prove. - - - - + @media (max-width: 900px) { + .hero, .section-head, .truth { grid-template-columns: 1fr; } + .hero { gap: 42px; } + .hero-visual { max-width: 640px; } + .cards { grid-template-columns: 1fr 1fr; } + .steps { grid-template-columns: repeat(3, 1fr); } + } + @media (max-width: 640px) { + .shell { width: min(100% - 28px, 1180px); } + .nav { min-height: 64px; } + nav a:not(.essential) { display: none; } + .hero { padding-top: 58px; } + h1 { font-size: clamp(42px, 15vw, 68px); } + .cards, .contract { grid-template-columns: 1fr; } + .steps { grid-template-columns: 1fr 1fr; } + section { padding: 64px 0; } + } + @media (prefers-reduced-motion: reduce) { + html { scroll-behavior: auto; } + .card { transition: none; } + } + - - -
-
- - Holding company · Kernel c7c0ba17 · Doctrine-bound -

Governed AI you can prove.

-

SZL Holdings builds governed autonomy with a checkable receipt for every decision. Every autonomous - action carries a machine-checked, tamper-evident warrant — proof of under what authority - it acted, on what trust evidence, and that the record was not quietly rewritten.

- - -
- 8 locked-proven - ~185 machine-checked - Λ = Conjecture 1 - Khipu = Conjecture 2 - SLSA L1 · L2 attested · L3 roadmap - cosign keyless -
- - - - - - - - - -
- - david-leads - Sovereign insurance intelligence — audit-defensible leads from public data only. - - - immune - Verifiable-AI defense — an append-only SHA-256 receipt chain with admission gates and tripwires. - - - sda - Domain awareness — graph anomaly detection and multi-sensor track fusion into a Λ-gated picture. - - - yarqa - Plug-flow compartments — a CFD engineering-method loop: sense → route → gate → receipt. + + +
+ - - - -
-

Confirm a decision happened, exactly as recorded — with zero trust in SZL

-

Pull the public signing key and a signed receipt from a live field node, then verify offline:

-
# pull the public key + a signed receipt from the live field node
-curl -s https://szlholdings-killinchu.hf.space/cosign.pub -o cosign.pub
-curl -s https://szlholdings-killinchu.hf.space/api/killinchu/v1/receipt/export > receipt.json
-# verify the DSSE signature offline "Verified OK"
-# tamper a single byte and re-verify"Verification failure"
+
+
-
- - -
-

What we claim — and what we don't

-

We surface only machine-checked facts as fact.

-

8 formulas formally proven & locked in Lean (sorry-free): - F1, F4, F7, F11, F12, F18, F19, F22 — this count never inflates. A larger experimental - tier is kernel-clean / CI-green on main @ c7c0ba17 across Waves 11–23 - (axioms ⊆ propext / Classical.choice / Quot.sound), labeled experimental — never folded into the locked eight.
- • Λ uniqueness = Conjecture 1 — unconditional uniqueness is machine-checked false. - The conditional uniqueness (Theorem U, on separability) is proven axiom-free. - Khipu Byzantine BFT safety = Conjecture 2 (Wave23 proves a conditional quorum-agreement, - axiom-clean; unconditional stays open).
- • SLSA L1 (honest) · L2 build-attested — container provenance via Sigstore keyless - (Fulcio + Rekor) where attest-build-provenance runs & verifies (a11oy, killinchu); - verify with gh attestation verify / cosign verify-attestation. - L3, FedRAMP, Iron Bank, CMMC, ATO = roadmap.
- • Receipts are genuinely signed where a key is present, honestly marked unsigned otherwise — - never fabricated. Trust is never 100%.
- • Maritime AIS uses a clearly-labeled sample/replay dataset, not a live feed.

-

Read the thesis → szl-papers - · Run the kernel → lutar-lean - · Deploy the mesh → uds deploy oci://ghcr.io/szl-holdings/szl-mesh:0.4.0 --confirm

+
+
+
+
Governed decision infrastructure
+

Autonomy,
under authority.

+

Systems that can reason, act within a declared bound, and return evidence another party can verify.

+ +
+ Signal to policy to bounded action to receipt to verification
+
+
+
+
One governed loop

Control before action. Evidence after.

+

The model proposes. A policy layer validates authority and evidence. The runtime executes only within a declared bound. A portable receipt records the decision path for independent review.

+
+
+
+
SignalObserve and attribute the request.
+
ReasonGround the proposal in disclosed context.
+
PolicyAllow, require approval, or refuse.
+
ActExecute only inside the permitted bound.
+
ReceiptBind inputs, policy, action, and outcome.
+
VerifyReplay evidence outside the product UI.
+
+
+
+
-
- - + -
- Built by Stephen P. Lutar Jr. · Honest by design · - github.com/szl-holdings
- Not affiliated with Defense Unicorns · SZL mark USPTO Serial 99831122 · no production ATO claimed · - Λ = Conjecture 1 · Khipu = Conjecture 2 · trust never 100% -
+
+
+
+
Publication contract

A card is not proof.

+

Promotion requires exact lineage, hashes, load and inference evidence, evaluation, restart reproducibility, resource context, and an explicit autonomy boundary.

+
+
+

Weights

Base and license lineage, immutable hashes, clean load, held-out evaluation, restart evidence, resource envelope.

+

Datasets

Schema, splits, provenance, consent, PII posture, validation, quarantine, gaps, and update policy.

+

Kernels

Canonical source, supported hardware matrix, executable tests, benchmark protocol, and non-model classification.

+

Spaces

Source revision, dependency pins, served-revision binding, privacy behavior, limits, and a reproducible local path.

+
-
-
+
+
+

Evidence and runtime are separate axes.

+

A signature establishes integrity and origin within scope. It does not automatically establish model quality, safety, regulatory compliance, profitability, or authorization to operate.

+
+ PROVEDMEASUREDREPORTEDMODELEDCONJECTUREROADMAP +
+
+
+

Inspect the served source.

+

This page is published from GitHub. The running Space exposes its source binding at /deployment.json.

+ Open deployment evidence +
+
+
+ - +
+
+
Build, evaluate, verify
+

Move from model output to accountable action.

+

Start with the product, follow the evidence, then reproduce the exact path from source.

+ +
+
+ + diff --git a/js/canvas_decals.js b/js/canvas_decals.js deleted file mode 100644 index b7c8350002e729dbb6e99c0e87a511d7e920f05f..0000000000000000000000000000000000000000 --- a/js/canvas_decals.js +++ /dev/null @@ -1,195 +0,0 @@ -// canvas_decals.js -// Procedural canvas-painted textures for UDS swag — zero external assets. -// Every texture is generated with the 2D Canvas API and wrapped in a THREE.CanvasTexture. -// This keeps the scene asset-free (fast load, no licensing risk, clearly readable). -import * as THREE from 'three'; - -const DPR = 2; // supersample the decal canvases for crisp text - -function makeCanvas(w, h) { - const c = document.createElement('canvas'); - c.width = w * DPR; - c.height = h * DPR; - const ctx = c.getContext('2d'); - ctx.scale(DPR, DPR); - return { c, ctx, w, h }; -} - -function texFrom(c) { - const t = new THREE.CanvasTexture(c); - t.anisotropy = 4; - t.colorSpace = THREE.SRGBColorSpace; - t.needsUpdate = true; - return t; -} - -// Draw a small emblem glyph for a hero. Keeps shapes simple + iconic. -function drawEmblem(ctx, kind, cx, cy, r, color) { - ctx.save(); - ctx.translate(cx, cy); - ctx.strokeStyle = color; - ctx.fillStyle = color; - ctx.lineWidth = Math.max(2, r * 0.14); - ctx.lineCap = 'round'; - ctx.lineJoin = 'round'; - switch (kind) { - case 'serpent': { // AMARU — golden serpent S-curve - ctx.beginPath(); - for (let i = 0; i <= 40; i++) { - const t = i / 40; - const a = t * Math.PI * 2.6; - const x = Math.sin(a) * r * 0.62; - const y = (t - 0.5) * r * 1.9; - if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); - } - ctx.stroke(); - ctx.beginPath(); ctx.arc(Math.sin(0) * r * 0.62, -0.5 * r * 1.9, r * 0.16, 0, 7); ctx.fill(); - break; - } - case 'shield': { // SENTRA — gate-glyph shield - ctx.beginPath(); - ctx.moveTo(0, -r); - ctx.lineTo(r * 0.82, -r * 0.45); - ctx.lineTo(r * 0.62, r * 0.85); - ctx.lineTo(0, r); - ctx.lineTo(-r * 0.62, r * 0.85); - ctx.lineTo(-r * 0.82, -r * 0.45); - ctx.closePath(); ctx.stroke(); - // gate bars inside - for (let i = -1; i <= 1; i++) { - ctx.beginPath(); - ctx.moveTo(-r * 0.4, i * r * 0.32); - ctx.lineTo(r * 0.4, i * r * 0.32); - ctx.stroke(); - } - break; - } - case 'console': { // ROSIE — console rune (terminal prompt) - ctx.strokeRect(-r * 0.9, -r * 0.7, r * 1.8, r * 1.4); - ctx.beginPath(); - ctx.moveTo(-r * 0.5, -r * 0.2); - ctx.lineTo(-r * 0.1, r * 0.05); - ctx.lineTo(-r * 0.5, r * 0.3); - ctx.stroke(); - ctx.beginPath(); - ctx.moveTo(r * 0.05, r * 0.3); - ctx.lineTo(r * 0.55, r * 0.3); - ctx.stroke(); - break; - } - case 'falcon': { // KILLINCHU — falcon / kestrel in flight - ctx.beginPath(); - ctx.moveTo(-r, -r * 0.1); - ctx.quadraticCurveTo(-r * 0.35, -r * 0.65, 0, -r * 0.15); - ctx.quadraticCurveTo(r * 0.35, -r * 0.65, r, -r * 0.1); - ctx.quadraticCurveTo(r * 0.35, r * 0.1, 0, r * 0.55); - ctx.quadraticCurveTo(-r * 0.35, r * 0.1, -r, -r * 0.1); - ctx.closePath(); ctx.fill(); - break; - } - case 'router': { // A11OY — neural-net / multi-arrow router node - ctx.beginPath(); ctx.arc(0, 0, r * 0.28, 0, 7); ctx.stroke(); - const dirs = [[0, -1], [0.87, 0.5], [-0.87, 0.5]]; - for (const [dx, dy] of dirs) { - ctx.beginPath(); - ctx.moveTo(dx * r * 0.3, dy * r * 0.3); - ctx.lineTo(dx * r, dy * r); - ctx.stroke(); - // arrowhead - ctx.beginPath(); - ctx.arc(dx * r, dy * r, r * 0.12, 0, 7); - ctx.fill(); - } - break; - } - } - ctx.restore(); -} - -// Build the wrap-around torso texture: dark fabric, name stencil on chest, -// UDS monogram patch on right shoulder, emblem on chest center. -// The texture wraps a cylinder; chest faces +Z, so we paint chest at U≈0.5. -export function makeTorsoTexture({ name, stencil, emblem, color, swatch }) { - const W = 512, H = 512; - const { c, ctx } = makeCanvas(W, H); - // base fabric - const g = ctx.createLinearGradient(0, 0, 0, H); - g.addColorStop(0, shade(swatch, -0.45)); - g.addColorStop(1, shade(swatch, -0.7)); - ctx.fillStyle = g; ctx.fillRect(0, 0, W, H); - - // subtle vertical seams - ctx.strokeStyle = 'rgba(0,0,0,0.25)'; ctx.lineWidth = 2; - for (let x = 64; x < W; x += 128) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, H); ctx.stroke(); } - - // chest panel (centered at U=0.5 -> x=W/2) - const cx = W / 2; - // emblem on chest center - drawEmblem(ctx, emblem, cx, H * 0.42, 56, color); - - // name stencil under emblem - ctx.fillStyle = '#f4f4f6'; - ctx.font = 'bold 30px "JetBrains Mono", monospace'; - ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; - ctx.fillText(stencil, cx, H * 0.66); - // colored underline - ctx.fillStyle = color; ctx.fillRect(cx - 120, H * 0.72, 240, 4); - - // UDS shoulder patch — right shoulder sits near U≈0.78 -> x≈0.78*W - drawUDSPatch(ctx, W * 0.80, H * 0.16, 70, color); - - return texFrom(c); -} - -// A reusable UDS monogram patch (also used by grey NPCs). -export function drawUDSPatch(ctx, cx, cy, size, accent = '#9aa3ad') { - ctx.save(); - ctx.translate(cx, cy); - // patch backing - ctx.fillStyle = '#1b2128'; - roundRect(ctx, -size * 0.7, -size * 0.55, size * 1.4, size * 1.1, 8); ctx.fill(); - ctx.strokeStyle = accent; ctx.lineWidth = 3; - roundRect(ctx, -size * 0.7, -size * 0.55, size * 1.4, size * 1.1, 8); ctx.stroke(); - // UDS text - ctx.fillStyle = '#e8edf2'; - ctx.font = `bold ${Math.round(size * 0.5)}px "JetBrains Mono", monospace`; - ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; - ctx.fillText('UDS', 0, -size * 0.05); - ctx.fillStyle = accent; - ctx.font = `${Math.round(size * 0.16)}px "JetBrains Mono", monospace`; - ctx.fillText('UNITED DEFENSE', 0, size * 0.32); - ctx.restore(); -} - -// Plain grey UDS NPC torso texture. -export function makeNPCTexture() { - const W = 256, H = 256; - const { c, ctx } = makeCanvas(W, H); - const g = ctx.createLinearGradient(0, 0, 0, H); - g.addColorStop(0, '#3a4048'); g.addColorStop(1, '#262b31'); - ctx.fillStyle = g; ctx.fillRect(0, 0, W, H); - drawUDSPatch(ctx, W / 2, H * 0.42, 48, '#7f8a95'); - ctx.fillStyle = '#b9c2cb'; - ctx.font = '600 16px "JetBrains Mono", monospace'; - ctx.textAlign = 'center'; - ctx.fillText('PARADE REST', W / 2, H * 0.78); - return texFrom(c); -} - -function roundRect(ctx, x, y, w, h, r) { - ctx.beginPath(); - ctx.moveTo(x + r, y); - ctx.arcTo(x + w, y, x + w, y + h, r); - ctx.arcTo(x + w, y + h, x, y + h, r); - ctx.arcTo(x, y + h, x, y, r); - ctx.arcTo(x, y, x + w, y, r); - ctx.closePath(); -} - -function shade(hex, amt) { - const c = new THREE.Color(hex); - const hsl = {}; c.getHSL(hsl); - hsl.l = Math.max(0, Math.min(1, hsl.l + amt)); - c.setHSL(hsl.h, hsl.s * 0.8, hsl.l); - return '#' + c.getHexString(); -} diff --git a/js/heroes.js b/js/heroes.js deleted file mode 100644 index acf4b6e36ccc63a05959cd4c493c13ad8fc613eb..0000000000000000000000000000000000000000 --- a/js/heroes.js +++ /dev/null @@ -1,219 +0,0 @@ -// heroes.js -// The 5 SZL heroes: stylized low-poly humanoids built from primitives -// (capsule torso/limbs, sphere head, cone stance) — deliberately PS1-era, -// readable, fast, fully procedural. UDS swag painted via canvas_decals. -import * as THREE from 'three'; -import { makeTorsoTexture } from './canvas_decals.js'; - -export const HEROES = [ - { - id: 'amaru', name: 'AMARU', role: 'Cognitive Cortex — the brain', - color: '#f5c518', stencil: 'AMARU · CORTEX', emblem: 'serpent', - swag: 'Gold UDS shoulder patch · golden serpent emblem', - url: 'https://huggingface.co/spaces/SZLHOLDINGS/amaru', - prop: 'brain', - powers: [ - { label: 'Dual-stream routing', icon: 'amaru_dualstream' }, - { label: '7-chakra memory', icon: 'amaru_memory' }, - { label: 'Forward-model prediction', icon: 'amaru_forward' }, - { label: 'Lineage DAG', icon: 'amaru_lineage' }, - ], - }, - { - id: 'sentra', name: 'SENTRA', role: 'Immune Sentinel — the gates', - color: '#c8324e', stencil: 'SENTRA · SHIELD', emblem: 'shield', - swag: 'Crimson UDS tactical vest · gate-glyph shield emblem', - url: 'https://huggingface.co/spaces/SZLHOLDINGS/sentra', - prop: 'runes', - powers: [ - { label: '8 fail-CLOSED gates', icon: 'sentra_gates' }, - { label: 'DSSE signing', icon: 'sentra_dsse' }, - { label: 'Conduction-aphasia detector', icon: 'sentra_conduction' }, - { label: 'Cosign verify', icon: 'sentra_cosign' }, - ], - }, - { - id: 'rosie', name: 'ROSIE', role: 'Executive Operator — multi-organ orchestrator', - color: '#2ea66c', stencil: 'ROSIE · CONSOLE', emblem: 'console', - swag: 'Emerald UDS command jacket · console-rune emblem', - url: 'https://huggingface.co/spaces/SZLHOLDINGS/rosie', - prop: 'console', - powers: [ - { label: 'Multi-LLM ensemble', icon: 'rosie_ensemble' }, - { label: 'Adaptive routing', icon: 'rosie_routing' }, - { label: 'Step-3.7-Flash voter', icon: 'rosie_step' }, - { label: 'Executive UI', icon: 'rosie_exec' }, - ], - }, - { - id: 'killinchu', name: 'KILLINCHU', role: 'Kestrel Drone Health — UDS Edition', - color: '#4ac4d9', stencil: 'KILLINCHU · KESTREL', emblem: 'falcon', - swag: 'Full UDS field uniform · falcon emblem — the UDS face', - url: 'https://huggingface.co/spaces/SZLHOLDINGS/killinchu', - prop: 'hud', isUDSFace: true, - powers: [ - { label: 'NOAA space-weather', icon: 'kil_noaa' }, - { label: 'USGS seismic', icon: 'kil_usgs' }, - { label: 'MQ-9 drone health', icon: 'kil_mq9' }, - { label: 'Phase prediction', icon: 'kil_phase' }, - ], - }, - { - id: 'a11oy', name: 'A11OY', role: 'Sovereign Router — the wires', - color: '#8b6cf2', stencil: 'A11OY · ROUTER', emblem: 'router', - swag: 'Violet UDS sash · neural-net circuit pattern', - url: 'https://huggingface.co/spaces/SZLHOLDINGS/a11oy', - prop: 'streams', - powers: [ - { label: 'PAC-Bayes governance', icon: 'a11_governance' }, - { label: 'Multi-LLM router', icon: 'a11_router' }, - { label: '35 anchor formulas', icon: 'a11_formulas' }, - { label: 'Khipu chain', icon: 'a11_khipu' }, - ], - }, -]; - -// Build one stylized low-poly humanoid. Returns a THREE.Group with a `.userData` -// describing animatable parts (torso for breathing, prop group, etc.). -export function buildHero(hero) { - const g = new THREE.Group(); - const col = new THREE.Color(hero.color); - const skin = new THREE.Color('#caa98c'); - - const matBody = new THREE.MeshStandardMaterial({ - map: makeTorsoTexture({ - name: hero.name, stencil: hero.stencil, emblem: hero.emblem, - color: hero.color, swatch: hero.color, - }), - roughness: 0.62, metalness: 0.12, flatShading: true, - }); - const matLimb = new THREE.MeshStandardMaterial({ - color: col.clone().multiplyScalar(0.45), roughness: 0.7, metalness: 0.1, flatShading: true, - }); - const matSkin = new THREE.MeshStandardMaterial({ color: skin, roughness: 0.8, flatShading: true }); - const matAccent = new THREE.MeshStandardMaterial({ - color: col, emissive: col, emissiveIntensity: 0.35, roughness: 0.4, metalness: 0.3, flatShading: true, - }); - - // Torso — capsule. Pivot so breathing scales from the waist. - const torsoGeo = new THREE.CapsuleGeometry(0.34, 0.7, 4, 10); - const torso = new THREE.Mesh(torsoGeo, matBody); - torso.castShadow = true; - const torsoPivot = new THREE.Group(); - torso.position.y = 0.55; - torsoPivot.add(torso); - torsoPivot.position.y = 0.9; - g.add(torsoPivot); - - // Head — sphere + a small accent visor band. - const head = new THREE.Mesh(new THREE.SphereGeometry(0.27, 16, 12), matSkin); - head.position.y = 0.55 + 0.62; - head.castShadow = true; - torsoPivot.add(head); - const visor = new THREE.Mesh(new THREE.TorusGeometry(0.24, 0.05, 6, 16), matAccent); - visor.rotation.x = Math.PI / 2.1; - visor.position.y = 0.55 + 0.66; - torsoPivot.add(visor); - - // Shoulders / arms — capsules angled outward (parade-ready stance). - for (const side of [-1, 1]) { - const arm = new THREE.Mesh(new THREE.CapsuleGeometry(0.1, 0.6, 4, 8), matLimb); - arm.position.set(side * 0.46, 0.42, 0); - arm.rotation.z = side * 0.18; - arm.castShadow = true; - torsoPivot.add(arm); - const shoulder = new THREE.Mesh(new THREE.SphereGeometry(0.14, 10, 8), matAccent); - shoulder.position.set(side * 0.44, 0.78, 0); - torsoPivot.add(shoulder); - } - - // Legs — capsules. - for (const side of [-1, 1]) { - const leg = new THREE.Mesh(new THREE.CapsuleGeometry(0.13, 0.7, 4, 8), matLimb); - leg.position.set(side * 0.17, 0.45, 0); - leg.castShadow = true; - g.add(leg); - } - - // Stance cone — anchors the figure to the dais (the "base"). - const base = new THREE.Mesh(new THREE.ConeGeometry(0.5, 0.3, 16), matLimb); - base.position.y = 0.12; base.rotation.x = Math.PI; - g.add(base); - - // Prop group (weapon/tool) — hidden until hover. - const prop = buildProp(hero, col); - prop.visible = false; - g.add(prop); - - g.userData = { hero, torsoPivot, prop, baseScale: 1 }; - return g; -} - -// Per-hero activated prop. Returns a group positioned around the hero. -function buildProp(hero, col) { - const grp = new THREE.Group(); - const mat = new THREE.MeshStandardMaterial({ - color: col, emissive: col, emissiveIntensity: 0.9, transparent: true, - opacity: 0.85, roughness: 0.3, metalness: 0.4, - }); - switch (hero.prop) { - case 'brain': { // glowing brain hemispheres halo above head - for (const side of [-1, 1]) { - const hemi = new THREE.Mesh(new THREE.SphereGeometry(0.18, 12, 10, 0, Math.PI), mat); - hemi.position.set(side * 0.16, 2.05, 0); - hemi.rotation.y = side > 0 ? 0 : Math.PI; - grp.add(hemi); - } - const halo = new THREE.Mesh(new THREE.TorusGeometry(0.34, 0.02, 6, 24), mat); - halo.position.y = 2.05; halo.rotation.x = Math.PI / 2; - grp.add(halo); - grp.userData.spin = halo; - break; - } - case 'runes': { // 8 floating shield runes orbit - const runes = []; - for (let i = 0; i < 8; i++) { - const r = new THREE.Mesh(new THREE.BoxGeometry(0.12, 0.16, 0.03), mat); - const a = (i / 8) * Math.PI * 2; - r.position.set(Math.cos(a) * 0.7, 1.0, Math.sin(a) * 0.7); - grp.add(r); runes.push(r); - } - grp.userData.orbit = runes; - break; - } - case 'console': { // holographic console panel materializes in front - const panel = new THREE.Mesh(new THREE.PlaneGeometry(0.8, 0.5), mat); - panel.position.set(0, 1.1, 0.55); - grp.add(panel); - for (let i = 0; i < 3; i++) { - const bar = new THREE.Mesh(new THREE.BoxGeometry(0.5, 0.04, 0.01), - new THREE.MeshStandardMaterial({ color: '#0a160f', emissive: col, emissiveIntensity: 0.6 })); - bar.position.set(0, 1.2 - i * 0.12, 0.56); - grp.add(bar); - } - break; - } - case 'hud': { // holographic drone HUD reticle locks on - const reticle = new THREE.Mesh(new THREE.RingGeometry(0.28, 0.34, 24), mat); - reticle.position.set(0, 1.4, 0.5); - grp.add(reticle); - const inner = new THREE.Mesh(new THREE.RingGeometry(0.1, 0.12, 16), mat); - inner.position.set(0, 1.4, 0.5); - grp.add(inner); - grp.userData.spin = reticle; - break; - } - case 'streams': { // glowing routing-arrow streams flow from hand - const streams = []; - for (let i = 0; i < 5; i++) { - const s = new THREE.Mesh(new THREE.ConeGeometry(0.05, 0.18, 6), mat); - s.position.set(0.5, 0.7 + i * 0.02, 0.2); - s.rotation.z = -Math.PI / 2; - grp.add(s); streams.push(s); - } - grp.userData.stream = streams; - break; - } - } - return grp; -} diff --git a/js/hover_panel.js b/js/hover_panel.js deleted file mode 100644 index 9d9dee5071863b792142c181dcabdb2e4b8bed51..0000000000000000000000000000000000000000 --- a/js/hover_panel.js +++ /dev/null @@ -1,84 +0,0 @@ -// hover_panel.js -// Floating holographic superpower panel. Rendered as a DOM overlay anchored to -// the hero's screen-projected head position (rises ~60cm above the head in world -// space). Name in hero color (monospace), SUPERPOWERS header, 4 lines that type -// out sequentially (30ms/char) then pulse, each with an animated SVG icon. -import { buildIcon } from './superpower_icons.js'; - -export class HoverPanel { - constructor(container, reduced) { - this.container = container; - this.reduced = reduced; - this.el = document.createElement('div'); - this.el.className = 'hover-panel'; - this.el.setAttribute('role', 'tooltip'); - this.el.setAttribute('aria-hidden', 'true'); - container.appendChild(this.el); - this.activeId = null; - this._timers = []; - } - - _clearTimers() { this._timers.forEach(clearTimeout); this._timers = []; } - - show(hero) { - if (this.activeId === hero.id) return; - this.activeId = hero.id; - this._clearTimers(); - const c = hero.color; - this.el.style.setProperty('--hc', c); - this.el.innerHTML = ` -
${hero.name}
-
${hero.role}
-
SUPERPOWERS
-
    `; - const list = this.el.querySelector('.hp-list'); - hero.powers.forEach((p, i) => { - const li = document.createElement('li'); - li.className = 'hp-line'; - const icon = buildIcon(p.icon, c, this.reduced); - const txt = document.createElement('span'); - txt.className = 'hp-text'; - li.appendChild(icon); - li.appendChild(txt); - list.appendChild(li); - if (this.reduced) { - txt.textContent = p.label; - li.classList.add('hp-shown'); - } else { - // sequential type-out: 30ms/char, staggered per line - const startDelay = i * 520; - this._timers.push(setTimeout(() => this._type(li, txt, p.label), startDelay)); - } - }); - this.el.classList.add('hp-visible'); - this.el.setAttribute('aria-hidden', 'false'); - } - - _type(li, txt, label) { - li.classList.add('hp-shown'); - let n = 0; - const step = () => { - txt.textContent = label.slice(0, n); - n++; - if (n <= label.length) { - this._timers.push(setTimeout(step, 30)); - } else { - li.classList.add('hp-pulse'); // pulse once typed - } - }; - step(); - } - - hide() { - this.activeId = null; - this._clearTimers(); - this.el.classList.remove('hp-visible'); - this.el.setAttribute('aria-hidden', 'true'); - } - - // Position the panel at a screen-space point (px), centered horizontally above it. - place(x, y) { - this.el.style.left = x + 'px'; - this.el.style.top = y + 'px'; - } -} diff --git a/js/main.js b/js/main.js deleted file mode 100644 index a1c832148d1a60d7b0bae4d44d567d48717719a2..0000000000000000000000000000000000000000 --- a/js/main.js +++ /dev/null @@ -1,347 +0,0 @@ -// main.js — Three.js bootstrap + character-select scene for the SZL org card. -// Five procedural low-poly heroes on lit daises in a slight arc, slow camera -// carousel orbit, KHIPU-style particle motes, UDS NPCs in the background. -// Hover reveals animated superpowers; click opens the hero's HF Space. -import * as THREE from 'three'; -import { HEROES, buildHero } from './heroes.js'; -import { buildUDSNPCs, animateNPCs } from './uds_npcs.js'; -import { HoverPanel } from './hover_panel.js'; - -const REDUCED = window.matchMedia('(prefers-reduced-motion: reduce)').matches; - -// ---- WebGL capability gate (graceful degradation to SVG grid) ---- -function webglOK() { - try { - if (!window.WebGLRenderingContext) return false; - const c = document.createElement('canvas'); - return !!(c.getContext('webgl2') || c.getContext('webgl')); - } catch (e) { return false; } -} - -const stage = document.getElementById('stage'); -const canvas = document.getElementById('roster'); -const fallback = document.getElementById('fallback'); - -// The static SVG grid (#fallback) is shown by DEFAULT in the markup so the -// org-card context (scripts stripped) and no-WebGL browsers always render the -// 5 tiles. Only when WebGL boots do we hide it and reveal the 3D canvas. -if (!webglOK()) { - canvas.hidden = true; - if (fallback) fallback.hidden = false; // keep visible -} else { - if (fallback) fallback.hidden = true; // hide static grid - canvas.hidden = false; - canvas.style.display = 'block'; - init(); -} - -function init() { - const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true }); - renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); - renderer.shadowMap.enabled = true; - renderer.shadowMap.type = THREE.PCFSoftShadowMap; - - const scene = new THREE.Scene(); - scene.fog = new THREE.FogExp2(0x12091f, 0.045); - - const camera = new THREE.PerspectiveCamera(42, 1, 0.1, 100); - const CAM_RADIUS = 9.2, CAM_HEIGHT = 2.4; - camera.position.set(0, CAM_HEIGHT, CAM_RADIUS); - - // ---- Lights ---- - scene.add(new THREE.AmbientLight(0x5a4a7a, 0.55)); - const key = new THREE.DirectionalLight(0xffffff, 0.85); - key.position.set(4, 9, 6); key.castShadow = true; - key.shadow.mapSize.set(1024, 1024); - key.shadow.camera.near = 1; key.shadow.camera.far = 30; - key.shadow.camera.left = -10; key.shadow.camera.right = 10; - key.shadow.camera.top = 10; key.shadow.camera.bottom = -10; - scene.add(key); - const fill = new THREE.DirectionalLight(0x8b6cf2, 0.3); - fill.position.set(-6, 4, -4); scene.add(fill); - - // ---- Ground plane (receives shadows, dark) ---- - const ground = new THREE.Mesh( - new THREE.CircleGeometry(16, 48), - new THREE.MeshStandardMaterial({ color: 0x0c0718, roughness: 1, metalness: 0 }) - ); - ground.rotation.x = -Math.PI / 2; ground.position.y = -0.02; ground.receiveShadow = true; - scene.add(ground); - - // ---- Heroes on daises in a slight arc, slightly elevated ---- - const heroRoot = new THREE.Group(); - scene.add(heroRoot); - const heroEntries = []; - const N = HEROES.length; - const arcSpan = 2.0; // radians across which heroes are spread - const arcRadius = 5.0; // distance from arc center - HEROES.forEach((hero, i) => { - const t = N === 1 ? 0.5 : i / (N - 1); - const a = -arcSpan / 2 + t * arcSpan; - const x = Math.sin(a) * arcRadius; - const z = -arcRadius + Math.cos(a) * arcRadius * 0.55; // gentle forward arc - const slot = new THREE.Group(); - slot.position.set(x, 0.25, z); // slightly elevated - slot.rotation.y = -a * 0.45; // face toward camera center - - // dais - const daisMat = new THREE.MeshStandardMaterial({ color: 0x171022, roughness: 0.5, metalness: 0.4 }); - const dais = new THREE.Mesh(new THREE.CylinderGeometry(0.95, 1.05, 0.18, 32), daisMat); - dais.position.y = -0.09; dais.receiveShadow = true; dais.castShadow = true; - slot.add(dais); - // colored rim-light ring on the dais edge - const rimMat = new THREE.MeshStandardMaterial({ - color: hero.color, emissive: hero.color, emissiveIntensity: 1.0, - roughness: 0.3, transparent: true, opacity: 0.95, - }); - const rim = new THREE.Mesh(new THREE.TorusGeometry(0.98, 0.045, 8, 48), rimMat); - rim.rotation.x = Math.PI / 2; rim.position.y = 0.02; - slot.add(rim); - // a point light per dais (cheap; 5 total) for the colored glow - const rimLight = new THREE.PointLight(new THREE.Color(hero.color), 1.4, 4.5, 2); - rimLight.position.set(0, 0.6, 0.4); - slot.add(rimLight); - - const figure = buildHero(hero); - slot.add(figure); - - heroRoot.add(slot); - heroEntries.push({ hero, slot, figure, rim, rimMat, rimLight, baseRim: 1.0, - bodyMats: collectBodyMats(figure), hovered: false, scale: 1 }); - }); - - // ---- UDS NPCs in the background ---- - const { group: npcGroup, npcs } = buildUDSNPCs(4); - scene.add(npcGroup); - - // ---- KHIPU DAG particle motes ---- - const PCOUNT = REDUCED ? 0 : 420; - let particles = null, pPos = null, pHome = null, pVel = null; - if (PCOUNT > 0) { - pPos = new Float32Array(PCOUNT * 3); - pHome = new Float32Array(PCOUNT * 3); - pVel = new Float32Array(PCOUNT * 3); - for (let i = 0; i < PCOUNT; i++) { - const r = 3 + Math.random() * 7; - const a = Math.random() * Math.PI * 2; - const x = Math.cos(a) * r, y = Math.random() * 6 + 0.2, z = Math.sin(a) * r - 2; - pPos[i * 3] = pHome[i * 3] = x; - pPos[i * 3 + 1] = pHome[i * 3 + 1] = y; - pPos[i * 3 + 2] = pHome[i * 3 + 2] = z; - } - const pg = new THREE.BufferGeometry(); - pg.setAttribute('position', new THREE.BufferAttribute(pPos, 3)); - const pm = new THREE.PointsMaterial({ color: 0xcda8ff, size: 0.06, transparent: true, opacity: 0.7, - depthWrite: false, blending: THREE.AdditiveBlending }); - particles = new THREE.Points(pg, pm); - scene.add(particles); - } - - // ---- Hover panel (DOM overlay) ---- - const panel = new HoverPanel(stage, REDUCED); - - // ---- Raycaster + invisible hit cylinders per hero ---- - const raycaster = new THREE.Raycaster(); - const pointer = new THREE.Vector2(); - let pointerInside = false; - const hitMeshes = heroEntries.map((e, i) => { - const hit = new THREE.Mesh( - new THREE.CylinderGeometry(0.9, 0.9, 2.6, 8), - new THREE.MeshBasicMaterial({ visible: false }) - ); - hit.position.y = 1.1; - hit.userData.index = i; - e.slot.add(hit); - return hit; - }); - - let activeIndex = -1; - function setActive(idx) { - if (idx === activeIndex) return; - activeIndex = idx; - heroEntries.forEach((e, i) => { e.hovered = (i === idx); }); - if (idx >= 0) { - panel.show(heroEntries[idx].hero); - burst(idx); - stage.style.cursor = 'pointer'; - stage.setAttribute('data-active', heroEntries[idx].hero.id); - } else { - panel.hide(); - stage.style.cursor = 'default'; - stage.removeAttribute('data-active'); - } - } - - // particle energy burst toward a hero then radiate - let burstUntil = 0, burstTarget = new THREE.Vector3(); - function burst(idx) { - if (!particles) return; - burstTarget.copy(heroEntries[idx].slot.position).add(new THREE.Vector3(0, 1.2, 0)); - burstUntil = performance.now() + 900; - } - - // ---- Pointer events ---- - function updatePointer(ev) { - const rect = canvas.getBoundingClientRect(); - pointer.x = ((ev.clientX - rect.left) / rect.width) * 2 - 1; - pointer.y = -((ev.clientY - rect.top) / rect.height) * 2 + 1; - pointerInside = true; - } - canvas.addEventListener('pointermove', updatePointer); - canvas.addEventListener('pointerleave', () => { pointerInside = false; setActive(-1); }); - canvas.addEventListener('click', () => { - if (activeIndex >= 0) window.open(heroEntries[activeIndex].hero.url, '_blank', 'noopener'); - }); - - // ---- Keyboard accessibility: Tab cycles, Enter activates ---- - // Hidden focusable proxies announce each hero and drive the 3D highlight. - const a11yRoot = document.getElementById('a11y-heroes'); - heroEntries.forEach((e, i) => { - const b = document.createElement('button'); - b.className = 'a11y-hero'; - const labels = e.hero.powers.map(p => p.label.toLowerCase()).join(', '); - b.setAttribute('aria-label', - `${e.hero.name} — ${e.hero.role}. Superpowers: ${labels}. Click to open Space.`); - b.addEventListener('focus', () => setKeyActive(i)); - b.addEventListener('blur', () => { if (kbActive === i) setKeyActive(-1); }); - b.addEventListener('click', () => window.open(e.hero.url, '_blank', 'noopener')); - a11yRoot.appendChild(b); - }); - let kbActive = -1; - function setKeyActive(i) { kbActive = i; setActive(i); } - - // ---- Resize ---- - function resize() { - const w = stage.clientWidth, h = stage.clientHeight; - renderer.setSize(w, h, false); - camera.aspect = w / h; camera.updateProjectionMatrix(); - } - window.addEventListener('resize', resize); - resize(); - - // ---- Animation loop ---- - const clock = new THREE.Clock(); - let camAngle = 0; - const _proj = new THREE.Vector3(); - - function frame() { - const dt = clock.getDelta(); - const t = clock.elapsedTime * 1000; - - // camera slow orbit (~60s period) unless reduced motion - if (!REDUCED) camAngle = (clock.elapsedTime / 60) * Math.PI * 2; - const orbitR = CAM_RADIUS; - camera.position.x = Math.sin(camAngle) * orbitR; - camera.position.z = Math.cos(camAngle) * orbitR; - camera.position.y = CAM_HEIGHT; - camera.lookAt(0, 1.0, -1.2); - - // hover hit-test (only when pointer is in canvas) - if (pointerInside) { - raycaster.setFromCamera(pointer, camera); - const hits = raycaster.intersectObjects(hitMeshes, false); - setActive(hits.length ? hits[0].object.userData.index : -1); - } - - // per-hero animation - heroEntries.forEach((e, i) => { - const ud = e.figure.userData; - // breathing: torso scale y ±2% over 3s - if (!REDUCED) { - const breathe = 1 + Math.sin(t * 0.00209 + i) * 0.02; - ud.torsoPivot.scale.y = breathe; - } - // hover scale-up to 1.15x over ~200ms (ease toward target) - const target = e.hovered ? 1.15 : 1.0; - const lerpK = REDUCED ? 1 : Math.min(1, dt / 0.2); - e.scale += (target - e.scale) * lerpK; - e.slot.scale.setScalar(e.scale); - - // dais rim pulse (HSL lightness) + hover brighten +50% - const baseI = e.hovered ? 1.5 : 1.0; - const pulse = REDUCED ? 0 : Math.sin(t * 0.0016 + i * 1.3) * 0.25; - e.rimMat.emissiveIntensity = baseI + pulse; - e.rimLight.intensity = (e.hovered ? 2.6 : 1.4) + pulse; - - // dim non-hovered heroes to 50% when one is active - const dim = (activeIndex >= 0 && !e.hovered) ? 0.5 : 1.0; - e.bodyMats.forEach(m => { - m.transparent = dim < 1; - m.opacity += (dim - m.opacity) * (REDUCED ? 1 : Math.min(1, dt * 6)); - }); - - // prop activation on hover - ud.prop.visible = e.hovered; - if (e.hovered && !REDUCED) animateProp(ud.prop, t); - }); - - // NPC idle - animateNPCs(npcs, t, REDUCED); - - // particle motes drift + burst/converge - if (particles) { - const now = performance.now(); - const bursting = now < burstUntil; - for (let i = 0; i < PCOUNT; i++) { - const ix = i * 3; - if (bursting) { - // converge toward target then radiate (second half) - const half = burstUntil - 450; - const k = now < half ? 0.06 : -0.05; - pPos[ix] += (burstTarget.x - pPos[ix]) * k; - pPos[ix + 1] += (burstTarget.y - pPos[ix + 1]) * k; - pPos[ix + 2] += (burstTarget.z - pPos[ix + 2]) * k; - } else { - // ease home + gentle float - pPos[ix] += (pHome[ix] - pPos[ix]) * 0.02; - pPos[ix + 1] += (pHome[ix + 1] - pPos[ix + 1]) * 0.02 + Math.sin(t * 0.0006 + i) * 0.0009; - pPos[ix + 2] += (pHome[ix + 2] - pPos[ix + 2]) * 0.02; - } - } - particles.geometry.attributes.position.needsUpdate = true; - if (!REDUCED) particles.rotation.y = clock.elapsedTime * 0.01; - } - - // place hover panel above active hero's head (screen projection) - if (activeIndex >= 0) { - const e = heroEntries[activeIndex]; - _proj.copy(e.slot.position); _proj.y += 2.6; // ~60cm above head - _proj.project(camera); - const rect = canvas.getBoundingClientRect(); - const sx = (_proj.x * 0.5 + 0.5) * rect.width; - const sy = (-_proj.y * 0.5 + 0.5) * rect.height; - panel.place(sx, sy); - } - - renderer.render(scene, camera); - requestAnimationFrame(frame); - } - - document.getElementById('loading')?.remove(); - requestAnimationFrame(frame); - - // expose for smoke tests - window.__SZL_ROSTER__ = { setActive, heroEntries, HEROES }; -} - -function collectBodyMats(figure) { - const mats = []; - figure.traverse(o => { if (o.isMesh && o.material && o.material.map) mats.push(o.material); }); - return mats; -} - -function animateProp(prop, t) { - if (prop.userData.spin) prop.userData.spin.rotation.z = t * 0.003; - if (prop.userData.orbit) { - prop.userData.orbit.forEach((r, k) => { - const a = (k / 8) * Math.PI * 2 + t * 0.001; - r.position.set(Math.cos(a) * 0.7, 1.0 + Math.sin(t * 0.002 + k) * 0.05, Math.sin(a) * 0.7); - }); - } - if (prop.userData.stream) { - prop.userData.stream.forEach((s, k) => { - s.position.x = 0.5 + ((t * 0.001 + k * 0.2) % 0.6); - s.material.opacity = 0.3 + 0.6 * Math.abs(Math.sin(t * 0.003 + k)); - }); - } -} diff --git a/js/superpower_icons.js b/js/superpower_icons.js deleted file mode 100644 index 0b212400bdf4456c4468268b8a7e1704bc22c849..0000000000000000000000000000000000000000 --- a/js/superpower_icons.js +++ /dev/null @@ -1,105 +0,0 @@ -// superpower_icons.js -// Animated SVG icon set, one per superpower. Each factory returns an -// element (24x24 viewBox) with embedded CSS/SMIL animation. Color is injected. -// Animations respect prefers-reduced-motion via the `reduced` flag (freezes). - -const NS = 'http://www.w3.org/2000/svg'; - -function svg(color, reduced, inner) { - const s = `${inner}`; - const wrap = document.createElement('span'); - wrap.className = 'sp-icon'; - wrap.innerHTML = s; - return wrap; -} - -// Each builder takes (color, reduced) and returns an element. -const ICONS = { - // ---- AMARU ---- - amaru_dualstream: (c, r) => svg(c, r, ` - - - - `), - amaru_memory: (c, r) => { - let dots = ''; - for (let i = 0; i < 7; i++) { const a = (i / 7) * Math.PI * 2; dots += ``; } - return svg(c, r, `${dots}`); - }, - amaru_forward: (c, r) => svg(c, r, ` - - `), - amaru_lineage: (c, r) => svg(c, r, ` - - - `), - // ---- SENTRA ---- - sentra_gates: (c, r) => { - let locks = ''; - for (let i = 0; i < 8; i++) { const x = 3 + (i % 4) * 6; const y = i < 4 ? 7 : 16; - locks += ``; } - return svg(c, r, locks); - }, - sentra_dsse: (c, r) => svg(c, r, ` - - SIG - - `), - sentra_conduction: (c, r) => svg(c, r, ` - `), - sentra_cosign: (c, r) => svg(c, r, ` - - `), - // ---- ROSIE ---- - rosie_ensemble: (c, r) => { - let tally = ''; - for (let i = 0; i < 5; i++) tally += ``; - return svg(c, r, tally); - }, - rosie_routing: (c, r) => svg(c, r, ` - - `), - rosie_step: (c, r) => svg(c, r, ` - `), - rosie_exec: (c, r) => svg(c, r, ` - - - `), - // ---- KILLINCHU ---- - kil_noaa: (c, r) => svg(c, r, ` - - `), - kil_usgs: (c, r) => svg(c, r, ` - `), - kil_mq9: (c, r) => svg(c, r, ` - - `), - kil_phase: (c, r) => svg(c, r, ` - - `), - // ---- A11OY ---- - a11_governance: (c, r) => svg(c, r, ` - - - - `), - a11_router: (c, r) => svg(c, r, ` - `), - a11_formulas: (c, r) => { - let dots = ''; - for (let i = 0; i < 35; i++) { const x = 3 + (i % 7) * 3; const y = 4 + Math.floor(i / 7) * 4; - dots += ``; } - return svg(c, r, `${dots}`); - }, - a11_khipu: (c, r) => svg(c, r, ` - - `), -}; - -export function buildIcon(name, color, reduced) { - const f = ICONS[name]; - if (f) return f(color, reduced); - return svg(color, reduced, ``); -} diff --git a/js/uds_npcs.js b/js/uds_npcs.js deleted file mode 100644 index 7c54b5baa1a25988afa0966983e54378398e6cc8..0000000000000000000000000000000000000000 --- a/js/uds_npcs.js +++ /dev/null @@ -1,64 +0,0 @@ -// uds_npcs.js -// Background UDS NPC silhouettes — same humanoid template, neutral grey, -// "UDS" monogram decal, standing at parade rest. They orbit slowly + idle-sway. -import * as THREE from 'three'; -import { makeNPCTexture } from './canvas_decals.js'; - -let sharedTexture = null; - -function npcMaterials() { - if (!sharedTexture) sharedTexture = makeNPCTexture(); - return { - body: new THREE.MeshStandardMaterial({ map: sharedTexture, roughness: 0.85, metalness: 0.05, flatShading: true }), - limb: new THREE.MeshStandardMaterial({ color: 0x2c3138, roughness: 0.9, flatShading: true }), - head: new THREE.MeshStandardMaterial({ color: 0x3c4249, roughness: 0.9, flatShading: true }), - }; -} - -function buildNPC() { - const g = new THREE.Group(); - const m = npcMaterials(); - const torso = new THREE.Mesh(new THREE.CapsuleGeometry(0.3, 0.6, 4, 8), m.body); - torso.position.y = 1.05; g.add(torso); - const head = new THREE.Mesh(new THREE.SphereGeometry(0.22, 12, 10), m.head); - head.position.y = 1.62; g.add(head); - for (const side of [-1, 1]) { - // arms at parade rest — hands clasped front, slight inward angle - const arm = new THREE.Mesh(new THREE.CapsuleGeometry(0.08, 0.5, 4, 6), m.limb); - arm.position.set(side * 0.36, 0.92, 0.08); - arm.rotation.z = side * 0.12; arm.rotation.x = -0.25; - g.add(arm); - const leg = new THREE.Mesh(new THREE.CapsuleGeometry(0.11, 0.6, 4, 6), m.limb); - leg.position.set(side * 0.15, 0.5, 0); - g.add(leg); - } - return g; -} - -// Create N NPCs arranged in a back arc. Returns { group, npcs[] } for animation. -export function buildUDSNPCs(count = 4) { - const group = new THREE.Group(); - const npcs = []; - for (let i = 0; i < count; i++) { - const npc = buildNPC(); - const a = -0.9 + (i / Math.max(1, count - 1)) * 1.8; // spread across back arc - const radius = 6.5; - npc.position.set(Math.sin(a) * radius, 0, -radius * 0.55 + Math.cos(a) * 0.4); - npc.scale.setScalar(0.85); - npc.rotation.y = -a * 0.5; // face roughly toward center/camera - npc.userData = { baseAngle: a, radius, phase: Math.random() * Math.PI * 2, baseX: npc.position.x }; - group.add(npc); npcs.push(npc); - } - return { group, npcs }; -} - -// Slow orbit + idle sway. orbit is subtle so NPCs stay readable in-frame. -export function animateNPCs(npcs, t, reduced) { - if (reduced) return; - for (const npc of npcs) { - const u = npc.userData; - npc.position.y = Math.sin(t * 0.0009 + u.phase) * 0.04; // idle bob - npc.rotation.z = Math.sin(t * 0.0011 + u.phase) * 0.02; // idle sway - npc.position.x = u.baseX + Math.sin(t * 0.00012 + u.phase) * 0.6; // slow lateral orbit - } -} diff --git a/roster.png b/roster.png deleted file mode 100644 index 41a448057431888b15a509d4716e24c18fada740..0000000000000000000000000000000000000000 --- a/roster.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3008a91b4912c70407360b5ba582834057eda3309b7cb1e3438965727314e937 -size 753585