Skip to content

About

Documentation for the OnlyWorlds standard and tools.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

OnlyWorlds docs

The source of onlyworlds.github.io: the OnlyWorlds schema, API, SDKs and AI tools. Built with Starlight and deployed to GitHub Pages by .github/workflows/pages.yml.

The Jekyll site this replaced is kept whole on the jekyll branch and the jekyll-final tag.

Work on it

npm ci
npm run build     # gen_sdk_ref, gen_errors, astro build, then scripts/postbuild.mjs
npm run verify    # the checks package.json lists (figures, workflows, URLs, words, the snapshots, the LLM guide), offline, on dist/ and the sources
node scripts/serve.mjs   # dist/ on http://localhost:4321/, resolved the way GitHub Pages resolves it

Pages are Markdown in src/content/docs/, at the URL they are served from. The sidebar (in astro.config.mjs) is independent of the folders.

Deploys. pages.yml runs on every push to main and whenever schema-dist publishes (its publish step runs gh workflow run pages.yml -R OnlyWorlds/onlyworlds.github.io). A 4-hourly schedule is only a fallback: GitHub runs scheduled workflows late or not at all. Nothing uploads unless npm run verify passes. Push and manual deploys are tagged docs-live-<date>-<run>; to roll back, run the workflow on an earlier tag. An outside check watches the live site and notices if the workflow is disabled (GitHub does that after 60 days without activity) or the site falls behind schema-dist.

Run npm run verify before you push: a workflow file that doesn't parse never runs, and GitHub shows no failed check, only none.

Keeping it true

Docs follow what ships, the same hour, and a weekly sweep catches the rest: node scripts/sweep.mjs, then the reading list and the terms in SWEEP.md.

Old URLs are part of the contract

The API's error responses link to /api/errors#<code>, the LLM guide lives at /assets/ow_llm_guide.txt, and tools, READMEs and AI chats link to old paths. contract/urls.tsv lists every one, with where it is linked from:

  • load-bearing rows must answer 200 with the real page, on this host. Never a redirect stub: agents read the stub, not its target.
  • floor rows are the error codes keel links to; each must be an id on /api/errors/.
  • page rows are old pages nothing outside links to; a stub redirect is enough if one moves.

Two checks read that file: npm run verify on every build (CI and the deploy), and the outside check on the live site. A page keeps its path; to move one that the contract lists, change the contract first.

