@zerwiz/ymir 0.1.16 → 0.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/.agents/config/app-repos.yaml +38 -0
  2. package/.claude/settings.json +31 -0
  3. package/.codex/hooks.json +43 -0
  4. package/.cursor/hooks.json +33 -0
  5. package/.pi/extensions/README.md +39 -0
  6. package/.pi/extensions/gna-pi-watch.ts +15 -0
  7. package/.pi/extensions/lib/ro-assistant-layout.ts +96 -0
  8. package/.pi/extensions/lib/ro-operational-user-layout.ts +145 -0
  9. package/.pi/extensions/lib/ro-visibility.ts +99 -0
  10. package/.pi/extensions/lib/ro-working-ship.ts +243 -0
  11. package/.pi/extensions/lib/rodd-operational-input.ts +62 -0
  12. package/.pi/extensions/lib/skuld-branch-dispatch.ts +252 -0
  13. package/.pi/extensions/lib/skuld-branch-model-picker.ts +77 -0
  14. package/.pi/extensions/lib/vordr-sessionstart-supervisor.mjs +48 -0
  15. package/.pi/extensions/ro.ts +11 -0
  16. package/.pi/extensions/skuld-branch-supervision.ts +11 -0
  17. package/.pi/extensions/syn-turnend-guard.ts +11 -0
  18. package/.pi/mcp.json +16 -0
  19. package/.pi/mcp.json.example +11 -0
  20. package/.pi/npm/.gitignore +2 -0
  21. package/.pi/settings.json +8 -0
  22. package/.pi/shared/extensions/gna-pi-watch.ts +750 -0
  23. package/.pi/shared/extensions/herdr-agent-state.ts +257 -0
  24. package/.pi/shared/extensions/open-editor.ts +509 -0
  25. package/.pi/shared/extensions/ro.ts +504 -0
  26. package/.pi/shared/extensions/skuld-branch-supervision.ts +1535 -0
  27. package/.pi/shared/extensions/syn-turnend-guard.ts +683 -0
  28. package/.pi/shared/extensions/todo.ts +133 -0
  29. package/.pi/shared/extensions/ymir-subagents.ts +287 -0
  30. package/.pi/shared/extensions/ymir-well.ts +130 -0
  31. package/CHANGELOG.md +23 -0
  32. package/assets/Ymir.md +4654 -0
  33. package/assets/healer.html +717 -0
  34. package/assets/icon-family/family-sheet.png +0 -0
  35. package/assets/icon-family/hlidskjalf.svg +1 -0
  36. package/assets/icon-family/sessrumnir.svg +1 -0
  37. package/assets/icon-family/smidja.svg +1 -0
  38. package/assets/icon-family/ymir.svg +1 -0
  39. package/assets/mimirswell.html +880 -0
  40. package/assets/mock/README.md +16 -0
  41. package/assets/mock/feeds.ts +175 -0
  42. package/assets/mock/mock.ts +408 -0
  43. package/assets/reference/docs/agent-control.md +122 -0
  44. package/assets/reference/docs/apodex/Appdex_as_Orchestrator_Planner_Reviewer_Assessment.md +176 -0
  45. package/assets/reference/docs/apodex/Final Report(1).md +198 -0
  46. package/assets/reference/docs/apodex/Final Report(2).md +54 -0
  47. package/assets/reference/docs/apodex/Final Report(3).md +40 -0
  48. package/assets/reference/docs/apodex/Final Report(4).md +234 -0
  49. package/assets/reference/docs/apodex/Final Report(5).md +13 -0
  50. package/assets/reference/docs/apodex/Final Report.md +82 -0
  51. package/assets/reference/docs/architecture.md +392 -0
  52. package/assets/reference/docs/arm-pretool-check.md +247 -0
  53. package/assets/reference/docs/calm-mode-feasibility.md +541 -0
  54. package/assets/reference/docs/calm.md +59 -0
  55. package/assets/reference/docs/captain-hold-lifecycle.md +96 -0
  56. package/assets/reference/docs/cd-guard.md +165 -0
  57. package/assets/reference/docs/cmux-backend.md +133 -0
  58. package/assets/reference/docs/codex-app-backend.md +57 -0
  59. package/assets/reference/docs/configuration.md +924 -0
  60. package/assets/reference/docs/documentation-audiences.json +468 -0
  61. package/assets/reference/docs/documentation-audiences.md +28 -0
  62. package/assets/reference/docs/examples/crew-dispatch.json +26 -0
  63. package/assets/reference/docs/examples/process-event-extension/file-signal.mjs +96 -0
  64. package/assets/reference/docs/examples/process-event-extension/firstmate-extension.json +15 -0
  65. package/assets/reference/docs/examples/watched-tools.json +24 -0
  66. package/assets/reference/docs/examples/wedge-alarm +22 -0
  67. package/assets/reference/docs/extension-bindings.md +237 -0
  68. package/assets/reference/docs/fm-test-isolation-proof.json +37 -0
  69. package/assets/reference/docs/fm-test-isolation-proof.md +149 -0
  70. package/assets/reference/docs/fm-test-portable-shards.md +118 -0
  71. package/assets/reference/docs/gitlab-merge-watch.md +275 -0
  72. package/assets/reference/docs/herdr-backend.md +346 -0
  73. package/assets/reference/docs/orca-backend.md +84 -0
  74. package/assets/reference/docs/pi-supervision-branch-poster.svg +125 -0
  75. package/assets/reference/docs/pi-supervision-branch.md +96 -0
  76. package/assets/reference/docs/plans/agentic-engineering-workflow.md +395 -0
  77. package/assets/reference/docs/plans/agentic-factory-implementation-plan.md +615 -0
  78. package/assets/reference/docs/plans/command-factory-enhancement-plan.md +420 -0
  79. package/assets/reference/docs/plans/phase-1-layer3-program-design.md +134 -0
  80. package/assets/reference/docs/plans/phase-2-vertical-slices.md +100 -0
  81. package/assets/reference/docs/plans/phase-3-measurable-goals.md +106 -0
  82. package/assets/reference/docs/plans/phase-4-context-budget.md +106 -0
  83. package/assets/reference/docs/plans/phase-5-pre-mortem-confidence.md +100 -0
  84. package/assets/reference/docs/plans/phase-6-incident-to-agent.md +109 -0
  85. package/assets/reference/docs/remote-secondmates.md +268 -0
  86. package/assets/reference/docs/scripts.md +146 -0
  87. package/assets/reference/docs/sessionstart-nudge.md +115 -0
  88. package/assets/reference/docs/subagent-guard.md +383 -0
  89. package/assets/reference/docs/supervision-protocols/claude.md +27 -0
  90. package/assets/reference/docs/supervision-protocols/codex.md +16 -0
  91. package/assets/reference/docs/supervision-protocols/cursor.md +31 -0
  92. package/assets/reference/docs/supervision-protocols/grok.md +39 -0
  93. package/assets/reference/docs/supervision-protocols/opencode.md +17 -0
  94. package/assets/reference/docs/supervision-protocols/pi.md +33 -0
  95. package/assets/reference/docs/supervision-protocols/unknown.md +13 -0
  96. package/assets/reference/docs/tmux-backend.md +115 -0
  97. package/assets/reference/docs/trace-context.md +117 -0
  98. package/assets/reference/docs/turnend-guard.md +170 -0
  99. package/assets/reference/docs/verification/dispatch-auth.md +204 -0
  100. package/assets/reference/docs/verification/muse.md +221 -0
  101. package/assets/reference/docs/verification/process-event-sources.md +208 -0
  102. package/assets/reference/docs/verification/public-followup.md +119 -0
  103. package/assets/reference/docs/verification/runtime-backends.md +1022 -0
  104. package/assets/reference/docs/verification/stow-memory.md +53 -0
  105. package/assets/reference/docs/verification/supervision.md +534 -0
  106. package/assets/reference/docs/verification/trace-context.md +31 -0
  107. package/assets/reference/docs/voice-relay.md +295 -0
  108. package/assets/reference/docs/watcher-continuity.md +119 -0
  109. package/assets/reference/docs/wedge-alarm.md +39 -0
  110. package/assets/reference/docs/zellij-backend.md +114 -0
  111. package/assets/reference/index.html +1172 -0
  112. package/assets/reference/skills/afk/SKILL.md +241 -0
  113. package/assets/reference/skills/ahoy/SKILL.md +56 -0
  114. package/assets/reference/skills/ask-user-authority/SKILL.md +56 -0
  115. package/assets/reference/skills/bearings/SKILL.md +161 -0
  116. package/assets/reference/skills/bearings/assets/board-template.html +731 -0
  117. package/assets/reference/skills/bootstrap-diagnostics/SKILL.md +68 -0
  118. package/assets/reference/skills/captain-hold-lifecycle/SKILL.md +54 -0
  119. package/assets/reference/skills/decision-hold-lifecycle/SKILL.md +15 -0
  120. package/assets/reference/skills/diagnostic-reasoning/SKILL.md +53 -0
  121. package/assets/reference/skills/firstmate-codexapp/SKILL.md +110 -0
  122. package/assets/reference/skills/firstmate-codexapp/agents/openai.yaml +4 -0
  123. package/assets/reference/skills/firstmate-coding-guidelines/SKILL.md +127 -0
  124. package/assets/reference/skills/firstmate-orca/SKILL.md +92 -0
  125. package/assets/reference/skills/fmx-respond/SKILL.md +283 -0
  126. package/assets/reference/skills/harness-adapters/SKILL.md +95 -0
  127. package/assets/reference/skills/harness-adapters/references/common/control-and-recovery.md +37 -0
  128. package/assets/reference/skills/harness-adapters/references/common/dispatch.md +32 -0
  129. package/assets/reference/skills/harness-adapters/references/common/model-and-effort.md +42 -0
  130. package/assets/reference/skills/harness-adapters/references/common/primary-hooks.md +40 -0
  131. package/assets/reference/skills/harness-adapters/references/harness/claude.md +55 -0
  132. package/assets/reference/skills/harness-adapters/references/harness/codex.md +43 -0
  133. package/assets/reference/skills/harness-adapters/references/harness/cursor.md +75 -0
  134. package/assets/reference/skills/harness-adapters/references/harness/grok.md +69 -0
  135. package/assets/reference/skills/harness-adapters/references/harness/kimi.md +51 -0
  136. package/assets/reference/skills/harness-adapters/references/harness/muse.md +70 -0
  137. package/assets/reference/skills/harness-adapters/references/harness/opencode.md +42 -0
  138. package/assets/reference/skills/harness-adapters/references/harness/pi.md +56 -0
  139. package/assets/reference/skills/process-event-sources/SKILL.md +137 -0
  140. package/assets/reference/skills/project-management/SKILL.md +92 -0
  141. package/assets/reference/skills/quota-array-dispatch/SKILL.md +131 -0
  142. package/assets/reference/skills/secondmate-provisioning/SKILL.md +254 -0
  143. package/assets/reference/skills/stow/SKILL.md +309 -0
  144. package/assets/reference/skills/stuck-crewmate-recovery/SKILL.md +54 -0
  145. package/assets/reference/skills/updatefirstmate/SKILL.md +64 -0
  146. package/assets/skills/README.md +5 -0
  147. package/assets/yggdrasil.html +649 -0
  148. package/assets/ymir-banner-01.png +0 -0
  149. package/assets/ymir-banner-02.png +0 -0
  150. package/assets/ymir-banner-03.png +0 -0
  151. package/assets/ymir-banner-04.png +0 -0
  152. package/assets/ymir-banner-05.png +0 -0
  153. package/assets/ymir-banner-06.png +0 -0
  154. package/assets/ymir-emblem-darksteel.svg +63 -0
  155. package/assets/ymir-emblem-forged.svg +55 -0
  156. package/assets/ymir-emblem-slate.svg +55 -0
  157. package/assets/ymir-mark-algiz-anvil.svg +9 -0
  158. package/assets/ymir-stave.svg +53 -0
  159. package/assets/ymir.html +563 -0
  160. package/bin/ymir-install.sh +6 -1
  161. package/data/learnings.md +33 -0
  162. package/data/local-models.md +34 -0
  163. package/data/operator.md +15 -0
  164. package/data/projects.md +28 -0
  165. package/data/realm.md +1 -0
  166. package/deploy/Containerfile +27 -0
  167. package/deploy/README.md +104 -0
  168. package/deploy/compose/compose.yaml +45 -0
  169. package/deploy/env.example +30 -0
  170. package/deploy/quadlet/ymir.container +57 -0
  171. package/package.json +10 -8
@@ -0,0 +1,563 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Ymir — The Creation</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Cormorant:wght@500;600&family=Newsreader:ital,opsz,wght@0,6..72,300..500;1,6..72,300..500&family=IBM+Plex+Mono:wght@300;400;500&family=Noto+Sans+Runic&display=swap" rel="stylesheet">
10
+ <style>
11
+ /* ============ tokens — obsidian, bone, bronze, blood ============ */
12
+ :root{
13
+ --bg:#0e0c09; --panel:#151209; --panel3:#14100b;
14
+ --line:#2b241a; --line-soft:#221d14;
15
+ --bone:#cfc3a9; --bone-dim:#9a8f75; --bone-faint:#6b6250;
16
+ --steel:#96a0a8; --steel-dim:#5f686e;
17
+ --bronze:#c9973f; --bronze-deep:#7d5f2a;
18
+ --blood:#7c3a30; --blood-lit:#c2584a;
19
+ --disp:'Cormorant',serif; --serif:'Newsreader',Georgia,serif;
20
+ --mono:'IBM Plex Mono',monospace; --run:'Noto Sans Runic','Segoe UI Historic',serif;
21
+ }
22
+ *{box-sizing:border-box;margin:0;padding:0}
23
+ body{background:var(--bg);color:var(--bone);font-family:var(--serif);
24
+ -webkit-font-smoothing:antialiased;overflow-x:hidden}
25
+ ::selection{background:#57411a;color:#f0e6cd}
26
+ :focus-visible{outline:1px solid var(--bronze);outline-offset:3px}
27
+
28
+ /* stone grain + vignette */
29
+ body::before{content:'';position:fixed;inset:0;z-index:60;pointer-events:none;opacity:.055;
30
+ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}
31
+ body::after{content:'';position:fixed;inset:0;z-index:59;pointer-events:none;
32
+ box-shadow:inset 0 0 170px 30px rgba(0,0,0,.5)}
33
+ #gap{position:fixed;inset:0;width:100%;height:100%;z-index:0}
34
+ main,footer{position:relative;z-index:2}
35
+
36
+ /* ============ topbar ============ */
37
+ .topbar{position:fixed;inset:0 0 auto 0;height:46px;display:flex;justify-content:space-between;align-items:center;
38
+ padding:0 clamp(1rem,3vw,2rem);z-index:50;background:rgba(13,11,8,.78);backdrop-filter:blur(10px);
39
+ border-bottom:1px solid var(--line-soft);font-family:var(--mono);font-size:.58rem;
40
+ letter-spacing:.3em;color:var(--bone-dim);text-transform:uppercase}
41
+ .topbar .rn{color:var(--bronze);margin-right:.6em;font-size:.85rem}
42
+ main{padding-top:46px}
43
+
44
+ /* ============ stage ============ */
45
+ .stage{min-height:calc(100svh - 46px);display:flex;align-items:center;justify-content:center;
46
+ position:relative;padding:74px 1rem 2rem;animation:fadeUp 1s .05s both}
47
+ .scenewrap{width:min(94vw, calc(78svh * .628), 600px);aspect-ratio:760/1210}
48
+ #scene{width:100%;height:100%;display:block}
49
+ @keyframes fadeUp{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
50
+
51
+ .anno{position:absolute;top:96px;max-width:250px;line-height:1.95;font-size:.92rem;z-index:3}
52
+ .anno-l{left:clamp(1rem,4vw,3.2rem);font-style:italic;color:var(--bone-faint)}
53
+ .anno-r{right:clamp(1rem,4vw,3.2rem);text-align:right;font-family:var(--mono);font-size:.56rem;
54
+ letter-spacing:.26em;color:var(--steel-dim);text-transform:uppercase;line-height:2.5}
55
+ @media(max-width:900px){.anno{display:none}}
56
+
57
+ /* ============ SVG — the carving ============ */
58
+ #scene text{font-family:var(--mono);user-select:none}
59
+ g[data-part]{cursor:pointer;outline:none}
60
+ .wgroup{transition:opacity .45s}
61
+ #scene.focus g.wgroup:not(.lit){opacity:.5}
62
+
63
+ /* world defaults (slightly cooler stone than the body) */
64
+ .wgroup .gs{stroke:#4a4232;fill:#12100b;transition:stroke .4s,fill .4s}
65
+ .wgroup .wvault{fill:none;stroke-width:2}
66
+ .wgroup .star{fill:#4f4530;stroke:none;animation:tw 4.5s ease-in-out infinite}
67
+ .wgroup .tree{fill:none;stroke:#4a4232;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;transition:stroke .4s}
68
+ .wgroup .wave{fill:none;stroke:#3b3222;stroke-width:1.8;transition:stroke .4s}
69
+ .wgroup .gline{fill:none;stroke:#4a4232;stroke-width:2.5}
70
+ .wgroup .hatch{fill:none;stroke:#2c251a;stroke-width:1.2;transition:stroke .4s}
71
+ .lab{font-size:17px;letter-spacing:4.2px;fill:#6f6650;opacity:.9;paint-order:stroke;
72
+ stroke:#0e0c09;stroke-width:5;stroke-linejoin:round;transition:fill .4s}
73
+ @keyframes tw{50%{opacity:.25}}
74
+
75
+ /* body defaults */
76
+ .bpart .gs{stroke:#4a3d2a;fill:#161009;stroke-width:2;transition:stroke .4s,fill .4s}
77
+ .bpart .arm-o{fill:none;stroke:#4a3d2a;stroke-width:50;stroke-linecap:round;transition:stroke .4s}
78
+ .bpart .arm-i{fill:none;stroke:#161009;stroke-width:41;stroke-linecap:round}
79
+ .bpart .leg-o{fill:none;stroke:#4a3d2a;stroke-width:46;stroke-linecap:round;transition:stroke .4s}
80
+ .bpart .leg-i{fill:none;stroke:#161009;stroke-width:37;stroke-linecap:round}
81
+ .bpart .det{fill:none;stroke:#2e261a;stroke-linecap:round;transition:stroke .4s}
82
+ .chest{font-family:var(--run);font-size:38px;fill:#6d5426;transition:fill .4s;animation:rp 6.8s ease-in-out infinite}
83
+ @keyframes rp{0%,100%{opacity:.45}50%{opacity:.85}}
84
+
85
+ /* the blood keeps its own color — a rune apart */
86
+ #bloodG .gs{fill:none;stroke:#7c3a30;stroke-width:5.5;stroke-linecap:round;stroke-linejoin:round;transition:stroke .4s}
87
+ #bloodG .bl{fill:#7c3a30;stroke:none;transition:fill .4s}
88
+ .bflow{fill:none;stroke:#e08a6a;stroke-width:2.6;stroke-dasharray:5 11;opacity:0;transition:opacity .4s}
89
+ .hit{fill:none;stroke:#000;stroke-opacity:0}
90
+
91
+ /* lit states */
92
+ .wgroup.lit .gs{stroke:var(--bronze);fill:#231b10}
93
+ .wgroup.lit .tree{stroke:var(--bronze)}
94
+ .wgroup.lit .wave{stroke:var(--bronze)}
95
+ .wgroup.lit .hatch{stroke:#8a6a34}
96
+ .wgroup.lit .star{fill:var(--bronze)}
97
+ .wgroup.lit .lab{fill:var(--bone)}
98
+ .bpart.lit .gs{stroke:var(--bronze)}
99
+ .bpart.lit .fillable{fill:#241b0e}
100
+ .bpart.lit .arm-o{stroke:var(--bronze)}
101
+ .bpart.lit .leg-o{stroke:var(--bronze)}
102
+ .bpart.lit .det{stroke:var(--bronze)}
103
+ .bpart.lit .chest{fill:var(--bronze)}
104
+ #bloodG.lit .gs{stroke:var(--blood-lit)}
105
+ #bloodG.lit .bl{fill:var(--blood-lit)}
106
+ #bloodG.lit .bflow{opacity:.9;animation:march2 1s linear infinite}
107
+
108
+ /* connectors — hidden until the part is lit */
109
+ .lnk{fill:none;stroke:var(--bronze);stroke-width:1.6;stroke-dasharray:3 8;opacity:0;transition:opacity .4s}
110
+ .lnk.lit{opacity:.75;animation:march 1.1s linear infinite}
111
+ @keyframes march{to{stroke-dashoffset:-22}}
112
+ @keyframes march2{to{stroke-dashoffset:-32}}
113
+
114
+ /* the giant breathes — barely */
115
+ #figure{transform-box:fill-box;transform-origin:50% 100%;animation:breathe 6.8s ease-in-out infinite}
116
+ @keyframes breathe{50%{transform:scaleY(1.005) translateY(-2px)}}
117
+
118
+ /* ============ caption + plinth ============ */
119
+ .plate{max-width:780px;margin:0 auto;padding:0 1.4rem 3rem;animation:fadeUp 1s .35s both}
120
+ .cap{text-align:center;font-family:var(--mono);font-size:.62rem;letter-spacing:.24em;
121
+ text-transform:uppercase;color:var(--bone-faint);line-height:2.6}
122
+ .cap button{background:none;border:none;cursor:pointer;font:inherit;color:var(--bone-dim);
123
+ letter-spacing:inherit;padding:.2em .1em;border-bottom:1px solid transparent;
124
+ transition:color .25s,border-color .25s}
125
+ .cap button:hover,.cap button.on{color:var(--bronze);border-bottom-color:var(--bronze-deep)}
126
+ .cap i{font-style:normal;color:var(--bone-faint);margin:0 .3em}
127
+
128
+ .carved{background:var(--panel3);border:1px solid var(--line);
129
+ box-shadow:inset 0 1px 0 rgba(255,244,214,.03),inset 0 -1px 0 rgba(0,0,0,.5),0 2px 16px rgba(0,0,0,.35)}
130
+ .plinth{margin-top:1.7rem;padding:1.7rem clamp(1.2rem,4vw,2.1rem) 1.9rem}
131
+ .pl-head{display:flex;align-items:center;gap:1.3rem;padding-bottom:1.2rem;border-bottom:1px solid var(--line)}
132
+ #pRune{font-family:var(--run);font-size:2.6rem;color:var(--bronze);line-height:1}
133
+ .pl-k{font-family:var(--mono);font-size:.56rem;letter-spacing:.34em;color:var(--steel-dim);text-transform:uppercase}
134
+ #pName{font-family:var(--disp);font-weight:600;font-size:1.3rem;letter-spacing:.14em;color:var(--bone);margin-top:.35rem}
135
+ .prow{display:grid;grid-template-columns:5.4rem 1fr;gap:1.2rem;padding:1.05rem 0;
136
+ border-bottom:1px dashed var(--line-soft)}
137
+ .prow:last-of-type{border-bottom:none}
138
+ .ptag{font-family:var(--mono);font-size:.56rem;letter-spacing:.26em;color:var(--bronze);
139
+ text-transform:uppercase;padding-top:.4rem}
140
+ .pmyth{font-family:var(--serif);font-style:italic;font-size:1.07rem;color:var(--bone);line-height:1.75}
141
+ .pymir{font-family:var(--mono);font-size:.72rem;color:var(--steel);line-height:1.85}
142
+ .pl-head,.prow{transition:opacity .18s}
143
+ .plinth.swap .pl-head,.plinth.swap .prow{opacity:.06}
144
+ @media(max-width:560px){.prow{grid-template-columns:1fr;gap:.3rem}.ptag{padding-top:0}}
145
+
146
+ .pl-actions{text-align:center;margin-top:1.9rem}
147
+ .btn-carv{font-family:var(--mono);font-size:.64rem;letter-spacing:.32em;text-indent:.32em;text-transform:uppercase;
148
+ color:var(--bone);background:var(--panel);border:1px solid var(--line);padding:.95rem 1.9rem;cursor:pointer;
149
+ box-shadow:inset 0 1px 0 rgba(255,244,214,.05),inset 0 -1px 0 rgba(0,0,0,.55),0 2px 10px rgba(0,0,0,.4);
150
+ transition:border-color .3s,color .3s,transform .1s}
151
+ .btn-carv .rn{color:var(--bronze);margin-right:.7em;font-size:.85rem;letter-spacing:0;text-indent:0}
152
+ .btn-carv:hover{border-color:var(--bronze-deep);color:#e6dcc2}
153
+ .btn-carv:active{transform:translateY(1px)}
154
+ .btn-carv.busy{opacity:.55;pointer-events:none}
155
+
156
+ /* ============ footer ============ */
157
+ footer{border-top:1px solid var(--line);padding:3.6rem 1.5rem 4rem;text-align:center;animation:fadeUp 1s .55s both}
158
+ .frule{display:flex;align-items:center;gap:1.4rem;max-width:640px;margin:0 auto 2.8rem}
159
+ .frule::before,.frule::after{content:'';flex:1;height:1px;background:var(--line-soft)}
160
+ .frule span{font-family:var(--run);font-size:.7rem;letter-spacing:.42em;color:var(--bone-faint);white-space:nowrap}
161
+ .f-big{font-family:var(--disp);font-weight:600;font-size:clamp(1.15rem,2.6vw,1.65rem);
162
+ letter-spacing:.14em;color:var(--bone);text-shadow:0 -1px 0 rgba(0,0,0,.8)}
163
+ .f-mono{font-family:var(--mono);font-size:.56rem;letter-spacing:.3em;color:var(--steel-dim);
164
+ margin-top:1.7rem;text-transform:uppercase;line-height:2.3}
165
+ .f-repo{font-family:var(--mono);font-size:.58rem;color:var(--bone-faint);letter-spacing:.16em;margin-top:1.2rem}
166
+
167
+ @media (prefers-reduced-motion:reduce){
168
+ *,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important}
169
+ }
170
+ </style>
171
+ </head>
172
+ <body>
173
+
174
+ <div class="topbar">
175
+ <span><span class="rn">ᚢ</span>YMIR · THE CREATION</span>
176
+ <span>carved, not skinned</span>
177
+ </div>
178
+
179
+ <canvas id="gap" aria-hidden="true"></canvas>
180
+
181
+ <main>
182
+ <!-- ============ THE STANDING GIANT ============ -->
183
+ <section class="stage">
184
+ <p class="anno anno-l">Ymir (Aurgelmir) — the primordial giant, the ancestor of
185
+ everything. The gods slew him and made the world from his body: flesh, blood,
186
+ bones, hair, skull.</p>
187
+ <p class="anno anno-r">substrate — one repo<br>one machine<br>all realms carved from it</p>
188
+
189
+ <div class="scenewrap">
190
+ <svg id="scene" viewBox="0 0 760 1210" role="group" aria-label="The standing giant Ymir, and the world made from his body">
191
+
192
+ <defs>
193
+ <radialGradient id="halo" cx="50%" cy="50%" r="50%">
194
+ <stop offset="0" stop-color="#20180e" stop-opacity=".5"/>
195
+ <stop offset="1" stop-color="#20180e" stop-opacity="0"/>
196
+ </radialGradient>
197
+ </defs>
198
+ <ellipse cx="380" cy="600" rx="330" ry="560" fill="url(#halo)" pointer-events="none"/>
199
+
200
+ <!-- THE SKY (from the skull) -->
201
+ <g id="skyG" class="wgroup" data-part="skull" tabindex="0" role="button"
202
+ aria-label="the sky — made from his skull">
203
+ <path class="hit" d="M92 202 Q380 -96 668 202 Z" pointer-events="all"/>
204
+ <path class="gs wvault" d="M92 202 Q380 -96 668 202"/>
205
+ <g id="dwarfMarks"></g>
206
+ <g id="starG"></g>
207
+ <text class="lab" x="380" y="34" text-anchor="middle">THE SKY</text>
208
+ </g>
209
+
210
+ <!-- THE MOUNTAINS (from the bones) -->
211
+ <g id="mtnG" class="wgroup" data-part="bones" tabindex="0" role="button"
212
+ aria-label="the mountains — made from his bones">
213
+ <path class="gs fillable" d="M468 1050 L508 936 L534 970 L568 874 L598 928 L634 844 L664 900 L698 868 L732 948 L746 1050 Z"/>
214
+ <path class="gs" d="M568 874 L578 902 M634 844 L644 874 M698 868 L706 896" fill="none"/>
215
+ <path class="gs fillable" d="M28 1050 L76 948 L104 984 L140 918 L176 976 L208 936 L232 1050 Z"/>
216
+ <path class="gs" d="M140 918 L148 944" fill="none"/>
217
+ <text class="lab" x="634" y="812" text-anchor="middle">THE MOUNTAINS</text>
218
+ </g>
219
+
220
+ <!-- THE FORESTS (from the hair) -->
221
+ <g id="forG" class="wgroup" data-part="hair" tabindex="0" role="button"
222
+ aria-label="the forests — made from his hair">
223
+ <g id="trees"></g>
224
+ <rect class="hit" x="56" y="896" width="192" height="154" pointer-events="all"/>
225
+ <rect class="hit" x="660" y="952" width="90" height="98" pointer-events="all"/>
226
+ <text class="lab" x="162" y="906" text-anchor="middle">THE FORESTS</text>
227
+ </g>
228
+
229
+ <!-- THE EARTH (from the flesh) -->
230
+ <g id="earthG" class="wgroup" data-part="flesh" tabindex="0" role="button"
231
+ aria-label="the earth — made from his flesh">
232
+ <rect class="hit" x="42" y="1044" width="676" height="46" pointer-events="all"/>
233
+ <path class="gline" d="M40 1050 L720 1050"/>
234
+ <path id="hatch" class="hatch" d=""/>
235
+ <path class="hatch" d="M56 1088 L704 1088" style="stroke-width:1.2"/>
236
+ <text class="lab" x="150" y="1076" text-anchor="middle">THE EARTH</text>
237
+ </g>
238
+
239
+ <!-- THE SEAS (from the blood) -->
240
+ <g id="seaG" class="wgroup" data-part="blood" tabindex="0" role="button"
241
+ aria-label="the seas — made from his blood">
242
+ <rect class="hit" x="56" y="1094" width="648" height="62" pointer-events="all"/>
243
+ <g id="waves"></g>
244
+ <text class="lab" x="380" y="1182" text-anchor="middle">THE SEAS</text>
245
+ </g>
246
+
247
+ <!-- ============ THE GIANT, STANDING ============ -->
248
+ <g id="figure">
249
+
250
+ <!-- bones : the legs he stands on -->
251
+ <g id="bonesG" class="bpart" data-part="bones" tabindex="0" role="button"
252
+ aria-label="the bones — they became the mountains">
253
+ <path class="leg-o" d="M324 692 C314 756 312 818 314 878"/>
254
+ <path class="leg-i" d="M324 692 C314 756 312 818 314 878"/>
255
+ <path class="leg-o" d="M436 692 C446 756 448 818 446 878"/>
256
+ <path class="leg-i" d="M436 692 C446 756 448 818 446 878"/>
257
+ <path class="leg-o" d="M312 894 C310 940 308 988 306 1026" style="stroke-width:38"/>
258
+ <path class="leg-i" d="M312 894 C310 940 308 988 306 1026" style="stroke-width:30"/>
259
+ <path class="leg-o" d="M448 894 C450 940 452 988 454 1026" style="stroke-width:38"/>
260
+ <path class="leg-i" d="M448 894 C450 940 452 988 454 1026" style="stroke-width:30"/>
261
+ <circle class="gs" cx="324" cy="694" r="11"/>
262
+ <circle class="gs" cx="436" cy="694" r="11"/>
263
+ <path class="gs" d="M314 870 L327 884 L314 898 L301 884 Z"/>
264
+ <path class="gs" d="M446 870 L459 884 L446 898 L433 884 Z"/>
265
+ <circle class="gs" cx="306" cy="1030" r="8"/>
266
+ <circle class="gs" cx="454" cy="1030" r="8"/>
267
+ <path class="gs" d="M344 1050 L346 1028 L306 1016 L268 1024 L258 1050 Z"/>
268
+ <path class="gs" d="M416 1050 L414 1028 L454 1016 L492 1024 L502 1050 Z"/>
269
+ </g>
270
+
271
+ <!-- flesh : the mighty mass of him -->
272
+ <g id="fleshG" class="bpart" data-part="flesh" tabindex="0" role="button"
273
+ aria-label="the flesh — it became the earth">
274
+ <path class="gs" d="M354 268 L406 268 L412 302 L348 302 Z"/>
275
+ <path class="gs fillable" d="M232 336 L300 300 L350 294 L410 294 L460 300 L528 336 L536 372
276
+ C526 452 508 532 486 612 C478 646 458 664 430 672 L330 672 C302 664 282 646 274 612
277
+ C252 532 234 452 224 372 Z"/>
278
+ <path class="arm-o" d="M250 358 C202 390 174 432 162 480 C150 528 140 570 134 610"/>
279
+ <path class="arm-i" d="M250 358 C202 390 174 432 162 480 C150 528 140 570 134 610"/>
280
+ <path class="arm-o" d="M510 358 C558 390 586 432 598 480 C610 528 620 570 626 610"/>
281
+ <path class="arm-i" d="M510 358 C558 390 586 432 598 480 C610 528 620 570 626 610"/>
282
+ <path class="gs" d="M100 616 L158 606 L172 650 L152 674 L104 670 Z"/>
283
+ <path class="gs" d="M660 616 L602 606 L588 650 L608 674 L656 670 Z"/>
284
+ <path class="det" d="M118 640 L146 636 M642 640 L614 636" stroke-width="2"/>
285
+ <path class="det" d="M262 374 C298 358 338 356 372 368 M498 374 C462 358 422 356 388 368" stroke-width="2"/>
286
+ <path class="det" d="M318 462 C350 474 410 474 442 462 M310 542 C346 558 414 558 450 542" stroke-width="2"/>
287
+ <text class="chest" x="380" y="434" text-anchor="middle">ᚢ</text>
288
+ </g>
289
+
290
+ <!-- hair : the wild mane -->
291
+ <g id="hairG" class="bpart" data-part="hair" tabindex="0" role="button"
292
+ aria-label="the hair — it became the forests">
293
+ <path class="gs fillable" d="M266 175 L278 146 L339 156 L340 94 L380 141 L420 94 L421 156 L482 146
294
+ L494 175 L474 210 L452 222 L308 222 L286 210 Z"/>
295
+ <path class="gs fillable" d="M280 240 L312 208 L298 268 L320 324 L294 374 L266 318 L274 252 Z"/>
296
+ <path class="gs fillable" d="M480 240 L448 208 L462 268 L440 324 L466 374 L494 318 L486 252 Z"/>
297
+ </g>
298
+
299
+ <!-- skull : the head held high -->
300
+ <g id="skullG" class="bpart" data-part="skull" tabindex="0" role="button"
301
+ aria-label="the skull — it became the sky">
302
+ <path class="gs fillable" d="M336 150 L424 150 L442 188 L436 238 L412 268 L348 268 L324 238 L320 188 Z"/>
303
+ <path class="det" d="M380 152 L380 194" stroke-width="1"/>
304
+ <path class="det" d="M340 194 L420 194" stroke-width="2"/>
305
+ <path class="det" d="M350 210 L376 206 M384 206 L410 210" stroke-width="4.5"/>
306
+ <path class="gs" d="M380 206 L372 244 L388 244 Z"/>
307
+ <path class="det" d="M360 258 L400 258" stroke-width="3"/>
308
+ </g>
309
+
310
+ <!-- blood : the running vein of him -->
311
+ <g id="bloodG" class="bpart" data-part="blood" tabindex="0" role="button"
312
+ aria-label="the blood — it ran out and became the seas">
313
+ <path class="hit" stroke-width="46" pointer-events="stroke"
314
+ d="M470 474 C486 500 488 536 478 574 C466 616 448 640 452 678 C458 716 480 740 484 786
315
+ C488 834 476 884 482 934 C488 990 506 1012 512 1046 C530 1058 568 1062 608 1068
316
+ C648 1074 670 1082 690 1096"/>
317
+ <path class="gs"
318
+ d="M470 474 C486 500 488 536 478 574 C466 616 448 640 452 678 C458 716 480 740 484 786
319
+ C488 834 476 884 482 934 C488 990 506 1012 512 1046 C530 1058 568 1062 608 1068
320
+ C648 1074 670 1082 690 1096"/>
321
+ <path class="bl" d="M460 460 L482 470 L476 488 L456 480 Z"/>
322
+ <circle class="bl" cx="482" cy="560" r="3"/>
323
+ <circle class="bl" cx="484" cy="764" r="2.5"/>
324
+ <circle class="bl" cx="478" cy="886" r="3"/>
325
+ <ellipse class="bl" cx="566" cy="1054" rx="30" ry="5"/>
326
+ <path class="bflow"
327
+ d="M470 474 C486 500 488 536 478 574 C466 616 448 640 452 678 C458 716 480 740 484 786
328
+ C488 834 476 884 482 934 C488 990 506 1012 512 1046 C530 1058 568 1062 608 1068
329
+ C648 1074 670 1082 690 1096"/>
330
+ </g>
331
+ </g>
332
+
333
+ <!-- connectors : part → world -->
334
+ <g id="links">
335
+ <path class="lnk" data-part="skull" d="M400 154 C424 118 432 90 426 58"/>
336
+ <path class="lnk" data-part="hair" d="M270 354 C180 380 108 470 88 588 C72 700 88 820 108 878"/>
337
+ <path class="lnk" data-part="flesh" d="M380 676 L380 1040"/>
338
+ <path class="lnk" data-part="bones" d="M462 876 C502 866 534 884 560 926"/>
339
+ </g>
340
+ </svg>
341
+ </div>
342
+ </section>
343
+
344
+ <!-- ============ caption + the plinth ============ -->
345
+ <section class="plate">
346
+ <p class="cap">hover or touch the carving —
347
+ <button data-p="skull">skull</button><i>·</i>
348
+ <button data-p="hair">hair</button><i>·</i>
349
+ <button data-p="flesh">flesh</button><i>·</i>
350
+ <button data-p="bones">bones</button><i>·</i>
351
+ <button data-p="blood">blood</button>
352
+ </p>
353
+
354
+ <div class="plinth carved" id="plinth" aria-live="polite">
355
+ <div class="pl-head">
356
+ <span id="pRune" class="rn">ᚢ</span>
357
+ <div>
358
+ <p class="pl-k">The carving speaks</p>
359
+ <p id="pName">the giant, whole</p>
360
+ </div>
361
+ </div>
362
+ <div class="prow">
363
+ <span class="ptag">The myth</span>
364
+ <p class="pmyth" id="pMyth">Run your hand over the giant — every part of him became a part of the world.</p>
365
+ </div>
366
+ <div class="prow">
367
+ <span class="ptag">In Ymir</span>
368
+ <p class="pymir" id="pYmir">The same body is the substrate: one repo, one machine, all realms carved from it.</p>
369
+ </div>
370
+ </div>
371
+
372
+ <div class="pl-actions">
373
+ <button class="btn-carv" id="tourBtn"><span class="rn">ᛏ</span><span id="tourLabel">carve the worlds</span></button>
374
+ </div>
375
+ </section>
376
+ </main>
377
+
378
+ <footer>
379
+ <div class="frule"><span>ᚠ ᚢ ᚦ ᚨ ᚱ ᚲ ᚷ ᚹ ᚺ ᚾ ᛁ ᛇ ᛈ ᛉ ᛊ ᛏ ᛒ ᛖ ᛗ ᛚ ᛜ ᛞ ᛟ</span></div>
380
+ <p class="f-big">The giant stands — and from it, the worlds are carved.</p>
381
+ <p class="f-mono">light metal first · rut steel after</p>
382
+ <p class="f-repo">zerwiz/ymir · docs/design.md · the lore v2 · §I</p>
383
+ </footer>
384
+
385
+ <script>
386
+ (function(){
387
+ 'use strict';
388
+ const $ = s => document.querySelector(s);
389
+ const $$ = s => Array.from(document.querySelectorAll(s));
390
+ const NS = 'http://www.w3.org/2000/svg';
391
+ const RM = matchMedia('(prefers-reduced-motion: reduce)').matches;
392
+
393
+ /* ---------- generated texture: stars, dwarves, hatch, waves, trees ---------- */
394
+ const STARS = [[150,120],[210,78],[258,150],[176,182],[506,150],[552,80],[612,124],[588,184]];
395
+ STARS.forEach(([x,y],i)=>{
396
+ const s = 5 + (i % 3);
397
+ const d = `M${x} ${y-s} L${x+s*.33} ${y-s*.33} L${x+s} ${y} L${x+s*.33} ${y+s*.33}
398
+ L${x} ${y+s} L${x-s*.33} ${y+s*.33} L${x-s} ${y} L${x-s*.33} ${y-s*.33} Z`;
399
+ const p = document.createElementNS(NS,'path');
400
+ p.setAttribute('d', d.replace(/\s+/g,' '));
401
+ p.setAttribute('class','star');
402
+ p.style.animationDelay = (-(i*0.85)) + 's';
403
+ p.style.animationDuration = (3.4 + (i%4)*.9) + 's';
404
+ $('#starG').appendChild(p);
405
+ });
406
+ /* the four dwarves holding the sky at its corners */
407
+ [[178,126],[236,90],[524,90],[582,126]].forEach(([x,y])=>{
408
+ const p = document.createElementNS(NS,'path');
409
+ p.setAttribute('d', `M${x} ${y-5} L${x+5} ${y} L${x} ${y+5} L${x-5} ${y} Z`);
410
+ p.setAttribute('class','gs');
411
+ $('#dwarfMarks').appendChild(p);
412
+ });
413
+ /* earth hatching */
414
+ (()=>{ let d='';
415
+ for(let x=64; x<=712; x+=26) d += `M${x} 1053 l-9 11 `;
416
+ $('#hatch').setAttribute('d', d);
417
+ })();
418
+ /* the seas */
419
+ function wave(y, x0, x1, dir){
420
+ let d = `M${x0} ${y} Q${x0+20} ${y-9*dir} ${x0+40} ${y}`;
421
+ for(let x=x0+80; x<=x1; x+=40) d += ` T${x} ${y}`;
422
+ return d;
423
+ }
424
+ [[1102,60,700,1],[1126,80,680,-1],[1150,100,660,1]].forEach(([y,a,b,dir])=>{
425
+ const p = document.createElementNS(NS,'path');
426
+ p.setAttribute('d', wave(y,a,b,dir));
427
+ p.setAttribute('class','wave');
428
+ $('#waves').appendChild(p);
429
+ });
430
+ /* the forests */
431
+ function tree(x, b, h){
432
+ const w = h*0.42;
433
+ return `M${x-w} ${b} L${x} ${b-h} L${x+w} ${b}` +
434
+ `M${x-w*.72} ${b-h*.34} L${x} ${b-h*.78} L${x+w*.72} ${b-h*.34}` +
435
+ `M${x-w*.45} ${b-h*.6} L${x} ${b-h} L${x+w*.45} ${b-h*.6}`;
436
+ }
437
+ [[88,1050,90],[126,1050,122],[168,1050,98],[208,1050,76],[688,1050,88],[718,1050,66]]
438
+ .forEach(([x,b,h])=>{
439
+ const p = document.createElementNS(NS,'path');
440
+ p.setAttribute('d', tree(x,b,h));
441
+ p.setAttribute('class','tree');
442
+ $('#trees').appendChild(p);
443
+ });
444
+
445
+ /* ---------- the carving speaks ---------- */
446
+ const PARTS = {
447
+ skull:{ rune:'ᚼ', name:'the skull',
448
+ myth:'His skull was lifted up and made the sky — held at its corners by four dwarves.',
449
+ ymir:'The ceiling every hall lives under — Hlidskjalf watches all realms from beneath it.'},
450
+ hair:{ rune:'ᛇ', name:'the hair',
451
+ myth:'His hair became the forests.',
452
+ ymir:'The worktrees of Yggdrasil — branching, parallel, alive without collision.'},
453
+ flesh:{ rune:'ᛜ', name:'the flesh',
454
+ myth:'His flesh became the earth — the ground every hall stands on.',
455
+ ymir:'The substrate itself — one repo, one machine; every realm of work is carved from it.'},
456
+ bones:{ rune:'ᛒ', name:'the bones',
457
+ myth:'His bones became the mountains — the load-bearing heights.',
458
+ ymir:'The seven gates — the structure every realm hangs from.'},
459
+ blood:{ rune:'ᛚ', name:'the blood',
460
+ myth:'His blood ran out and became the seas.',
461
+ ymir:'The event stream — Ratatoskr\u2019s words carried between every realm.'}
462
+ };
463
+
464
+ const plinth = $('#plinth');
465
+ let swapT = null, pinned = null, touring = false;
466
+
467
+ function light(p){
468
+ $$('g[data-part], .lnk').forEach(el =>
469
+ el.classList.toggle('lit', !!p && el.dataset.part === p));
470
+ $('#scene').classList.toggle('focus', !!p);
471
+ $$('.cap button').forEach(b => b.classList.toggle('on', !!p && b.dataset.p === p));
472
+ plinth.classList.add('swap');
473
+ clearTimeout(swapT);
474
+ swapT = setTimeout(() => {
475
+ $('#pRune').textContent = p ? PARTS[p].rune : 'ᚢ';
476
+ $('#pName').textContent = p ? PARTS[p].name : 'the giant, whole';
477
+ $('#pMyth').textContent = p ? PARTS[p].myth :
478
+ 'Run your hand over the giant — every part of him became a part of the world.';
479
+ $('#pYmir').textContent = p ? PARTS[p].ymir :
480
+ 'The same body is the substrate: one repo, one machine, all realms carved from it.';
481
+ plinth.classList.remove('swap');
482
+ }, 170);
483
+ }
484
+
485
+ function hook(el, p){
486
+ el.addEventListener('mouseenter', () => { if(!touring) light(p); });
487
+ el.addEventListener('mouseleave', () => { if(!touring) light(pinned); });
488
+ const act = () => { pinned = (pinned === p) ? null : p; light(pinned); };
489
+ el.addEventListener('click', act);
490
+ el.addEventListener('keydown', e => {
491
+ if(e.key === 'Enter' || e.key === ' '){ e.preventDefault(); act(); }
492
+ });
493
+ el.addEventListener('focus', () => { if(!touring) light(p); });
494
+ el.addEventListener('blur', () => { if(!touring) light(pinned); });
495
+ }
496
+ $$('#scene g[data-part]').forEach(g => hook(g, g.dataset.part));
497
+ $$('.cap button').forEach(b => hook(b, b.dataset.p));
498
+
499
+ /* ---------- the carving tour ---------- */
500
+ $('#tourBtn').addEventListener('click', () => {
501
+ if(touring) return;
502
+ touring = true; pinned = null;
503
+ const btn = $('#tourBtn');
504
+ btn.classList.add('busy');
505
+ $('#tourLabel').textContent = 'the hammer falls';
506
+ const order = ['skull','hair','flesh','bones','blood'];
507
+ let i = 0;
508
+ (function step(){
509
+ if(i < order.length){ light(order[i++]); setTimeout(step, 2150); }
510
+ else{
511
+ light(null); touring = false;
512
+ btn.classList.remove('busy');
513
+ $('#tourLabel').textContent = 'carve the worlds';
514
+ }
515
+ })();
516
+ });
517
+
518
+ /* ---------- ambience: cold mist meets embers ---------- */
519
+ (function(){
520
+ const cv = $('#gap'), ctx = cv.getContext('2d');
521
+ const dpr = Math.min(window.devicePixelRatio || 1, 2);
522
+ let W = 0, H = 0, mist = [], embers = [], t = 0;
523
+ function size(){
524
+ W = innerWidth; H = innerHeight;
525
+ cv.width = W*dpr; cv.height = H*dpr;
526
+ ctx.setTransform(dpr,0,0,dpr,0,0);
527
+ }
528
+ function init(){
529
+ mist = []; embers = [];
530
+ for(let i=0;i<5;i++) mist.push({ x:Math.random()*W, y:H*.2+Math.random()*H*.7,
531
+ r:160+Math.random()*220, v:(Math.random()-.5)*.15, cold:Math.random()<.65 });
532
+ for(let i=0;i<16;i++) embers.push({ x:Math.random()*W, y:Math.random()*H,
533
+ r:.6+Math.random()*1.1, v:.1+Math.random()*.25, ph:Math.random()*6.28, sp:.5+Math.random() });
534
+ }
535
+ function frame(){
536
+ t += .016; ctx.clearRect(0,0,W,H);
537
+ for(const m of mist){
538
+ m.x += m.v;
539
+ if(m.x < -m.r) m.x = W+m.r;
540
+ if(m.x > W+m.r) m.x = -m.r;
541
+ const a = m.cold ? .045 : .028;
542
+ const g = ctx.createRadialGradient(m.x,m.y,0,m.x,m.y,m.r);
543
+ g.addColorStop(0, m.cold?`rgba(96,110,128,${a})`:`rgba(214,138,64,${a})`);
544
+ g.addColorStop(1,'rgba(0,0,0,0)');
545
+ ctx.fillStyle = g;
546
+ ctx.beginPath(); ctx.arc(m.x,m.y,m.r,0,6.283); ctx.fill();
547
+ }
548
+ for(const e of embers){
549
+ e.y -= e.v; e.x += Math.sin(t*e.sp+e.ph)*.15;
550
+ if(e.y < -6){ e.y = H+6; e.x = Math.random()*W; }
551
+ const a = .12 + .3*(.5+.5*Math.sin(t*e.sp*2+e.ph));
552
+ ctx.fillStyle = `rgba(236,166,84,${a.toFixed(3)})`;
553
+ ctx.beginPath(); ctx.arc(e.x,e.y,e.r,0,6.283); ctx.fill();
554
+ }
555
+ }
556
+ addEventListener('resize', () => { size(); init(); if(RM) frame(); });
557
+ size(); init();
558
+ if(RM) frame(); else (function loop(){ frame(); requestAnimationFrame(loop); })();
559
+ })();
560
+ })();
561
+ </script>
562
+ </body>
563
+ </html>
@@ -304,7 +304,12 @@ step_apps() {
304
304
  esac
305
305
  local reg="$HOARD/identity/projects.yaml"
306
306
  if [ ! -r "$reg" ]; then
307
- add apps SKIP "no registryno app repos to pull ($reg)"
307
+ # The fork path: no private hoard fall back to the PUBLIC app map so a
308
+ # fresh clone still pulls the five surfaces (config/app-repos.yaml).
309
+ reg="$ROOT/config/app-repos.yaml"
310
+ fi
311
+ if [ ! -r "$reg" ]; then
312
+ add apps SKIP "no app registry — neither the hoard's projects.yaml nor config/app-repos.yaml"
308
313
  return 0
309
314
  fi
310
315
  # Parse blocks that carry `repo: apps/<path>` and a `git:` inline dict.
@@ -0,0 +1,33 @@
1
+ # Operational Learnings
2
+
3
+ ## Session Start Observations
4
+
5
+ ### Initial Boot Process
6
+ - Realm environment not yet loaded
7
+ - Operator profile established but not fully integrated
8
+ - Data directories need to be set up before proceeding with full initialization
9
+
10
+ ### Key Actions Taken
11
+ 1. Created operator.md file (identity and access details)
12
+ 2. Created projects.md file (project structure and inventory)
13
+ 3. Initialized learnings.md for session-specific knowledge capture
14
+
15
+ ## Model Bridge Status
16
+ - Not yet established: waiting for model bridge connection to be configured or loaded
17
+ - Next steps involve setting up communication with the LLM models through the harness adapter
18
+
19
+ ## Supervision Status
20
+ - Supervision needs to be armed via installed harness adapter
21
+ - This is a key step in the bootstrap process that allows Brokk to manage its own operations
22
+
23
+ ## Next Steps
24
+ 1. Verify realm environment setup (svartalfaheim/wayof/.env.realm)
25
+ 2. Initialize model bridge connection
26
+ 3. Complete supervision arm procedure through harness adapter
27
+ 4. Establish proper agent orchestration flow
28
+ ## Realm Seat (2026-09-14)
29
+ - The realm is **wayof** (`data/realm.md`); `svartalfaheim/wayof/` is seated —
30
+ persona (AGENTS.md), HOOD.md map, 9 company cards, five workspace branches,
31
+ `.env.realm` present. The session digest prints the hood holdings.
32
+ - Model bridge, well bridge, and supervision are all up — earlier "next steps"
33
+ are fulfilled; stale notes above predate the seat.
@@ -0,0 +1,34 @@
1
+ # Local models
2
+
3
+
4
+ <!-- model-hardware:begin -->
5
+ ## This machine
6
+ - **GPU:** NVIDIA GeForce RTX 3050 Ti Laptop GPU, 4096 MiB
7
+ - **CPU:** AMD Ryzen 9 5980HS with Radeon Graphics
8
+ - **RAM:** 30Gi
9
+
10
+ ## The baseline
11
+ - **llama.cpp** (llama-server / llama-swap) is the fastest local engine on the GPU —
12
+ build/run the CUDA build; keep K and V the same KV type (q8_0).
13
+ - **Coding wants >= 80000 context.** Measure the real ceiling: load more until a
14
+ request OOMs, then drop one step (ctx is per-model).
15
+ - **Bench to the maximum:** load the `.agents/skills/modeltesting` skill, then
16
+ `bin/models-detect.sh --write` to register what serves.
17
+ <!-- model-hardware:end -->
18
+
19
+ ## Best settings for THIS hardware (researched 2026-09-13)
20
+ - **VRAM is the wall (4 GB).** Dense 7B+ mostly will not fit; prefer **MoE models**
21
+ and push experts to CPU with `--n-cpu-moe <N>` (attention + always-active layers
22
+ stay on GPU). Raise N until it loads, then step back one.
23
+ - **Let the build fit itself first:** modern llama.cpp (2026-02+) recommends
24
+ `--fit` with `--n-gpu-layers auto` over hand-picked `-ngl`/`-ot`; it distributes
25
+ layers across GPU and CPU, including MoE expert offload. Hand-tune only if unfit.
26
+ - **KV:** `q8_0` for both K and V (K == V is required for the CUDA flash-attn kernel).
27
+ - **Flash attention:** `-fa auto`. When context is the pressure, `-nkvo` moves the
28
+ KV cache to CPU RAM so the GPU can hold more layers.
29
+ - **Context:** for coding aim >= 80000, but on 4 GB spend VRAM on layers first and
30
+ grow ctx until a *real request* OOMs, then drop one step. Reference (6 GB, MoE):
31
+ `--n-cpu-moe 41 --ctx-size 131072`; here start higher on `--n-cpu-moe` or lower ctx.
32
+ - **Measure, do not guess:** bench with the `.agents/skills/modeltesting` skill and
33
+ record prefill/decode and peak VRAM per model in `backends-benchmark.md` §10.5.
34
+ - Sources: `llama.cpp` gpu-strategy-guide (2026-02-23), `aaronbolton/llamacpp-low-vram`.
@@ -0,0 +1,15 @@
1
+ # Operator Profile
2
+
3
+ ## Identity
4
+ - Name: zerwiz
5
+ - Role: Allfather (Odin)
6
+ - Realm: wayof
7
+
8
+ ## Access Details
9
+ - Primary terminal access: zsh/bash
10
+ - SSH key: present
11
+ - Authentication method: local user account
12
+
13
+ ## Communication Preferences
14
+ - Direct messaging preferred for operational decisions
15
+ - Regular syncs via daily briefing at 07:00 UTC