create-egregore 0.19.21 → 0.19.22

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 (226) hide show
  1. package/assets/egregore-launcher.js +29 -3
  2. package/bin/cli.js +3 -4
  3. package/lib/auth.js +3 -4
  4. package/lib/path-lookup.js +59 -0
  5. package/lib/setup.js +52 -6
  6. package/package.json +2 -2
  7. package/runtime/codex/.claude/context/notification-consent.md +66 -0
  8. package/runtime/codex/.codex/hooks/branch-guard.js +14 -3
  9. package/runtime/codex/.codex/skills/add/SKILL.md +8 -4
  10. package/runtime/codex/.codex/skills/announce/SKILL.md +21 -8
  11. package/runtime/codex/.codex/skills/answer/SKILL.md +8 -4
  12. package/runtime/codex/.codex/skills/archive/SKILL.md +8 -4
  13. package/runtime/codex/.codex/skills/ask/SKILL.md +14 -6
  14. package/runtime/codex/.codex/skills/audit/SKILL.md +29 -0
  15. package/runtime/codex/.codex/skills/autosave/SKILL.md +29 -0
  16. package/runtime/codex/.codex/skills/branch/SKILL.md +8 -4
  17. package/runtime/codex/.codex/skills/checkup/SKILL.md +8 -4
  18. package/runtime/codex/.codex/skills/commit/SKILL.md +8 -4
  19. package/runtime/codex/.codex/skills/contribute/SKILL.md +8 -4
  20. package/runtime/codex/.codex/skills/dark-mode/SKILL.md +8 -4
  21. package/runtime/codex/.codex/skills/delete-user/SKILL.md +8 -4
  22. package/runtime/codex/.codex/skills/demo-mode/SKILL.md +29 -0
  23. package/runtime/codex/.codex/skills/deploy-bridge/SKILL.md +8 -4
  24. package/runtime/codex/.codex/skills/design/SKILL.md +29 -0
  25. package/runtime/codex/.codex/skills/egregore-voice/SKILL.md +8 -4
  26. package/runtime/codex/.codex/skills/emissary/SKILL.md +8 -4
  27. package/runtime/codex/.codex/skills/env/SKILL.md +8 -4
  28. package/runtime/codex/.codex/skills/handoff/SKILL.md +15 -6
  29. package/runtime/codex/.codex/skills/harvest/QUESTION_PALETTE.md +76 -0
  30. package/runtime/codex/.codex/skills/harvest/SKILL.md +30 -6
  31. package/runtime/codex/.codex/skills/ingest/SKILL.md +8 -4
  32. package/runtime/codex/.codex/skills/ingest-google/SKILL.md +8 -4
  33. package/runtime/codex/.codex/skills/ingest-user-interview/SKILL.md +8 -4
  34. package/runtime/codex/.codex/skills/invite/SKILL.md +6 -2
  35. package/runtime/codex/.codex/skills/issue/SKILL.md +8 -4
  36. package/runtime/codex/.codex/skills/me/SKILL.md +8 -4
  37. package/runtime/codex/.codex/skills/meeting/SKILL.md +8 -4
  38. package/runtime/codex/.codex/skills/minion/SKILL.md +8 -4
  39. package/runtime/codex/.codex/skills/mock/SKILL.md +29 -0
  40. package/runtime/codex/.codex/skills/note/SKILL.md +8 -4
  41. package/runtime/codex/.codex/skills/onboarding/SKILL.md +8 -4
  42. package/runtime/codex/.codex/skills/pr/SKILL.md +8 -4
  43. package/runtime/codex/.codex/skills/product-voice/SKILL.md +29 -0
  44. package/runtime/codex/.codex/skills/project/SKILL.md +8 -4
  45. package/runtime/codex/.codex/skills/pull/SKILL.md +8 -4
  46. package/runtime/codex/.codex/skills/push/SKILL.md +8 -4
  47. package/runtime/codex/.codex/skills/quest/SKILL.md +6 -3
  48. package/runtime/codex/.codex/skills/quest-suggest/SKILL.md +8 -4
  49. package/runtime/codex/.codex/skills/reflect/SKILL.md +8 -4
  50. package/runtime/codex/.codex/skills/review-pr/SKILL.md +8 -4
  51. package/runtime/codex/.codex/skills/save/SKILL.md +6 -4
  52. package/runtime/codex/.codex/skills/scroll/SKILL.md +92 -23
  53. package/runtime/codex/.codex/skills/scroll/assets/shell.html +381 -52
  54. package/runtime/codex/.codex/skills/session-view/SKILL.md +8 -4
  55. package/runtime/codex/.codex/skills/setup/SKILL.md +8 -4
  56. package/runtime/codex/.codex/skills/summon/SKILL.md +8 -4
  57. package/runtime/codex/.codex/skills/sync-repos/SKILL.md +8 -4
  58. package/runtime/codex/.codex/skills/task/SKILL.md +9 -5
  59. package/runtime/codex/.codex/skills/teams-connect/SKILL.md +29 -0
  60. package/runtime/codex/.codex/skills/telegram-connect/SKILL.md +8 -4
  61. package/runtime/codex/.codex/skills/telemetry/SKILL.md +8 -4
  62. package/runtime/codex/.codex/skills/test/SKILL.md +8 -4
  63. package/runtime/codex/.codex/skills/thread/SKILL.md +8 -4
  64. package/runtime/codex/.codex/skills/todo/SKILL.md +8 -4
  65. package/runtime/codex/.codex/skills/tui-design/SKILL.md +8 -4
  66. package/runtime/codex/.codex/skills/tutorial/SKILL.md +8 -4
  67. package/runtime/codex/.codex/skills/update/SKILL.md +8 -4
  68. package/runtime/codex/.codex/skills/visual-explain/SKILL.md +8 -4
  69. package/runtime/codex/.codex/spec-manifest.json +4 -4
  70. package/runtime/codex/AGENTS.md +36 -14
  71. package/runtime/codex/bin/activity-data.sh +1 -1
  72. package/runtime/codex/bin/agent.sh +38 -19
  73. package/runtime/codex/bin/attendant.sh +8 -2
  74. package/runtime/codex/bin/autosave.sh +1 -1
  75. package/runtime/codex/bin/capture-reconcile.sh +8 -6
  76. package/runtime/codex/bin/capture-run.sh +1 -1
  77. package/runtime/codex/bin/codex-install-skills.sh +1 -1
  78. package/runtime/codex/bin/codex-render-spec.mjs +12 -5
  79. package/runtime/codex/bin/codex-session-start.sh +1 -1
  80. package/runtime/codex/bin/codex-sync-skills.sh +9 -5
  81. package/runtime/codex/bin/dashboard-data.sh +1 -1
  82. package/runtime/codex/bin/graph-batch.sh +1 -1
  83. package/runtime/codex/bin/graph-op.sh +1 -1
  84. package/runtime/codex/bin/graph-wal.sh +1 -1
  85. package/runtime/codex/bin/graph.sh +1 -1
  86. package/runtime/codex/bin/handoff-pr-backfill.sh +1 -1
  87. package/runtime/codex/bin/handoff-run.sh +53 -39
  88. package/runtime/codex/bin/handoff-save-egregore.sh +62 -32
  89. package/runtime/codex/bin/index-handoff.sh +1 -1
  90. package/runtime/codex/bin/ingest-graph.sh +1 -1
  91. package/runtime/codex/bin/ingest.sh +1 -1
  92. package/runtime/codex/bin/lib/artifact-id.sh +1 -1
  93. package/runtime/codex/bin/lib/config.sh +56 -20
  94. package/runtime/codex/bin/lib/context.sh +7 -1
  95. package/runtime/codex/bin/lib/ensure-develop.sh +1 -1
  96. package/runtime/codex/bin/lib/git-sync.sh +145 -59
  97. package/runtime/codex/bin/lib/greeting.sh +14 -0
  98. package/runtime/codex/bin/lib/hash.sh +1 -1
  99. package/runtime/codex/bin/lib/noncode.sh +1 -1
  100. package/runtime/codex/bin/lib/time.sh +1 -1
  101. package/runtime/codex/bin/notify.sh +492 -153
  102. package/runtime/codex/bin/person.sh +1 -1
  103. package/runtime/codex/bin/publish-artifact.sh +39 -4
  104. package/runtime/codex/bin/publish-references.sh +1 -1
  105. package/runtime/codex/bin/repo-state.sh +7 -10
  106. package/runtime/codex/bin/search.sh +1 -1
  107. package/runtime/codex/bin/session-autosave.sh +1 -1
  108. package/runtime/codex/bin/session-log.sh +1 -1
  109. package/runtime/codex/bin/settings.sh +32 -2
  110. package/runtime/codex/bin/telemetry.sh +1 -1
  111. package/runtime/codex/bin/worktree-create.sh +14 -4
  112. package/runtime/codex/bin/worktree-remove.sh +1 -1
  113. package/runtime/codex/bin/worktree.sh +1 -1
  114. package/runtime/codex/manifest.json +18 -1
  115. package/runtime/pi/.claude/context/notification-consent.md +66 -0
  116. package/runtime/pi/.codex/hooks/branch-guard.js +14 -3
  117. package/runtime/pi/.codex/skills/add/SKILL.md +8 -4
  118. package/runtime/pi/.codex/skills/announce/SKILL.md +21 -8
  119. package/runtime/pi/.codex/skills/answer/SKILL.md +8 -4
  120. package/runtime/pi/.codex/skills/archive/SKILL.md +8 -4
  121. package/runtime/pi/.codex/skills/ask/SKILL.md +14 -6
  122. package/runtime/pi/.codex/skills/audit/SKILL.md +29 -0
  123. package/runtime/pi/.codex/skills/autosave/SKILL.md +29 -0
  124. package/runtime/pi/.codex/skills/branch/SKILL.md +8 -4
  125. package/runtime/pi/.codex/skills/checkup/SKILL.md +8 -4
  126. package/runtime/pi/.codex/skills/commit/SKILL.md +8 -4
  127. package/runtime/pi/.codex/skills/contribute/SKILL.md +8 -4
  128. package/runtime/pi/.codex/skills/dark-mode/SKILL.md +8 -4
  129. package/runtime/pi/.codex/skills/delete-user/SKILL.md +8 -4
  130. package/runtime/pi/.codex/skills/demo-mode/SKILL.md +29 -0
  131. package/runtime/pi/.codex/skills/deploy-bridge/SKILL.md +8 -4
  132. package/runtime/pi/.codex/skills/design/SKILL.md +29 -0
  133. package/runtime/pi/.codex/skills/egregore-voice/SKILL.md +8 -4
  134. package/runtime/pi/.codex/skills/emissary/SKILL.md +8 -4
  135. package/runtime/pi/.codex/skills/env/SKILL.md +8 -4
  136. package/runtime/pi/.codex/skills/handoff/SKILL.md +15 -6
  137. package/runtime/pi/.codex/skills/harvest/QUESTION_PALETTE.md +76 -0
  138. package/runtime/pi/.codex/skills/harvest/SKILL.md +30 -6
  139. package/runtime/pi/.codex/skills/ingest/SKILL.md +8 -4
  140. package/runtime/pi/.codex/skills/ingest-google/SKILL.md +8 -4
  141. package/runtime/pi/.codex/skills/ingest-user-interview/SKILL.md +8 -4
  142. package/runtime/pi/.codex/skills/invite/SKILL.md +6 -2
  143. package/runtime/pi/.codex/skills/issue/SKILL.md +8 -4
  144. package/runtime/pi/.codex/skills/me/SKILL.md +8 -4
  145. package/runtime/pi/.codex/skills/meeting/SKILL.md +8 -4
  146. package/runtime/pi/.codex/skills/minion/SKILL.md +8 -4
  147. package/runtime/pi/.codex/skills/mock/SKILL.md +29 -0
  148. package/runtime/pi/.codex/skills/note/SKILL.md +8 -4
  149. package/runtime/pi/.codex/skills/onboarding/SKILL.md +8 -4
  150. package/runtime/pi/.codex/skills/pr/SKILL.md +8 -4
  151. package/runtime/pi/.codex/skills/product-voice/SKILL.md +29 -0
  152. package/runtime/pi/.codex/skills/project/SKILL.md +8 -4
  153. package/runtime/pi/.codex/skills/pull/SKILL.md +8 -4
  154. package/runtime/pi/.codex/skills/push/SKILL.md +8 -4
  155. package/runtime/pi/.codex/skills/quest/SKILL.md +6 -3
  156. package/runtime/pi/.codex/skills/quest-suggest/SKILL.md +8 -4
  157. package/runtime/pi/.codex/skills/reflect/SKILL.md +8 -4
  158. package/runtime/pi/.codex/skills/review-pr/SKILL.md +8 -4
  159. package/runtime/pi/.codex/skills/save/SKILL.md +6 -4
  160. package/runtime/pi/.codex/skills/scroll/SKILL.md +92 -23
  161. package/runtime/pi/.codex/skills/scroll/assets/shell.html +381 -52
  162. package/runtime/pi/.codex/skills/session-view/SKILL.md +8 -4
  163. package/runtime/pi/.codex/skills/setup/SKILL.md +8 -4
  164. package/runtime/pi/.codex/skills/summon/SKILL.md +8 -4
  165. package/runtime/pi/.codex/skills/sync-repos/SKILL.md +8 -4
  166. package/runtime/pi/.codex/skills/task/SKILL.md +9 -5
  167. package/runtime/pi/.codex/skills/teams-connect/SKILL.md +29 -0
  168. package/runtime/pi/.codex/skills/telegram-connect/SKILL.md +8 -4
  169. package/runtime/pi/.codex/skills/telemetry/SKILL.md +8 -4
  170. package/runtime/pi/.codex/skills/test/SKILL.md +8 -4
  171. package/runtime/pi/.codex/skills/thread/SKILL.md +8 -4
  172. package/runtime/pi/.codex/skills/todo/SKILL.md +8 -4
  173. package/runtime/pi/.codex/skills/tui-design/SKILL.md +8 -4
  174. package/runtime/pi/.codex/skills/tutorial/SKILL.md +8 -4
  175. package/runtime/pi/.codex/skills/update/SKILL.md +8 -4
  176. package/runtime/pi/.codex/skills/visual-explain/SKILL.md +8 -4
  177. package/runtime/pi/.codex/spec-manifest.json +4 -4
  178. package/runtime/pi/.pi/APPEND_SYSTEM.md +34 -12
  179. package/runtime/pi/.pi/extensions/egregore.ts +8 -1
  180. package/runtime/pi/.pi/spec-manifest.json +2 -2
  181. package/runtime/pi/AGENTS.md +36 -14
  182. package/runtime/pi/bin/activity-data.sh +1 -1
  183. package/runtime/pi/bin/agent.sh +38 -19
  184. package/runtime/pi/bin/attendant.sh +8 -2
  185. package/runtime/pi/bin/autosave.sh +1 -1
  186. package/runtime/pi/bin/capture-reconcile.sh +8 -6
  187. package/runtime/pi/bin/capture-run.sh +1 -1
  188. package/runtime/pi/bin/codex-install-skills.sh +1 -1
  189. package/runtime/pi/bin/codex-render-spec.mjs +12 -5
  190. package/runtime/pi/bin/codex-session-start.sh +1 -1
  191. package/runtime/pi/bin/codex-sync-skills.sh +9 -5
  192. package/runtime/pi/bin/dashboard-data.sh +1 -1
  193. package/runtime/pi/bin/graph-batch.sh +1 -1
  194. package/runtime/pi/bin/graph-op.sh +1 -1
  195. package/runtime/pi/bin/graph-wal.sh +1 -1
  196. package/runtime/pi/bin/graph.sh +1 -1
  197. package/runtime/pi/bin/handoff-pr-backfill.sh +1 -1
  198. package/runtime/pi/bin/handoff-run.sh +53 -39
  199. package/runtime/pi/bin/handoff-save-egregore.sh +62 -32
  200. package/runtime/pi/bin/index-handoff.sh +1 -1
  201. package/runtime/pi/bin/ingest-graph.sh +1 -1
  202. package/runtime/pi/bin/ingest.sh +1 -1
  203. package/runtime/pi/bin/lib/artifact-id.sh +1 -1
  204. package/runtime/pi/bin/lib/config.sh +56 -20
  205. package/runtime/pi/bin/lib/context.sh +7 -1
  206. package/runtime/pi/bin/lib/ensure-develop.sh +1 -1
  207. package/runtime/pi/bin/lib/git-sync.sh +145 -59
  208. package/runtime/pi/bin/lib/greeting.sh +14 -0
  209. package/runtime/pi/bin/lib/hash.sh +1 -1
  210. package/runtime/pi/bin/lib/noncode.sh +1 -1
  211. package/runtime/pi/bin/lib/time.sh +1 -1
  212. package/runtime/pi/bin/notify.sh +492 -153
  213. package/runtime/pi/bin/person.sh +1 -1
  214. package/runtime/pi/bin/pi-session-start.sh +1 -1
  215. package/runtime/pi/bin/publish-artifact.sh +39 -4
  216. package/runtime/pi/bin/publish-references.sh +1 -1
  217. package/runtime/pi/bin/repo-state.sh +7 -10
  218. package/runtime/pi/bin/search.sh +1 -1
  219. package/runtime/pi/bin/session-autosave.sh +1 -1
  220. package/runtime/pi/bin/session-log.sh +1 -1
  221. package/runtime/pi/bin/settings.sh +32 -2
  222. package/runtime/pi/bin/telemetry.sh +1 -1
  223. package/runtime/pi/bin/worktree-create.sh +14 -4
  224. package/runtime/pi/bin/worktree-remove.sh +1 -1
  225. package/runtime/pi/bin/worktree.sh +1 -1
  226. package/runtime/pi/manifest.json +18 -1
@@ -59,6 +59,127 @@
59
59
  };
60
60
  })();
61
61
  </script>
62
+ <script id="scroll-logic">
63
+ (function(root){
64
+ 'use strict';
65
+ var api={};
66
+ function text(v){return v===undefined||v===null?'':String(v);}
67
+ function lf(v){return text(v).replace(/\r\n?/g,'\n');}
68
+ function nfc(v){var s=lf(v);return s.normalize?s.normalize('NFC'):s;}
69
+ function has(obj,key){return Object.prototype.hasOwnProperty.call(obj,key);}
70
+ function cleanLine(v){return lf(v).trim().replace(/\n+/g,' ');}
71
+ function undecided(){return {key:'UNDECIDED',label:'Leave this open'};}
72
+ function blankChannels(){return {single:{},multi:{},rank:{},weight:{},spectrum:{}};}
73
+ function forkMode(meta,did){return ((meta.forkModes||{})[did])||'single';}
74
+ function selectedFor(state,meta,did){
75
+ if(state.undecided&&has(state.undecided,did))return undecided();
76
+ var mode=forkMode(meta,did),channel=((state.channels||{})[mode])||{};
77
+ return has(channel,did)?channel[did]:null;
78
+ }
79
+ function pruneState(state,meta){
80
+ var source=state&&typeof state==='object'?state:{},out={channels:blankChannels(),undecided:{},decisions:{},notes:{},opens:{}};
81
+ var decisions=source.decisions&&typeof source.decisions==='object'?source.decisions:{};
82
+ var channels=source.channels&&typeof source.channels==='object'?source.channels:{};
83
+ var explicitUndecided=source.undecided&&typeof source.undecided==='object'?source.undecided:{};
84
+ var notes=source.notes&&typeof source.notes==='object'?source.notes:{};
85
+ var opens=source.opens&&typeof source.opens==='object'?source.opens:{};
86
+ (meta.forkOrder||[]).forEach(function(did){
87
+ var mode=forkMode(meta,did),modeChannel=channels[mode]&&typeof channels[mode]==='object'?channels[mode]:{};
88
+ var selected=modeChannel[did],legacy=decisions[did],allowed=(meta.forkOptions||{})[did],labels=(meta.forkLabels||{})[did]||{};
89
+ var isUndecided=has(explicitUndecided,did)||(legacy&&typeof legacy==='object'&&cleanLine(legacy.key)==='UNDECIDED');
90
+ if(mode==='single'){
91
+ if(!selected&&legacy&&typeof legacy==='object'&&cleanLine(legacy.key)!=='UNDECIDED')selected=legacy;
92
+ if(selected&&typeof selected==='object'){
93
+ var key=cleanLine(selected.key),label=cleanLine(selected.label);
94
+ if(key&&(!Array.isArray(allowed)||allowed.indexOf(key)!==-1)){
95
+ out.channels.single[did]={key:key,label:label||cleanLine(labels[key])||key};
96
+ out.decisions[did]=out.channels.single[did];isUndecided=false;
97
+ }
98
+ }
99
+ }else if(mode==='multi'&&Array.isArray(selected)){
100
+ var seen={},max=Number((meta.forkMax||{})[did]),picks=[];
101
+ selected.forEach(function(entry){
102
+ if(!entry||typeof entry!=='object')return;
103
+ var key=cleanLine(entry.key),label=cleanLine(entry.label);
104
+ if(!key||seen[key]||(Array.isArray(allowed)&&allowed.indexOf(key)===-1))return;
105
+ seen[key]=true;picks.push({key:key,label:label||cleanLine(labels[key])||key});
106
+ });
107
+ if(Number.isInteger(max)&&max>0)picks=picks.slice(0,max);
108
+ if(picks.length){out.channels.multi[did]=picks;isUndecided=false;}
109
+ }else if(mode==='rank'&&Array.isArray(selected)){
110
+ var rankSeen={},rankCount=0,ranks=[];
111
+ selected.forEach(function(tier){
112
+ if(!Array.isArray(tier)||rankCount>=5)return;
113
+ var cleanTier=[];
114
+ tier.forEach(function(entry){
115
+ if(rankCount>=5||!entry||typeof entry!=='object')return;
116
+ var key=cleanLine(entry.key),label=cleanLine(entry.label);
117
+ if(!key||rankSeen[key]||(Array.isArray(allowed)&&allowed.indexOf(key)===-1))return;
118
+ rankSeen[key]=true;rankCount++;cleanTier.push({key:key,label:label||cleanLine(labels[key])||key});
119
+ });
120
+ if(cleanTier.length)ranks.push(cleanTier);
121
+ });
122
+ if(ranks.length){out.channels.rank[did]=ranks;isUndecided=false;}
123
+ }else if(mode==='spectrum'&&selected&&typeof selected==='object'){
124
+ var position=Number(selected.position),positionKey=cleanLine(selected.position),label=cleanLine(selected.label),authoredLabel='';
125
+ Object.keys(labels).some(function(key){
126
+ if(Number(key)!==position)return false;
127
+ authoredLabel=cleanLine(labels[key]);return true;
128
+ });
129
+ if(Number.isFinite(position)&&position>=0&&position<=1
130
+ &&(!Array.isArray(allowed)||allowed.some(function(value){return Number(value)===position;}))){
131
+ out.channels.spectrum[did]={position:position,label:label||authoredLabel||positionKey};
132
+ isUndecided=false;
133
+ }
134
+ }
135
+ if(isUndecided){
136
+ out.undecided[did]=true;out.decisions[did]=undecided();
137
+ }
138
+ if(has(notes,did)&&lf(notes[did]).trim()){
139
+ out.notes[did]=nfc(notes[did]);
140
+ if(!selectedFor(out,meta,did)){out.undecided[did]=true;out.decisions[did]=undecided();}
141
+ }
142
+ });
143
+ (meta.promptOrder||[]).forEach(function(oid){if(has(opens,oid)&&lf(opens[oid]).trim())out.opens[oid]=nfc(opens[oid]);});
144
+ return out;
145
+ }
146
+ function decisionProgress(state,meta){
147
+ var current=pruneState(state,meta),total=(meta.forkOrder||[]).length,done=0;
148
+ (meta.forkOrder||[]).forEach(function(did){if(selectedFor(current,meta,did))done++;});
149
+ return {done:Math.min(done,total),total:total};
150
+ }
151
+ function buildDecisionsFence(state,meta){
152
+ var current=pruneState(state,meta),out='#'+meta.slug+'-decisions:v'+meta.version+'\n'
153
+ +'surface: '+meta.surfaceId+'\n'+'harvest: '+meta.harvestId+'\n'+'date: '+meta.date+'\n\n';
154
+ (meta.forkOrder||[]).forEach(function(did,i){
155
+ var selected=selectedFor(current,meta,did),mode=forkMode(meta,did);
156
+ if(!selected)return;
157
+ if(selected.key==='UNDECIDED')out+='Q'+(i+1)+' '+did+': UNDECIDED\n';
158
+ else if(mode==='multi'){
159
+ out+='Q'+(i+1)+' '+did+': ['+selected.map(function(pick){return pick.key;}).join(', ')+'] ('
160
+ +selected.map(function(pick){return '"'+pick.label+'"';}).join(' + ')+')\n';
161
+ }else if(mode==='rank'){
162
+ out+='Q'+(i+1)+' '+did+': '+selected.map(function(tier){
163
+ return tier.map(function(pick){return pick.key;}).join(' = ');
164
+ }).join(' > ')+'\n';
165
+ }else if(mode==='spectrum'){
166
+ var ends=(meta.forkEnds||{})[did]||[];
167
+ out+='Q'+(i+1)+' '+did+': '+selected.position+' ('+cleanLine(ends[0])+'\u2192'+cleanLine(ends[1])+')\n';
168
+ }else out+='Q'+(i+1)+' '+did+': '+selected.key+' ("'+selected.label+'")\n';
169
+ var note=current.notes[did];
170
+ if(note&&note.trim()){
171
+ out+=' note: |\n';
172
+ lf(note).split('\n').forEach(function(line){out+=' '+line+'\n';});
173
+ }
174
+ });
175
+ if((meta.promptOrder||[]).length)out+='\n';
176
+ (meta.promptOrder||[]).forEach(function(oid,i){var answer=has(current.opens,oid)?cleanLine(current.opens[oid]):'';out+='O'+(i+1)+' '+oid+': '+(answer||'UNDECIDED')+'\n';});
177
+ return out;
178
+ }
179
+ api.pruneState=pruneState;api.decisionProgress=decisionProgress;api.buildDecisionsFence=buildDecisionsFence;
180
+ root.__scroll=api;
181
+ })(typeof window!=='undefined'?window:globalThis);
182
+ </script>
62
183
  <style>
