Merge pull request 'Proposals page for human reviewers' (#7) from weksa/proposals-page into main

This commit is contained in:
Weksa 2026-11-06 19:25:04 +00:00
commit c86ea69853
4 changed files with 224 additions and 0 deletions

1
tools/proposals-page/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
out/

View file

@ -0,0 +1,9 @@
# Proposals page
A static page for humans who feed Weksa ideas, so they need not review forge pull requests.
- `proposals.json`: the content, one entry per proposal (plain-language summary, evidence vs invention, stance, open questions). Hand-maintained; update it when a PR changes or is ruled on.
- `generate.py`: `python3 tools/proposals-page/generate.py [in.json] [out/index.html]`. Standard library only; output has no scripts.
- Published copy: `/srv/minds-web/weksa/proposals-<short-sha>/` on minds.gamecult.org.
Only public material belongs in `proposals.json`. The page is what the JSON says; nothing is fetched.

View file

@ -0,0 +1,63 @@
#!/usr/bin/env python3
"""Render proposals.json into one static HTML page.
usage: generate.py [proposals.json] [out/index.html]
Standard library only. The page has no scripts, no network calls and no data
beyond what proposals.json holds, so what is in the JSON is what gets published.
"""
import json
import pathlib
import sys
from html import escape as e
here = pathlib.Path(__file__).parent
src = pathlib.Path(sys.argv[1]) if len(sys.argv) > 1 else here / "proposals.json"
out = pathlib.Path(sys.argv[2]) if len(sys.argv) > 2 else here / "out" / "index.html"
data = json.loads(src.read_text(encoding="utf-8"))
CSS = """body{font:16px/1.55 system-ui,sans-serif;max-width:46rem;margin:2rem auto;padding:0 1rem;color:#1b1b1b;background:#fafafa}
h1{margin-bottom:.2rem}h2{margin:0 0 .3rem}.meta{color:#555;font-size:.9rem}
article{border:1px solid #bbb;border-radius:6px;padding:1rem 1.2rem;margin:1.5rem 0;background:#fff}
h3{margin:1rem 0 .2rem;font-size:1rem;text-transform:uppercase;letter-spacing:.04em;color:#333}
.ev h3{color:#0a6b4e}.inv h3{color:#a04a00}.forks li{margin:.4rem 0}
.stance{background:#f1f1f1;padding:.5rem .8rem;border-radius:4px}
nav a{margin-right:1rem}code{background:#eee;padding:0 .2rem}"""
def ul(items):
return "<ul>" + "".join(f"<li>{e(i)}</li>" for i in items) + "</ul>"
def forks(p):
if not p["forks"]:
return ""
items = "".join(f"<li>{e(f)}</li>" for f in p["forks"])
return f'<div class="forks"><h3>Questions for you (one sentence each, in the project room)</h3><ol>{items}</ol></div>'
def card(p):
ref = f"{p['repo']} #{p['pr']}" if p["pr"] else p["repo"]
return f"""<article id="{e(p['id'])}">
<h2>{e(p['title'])}</h2>
<p class="meta">{e(ref)} · {e(p['status'])} · owner: {e(p['owner'])} · <a href="{e(p['url'])}">source on the forge</a></p>
<h3>What is proposed</h3><p>{e(p['what'])}</p>
<div class="ev"><h3>Rests on existing material</h3>{ul(p['evidence'])}</div>
<div class="inv"><h3>Weksa's invention</h3>{ul(p['invention'])}</div>
<h3>Weksa's stance and uncertainty</h3><p class="stance">{e(p['stance'])}</p>
{forks(p)}
</article>"""
page = f"""<!doctype html><html lang="en"><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Weksa proposals</title><style>{CSS}</style>
<h1>Weksa proposals</h1>
<p class="meta">State as of {e(data['as_of'])}. Nothing on this page is canon.</p>
<p>{e(data['intro'])}</p>
<nav>{"".join(f'<a href="#{e(p["id"])}">{e(p["title"].split(":")[0])}</a>' for p in data['proposals'])}</nav>
{"".join(card(p) for p in data['proposals'])}
</html>
"""
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(page, encoding="utf-8")
print(f"wrote {out} ({len(data['proposals'])} proposals)")

View file

@ -0,0 +1,151 @@
{
"as_of": "2026-11-06",
"intro": "Weksa drafts ideas for settings and languages that other people own. None of it is canon. Each card says what is proposed, which parts rest on existing material and which parts Weksa made up, and what Weksa needs from you. Answer in one sentence in the project room; you do not need to open the pull request.",
"proposals": [
{
"id": "zyphos-2",
"title": "Draft names for Zyphos peoples and places",
"repo": "Zyphos",
"pr": 2,
"url": "https://eureka.gamecult.org/forge/GameCult/Zyphos/pulls/2",
"status": "open, not merged",
"owner": "Deru (setting owner)",
"what": "A note proposing names for the Sa'ueia and Airawa: the family unit, routes, the continent, memory partners, the mother tree, the Airawa empire and its word for unincorporated natives. Each name shows how it is built from smaller word-pieces and what it is meant to carry. The vault itself is not edited; the note is one new file. It was revised after Deru's phonotactic answers of 2026-11-06 (below).",
"evidence": [
"Deru's answers, 2026-11-06 (settled by Deru): the main word comes first in a Sa'ueia compound; sharing memory and knowledge is valued and no reputation attaches to the act, the partner or the memory; each Airawa tribe has its own name, linked to a matriarch tree; individual names are given by those trees, not inherited.",
"Deru's phonotactics, for both Airawa and Sa'ueia: no two consonants adjacent, no two identical vowels adjacent, k and never q. The checker in Weksa PR 9 enforces them; all names in the note now pass it (0 errors, 0 warnings).",
"Sa'ueia names are built only from Deru's roots (ila walk, weru know, olune breeding ground, -um) plus new stand-in roots.",
"No name collides with Deru's words; the near-misses are listed in the note."
],
"invention": [
"Every Sa'ueia root not from Deru (muna memory, sela gift, rena return, kasu partner, mano kin, sulo stay) is a Weksa stand-in.",
"The earlier Airawa names built from closed-syllable roots (gor, dak, zeg, sar, tez, -ur) all broke Deru's rules and were replaced by open-syllable roots (gora, daka, zege, sara, teza) and the word kerath (the slice's qerath with q replaced). All are Weksa placeholders; open roots make Airawa smoother than the setting wants.",
"Whether sh, zh and kh count as one consonant, like th, is not known; the checker treats them as two, so names using them are flagged provisionally."
],
"stance": "Weksa thinks the names are worth reading as a starting vocabulary, not as answers. Confidence is moderate on the Sa'ueia forms and low on the Airawa forms. Nothing should be adopted before Deru rules.",
"forks": [
"Are sh, zh and kh single consonants like th, or two consonants?",
"What is the Airawa sound inventory? Open-syllable roots make Airawa softer than the setting asks.",
"Do the Sa'ueia call the Airawa by one word, and what is it? (Deru: one word, not unkind.)"
]
},
{
"id": "weksa-6",
"title": "Rust to Dust: imperial ontology built on Dao and path-fit, not shame and honour",
"repo": "Weksa",
"pr": 6,
"url": "https://eureka.gamecult.org/forge/GameCult/Weksa/pulls/6",
"status": "merged 2026-11-06 as a proposal; nothing in it is canon",
"owner": "Rust to Dust setting owner",
"what": "Two parts. An example in the Rust to Dust language notes still showed the client sending 'authentic local defiance' as a fact about an ambush; it now shows plain facts plus the speaker's stance and marks the old value as something the empire's reading produces. Separately, a companion draft (imperial/dao-ontology.md) builds the empire's ontology around a placeholder concept called Dao (living well, self-actualization), where painting is a duty and going unpainted is heresy unless it expresses the speaker's own path. The edited lines in the existing imperial language notes are marked as proposal.",
"evidence": [
"A standing ruling (weksa-body:ruling:rtd-imperial-aesthetic-reading-to-ontology) already puts aesthetic readings on the ontology side.",
"The real packet fields live in crates/weksa/src/packet.rs; the example is now labelled a sketch that does not define them.",
"Dao as living well, painting as duty, unpainted as heresy unless it expresses the speaker's own path (a warrior yes, a celebrity making a statement is gauche): Meta, 2026-11-06."
],
"invention": [
"The numbers in the stance example (contempt 600, restraint 800) are made up to show the shape.",
"'Contempt' is a human-flavoured placeholder grade, not an imperial reading; the empire's value system is Dao and path-fit, not shame or honour.",
"'Authentic local defiance' is kept as a class the empire could output; whether it survives is undecided.",
"The four readings of a norm-break (devout, heretical, path-true, gauche) and the path-fit test that picks among them are Weksa's generalisation of Meta's examples.",
"Native terms as several context-tagged readings with the chosen gloss recorded separately is Weksa's modelling of Meta's Dao De Jing analogy.",
"'Dao' is a placeholder label only; the term has no native name or sound yet."
],
"stance": "Weksa is fairly confident the old example was inconsistent with the ruling and that shame/honour is the wrong frame. It is unsure whether four readings are the right set, and how a commentator tells path-true from gauche by conduct alone.",
"forks": [
"Should 'authentic local defiance' stay as one of the empire's reading classes, or be dropped or renamed?",
"Is 'path-true' versus 'gauche' the right split, or is fit a matter of degree?",
"Does the same path-fit test cover obscenity and other norm-breaking, or only going unpainted?"
]
},
{
"id": "weksa-9",
"title": "Name rules in the Sa'ueia/Airawa checker",
"repo": "Weksa",
"pr": 9,
"url": "https://eureka.gamecult.org/forge/GameCult/Weksa/pulls/9",
"status": "merged 2026-11-06 (open questions below)",
"owner": "Deru (setting owner)",
"what": "The word checker now enforces Deru's 2026-11-06 phonotactic rules for both languages, can check whole proposed names built from word-pieces, and the naming briefs record Deru's answers (settled) apart from Weksa's readings (invented).",
"evidence": [
"Deru's rules: no two consonants adjacent, no two identical vowels adjacent, k and never q, for Airawa and Sa'ueia.",
"31 tests pass; every name in the names file checks clean.",
"Of the earlier candidate names, only Sauwele passes, and it is too close to Sa'ueia."
],
"invention": [
"Reading th as one consonant and sh, zh, kh as two is Weksa's, pending Deru.",
"The new open-syllable Airawa roots are placeholders."
],
"stance": "Weksa is confident the checker implements the rules as relayed; the relay is the weak point, so Deru should confirm the edge cases.",
"forks": [
"Are sh, zh and kh single consonants like th?",
"What is the Airawa inventory?"
]
},
{
"id": "rtd-notes",
"title": "Rust to Dust: open design questions in the language notes",
"repo": "Weksa",
"pr": null,
"url": "https://eureka.gamecult.org/forge/GameCult/Weksa/src/branch/main/settings/rust-to-dust/imperial/language-design.md",
"status": "draft on main (r0), not ruled",
"owner": "Rust to Dust setting owner",
"what": "A first draft of how the empire's language might work: its sound shape, how it splits ideas like victory, mastery, spectacle and vulgar overmatch, and how decoration works as its central metaphor (address, insult, praise, grief). It is written so a program could choose words from facts about a scene, not from English glosses.",
"evidence": [
"Tight, composed sound and 'constraint is mastery' come from the setting source.",
"The list of distinctions (unpainted as shame, danger, contempt, purity; resistance as threat, folk art, breakout talent) comes from the source and the battle-royale commentary."
],
"invention": [
"The sound inventory (voiceless stops, held fricatives) is a draft, and the reptilian vocal tract is the weakest-supported choice.",
"Decoration-as-metaphor in grammar is the draft's strongest invention and the easiest to overrule.",
"The breakdown of victory, mastery, spectacle and overmatch is a hypothesis.",
"Grades and words named after human shame, honour, contempt or vulgarity in this draft are placeholders for imperial readings not yet defined."
],
"stance": "Weksa thinks the decoration metaphor is the most promising idea here and also the least backed by the source. Treat the whole draft as overrulable.",
"forks": [
"Does the empire's language really talk about grief and obligation as things worn, like decoration?",
"Is 'mastery = victory plus chosen constraint' what the setting means, or is something missing?",
"Which human distinctions should this language collapse, and which should it force speakers to make?",
"Do you want the empire to misread distributed cooperation as noise, or as one performer's act?"
]
},
{
"id": "weksa-5",
"title": "Sa'ueia workshop: word table, checker, sound proposal",
"repo": "Weksa",
"pr": 5,
"url": "https://eureka.gamecult.org/forge/GameCult/Weksa/pulls/5",
"status": "merged 2026-11-04 (questions below remain open)",
"owner": "Deru (setting owner)",
"what": "A table of Sa'ueia word-pieces, a checker that joins them and flags rule breaks, and a written sound proposal. This is merged work; its open questions are still unanswered and the names proposal above depends on them.",
"evidence": [
"Every table entry says whether it is Deru's word or a Weksa placeholder.",
"The checker has 15 tests."
],
"invention": [
"The sound section is a proposal for Deru to cut.",
"The consonant list is marked open on purpose; the checker refuses to accept a guess."
],
"stance": "Weksa is confident the tooling works and not at all confident about the sound rules. Only the species name Sa'ueia is canon.",
"forks": []
},
{
"id": "zyphos-1",
"title": "Respell Sa'auei'a as Sa'ueia",
"repo": "Zyphos",
"pr": 1,
"url": "https://eureka.gamecult.org/forge/GameCult/Zyphos/pulls/1",
"status": "merged 2026-11-04 (done)",
"owner": "Deru (setting owner)",
"what": "A spelling-only sweep with Deru's permission: 53 occurrences in 26 files and one file name now use Sa'ueia. Shown for completeness; nothing further is asked.",
"evidence": [
"Deru's permission, 2026-11-04 in the Zyphos room."
],
"invention": [
"None. One identifier, saaueia-nomadic-advanced in state/branches.json, was left alone as a slug."
],
"stance": "Done. The only loose end is whether that slug should be renamed too.",
"forks": []
}
]
}