@litfamily/litgrok 1.0.25 → 1.0.27

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 (227) hide show
  1. package/.grok/hooks/lit-mark.mjs +42 -0
  2. package/.grok/hooks/lit-status-line.mjs +142 -19
  3. package/.grok/hooks/record-passive-event.mjs +21 -2
  4. package/.grok/hooks/session-start.mjs +17 -0
  5. package/.grok/hooks/workflow-stage.mjs +5 -2
  6. package/.grok/rules/00-litgrok.md +13 -0
  7. package/.grok/skills/frontend-ui-ux/ATTRIBUTION.md +23 -0
  8. package/.grok/skills/frontend-ui-ux/SKILL.md +4 -1
  9. package/.grok/skills/frontend-ui-ux/examples/phase-3-readme-ab/README.md +9 -0
  10. package/.grok/skills/frontend-ui-ux/kit/components.css +414 -0
  11. package/.grok/skills/frontend-ui-ux/kit/fonts.json +22 -0
  12. package/.grok/skills/frontend-ui-ux/kit/layouts/landing.html +164 -0
  13. package/.grok/skills/frontend-ui-ux/kit/layouts/settings.html +114 -0
  14. package/.grok/skills/frontend-ui-ux/kit/layouts/workspace.html +115 -0
  15. package/.grok/skills/frontend-ui-ux/kit/styles/computational-brutalism.json +227 -0
  16. package/.grok/skills/frontend-ui-ux/kit/styles/field-notes.json +205 -0
  17. package/.grok/skills/frontend-ui-ux/kit/styles/graphite.json +200 -0
  18. package/.grok/skills/frontend-ui-ux/kit/styles/meadow.json +199 -0
  19. package/.grok/skills/frontend-ui-ux/kit/styles/neo-brutalism.json +222 -0
  20. package/.grok/skills/frontend-ui-ux/kit/ui.js +226 -0
  21. package/.grok/skills/frontend-ui-ux/references/adaptive-layout.md +10 -4
  22. package/.grok/skills/frontend-ui-ux/references/brand-and-imagery.md +11 -7
  23. package/.grok/skills/frontend-ui-ux/references/complete-contract.md +21 -0
  24. package/.grok/skills/frontend-ui-ux/references/composition.md +10 -6
  25. package/.grok/skills/frontend-ui-ux/references/craft-floor.md +256 -93
  26. package/.grok/skills/frontend-ui-ux/references/creative-directions.md +9 -6
  27. package/.grok/skills/frontend-ui-ux/references/default-editorial-pixel.json +28 -0
  28. package/.grok/skills/frontend-ui-ux/references/house-styles.md +234 -0
  29. package/.grok/skills/frontend-ui-ux/references/implementation-platforms.md +10 -6
  30. package/.grok/skills/frontend-ui-ux/references/inclusive-interface.md +11 -5
  31. package/.grok/skills/frontend-ui-ux/references/interaction-motion.md +34 -78
  32. package/.grok/skills/frontend-ui-ux/references/motion-guide.md +10 -7
  33. package/.grok/skills/frontend-ui-ux/references/performance-delivery.md +11 -8
  34. package/.grok/skills/frontend-ui-ux/references/probe-loop.md +1 -1
  35. package/.grok/skills/frontend-ui-ux/references/product-direction.md +9 -4
  36. package/.grok/skills/frontend-ui-ux/references/production-interview.md +17 -0
  37. package/.grok/skills/frontend-ui-ux/references/redesign-playbook.md +10 -6
  38. package/.grok/skills/frontend-ui-ux/references/slop-register.md +148 -73
  39. package/.grok/skills/frontend-ui-ux/references/system-foundations.md +10 -4
  40. package/.grok/skills/frontend-ui-ux/references/visual-language.md +10 -4
  41. package/.grok/skills/frontend-ui-ux/references/visual-reconstruction.md +39 -72
  42. package/.grok/skills/frontend-ui-ux/scripts/design-lock.mjs +400 -0
  43. package/.grok/skills/frontend-ui-ux/scripts/interface-probe-driver.mjs +33 -0
  44. package/.grok/skills/frontend-ui-ux/scripts/interface-probe-lock.mjs +196 -0
  45. package/.grok/skills/frontend-ui-ux/scripts/interface-probe-page.mjs +1555 -0
  46. package/.grok/skills/frontend-ui-ux/scripts/interface-probe-rules.mjs +153 -0
  47. package/.grok/skills/frontend-ui-ux/scripts/interface-probe-server.mjs +57 -0
  48. package/.grok/skills/frontend-ui-ux/scripts/interface-probe-static.mjs +139 -0
  49. package/.grok/skills/frontend-ui-ux/scripts/interface-probe.mjs +363 -0
  50. package/.grok/skills/frontend-ui-ux/scripts/pixel-art.mjs +60 -0
  51. package/.grok/skills/lit-adhd/SKILL.md +151 -0
  52. package/.grok/skills/lit-adhd/references/card-examples.md +118 -0
  53. package/.grok/skills/lit-adhd/references/status-taxonomy.md +36 -0
  54. package/.grok/skills/lit-adhd/scripts/lib/brief.mjs +370 -0
  55. package/.grok/skills/lit-adhd/scripts/lib/collect.mjs +327 -0
  56. package/.grok/skills/lit-adhd/scripts/lib/gauge.mjs +87 -0
  57. package/.grok/skills/lit-adhd/scripts/lib/next-step.mjs +18 -0
  58. package/.grok/skills/lit-adhd/scripts/lib/plan-task-rows.mjs +32 -0
  59. package/.grok/skills/lit-adhd/scripts/lib/project-state-root.mjs +55 -0
  60. package/.grok/skills/lit-adhd/scripts/lib/redact.mjs +64 -0
  61. package/.grok/skills/lit-adhd/scripts/lib/suggest.mjs +140 -0
  62. package/.grok/skills/lit-adhd/scripts/lib/transcripts.mjs +232 -0
  63. package/.grok/skills/lit-adhd/scripts/rewind.mjs +6 -0
  64. package/.grok/skills/lit-diagram-drawer/SKILL.md +17 -5
  65. package/.grok/skills/lit-diagram-drawer/references/output-spec.md +2 -2
  66. package/.grok/skills/lit-diagram-drawer/references/style-guide.md +20 -11
  67. package/.grok/skills/lit-diagram-drawer/references/type-architecture.md +3 -3
  68. package/.grok/skills/lit-diagram-drawer/references/type-dependency.md +1 -1
  69. package/.grok/skills/lit-diagram-drawer/references/type-tree.md +3 -3
  70. package/.grok/skills/lit-diagram-drawer/references/type-wardley.md +1 -1
  71. package/.grok/skills/lit-diagram-drawer/references/verifier-guide.md +4 -0
  72. package/.grok/skills/lit-diagram-drawer/scripts/visual-quality.mjs +2 -2
  73. package/.grok/skills/lit-handoff/SKILL.md +2 -0
  74. package/.grok/skills/lit-hijack/SKILL.md +459 -0
  75. package/.grok/skills/lit-hijack/references/capture-and-provenance.md +124 -0
  76. package/.grok/skills/lit-hijack/references/clean-room-build.md +130 -0
  77. package/.grok/skills/lit-hijack/references/distil-and-licence.md +128 -0
  78. package/.grok/skills/lit-hijack/references/gap-and-port-design.md +150 -0
  79. package/.grok/skills/lit-hijack/references/parity-and-report.md +130 -0
  80. package/.grok/skills/lit-hijack/scripts/hijack.mjs +890 -0
  81. package/.grok/skills/lit-hijack/scripts/lib/safe-fetch.mjs +213 -0
  82. package/.grok/skills/lit-plan/SKILL.md +1 -1
  83. package/.grok/skills/lit-pptx/SKILL.md +10 -5
  84. package/.grok/skills/lit-pptx/examples/13-engineering-review-computational-brutalism-ko.md +173 -0
  85. package/.grok/skills/lit-pptx/examples/14-launch-pitch-neo-brutalism-ko.md +154 -0
  86. package/.grok/skills/lit-pptx/examples/15-design-lecture-bauhaus-ko.md +139 -0
  87. package/.grok/skills/lit-pptx/examples/16-community-programme-riso-ko.md +158 -0
  88. package/.grok/skills/lit-pptx/examples/17-public-data-briefing-newsroom-ko.md +179 -0
  89. package/.grok/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Bold.ttf +0 -0
  90. package/.grok/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Regular.ttf +0 -0
  91. package/.grok/skills/lit-pptx/fonts/jetbrains-mono/OFL.txt +93 -0
  92. package/.grok/skills/lit-pptx/fonts/jetbrains-mono/provenance.json +1 -0
  93. package/.grok/skills/lit-pptx/references/direction-step.md +34 -8
  94. package/.grok/skills/lit-pptx/references/tonalities/bauhaus.md +140 -0
  95. package/.grok/skills/lit-pptx/references/tonalities/computational-brutalism.md +150 -0
  96. package/.grok/skills/lit-pptx/references/tonalities/neo-brutalism.md +161 -0
  97. package/.grok/skills/lit-pptx/references/tonalities/newsroom.md +144 -0
  98. package/.grok/skills/lit-pptx/references/tonalities/riso.md +137 -0
  99. package/.grok/skills/lit-pptx/scripts/compile-deck.js +1 -1
  100. package/.grok/skills/lit-pptx/scripts/craft_extras.py +61 -3
  101. package/.grok/skills/lit-pptx/scripts/deck_output.py +76 -62
  102. package/.grok/skills/lit-pptx/scripts/embed_fonts.py +14 -1
  103. package/.grok/skills/lit-pptx/scripts/lib/grid-resolver.js +101 -110
  104. package/.grok/skills/lit-pptx/scripts/lib/layout-resolver.js +9 -15
  105. package/.grok/skills/lit-pptx/scripts/lib/render-pack.js +389 -582
  106. package/.grok/skills/lit-pptx/scripts/lib/slide-grid.js +104 -0
  107. package/.grok/skills/lit-pptx/scripts/lib/template-registry.js +60 -8
  108. package/.grok/skills/lit-pptx/scripts/qa_deck.py +4 -4
  109. package/.grok/skills/lit-pptx/templates/tonalities/atlas/pack.yaml +2 -0
  110. package/.grok/skills/lit-pptx/templates/tonalities/bauhaus/pack.yaml +98 -0
  111. package/.grok/skills/lit-pptx/templates/tonalities/chalk/pack.yaml +2 -0
  112. package/.grok/skills/lit-pptx/templates/tonalities/computational-brutalism/pack.yaml +99 -0
  113. package/.grok/skills/lit-pptx/templates/tonalities/gazette/pack.yaml +2 -0
  114. package/.grok/skills/lit-pptx/templates/tonalities/ledger/pack.yaml +2 -0
  115. package/.grok/skills/lit-pptx/templates/tonalities/neo-brutalism/pack.yaml +107 -0
  116. package/.grok/skills/lit-pptx/templates/tonalities/newsroom/pack.yaml +99 -0
  117. package/.grok/skills/lit-pptx/templates/tonalities/night/pack.yaml +2 -0
  118. package/.grok/skills/lit-pptx/templates/tonalities/paper/pack.yaml +2 -0
  119. package/.grok/skills/lit-pptx/templates/tonalities/riso/pack.yaml +99 -0
  120. package/.grok/skills/lit-pptx/templates/tonalities/signal/pack.yaml +3 -0
  121. package/.grok/skills/lit-pptx/templates/tonalities/studio/pack.yaml +2 -0
  122. package/.grok/skills/lit-recap/SKILL.md +1 -1
  123. package/.grok/skills/lit-schematic/SKILL.md +140 -0
  124. package/.grok/skills/lit-schematic/examples/iso-heat-exchanger/build.mjs +38 -0
  125. package/.grok/skills/lit-schematic/examples/iso-heat-exchanger/scene.mjs +133 -0
  126. package/.grok/skills/lit-schematic/examples/journal-adsorption-rig/build.mjs +87 -0
  127. package/.grok/skills/lit-schematic/examples/pid-dosing-skid/build.mjs +85 -0
  128. package/.grok/skills/lit-schematic/references/cutaway-outputs.md +70 -0
  129. package/.grok/skills/lit-schematic/references/isometric-craft.md +101 -0
  130. package/.grok/skills/lit-schematic/references/journal-figures.md +72 -0
  131. package/.grok/skills/lit-schematic/references/kit-api.md +134 -0
  132. package/.grok/skills/lit-schematic/references/pfd-and-layout.md +53 -0
  133. package/.grok/skills/lit-schematic/references/pid-drafting.md +103 -0
  134. package/.grok/skills/lit-schematic/references/pid-symbols.md +163 -0
  135. package/.grok/skills/lit-schematic/references/verification.md +100 -0
  136. package/.grok/skills/lit-schematic/scripts/doctor.mjs +57 -0
  137. package/.grok/skills/lit-schematic/scripts/lib/figure.mjs +81 -0
  138. package/.grok/skills/lit-schematic/scripts/lib/fonts.mjs +27 -0
  139. package/.grok/skills/lit-schematic/scripts/lib/geom.mjs +113 -0
  140. package/.grok/skills/lit-schematic/scripts/lib/interactive.mjs +292 -0
  141. package/.grok/skills/lit-schematic/scripts/lib/isa.mjs +115 -0
  142. package/.grok/skills/lit-schematic/scripts/lib/iso.mjs +719 -0
  143. package/.grok/skills/lit-schematic/scripts/lib/legend-sheet.mjs +162 -0
  144. package/.grok/skills/lit-schematic/scripts/lib/pid.mjs +937 -0
  145. package/.grok/skills/lit-schematic/scripts/lib/png.mjs +132 -0
  146. package/.grok/skills/lit-schematic/scripts/lib/qa-core.mjs +658 -0
  147. package/.grok/skills/lit-schematic/scripts/lib/route.mjs +218 -0
  148. package/.grok/skills/lit-schematic/scripts/lib/sheet.mjs +890 -0
  149. package/.grok/skills/lit-schematic/scripts/lib/svg.mjs +82 -0
  150. package/.grok/skills/lit-schematic/scripts/lib/theme.mjs +115 -0
  151. package/.grok/skills/lit-schematic/scripts/motion.mjs +129 -0
  152. package/.grok/skills/lit-schematic/scripts/qa.mjs +92 -0
  153. package/.grok/skills/lit-schematic/scripts/render.mjs +233 -0
  154. package/.grok/skills/lit-schematic/scripts/scaffold.mjs +60 -0
  155. package/.grok/skills/lit-scientific-visualization/SKILL.md +36 -12
  156. package/.grok/skills/lit-typographic-motion/SKILL.md +7 -4
  157. package/.grok/skills/lit-typographic-motion/THIRD_PARTY_NOTICES +11 -0
  158. package/.grok/skills/lit-typographic-motion/recipes/hero-3d/expected.json +62 -0
  159. package/.grok/skills/lit-typographic-motion/recipes/hero-3d/index.html +82 -0
  160. package/.grok/skills/lit-typographic-motion/references/choice-first.md +30 -0
  161. package/.grok/skills/lit-typographic-motion/references/cover.md +10 -1
  162. package/.grok/skills/lit-typographic-motion/references/depth.md +119 -0
  163. package/.grok/skills/lit-typographic-motion/references/treatment.md +9 -1
  164. package/.grok/skills/lit-typographic-motion/requirements-audio.txt +3 -3
  165. package/.grok/skills/lit-typographic-motion/scripts/blender/runner.py +218 -0
  166. package/.grok/skills/lit-typographic-motion/scripts/lib/assets.mjs +230 -0
  167. package/.grok/skills/lit-typographic-motion/scripts/lib/blender.mjs +136 -0
  168. package/.grok/skills/lit-typographic-motion/scripts/lib/board.mjs +153 -0
  169. package/.grok/skills/lit-typographic-motion/scripts/lib/chrome.mjs +61 -32
  170. package/.grok/skills/lit-typographic-motion/scripts/lib/constants.mjs +4 -2
  171. package/.grok/skills/lit-typographic-motion/scripts/lib/cover-capture.mjs +20 -11
  172. package/.grok/skills/lit-typographic-motion/scripts/lib/cover-treatment.mjs +26 -2
  173. package/.grok/skills/lit-typographic-motion/scripts/lib/cover.mjs +12 -5
  174. package/.grok/skills/lit-typographic-motion/scripts/lib/frame-pool.mjs +78 -1
  175. package/.grok/skills/lit-typographic-motion/scripts/lib/gallery.mjs +160 -0
  176. package/.grok/skills/lit-typographic-motion/scripts/lib/house.mjs +43 -0
  177. package/.grok/skills/lit-typographic-motion/scripts/lib/look.mjs +39 -1
  178. package/.grok/skills/lit-typographic-motion/scripts/lib/scaffold.mjs +174 -0
  179. package/.grok/skills/lit-typographic-motion/scripts/lib/score.mjs +640 -0
  180. package/.grok/skills/lit-typographic-motion/scripts/lib/sound.mjs +143 -0
  181. package/.grok/skills/lit-typographic-motion/scripts/lib/soundtrack.mjs +12 -3
  182. package/.grok/skills/lit-typographic-motion/scripts/lib/stage-gate.mjs +44 -0
  183. package/.grok/skills/lit-typographic-motion/scripts/lib/stage-qa.mjs +132 -3
  184. package/.grok/skills/lit-typographic-motion/scripts/lib/stage-session.mjs +51 -3
  185. package/.grok/skills/lit-typographic-motion/scripts/lib/stage.mjs +74 -9
  186. package/.grok/skills/lit-typographic-motion/scripts/lib/styles.mjs +224 -0
  187. package/.grok/skills/lit-typographic-motion/scripts/lib/treatment.mjs +198 -4
  188. package/.grok/skills/lit-typographic-motion/scripts/lib/vendor/three/LICENSE +21 -0
  189. package/.grok/skills/lit-typographic-motion/scripts/lib/vendor/three/addons/environments/RoomEnvironment.js +144 -0
  190. package/.grok/skills/lit-typographic-motion/scripts/lib/vendor/three/addons/geometries/RoundedBoxGeometry.js +155 -0
  191. package/.grok/skills/lit-typographic-motion/scripts/lib/vendor/three/three.module.js +54571 -0
  192. package/.grok/skills/lit-typographic-motion/scripts/motion.mjs +56 -6
  193. package/.grok/skills/lit-typographic-motion/scripts/stage/cover-init.js +20 -8
  194. package/.grok/skills/lit-typographic-motion/scripts/stage/loop-kit.js +2 -2
  195. package/.grok/skills/lit-typographic-motion/scripts/stage/stage-kit.js +25 -0
  196. package/.grok/skills/lit-typographic-motion/styles/paper.json +1 -0
  197. package/.grok/skills/lit-typographic-motion/styles/swiss-signal.json +1 -0
  198. package/.grok/skills/lit-typographic-motion/styles/terminalcore.json +1 -0
  199. package/.grok/skills/lit-typographic-motion/styles/tidal.json +1 -0
  200. package/.grok/skills/litgrok/SKILL.md +1 -1
  201. package/.grok/skills/litresearch/SKILL.md +2 -0
  202. package/.grok/skills/readme-studio/SKILL.md +14 -12
  203. package/.grok/skills/readme-studio/references/choice-first.md +24 -0
  204. package/.grok/skills/readme-studio/templates/hyperframes/package-lock.json +3 -3
  205. package/.grok/skills/readme-studio/templates/remotion/package-lock.json +3 -3
  206. package/.grok/skills/start-work/SKILL.md +1 -1
  207. package/.grok-plugin/plugin.json +4 -1
  208. package/CHANGELOG.md +16 -0
  209. package/README.md +11 -11
  210. package/README_ko-KR.md +11 -11
  211. package/docs/assets/readme/badge-version.svg +1 -1
  212. package/docs/assets/showcase/brief.webp +0 -0
  213. package/docs/assets/showcase/deck.webp +0 -0
  214. package/docs/assets/showcase/page.webp +0 -0
  215. package/docs/assets/showcase/pid.webp +0 -0
  216. package/docs/assets/skills/lit-adhd.webp +0 -0
  217. package/docs/assets/skills/lit-hijack.webp +0 -0
  218. package/docs/assets/skills/lit-schematic.webp +0 -0
  219. package/docs/reference.md +5 -5
  220. package/docs/reference_ko-KR.md +5 -5
  221. package/package.json +5 -1
  222. package/plugin.json +1 -1
  223. package/.grok/skills/frontend-ui-ux/scripts/page-probe.mjs +0 -105
  224. package/.grok/skills/frontend-ui-ux/scripts/probe.mjs +0 -91
  225. package/.grok/skills/frontend-ui-ux/scripts/rule-data.mjs +0 -56
  226. package/.grok/skills/frontend-ui-ux/scripts/static-probe.mjs +0 -27
  227. package/.grok/skills/frontend-ui-ux/scripts/static-server.mjs +0 -19