build.format: 'file' writes page.html, which Pages serves as both /page and /page.html (the old site's two forms). scripts/postbuild.mjs moves section pages (<dir>/index.md) back to <dir>/index.html, so /docs/x keeps its same-host 301 to /docs/x/. A directory that holds pages but none of its own (/docs, /api, /docs/development/api) gets a copy of the page named for it in DIR_INDEX, and a new one fails the build until it is named. Every other page is a file, so /page/ answers the 404 page, which in a browser sends it on to /page once.

Element pages

The field tables on the 22 element pages are generated by scripts/gen_elements.py from schema-dist, through schema-dist's own walk (imported from the checkout after it is verified against its MANIFEST.json, never copied). Hand-written prose stays above the marker line; everything below it is rewritten. The same run writes contract/folder-example.json, schema-dist's example world folder (example/hyperion) as the checkout holds it, with the checkout's serial, which the figure on World folders draws: one run, one checkout, so the figure and the tables are always one serial. Every deploy runs the generator on a clone of the newest v*-dist.* tag, so the site follows the schema without a commit here. Run it locally on a clone of a tag, never a working tree that may sit serials behind.

python scripts/gen_elements.py --dist ../schema-dist          # rewrite
python scripts/gen_elements.py --dist ../schema-dist --check  # exit 1 if a page is behind

Other generated parts

  • The errors page's summary table and the contract's floor rows come from keel's own list of error codes (Error.x-ow-error-codes in its OpenAPI), vendored as contract/error-codes.json. scripts/gen_errors.mjs runs in every build. It fails when a public code has no ### <code> section, when a section isn't a public code, or when the Upload host errors table disagrees with the host rows. The sections themselves are hand-written. --refresh re-reads the live list; --live compares the snapshot with it (CI and the deploy warn on a difference).
  • The public page palettes (the figure on Public worlds) come from keel's palette table (PALETTES and HOUSE_PALETTE in worlds/public_page.py), vendored as contract/palettes.json in the table's order, with the keel commit it was read at. keel is private, so the build and CI read only the snapshot. node scripts/gen_palettes.mjs compares the snapshot with keel's published branch (it fetches, then reads origin/main, never the working tree, from ../keel or --keel PATH): exit 0 when it matches, 1 when stale, 2 (BLIND) when keel cannot be read. --refresh rewrites the snapshot from it.
  • The TypeScript page's reference comes from the pinned @onlyworlds/sdk (a dev dependency): scripts/gen_sdk_ref.mjs reads its types with the TypeScript compiler. Bump the pin after an SDK release to move the reference.

Figures

A figure is an Astro component in src/components/figures/, placed in a page's MDX (<CategoryLinks /> on the schema page, <CategoryFields /> above it: the 22 categories by family, each with its own fields split into links and values, from the SDK's FIELD_SCHEMA and families through fields.mjs, held by verify-figures.mjs to the element pages' field tables, <FourNouns /> on Lenses, <ErrorFamilies /> on the errors page: the public error codes by family and status, from contract/error-codes.json through errors.mjs, held by verify-figures.mjs to the summary table on the same page and its Retry-After marks to the API's own document, <PagePalettes /> on Public worlds: the five palettes a public world page can wear, each a small page in its own colours with its contrast ratios, from contract/palettes.json through palettes.mjs, which computes every ratio and fails the build if the lead's claim does not hold, held by verify-figures.mjs to the snapshot with a contrast formula of its own, and the page's Palette row with it, <FolderExample /> on World folders: Hyperion, schema-dist's example world folder, its tree with each category folder's file count and three of its elements' names and ids becoming their file names, from contract/folder-example.json through folders.mjs, which derives every file name by the page's naming rule and fails the build if one of the example's files breaks it, held by verify-figures.mjs to the snapshot, and at deploy to the schema-dist clone itself, with a second implementation of the rule that reads its numbers from the page's own paragraph, <ApiCallers /> on the API overview: every operation of the API by route family and by the credential each accepts (no key, a key alone, a key and its PIN, an account token), from the security the API's own document lists, vendored as contract/callers.json by scripts/gen_callers.mjs (--refresh; with no flag it compares the snapshot with the live document) and drawn through callers.mjs, held by verify-figures.mjs to the snapshot with a count of its own, its keyless reads to the public worlds page's table, and the snapshot compared with the live document, printed STALE, never failed, <SigninSteps /> on Sign in with OnlyWorlds: the four steps as hops between the tool, the person's browser and onlyworlds.com, with the authorize page's parameters, the token route's fields and answer and the code's lifetime from the API's own document, vendored as contract/signin.json by scripts/gen_signin.mjs (--refresh; with no flag it compares the snapshot with the live document, and the document's words with keel's code where a checkout is) and drawn through signin.mjs, held by verify-figures.mjs to the snapshot and to the page's own parameter and field tables and examples, and the snapshot compared with the live document, printed STALE, never failed, <TimeLadder /> on Worlds: how a world counts time, its steps as counts of the basic unit drawn to scale and its line from the earliest tracked point to the latest with its now and one element's date, the field names from the standard (schema-dist's newest tag: schema.json and the example folder's world.json) and the API's own document, the values from the demo world Moppetopia read with no key, vendored as contract/time.json by scripts/gen_time.mjs (--refresh; with no flag it compares the snapshot with those sources) and drawn through time.mjs, held by verify-figures.mjs to the snapshot with the two spellings of now derived on its own, its words to the page's Timeline table, now's spellings to the folders page and the world's values to the worked example, and the snapshot compared with the live sources, printed STALE, never failed, <PublicView /> on Public worlds: what a stranger reads of an open world, the three kinds of element the public reader removes with their marks, what is left, the three ways in (the keyless reads, the public page, the graph), what is never shown and the one 404 for a world that answers nothing, the removals, the /w/ routes, the graph's leave-outs and the two 404 pages from keel's public reader, vendored as contract/public.json by scripts/gen_public.mjs (--refresh; with no flag it compares the snapshot with keel's code where a checkout is, BLIND when none), the keyless routes from contract/callers.json, drawn through public.mjs, held by verify-figures.mjs to both snapshots with code of its own and every phrase it says to the page's source, <WriteBody /> on Fields: what a write body may carry, each key stored, tolerated and ignored, or rejected with 422, with the caps, the reasons and the codes, from the 22 categories' write schemas in the API's own document, vendored as contract/write.json by scripts/gen_write.mjs (--refresh; with no flag it compares the snapshot with the live document) and drawn through write.mjs, held by verify-figures.mjs to the snapshot sorted by a rule of its own, each category's own fields to its element page, the page's own sentences and every phrase it says to the page's source, and the snapshot compared with the live document, printed STALE, never failed, <DraughtRead /> on the draught page: one Character's context in one read, the sections served by default round her (the three the budget never cuts marked), the three served only when named and the lenses beside them, and the policy's query parameters with their values and defaults, from the route GET /api/v2/character/{id}/context in the API's own document, vendored as contract/draught.json by scripts/gen_draught.mjs (--refresh; with no flag it compares the snapshot with the live document) and drawn through draught.mjs, held by verify-figures.mjs to the snapshot by rules of its own, to the page's policy and sections tables and its sentences, every phrase it says to the page's source, and the snapshot compared with the live document, printed STALE, never failed, <ProposalLife /> on Proposed changes: a proposal's life, the propose with its expiry, the undecided states (open, lapsed) and the accept, decline and withdraw on them, each with its route, who may call it, its answer, its refusals and the state it leaves, then what the switch makes of an AI seat's writes and new elements with the review's decisions, and the queue's states and kinds, from the proposal routes, the queue, the Proposal schema, the queue's new_element row and the operations answering 202 in the API's own document, vendored as contract/proposals.json by scripts/gen_proposals.mjs (--refresh; with no flag it compares the snapshot with the live document) and drawn through proposals.mjs, held by verify-figures.mjs to the snapshot by rules of its own, to the page's own sentences, every phrase it says to the page's source, and the snapshot compared with the live document, printed STALE, never failed, <RolesView /> on Members and sharing: one invented world of 36 elements read by the owner, a co-builder, a contributor, a guest and the public, each with what it sees and changes, its words read at build time from the page's own roles table, the Hidden page's public row and the public worlds page's keyless writes line through roles.mjs, the dots a shape only, held by verify-figures.mjs word for word to the table the built page prints, the role names to the API document's /me role values, each count to its own dots and the shape to each reader's rule). Each one keeps to five rules:

  • Its data comes from a source at build time, never drawn by hand. The link map reads the SDK's FIELD_SCHEMA (links.mjs); words that no source holds sit in one module (four-nouns.mjs) that the component and the text version both read.
  • It has a text version. The page carries it (a list under the figure, or the figure is itself HTML text), and scripts/postbuild.mjs writes it into the page's Markdown twin in place of the component's tag (FIGURE_TEXT; a tag with no text there fails the build).
  • It takes the docs' theme, through Starlight's colour variables, so it follows the light and dark switch.
  • Its height fits its width, with no inner scroll: it lays out by its own width (a container query), from the phone to the content column.
  • A check holds it to its source. scripts/verify-figures.mjs, first in npm run verify, reads the built pages: the link map against the element pages (generated from schema-dist, a second source), and the address the four nouns show parsed by the SDK's parseOwLink. A new figure adds its check there, watched failing on a planted error before it is trusted.

Contributing

Issues are welcome: a bug, a wrong word, a thing you could not do. Pull requests are read; a small fix is usually taken as is, and a change to what a page does is better opened as an issue first, since it may already be built or ruled out. A reply can take a few days. A vulnerability goes privately, never in an issue: SECURITY.md. What we ask at the door, and what you can expect: the code of conduct. The field descriptions on the element pages are the schema's own text, so raise a change to one on the standard's repository rather than here; the next deploy picks it up.

Licence

The code is MIT (LICENSE). The documentation's text is CC BY 4.0 (LICENSE-CONTENT): share and adapt it with credit.

Maintained by Kael, an AI agent working for Titus. Issues and pull requests are read and answered here.

About

Documentation for the OnlyWorlds standard and tools.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages