# AienOS website (aienos.com)

> Static site for aienos.com. One Rust program, `crates/site-builder`, renders every page from Maud templates, copies hand-written files from `public/`, then rewrites every head and writes the machine surface. GitHub Pages serves the output; `.github/workflows/pages.yml` builds and deploys it on every push to `main`.

Shared rules: read https://www.aienos.com/agents/RULES.md first. This file adds what is specific to this repository; where the two differ, this file wins here. The rules live in `public/agents/RULES.md`; every public repository is listed at https://www.aienos.com/agents/ (`components/agents.rs`, data refreshed by `site-builder agents`). The catalog follows every GitHub API page, includes archived repositories as read-only references, and links the actual `AGENTS.md` or `CLAUDE.md` when present. Missing instructions are marked explicitly. AienOS is the whole system at its current `aien-dev/aienix` URL until renamed; Aienux is the separate kernel.

## Scope

- Applies to the whole repository.
- Source of truth is `crates/site-builder/src` plus `public/`. The root `index.html` and `dist/` are not the live site.
- `dist/` is generated output. Never edit it by hand; rebuild it.
- `crates/hive-feed` is opt-in Rust website telemetry tooling. It does not run during static builds. `scripts/hive/` holds its service and exact-route edge templates; README documents installation and the publication boundary.

## Installation

```bash
git clone https://github.com/aien-dev/aienos.com.git
cd aienos.com
rustup toolchain install stable
cargo build --release --manifest-path crates/site-builder/Cargo.toml
```

There is no Node build, no `package.json`, and no package manager. The only tool needed is a Rust toolchain; the site depends on `maud`, `serde` and `serde_json`.

## Configuration

- `facts.json` at the repository root is read by every build. Refresh it from the public GitHub record when the fact sheet must move:

```bash
GH_TOKEN="$(gh auth token)" cargo run --release --manifest-path crates/site-builder/Cargo.toml -- facts facts.json
```

- `public/data/project-progress.json` feeds `/progress/`. Recollect it with:

```bash
GH_TOKEN="$(gh auth token)" cargo run --release --manifest-path crates/site-builder/Cargo.toml -- progress public/data/project-progress.json
```

- `CNAME` holds the custom domain. `.github/workflows/pages.yml` is the deployment configuration.
- Pages build uses SHA-pinned external actions with read-only repository permission; only deploy holds Pages/OIDC write permissions. It runs the committed Hive skeleton digest test before uploading. The remaining suite runs on the Spark.
- `crates/site-builder/data/research_status.json` is the canonical research ladder and experiment verdicts.
- `/dash/` reads `public/data/accounts.tsv` and `routing.tsv`, which the pages workflow lays in from the `data/now` branch. The Spark writes them with `~/.local/bin/dash-snapshot` (called by `now-publish`). Accounts are numbered per provider; never publish an email, account id, org or project name. `components::dash::word` strips `@` and markup as a second guard.
- `/now/`, `/now.json`, `/now/feed.xml`, and `/data/now.tsv` use one line-preserving public projection of the private ledger. The `site-builder ledger-project INPUT` command prints it only after checking all rows; `ledger-check FILE` refuses a raw or malformed public file. Pages checks the laid-in file before building, and the builder checks it again before copying assets. The cron publisher must project and check before staging `data/now`, otherwise a credential can leak in Git history even if Pages refuses the build. A refused input keeps the last published file and logs the reason without printing private text; never treat that as a fresh ledger update.
- The page registry in `crates/site-builder/src/seo.rs` (`seo::PAGES`) drives the sitemap, `llms.txt`, `sitemap.md`, the feeds and the JSON-LD. Add every new page there or the build fails.

## Usage

```bash
# Full test suite
cargo test --workspace

# Build the site into dist/ (this also runs the integrity verifier)
cargo run --release --manifest-path crates/site-builder/Cargo.toml -- build dist

# Re-check an existing dist/ without rebuilding
cargo run --release --manifest-path crates/site-builder/Cargo.toml -- verify dist

# Preview the generated output locally
python3 -m http.server 8080 --directory dist
```

Open `http://127.0.0.1:8080/` after the preview server starts. GitHub Pages serves directories through `index.html`, so local previews match the live routes.

## Conventions

- Most generated pages are Maud markup in `crates/site-builder/src/components/`. Hand-written pages live under `public/<route>/index.html` and are copied verbatim. `/hive/` and `/alpha/` are Omega-generated exceptions: their structure lives under `om/` and their Rust components only embed the artifacts.
- `/alpha/` is generated by `om/alpha-page/page.om`; `client.om` emits its copy/motion client. Regenerate on arm64 with `OMEGA_ACCEPT_CHANGE=1 sh om/alpha-page/check.sh`, then run it again without the override. It uses the unchanged Hive compiler pin, checks repeatable output and refuses empty capture input. Commit the HTML/JS and hash sidecars together. The terminal capture (`aien-dev/sovereign-intelligence` `evidence/<tag>/capture/wizard-plan.{txt,svg}`) and downloadable `public/alpha/wizard.om` (the release asset `aienos.om`, checked against its signed `SHA256SUMS`) must come from the named release, never a mockup. Current release: `alpha-20261026.2` (Qwen3.6-35B-A3B-FP8 only; the 27B is not offered). The source is escaped into the page at build time, not fetched by the browser. A local site build needs the CI ledger files from `data/now` in `public/data` (see `pages.yml`); restore them afterwards.
- Alpha's black-hole illustration uses palette tokens only and compositor-only motion. Motion starts off, requires the native button, stops when the page is hidden and is disabled by `prefers-reduced-motion`. The metaphor removes user-space dependencies from the inference path, never the user's packages, GPU or NVIDIA kernel driver. The site's existing Rust builder and shell generation orchestrator remain explicit host dependencies; the page, browser client and wizard source are Omega.
- `/support/`, its shared home/contact/Alpha invitation and its CSS are emitted by `om/support-page/support.om`; the Rust component only embeds the artifacts. Regenerate with `OMEGA_ACCEPT_CHANGE=1 sh om/support-page/check.sh`, then run without the override; commit sources, outputs and hashes together. The header Support link is inserted in the shared document pass. X Money is currently US-only, requires an eligible X account, and has no public payment checkout link: the plain button opens `https://x.com/mdrakestapleton`, with Money, Send Money and recipient-search instructions. Never add a payment widget or external script.
- About the engineer (`/engineer/`, Drake's own story, philosophy, works and glossary) is data: `public/data/engineer.json` holds every page (path, the old drakestapleton.com paths that redirect to it, title, description, body). `components::engineer` renders it, fills `<!--engineer:live-->` and `<!--engineer:verdict-->` from `facts.json`, and `engineer::verify` fails the build on an unwritten page, an unfilled placeholder, an outside resource or a broken `/engineer/` link. drakestapleton.com was merged here on 2026-10-26; its repository (`aien-spark/drakestapleton.com`) now only serves redirect stubs. Edit the JSON, not the old site. Styles are `public/assets/engineer.css`, scoped under `.engineer`; each page is listed in `seo::PAGES` under `Section::Engineer`.
- Every page gets its head rewritten by `seo::enrich`: canonical on `https://www.aienos.com`, Open Graph and Twitter cards, hreflang, JSON-LD, `rel="alternate" type="text/markdown"`, `rel="describedby"` to `/llms.txt`, and robots snippet directives. Do not duplicate those tags in a component.
- Every page also gets a Markdown mirror at the same path with `.md` (`/` becomes `/index.md`), with YAML frontmatter and a `## Sitemap` section. The mirror is generated from the final HTML; do not hand-write one.
- Voice: Drake writes this site alone, in first person singular (I, me, my). Never a plural first-person word (the list is the regex in `voice::plural`). Where agents did the work, say so ("my agents", "I build this with AI agents"); never credit Drake with an agent's work, and never imply a team. Shared human claims use "everyone" or "people". `components::voice::verify_singular_voice` fails the build on any plural first-person word in rendered `dist` text (`.html` visible text, `.md`, `.txt`). Not counted: markup, scripts, styles, link targets, path/identifier parts (`how-we-did-it`), `50 us`, and on the ledger pages (`voice::LEDGER_PAGES`) text found verbatim in `data/now.tsv`, which is a dated record. Quotes of other people go in `voice::ALLOW` as (file, exact phrase); keep it small. Repository descriptions render on /agents/, so fix the GitHub description, not just `agent-repos.json`.
- Copy rules: no em dashes, no en dashes, no outside fonts or unconditional third-party scripts/trackers. The sole tracking exception is X pixel `rfrlz`, loaded from the first-party `public/js/allen-intro.js` only after explicit consent to the Allen introduction. Never embed `uwt.js` as a script source in HTML, inline its bootstrap, or preconnect/prefetch X hosts. The verifier rejects outside script sources on every emitted HTML page; `node scripts/test-allen-intro.cjs` exercises refusal, consent, reload and revocation.
- Keep one source for machine-readable state. `status.json`, the status section, and the current-state lines in `llms.txt` all read `components::status::layer_states()`.
- Tests live beside the code in `#[cfg(test)]` modules. Add a test when a rule can regress silently.
- The final shared `components::allen_intro::enrich` pass in `seo::enrich` adds one local consent loader, a native modal dialog and a privacy link to generated, hand-written and translated pages. `404.html` gets the same pass. `/privacy/` stays readable without an automatic modal and provides review and refusal controls. No and Escape persist refusal, with no automatic re-prompt. Stored Yes permits one initialization per document; refusal of an active pixel reloads without it. Local storage holds the choice; a session-storage refusal and `#allen-intro-no` protect reload if persistent storage fails. Storage clearing or another browser resets the choice, not consent.
- Every page shows how to reach Drake: the header nav ends with the `aien-nav-reach` group (the `/contact/` page and a plain "Follow me on X" link to `https://x.com/mdrakestapleton` with an inline SVG mark, no widget or script), and the footer carries the `aien-reach-foot` line (X, `drake@aienos.com`, `/allen/`, GitHub aien-dev). Generated pages get both from `components::navbar` and `components::footer`; `components::contact::enrich` in `seo::enrich` adds them to hand-written and `/zh-CN/` pages (Chinese labels there), and `contact::verify` fails the build if any HTML page in `dist` lacks either.
- CSP coordination: no inline allen-intro scripts. An edge CSP for a page that enables this feature needs `script-src 'self' https://static.ads-twitter.com` and `connect-src` / `img-src` permissions for `https://analytics.twitter.com`, `https://analytics.x.com` and `https://t.co` (in addition to its first-party sources). These are the hosts named by the official loader inspected on 2026-10-26, not a wildcard allowance. CSP permissions are static, not conditional consent: `allen-intro.js` enforces consent before any X load. Do not loosen a no-JS edge board CSP; explicitly exclude that board from enrichment if introduced. `allen-intro.js` is outside the separate Hive/Turing Omega-generation change, by agreement with that lane.
- Before publishing a consent change, build `dist`, run `node scripts/test-allen-intro.cjs dist/js/allen-intro.js`, and verify in a real browser with cache disabled and requests observed before navigation: unknown/No/Escape and reload produce no X requests and no `window.twq`; saying hello requests the exact loader and configures `rfrlz` once. Test at mobile width 390, verify modal focus and keyboard dismissal, and run a guard-bypass negative control. Intercepted X requests prove gating, not X ingestion. The public project board and storage of check-ins are deferred pending Drake's storage decision; never collect entries under the pixel consent.
- Only after consent, retain the landing URL's `twclid` under browser-local `aien-allen-intro-twclid`; remove it on refusal. Drake chose pixel-only operation; server Conversion API work is deferred until the introduction flow has a backend. The single `eventIds` constant in `allen-intro.js` holds `pageVisit` and `introducedToAllen`, empty until Drake supplies the real IDs. Empty means no custom event. Configured IDs send one visit per consenting document and one introduced-to-Allen event per explicit introduction document, each with its own `crypto.randomUUID()` `conversion_id`. A future backend must forward that exact ID for deduplication, read `X_PIXEL_TOKEN` only from its private environment, and never expose the token in static output.
- Hive's shell and browser client are generated by seeded Omega, never written in Rust or hand-edited in `public/js/`. `om/hive-page/check.sh` composes `contract.om`, `hive.om` and `hive-js.om`: stdout emits `main.html`, fd 3 emits `hive.js`. The shared contract owns ids, poll/freshness bounds and the board route; append entries rather than renumbering. `hive.om` owns the section order (`meta`, eight pipe-separated fields), shell controls, aria wiring and bounded panels. `om/hive-render/render.om` owns feed-derived rows, native details, manifests and messages. The browser only DOMParser-parses same-origin `/hive/board/` and morphs keyed nodes in place, preserving native open state, selection, focus, search and scroll. It never renders JSON or constructs feed markup. `turing-look.js` has its separate Omega generator. Commit sources, artifacts and hashes together; run the generation gate twice, site-builder tests and `scripts/test-hive-cosmic.py`. Neither served JS file is hand-edited.
- `.github/workflows/generated-hive.yml` runs only the skeleton-hash and generated-script-hash tests on x86_64 for relevant pull requests and main pushes. It does not run `omc`, regenerate artifacts or change the full-suite-on-Spark policy.
- Hive keeps its Omega-generated information board. The decorative scene is Allen's two black holes in the masthead, and at Drake's explicit request the galaxy (`public/assets/hive-universe.svg`) is one fixed, borderless layer behind the whole page (`.hive::before`), with sections as 86% `--bg-surface` glass and an edgeless elliptical scrim behind the masthead prose, set in the presentation block at the end of `public/assets/hive.css`. The scene is never a source of positions, topology or progress. Real observations supply the freshness strip, mission tree, compact agent rows, per-agent manifests and message feed. The missions and manifest panels remain bounded scroll bodies; the manifest is sticky beside missions and stacks below 900px. Branches use native `<details>` with stable ids; search reveals matching paths, and clearing it restores the prior open states. Selected cards move from the hidden single-artifact manifest store to the visible panel. Task, activity and lifecycle data must come from real observations. Preserve partial coverage, unknown states, message-time model identity, keyboard focus and reduced-motion support.
- The page says what it is. The masthead and `hive-omega` band state that the page is written in Omega and glitches are expected while the language is being finished. The shell is `om/hive-page/hive.om`; live board structure is `om/hive-render/render.om`. The no-script link opens `/hive/board/`. `scripts/test-hive-cosmic.py` keeps the visible provenance statement.
- Hive freshness has a seeded WebAssembly backend: `om/hive-page/fresh.om` takes the current/effective source clock, generated timestamp, previous timestamp, stale threshold and fetch status; the threshold remains a caller input, not a duplicated policy constant. `freshness-js.om` emits the loader and explicit JavaScript fallback (`window.hiveFresh`); `data-fresh-engine="wasm|js"` and `data-fresh-state="0|1|2|3"` expose which decision ran. States are fresh, source stale (strictly past the threshold), timestamp moved backwards, and fetch aborted; backwards retains priority over abort. Clock-trust gating remains outside this scalar decision. `check.sh` compiles it through `omc ir` and the vendored, hash-pinned `irwasm` to `public/wasm/hive-fresh.wasm`; provenance lives in `irwasm.provenance`. The site omc pin stays unchanged. The existing generated-script hash test also checks the wasm on x86_64 without executing either arm64 tool. `sh om/hive-page/gate-fresh.sh` uses real AArch64 drivers and Node solely as a read-only wasm oracle, never a build dependency.
- The scene is Allen's law, and the `.om` owns every number of it. `native/kernel/ui/night.c` (`orbit_angle`, `ck_night_at`) and `chirp.c` in the `aienos-allen-portable-build` tree are the source: separation as t^(1/4), angle as t^(5/8), t the time left, with the wide orbit at 270 units and one turn per 5200 ms, the shadows grown in from 2600 and 4000 ms, the merger at 12000 ms with a shadow from 323/256 to 2 of a single one and a glow of 362/256, the last hole gone at 15200 ms and the ripple out to 15600 ms. That law is real (section 4 of `docs/ALLEN_SKY_SCIENCE.md`); the ripple across the sky and the ringing of the last hole are illustration, not evidence, and the page says so. `om/hive-page/hive.om` samples it with integer and `f64` arithmetic and emits the markup, the keyframes and the wiring into `main.html`; `public/assets/hive.css` only places the stage and paints the discs, and animates nothing. Never hand write a sample, a keyframe or a duration in the stylesheet: a change to the sequence is an edit to the `.om` and then `sh om/hive-page/check.sh`.
- The sky is a stable layer. `.hive::before` is one `position: fixed; inset: 0` layer the size of the viewport with `transform: translateZ(0)` and `will-change: transform`, sized `cover`, so it has no edge and never scrolls or re-rasterises. Never put a sky or scene layer on a negative z-index under `isolation: isolate`: that made Chromium rebuild the layer during scroll and the background flickered badly (reported 2026-10-25). The sky is at z-index 0 and every child of `.hive` at 1; inside the masthead the holes are at 0, the edgeless elliptical scrim at 1 and the prose at 2. Because the fixed sky paints over static flow, hive.css lifts `.aien-footer` and the non-sticky (below 1100px) `.aien-header`. Prose outside a section or the masthead scrim (`.hive-jumps`, `.hive-closing`) sits on 86% `--bg-surface` glass. `scripts/test-hive-cosmic.py` enforces these rules.
- The sequence is compositor-only (`transform` and `opacity`) and attaches animations only inside `prefers-reduced-motion:no-preference` while the native `#hive-motion` checkbox is checked. CSS `:has()` owns the toggle; no browser motion code or stored preference remains. The checkbox starts off. Reduced-motion or an unchecked control yields the static pair, no merged hole/ripple and no animations. `scripts/test-hive-cosmic.py` pins that gate and frame.
- Hive surfaces use shared palette tokens, never a bespoke near-black or local hex palette. Animate only transform and opacity, never filter or box-shadow. Clamp feed-rewritten text lines and reserve the activity line's two lines so ticks do not resize rows under the pointer. The disclosure chevron's transform is the only transition; unchecked motion or reduced-motion removes it. Prose stays on the existing token scrim and glass, and the black holes remain clipped to the masthead away from the information board; do not weaken the tested scrim or contrast contract.
- Hive text passes a whitelist and privacy screening before publication, including whitespace-separated credential CLI flags such as `--password value`. Never serialize raw sessions, system/task prompts, tool payloads, hidden reasoning, credentials or control metadata. The edge Omega renderer escapes every feed string; only its complete same-origin HTML is parsed by the client, never JSON-to-markup, third-party markup or payload HTML.
- Hive edge rendering is owned by `om/hive-render/render.om`, compiled with the same pinned `om/hive-page/omc`. `check.sh` exercises deterministic compilation, independent escaping/HTML oracles, schema refusals and bounded trees. The edge receiver canonicalizes JSON before invoking it, publishes `board.html` only on successful nonempty output, and logs while keeping the last board on a render failure. The minimal Rust process/rename glue is unfinished migration to Omega's fork/dupfd/execprog/waitpid host words (introduced in omega-mv PR #678). `scripts/hive/DEPLOY-board.md` owns the authorization-gated installation and rollback. `/hive/board/` is a no-JavaScript, no-tracking document with strict CSP, native details, fixed source-relative durations and a 15-second meta refresh. Never add payload markup or pixel enrichment to that route.

## Safety and approvals

- Ask before changing the canonical host, the page registry shape, or a published claim that carries a receipt.
- Never commit tokens, API keys, or `.env` files. `GH_TOKEN` is read from the environment and is never written into the site.
- Never publish `dist/`, `.crumb.local`, or private evidence. `.gitignore` and the copy step already exclude local coordination files.
- Do not run destructive git commands or rewrite published history. Work on a branch, run the full test suite and `build dist`, then merge through a pull request.

## Further reading

- `README.md`: the human-facing build and deployment guide.
- `crates/site-builder/src/seo.rs`: the page registry, head pass, sitemap, llms files and machine surface.
- `om/hive-page/`: Omega sources, generated Hive skeleton and script hashes, `check.sh`, and the pinned `omc.sha256`.
- `https://www.aienos.com/llms.txt`: the site as AI readers see it.
- `https://www.aienos.com/sitemap.md`: every page, grouped and described.
