@litfamily/litgrok 1.0.23 → 1.0.25
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/auto-handoff.mjs +1 -1
- package/.grok/hooks/deliverable-hedge-guard.mjs +100 -15
- package/.grok/hooks/lit-status-line.mjs +414 -269
- package/.grok/hooks/plan-progress.mjs +11 -2
- package/.grok/hooks/record-passive-event.mjs +20 -9
- package/.grok/hooks/workflow-stage.mjs +48 -13
- package/.grok/rules/00-litgrok.md +21 -12
- package/.grok/skills/autoconference/SKILL.md +3 -1
- package/.grok/skills/autoresearch/SKILL.md +3 -1
- package/.grok/skills/browser-drive/SKILL.md +3 -1
- package/.grok/skills/browser-drive/scripts/capability-probe.mjs +2 -2
- package/.grok/skills/comment-checker/SKILL.md +3 -1
- package/.grok/skills/debugging/SKILL.md +3 -1
- package/.grok/skills/deep-interview/SKILL.md +4 -1
- package/.grok/skills/frontend-ui-ux/scripts/probe.mjs +3 -2
- package/.grok/skills/lit-brainstorm/SKILL.md +162 -0
- package/.grok/skills/lit-brainstorm/references/converge-and-score.md +85 -0
- package/.grok/skills/lit-brainstorm/references/handoff-and-notes.md +66 -0
- package/.grok/skills/lit-brainstorm/references/idea-lane-packet.md +58 -0
- package/.grok/skills/lit-brainstorm/references/idea-lenses.md +60 -0
- package/.grok/skills/lit-diagram-drawer/scripts/diagram-metrics.mjs +1 -1
- package/.grok/skills/lit-diagram-drawer/scripts/export.mjs +6 -6
- package/.grok/skills/lit-diagram-drawer/scripts/renderer-status.mjs +3 -3
- package/.grok/skills/lit-docx/SKILL.md +3 -1
- package/.grok/skills/lit-docx/scripts/convert_md_to_pdf.py +7 -4
- package/.grok/skills/lit-docx/scripts/docx_gate.py +5 -2
- package/.grok/skills/lit-docx/scripts/pdf_fonts.py +63 -0
- package/.grok/skills/lit-docx/scripts/run.mjs +3 -5
- package/.grok/skills/lit-docx/templates/latex/acs/template.tex +5 -0
- package/.grok/skills/lit-docx/templates/latex/elsevier/template.tex +5 -0
- package/.grok/skills/lit-docx/templates/latex/ieee/template.tex +5 -0
- package/.grok/skills/lit-docx/templates/latex/korean-generic/template.tex +5 -0
- package/.grok/skills/lit-docx/templates/latex/nature/template.tex +5 -0
- package/.grok/skills/lit-handoff/SKILL.md +3 -1
- package/.grok/skills/lit-humanizer/SKILL.md +4 -0
- package/.grok/skills/lit-humanizer/assets/always-on-rule.md +3 -1
- package/.grok/skills/lit-humanizer/fixtures/rule-cases.json +4 -2
- package/.grok/skills/lit-humanizer/rules.json +24 -0
- package/.grok/skills/lit-humanizer/scripts/core.mjs +56 -1
- package/.grok/skills/lit-humanizer/scripts/extract.mjs +6 -3
- package/.grok/skills/lit-humanizer/scripts/test-fixtures.mjs +3 -1
- package/.grok/skills/lit-plan/SKILL.md +2 -0
- package/.grok/skills/lit-pptx/SKILL.md +3 -1
- package/.grok/skills/lit-pptx/scripts/deps.cjs +18 -8
- package/.grok/skills/lit-pptx/scripts/proc.cjs +192 -0
- package/.grok/skills/lit-pptx/scripts/run.mjs +3 -5
- package/.grok/skills/lit-recap/SKILL.md +3 -1
- package/.grok/skills/lit-typographic-motion/SKILL.md +9 -6
- package/.grok/skills/lit-typographic-motion/THIRD_PARTY_NOTICES +3 -0
- package/.grok/skills/lit-typographic-motion/fonts/JetBrainsMono-OFL.txt +93 -0
- package/.grok/skills/lit-typographic-motion/fonts/JetBrainsMono-wght-latin.woff2 +0 -0
- package/.grok/skills/lit-typographic-motion/fonts/pins.json +15 -0
- package/.grok/skills/lit-typographic-motion/recipes/negatives/card-scenes/expected.json +16 -0
- package/.grok/skills/lit-typographic-motion/recipes/negatives/card-scenes/index.html +36 -0
- package/.grok/skills/lit-typographic-motion/recipes/negatives/reset-sweep/expected.json +16 -0
- package/.grok/skills/lit-typographic-motion/recipes/negatives/reset-sweep/index.html +24 -0
- package/.grok/skills/lit-typographic-motion/recipes/negatives/still-glow/expected.json +17 -0
- package/.grok/skills/lit-typographic-motion/recipes/negatives/still-glow/index.html +25 -0
- package/.grok/skills/lit-typographic-motion/recipes/negatives/title-slam/expected.json +17 -0
- package/.grok/skills/lit-typographic-motion/recipes/negatives/title-slam/index.html +37 -0
- package/.grok/skills/lit-typographic-motion/recipes/orbit-loop/expected.json +67 -0
- package/.grok/skills/lit-typographic-motion/recipes/orbit-loop/index.html +119 -0
- package/.grok/skills/lit-typographic-motion/recipes/painted-light/expected.json +95 -0
- package/.grok/skills/lit-typographic-motion/recipes/painted-light/index.html +192 -0
- package/.grok/skills/lit-typographic-motion/recipes/weight-tide/expected.json +67 -0
- package/.grok/skills/lit-typographic-motion/recipes/weight-tide/index.html +85 -0
- package/.grok/skills/lit-typographic-motion/references/cover.md +380 -0
- package/.grok/skills/lit-typographic-motion/references/craft-loop.md +4 -0
- package/.grok/skills/lit-typographic-motion/references/runtime.md +14 -3
- package/.grok/skills/lit-typographic-motion/references/stage.md +2 -1
- package/.grok/skills/lit-typographic-motion/references/treatment.md +5 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/cache.mjs +1 -1
- package/.grok/skills/lit-typographic-motion/scripts/lib/chrome.mjs +14 -4
- package/.grok/skills/lit-typographic-motion/scripts/lib/constants.mjs +39 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/cover-assets.mjs +88 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/cover-capture.mjs +144 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/cover-gate.mjs +312 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/cover-image.mjs +111 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/cover-pool.mjs +62 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/cover-sheet.mjs +73 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/cover-treatment.mjs +104 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/cover-webp.mjs +134 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/cover.mjs +347 -0
- package/.grok/skills/lit-typographic-motion/scripts/lib/encode.mjs +1 -1
- package/.grok/skills/lit-typographic-motion/scripts/lib/gate.mjs +2 -2
- package/.grok/skills/lit-typographic-motion/scripts/lib/look.mjs +99 -7
- package/.grok/skills/lit-typographic-motion/scripts/lib/render.mjs +8 -11
- package/.grok/skills/lit-typographic-motion/scripts/lib/sound.mjs +1 -1
- package/.grok/skills/lit-typographic-motion/scripts/lib/stage.mjs +3 -1
- package/.grok/skills/lit-typographic-motion/scripts/lib/treatment.mjs +1 -0
- package/.grok/skills/lit-typographic-motion/scripts/motion.mjs +45 -3
- package/.grok/skills/lit-typographic-motion/scripts/prewarm.mjs +35 -22
- package/.grok/skills/lit-typographic-motion/scripts/stage/cover-init.js +44 -0
- package/.grok/skills/lit-typographic-motion/scripts/stage/loop-kit.js +96 -0
- package/.grok/skills/litgoal/SKILL.md +14 -2
- package/.grok/skills/litgrok/SKILL.md +30 -7
- package/.grok/skills/litresearch/SKILL.md +3 -1
- package/.grok/skills/litwork/SKILL.md +12 -1
- package/.grok/skills/lsp/SKILL.md +3 -1
- package/.grok/skills/lsp-setup/SKILL.md +3 -1
- package/.grok/skills/lsp-setup/scripts/lsp-server-table.mjs +3 -3
- package/.grok/skills/refactor/SKILL.md +3 -1
- package/.grok/skills/review-work/SKILL.md +20 -26
- package/.grok/skills/rules/SKILL.md +3 -1
- package/.grok/skills/start-work/SKILL.md +1 -1
- package/.grok/skills/structural-search/SKILL.md +3 -1
- package/.grok/skills/wikify/SKILL.md +2 -0
- package/.grok-plugin/plugin.json +2 -1
- package/CHANGELOG.md +19 -0
- package/README.md +12 -11
- package/README_ko-KR.md +12 -11
- package/bin/litgrok.mjs +7 -2
- package/bin/status-line-config.mjs +26 -14
- package/docs/assets/cover-motion-still.webp +0 -0
- package/docs/assets/cover-motion.webp +0 -0
- package/docs/assets/cover.webp +0 -0
- package/docs/assets/readme/README.md +5 -5
- package/docs/assets/readme/badge-version.svg +1 -1
- package/docs/assets/skills/lit-brainstorm.webp +0 -0
- package/docs/reference.md +18 -8
- package/docs/reference_ko-KR.md +19 -8
- package/package.json +3 -2
- package/plugin.json +1 -1
|
@@ -245,7 +245,7 @@ export async function runAutoHandoff(args, { env = process.env, stdout = process
|
|
|
245
245
|
|
|
246
246
|
const located = projectRoot(cwd);
|
|
247
247
|
const { root } = located;
|
|
248
|
-
const notes = rootNotes(located, env.HOME || null);
|
|
248
|
+
const notes = rootNotes(located, env.HOME || env.USERPROFILE || null);
|
|
249
249
|
const file = `Project file: ${configPath(root)}`;
|
|
250
250
|
const resolved = resolveAutoHandoff({ env, dirs: [root] });
|
|
251
251
|
if (action === 'status') {
|
|
@@ -36,21 +36,90 @@ function field(value, pattern) {
|
|
|
36
36
|
return stringLeaves(value).find(({ key }) => pattern.test(key))?.value;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
const MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
40
|
+
const FENCE = /^ {0,3}(?:`{3,}|~{3,})/;
|
|
41
|
+
|
|
42
|
+
// Line-level diff of an Edit: the 1-based lines of `after` that differ from `before`.
|
|
43
|
+
function changedLines(before, after, offset) {
|
|
44
|
+
const old = before.split('\n');
|
|
45
|
+
const next = after.split('\n');
|
|
46
|
+
let head = 0;
|
|
47
|
+
while (head < old.length && head < next.length && old[head] === next[head]) head += 1;
|
|
48
|
+
let tail = 0;
|
|
49
|
+
while (tail < old.length - head && tail < next.length - head && old[old.length - 1 - tail] === next[next.length - 1 - tail]) tail += 1;
|
|
50
|
+
let first = head;
|
|
51
|
+
let end = next.length - tail;
|
|
52
|
+
// A pure deletion can join its two neighbours into one paragraph.
|
|
53
|
+
if (end <= first) { first = Math.max(0, head - 1); end = Math.min(next.length, head + 1); }
|
|
54
|
+
const lines = new Set();
|
|
55
|
+
for (let index = first; index < end; index += 1) lines.add(offset + index + 1);
|
|
56
|
+
return lines;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function readCurrent(file, cwd) {
|
|
60
|
+
try {
|
|
61
|
+
const target = resolve(cwd, file);
|
|
62
|
+
const stat = lstatSync(target);
|
|
63
|
+
if (!stat.isFile() || stat.size > MAX_FILE_BYTES) return null;
|
|
64
|
+
return readFileSync(target, 'utf8');
|
|
65
|
+
} catch { return null; }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Rebuild what a patch's hunks show: context and added lines in order, a blank line at every
|
|
69
|
+
// hunk or file break, removed lines dropped. The added lines are the changed ones.
|
|
70
|
+
function patchView(patch) {
|
|
71
|
+
const rows = [];
|
|
72
|
+
const changed = new Set();
|
|
73
|
+
const gap = () => { if (rows.length && rows[rows.length - 1] !== '') rows.push(''); };
|
|
74
|
+
for (const line of patch.split(/\r?\n/)) {
|
|
75
|
+
if (/^(?:\+\+\+|---) |^\*\*\*|^@@|^diff |^index /.test(line)) gap();
|
|
76
|
+
else if (line.startsWith('+')) { rows.push(line.slice(1)); changed.add(rows.length); }
|
|
77
|
+
else if (line.startsWith(' ')) rows.push(line.slice(1));
|
|
78
|
+
else if (line === '') rows.push('');
|
|
79
|
+
else if (!line.startsWith('-') && !line.startsWith('\\')) gap();
|
|
80
|
+
}
|
|
81
|
+
return { text: rows.join('\n'), changed };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// The text to scan and the 1-based lines of it that this write changes. An Edit is applied to the
|
|
85
|
+
// current file so fences, quotes and paragraph breaks keep their context; without a readable file
|
|
86
|
+
// the new_string is scanned whole with its own fence state.
|
|
87
|
+
function writeView(input, cwd) {
|
|
40
88
|
const before = field(input, OLD_KEY);
|
|
41
89
|
const after = field(input, /^new_?string$/i);
|
|
42
90
|
if (before !== undefined && after !== undefined) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return after.slice(
|
|
91
|
+
const file = field(input, PATH_KEY);
|
|
92
|
+
const current = file && before ? readCurrent(file, cwd) : null;
|
|
93
|
+
const at = current === null ? -1 : current.indexOf(before);
|
|
94
|
+
if (at < 0) return { text: after, changed: changedLines(before, after, 0) };
|
|
95
|
+
const text = current.slice(0, at) + after + current.slice(at + before.length);
|
|
96
|
+
return { text, changed: changedLines(before, after, current.slice(0, at).split('\n').length - 1) };
|
|
49
97
|
}
|
|
50
98
|
const leaves = stringLeaves(input).filter(({ key }) => CONTENT_KEY.test(key) && !OLD_KEY.test(key));
|
|
51
99
|
const patch = leaves.find(({ key }) => /^patch$/i.test(key))?.value;
|
|
52
|
-
if (patch) return patch
|
|
53
|
-
|
|
100
|
+
if (patch) return patchView(patch);
|
|
101
|
+
// A Write over a readable file is judged on the lines it changes; a new file is judged whole.
|
|
102
|
+
const text = leaves.map(({ value }) => value).join('\n');
|
|
103
|
+
const file = field(input, PATH_KEY);
|
|
104
|
+
const current = file ? readCurrent(file, cwd) : null;
|
|
105
|
+
return { text, changed: current === null ? null : changedLines(current, text, 0) };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// The 1-based lines a finding covers. A counted rule reads a whole paragraph, so its finding covers it.
|
|
109
|
+
// A document-scope match covers the lines where it starts and ends (its first and last occurrence),
|
|
110
|
+
// not the lines between them.
|
|
111
|
+
function findingLines(finding, lines, counted, documentScope) {
|
|
112
|
+
if (documentScope && !counted) return [...new Set([finding.line, finding.endLine ?? finding.line])];
|
|
113
|
+
let first = finding.line;
|
|
114
|
+
let last = finding.line;
|
|
115
|
+
if (counted) {
|
|
116
|
+
const prose = (number) => number >= 1 && number <= lines.length && lines[number - 1].trim() && !FENCE.test(lines[number - 1]);
|
|
117
|
+
while (prose(first - 1)) first -= 1;
|
|
118
|
+
while (prose(last + 1)) last += 1;
|
|
119
|
+
}
|
|
120
|
+
const covered = [];
|
|
121
|
+
for (let number = first; number <= last; number += 1) covered.push(number);
|
|
122
|
+
return covered;
|
|
54
123
|
}
|
|
55
124
|
|
|
56
125
|
function readerFacing(file) {
|
|
@@ -59,7 +128,8 @@ function readerFacing(file) {
|
|
|
59
128
|
|
|
60
129
|
function removeQuotedPrompt(text, event) {
|
|
61
130
|
for (const { key, value } of stringLeaves(event).filter(({ key }) => PROMPT_KEY.test(key))) {
|
|
62
|
-
|
|
131
|
+
// Keep the line breaks so changed-line numbers still match.
|
|
132
|
+
if (value.length > 0) text = text.split(value).join(value.replace(/[^\n]+/g, ' '));
|
|
63
133
|
}
|
|
64
134
|
return text;
|
|
65
135
|
}
|
|
@@ -67,8 +137,9 @@ function removeQuotedPrompt(text, event) {
|
|
|
67
137
|
function writeTarget(event) {
|
|
68
138
|
const file = field(event.toolInput, PATH_KEY);
|
|
69
139
|
if (!file || file.includes('\n') || !readerFacing(file)) return null;
|
|
70
|
-
const
|
|
71
|
-
|
|
140
|
+
const view = writeView(event.toolInput, event.cwd || process.cwd());
|
|
141
|
+
const text = removeQuotedPrompt(view.text, event);
|
|
142
|
+
return text.trim() ? { file, text, changed: view.changed } : null;
|
|
72
143
|
}
|
|
73
144
|
|
|
74
145
|
function postTargets(event) {
|
|
@@ -114,14 +185,28 @@ try {
|
|
|
114
185
|
const target = writeTarget(event);
|
|
115
186
|
if (!target) allow();
|
|
116
187
|
else {
|
|
117
|
-
const
|
|
188
|
+
const rules = loadRules();
|
|
189
|
+
const lines = target.text.split('\n');
|
|
190
|
+
const counted = new Set(rules.filter((rule) => rule.threshold !== undefined).map((rule) => rule.id));
|
|
191
|
+
const documentScope = new Set(rules.filter((rule) => rule.scope === 'document').map((rule) => rule.id));
|
|
192
|
+
const findings = scanText(target.text, rules, target.file).filter((item) => {
|
|
193
|
+
if (!target.changed) return true;
|
|
194
|
+
return findingLines(item, lines, counted.has(item.rule), documentScope.has(item.rule)).some((number) => target.changed.has(number));
|
|
195
|
+
});
|
|
118
196
|
const finding = findings.find((item) => item.severity === 'block');
|
|
197
|
+
const advice = rules.find((rule) => rule.id === 'negation-cluster')?.message;
|
|
119
198
|
if (!finding) {
|
|
120
199
|
const warning = findings.find((item) => item.severity === 'warn');
|
|
121
|
-
|
|
200
|
+
const message = advice && findings.some((item) => item.rule === 'negation-cluster');
|
|
201
|
+
allow(warning ? `advisory ${warning.rule} in ${target.file}; review wording${message ? `: ${advice}` : ''}` : undefined);
|
|
122
202
|
}
|
|
123
203
|
else {
|
|
124
|
-
|
|
204
|
+
// The deny reason carries the rewrite advice when a negation cluster is what blocks.
|
|
205
|
+
const message = advice && findings.some((item) => item.rule === 'negation-cluster' && item.severity === 'block');
|
|
206
|
+
const reason = `lit-humanizer ${blockNote(target.file, finding)}${message ? `: ${advice}` : ''}`;
|
|
207
|
+
process.stdout.write(`${JSON.stringify({ decision: 'deny', reason })}\n`);
|
|
208
|
+
// Grok Build reads the JSON reason; its first stderr line is the fallback reason on exit 2.
|
|
209
|
+
process.stderr.write(`${reason.replace(/\s*\n\s*/g, ' ')}\n`);
|
|
125
210
|
process.exitCode = 2;
|
|
126
211
|
}
|
|
127
212
|
}
|