@litfamily/litgrok 1.0.26 → 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.
- package/.grok/hooks/lit-mark.mjs +42 -0
- package/.grok/hooks/lit-status-line.mjs +142 -19
- package/.grok/hooks/record-passive-event.mjs +21 -2
- package/.grok/hooks/session-start.mjs +17 -0
- package/.grok/hooks/workflow-stage.mjs +5 -2
- package/.grok/rules/00-litgrok.md +13 -0
- package/.grok/skills/frontend-ui-ux/ATTRIBUTION.md +23 -0
- package/.grok/skills/frontend-ui-ux/SKILL.md +4 -1
- package/.grok/skills/frontend-ui-ux/examples/phase-3-readme-ab/README.md +9 -0
- package/.grok/skills/frontend-ui-ux/kit/components.css +414 -0
- package/.grok/skills/frontend-ui-ux/kit/fonts.json +22 -0
- package/.grok/skills/frontend-ui-ux/kit/layouts/landing.html +164 -0
- package/.grok/skills/frontend-ui-ux/kit/layouts/settings.html +114 -0
- package/.grok/skills/frontend-ui-ux/kit/layouts/workspace.html +115 -0
- package/.grok/skills/frontend-ui-ux/kit/styles/computational-brutalism.json +227 -0
- package/.grok/skills/frontend-ui-ux/kit/styles/field-notes.json +205 -0
- package/.grok/skills/frontend-ui-ux/kit/styles/graphite.json +200 -0
- package/.grok/skills/frontend-ui-ux/kit/styles/meadow.json +199 -0
- package/.grok/skills/frontend-ui-ux/kit/styles/neo-brutalism.json +222 -0
- package/.grok/skills/frontend-ui-ux/kit/ui.js +226 -0
- package/.grok/skills/frontend-ui-ux/references/adaptive-layout.md +10 -4
- package/.grok/skills/frontend-ui-ux/references/brand-and-imagery.md +11 -7
- package/.grok/skills/frontend-ui-ux/references/complete-contract.md +21 -0
- package/.grok/skills/frontend-ui-ux/references/composition.md +10 -6
- package/.grok/skills/frontend-ui-ux/references/craft-floor.md +256 -93
- package/.grok/skills/frontend-ui-ux/references/creative-directions.md +9 -6
- package/.grok/skills/frontend-ui-ux/references/default-editorial-pixel.json +28 -0
- package/.grok/skills/frontend-ui-ux/references/house-styles.md +234 -0
- package/.grok/skills/frontend-ui-ux/references/implementation-platforms.md +10 -6
- package/.grok/skills/frontend-ui-ux/references/inclusive-interface.md +11 -5
- package/.grok/skills/frontend-ui-ux/references/interaction-motion.md +34 -78
- package/.grok/skills/frontend-ui-ux/references/motion-guide.md +10 -7
- package/.grok/skills/frontend-ui-ux/references/performance-delivery.md +11 -8
- package/.grok/skills/frontend-ui-ux/references/probe-loop.md +1 -1
- package/.grok/skills/frontend-ui-ux/references/product-direction.md +9 -4
- package/.grok/skills/frontend-ui-ux/references/production-interview.md +17 -0
- package/.grok/skills/frontend-ui-ux/references/redesign-playbook.md +10 -6
- package/.grok/skills/frontend-ui-ux/references/slop-register.md +148 -73
- package/.grok/skills/frontend-ui-ux/references/system-foundations.md +10 -4
- package/.grok/skills/frontend-ui-ux/references/visual-language.md +10 -4
- package/.grok/skills/frontend-ui-ux/references/visual-reconstruction.md +39 -72
- package/.grok/skills/frontend-ui-ux/scripts/design-lock.mjs +400 -0
- package/.grok/skills/frontend-ui-ux/scripts/interface-probe-driver.mjs +33 -0
- package/.grok/skills/frontend-ui-ux/scripts/interface-probe-lock.mjs +196 -0
- package/.grok/skills/frontend-ui-ux/scripts/interface-probe-page.mjs +1555 -0
- package/.grok/skills/frontend-ui-ux/scripts/interface-probe-rules.mjs +153 -0
- package/.grok/skills/frontend-ui-ux/scripts/interface-probe-server.mjs +57 -0
- package/.grok/skills/frontend-ui-ux/scripts/interface-probe-static.mjs +139 -0
- package/.grok/skills/frontend-ui-ux/scripts/interface-probe.mjs +363 -0
- package/.grok/skills/frontend-ui-ux/scripts/pixel-art.mjs +60 -0
- package/.grok/skills/lit-adhd/SKILL.md +151 -0
- package/.grok/skills/lit-adhd/references/card-examples.md +118 -0
- package/.grok/skills/lit-adhd/references/status-taxonomy.md +36 -0
- package/.grok/skills/lit-adhd/scripts/lib/brief.mjs +370 -0
- package/.grok/skills/lit-adhd/scripts/lib/collect.mjs +327 -0
- package/.grok/skills/lit-adhd/scripts/lib/gauge.mjs +87 -0
- package/.grok/skills/lit-adhd/scripts/lib/next-step.mjs +18 -0
- package/.grok/skills/lit-adhd/scripts/lib/plan-task-rows.mjs +32 -0
- package/.grok/skills/lit-adhd/scripts/lib/project-state-root.mjs +55 -0
- package/.grok/skills/lit-adhd/scripts/lib/redact.mjs +64 -0
- package/.grok/skills/lit-adhd/scripts/lib/suggest.mjs +140 -0
- package/.grok/skills/lit-adhd/scripts/lib/transcripts.mjs +232 -0
- package/.grok/skills/lit-adhd/scripts/rewind.mjs +6 -0
- package/.grok/skills/lit-diagram-drawer/SKILL.md +17 -5
- package/.grok/skills/lit-diagram-drawer/references/output-spec.md +2 -2
- package/.grok/skills/lit-diagram-drawer/references/style-guide.md +20 -11
- package/.grok/skills/lit-diagram-drawer/references/type-architecture.md +3 -3
- package/.grok/skills/lit-diagram-drawer/references/type-dependency.md +1 -1
- package/.grok/skills/lit-diagram-drawer/references/type-tree.md +3 -3
- package/.grok/skills/lit-diagram-drawer/references/type-wardley.md +1 -1
- package/.grok/skills/lit-diagram-drawer/references/verifier-guide.md +4 -0
- package/.grok/skills/lit-diagram-drawer/scripts/visual-quality.mjs +2 -2
- package/.grok/skills/lit-handoff/SKILL.md +2 -0
- package/.grok/skills/lit-hijack/SKILL.md +459 -0
- package/.grok/skills/lit-hijack/references/capture-and-provenance.md +124 -0
- package/.grok/skills/lit-hijack/references/clean-room-build.md +130 -0
- package/.grok/skills/lit-hijack/references/distil-and-licence.md +128 -0
- package/.grok/skills/lit-hijack/references/gap-and-port-design.md +150 -0
- package/.grok/skills/lit-hijack/references/parity-and-report.md +130 -0
- package/.grok/skills/lit-hijack/scripts/hijack.mjs +890 -0
- package/.grok/skills/lit-hijack/scripts/lib/safe-fetch.mjs +213 -0
- package/.grok/skills/lit-plan/SKILL.md +1 -1
- package/.grok/skills/lit-pptx/SKILL.md +10 -5
- package/.grok/skills/lit-pptx/examples/13-engineering-review-computational-brutalism-ko.md +173 -0
- package/.grok/skills/lit-pptx/examples/14-launch-pitch-neo-brutalism-ko.md +154 -0
- package/.grok/skills/lit-pptx/examples/15-design-lecture-bauhaus-ko.md +139 -0
- package/.grok/skills/lit-pptx/examples/16-community-programme-riso-ko.md +158 -0
- package/.grok/skills/lit-pptx/examples/17-public-data-briefing-newsroom-ko.md +179 -0
- package/.grok/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Bold.ttf +0 -0
- package/.grok/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Regular.ttf +0 -0
- package/.grok/skills/lit-pptx/fonts/jetbrains-mono/OFL.txt +93 -0
- package/.grok/skills/lit-pptx/fonts/jetbrains-mono/provenance.json +1 -0
- package/.grok/skills/lit-pptx/references/direction-step.md +34 -8
- package/.grok/skills/lit-pptx/references/tonalities/bauhaus.md +140 -0
- package/.grok/skills/lit-pptx/references/tonalities/computational-brutalism.md +150 -0
- package/.grok/skills/lit-pptx/references/tonalities/neo-brutalism.md +161 -0
- package/.grok/skills/lit-pptx/references/tonalities/newsroom.md +144 -0
- package/.grok/skills/lit-pptx/references/tonalities/riso.md +137 -0
- package/.grok/skills/lit-pptx/scripts/compile-deck.js +1 -1
- package/.grok/skills/lit-pptx/scripts/craft_extras.py +61 -3
- package/.grok/skills/lit-pptx/scripts/deck_output.py +76 -62
- package/.grok/skills/lit-pptx/scripts/embed_fonts.py +14 -1
- package/.grok/skills/lit-pptx/scripts/lib/grid-resolver.js +101 -110
- package/.grok/skills/lit-pptx/scripts/lib/layout-resolver.js +9 -15
- package/.grok/skills/lit-pptx/scripts/lib/render-pack.js +389 -582
- package/.grok/skills/lit-pptx/scripts/lib/slide-grid.js +104 -0
- package/.grok/skills/lit-pptx/scripts/lib/template-registry.js +60 -8
- package/.grok/skills/lit-pptx/scripts/qa_deck.py +4 -4
- package/.grok/skills/lit-pptx/templates/tonalities/atlas/pack.yaml +2 -0
- package/.grok/skills/lit-pptx/templates/tonalities/bauhaus/pack.yaml +98 -0
- package/.grok/skills/lit-pptx/templates/tonalities/chalk/pack.yaml +2 -0
- package/.grok/skills/lit-pptx/templates/tonalities/computational-brutalism/pack.yaml +99 -0
- package/.grok/skills/lit-pptx/templates/tonalities/gazette/pack.yaml +2 -0
- package/.grok/skills/lit-pptx/templates/tonalities/ledger/pack.yaml +2 -0
- package/.grok/skills/lit-pptx/templates/tonalities/neo-brutalism/pack.yaml +107 -0
- package/.grok/skills/lit-pptx/templates/tonalities/newsroom/pack.yaml +99 -0
- package/.grok/skills/lit-pptx/templates/tonalities/night/pack.yaml +2 -0
- package/.grok/skills/lit-pptx/templates/tonalities/paper/pack.yaml +2 -0
- package/.grok/skills/lit-pptx/templates/tonalities/riso/pack.yaml +99 -0
- package/.grok/skills/lit-pptx/templates/tonalities/signal/pack.yaml +3 -0
- package/.grok/skills/lit-pptx/templates/tonalities/studio/pack.yaml +2 -0
- package/.grok/skills/lit-recap/SKILL.md +1 -1
- package/.grok/skills/lit-schematic/SKILL.md +140 -0
- package/.grok/skills/lit-schematic/examples/iso-heat-exchanger/build.mjs +38 -0
- package/.grok/skills/lit-schematic/examples/iso-heat-exchanger/scene.mjs +133 -0
- package/.grok/skills/lit-schematic/examples/journal-adsorption-rig/build.mjs +87 -0
- package/.grok/skills/lit-schematic/examples/pid-dosing-skid/build.mjs +85 -0
- package/.grok/skills/lit-schematic/references/cutaway-outputs.md +70 -0
- package/.grok/skills/lit-schematic/references/isometric-craft.md +101 -0
- package/.grok/skills/lit-schematic/references/journal-figures.md +72 -0
- package/.grok/skills/lit-schematic/references/kit-api.md +134 -0
- package/.grok/skills/lit-schematic/references/pfd-and-layout.md +53 -0
- package/.grok/skills/lit-schematic/references/pid-drafting.md +103 -0
- package/.grok/skills/lit-schematic/references/pid-symbols.md +163 -0
- package/.grok/skills/lit-schematic/references/verification.md +100 -0
- package/.grok/skills/lit-schematic/scripts/doctor.mjs +57 -0
- package/.grok/skills/lit-schematic/scripts/lib/figure.mjs +81 -0
- package/.grok/skills/lit-schematic/scripts/lib/fonts.mjs +27 -0
- package/.grok/skills/lit-schematic/scripts/lib/geom.mjs +113 -0
- package/.grok/skills/lit-schematic/scripts/lib/interactive.mjs +292 -0
- package/.grok/skills/lit-schematic/scripts/lib/isa.mjs +115 -0
- package/.grok/skills/lit-schematic/scripts/lib/iso.mjs +719 -0
- package/.grok/skills/lit-schematic/scripts/lib/legend-sheet.mjs +162 -0
- package/.grok/skills/lit-schematic/scripts/lib/pid.mjs +937 -0
- package/.grok/skills/lit-schematic/scripts/lib/png.mjs +132 -0
- package/.grok/skills/lit-schematic/scripts/lib/qa-core.mjs +658 -0
- package/.grok/skills/lit-schematic/scripts/lib/route.mjs +218 -0
- package/.grok/skills/lit-schematic/scripts/lib/sheet.mjs +890 -0
- package/.grok/skills/lit-schematic/scripts/lib/svg.mjs +82 -0
- package/.grok/skills/lit-schematic/scripts/lib/theme.mjs +115 -0
- package/.grok/skills/lit-schematic/scripts/motion.mjs +129 -0
- package/.grok/skills/lit-schematic/scripts/qa.mjs +92 -0
- package/.grok/skills/lit-schematic/scripts/render.mjs +233 -0
- package/.grok/skills/lit-schematic/scripts/scaffold.mjs +60 -0
- package/.grok/skills/lit-scientific-visualization/SKILL.md +36 -12
- package/.grok/skills/lit-typographic-motion/SKILL.md +7 -4
- package/.grok/skills/lit-typographic-motion/THIRD_PARTY_NOTICES +11 -0
- package/.grok/skills/lit-typographic-motion/recipes/hero-3d/expected.json +62 -0
- package/.grok/skills/lit-typographic-motion/recipes/hero-3d/index.html +82 -0
- package/.grok/skills/lit-typographic-motion/references/choice-first.md +30 -0
- package/.grok/skills/lit-typographic-motion/references/cover.md +10 -1
- package/.grok/skills/lit-typographic-motion/references/depth.md +119 -0
- package/.grok/skills/lit-typographic-motion/references/treatment.md +9 -1
- package/.grok/skills/lit-typographic-motion/scripts/blender/runner.py +218 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/assets.mjs +230 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/blender.mjs +136 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/board.mjs +153 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/chrome.mjs +61 -32
- package/.grok/skills/lit-typographic-motion/scripts/lib/constants.mjs +4 -2
- package/.grok/skills/lit-typographic-motion/scripts/lib/cover-capture.mjs +20 -11
- package/.grok/skills/lit-typographic-motion/scripts/lib/cover-treatment.mjs +26 -2
- package/.grok/skills/lit-typographic-motion/scripts/lib/cover.mjs +12 -5
- package/.grok/skills/lit-typographic-motion/scripts/lib/frame-pool.mjs +78 -1
- package/.grok/skills/lit-typographic-motion/scripts/lib/gallery.mjs +160 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/house.mjs +43 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/look.mjs +39 -1
- package/.grok/skills/lit-typographic-motion/scripts/lib/scaffold.mjs +174 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/score.mjs +640 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/sound.mjs +143 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/soundtrack.mjs +12 -3
- package/.grok/skills/lit-typographic-motion/scripts/lib/stage-gate.mjs +44 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/stage-qa.mjs +132 -3
- package/.grok/skills/lit-typographic-motion/scripts/lib/stage-session.mjs +51 -3
- package/.grok/skills/lit-typographic-motion/scripts/lib/stage.mjs +74 -9
- package/.grok/skills/lit-typographic-motion/scripts/lib/styles.mjs +224 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/treatment.mjs +198 -4
- package/.grok/skills/lit-typographic-motion/scripts/lib/vendor/three/LICENSE +21 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/vendor/three/addons/environments/RoomEnvironment.js +144 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/vendor/three/addons/geometries/RoundedBoxGeometry.js +155 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/vendor/three/three.module.js +54571 -0
- package/.grok/skills/lit-typographic-motion/scripts/motion.mjs +56 -6
- package/.grok/skills/lit-typographic-motion/scripts/stage/cover-init.js +20 -8
- package/.grok/skills/lit-typographic-motion/scripts/stage/loop-kit.js +2 -2
- package/.grok/skills/lit-typographic-motion/scripts/stage/stage-kit.js +25 -0
- package/.grok/skills/lit-typographic-motion/styles/paper.json +1 -0
- package/.grok/skills/lit-typographic-motion/styles/swiss-signal.json +1 -0
- package/.grok/skills/lit-typographic-motion/styles/terminalcore.json +1 -0
- package/.grok/skills/lit-typographic-motion/styles/tidal.json +1 -0
- package/.grok/skills/litgrok/SKILL.md +1 -1
- package/.grok/skills/litresearch/SKILL.md +2 -0
- package/.grok/skills/readme-studio/SKILL.md +14 -12
- package/.grok/skills/readme-studio/references/choice-first.md +24 -0
- package/.grok/skills/start-work/SKILL.md +1 -1
- package/.grok-plugin/plugin.json +4 -1
- package/CHANGELOG.md +10 -0
- package/README.md +11 -11
- package/README_ko-KR.md +11 -11
- package/docs/assets/readme/badge-version.svg +1 -1
- package/docs/assets/showcase/brief.webp +0 -0
- package/docs/assets/showcase/deck.webp +0 -0
- package/docs/assets/showcase/page.webp +0 -0
- package/docs/assets/showcase/pid.webp +0 -0
- package/docs/assets/skills/lit-adhd.webp +0 -0
- package/docs/assets/skills/lit-hijack.webp +0 -0
- package/docs/assets/skills/lit-schematic.webp +0 -0
- package/docs/reference.md +5 -5
- package/docs/reference_ko-KR.md +5 -5
- package/package.json +5 -1
- package/plugin.json +1 -1
- package/.grok/skills/frontend-ui-ux/scripts/page-probe.mjs +0 -105
- package/.grok/skills/frontend-ui-ux/scripts/probe.mjs +0 -91
- package/.grok/skills/frontend-ui-ux/scripts/rule-data.mjs +0 -56
- package/.grok/skills/frontend-ui-ux/scripts/static-probe.mjs +0 -27
- package/.grok/skills/frontend-ui-ux/scripts/static-server.mjs +0 -19
package/.grok/hooks/lit-mark.mjs
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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(
|
|
594
|
-
clip: 0.5, minCells:
|
|
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 (
|
|
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')
|
|
606
|
-
|
|
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
|
-
|
|
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:
|
|
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.
|