@@ -104,6 +104,48 @@ export function lockup(productName) {
104
104
  return standard.map((row, index) => row.padEnd(28) + (index === 5 ? ` ${label}` : ''));
105
105
  }
106
106
 
107
+ // The psychedelic rewind hue for the lit-adhd card and ignition mark: one hue at a time at a
108
+ // steady lightness, so the card never flashes. `motion` is 'full' (a 24-second hue cycle),
109
+ // 'subtle' (a slow 96-second drift) or 'off' (one still rainbow frame). Returns [r, g, b].
110
+ export function rewindHue(nowMs, motion = 'full') {
111
+ return hueToRgb(rewindBaseAngle(nowMs, motion));
112
+ }
113
+
114
+ // One full wheel across a run of `total` cells, so each cell of a pill or mark takes its own
115
+ // step round the wheel at the same steady lightness. Colour moves only on fixed glyphs.
116
+ export function rewindCellRgb(nowMs, motion, index, total) {
117
+ const base = rewindBaseAngle(nowMs, motion);
118
+ const step = total > 1 ? 360 / total : 0;
119
+ return hueToRgb((((base + step * index) % 360) + 360) % 360);
120
+ }
121
+
122
+ function rewindBaseAngle(nowMs, motion = 'full') {
123
+ if (motion !== 'subtle' && motion !== 'off' && motion !== 'full') motion = 'full';
124
+ const time = Number.isFinite(nowMs) ? nowMs : 0;
125
+ const hue = motion === 'off' ? 280 : (((time % 96_000) + 96_000) % 96_000) / 96_000 * 360;
126
+ const period = motion === 'subtle' ? 1 : 4;
127
+ return (((hue * period) % 360) + 360) % 360;
128
+ }
129
+
130
+ function hueToRgb(angle) {
131
+ const saturation = 0.85;
132
+ const lightness = 0.62;
133
+ const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;
134
+ const part = chroma * (1 - Math.abs(((angle / 60) % 2) - 1));
135
+ const match = lightness - chroma / 2;
136
+ let red;
137
+ let green;
138
+ let blue;
139
+ if (angle < 60) [red, green, blue] = [chroma, part, 0];
140
+ else if (angle < 120) [red, green, blue] = [part, chroma, 0];
141
+ else if (angle < 180) [red, green, blue] = [0, chroma, part];
142
+ else if (angle < 240) [red, green, blue] = [0, part, chroma];
143
+ else if (angle < 300) [red, green, blue] = [part, 0, chroma];
144
+ else [red, green, blue] = [chroma, 0, part];
145
+ const channel = (value) => Math.max(0, Math.min(255, Math.round((value + match) * 255)));
146
+ return [channel(red), channel(green), channel(blue)];
147
+ }
148
+
107
149
  export function colorize(rows, { mode = 'none' } = {}) {
108
150
  if (!['truecolor', '256', 'none'].includes(mode)) throw new TypeError('Invalid color mode');
109
151
  if (mode === 'none') return [...rows];
@@ -5,6 +5,7 @@ import { closeSync, constants, fstatSync, openSync, readFileSync, readSync, real
5
5
  import { dirname, isAbsolute, join } from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
7
  import { resolveAutoHandoff } from './auto-handoff.mjs';
8
+ import { rewindCellRgb } from './lit-mark.mjs';
8
9
  import { readHudRecordForCwd, writeContextRecord } from './litgrok-hud-state.mjs';
9
10
  import { STAGES, readWorkflowState } from './workflow-stage.mjs';
10
11
 
@@ -38,17 +39,17 @@ const GLYPHS = {
38
39
  basic: {
39
40
  fire: '🔥', tick: '✓', cross: '✗', dot: '·', lit: '━', unlit: '─', run: '●', warn: '⚠', elbow: '└', next: '▸', sep: '│',
40
41
  full: '▮', empty: '▯', rail: '▎', ellipsis: '…', spinner: BRAILLE, bar: ['█', '░', ['', '▏', '▎', '▍', '▌', '▋', '▊', '▉']],
41
- timer: '', tools: (n) => plural(n, 'tool'), agents: (n) => plural(n, 'agent'), git: 'git ',
42
+ timer: '', burst: '★', tools: (n) => plural(n, 'tool'), agents: (n) => plural(n, 'agent'), git: 'git ',
42
43
  },
43
44
  nerd: {
44
45
  fire: '🔥', tick: '', cross: '', dot: '·', lit: '━', unlit: '─', run: '', warn: '', elbow: '└', next: '▸', sep: '│',
45
46
  full: '▮', empty: '▯', rail: '▎', ellipsis: '…', spinner: BRAILLE, bar: ['█', '░', ['', '▏', '▎', '▍', '▌', '▋', '▊', '▉']],
46
- timer: ' ', tools: (n) => ` ${n}`, agents: (n) => ` ${n}`, git: ' ',
47
+ timer: ' ', burst: '★', tools: (n) => ` ${n}`, agents: (n) => ` ${n}`, git: ' ',
47
48
  },
48
49
  ascii: {
49
50
  fire: '', tick: '+', cross: 'x', dot: '-', lit: '=', unlit: '-', run: '*', warn: '!', elbow: '`', next: '>', sep: '|',
50
51
  full: '#', empty: '-', rail: '|', ellipsis: '~', spinner: ['|', '/', '-', '\\'], bar: ['#', '-', ['']],
51
- timer: '', tools: (n) => plural(n, 'tool'), agents: (n) => plural(n, 'agent'), git: 'git ',
52
+ timer: '', burst: '*', tools: (n) => plural(n, 'tool'), agents: (n) => plural(n, 'agent'), git: 'git ',
52
53
  },
53
54
  };
54
55
  // Grok's own tool names, shortened to the words people know them by. Any other name shows as sent.
@@ -158,9 +159,17 @@ function painter(depth) {
158
159
  return {
159
160
  depth,
160
161
  fg: (text, role, bold = false) => (depth && text ? `${bold ? '\u001b[1m' : ''}${sgr(ROLES[role], depth)}${text}\u001b[0m` : text),
162
+ hue: (text, rgb, bold = false) => (depth && text ? `${bold ? '\u001b[1m' : ''}${sgr(rgb, depth)}${text}\u001b[0m` : text),
161
163
  };
162
164
  }
163
165
 
166
+ // The rewind look's motion: 'full' cycles the hue, 'subtle' drifts it slowly, 'off' holds one still
167
+ // rainbow frame. Anything else is 'full'.
168
+ function hudMotion(env = process.env) {
169
+ const motion = (env.LITGROK_HUD_MOTION ?? 'full').toLowerCase();
170
+ return motion === 'off' || motion === 'subtle' ? motion : 'full';
171
+ }
172
+
164
173
  // A filled chip on the pink (the brand) or the accent (the current stage) with dark text and a space of
165
174
  // padding each side; a Nerd Font gives it rounded caps, and without colour it falls back to brackets.
166
175
  function chip(text, background, paint, nerd, open = '(', close = ')') {
@@ -474,13 +483,68 @@ function disciplineName(name, glyphs, cells = Infinity) {
474
483
  return clipCells(name, Math.min(cells, name === 'lit-scientific-visualization' ? 32 : 24), glyphs.ellipsis);
475
484
  }
476
485
 
486
+ // The look registry: a discipline maps to one look, and every route that runs a skill goes through
487
+ // the collector's discipline, so bare words, slash commands, skill loads and aliases all select it.
488
+ // Grok's one line can only tint and label, so a look is a tint plus a label (the card adds the pill).
489
+ const LOOKS = { 'lit-adhd': 'rewind', 'review-work': 'lanes' };
490
+ function lookOf(discipline, stage = null) {
491
+ if (typeof discipline === 'string' && Object.hasOwn(LOOKS, discipline)) return LOOKS[discipline];
492
+ if (stage === 'review') return 'lanes';
493
+ return 'plain';
494
+ }
495
+
496
+ // review-work's six lanes. Progress is real only: the test lane follows the workflow test verdict
497
+ // and a lane with no report stays dim, never a fake fill.
498
+ const REVIEW_LANES = ['behavior', 'test', 'safety', 'integration', 'documentation', 'regression'];
499
+ function laneStates(workflow) {
500
+ const verdict = workflow?.test?.verdict;
501
+ return REVIEW_LANES.map((name) => ({
502
+ name,
503
+ state: name === 'test' && (verdict === 'pass' || verdict === 'fail') ? verdict : 'unreported',
504
+ }));
505
+ }
506
+
507
+ // Waiting on the user: a held plan gate (the typed start-work boundary) or a live Ask tool call.
508
+ // The next UserPromptSubmit starts a new turn, so the label stops the moment the user types.
509
+ function waitingOf(activity) {
510
+ if (!activity) return null;
511
+ if (activity.planGate) return { reason: 'plan gate' };
512
+ if (activity.live?.name === 'ask_user_question') return { reason: 'question' };
513
+ return null;
514
+ }
515
+
477
516
  // The ignition mark of the one-line row: the pink 🔥 LIT chip, then IGNITED · <discipline> 🔥 in the accent.
478
517
  // Without colour it reads 🔥 LIT IGNITED · <discipline> 🔥. A narrow row clips the discipline, never the frame.
518
+ // While lit-adhd is the discipline the mark keeps its shape but the discipline rides a hue that turns
519
+ // (one still rainbow frame when the HUD motion is off): the tint, never a flash.
479
520
  function ignitionSegment(discipline, glyphs, paint, nerd, options = {}) {
480
521
  const label = glyphs.fire ? `${glyphs.fire} LIT` : 'LIT';
481
522
  const brand = chip(label, 'pink', paint, nerd, '', '');
482
523
  const build = (name) => `${brand.plain} IGNITED ${glyphs.dot} ${name}${glyphs.fire ? ` ${glyphs.fire}` : ''}`;
483
524
  const frame = width(build(''));
525
+ const ignitionLook = options.look ?? lookOf(discipline);
526
+ if (ignitionLook === 'rewind') {
527
+ // Each cell of the mark past the brand rides its own step round the wheel (one still rainbow
528
+ // frame when the HUD motion is off): the tint, never a flash.
529
+ const motion = hudMotion();
530
+ const when = options.now ?? Date.now();
531
+ const rainbow = (text) => {
532
+ const cells = [...text];
533
+ return cells.map((cell, index) => paint.hue(cell, rewindCellRgb(when, motion, index, cells.length), true)).join('');
534
+ };
535
+ return segment(build(disciplineName(discipline, glyphs)), (text) => `${brand.painted}${rainbow(text.slice(brand.plain.length))}`, {
536
+ ...options, minCells: frame + 1, shrink: (cells) => build(disciplineName(discipline, glyphs, Math.max(1, cells - frame))),
537
+ });
538
+ }
539
+ if (ignitionLook === 'lanes') {
540
+ const lanes = options.lanes ?? laneStates(null);
541
+ const reported = lanes.filter((lane) => lane.state !== 'unreported').length;
542
+ const full = build(`REVIEW ${reported}/${lanes.length}`);
543
+ return segment(full, (text) => `${brand.painted}${paint.fg(text.slice(brand.plain.length), 'accent', true)}`, {
544
+ ...options, minCells: frame + 1,
545
+ shrink: (cells) => (cells < width(full) ? clipCells(full, Math.max(1, cells), glyphs.ellipsis) : full),
546
+ });
547
+ }
484
548
  return segment(build(disciplineName(discipline, glyphs)), (text) => `${brand.painted}${paint.fg(text.slice(brand.plain.length), 'accent', true)}`, {
485
549
  ...options, minCells: frame + 1, shrink: (cells) => build(disciplineName(discipline, glyphs, Math.max(1, cells - frame))),
486
550
  });
@@ -498,11 +562,23 @@ function figureLeads(figures, glyphs, paint, afterMark) {
498
562
  // handoff percent, cost and branch. It is the whole HUD between workflows and in LITGROK_HUD_LINES=1
499
563
  // mode. A narrow row gives up the branch, the handoff percent, the cost and the version, then clips the
500
564
  // model name and last the discipline.
501
- function compactRow({ status, discipline, version, glyphs, paint, nerd, handoff, maxCells }) {
565
+ function compactRow({ status, discipline, version, glyphs, paint, nerd, handoff, maxCells, looks = null, phase = null }) {
502
566
  const [model, context, ...extras] = figureSegments(status, { glyphs, paint, handoff });
503
- const figures = [model, context, ...(discipline ? [ignitionSegment(discipline, glyphs, paint, nerd, { clip: 1 })] : []), ...extras];
567
+ const figures = [model, context];
568
+ if (discipline) {
569
+ figures.push(looks?.look === 'lanes'
570
+ ? ignitionSegment(discipline, glyphs, paint, nerd, { clip: 1, lanes: looks.lanes, look: looks.look })
571
+ : ignitionSegment(discipline, glyphs, paint, nerd, { clip: 1 }));
572
+ }
573
+ figures.push(...extras);
504
574
  const left = [brandSegment(version, glyphs, paint, { clip: 3 }), ...figureLeads(figures, glyphs, paint, true)];
505
- return layoutLine({ left, separator: { plain: ' ', painted: ' ' }, rail: { plain: '', painted: '' }, maxCells, ellipsis: glyphs.ellipsis });
575
+ const right = [];
576
+ if (looks?.waiting) right.push(segment(`YOUR TURN · ${looks.waiting.reason}`, (text) => paint.fg(text, 'yellow', true), {
577
+ drop: 0.6, clip: 3, minCells: width('YOUR TURN'),
578
+ shrink: (cells) => (cells < width(`YOUR TURN · ${looks.waiting.reason}`) ? clipCells('YOUR TURN', Math.max(1, cells), glyphs.ellipsis) : `YOUR TURN · ${looks.waiting.reason}`),
579
+ }));
580
+ if (looks?.burst) right.push(segment(`${glyphs.burst} complete${phase?.timer ? ` ${phase.timer}` : ''}`, (text) => paint.fg(text, 'pink', true), { drop: 1 }));
581
+ return layoutLine({ left, right, separator: { plain: ' ', painted: ' ' }, rail: { plain: '', painted: '' }, maxCells, ellipsis: glyphs.ellipsis });
506
582
  }
507
583
 
508
584
  // The current stage's label: its name, the plan's checked tasks while working, and a tick once the
@@ -584,14 +660,50 @@ function railFor(paint, glyphs) {
584
660
  // The card's title: the mark, the pink 🔥 LIT chip and the discipline, then at the right edge the turn's
585
661
  // tool calls and subagents beside its state, as the family card's corner reads (● 1m42s running,
586
662
  // ✓ complete, ⚠ a warning, idle).
587
- function titleLine({ discipline, version, glyphs, paint, nerd, phase, warning, activity, maxCells, rail }) {
663
+ function titleLine({ discipline, version, glyphs, paint, nerd, phase, warning, activity, maxCells, rail, now, looks = null }) {
588
664
  const brand = chip(glyphs.fire ? `${glyphs.fire} LIT` : 'LIT', 'pink', paint, nerd);
589
665
  const name = discipline ?? 'workflow';
666
+ const look = looks?.look ?? lookOf(discipline);
667
+ const lanes = look === 'lanes' ? (looks?.lanes ?? laneStates(null)) : null;
668
+ const reported = lanes ? lanes.filter((lane) => lane.state !== 'unreported').length : 0;
669
+ // The rewind pill rides the wheel cell by cell, like the ignition mark below. The lanes pill
670
+ // names review-work's six lanes; a lane with a verdict takes its colour, the rest stay dim.
671
+ const nameText = look === 'rewind' ? `✺ REWIND ${disciplineName(name, glyphs)}`
672
+ : lanes ? `REVIEW ${lanes.map((lane) => lane.name).join(' · ')}` : `${glyphs.dot} ${disciplineName(name, glyphs)}`;
673
+ const paintLane = (laneName) => {
674
+ const state = lanes.find((lane) => lane.name === laneName)?.state;
675
+ if (state === 'pass') return paint.fg(laneName, 'green', true);
676
+ if (state === 'fail') return paint.fg(laneName, 'red', true);
677
+ return paint.fg(laneName, 'dim');
678
+ };
679
+ const namePaint = look === 'rewind'
680
+ ? (text) => {
681
+ const motion = hudMotion();
682
+ const when = now ?? Date.now();
683
+ const cells = [...text];
684
+ return cells.map((cell, index) => paint.hue(cell, rewindCellRgb(when, motion, index, cells.length), true)).join('');
685
+ }
686
+ : lanes
687
+ ? (text) => {
688
+ const prefix = 'REVIEW ';
689
+ if (!text.startsWith(prefix)) return paint.fg(text, 'accent', true);
690
+ const names = text.slice(prefix.length).split(' · ');
691
+ const painted = names.map((laneName) => (lanes.some((lane) => lane.name === laneName)
692
+ ? paintLane(laneName) : paint.fg(laneName, 'accent', true)));
693
+ return `${paint.fg(prefix, 'accent', true)}${painted.join(paint.fg(' · ', 'dim'))}`;
694
+ }
695
+ : (text) => `${paint.fg(glyphs.dot, 'dim')} ${paint.fg(text.slice(glyphs.dot.length + 1), discipline ? 'accent' : 'dim', Boolean(discipline))}`;
696
+ const shrinkName = lanes
697
+ ? (cells) => {
698
+ const short = `REVIEW ${reported}/${lanes.length}`;
699
+ return cells < width(nameText) ? clipCells(short, Math.max(1, cells), glyphs.ellipsis) : nameText;
700
+ }
701
+ : (cells) => `${glyphs.dot} ${disciplineName(name, glyphs, Math.max(1, cells - width(glyphs.dot) - 1))}`;
590
702
  const left = [
591
703
  brandSegment(version, glyphs, paint, { clip: 3 }),
592
704
  { ...segment(brand.plain, () => brand.painted), lead: ' | ', leadPainted: paint.fg(' | ', 'accent') },
593
- segment(`${glyphs.dot} ${disciplineName(name, glyphs)}`, (text) => `${paint.fg(glyphs.dot, 'dim')} ${paint.fg(text.slice(glyphs.dot.length + 1), discipline ? 'accent' : 'dim', Boolean(discipline))}`, {
594
- clip: 0.5, minCells: width(glyphs.dot) + 2, shrink: (cells) => `${glyphs.dot} ${disciplineName(name, glyphs, Math.max(1, cells - width(glyphs.dot) - 1))}`,
705
+ segment(nameText, namePaint, {
706
+ clip: 0.5, minCells: lanes ? width(`REVIEW ${reported}/${lanes.length}`) : width(glyphs.dot) + 2, shrink: shrinkName,
595
707
  }),
596
708
  ];
597
709
  const right = [];
@@ -600,10 +712,16 @@ function titleLine({ discipline, version, glyphs, paint, nerd, phase, warning, a
600
712
  if (phase.phase === 'running' && activity.agents > 0) parts.push(glyphs.agents(activity.agents));
601
713
  if (parts.length > 0) right.push(segment(parts.join(` ${glyphs.dot} `), (text) => paint.fg(text, 'dim'), { drop: 4 }));
602
714
  }
603
- if (warning) right.push(segment(`${glyphs.warn} ${warning[1]}`, (text) => paint.fg(text, 'yellow', true), { drop: 1 }));
715
+ if (looks?.waiting) right.push(segment(`YOUR TURN · ${looks.waiting.reason}`, (text) => paint.fg(text, 'yellow', true), {
716
+ drop: 0.6, clip: 3, minCells: width('YOUR TURN'),
717
+ shrink: (cells) => (cells < width(`YOUR TURN · ${looks.waiting.reason}`) ? clipCells('YOUR TURN', Math.max(1, cells), glyphs.ellipsis) : `YOUR TURN · ${looks.waiting.reason}`),
718
+ }));
719
+ else if (warning) right.push(segment(`${glyphs.warn} ${warning[1]}`, (text) => paint.fg(text, 'yellow', true), { drop: 1 }));
604
720
  if (phase.phase === 'running') right.push(segment(`${glyphs.run} ${phase.timer ? `${glyphs.timer}${phase.timer}` : 'running'}`, (text) => paint.fg(text, 'accent', true), { drop: 2 }));
605
- else if (phase.phase === 'complete') right.push(segment(`${glyphs.tick} complete ${phase.timer}`, (text) => paint.fg(text, 'green', true), { drop: 2 }));
606
- else if (!warning) right.push(segment('idle', (text) => paint.fg(text, 'dim'), { drop: 2 }));
721
+ else if (phase.phase === 'complete') {
722
+ if (looks?.burst) right.push(segment(`${glyphs.burst} complete ${phase.timer}`, (text) => paint.fg(text, 'pink', true), { drop: 2 }));
723
+ else right.push(segment(`${glyphs.tick} complete ${phase.timer}`, (text) => paint.fg(text, 'green', true), { drop: 2 }));
724
+ } else if (!warning && !looks?.waiting) right.push(segment('idle', (text) => paint.fg(text, 'dim'), { drop: 2 }));
607
725
  return layoutLine({ left, right, separator: { plain: ' ', painted: ' ' }, rail, maxCells, ellipsis: glyphs.ellipsis });
608
726
  }
609
727
 
@@ -681,10 +799,8 @@ function render(input) {
681
799
  handoff = { active: false, percent: null };
682
800
  }
683
801
  const version = installedVersion();
684
- const shared = { status: input, discipline, version, glyphs, paint, nerd, handoff, maxCells };
685
- if (process.env.LITGROK_HUD_LINES === '1') return [compactRow(shared)];
686
-
687
802
  const now = Date.now();
803
+ const shared = { status: input, discipline, version, glyphs, paint, nerd, handoff, maxCells, now };
688
804
  let activity = null;
689
805
  try {
690
806
  activity = turnActivity(readLedgerTail(input), input?.prompt_id);
@@ -697,15 +813,22 @@ function render(input) {
697
813
  } catch {
698
814
  workflow = null;
699
815
  }
700
- // The card shows while a discipline is active or the session has a workflow stage; otherwise the
701
- // HUD is the single row.
702
- if (!discipline && !workflow?.stage) return [compactRow(shared)];
703
816
  const turn = turnState(input, activity, now);
704
817
  const phase = phaseOf(now, activity, turn);
818
+ const looks = {
819
+ look: lookOf(discipline, workflow?.stage ?? null),
820
+ lanes: laneStates(workflow),
821
+ waiting: waitingOf(activity),
822
+ burst: phase.phase === 'complete' && workflow?.stage === 'done',
823
+ };
824
+ if (process.env.LITGROK_HUD_LINES === '1') return [compactRow({ ...shared, looks, phase })];
825
+ // The card shows while a discipline is active or the session has a workflow stage; otherwise the
826
+ // HUD is the single row.
827
+ if (!discipline && !workflow?.stage) return [compactRow({ ...shared, looks, phase })];
705
828
  const warning = warningText(input, activity, handoff);
706
829
  const live = turn.running ? activity?.live ?? null : null;
707
830
  const rail = railFor(paint, glyphs);
708
- const lines = [titleLine({ ...shared, phase, warning, activity: phase.phase === 'idle' ? null : activity, rail })];
831
+ const lines = [titleLine({ ...shared, phase, warning, activity: phase.phase === 'idle' ? null : activity, rail, looks })];
709
832
  if (workflow?.stage) lines.push(mapLine(workflow, { paint, glyphs, nerd, running: turn.running, now }, rail, maxCells));
710
833
  const detail = detailLine({ workflow, live, warning, glyphs, paint, now, maxCells, rail });
711
834
  if (detail) lines.push(detail);
@@ -32,7 +32,12 @@ const TOOL_EVENTS = new Set(['PostToolUse', 'PostToolUseFailure']);
32
32
  const RECORD_SCHEMA = 'litgrok.hook-event/v1';
33
33
  // A finished call by one of these tools cannot have changed a plan file, so it skips the plan reread.
34
34
  const READ_ONLY_TOOLS = /^(?:read_file|grep|list_dir|glob|todo_write|web_search|web_fetch|read|ls)$/iu;
35
- const HUD_DISCIPLINE_PATTERN = /(?:^|[\s/])(lit-scientific-visualization|lit-handoff|lit-brainstorm|autoconference|autoresearch|lit-plan|litwork|lit)(?=$|[^\w-])/iu;
35
+ const HUD_DISCIPLINE_PATTERN = /(?:^|[\s/])(lit-scientific-visualization|lit-handoff|lit-brainstorm|lit-adhd|lit-rewind|autoconference|autoresearch|lit-plan|litwork|review-work|lit)(?=$|[^\w-])/iu;
36
+ // The skill also runs from bare words, the rule and the catalog, where no prompt names it. Its
37
+ // collector starting is the run, so that call switches the card to the rewind look. The command
38
+ // text is only inspected, never stored: the ledger keeps the tool name alone.
39
+ const ADHD_COLLECTOR_SCRIPT = /lit-adhd\/scripts\/rewind\.mjs/u;
40
+ const ADHD_COLLECTOR_RUN = /(?:^|[\s"'])(?:--brief|--json)(?:$|[\s"'=])/u;
36
41
 
37
42
  function maskCode(text) {
38
43
  return text.replace(/[^\r\n]/gu, '\u0000');
@@ -93,7 +98,9 @@ function hudDisciplineFromPrompt(prompt) {
93
98
  const match = HUD_DISCIPLINE_PATTERN.exec(visiblePromptText(prompt));
94
99
  if (!match) return null;
95
100
  const token = match[1].toLowerCase();
96
- return token === 'lit' ? 'litwork' : token;
101
+ if (token === 'lit') return 'litwork';
102
+ if (token === 'lit-rewind') return 'lit-adhd';
103
+ return token;
97
104
  }
98
105
 
99
106
  class RecorderError extends Error {
@@ -445,6 +452,18 @@ export async function recordPassiveEvent(expectedEvent) {
445
452
  if (expectedEvent === 'UserPromptSubmit') {
446
453
  hudDiscipline = continued ?? (entry?.discipline !== undefined ? entry.discipline : hudDisciplineFromPrompt(event.prompt));
447
454
  }
455
+ if (expectedEvent === 'PreToolUse') {
456
+ const command = event?.toolInput?.command ?? event?.toolInput?.cmd;
457
+ if (typeof command === 'string' && ADHD_COLLECTOR_SCRIPT.test(command) && ADHD_COLLECTOR_RUN.test(command)) {
458
+ writeHudRecords({
459
+ env: process.env,
460
+ sessionId: environment.sessionId,
461
+ cwd: environment.eventCwd,
462
+ workspaceRoot: environment.realWorkspaceRoot,
463
+ discipline: 'lit-adhd',
464
+ });
465
+ }
466
+ }
448
467
  if (discipline !== null) record.discipline = discipline;
449
468
  if (entry?.stage && continued !== 'lit-brainstorm') record.stage = entry.stage;
450
469
  // Only the verdict and one count of a test run are kept, never the command or its output.
@@ -1,7 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
3
5
  import { renderMark } from './lit-mark.mjs';
4
6
  import { claimSessionIgnition } from './record-passive-event.mjs';
7
+ import { adhdSuggestion } from '../skills/lit-adhd/scripts/lib/suggest.mjs';
5
8
 
6
9
  // Decode once: a multi-byte character can straddle two pipe chunks.
7
10
  const chunks = [];
@@ -16,6 +19,20 @@ try {
16
19
  if (bytes > 1024 * 1024) throw new Error('EVENT_TOO_LARGE');
17
20
  event = JSON.parse(Buffer.concat(chunks).toString('utf8'));
18
21
  if (claimSessionIgnition(event)) process.stdout.write(`${renderMark({ args: process.argv.slice(2) }).join('\n')}\n`);
22
+ // One nudge toward the catch-up brief per day, only when this project has other recent sessions.
23
+ // Best effort: a broken suggestion never breaks session start.
24
+ try {
25
+ const home = process.env.HOME || homedir();
26
+ const line = adhdSuggestion({
27
+ storeDir: join(home, '.grok', 'sessions'),
28
+ projectRoot: event.realWorkspaceRoot ?? event.workspaceRoot ?? event.cwd ?? process.cwd(),
29
+ sessionId: event.sessionId ?? process.env.GROK_SESSION_ID,
30
+ stateRoot: event.realWorkspaceRoot ?? event.workspaceRoot ?? event.cwd ?? process.cwd(),
31
+ });
32
+ if (line) process.stdout.write(`${line}\n`);
33
+ } catch {
34
+ // No suggestion; session start continues.
35
+ }
19
36
  } catch (error) {
20
37
  process.stderr.write(`LitGrok session-start: ${error.code || 'EVENT_INVALID'}\n`);
21
38
  process.exitCode = 1;
@@ -60,21 +60,24 @@ const SPACED_PLAN_PATTERN = /^\s*\/?lit\s+plan(?=$|[^\w-])/iu;
60
60
  const SPACED_REVIEW_PATTERN = /^\s*\/?lit\s+review(?=$|[^\w-])/iu;
61
61
  // Open brainstorming is no workflow stage: it names its own discipline and leaves the row where it was.
62
62
  const BRAINSTORM_PATTERN = /^\s*\/?(?:lit-brainstorm|lit\s+(?:brainstorm|brainstorming|ideation|ideate|idea|ideas))(?=$|[^\w-])/iu;
63
+ // Catch-up is no workflow stage either: it names its own discipline and leaves the row where it was.
64
+ const ADHD_PATTERN = /^\s*\/?(?:lit-adhd|lit-rewind|lit\s+(?:adhd|rewind))(?=$|[^\w-])/iu;
63
65
 
64
66
  /**
65
67
  * The stage a prompt names and how it enters it: 'switch' for a named skill (`discipline` is 'lit-plan' for the
66
68
  * spaced `lit plan`, null for the spaced `lit review`), 'continue' or 'restart' for lit. A brainstorm prompt
67
- * carries the discipline 'lit-brainstorm' and no stage.
69
+ * carries the discipline 'lit-brainstorm' and no stage; a catch-up prompt carries 'lit-adhd' and no stage.
68
70
  */
69
71
  export function entryFromPrompt(visibleText) {
70
72
  if (typeof visibleText !== 'string') return null;
71
73
  if (BRAINSTORM_PATTERN.test(visibleText)) return { stage: null, entry: 'switch', discipline: 'lit-brainstorm' };
74
+ if (ADHD_PATTERN.test(visibleText)) return { stage: null, entry: 'switch', discipline: 'lit-adhd' };
72
75
  const match = STAGE_PATTERN.exec(visibleText);
73
76
  if (!match) return null;
74
77
  const token = match[1].toLowerCase();
75
78
  if (token !== 'lit') return { stage: STAGE_OF[token], entry: 'switch' };
76
79
  if (SPACED_PLAN_PATTERN.test(visibleText)) return { stage: STAGE_OF['lit-plan'], entry: 'switch', discipline: 'lit-plan' };
77
- if (SPACED_REVIEW_PATTERN.test(visibleText)) return { stage: STAGE_OF['review-work'], entry: 'switch', discipline: null };
80
+ if (SPACED_REVIEW_PATTERN.test(visibleText)) return { stage: STAGE_OF['review-work'], entry: 'switch', discipline: 'review-work' };
78
81
  return { stage: STAGE_OF.lit, entry: RESTART_PATTERN.test(visibleText) ? 'restart' : 'continue' };
79
82
  }
80
83
 
@@ -122,11 +122,24 @@ Exclusions are checked before the trigger and route away even when a video noun
122
122
  - (iii) an Office deliverable other than a bare 발표 — 발표자료, 슬라이드, PPT, 덱, 보고서, 문서, slides, deck, pptx, report, document — with 넣, 삽입, embed or insert: that Office skill;
123
123
  - (iv) a text or image about a video — 스크립트, 대본, 썸네일, 요약, 기획안, script, transcript, thumbnail, summary, storyboard: its own task;
124
124
  - (v) motion on an interface with no video noun — 버튼, 호버, button, hover, motion tokens, reduced motion: `frontend-ui-ux`.
125
+ - (vi) a drawing of real equipment, even as an HTML page or a loop: `lit-schematic`.
125
126
 
126
127
  Film context: this is a film request. Load `lit-typographic-motion` from `.grok/skills/lit-typographic-motion/` (project) or `~/.grok/skills/lit-typographic-motion/` (user) and write `treatment.json` in the run's output directory first. Path rule: the type path when the words themselves are the film; the stage path for every other film, including anything with shapes, drawn objects, diagrams or imagery; a 9:16 film always takes the stage path. Every frame and track passes through the skill's renderer; hand-encoded films are not the deliverable. Never claim a hook routed the prompt.
127
128
 
128
129
  Film commands, run from the skill root: `node scripts/motion.mjs` with `make`, `stage`, `sound`, `look`, `gate`, `verify` (each takes `--out <dir>`); a README cover loop uses `cover` and `cover-gate` (references/cover.md); pre-warm outside the session with `npm exec --yes --package @litfamily/litgrok@<installed version> -- litgrok motion-runtime install`.
129
130
 
131
+ ## Equipment drawings
132
+
133
+ For an authorized bare `lit` request to draw real process or lab equipment, or `/lit-schematic`, load `lit-schematic` from `.grok/skills/lit-schematic/` (project) or `~/.grok/skills/lit-schematic/` (user). Triggers: P&ID, PFD, BFD, 공정도, 계장도, 장치도, 모식도, 배치도, 계통도, 단면도, apparatus, isometric cutaway, equipment layout. Measured-data plots go to `lit-scientific-visualization`, software or business diagrams to `lit-diagram-drawer`, a report or deck about a drawing to its Office skill, an interface that shows one to `frontend-ui-ux`.
134
+
135
+ ## Brief over sessions
136
+
137
+ For an authorized bare `lit` request to catch up on every recent session of the repository, or `/lit-adhd` or `/lit-rewind`, load `lit-adhd` from `.grok/skills/lit-adhd/` (project) or `~/.grok/skills/lit-adhd/` (user). Triggers: adhd, rewind, where was I, catch up, 어디까지, 브리핑. It runs read-only and prints the drawn brief; it never edits plans or files. One session's own state is `lit-recap`; many sessions' state is this skill.
138
+
139
+ ## Mechanism ports
140
+
141
+ For an authorized bare `lit` request to port someone else's published technique into a skill or system, or `/lit-hijack`, load `lit-hijack` from `.grok/skills/lit-hijack/` (project) or `~/.grok/skills/lit-hijack/` (user). Triggers: hijack, hijacking, 하이재킹, 하이잭. The route words directly after `lit` win over trigger or owner words later in the prompt. Finding sources first goes to `litresearch`, planning the port to `lit-plan`, executing it to `start-work`, and reviewing the diff to `review-work`. A request that only draws equipment goes to `lit-schematic` even when it names a port; a topic with no sources goes to `litresearch` first.
142
+
130
143
  ## Office output selection
131
144
 
132
145
  For an authorized bare `lit` request, choose `lit-docx` for a report, doc, docx, Word, 보고서, 리포트, 기획서, 제안서, 문서, or 워드, and `lit-pptx` for slides, deck, presentation, PPT, pptx, 발표자료, 발표, 슬라이드, 덱, or 피피티. If both groups occur, use both skills. A file asked for as Markdown or plain text (`report.md`, `.txt`) is no Office file: write plain Markdown for its reader, without front matter or `:::` blocks, and load neither skill. Put figures with units or periods in a table and asked-for decisions in a numbered list. Judge the task's intent, not stray quoted words or file contents.
@@ -0,0 +1,23 @@
1
+ # ATTRIBUTION / NOTICE: frontend-ui-ux craft floor, slop register and interface probe
2
+
3
+ The craft-floor and slop-register rules (`references/craft-floor.md`,
4
+ `references/slop-register.md`), the interface probe (`scripts/interface-probe.mjs` and its
5
+ modules) and the build, polish, audit and harden modes were written for LitGrok after studying
6
+ public projects, credited below. **No source file, prose, fixture or golden file from any studied
7
+ project is vendored, copied or redistributed here.** A guard test fails if any packed file is
8
+ byte-identical to a listed reference skill file.
9
+
10
+ The UI/UX Pro Max design data keeps its own notice in `THIRD-PARTY-NOTICE.txt`, which is pinned
11
+ to that dataset's provenance; these credits live here so the two records stay independent.
12
+
13
+ ---
14
+
15
+ - **jakubkrehel/skills** (https://github.com/jakubkrehel/skills),
16
+ Copyright (c) 2026 Jakub Krehel, MIT License, consulted at upstream commit `267330e`. Its
17
+ mode, review-format and routing-governance mechanisms were re-expressed.
18
+ - **ui-skills.com playbook** (https://www.ui-skills.com/playbook), sourced from
19
+ **ibelick/ui-skills** (https://github.com/ibelick/ui-skills),
20
+ Copyright (c) 2026 Julien Thibeaut, MIT License. Its anti-slop entries and responsive and
21
+ polish values were cross-checked and re-expressed.
22
+
23
+ This file ships as long as those references and the probe ship; remove it only with them.
@@ -10,12 +10,13 @@ argument-hint: "<surface and intended outcome>"
10
10
  Use Grok Build's selected skill and authorized repository tools. A clear build request proceeds to implementation and rendered inspection; a contract alone is not delivery. Review-only and plan-only requests authorize no edits. Incidental mentions are not requests; infer a bare target only when one frontend is unambiguous.
11
11
 
12
12
  Read references/production.md when deciding whether to clarify or build.
13
+ Ask a numbered choice of house style first (recommended first); skip only when the prompt names it or says you choose.
13
14
  Read references/complete-contract.md for the v1beta2 contract and validation limits.
14
15
  Read references/probe-loop.md for the required rendered check and fix cycle.
15
16
 
16
17
  Record direction and inventory, then implement. Evolve and validate the `litfamily.design-contract/v1beta2` contract as decisions settle; retain its evidence requirements. Respect explicit art direction and existing tokens, or use the authored editorial/pixel profile in the production reference.
17
18
 
18
- Resolve resources from the exact selected SKILL.md parent; bind its absolute path as FRONTEND_SKILL_ROOT and quote it, including spaces. Run scripts/verify-canonical-corpus.mjs before corpus use. Run scripts/validate-design-contract.mjs to validate the task contract. Run scripts/query-design-intelligence.mjs when retrieval helps. Run scripts/import-design-intelligence.mjs before trusting its dataset. See the complete contract for rooted commands.
19
+ Resolve resources from the exact selected SKILL.md parent; bind its absolute path as FRONTEND_SKILL_ROOT and quote it, including spaces. Run scripts/verify-canonical-corpus.mjs before corpus use. Run scripts/validate-design-contract.mjs to validate the task contract. Run scripts/query-design-intelligence.mjs when retrieval helps. Run scripts/import-design-intelligence.mjs before trusting its dataset. Run scripts/design-lock.mjs init --family <landing|workspace|settings> when the lock is missing. Run scripts/pixel-art.mjs init <style-id> to see the pixels first. Run scripts/interface-probe.mjs <built-page-or-directory> --out <task-evidence-directory> when the page stands. See the complete contract for rooted commands.
19
20
 
20
21
  ## Reference routes
21
22
 
@@ -27,6 +28,7 @@ Load references/craft-floor.md when checking numeric craft or responsive rules.
27
28
  Load references/composition.md when reading order, columns, or density is undecided.
28
29
  Load references/creative-directions.md when comparing visual directions.
29
30
  Load references/evidence-review.md when preparing observations or an independent verdict.
31
+ Load references/house-styles.md when naming the style, then lock it with design-lock.
30
32
  Load references/implementation-platforms.md when rendering or styling changes.
31
33
  Load references/inclusive-interface.md when keyboard, semantics, CJK, IME, or preferences matter.
32
34
  Load references/interaction-motion.md when states, feedback, focus, or motion need specification.
@@ -34,6 +36,7 @@ Load references/motion-guide.md when planning animation timing, scroll choreogra
34
36
  Load references/operating-lanes.md when selecting or recording the lane.
35
37
  Load references/performance-delivery.md when budgets or critical-path evidence matter.
36
38
  Load references/product-direction.md when the user, completion condition, or non-goal is unclear.
39
+ Load references/production-interview.md before the production round.
37
40
  Load references/redesign-playbook.md when changing an existing visual language.
38
41
  Load references/system-foundations.md when token layers or primitives need grounding.
39
42
  Load references/slop-register.md when reviewing generic patterns and functional tells.
@@ -0,0 +1,9 @@
1
+ # Phase 3 README A/B example slot
2
+
3
+ Add one directory per completed run under this path. Each case directory contains:
4
+
5
+ - `before.md` and `after.md`: the README copy before and after the design pass.
6
+ - `before.png` and `after.png`: matching screenshots from the same viewport and state.
7
+
8
+ Record the prompt, viewport, and run date in the case notes. Add a case only after both
9
+ versions have been rendered and reviewed.