@litfamily/litgrok 1.0.28 → 1.0.30
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/rules/00-litgrok.md +13 -0
- package/.grok/skills/lit-adhd/SKILL.md +10 -4
- package/.grok/skills/lit-adhd/scripts/lib/brief.mjs +4 -1
- package/.grok/skills/lit-adhd/scripts/lib/collect.mjs +14 -1
- package/.grok/skills/lit-adhd/scripts/lib/next-step.mjs +46 -5
- package/.grok/skills/lit-init/SKILL.md +4 -0
- package/.grok/skills/lit-typographic-motion/requirements-audio.txt +92 -89
- package/.grok/skills/readme-studio/templates/remotion/package-lock.json +3 -3
- package/.grok/skills/readme-studio/templates/remotion/package.json +3 -0
- package/.grok-plugin/plugin.json +1 -1
- package/CHANGELOG.md +12 -0
- package/README.md +8 -8
- package/README_ko-KR.md +8 -8
- package/bin/ground-rule.mjs +573 -0
- package/bin/litgrok.mjs +42 -5
- package/docs/assets/readme/badge-version.svg +1 -1
- package/docs/reference.md +2 -2
- package/docs/reference_ko-KR.md +2 -2
- package/package.json +1 -1
- package/plugin.json +1 -1
package/bin/litgrok.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import { homedir } from 'node:os';
|
|
|
6
6
|
import { basename, dirname, join, relative, resolve, sep } from 'node:path';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
8
|
import { renderMark, terminalMode } from '../.grok/hooks/lit-mark.mjs';
|
|
9
|
+
import { applyStoredGround, backupIfSectionAbsent, decideGround, groundReport, ruleSourceForInstall, runGround } from './ground-rule.mjs';
|
|
9
10
|
import { installNotifications, installStatusLine, removeNotifications, removeStatusLine } from './status-line-config.mjs';
|
|
10
11
|
|
|
11
12
|
const PACKAGE_ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
@@ -208,7 +209,7 @@ const PRE_MANIFEST_LEGACY_PAYLOAD_HASHES = Object.freeze({
|
|
|
208
209
|
'skills/text-naturalization/SKILL.md': 'aa1ff8f68ab0bf71cb47818b536c4a2934da65adb413ee43ec5839b540b2df8e',
|
|
209
210
|
'skills/lit-korean/SKILL.md': 'dc2e4b0ea2ff6acca904f05767a62448387571e4183a615d5e53b230704ee828',
|
|
210
211
|
});
|
|
211
|
-
const USAGE = 'Usage: litgrok [install|uninstall] [--user|--project] [--status-line] [--notify] [--dry-run] [--no-color] [--yes]\n litgrok auto-handoff on [percent]|off|status\n litgrok doctor [--no-color]\n litgrok motion-runtime install|status\nTypographic-motion engine adapted from mexicat/pdoom-video (MIT, Giacomo Magnanini), commit ca251e3.\n';
|
|
212
|
+
const USAGE = 'Usage: litgrok [install|uninstall] [--user|--project] [--status-line] [--notify] [--dry-run] [--no-color] [--yes] [--no-ground]\n litgrok ground on|off|status\n litgrok ground project [--dir <path>] [--remove] [--dry-run]\n litgrok auto-handoff on [percent]|off|status\n litgrok doctor [--no-color]\n litgrok motion-runtime install|status\nTypographic-motion engine adapted from mexicat/pdoom-video (MIT, Giacomo Magnanini), commit ca251e3.\n';
|
|
212
213
|
const BRAILLE_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
213
214
|
const SPINNER_INTERVAL_MS = 80;
|
|
214
215
|
const CLEAR_LINE = '\r\u001b[2K';
|
|
@@ -217,7 +218,7 @@ function parseInstall(args) {
|
|
|
217
218
|
const remaining = [...args];
|
|
218
219
|
let command = 'install';
|
|
219
220
|
if (['install', 'uninstall'].includes(remaining[0])) command = remaining.shift();
|
|
220
|
-
if (remaining.some((argument) => !['--user', '--project', '--status-line', '--notify', '--dry-run', '--no-color', '--yes'].includes(argument))) return null;
|
|
221
|
+
if (remaining.some((argument) => !['--user', '--project', '--status-line', '--notify', '--dry-run', '--no-color', '--yes', '--no-ground'].includes(argument))) return null;
|
|
221
222
|
if (remaining.includes('--user') && remaining.includes('--project')) return null;
|
|
222
223
|
// Both opt-ins change ~/.grok/config.toml, which only a user install may touch.
|
|
223
224
|
if ((remaining.includes('--status-line') || remaining.includes('--notify')) && (command !== 'install' || !remaining.includes('--user'))) return null;
|
|
@@ -226,6 +227,7 @@ function parseInstall(args) {
|
|
|
226
227
|
dryRun: remaining.includes('--dry-run'),
|
|
227
228
|
noColor: remaining.includes('--no-color'),
|
|
228
229
|
yes: remaining.includes('--yes'),
|
|
230
|
+
noGround: remaining.includes('--no-ground'),
|
|
229
231
|
statusLine: remaining.includes('--status-line'),
|
|
230
232
|
notify: remaining.includes('--notify'),
|
|
231
233
|
scope: remaining.includes('--user') ? 'user' : 'project',
|
|
@@ -833,7 +835,7 @@ async function runDoctor(args, { env, stdout, stderr, fetchFn }) {
|
|
|
833
835
|
return 1;
|
|
834
836
|
}
|
|
835
837
|
const current = packageVersion();
|
|
836
|
-
stdout.write(`litgrok ${current}\n`);
|
|
838
|
+
stdout.write(`litgrok ${current}\n${groundReport(env)}\n`);
|
|
837
839
|
if (UPDATE_OPT_OUTS.some((name) => Object.hasOwn(env, name))) return 0;
|
|
838
840
|
let latest;
|
|
839
841
|
try {
|
|
@@ -855,6 +857,7 @@ export async function run(args, context = {}) {
|
|
|
855
857
|
const { runAutoHandoff } = await import('../.grok/hooks/auto-handoff.mjs');
|
|
856
858
|
return runAutoHandoff(args.slice(1), { env: context.env ?? process.env, stdout: context.stdout ?? process.stdout, stderr: context.stderr ?? process.stderr, cwd: context.cwd ?? process.cwd() });
|
|
857
859
|
}
|
|
860
|
+
if (args[0] === 'ground') return runGround(args.slice(1), context);
|
|
858
861
|
if (args[0] === 'doctor') {
|
|
859
862
|
return runDoctor(args.slice(1), {
|
|
860
863
|
env: context.env ?? process.env,
|
|
@@ -906,7 +909,7 @@ export async function run(args, context = {}) {
|
|
|
906
909
|
if (projectHooksIncluded(files)) stdout.write('Project hooks require a trusted Git project root: use /hooks-trust or, on Grok Build 1.0.13, grok --trust inspect --json; the installer never runs git init or changes trust.\n');
|
|
907
910
|
}
|
|
908
911
|
|
|
909
|
-
|
|
912
|
+
let files = discoveredPayload ? filesFromPayload(discoveredPayload) : null;
|
|
910
913
|
const payloadElapsed = payloadError ? null : elapsedSince(payloadStarted);
|
|
911
914
|
const colors = printInstallFrame(stdout, options, env, files?.length, displayRoot);
|
|
912
915
|
|
|
@@ -930,6 +933,33 @@ export async function run(args, context = {}) {
|
|
|
930
933
|
return 0;
|
|
931
934
|
}
|
|
932
935
|
|
|
936
|
+
let includeGround = true;
|
|
937
|
+
let groundAfter = null;
|
|
938
|
+
let cleanupGround = () => {};
|
|
939
|
+
if (options.command === 'install') {
|
|
940
|
+
try {
|
|
941
|
+
const decision = await decideGround({
|
|
942
|
+
scope: options.scope,
|
|
943
|
+
yes: options.yes,
|
|
944
|
+
noGround: options.noGround,
|
|
945
|
+
env,
|
|
946
|
+
stdin,
|
|
947
|
+
stdout,
|
|
948
|
+
home,
|
|
949
|
+
});
|
|
950
|
+
includeGround = decision.include;
|
|
951
|
+
groundAfter = decision.afterWrite;
|
|
952
|
+
if (!decision.include) {
|
|
953
|
+
const prepared = ruleSourceForInstall(files);
|
|
954
|
+
files = prepared.files;
|
|
955
|
+
cleanupGround = prepared.cleanup;
|
|
956
|
+
}
|
|
957
|
+
} catch (error) {
|
|
958
|
+
stderr.write(`litgrok: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
959
|
+
return 1;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
|
|
933
963
|
const progress = new InstallProgress(stdout, colors);
|
|
934
964
|
progress.open();
|
|
935
965
|
let step = 'PAYLOAD';
|
|
@@ -1046,6 +1076,7 @@ export async function run(args, context = {}) {
|
|
|
1046
1076
|
throw error;
|
|
1047
1077
|
}
|
|
1048
1078
|
const statusDetail = configDetail(statusLineResult, notifyResult);
|
|
1079
|
+
if (groundAfter) applyStoredGround(home, groundAfter);
|
|
1049
1080
|
skipStep(progress, 'WRITE', `SKIPPED · 0 written · ${states.counts.current} already-current${statusDetail}`);
|
|
1050
1081
|
const receipt = receiptCard(options, displayRoot, colors, { status: 'Already current', written: 0, current: states.counts.current });
|
|
1051
1082
|
progress.close();
|
|
@@ -1059,8 +1090,11 @@ export async function run(args, context = {}) {
|
|
|
1059
1090
|
try {
|
|
1060
1091
|
for (let index = 0; index < files.length; index += 1) {
|
|
1061
1092
|
if (states.states[index] === 'current') continue;
|
|
1062
|
-
const { source, target } = files[index];
|
|
1093
|
+
const { source, target, relativePath } = files[index];
|
|
1063
1094
|
mkdirSync(dirname(target), { recursive: true });
|
|
1095
|
+
if (includeGround && normalizedRelativePath(relativePath) === 'rules/00-litgrok.md' && states.states[index] !== 'missing') {
|
|
1096
|
+
backupIfSectionAbsent(target);
|
|
1097
|
+
}
|
|
1064
1098
|
if (states.states[index] === 'owned') replaceOwnedFile(source, target);
|
|
1065
1099
|
else copyFileSync(source, target, constants.COPYFILE_EXCL);
|
|
1066
1100
|
installed += 1;
|
|
@@ -1072,6 +1106,7 @@ export async function run(args, context = {}) {
|
|
|
1072
1106
|
const notifyResult = options.notify ? installNotifications(root) : null;
|
|
1073
1107
|
const legacyDetail = removedLegacy === 0 ? '' : ` · ${removedLegacy} legacy removed`;
|
|
1074
1108
|
const statusDetail = configDetail(statusLineResult, notifyResult);
|
|
1109
|
+
if (groundAfter) applyStoredGround(home, groundAfter);
|
|
1075
1110
|
progress.finish('ok', 'WRITE', `${installed} written · ${states.counts.current} already-current · ${states.counts.owned} owned${legacyDetail}${statusDetail}`, elapsedSince(writeStarted));
|
|
1076
1111
|
} catch (error) {
|
|
1077
1112
|
progress.finish('failed', 'WRITE', errorText(error), elapsedSince(writeStarted));
|
|
@@ -1086,6 +1121,8 @@ export async function run(args, context = {}) {
|
|
|
1086
1121
|
progress.close();
|
|
1087
1122
|
reportFailure(error, { stderr, stdout, options, root: displayRoot, colors, step });
|
|
1088
1123
|
return 1;
|
|
1124
|
+
} finally {
|
|
1125
|
+
cleanupGround();
|
|
1089
1126
|
}
|
|
1090
1127
|
}
|
|
1091
1128
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="local: 1.0.
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="local: 1.0.30"><title>local: 1.0.30</title><g shape-rendering="crispEdges"><rect width="49" height="20" fill="#080d14"/><rect x="49" width="97" height="20" fill="#ff6337"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text x="255" y="140" textLength="290" transform="scale(.1)">local</text><text x="965" y="140" textLength="870" transform="scale(.1)" fill="#080D14">1.0.30</text></g></svg>
|
package/docs/reference.md
CHANGED
|
@@ -80,7 +80,7 @@ npm exec --yes --package @litfamily/litgrok@latest -- litgrok install
|
|
|
80
80
|
Pin a version when you need a reproducible install:
|
|
81
81
|
|
|
82
82
|
```bash
|
|
83
|
-
npm exec --yes --package @litfamily/litgrok@1.0.
|
|
83
|
+
npm exec --yes --package @litfamily/litgrok@1.0.30 -- litgrok install
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
Preview without writing files:
|
|
@@ -103,7 +103,7 @@ npm exec --yes --package @litfamily/litgrok@latest -- litgrok install --user
|
|
|
103
103
|
npm exec --yes --package @litfamily/litgrok@latest -- litgrok doctor
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
`doctor` is read-only. It prints the package version
|
|
106
|
+
`doctor` is read-only. It prints the package version and one `GROUND:` line for the section at the end of `~/.grok/rules/00-litgrok.md`: `present v=<version>`, `stale v=<version>`, `absent`, `malformed` or `off`. It asks the npm registry for the latest stable `@litfamily/litgrok` with a 3-second limit, and adds `newer version available: <version> (run: npm exec --yes --package @litfamily/litgrok@latest -- litgrok install)` when one exists. It adds nothing further when you are current, and one `update check unavailable` line when the registry cannot be reached. It never installs or writes files. `NO_UPDATE_NOTIFIER`, `CI` or `LITGROK_NO_UPDATE_CHECK` (present, even empty) skips the registry request. `litgrok ground off` removes that section and keeps it off; `litgrok ground on` restores it; `install --no-ground` skips it for that run. `litgrok ground project` writes the repo copy at `.grok/rules/10-litgrok-ground.md` and refuses a symlink, a non-directory path, or a file it does not own.
|
|
107
107
|
|
|
108
108
|
### Persistent status line (opt-in)
|
|
109
109
|
|
package/docs/reference_ko-KR.md
CHANGED
|
@@ -81,7 +81,7 @@ npm exec --yes --package @litfamily/litgrok@latest -- litgrok install
|
|
|
81
81
|
재현 가능한 설치는 버전을 고정합니다.
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
|
-
npm exec --yes --package @litfamily/litgrok@1.0.
|
|
84
|
+
npm exec --yes --package @litfamily/litgrok@1.0.30 -- litgrok install
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
파일을 쓰지 않고 미리보기:
|
|
@@ -104,7 +104,7 @@ npm exec --yes --package @litfamily/litgrok@latest -- litgrok install --user
|
|
|
104
104
|
npm exec --yes --package @litfamily/litgrok@latest -- litgrok doctor
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
`doctor`는 읽기만 합니다. 패키지 버전을 출력하고, npm 레지스트리에 최신 안정 `@litfamily/litgrok` 버전을 최대 3초 동안 물어봅니다. 더 새 버전이 있으면 `newer version available: <version> (run: npm exec --yes --package @litfamily/litgrok@latest -- litgrok install)` 한 줄을 더합니다. 최신이면
|
|
107
|
+
`doctor`는 읽기만 합니다. 패키지 버전을 출력하고, `~/.grok/rules/00-litgrok.md` 끝 구간에 대해 `GROUND:` 한 줄을 냅니다. 값은 `present v=<version>`, `stale v=<version>`, `absent`, `malformed`, `off` 중 하나입니다. npm 레지스트리에 최신 안정 `@litfamily/litgrok` 버전을 최대 3초 동안 물어봅니다. 더 새 버전이 있으면 `newer version available: <version> (run: npm exec --yes --package @litfamily/litgrok@latest -- litgrok install)` 한 줄을 더합니다. 최신이면 그 이상은 더하지 않고, 레지스트리에 닿지 못하면 `update check unavailable` 한 줄을 출력합니다. 설치하거나 파일을 쓰지 않습니다. `NO_UPDATE_NOTIFIER`, `CI`, `LITGROK_NO_UPDATE_CHECK` 중 하나가 있으면(값이 비어 있어도) 레지스트리에 묻지 않습니다. `litgrok ground off`는 그 구간을 빼고 꺼 둔 채로 두며, `litgrok ground on`은 다시 넣습니다. `install --no-ground`는 그 한 번만 건너뜁니다. `litgrok ground project`는 저장소 복사본을 `.grok/rules/10-litgrok-ground.md`에 쓰며, 심볼릭 링크, 디렉터리가 아닌 경로, 자신이 소유하지 않은 파일은 거절합니다.
|
|
108
108
|
|
|
109
109
|
### 지속 상태 행 (선택)
|
|
110
110
|
|
package/package.json
CHANGED