63
184
  /*__MERIDIAN_CSS__*/
64
185
 
@@ -130,10 +251,10 @@ section::after{content:"";position:absolute;left:50%;bottom:-4px;width:7px;heigh
130
251
  border-radius:0 10px 10px 0;padding:16px 22px;margin:24px 0;color:var(--text-dim)}
131
252
  .callout b{color:var(--text)}
132
253
 
133
- /* spectrum (progression of 2-4 options) */
134
- .spectrum{display:grid;gap:0;margin:26px 0 10px;grid-auto-flow:column;grid-auto-columns:1fr;
254
+ /* phase strip (progression of 2-4 explanatory phases) */
255
+ .phase-strip{display:grid;gap:0;margin:26px 0 10px;grid-auto-flow:column;grid-auto-columns:1fr;
135
256
  border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;background:var(--surface)}
136
- @media(max-width:680px){.spectrum{grid-auto-flow:row}}
257
+ @media(max-width:680px){.phase-strip{grid-auto-flow:row}}
137
258
  .sp{padding:22px 22px 24px;border-right:1px solid var(--border-soft);position:relative}
138
259
  .sp:last-child{border-right:none}
139
260
  .sp.win{background:var(--t1-bg)}
@@ -318,11 +439,13 @@ body{background:var(--paper);color:var(--ink);font-family:var(--sans);line-heigh
318
439
 
319
440
  .dcard{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:24px 26px;margin:22px 0}
320
441
  .dcard.answered{border-color:var(--t1);box-shadow:0 0 0 2px var(--t1-bg)}
442
+ .dcard.left-open{border-color:var(--t3);box-shadow:0 0 0 2px color-mix(in srgb,var(--t3) 16%,transparent)}
321
443
  .dhead{display:flex;align-items:baseline;gap:12px;margin-bottom:6px}
322
444
  .dhead .dnum{font-family:var(--mono);font-size:.74rem;color:var(--t1);font-weight:600;flex:none;border:1px solid var(--t1);border-radius:6px;padding:1px 7px;background:var(--card)}
323
445
  .dhead h3{font-family:var(--serif);font-weight:400;margin:0;font-size:1.2rem;line-height:1.25;color:var(--ink)}
324
446
  .dframe{font-size:.96rem;color:var(--ink-soft);margin:6px 0 4px}
325
447
  .dframe .ref{font-family:var(--mono);font-size:.78rem;color:var(--ink-faint)}
448
+ .modehint{margin:14px 0 -8px;font-family:var(--mono);font-size:.7rem;letter-spacing:.4px;color:var(--ink-faint)}
326
449
 
327
450
  .opts{display:grid;gap:12px;margin:18px 0 6px}
328
451
  .opts.two{grid-template-columns:1fr 1fr}.opts.three{grid-template-columns:1fr 1fr 1fr}
@@ -334,6 +457,28 @@ body{background:var(--paper);color:var(--ink);font-family:var(--sans);line-heigh
334
457
  .opt .okey{font-family:var(--mono);font-size:.7rem;width:20px;height:20px;display:grid;place-items:center;border:1px solid var(--line);border-radius:5px;color:var(--ink-soft);flex:none;background:var(--card)}
335
458
  .opt.sel .okey{background:var(--t1);color:var(--paper);border-color:var(--t1)}
336
459
  .opt .olabel{font-weight:600;color:var(--ink);font-size:.96rem;line-height:1.25}
460
+ .spectrum-poles{display:flex;justify-content:space-between;gap:20px;margin:17px 2px 8px;font-family:var(--mono);font-size:.72rem;color:var(--ink-soft)}
461
+ .spectrum-poles span:last-child{text-align:right}
462
+ .spectrum-stops{display:grid;grid-template-columns:repeat(auto-fit,minmax(96px,1fr));gap:8px;margin:10px 0 6px}
463
+ .sstop{appearance:none;border:1px solid var(--line);border-radius:10px;padding:12px 9px;background:var(--paper);color:var(--ink);cursor:pointer;display:flex;flex-direction:column;align-items:center;gap:5px;text-align:center;font-family:var(--sans);transition:.16s}
464
+ .sstop:hover{border-color:var(--t1);background:var(--paper-2)}
465
+ .sstop.sel{border-color:var(--t1);background:var(--t1-bg);box-shadow:0 0 0 2px var(--t1)}
466
+ .spos{font-family:var(--mono);font-size:.68rem;color:var(--ink-faint)}
467
+ .slabel{font-size:.82rem;font-weight:600;line-height:1.25}
468
+ .rank-list{display:flex;flex-direction:column;gap:9px;margin:18px 0 6px}
469
+ .rank-item{position:relative;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px 12px;align-items:start;border:1px solid var(--line);border-radius:11px;padding:12px 13px;background:var(--paper);transition:.16s}
470
+ .rank-item.ranked{border-color:var(--t1);background:var(--t1-bg)}
471
+ .rank-toggle{appearance:none;border:0;background:transparent;color:var(--ink);padding:2px;text-align:left;cursor:pointer;display:flex;align-items:center;gap:10px;font:inherit}
472
+ .rank-toggle .rank-badge{font-family:var(--mono);font-size:.68rem;min-width:25px;height:25px;display:grid;place-items:center;border:1px solid var(--line);border-radius:6px;color:var(--ink-faint);background:var(--card)}
473
+ .rank-item.ranked .rank-badge{border-color:var(--t1);background:var(--t1);color:var(--paper)}
474
+ .rank-toggle .rank-label{font-weight:600;line-height:1.3}
475
+ .rank-controls{display:flex;gap:5px;align-items:center}
476
+ .rank-controls button{appearance:none;border:1px solid var(--line);border-radius:7px;background:var(--card);color:var(--ink-soft);font-family:var(--mono);font-size:.66rem;padding:5px 7px;cursor:pointer;min-height:29px}
477
+ .rank-controls button:hover:not(:disabled){border-color:var(--t1);color:var(--t1)}
478
+ .rank-controls button:disabled{opacity:.35;cursor:not-allowed}
479
+ .rank-item .otrade{grid-column:1 / -1;padding-left:37px}
480
+ .rank-summary{margin:12px 0 -7px;padding:9px 11px;border:1px dashed var(--line);border-radius:8px;background:var(--paper);font-family:var(--mono);font-size:.72rem;color:var(--ink-soft)}
481
+ @media(max-width:620px){.rank-item{grid-template-columns:1fr}.rank-controls{padding-left:37px}.rank-item .otrade{padding-left:37px}}
337
482
  .oviz{font-family:var(--mono);font-size:.7rem;line-height:1.5;color:var(--ink-soft);background:var(--card);border:1px solid var(--line-soft);border-radius:8px;padding:9px 11px;white-space:pre-wrap;overflow-x:auto}
338
483
  .obadges{display:flex;flex-wrap:wrap;gap:6px}
339
484
  .obadges .bdg{font-family:var(--mono);font-size:.64rem;border:1px solid var(--line);border-radius:20px;padding:2px 9px;background:var(--card);color:var(--ink-soft)}
@@ -346,9 +491,13 @@ body{background:var(--paper);color:var(--ink);font-family:var(--sans);line-heigh
346
491
  .orec{margin-top:14px;font-size:.88rem;color:var(--ink-soft);background:var(--paper);border:1px dashed var(--t1);border-radius:9px;padding:11px 14px}
347
492
  .orec b{color:var(--t1)}
348
493
  .orec::before{content:"\2605 lean ";font-family:var(--mono);font-size:.72rem;letter-spacing:1px;color:var(--t1);font-weight:600}
494
+ .undecided-control{appearance:none;display:flex;align-items:baseline;gap:9px;width:100%;margin-top:14px;padding:10px 13px;border:1px dashed var(--line);border-radius:9px;background:transparent;color:var(--ink-soft);font-family:var(--sans);font-size:.86rem;text-align:left;cursor:pointer}
495
+ .undecided-control:hover{border-color:var(--t3);background:var(--paper)}
496
+ .undecided-control[aria-pressed="true"]{border-style:solid;border-color:var(--t3);background:color-mix(in srgb,var(--t3) 10%,var(--paper));color:var(--ink)}
497
+ .undecided-control .uwhen{font-family:var(--mono);font-size:.68rem;color:var(--ink-faint)}
349
498
  .dnote,.otext{width:100%;margin-top:14px;font-family:var(--sans);font-size:.9rem;color:var(--ink);background:var(--paper);border:1px solid var(--line);border-radius:9px;padding:11px 13px;resize:vertical;min-height:46px;line-height:1.5}
350
499
  .dnote::placeholder,.otext::placeholder{color:var(--ink-faint)}
351
- .dnote:focus,.otext:focus,.opt:focus-visible{outline:2px solid var(--t1);outline-offset:1px}
500
+ .dnote:focus,.otext:focus,.opt:focus-visible,.sstop:focus-visible,.rank-toggle:focus-visible,.rank-controls button:focus-visible,.undecided-control:focus-visible{outline:2px solid var(--t1);outline-offset:1px}
352
501
  .oprompt{background:var(--card);border:1px solid var(--line);border-left:3px solid var(--sky);border-radius:14px;padding:22px 24px;margin:22px 0}
353
502
  .oprompt .otext{min-height:80px}
354
503
  .oprompt h3{font-family:var(--serif);font-weight:400;margin:0 0 8px;font-size:1.15rem;color:var(--ink)}
@@ -387,14 +536,10 @@ body{background:var(--paper);color:var(--ink);font-family:var(--sans);line-heigh
387
536
 
388
537
  <div id="view-paper" class="view active">
389
538
  <div class="wrap">
390
- <!-- __FACE__ : replace this comment with the paper face. Required grammar:
539
+ <!-- __FACE__ : replace this comment with the paper face. Composition semantics and module-fit rules live in SKILL.md; this is syntax reference only:
391
540
  <header class="phead"> kicker · h1 · subtitle · .meta (Author / Version vN — updates in place / Grounds / Date)
392
- <section id="s-…"> blocks (rail-nav builds from these; h2 per section):
393
- · the setting/question — what exists, what it cannot answer; .claims grid for load-bearing numbers; .thesis for the reframe
394
- · the lenses — 2–4 distinct mental models of the same design (h3 each); every lens must stress-test, not decorate
395
- · the machine — the concrete architecture; .layers for anatomy; tokenized SVG <figure> (fill/stroke ONLY var(--token)); .steps for protocol
396
- · the consequences/product section
397
- · honest costs — .threats grid of .tcard, each residual deep-linking <a onclick="goFork('fork-id')"> to the fork that prices it
541
+ <section id="s-…"> one block per chosen module; rail-nav builds from these; use h2 per section.
542
+ Available structures: .claims for load-bearing numbers · .thesis for a reframe · .layers for anatomy · .steps for protocol · tokenized SVG <figure> (fill/stroke ONLY var(--token)) · .threats of .tcard · <a onclick="goFork('fork-id')"> for a cost priced by a fork.
398
543
  <footer class="pfoot"> title line · .src grounds + "updates in place" note · .tag-row
399
544
  -->
400
545
  </div>
@@ -402,14 +547,16 @@ body{background:var(--paper);color:var(--ink);font-family:var(--sans);line-heigh
402
547
 
403
548
  <div id="view-harvest" class="view">
404
549
  <div class="wrap">
405
- <!-- __HARVEST__ : replace this comment with the harvest face. Required grammar:
550
+ <!-- __HARVEST__ : replace this comment with the decisions face. Question-design rules live in SKILL.md; this is syntax reference only:
406
551
  <div class="hv-hero"> .sig · h1 · lede naming every fork in one breath · .hv-meta (Respondent / Surface: N forks · M prompts / Loop: paste-back → vN+1 / Returns to)
407
- <div class="callout"> how-to-read (every option carries a real + and a real −; at most one ★ lean; the why-note rides back)
552
+ <div class="callout"> how-to-read
408
553
  <section class="band"> per band (2–4 bands), .bhead with .bnum letter:
409
- <div class="dcard" data-decision="fork-id"> · .dhead (.dnum A1 · h3 question) · .dframe with .ref grounds
410
- .opts.two|.three of <div class="opt" data-opt="key" data-label="Label"> · .ohead (.okey letter · .olabel) · optional .oviz (mono sketch) / .obadges · .otrade (one .plus + one .minus — an option with no minus is propaganda)
411
- <div class="orec"> at most one ★ lean, a position not a verdict · <textarea class="dnote" data-note="fork-id">
412
- <div class="oprompt" data-openid="prompt-id"> open prompts — ALWAYS include one meta-prompt: "this paper is alive — what should vN+1 ask?"
554
+ <div class="dcard" data-decision="fork-id"> for legacy/single, add data-mode="multi" data-max="N" for multi, add data-mode="rank" for rank, or add data-mode="spectrum" data-left="left pole" data-right="right pole" for spectrum · .dhead (.dnum A1 · h3 question) · .dframe with .ref grounds
555
+ single/multi: .opts.two|.three of <div class="opt" data-opt="key" data-label="Label"> · .ohead (.okey letter · .olabel) · optional .oviz (mono sketch) / .obadges · .otrade (.plus + .minus)
556
+ rank: .rank-list of 2–5 <div class="rank-item" data-opt="key" data-label="Label">, each containing one native <button type="button" class="rank-toggle"> and one .otrade; runtime adds ranking controls, badges, summary, and supports ties plus partial top-k
557
+ spectrum: .spectrum-poles plus .spectrum-stops of 5–7 <button class="sstop" data-pos="0..1" data-label="fully labeled stop">; no slider and no selected class in authored HTML; runtime adds mode-correct radio/checkbox ARIA behavior and the explicit leave-open control
558
+ optional <div class="orec"> · <textarea class="dnote">
559
+ <div class="oprompt" data-openid="prompt-id"> open prompt
413
560
  copydock + harvest pfoot (keep from shell)
414
561
  -->
415
562
 
@@ -425,7 +572,7 @@ body{background:var(--paper);color:var(--ink);font-family:var(--sans);line-heigh
425
572
 
426
573
  <footer class="pfoot">
427
574
  <div>Egregore — harvest surface for __TITLE__</div>
428
- <div class="src">Decisions paste back into the session · absorbed through the harvest loop · the paper updates in place and v__NEXT_VERSION__'s questions regenerate · UNDECIDED stays open, never forced.</div>
575
+ <div class="src">Copy your decisions and paste the block into this Egregore session · the paper updates in place and v__NEXT_VERSION__'s questions regenerate · “Leave this open” returns once in a different form; untouched questions do not enter the return block.</div>
429
576
  <div class="tag-row"><span class="tg">__HARVEST_ID__</span><span class="tg">__SURFACE_ID__</span></div>
430
577
  </footer>
431
578
  </div>
@@ -467,55 +614,237 @@ function buildRail(){
467
614
  }
468
615
 
469
616
  var SLUG='__SLUG__';
470
- var state={decisions:{},notes:{},opens:{}};
617
+ var state={channels:{single:{},multi:{},rank:{},weight:{},spectrum:{}},undecided:{},decisions:{},notes:{},opens:{}};
471
618
  function loadState(){ try{Object.assign(state, JSON.parse(localStorage.getItem('__STORAGE_KEY__')||'{}'));}catch(e){}
472
- if(!state.decisions)state.decisions={}; if(!state.notes)state.notes={}; if(!state.opens)state.opens={}; }
473
- function saveState(){ try{localStorage.setItem('__STORAGE_KEY__', JSON.stringify(state));}catch(e){} }
619
+ if(!state.channels)state.channels={};['single','multi','rank','weight','spectrum'].forEach(function(mode){if(!state.channels[mode])state.channels[mode]={};});
620
+ if(!state.undecided)state.undecided={};if(!state.decisions)state.decisions={}; if(!state.notes)state.notes={}; if(!state.opens)state.opens={}; }
621
+ function saveState(){ try{localStorage.setItem('__STORAGE_KEY__',JSON.stringify({channels:state.channels,undecided:state.undecided,decisions:state.decisions,notes:state.notes,opens:state.opens}));}catch(e){} }
622
+ function hasState(obj,key){return Object.prototype.hasOwnProperty.call(obj,key);}
623
+ function cardMode(card){return card.dataset.mode||'single';}
624
+ function cardMax(card){var parsed=Number(card.dataset.max);return Number.isInteger(parsed)&&parsed>0?parsed:card.querySelectorAll('.opt').length;}
625
+ function channelFor(mode){if(!state.channels[mode])state.channels[mode]={};return state.channels[mode];}
626
+ function rankLocation(ranks,key){
627
+ var found=null;(ranks||[]).some(function(tier,tierIndex){
628
+ var itemIndex=tier.findIndex(function(item){return item.key===key;});
629
+ if(itemIndex===-1)return false;found={tier:tierIndex,item:itemIndex};return true;
630
+ });return found;
631
+ }
632
+ function rankCount(ranks){return (ranks||[]).reduce(function(total,tier){return total+tier.length;},0);}
633
+ function selectedForDecision(did,mode){
634
+ if(hasState(state.undecided,did))return {key:'UNDECIDED',label:'Leave this open'};
635
+ var channel=channelFor(mode);return hasState(channel,did)?channel[did]:null;
636
+ }
637
+ function clearDecision(did,mode){delete channelFor(mode)[did];delete state.undecided[did];delete state.decisions[did];}
638
+ function syncLegacyDecision(did,mode){
639
+ delete state.decisions[did];
640
+ if(hasState(state.undecided,did))state.decisions[did]={key:'UNDECIDED',label:'Leave this open'};
641
+ else if(mode==='single'&&hasState(channelFor('single'),did))state.decisions[did]=channelFor('single')[did];
642
+ }
643
+ function renderDecision(card,did){
644
+ var mode=cardMode(card),selected=selectedForDecision(did,mode),leftOpen=selected&&selected.key==='UNDECIDED';
645
+ card.querySelectorAll('.opt').forEach(function(opt){
646
+ var chosen=!!selected&&!leftOpen&&(mode==='multi'?selected.some(function(pick){return pick.key===opt.dataset.opt;}):selected.key===opt.dataset.opt);
647
+ opt.classList.toggle('sel',chosen);opt.setAttribute('aria-checked',chosen?'true':'false');
648
+ });
649
+ card.querySelectorAll('.sstop').forEach(function(stop){
650
+ var chosen=!!selected&&!leftOpen&&mode==='spectrum'&&Number(selected.position)===Number(stop.dataset.pos);
651
+ stop.classList.toggle('sel',chosen);stop.setAttribute('aria-checked',chosen?'true':'false');
652
+ });
653
+ card.querySelectorAll('.rank-item').forEach(function(item){
654
+ var key=item.dataset.opt,location=mode==='rank'&&Array.isArray(selected)?rankLocation(selected,key):null;
655
+ item.classList.toggle('ranked',!!location);
656
+ var toggle=item.querySelector('.rank-toggle'),badge=item.querySelector('.rank-badge');
657
+ if(toggle)toggle.setAttribute('aria-pressed',location?'true':'false');
658
+ if(badge)badge.textContent=location?String(location.tier+1)+(selected[location.tier].length>1?'='):'\u2014';
659
+ item.querySelectorAll('.rank-controls button').forEach(function(button){
660
+ var action=button.dataset.rankAction,disabled=!location;
661
+ if(action==='up'||action==='tie')disabled=disabled||location.tier===0;
662
+ if(action==='down')disabled=disabled||location.tier===selected.length-1;
663
+ if(action==='untie')disabled=disabled||selected[location.tier].length<2;
664
+ button.disabled=disabled;
665
+ });
666
+ });
667
+ if(mode==='rank'){
668
+ var rankList=card.querySelector('.rank-list'),rankItems=[].slice.call(card.querySelectorAll('.rank-item'));
669
+ rankItems.sort(function(a,b){
670
+ var aLocation=Array.isArray(selected)?rankLocation(selected,a.dataset.opt):null,bLocation=Array.isArray(selected)?rankLocation(selected,b.dataset.opt):null;
671
+ if(aLocation&&bLocation)return aLocation.tier-bLocation.tier||aLocation.item-bLocation.item;
672
+ if(aLocation)return -1;if(bLocation)return 1;
673
+ return Number(a.dataset.rankSource)-Number(b.dataset.rankSource);
674
+ });
675
+ rankItems.forEach(function(item){rankList.appendChild(item);});
676
+ }
677
+ var control=card.querySelector('.undecided-control');
678
+ if(control)control.setAttribute('aria-pressed',leftOpen?'true':'false');
679
+ card.classList.toggle('answered',!!selected);
680
+ card.classList.toggle('left-open',!!leftOpen);
681
+ var hint=card.querySelector('.modehint');
682
+ if(hint&&mode==='multi'){var count=Array.isArray(selected)?selected.length:0,max=cardMax(card);hint.textContent='Pick up to '+max+' · '+count+' selected'+(count===max?' · limit reached':'');}
683
+ else if(hint&&mode==='spectrum'){var stops=card.querySelectorAll('.sstop').length;hint.textContent='Choose one of '+stops+' labeled stops · '+(selected&&!leftOpen?(selected.label||selected.position):leftOpen?'left open':'untouched');}
684
+ else if(hint&&mode==='rank'){var count=Array.isArray(selected)?rankCount(selected):0,total=card.querySelectorAll('.rank-item').length;hint.textContent='Rank up to '+total+' · '+count+' ranked · ties allowed · partial order is okay';}
685
+ var rankSummary=card.querySelector('.rank-summary');
686
+ if(rankSummary)rankSummary.textContent=leftOpen?'Left open':Array.isArray(selected)&&selected.length
687
+ ?selected.map(function(tier){return tier.map(function(item){return item.key;}).join(' = ');}).join(' > ')
688
+ :'No ranking yet';
689
+ }
474
690
  function wireHarvest(){
475
691
  document.querySelectorAll('.dcard').forEach(function(card){
476
- var did=card.dataset.decision;
477
- card.querySelectorAll('.opt').forEach(function(opt){
478
- var key=opt.dataset.opt, label=opt.dataset.label||(opt.querySelector('.olabel')||{}).textContent||key;
479
- if(state.decisions[did] && state.decisions[did].key===key) opt.classList.add('sel');
480
- opt.addEventListener('click', function(){
481
- var already=opt.classList.contains('sel');
482
- card.querySelectorAll('.opt').forEach(function(o){o.classList.remove('sel');});
483
- if(already){delete state.decisions[did];} else {opt.classList.add('sel'); state.decisions[did]={key:key,label:label};}
484
- card.classList.toggle('answered', !!state.decisions[did]); saveState(); updateProgress();
692
+ var did=card.dataset.decision,mode=cardMode(card),group=card.querySelector(mode==='spectrum'?'.spectrum-stops':mode==='rank'?'.rank-list':'.opts'),heading=card.querySelector('.dhead h3');
693
+ if(heading&&!heading.id)heading.id='decision-'+String(did).replace(/[^a-zA-Z0-9_-]/g,'-')+'-question';
694
+ if(group){
695
+ group.setAttribute('role',mode==='rank'?'list':mode==='multi'?'group':'radiogroup');if(heading)group.setAttribute('aria-labelledby',heading.id);
696
+ if(mode==='multi'||mode==='rank'||mode==='spectrum'){var hint=document.createElement('div');hint.className='modehint';hint.id=heading.id+'-mode';hint.setAttribute('aria-live','polite');card.insertBefore(hint,group);group.setAttribute('aria-describedby',hint.id);}
697
+ if(mode==='rank'){var summary=document.createElement('div');summary.className='rank-summary';summary.setAttribute('aria-live','polite');summary.id=heading.id+'-rank-summary';card.insertBefore(summary,group);group.setAttribute('aria-describedby',heading.id+'-mode '+summary.id);}
698
+ }
699
+ var options=[].slice.call(card.querySelectorAll('.opt'));
700
+ options.forEach(function(opt,index){
701
+ var key=opt.dataset.opt,label=opt.dataset.label||(opt.querySelector('.olabel')||{}).textContent||key;
702
+ opt.setAttribute('role',mode==='multi'?'checkbox':'radio');opt.setAttribute('tabindex','0');
703
+ if(!opt.title)opt.title=mode==='multi'?'Add this choice. Activate it again to remove it.':'Choose this option. Activate it again to clear.';
704
+ function activate(){
705
+ delete state.undecided[did];
706
+ if(mode==='multi'){
707
+ var selected=(channelFor('multi')[did]||[]).slice(),at=selected.findIndex(function(pick){return pick.key===key;});
708
+ if(at!==-1)selected.splice(at,1);else if(selected.length<cardMax(card))selected.push({key:key,label:label});
709
+ if(selected.length)channelFor('multi')[did]=selected;else delete channelFor('multi')[did];
710
+ }else{
711
+ var selected=channelFor('single')[did],already=selected&&selected.key===key;
712
+ if(already)delete channelFor('single')[did];else channelFor('single')[did]={key:key,label:label};
713
+ }
714
+ syncLegacyDecision(did,mode);
715
+ renderDecision(card,did);saveState();updateProgress();
716
+ }
717
+ opt.addEventListener('click',activate);
718
+ opt.addEventListener('keydown',function(event){
719
+ if(event.key==='Enter'||event.key===' '){event.preventDefault();activate();return;}
720
+ var next=index;
721
+ if(event.key==='ArrowRight'||event.key==='ArrowDown')next=(index+1)%options.length;
722
+ else if(event.key==='ArrowLeft'||event.key==='ArrowUp')next=(index+options.length-1)%options.length;
723
+ else if(event.key==='Home')next=0;
724
+ else if(event.key==='End')next=options.length-1;
725
+ else return;
726
+ event.preventDefault();options[next].focus();
485
727
  });
486
728
  });
487
- card.classList.toggle('answered', !!state.decisions[did]);
729
+ var rankItems=[].slice.call(card.querySelectorAll('.rank-item'));
730
+ rankItems.forEach(function(item,index){
731
+ var key=item.dataset.opt,label=item.dataset.label||(item.querySelector('.rank-label,.olabel')||{}).textContent||key;
732
+ var toggle=item.querySelector('.rank-toggle');if(!toggle)return;
733
+ item.dataset.rankSource=String(index);
734
+ item.setAttribute('role','listitem');toggle.type='button';toggle.setAttribute('aria-pressed','false');
735
+ if(!toggle.title)toggle.title='Add this item at the end of your ranking. Activate it again to remove it.';
736
+ var badge=toggle.querySelector('.rank-badge');
737
+ if(!badge){badge=document.createElement('span');badge.className='rank-badge';badge.setAttribute('aria-hidden','true');badge.textContent='\u2014';toggle.insertBefore(badge,toggle.firstChild);}
738
+ function commit(ranks){
739
+ delete state.undecided[did];
740
+ if(ranks.length)channelFor('rank')[did]=ranks;else delete channelFor('rank')[did];
741
+ syncLegacyDecision(did,mode);renderDecision(card,did);saveState();updateProgress();
742
+ }
743
+ function activate(){
744
+ var ranks=(channelFor('rank')[did]||[]).map(function(tier){return tier.slice();}),location=rankLocation(ranks,key);
745
+ if(location){ranks[location.tier].splice(location.item,1);if(!ranks[location.tier].length)ranks.splice(location.tier,1);}
746
+ else ranks.push([{key:key,label:label}]);
747
+ commit(ranks);
748
+ }
749
+ toggle.addEventListener('click',activate);
750
+ toggle.addEventListener('keydown',function(event){
751
+ var ordered=[].slice.call(card.querySelectorAll('.rank-toggle')),at=ordered.indexOf(toggle),next=at;
752
+ if(event.key==='ArrowRight'||event.key==='ArrowDown')next=(at+1)%ordered.length;
753
+ else if(event.key==='ArrowLeft'||event.key==='ArrowUp')next=(at+ordered.length-1)%ordered.length;
754
+ else if(event.key==='Home')next=0;
755
+ else if(event.key==='End')next=ordered.length-1;
756
+ else return;
757
+ event.preventDefault();ordered[next].focus();
758
+ });
759
+ var controls=document.createElement('div');controls.className='rank-controls';
760
+ [['up','\u2191','Move this rank tier up'],['down','\u2193','Move this rank tier down'],['tie','=','Tie this item with the tier above'],['untie','\u2260','Move this item into its own tier below']].forEach(function(spec){
761
+ var button=document.createElement('button');button.type='button';button.dataset.rankAction=spec[0];button.textContent=spec[1];button.setAttribute('aria-label',spec[2]);button.title=spec[2];
762
+ button.addEventListener('click',function(){
763
+ var ranks=(channelFor('rank')[did]||[]).map(function(tier){return tier.slice();}),location=rankLocation(ranks,key);if(!location)return;
764
+ if(spec[0]==='up'&&location.tier>0){var above=ranks[location.tier-1];ranks[location.tier-1]=ranks[location.tier];ranks[location.tier]=above;}
765
+ else if(spec[0]==='down'&&location.tier<ranks.length-1){var below=ranks[location.tier+1];ranks[location.tier+1]=ranks[location.tier];ranks[location.tier]=below;}
766
+ else if(spec[0]==='tie'&&location.tier>0){var tied=ranks[location.tier].splice(location.item,1)[0];ranks[location.tier-1].push(tied);if(!ranks[location.tier].length)ranks.splice(location.tier,1);}
767
+ else if(spec[0]==='untie'&&ranks[location.tier].length>1){var untied=ranks[location.tier].splice(location.item,1)[0];ranks.splice(location.tier+1,0,[untied]);}
768
+ else return;
769
+ commit(ranks);
770
+ });controls.appendChild(button);
771
+ });
772
+ item.insertBefore(controls,item.querySelector('.otrade')||null);
773
+ });
774
+ var spectrumStops=[].slice.call(card.querySelectorAll('.sstop'));
775
+ spectrumStops.forEach(function(stop,index){
776
+ var position=Number(stop.dataset.pos),label=stop.dataset.label||(stop.querySelector('.slabel')||{}).textContent||String(position);
777
+ stop.setAttribute('role','radio');stop.setAttribute('tabindex','0');
778
+ if(!stop.title)stop.title='Choose this stop. Activate it again to clear.';
779
+ function activate(){
780
+ delete state.undecided[did];
781
+ var selected=channelFor('spectrum')[did],already=selected&&Number(selected.position)===position;
782
+ if(already)delete channelFor('spectrum')[did];else channelFor('spectrum')[did]={position:position,label:label};
783
+ syncLegacyDecision(did,mode);renderDecision(card,did);saveState();updateProgress();
784
+ }
785
+ stop.addEventListener('click',activate);
786
+ stop.addEventListener('keydown',function(event){
787
+ if(event.key==='Enter'||event.key===' '){event.preventDefault();activate();return;}
788
+ var next=index;
789
+ if(event.key==='ArrowRight'||event.key==='ArrowDown')next=(index+1)%spectrumStops.length;
790
+ else if(event.key==='ArrowLeft'||event.key==='ArrowUp')next=(index+spectrumStops.length-1)%spectrumStops.length;
791
+ else if(event.key==='Home')next=0;
792
+ else if(event.key==='End')next=spectrumStops.length-1;
793
+ else return;
794
+ event.preventDefault();spectrumStops[next].focus();
795
+ });
796
+ });
797
+ var control=card.querySelector('.undecided-control');
798
+ if(!control){
799
+ control=document.createElement('button');control.type='button';control.className='undecided-control';
800
+ var label=document.createElement('span'),when=document.createElement('span');
801
+ label.textContent='Leave this open';when.className='uwhen';when.textContent='comes back once, differently';
802
+ control.appendChild(label);control.appendChild(when);
803
+ var noteField=card.querySelector('.dnote');card.insertBefore(control,noteField||null);
804
+ }
805
+ control.setAttribute('aria-label','Leave this question open; it will return once in a different form');
806
+ control.addEventListener('click',function(){
807
+ var already=hasState(state.undecided,did);clearDecision(did,mode);
808
+ if(!already)state.undecided[did]=true;
809
+ syncLegacyDecision(did,mode);
810
+ renderDecision(card,did);saveState();updateProgress();
811
+ });
488
812
  var nt=card.querySelector('.dnote');
489
- if(nt){ if(state.notes[did])nt.value=state.notes[did];
490
- nt.addEventListener('input', function(){state.notes[did]=nt.value; saveState();}); }
813
+ if(nt){
814
+ if(state.notes[did])nt.value=state.notes[did];
815
+ nt.addEventListener('input',function(){
816
+ if(nt.value.trim()){
817
+ state.notes[did]=nt.value;
818
+ if(!selectedForDecision(did,mode))state.undecided[did]=true;
819
+ }else delete state.notes[did];
820
+ syncLegacyDecision(did,mode);
821
+ renderDecision(card,did);saveState();updateProgress();
822
+ });
823
+ }
824
+ renderDecision(card,did);
491
825
  });
492
826
  document.querySelectorAll('.oprompt .otext').forEach(function(t){
493
827
  var oid=t.dataset.open;
494
828
  if(state.opens[oid])t.value=state.opens[oid];
495
- t.addEventListener('input', function(){state.opens[oid]=t.value; saveState(); updateProgress();});
829
+ t.addEventListener('input',function(){if(t.value.trim())state.opens[oid]=t.value;else delete state.opens[oid];saveState();updateProgress();});
496
830
  });
497
831
  updateProgress();
498
832
  }
833
+ function fenceMeta(){
834
+ return {slug:SLUG,version:__VERSION__,surfaceId:'__SURFACE_ID__',harvestId:'__HARVEST_ID__',date:'__DATE__',
835
+ forkOrder:[].slice.call(document.querySelectorAll('.dcard')).map(function(c){return c.dataset.decision;}),
836
+ forkOptions:[].slice.call(document.querySelectorAll('.dcard')).reduce(function(all,c){var mode=cardMode(c),selector=mode==='spectrum'?'.sstop':mode==='rank'?'.rank-item':'.opt';all[c.dataset.decision]=[].slice.call(c.querySelectorAll(selector)).map(function(o){return mode==='spectrum'?o.dataset.pos:o.dataset.opt;});return all;},{}),
837
+ forkLabels:[].slice.call(document.querySelectorAll('.dcard')).reduce(function(all,c){var mode=cardMode(c),selector=mode==='spectrum'?'.sstop':mode==='rank'?'.rank-item':'.opt';all[c.dataset.decision]={};[].slice.call(c.querySelectorAll(selector)).forEach(function(o){var key=mode==='spectrum'?o.dataset.pos:o.dataset.opt;all[c.dataset.decision][key]=o.dataset.label||(o.querySelector(mode==='spectrum'?'.slabel':mode==='rank'?'.rank-label,.olabel':'.olabel')||{}).textContent||key;});return all;},{}),
838
+ forkEnds:[].slice.call(document.querySelectorAll('.dcard')).reduce(function(all,c){if(cardMode(c)==='spectrum')all[c.dataset.decision]=[c.dataset.left,c.dataset.right];return all;},{}),
839
+ forkModes:[].slice.call(document.querySelectorAll('.dcard')).reduce(function(all,c){all[c.dataset.decision]=cardMode(c);return all;},{}),
840
+ forkMax:[].slice.call(document.querySelectorAll('.dcard')).reduce(function(all,c){if(cardMode(c)==='multi')all[c.dataset.decision]=cardMax(c);return all;},{}),
841
+ promptOrder:[].slice.call(document.querySelectorAll('.oprompt')).map(function(o){return o.dataset.openid||(o.querySelector('.otext')||{}).dataset.open;})};
842
+ }
499
843
  function buildBlock(){
500
- var cards=[].slice.call(document.querySelectorAll('.dcard'));
501
- var opens=[].slice.call(document.querySelectorAll('.oprompt'));
502
- var out='#'+SLUG+'-decisions:v__VERSION__\n'
503
- +'surface: __SURFACE_ID__\n'
504
- +'harvest: __HARVEST_ID__\n'
505
- +'date: __DATE__\n\n';
506
- cards.forEach(function(c,i){ var did=c.dataset.decision, sel=state.decisions[did];
507
- out+='Q'+(i+1)+' '+did+': '+(sel?sel.key+' ("'+sel.label+'")':'UNDECIDED')+'\n';
508
- if(state.notes[did] && state.notes[did].trim()) out+=' note: '+state.notes[did].trim().replace(/\n+/g,' ')+'\n';
509
- });
510
- if(opens.length) out+='\n';
511
- opens.forEach(function(o,i){ var oid=o.dataset.openid||(o.querySelector('.otext')||{}).dataset.open;
512
- var ans=(state.opens[oid]||'').trim();
513
- out+='O'+(i+1)+' '+oid+': '+(ans?ans.replace(/\n+/g,' '):'UNDECIDED')+'\n';
514
- });
515
- return out;
844
+ return window.__scroll.buildDecisionsFence(state,fenceMeta());
516
845
  }
517
846
  function updateProgress(){
518
- var total=document.querySelectorAll('.dcard').length, done=Object.keys(state.decisions).length;
847
+ var progress=window.__scroll.decisionProgress(state,fenceMeta()),total=progress.total,done=progress.done;
519
848
  var oTotal=document.querySelectorAll('.oprompt').length, oDone=Object.values(state.opens).filter(function(v){return v&&v.trim();}).length;
520
849
  var el=document.getElementById('prog'); if(el) el.innerHTML='<b>'+done+'</b>/'+total+' forks · <b>'+oDone+'</b>/'+oTotal+' prompts';
521
850
  var pre=document.querySelector('#copyblock pre'); if(pre) pre.textContent=buildBlock();
@@ -532,7 +861,7 @@ function togglePreview(force){
532
861
  cb.classList.toggle('show', force===true?true:!cb.classList.contains('show'));
533
862
  }
534
863
  (function(){
535
- loadState();
864
+ loadState();state=window.__scroll.pruneState(state,fenceMeta());saveState();
536
865
  if(window.__egTheme) __egTheme.init();
537
866
  buildRail(); wireHarvest();
538
867
  var h=location.hash.replace('#',''); if(h==='harvest') showView('harvest');
@@ -17,9 +17,13 @@ when it is available; otherwise render compact numbered choices with an
17
17
 
18
18
  1. Read `.claude/skills/session-view/SKILL.md` for the workflow details.
19
19
  2. Run the referenced `bin/` scripts directly from Codex.
20
- 3. Treat graph, publish, and notify steps as best-effort unless that workflow
21
- explicitly says they are required.
22
- 4. Keep local-mode behavior filesystem-first and avoid graph or notification
20
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
21
+ says they are required.
22
+ 4. For every external notification, follow
23
+ `.claude/context/notification-consent.md`: plan without sending, then show
24
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
25
+ consent from the workflow request or a batch approval.
26
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
23
27
  calls when `egregore.json` declares `"mode": "local"`.
24
- 5. Never call the deprecated `egregore-handoff` CLI for Egregore project
28
+ 6. Never call the deprecated `egregore-handoff` CLI for Egregore project
25
29
  handoffs.
@@ -17,9 +17,13 @@ when it is available; otherwise render compact numbered choices with an
17
17
 
18
18
  1. Read `.claude/skills/setup/SKILL.md` for the workflow details.
19
19
  2. Run the referenced `bin/` scripts directly from Codex.
20
- 3. Treat graph, publish, and notify steps as best-effort unless that workflow
21
- explicitly says they are required.
22
- 4. Keep local-mode behavior filesystem-first and avoid graph or notification
20
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
21
+ says they are required.
22
+ 4. For every external notification, follow
23
+ `.claude/context/notification-consent.md`: plan without sending, then show
24
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
25
+ consent from the workflow request or a batch approval.
26
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
23
27
  calls when `egregore.json` declares `"mode": "local"`.
24
- 5. Never call the deprecated `egregore-handoff` CLI for Egregore project
28
+ 6. Never call the deprecated `egregore-handoff` CLI for Egregore project
25
29
  handoffs.
@@ -33,9 +33,13 @@ reading `.claude/skills/summon/SKILL.md`, reproduce the same visible UX in Codex
33
33
 
34
34
  1. Read `.claude/skills/summon/SKILL.md` for the workflow details.
35
35
  2. Run the referenced `bin/` scripts directly from Codex.
36
- 3. Treat graph, publish, and notify steps as best-effort unless that workflow
37
- explicitly says they are required.
38
- 4. Keep local-mode behavior filesystem-first and avoid graph or notification
36
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
37
+ says they are required.
38
+ 4. For every external notification, follow
39
+ `.claude/context/notification-consent.md`: plan without sending, then show
40
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
41
+ consent from the workflow request or a batch approval.
42
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
39
43
  calls when `egregore.json` declares `"mode": "local"`.
40
- 5. Never call the deprecated `egregore-handoff` CLI for Egregore project
44
+ 6. Never call the deprecated `egregore-handoff` CLI for Egregore project
41
45
  handoffs.
@@ -17,9 +17,13 @@ when it is available; otherwise render compact numbered choices with an
17
17
 
18
18
  1. Read `.claude/skills/sync-repos/SKILL.md` for the workflow details.
19
19
  2. Run the referenced `bin/` scripts directly from Codex.
20
- 3. Treat graph, publish, and notify steps as best-effort unless that workflow
21
- explicitly says they are required.
22
- 4. Keep local-mode behavior filesystem-first and avoid graph or notification
20
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
21
+ says they are required.
22
+ 4. For every external notification, follow
23
+ `.claude/context/notification-consent.md`: plan without sending, then show
24
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
25
+ consent from the workflow request or a batch approval.
26
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
23
27
  calls when `egregore.json` declares `"mode": "local"`.
24
- 5. Never call the deprecated `egregore-handoff` CLI for Egregore project
28
+ 6. Never call the deprecated `egregore-handoff` CLI for Egregore project
25
29
  handoffs.