feat(worldbuilding): research knowledgebases + applied pattern libraries - #97
Conversation
…nt proposal (STAGING) - .arcanea/lore/NAMING_REGISTRY.md — ten naming registers with sound-spaces and morphology, tiered spell-suffix system, machine-checkable collision rules, earnable/losable name elements, locked + superseded inventories - .arcanea/lore/THESSARA.md — Thessara redeployed as the Drowned Academy of the Vantara March (+ founder Archmage Thessara), filling the unnamed slot in the merged Stilling legend; alternates + mystery-ledger entries recorded World-research knowledgebases (docs/worldbuilding/research/) follow in the next commit when the research swarm completes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
…benchmark + naming registry + Thessara canon proposal Research swarm output — one knowledgebase per benchmark franchise (docs/worldbuilding/research/): Tolkien/Middle-earth, Elder Scrolls, Final Fantasy, Marvel, Harry Potter/Fantastic Beasts, Warcraft, and anime/modern screen worlds (Avatar TLA, Arcane/Runeterra, JJK, FMA, Demon Slayer, AoT, Frieren, Ghibli). ~21k words, each with cosmology / magic / naming / bestiary / villain / canon-management extraction, a 'What Arcanea Should Steal (Architecture, Never Bricks)' section, and IP red lines. SYNTHESIS.md — honest 12-dimension scorecard of Arcanea vs the benchmarks, the Ten Upgrades (STAGING proposals U1-U10: First Duet cosmology, Shadow-as-marring, Binding Vows hard subsystem, Element-Cultures, World Registry + canon tiers, Shattered Verse, Villain Doctrine, naming roots, era machinery, Library-as-transmission), a 10-item trap list, and a build order. .arcanea/lore/NAMING_REGISTRY.md (STAGING) — full articulation system: ten registers with sound-spaces + morphology, tiered spell-naming, machine-checkable collision rules, earnable/losable name elements, locked + superseded inventories. .arcanea/lore/THESSARA.md (STAGING) — redeploys the Thessara name as the Drowned Academy of the Vantara March + founder Archmage Thessara, filling the existing unnamed slot in the Stilling legend; alternates recorded; mystery-ledger entries minted. All STAGING; CANON_LOCKED.md untouched; promotion via /lock-decision. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ReviewThis is a docs/lore-only PR (9 markdown files, ~9,000 lines / ~23k words: Verification performed
ObservationsIP/legal hygiene (the main "security" analogue here) — well handled. Every research file separates transferable architecture from protected expression and ends with an explicit "IP Red Lines" section (e.g., the HP file correctly flags Warner Bros.' aggressive enforcement history — the RDR Books case, the 2024 fan-festival takedowns — and draws the safe/unsafe line at mechanism-vs-expression). This is the right discipline for content that studies existing IP. One thing I couldn't verify: the external web citations (WordsRated, HP Lexicon, Wizarding World, etc. — dozens across the 7 files) weren't checked against live URLs since Minor / non-blocking nits:
Process / checklist
Overall: well-scoped, internally consistent, and appropriately cautious about both IP risk and canon-lock discipline. No blocking issues found; the external-citation verification gap above is the only thing I'd want closed out before treating these knowledgebases as authoritative references. |
…Thessara) Review nit on #97: THESSARA.md labels its register 'Reaches covenant / high-antiquity' while the registry table listed only the covenant register. The blend is intentional (Archmage Thessara = Seventh-Age antiquity figure; the Academy = Reaches place) — the registry table now states the dual-register rule explicitly so it stays the single source of truth. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
Review — PR #97 (docs/lore only, no source code)This PR adds 1,006 lines across 10 new markdown files (7 franchise-research knowledgebases + 🔴 Blocking: the PR's own safety claim doesn't holdTHESSARA.md §1 states:
This is not accurate. Live references to Thessara as Elara's current godbeast (not Vaelith) still exist in at least: Same issue for "Amaterasu": Since the whole point of THESSARA.md is to redeploy the name "Thessara" for a new entity (the Drowned Academy) on the premise that the old godbeast usage is dead, merging this while ~15 files still describe Thessara as Elara's live godbeast creates an active two-referent collision, not a resolved one. Recommend either: (a) scope this PR to also clean up the stray references (or file a tracked follow-up before promotion), or (b) soften the THESSARA.md/NAMING_REGISTRY.md language so it doesn't assert something the repo doesn't currently support. 🟡 Unverifiable citationTHESSARA.md §2.5 and the naming-adjacency reasoning in §4 lean on "Nethyssa" (a "PR #76" Leviathan) as an established sound-family peer. A repo-wide search finds "Nethyssa" nowhere except this PR's own two new files — there's no bestiary entry or other canon establishing it. If Nethyssa is real but unmerged/staged elsewhere, worth a pointer; if not, the "deliberate echo" reasoning in §2.5 is resting on nothing yet. ✅ What checks out
Minor
Nothing here blocks the staging nature of this PR (it doesn't touch locked canon), but the Thessara/Amaterasu superseded-reference claim should be fixed before this is used as the basis for a |
… PR #76 staging Review round 2 fixes: - THESSARA.md no longer claims #96 removed the last Thessara-as-godbeast references; stray references persist in mirrors, agent prompts, and packages, and a repo-wide sweep is now stated as a precondition for promoting the redeployment. - NAMING_REGISTRY.md superseded list gains a cleanup-status warning (Amaterasu and Thessara both still referenced repo-wide). - All Nethyssa citations now note it is proposed in open, unmerged PR #76 rather than reading as in-tree canon. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
|
Review addressed in 🔴 Blocking finding — confirmed and fixed. You're right: #96 only scrubbed the 33 conflict-marked files, and a fresh grep confirms Thessara-as-Elara's-godbeast plus Amaterasu both persist across mirrors ( 🟡 Nethyssa — real, but unmerged. It's the flagship of open PR #76 (Monster System + T3 Leviathan tier, PR body updated with a Round 2 review-notes section. Generated by Claude Code |
The aef2f43 run failed on memory.test.mjs 'memories.json should have valid structure when present' with 'Unexpected end of JSON input' — a cross-process race where the test reads ~/.arcanea/memories.json on the runner while concurrent suites write it. Unrelated to this PR's markdown-only diff; quality-gate was green on the prior head. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
Review — PR #97 (worldbuilding research + Naming Registry + Thessara)This is a docs/lore-only PR (10 new markdown files, 1010 additions, 0 deletions, no source touched), so the usual code-review lenses don't map 1:1 — I've adapted them below. I read Correctness / "bugs"
Consistency / best practices
Security
Test coverage / verification
Performance
OverallSolid, well-organized staging content with unusually honest self-critique already baked into the PR description (both review rounds are documented in-PR, which is good practice). The one thing I'd push on before merge: turn "repo-wide superseded-name sweep" from a documented precondition into an actual tracked issue/PR, since the drift it's flagging is already live in 🤖 Automated review via Claude Code |
… validator lint as proposed - Superseded-name sweep now tracked as issue #98 (referenced from THESSARA.md and NAMING_REGISTRY.md); citation verification tracked as issue #99. - SYNTHESIS.md U3 gains an explicit IP-differentiation requirement: the sworn-restriction mechanic hews closest to a single source and its common English name is that source's exact term, so the implementation must coin an Arcanean-register name via the registry coining procedure and keep the structural divergences. - NAMING_REGISTRY.md validation hook now explicitly marked proposed / not yet implemented so no reader assumes the lint runs today. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
|
Round 3 addressed in
The Elrond/Rivendell dedupe nit is noted for whenever these staging docs consolidate into canon files. Generated by Claude Code |
ReviewThis is a markdown-only worldbuilding/lore PR (10 new files, 0 deletions, no source code), so the usual "code quality / performance / test coverage" lenses don't apply directly. I reviewed it against the axes that matter for this kind of change: factual/citation accuracy, internal consistency with locked canon, IP discipline, and structural completeness. I independently re-verified the claims in the PR body rather than taking them at face value. Verified correct:
Minor observations (non-blocking):
No blocking issues found. The lore/canon discipline and citation hygiene are noticeably more careful than a typical docs PR — nice work tightening the claims between review rounds. |
…ne lint, CI Turns the worldbuilding research from documentation nothing reads into a pipeline that runs on every lore change. Mirrors the proven web-excellence pattern already load-bearing in this repo (skill + lint + CI ratchet). - .claude/skills/lore-release-gate/SKILL.md — the sequencing contract: ground in the vault, choose a pattern deliberately, draft in register, cross-check (canon/naming/IP/continuity), evaluate, stage, promote. Registered as an auto-activating skill on lore paths. - .claude/skills/canon-evaluation/SKILL.md — ten-dimension rubric with anchored 1-5 scales, hard gates, composite bands, and a four-lens adversarial pass that must be survived rather than argued with. - .claude/ci/lore-lint.mjs — the model-free half: superseded names, Gate frequencies, godbeast pairings, canon-tier banners. Verified clean on 8 legitimate canon files (zero false positives; changelog rows exempted since they must record superseded decisions verbatim) and catching 12 real errors across the known-drifted files. - .github/workflows/lore-canon.yml — runs the lint on every lore-touching PR as a ratchet on newly added lines. - CLAUDE.md — makes the gate discoverable, per the web-gate precedent. The lint reproduces issue #98 automatically and found more: guardians.md carries the entire Gate frequency ladder shifted one position. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
…s + U3 canon repair Re-cuts the seven world knowledgebases from vertical (by world) to horizontal (by craft problem), so the research is usable at the moment someone designs a specific thing. ~21k words. - patterns/ARTIFACTS.md — 13 legendary-object patterns, minting checklist, 5 unnamed STAGING slots (names withheld so the Registry coining procedure is not front-run), anti-patterns, IP red lines. - patterns/MAGIC_MECHANISMS.md — hard/soft spectrum made practical, 13 mechanisms, 7 failure modes, Arcanea application, 3 coined candidate names with etymologies. - patterns/ENCYCLOPEDIA_IA.md — 15 entity types with required fields and sections, canon-tier representation, and the Name Ledger: identity as stable ID with names as attributes, so a rename cannot half-land. - patterns/LANGUAGE_CRAFT.md — 8 registers with original examples, six compression techniques, phonaesthetic tests, and an audit of our own corpus prose tics. Lint corrections found by the pass itself: - The vault names the 852 Hz Gate Starweave (CANON_LOCKED.md:62); the linter had encoded the drifted name Shift from the instruction file. Now canonical, with an alias that still resolves for the frequency check and warns on the name — no rename is recorded in the approval log, so this is an unrecorded divergence, not a supersession. - packages/os/src/canon-validator.ts removed from the allowlist. Its 714 Hz entry is a real typo detector, but the file also asserts both superseded godbeast names as current (lines 164, 166) and normalizes misspellings toward them. It does not miss the drift; it certifies it. - Allowlist narrowed from docs/worldbuilding/ to research/ only, so pattern libraries quoting canon are checked. SYNTHESIS U3 canon repair: 'ranks measure accumulated binding' contradicts CANON_LOCKED.md:74, which defines rank by Gates Open and is LOCKED; and universal witnessed vows contradict the three unoathed Luminors in GATE_TOUCHED_UNDERGROUND.md:122. Repair recorded on the proposal — reframe to a payment ledger (negotiated / imposed / refused). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
Review: lore canon gate (.claude/ci/lore-lint.mjs, lore-canon.yml, the two new skills)Scoped this review to the actual code — lore-lint.mjs, the CI workflow, and the two SKILL.md files — since the other 18 files are prose/lore content. Overall this is careful, well-commented work: the assignment-vs-prose distinction in checkSupersededNames is a good design choice to keep false positives near zero, execFileSync is called with array args (no shell-injection surface), the workflow declares minimal permissions: contents: read, and the ratchet (--changed, only newly-added lines) is the right call for a repo with known pre-existing drift. A few things worth a look before/after merge: 1. Latent false positive in checkGodbeastPairing const wrong = Object.values(GODBEASTS).find( E.g. a row like '| Aiyami | Sol | Ino | Kyuro |' would report 'aiyami is bonded to Sol, not Kyuro' — a false positive. I confirmed this does not currently fire anywhere in this PR's content, but it cuts against the stated 'near-zero false positive by design' goal, and per the file's own framing, one bad false positive is how a linter like this gets switched off. 2. Allowlist is broader than its own comment implies 3. Silent skip on git diff failure 4. No automated tests for the linter itself 5. Minor/nit None of these block the gate from doing real, useful work — CI wiring, node --check, and the smoke test against CANON_LOCKED.md are all sound — but 1-3 are worth a follow-up pass given how central 'near-zero false positive' is to this linter staying trusted long-term. |
… into CI
Review round 5 on the canon gate. All five findings verified before fixing;
the linter's whole value is being trusted enough to stay switched on, and
that rests on near-zero false positives.
- Multi-pair table rows no longer misreport pairings. A row like
'| Aiyami | Sol | Ino | Kyuro |' reported BOTH pairs wrong, since the
check looked for any other canonical beast in the row without column
correspondence. Now skips rows naming more than one god, matching the
single-subject rule checkGateFrequency already used. Reproduced first.
- Gate names in ordinary English no longer fire. Nearly every Gate name is
also a common word; 'one legend per House voice ... (174→1111 Hz)' in
SYNTHESIS.md reported the Voice Gate as misnumbered. A name now counts
only in Gate context ('the Crown Gate', 'Gate of Crown') or alone in a
table cell. This vector was hidden while research/ was blanket-exempt.
- Allowlist narrowed to the check it was written for. It was applied
globally in main(), so NAMING_REGISTRY.md, THESSARA.md and the whole
research tree were also exempt from frequency, pairing and tier checks
they can still get wrong. Now superseded-names only; the linter's own
source stays fully excluded, since it states every name as data.
- git diff failures now log. A file dropping out of --changed silently
looked exactly like 'nothing to check'.
- LORE_FILENAME renamed LORE_HINT: it matches anywhere in the path, not
just the basename. Caught by a fixture whose temp dir contained 'lore'.
- canon-evaluation's example evidence row cited the disputed 'Shift' name
in a rubric about unrecorded naming drift. Now Starweave, per the vault.
lore-lint.test.mjs: 14 black-box fixtures through the real CLI, covering
both must-not-fire and must-fire cases. Wired into lore-canon.yml ahead of
the vault smoke test.
Verified: 14/14 fixtures pass; 19 legitimate canon, research and pattern
files clean; 19 real errors still caught across the known-drifted files.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
|
Round 5 addressed in 1. Multi-pair rows — confirmed, fixed. Reproduced exactly as you described: Two confident false errors on a correct row. Fixed with the single-subject rule 2. Allowlist broader than its comment — fixed by narrowing, not by documenting. You were right that it exempted four checks when it was written for one. Rather than update the comment, I scoped it: That narrowing immediately caught a sixth vector, which the blanket exemption had been hiding: 3. Silent skip — fixed. 4. No tests — fixed. Writing them caught the sixth item: my own 5. The ironic example — fixed. Fair catch. Verification: 14/14 fixtures pass · 19 legitimate canon, research and pattern files clean (zero false positives) · 19 real errors still caught across Generated by Claude Code |
The first CI run after the fixtures landed reported the test suite as canon drift — 5 errors, all of them fixture data. The test file deliberately contains a superseded godbeast in assignment position, a mispaired god, and a shifted frequency ladder, precisely so the checks can be proven to fire; its filename also matches the lore-file hint, so --changed picked it up. SELF widened to the .claude/ci/lore-lint prefix so both the linter and its fixtures are excluded from every check. Verified: CI's exact command (--changed --base origin/main) now clean across 5 files; 14/14 fixtures still pass; 17 real errors still caught in guardians.md and .claude/CLAUDE.md; the fixture file stays excluded even when named explicitly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
ReviewRead through the actual diff (18 files: two skills, the linter + its test suite, the CI workflow, two Code quality
Potential bugsNone found in the check logic. I traced Test coverage
Performance
SecurityNothing concerning — read-only permissions on the workflow, no Everything elseThe skill docs ( Overall: solid, well-tested tooling PR with clear rationale and good security practice. Only real ask is closing the |
Review round 6: checkLockClaim was the one rule with zero fixtures. Being WARN-only makes that worse rather than better — it cannot fail CI even if it silently breaks, so nothing would notice. Probing it to write the tests turned up a real inaccuracy in its own comment. It claimed 'only CANON_LOCKED.md may declare content LOCKED', but the repo contradicts that: .arcanea/lore/MAGIC_SYSTEM.md:3 carries 'Status: LOCKED ✅ — Approved by Frank (Creator) 2026-06-23' and is correct. The narrow regex was already skipping that case, so behavior was right for a reason the comment did not state. Corrected the rationale and the warning text: a status banner records a lock decision that was made; the rule targets running prose that asserts one. Behavior unchanged. Four fixtures: prose assertion warns without failing the build, an approved status banner does not warn, a tier-vocabulary listing does not warn, and the vault is exempt by path. Not changed: addedLinesFor shells out per changed file rather than batching one diff. Real, but the lore-PR file counts make it invisible (~1s runs) and the batched form is harder to attribute per file. Verified: 18/18 fixtures pass; MAGIC_SYSTEM.md clean; CI's --changed command clean across 5 files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
|
Round 6 addressed in Probing it to write the tests turned up an inaccuracy in the rule's own comment. It claimed "Only
That's legitimate: locked content lives outside the vault once the Creator has approved it. The narrow regex was already skipping it, so the behavior was right — for a reason the comment didn't state. Corrected both the rationale and the warning text: a status banner records a lock decision that was made; the rule targets running prose that asserts one. No behavior change. Four fixtures now cover it — one true positive (prose assertion warns, exits 0), and three near-misses that must stay silent (an approved status banner, a tier-vocabulary listing, and the vault itself by path exemption). 18/18 pass. On the Thanks for hand-verifying Generated by Claude Code |
Review: #97 — worldbuilding research/patterns + lore canon gateThis is a large, mostly docs/lore PR; I focused the code review on the one piece of actual logic — Code quality
Bug / gap found
Minor / non-blocking
SecurityNo concerns. Test coverageGood for the four canon checks (superseded names, gate frequency, godbeast pairing, tier banner, lock-claim) — both the "must fire" and "must not fire" cases are exercised, which is exactly right for a linter whose entire value proposition is staying trusted. See the gap noted above for the diff-parsing path. Content (lore/docs)Didn't do a full canon audit of the 21k words of research/pattern docs — that's what the new Overall: solid, well-reasoned tooling addition that mirrors the existing |
Review round 7. The workflow's paths filter omitted **/*.js and **/*.mjs
while LORE_EXT includes them, so lore-bearing JS anywhere else in the repo
would never trigger the check — not caught, not even attempted.
Resolved by widening the trigger rather than narrowing LORE_EXT, because
the repo really does carry lore in those files:
packages/chrome-extension/tests/chrome-extension.test.mjs
→ 2 superseded godbeast names + 2 shifted-ladder frequencies
scripts/generate-arcanea-visuals.js → 2 gate-name warnings
Dropping js/mjs would have discarded real coverage to fix a mismatch.
The trigger list is now a verified superset of LORE_EXT, and the comment
says why it must stay one: a type the linter checks but the trigger omits
is drift nothing ever looks at, which is worse than a rule that fires
wrongly — a false positive announces itself, a missing trigger does not.
Also covers addedLinesFor(), previously the least-tested and most
bug-prone function (hand-tracked cursor through @@ hunks). Two tests build
a real temp git repo and assert the ratchet property in both directions:
newly added drift is reported, pre-existing drift on the base commit is
not. Backwards either way and the linter either fails every PR on
inherited debt or silently passes new drift.
Documented the gate-name alias check's narrow reach: it returns early
without a Hz value on the line, so a bare 'the Shift Gate' is not
reported. Widening means matching a common word in prose for a WARN
nobody can act on until /lock-decision settles the name.
Verified: 20/20 fixtures; trigger/LORE_EXT consistency checked
programmatically; CI --changed command clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
|
Round 7 addressed in You offered two fixes — the evidence picks the wider trigger. The repo genuinely carries lore in JS: Dropping The comment now says why it must stay a superset, which I think is the durable point: a false positive announces itself; a missing trigger doesn't. A rule that fires wrongly gets reported and fixed. A file type the linter checks but the workflow never hands it produces silence that is indistinguishable from cleanliness.
Gate-name reach — confirmed and documented, not widened. You're right that it returns early without a Hz value, so a bare "the Shift Gate" stays silent. Widening means matching a common English word in prose to emit a WARN nobody can act on until 20/20 fixtures pass; CI's Generated by Claude Code |
Review: lore canon gate + worldbuilding libraries (PR #97)I focused verification on the mechanical/tooling pieces ( Code quality
BugsNone found. I specifically traced the trickiest paths against the new content added in this same PR, since a linter that flags the prose describing its own target problem would be an obvious own-goal:
PerformanceFine — pure line-scan regex checks over only the files/lines the ratchet selects, no network or model calls, no obvious quadratic blowup. Matches the PR's stated ~1s CI runtime. Security
Test coverageAbove average for a CI lint script: fixtures run through the real CLI as a black box (not just internal functions), explicit regression tests for previously-found false positives (the two-pair table row, "House voice" near a frequency range), and dedicated coverage for the Minor / non-blocking
Nothing blocking. This is solid, carefully defended tooling. |
Round 8 raised action pinning. Verified the convention before acting: zero of the ~78 'uses:' lines across .github/workflows/ are SHA-pinned, so SHA-pinning this one file alone would be inconsistent rather than safer. Supply-chain hardening is a repo-wide decision; left as-is with the reasoning recorded inline. What the check did surface: this workflow was on checkout@v4 / setup-node@v4 (inherited from the web-excellence workflow it mirrors) while 35 and 17 other workflows respectively are already on v5, and the v4 actions emit a Node-20 deprecation warning in this workflow's own logs. Bumped to match the majority and clear the warning. No change for the second note: .claude/ci/lore-lint.test.mjs is outside the 'packages/*/tests/*.test.mjs' glob of test:all, which is correct — it runs via the explicit node --test step in this workflow, and the sibling web-guidelines lint has no in-repo test file at all. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
ReviewThis is an unusually well-engineered PR — the review notes (11 rounds, documented in the PR body) show real adversarial iteration, and it shows in the code. Focused mainly on the mechanical parts ( Code quality
Potential bugs / edge cases
Performance
Security
Test coverage
Non-code (lore/docs)Didn't attempt to fact-check the ~21k words of research/pattern content against Overall: solid, well-tested infrastructure change with unusually thorough self-documentation of its own edge cases. The two notes above are minor and non-blocking. |
…m adjacency
Review round 13, two findings, both real. The first is a regression I
introduced one round earlier.
1. Round 12 fixed a false positive by counting BARE gate names for the
ambiguity bail-out. That created a false-negative class: "The Crown
Gate resonates at 963 Hz, though the source remains unclear" bails on
the ordinary word "source" and misses a real Crown error. Reproduced
before fixing.
Both blunt answers are wrong and both were tried — counting
Gate-context names blames the wrong gate (CONTINUITY_AUDIT.md:329),
counting bare names suppresses real errors. The actual signal is
proximity: a frequency belongs to whichever gate is quoted next to it
("Voice (528 Hz"), not to one mentioned elsewhere in the sentence. Bail
only when a DIFFERENT gate name sits in the 25-char window immediately
before the number. Resolves both directions.
2. checkLockClaim matched "LOCKED :" and "this document is" independently
on one line. Flagged as an inconsistency in rigor rather than a bug —
probed it, and it does misfire: "Status: LOCKED — this document is
superseded by the vault" warned that the file was claiming to be
locked, which is the opposite of what it says. Now requires adjacency,
with sentence breaks excluded from the gap.
Not changed: the reviewer suggested a fixture documenting the
ambiguity-bailout false negative as a limitation. Fixed the limitation
instead, and pinned both directions with fixtures.
Verified: FN case now errors; CONTINUITY_AUDIT.md and MAGIC_SYSTEM.md
still clean; .claude/CLAUDE.md still 17+3 and guardians.md 8+1 (no
detection lost); full FP sweep over research/patterns/lore = 0 errors;
31/31 fixtures; --changed clean across 18 files.
Note: the first attempt at this commit message used backticks, which the
shell expanded as command substitution and silently deleted two quoted
phrases. Amended via a message file.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
3b83bca to
6f6d150
Compare
|
Round 13 addressed in 1. The ambiguity bail-out — you called it a deliberate tradeoff; it was a bug I'd just created. Reproduced your exact example: Round 12 had swung the bail-out from counting Gate-context names to counting bare names, to kill a false positive. Both extremes are wrong, and I'd now shipped each in turn:
The real signal is neither: it's proximity. A frequency belongs to whichever gate is quoted next to it — 2. A banner saying the document is superseded was flagged as claiming it's locked — the opposite of what it says. Now requires adjacency, with sentence breaks excluded from the gap. The three near-miss cases stay silent and both true positives still fire. On your suggested fixture — you proposed documenting the ambiguity-bailout false negative as a known limitation. I fixed the limitation instead, and pinned both directions with regression fixtures. A documented false negative in a drift linter still reads as "clean" to whoever runs it. One process note against myself: the first push of this commit used backticks in the message, which the shell expanded as command substitution and silently deleted two quoted phrases — leaving "checkLockClaim matched and independently". Amended via a message file ( Verified: FN case now errors · Generated by Claude Code |
ReviewI read through the tooling/code portions in detail ( Code qualityThe linter and its tests are unusually well engineered for a CI script. A few things stood out positively:
Potential bugs / gaps (minor, worth a look)
PerformanceNon-issue at this scale — Security
Test coverageStrong. 28 fixtures covering must-fire, must-not-fire, alias resolution, the workflow/linter extension-coupling guard, and the Scope note (not a blocker)This PR bundles three fairly different things: ~21k words of research/pattern documentation, two new skills, and the lint/CI tooling. Given the tooling is the part with actual failure modes (bugs, false positives/negatives, CI behavior), a split where the lint script + tests + workflow could be reviewed in isolation might have been easier to vet — though given the extensive review history already documented in the PR description, this is a minor process note rather than something to act on now. Overall: this is a careful, self-critical piece of tooling with genuinely good test discipline. The findings above are minor refinements, not blockers. |
Review round 14, two actionable findings. 1. The lock-claim regex required LOCKED to be followed by a check-mark or a colon, which is punctuation coupling rather than meaning: "This document is now LOCKED." went unflagged. Verified, then widened. Widening naively would have inverted the rule — without a guard, "This section is not LOCKED" starts firing. The gap is now captured and rejected when it contains not / never / no longer. Both directions pinned with fixtures. 2. Nothing verified the linter's transcribed GATE_FREQUENCIES and GODBEASTS against the vault. The file states "if these disagree with the vault, the vault wins and this file is the bug", but that was an assertion with nothing behind it, and the CI smoke test does not close the gap: it runs the linter OVER the vault, so it only catches drift the checks already model. A locked rename the linter has never heard of passes silently — which is the exact drift class this tool exists to catch, in the tool itself. Added a test that parses the vault's Gate table and diffs it against the constants, asserting count and every frequency and god-to-godbeast pairing. This is the same machine-enforced-coupling move already applied to the workflow trigger and LORE_EXT; the constants deserved it more, since they are the reference every check depends on. Verified the guard can actually fail: setting crown to 999 produced "GATE_FREQUENCIES.crown must be 741 per the vault" and 3 failing tests. A guard that cannot go red is worse than none. Acknowledged without action: addedLinesFor remains the most bug-prone piece and is worth extra scrutiny in future diffs; the three-in-one scope of this PR (research, skills, tooling) would have been easier to vet split apart, which is a fair process note for next time rather than something to restructure now. Verified: 33/33 fixtures; FP sweep over research/patterns/lore = 0 errors; .claude/CLAUDE.md still 17+3; --changed clean across 18 files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
|
Round 14 addressed in 1. Lock-claim punctuation coupling — confirmed and widened, with a wrinkle. Requiring 2. Nothing enforced "the vault wins" — and the smoke test doesn't close it. This is the one worth dwelling on. The linter's header says "if these disagree with the vault, the vault wins and this file is the bug." That was an assertion with nothing behind it. And you're right that the CI smoke step doesn't help: it runs the linter over the vault, so it only catches drift the checks already model. A locked rename the linter has never heard of passes in silence — the exact drift class this tool exists to catch, occurring inside the tool. Added a test that parses And I verified the guard can fail, because a green test that can't go red is worse than none: This also has a direct bearing on the open Starweave vs Shift decision: whichever way Acknowledged without action: Verified: 33/33 fixtures · FP sweep across research/patterns/lore = 0 errors · Generated by Claude Code |
ReviewReviewed the diff directly ( Code qualityStrong. Test coverageThis is the standout part of the PR. One gap: the linter's own constants are diff-checked against Potential bug (minor, low severity)
const claim = line.match(/this (document|file|section) is([^.;—]{0,15})LOCKED\b/i);
if (claim && !/\b(not|never|no longer)\b/i.test(claim[2])) { ... }This won't catch contracted negation. For SecurityNo concerns. PerformanceNo concerns — the linter is pure regex/line-scanning over already-filtered file lists, Scope noteThis PR is explicitly diagnostic/tooling — it documents real drift (superseded names, shifted Gate frequencies) in I didn't independently deep-audit the ~21k words of lore content in Overall: a well-scoped, defensively-coded, thoroughly-tested addition that mirrors the existing |
…t the vault Review round 15, both findings actioned. 1. The lock-claim negation guard missed contractions. "This document isn't LOCKED, still evolving." leaves "n't " in the captured gap, which contains no literal "not", so the word-boundary test passed it through and warned that the file was claiming to be locked — the inverse of what it says. Reproduced, then matched the apostrophe form explicitly. Behaviour matrix now: "isn't LOCKED" silent, "is not LOCKED" silent, "is now LOCKED." fires, "is LOCKED check-mark" fires. 2. GATE_ALIASES was maintained by memory. An alias exists to resolve a name the vault does NOT use onto one it does; if a lock-decision ever settles Starweave vs Shift the other way, "shift" becomes canonical and the alias silently starts rewriting a correct name into a wrong one. Added a test asserting every alias key is absent from the vault's Gate names and every alias target is present. Verified it fires on exactly the scenario that matters: renaming the vault row to Shift produced '"shift" is an alias but the vault now names a Gate that' plus the constants-drift failure, 2 tests red. Vault restored and confirmed untouched afterwards. This closes the loop the previous round opened. The constants, the alias table, and the workflow trigger are now all machine-checked against their sources rather than against someone remembering. Verified: 35/35 fixtures; lock-claim matrix as above; vault byte-identical after the destructive probe. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
|
Round 15 addressed in 1. Contracted negation — reproduced exactly as you predicted.
2. Added a test asserting every alias key is absent from the vault's Gate names and every target is present. Verified it fires on precisely that scenario — I renamed the vault row to Vault restored and confirmed byte-identical afterwards ( Together with last round, the loop is closed: the constants, the alias table, and the workflow trigger are all now machine-checked against their sources rather than against someone remembering. Whichever way the Starweave/Shift call goes, the tooling fails loudly until it matches. On your scope note — agreed and worth amplifying for anyone skimming: the drift this gate discovered is still live on Verified: 35/35 fixtures. Generated by Claude Code |
ReviewScope: this PR is almost entirely additive docs/lore (research + pattern libraries, ~21k words) plus one real piece of executable code — Bugs / correctness
Both are narrow rather than exotic, but worth a couple more fixtures (two Hz values on one line; the alias combined with a neighboring gate name) given how much the PR leans on "near-zero false positive, verified by fixtures" to justify trusting this linter as the mechanical backstop. Code quality / best practices
PerformanceNo concerns — a SecurityNothing found. Test coverageThe 28-fixture black-box suite (real CLI invocations, not re-implemented regex copies) is genuinely strong — especially the OverallSolid, unusually well-documented tooling PR (the review-rounds log in the description is a good practice worth keeping up). The two |
Review round 16, both findings reproduced first, then actioned. 1. checkGateFrequency only ever inspected the first NNN Hz match on a line. "| Unity | 963 Hz | Crown | 400 Hz |" came back clean — Crown is 741 Hz and nothing looked. Multi-pair table rows are exactly the shape the vault and its mirrors use, so this was a silent miss in the most common layout. 2. The window used to attribute a frequency was derived from the raw line, but the alias substitution rewrites the string in place and moves every later index. The offsets survived the rewrite, so the attribution window slid by four characters per replacement. Both fall out of one fix. The function now walks every Hz on the line with matchAll and, for each, finds the nearest Gate mentioned before it in the rewritten string — so there are no stale indices left to go stale. gateMentionIndex() collects the position of the earliest Gate reference in any of the forms the corpus actually uses (X Gate, Gate of X, Gate N: X, Gate X, and a bare table cell) rather than a bare name match, which is what kept the false-positive rate at zero across the previous rounds. The hijacker check now looks at the text between the owning Gate and its number instead of a fixed window behind the number. Two fixtures added, and both were checked against a mutant rather than assumed: reintroducing first-match-only turns the multi-pair fixture red, and flipping owner selection from nearest-preceding to nearest-following turns both new fixtures red along with eight existing ones. Verified: 37/37; CONTINUITY_AUDIT clean; .claude/CLAUDE.md 17 errors / 3 warnings and guardians.md 8 / 1, both unchanged; --changed clean over 18 files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
|
Round 16 actioned in 1. Only the first Crown is 741 Hz. This matters more than the example suggests — multi-pair rows are the layout the vault's own tables and the mirrors use, so the most common shape in the corpus had a blind spot from the second column onward. 2. Stale indices across the alias rewrite. Also confirmed: Both collapse into one fix rather than two. The check now walks every frequency with The recall/precision tension you flagged is why On the two fixtures you named — I checked they can actually fail rather than assuming it, since twice in this PR a change to this function silently destroyed detection while every test stayed green:
Source restored from backup and re-verified after each probe. Verification: 37/37 fixtures. PR body refreshed — it still said 11 rounds / 28 fixtures. Generated by Claude Code |
ReviewReviewed the full diff (20 files, +3886/-0). This is the Correctness — verified, not just read
One real bug (low severity)
const negated = (gap) => /\b(not|never|no longer)\b/i.test(gap) || /^n[''`]?t\b/i.test(gap.trim());I checked the actual bytes of the character class — it contains the straight apostrophe ( Design observations (not blocking)
Test coverageExceptional for a CI linter of this scope: 37 black-box fixtures driven through the real CLI (not the internal functions), explicit regression tests for every documented false positive that was found and fixed, a real-temp-git-repo test for the Content (the lore additions)
Nothing here blocks merge; the one real fix (curly-apostrophe negation) is small and well-contained. Nice work — the comment density in |
Review round 17. The lock-claim negation guard's apostrophe class held two ASCII 0x27 and a backtick — the duplicate is almost certainly a U+2019 that got normalised to straight at some point, which is how the gap survived round 15 looking correct while only covering half the cases. Consequence: prose typed in a word processor or through autocorrect writes "isn't" with U+2019, the contraction is not recognised as a negation, and the file gets warned for claiming to be LOCKED when the sentence says the opposite. Reproduced before fixing: This document isn’t LOCKED, still evolving. WARN [lock-claim] Prose declaring this file LOCKED. WARN-only, so it never failed a build — but an inverted reading is the failure mode this check is least able to afford, since the whole point is telling apart a file that claims lock status from one that disclaims it. Fixture added and verified to guard: reverting the class to ASCII-only turns it red, 37 pass / 1 fail. Verified: 38/38; the curly sentence clean; --changed clean over 18 files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
|
Good catch on the apostrophe class — fixed in Confirmed the bytes before touching it, since that's the kind of claim that's easy to get backwards:
Reproduced: Fixed to Agreed it's low severity — On the two design observations, both correct, and I'm deliberately not changing either:
Also confirming your spot-checks match mine: the vault cross-check of Still open for Frank, unchanged: Starweave vs Shift for the 852 Hz Gate, the #98 sweep greenlight, and U3 as a payment ledger. Generated by Claude Code |
ReviewReviewed the diff against Potential bug:
|
…sGate in
Review round 18. Both findings reproduced first.
1. Owner selection requires a Gate name to appear in Gate context, because
every Gate name is also an ordinary English word. The hijacker check
that can override an owner did a bare word-boundary match, which
contradicted that premise and silently ate real errors:
The Foundation Gate resonates like a heart at 285 Hz.
lore-lint: clean
Foundation is 174 Hz. The simile "like a heart" suppressed a genuine
mistake. Candidates now have to name a Gate the same way an owner does.
The window widened from the last 25 characters to the whole span from
owner to number. A character budget can bisect "voice gate" and hide
the context the check now depends on, and the span is short by
construction: the owner is the nearest preceding mention, so anything
further back already lost the ownership race.
2. gateMentionIndex and namesGate encoded the same four Gate-context forms
verbatim, one returning an index and one a boolean. Two regex lists
that must stay identical are the drift this linter exists to catch, so
namesGate is now a one-line wrapper. The per-form rationale moved into
the surviving list rather than being dropped — those comments record
which real errors each form was added to catch.
Writing the first fixture exposed a third, unreported gap. With the
hijacker check disabled entirely the suite stayed green and the corpus
was unchanged, so nothing tested the only case it exists for: a Gate named
BOTH before the owner and again between owner and number. gateMentionIndex
returns a Gate's earliest mention, so that Gate loses the ownership race
even while sitting immediately before the number, and only the hijacker
saves it. Now pinned:
The Voice Gate and the Foundation Gate differ; the Voice Gate holds 528 Hz.
528 Hz is Voice's and correct; without the check the line is blamed on
Foundation. A heuristic no test can kill is one nobody can safely edit.
Both fixtures checked against their own mutants: disabling the hijacker
turns the second red, reverting it to a bare-name match turns the first
red. 39 pass / 1 fail in each case.
Verified: 40/40; CONTINUITY_AUDIT and the vault clean; .claude/CLAUDE.md
17/3, guardians.md 8/1, canon-validator.ts 3/1, all unchanged; --changed
clean over 18 files.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
|
Round 18 actioned in The reported bug. Reproduced exactly as traced: Foundation is 174 Hz. A simile ate a real error. You put your finger on the actual inconsistency: owner selection requires Gate context because every Gate name is an ordinary English word, and then the check that can override an owner threw that requirement away. Fixed by reusing I also widened the window from The third gap, which is the interesting one. Before adding the fixture I checked whether the hijacker was still reachable at all after R16 replaced presence-based ownership with proximity. Disabled it outright: Green suite, unchanged corpus. So nothing tested the one case it exists for. It isn't dead, though — That's now a fixture. A heuristic no test can kill is one nobody can safely edit — and this PR has twice had a change to this function silently destroy detection, so an untested guard was going to be deleted eventually by someone reasoning exactly as I did five minutes earlier. Both fixtures checked against their own mutants rather than assumed:
On the duplication. Agreed, and I checked equivalence before collapsing rather than assuming it: On the process note — fair, and I'd rather it be a conscious choice than a default. The bundling was deliberate for the reason in the body: the research alone was documentation nothing reads. If you'd prefer it split, the clean seam is Verified: 40/40 fixtures. Still open for Frank: Starweave vs Shift for the 852 Hz Gate, the #98 sweep greenlight, and U3 as a payment ledger. Generated by Claude Code |
ReviewThis PR is unusually well self-documented (17 review rounds logged in the description, each with the bug found and the fixture that pins it), which made this an easier review than the diff size suggests. I focused on the actual code — Code quality —
|
…irings Review round 19. Two of the three observations were coverage gaps worth closing; both reproduced before acting. 1. checkTierBanner ran once per file outside the added-lines gate, so a file that was merely edited got re-warned about a banner the edit never touched — the "forced to fix everything you touch" behaviour this tool's header explicitly promises it does not have. WARN-only, so it never failed a build, but warning about untouched debt is how a linter earns being switched off. My first attempt to reproduce this came back clean and nearly refuted a correct finding: the fixture was at lore/, and the check only applies under .arcanea/lore/. Retested at the right path and it fired exactly as reported. The banner is a whole-file property, so it cannot be attributed to an added line the way every other check can. In ratchet mode it now applies to files the change CREATED: a new lore file must declare its tier, an existing one without a banner is pre-existing debt (#98), visible in a full audit but not on an unrelated edit. If the diff call fails the set stays null and every file is checked — over-warning is recoverable, silence is not. 2. The pairing check was table-only, so "Elara's godbeast is Kaelith" read clean. That matters more than a normal coverage gap because #98's completion test is a full-repo lore-lint run: a pairing written as a sentence would have survived the sweep and reported as swept. Added a narrow prose form — possessive, the literal word "godbeast", present-tense copula, and a named beast that is itself canonical. It does not reach past tense ("was Thessara" is a true sentence about a rename), unknown creatures, or questions. Checked against the whole repo before keeping it: zero hits across every file the linter selects, so it adds a guard without moving today's numbers. The third observation — the alias rewrite being global rather than targeted — is already pinned by the "alias appearing twice" fixture and needs no change. Mutants, each verified to turn the matching fixture red: removing the prose check, moving the banner back outside the ratchet, and disabling the banner check entirely. That last one matters — it means the ratchet fix cannot be quietly degraded into never checking at all. Verified: 43/43; CONTINUITY_AUDIT and the vault clean; .claude/CLAUDE.md 17/3, guardians.md 8/1, canon-validator.ts 3/1, all unchanged; --changed clean over 18 files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
|
Round 19 actioned in Note this review landed against 1. The tier banner sat outside the ratchet — correct, and I nearly refuted it with a bad test. My first reproduction came back clean, and for a moment that looked like a refutation. The fixture was at Exactly the "forced to fix everything you touch" behaviour the header promises this tool doesn't have. The banner is a whole-file property, so it can't be attributed to an added line the way every other check can — in ratchet mode it now applies to files the change created. A new lore file must declare its tier; an existing one without a banner is pre-existing debt (#98), visible in a full audit but not on an unrelated edit. If the diff call fails the set stays 2. Prose-form pairings — closed, because of what it does to #98. Confirmed: You flagged this as a reasonable trade-off "if #98 relies on this linter" — it does, and that's the part that changes the calculus. #98's completion test is a full-repo Added one narrow form: possessive + the literal word 3. The global alias rewrite — no change. You reached the same conclusion I did, and it's already pinned: the fixture "an alias appearing twice, once as an ordinary word, resolves safely" exists precisely because the rewrite is broad and the downstream guard is what makes it safe. Your instinct that this is the one spot leaning on a second layer rather than being narrow by construction is right; the comment there says as much, and the fixture is what keeps that honest. On the Mutants for the two new fixtures, each verified to fail:
That third one is the one I cared about: it means this fix can't be quietly degraded into never checking at all, which is the shape the previous three rounds kept finding. Verified: 43/43 fixtures. Still open for Frank, unchanged: Starweave vs Shift for the 852 Hz Gate, the #98 sweep greenlight, U3 as a payment ledger, and whether to split this PR at the tooling/prose seam. Generated by Claude Code |
…ts; keep Starweave ruling text Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GLQUyDFhK9taQ7mBLht4aD
ReviewThis PR is purely additive documentation/lore (14 new files, 0 deletions, no code): seven franchise research files, four cross-cutting pattern libraries, a synthesis doc, and two What holds up well
Issues found1. 2. 3. Inconsistent citation link formatting. Nothing here blocks merge on its own — #1 is the one I'd actually fix before staging further work on top of |
… adapters Two follow-ups on this branch. packages-ci.yml failed at setup on every single run, on both matrix legs, with "Unable to locate executable file: pnpm" — before it built or tested anything. setup-node@v5 defaults package-manager-cache to true and reads packageManager from package.json, so it shells out to pnpm to resolve the cache directory. This job ran setup-node BEFORE pnpm/action-setup, so pnpm was not yet on PATH. test.yml already had the two steps the right way round; this one did not. Steps swapped, and cache: 'pnpm' now stated explicitly rather than left to a default whose behaviour depends on a file elsewhere in the repo. This is the third appearance of the same setup-node@v5 default in this repo. lore-canon.yml hit it during #97 and fixed it with package-manager-cache: false because that job installs nothing. Here the job does install, so the fix is to give it pnpm first rather than to switch the cache off. Verified the job's own commands against the built tree: core + overlay-claude 296 pass 0 fail, cli integration 137 pass 0 fail. Second: restore CRLF line endings on packages/aios/src/adapters/index.ts. The file is CRLF on main. The scripted edit that replaced the four execute() bodies wrote it back as LF, so every one of its 122 lines showed as changed and a four-line semantic change read as a full-file rewrite. Caught in review. The diff for that file is now 27 insertions and 9 deletions, which is what actually changed. No behaviour difference — rebuilt and re-ran aios: 68 pass, 0 fail. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT
Summary
The prose half of the split. The tooling half — the
lore-release-gateskill, thecanon-evaluationrubric,lore-lint.mjs, its fixtures, andlore-canon.yml— shipped separately in #102 and is already onmain. This PR carries the two content layers that gate reads from: research (what the best-built worlds do) and applied patterns (that research re-cut by craft problem so it is usable at a desk).Everything is STAGING.
CANON_LOCKED.mdis untouched — it is not among the changed files. Promotion happens via/lock-decision, by Frank. IP discipline throughout: copy the architecture, never the bricks.Title and description corrected before merge. The previous version described this PR as shipping the gate, which was true before the split and false after. It ships 14 files, none of them the gate.
What lands (14 files)
Applied pattern libraries — the seven knowledgebases are organized by world, which is useless when you sit down to design a specific thing.
docs/worldbuilding/patterns/re-cuts the same research by craft problem:ARTIFACTS.md— 13 legendary-object patterns with reusable design rules, a minting checklist, 5 STAGING artifact slots left deliberately unnamed so the Registry coining procedure is not front-run, anti-patterns, IP red lines. Found that Tier 7 lists only nine Vael Crystals for ten Gates — Source has none, held consistently across four files, so it reads as deliberate rather than as an omission.MAGIC_MECHANISMS.md— the hard/soft spectrum made practical, 13 mechanisms, 7 failure modes, and the U3 pressure test below. Three candidate Arcanean-register names coined with etymologies (the Narrowing Oath, the Held Word, the Forswearing).ENCYCLOPEDIA_IA.md— 15 entity types with required fields and narrative sections, canon-tier representation, contribution flow, and the Name Ledger: identity as a stable ID with names as attributes, where a rename cannot be marked complete while any redirect-class occurrence is live. That structure makes the Thessara two-referent collision impossible rather than merely discouraged.LANGUAGE_CRAFT.md— 8 registers with original Arcanean examples, six compression techniques, phonaesthetic tests, and an honest audit of our own corpus: the recent texts are franchise-grade, the older numbered legends are a tier below, and "not just X but Y" appears 19+ times.Research layer — 7 per-world knowledgebases (Tolkien, Elder Scrolls, Final Fantasy, Marvel, HP/Fantastic Beasts, Warcraft, anime/modern-screen) plus
SYNTHESIS.mdwith the 12-dimension scorecard and the Ten Upgrades.Two vault-adjacent proposals —
.arcanea/lore/NAMING_REGISTRY.mdand.arcanea/lore/THESSARA.md. Both additive, both STAGING;THESSARA.mdis on the linter's superseded-name allowlist precisely because documenting a retired name is its purpose.Verification
lore-lint.mjs --changed --base origin/mainover all 14 files — 0 errors, 0 warnings. This is the gate from feat(lore): the canon gate — skill, rubric, linter, CI #102 run against the prose it was built for.mainat49d186f.packages/.CLI TestsandTest Summaryare known repo-wide debt — 178 failures of 1868 in thepackages/CLI suite, untouched here. feat(lore): Kingdom of Proof, The Unmarred, Arbor of First Light + Worldbuilding OS + Lore Atlas MCP spec #81, ci: disable the dead cross-repository sync #87, fix(canon): resolve unresolved merge-conflict markers in 33 files, canon-aware #96 and feat(lore): the canon gate — skill, rubric, linter, CI #102 all merged with them red.What building the gate turned up
Recorded here because these are findings about the corpus, not about this PR's files, and they outlive it:
.claude/CLAUDE.md— 17 errors + 3 warnings: names supersededAmaterasu, and carries the entire Gate frequency ladder shifted one position, in two duplicate tablespackages/os/src/canon-validator.ts— asserts both superseded godbeast names as current and normalizes misspellings toward them (one annotated// correct)packages/chrome-extension/tests/chrome-extension.test.mjs— both superseded names plus two shifted frequencies, asserted as expected test valuesCANON_LOCKED.md:74, which defines rank by Gates Open and is LOCKED; universal witnessed vows contradict the three unoathed Luminors inGATE_TOUCHED_UNDERGROUND.md:122. Repair recorded: reframe to a payment ledger — negotiated / imposed / refusedCANON_LOCKED.md; each guardian in four files;godbeasts/holds bothamaterasu.mdandsource.md, unlinked; nothing has a stable ID. This is the root cause of #98 rather than a symptom of itDeliberately not swept piecemeal: a half-swept repo, where the instruction file disagrees with the remaining stale files, is worse for the next agent than uniform drift. That wants one atomic change — issue #98, which now has a machine-checkable completion test.
Promotion gates (hard preconditions for any
/lock-decision)lore-lint.mjsrun coming back clean.Open canon question — Starweave or Shift at 852 Hz— resolved 2026-08-14: the Gate isStarweave. The vault always said so; the ~186 occurrences of "Shift" are drift, tracked under Repo-wide superseded-name sweep: Thessara→Vaelith, Amaterasu→Source #98.Type
Checklist
CANON_LOCKED.md— all additive STAGING; the vault is untouched and is now machine-enforced as the source of truthanytypes introducedpackages/overlap🤖 Generated with Claude Code
https://claude.ai/code/session_01AomsLJvgAwwzuWph4bD7YT