@lovrozagar/grunt 0.10.0 → 0.11.0
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/.agents/agents/orchestrator.md +1 -1
- package/.agents/hooks.json +2 -2
- package/.agents/skills/browser/SKILL.md +3 -3
- package/.agents/skills/clasp/SKILL.md +1 -1
- package/.agents/skills/explain/SKILL.md +1 -1
- package/.agents/skills/google-workspace/SKILL.md +3 -3
- package/.agents/skills/handoff/SKILL.md +2 -2
- package/.agents/skills/implement-plan/SKILL.md +2 -2
- package/.agents/skills/jev/SKILL.md +3 -3
- package/.agents/skills/listen/SKILL.md +3 -3
- package/.agents/skills/pickup/SKILL.md +1 -1
- package/.agents/skills/speak/SKILL.md +3 -3
- package/.agents/skills/tmp/SKILL.md +2 -2
- package/.agents/skills/write-plan/SKILL.md +4 -2
- package/.claude/agents/orchestrator.md +1 -1
- package/.claude/settings.json +3 -3
- package/.claude/skills/browser/SKILL.md +3 -3
- package/.claude/skills/clasp/SKILL.md +1 -1
- package/.claude/skills/explain/SKILL.md +1 -1
- package/.claude/skills/google-workspace/SKILL.md +3 -3
- package/.claude/skills/handoff/SKILL.md +2 -2
- package/.claude/skills/implement-plan/SKILL.md +2 -2
- package/.claude/skills/jev/SKILL.md +3 -3
- package/.claude/skills/listen/SKILL.md +3 -3
- package/.claude/skills/pickup/SKILL.md +1 -1
- package/.claude/skills/speak/SKILL.md +3 -3
- package/.claude/skills/tmp/SKILL.md +2 -2
- package/.claude/skills/write-plan/SKILL.md +4 -2
- package/.codex/agents/orchestrator.toml +1 -1
- package/.codex/hooks.json +3 -3
- package/.grok/agents/orchestrator.md +1 -1
- package/.grok/hooks/orchestrate-parent.js +9 -9
- package/.grok/skills/browser/SKILL.md +3 -3
- package/.grok/skills/clasp/SKILL.md +1 -1
- package/.grok/skills/explain/SKILL.md +1 -1
- package/.grok/skills/google-workspace/SKILL.md +3 -3
- package/.grok/skills/handoff/SKILL.md +2 -2
- package/.grok/skills/implement-plan/SKILL.md +2 -2
- package/.grok/skills/jev/SKILL.md +3 -3
- package/.grok/skills/listen/SKILL.md +3 -3
- package/.grok/skills/pickup/SKILL.md +1 -1
- package/.grok/skills/speak/SKILL.md +3 -3
- package/.grok/skills/tmp/SKILL.md +2 -2
- package/.grok/skills/write-plan/SKILL.md +4 -2
- package/.rulesync/hooks.jsonc +3 -3
- package/.rulesync/reference/INDEX.md +10 -10
- package/.rulesync/reference/browser.md +4 -4
- package/.rulesync/reference/cascade.md +2 -2
- package/.rulesync/reference/clasp.md +1 -1
- package/.rulesync/reference/google-workspace.md +29 -29
- package/.rulesync/reference/hooks.md +3 -3
- package/.rulesync/reference/implementation-format.md +2 -2
- package/.rulesync/reference/jev.md +3 -3
- package/.rulesync/reference/law.md +1 -1
- package/.rulesync/reference/listen.md +12 -12
- package/.rulesync/reference/map.md +25 -25
- package/.rulesync/reference/output.md +9 -1
- package/.rulesync/reference/refs-map.md +4 -4
- package/.rulesync/reference/rtk.md +1 -1
- package/.rulesync/reference/scope.md +12 -14
- package/.rulesync/reference/setup.md +7 -7
- package/.rulesync/reference/skills-map.md +5 -5
- package/.rulesync/reference/speak.md +6 -6
- package/.rulesync/rules/overview.md +9 -5
- package/{scripts → .rulesync/scripts}/doctor.mjs +2 -2
- package/{scripts → .rulesync/scripts}/feature-packs.mjs +1 -1
- package/{scripts → .rulesync/scripts}/folder-map.mjs +7 -3
- package/{scripts → .rulesync/scripts}/gate-fat-tools.mjs +3 -3
- package/{scripts → .rulesync/scripts}/google-workspace.mjs +2 -2
- package/{scripts → .rulesync/scripts}/grunt-job.mjs +2 -0
- package/{scripts → .rulesync/scripts}/guarded-md.mjs +10 -4
- package/{scripts → .rulesync/scripts}/hooks-union.mjs +13 -8
- package/{scripts → .rulesync/scripts}/jev.mjs +2 -2
- package/{scripts → .rulesync/scripts}/listen.mjs +6 -6
- package/{scripts → .rulesync/scripts}/pipeline.mjs +14 -14
- package/{scripts → .rulesync/scripts}/session-map.mjs +1 -1
- package/{scripts → .rulesync/scripts}/setup.mjs +4 -4
- package/{scripts → .rulesync/scripts}/speak.mjs +4 -4
- package/.rulesync/skills/browser/SKILL.md +3 -3
- package/.rulesync/skills/clasp/SKILL.md +1 -1
- package/.rulesync/skills/explain/SKILL.md +1 -1
- package/.rulesync/skills/google-workspace/SKILL.md +3 -3
- package/.rulesync/skills/handoff/SKILL.md +2 -2
- package/.rulesync/skills/implement-plan/SKILL.md +2 -2
- package/.rulesync/skills/jev/SKILL.md +3 -3
- package/.rulesync/skills/listen/SKILL.md +3 -3
- package/.rulesync/skills/pickup/SKILL.md +1 -1
- package/.rulesync/skills/speak/SKILL.md +3 -3
- package/.rulesync/skills/tmp/SKILL.md +2 -2
- package/.rulesync/skills/write-plan/SKILL.md +4 -2
- package/.rulesync/subagents/orchestrator.md +1 -1
- package/AGENTS.md +11 -5
- package/CHANGELOG.md +22 -0
- package/CLAUDE.md +2 -0
- package/README.md +23 -23
- package/cli/grunt.mjs +3 -3
- package/cli/grunt.test.ts +6 -6
- package/cli/init.mjs +64 -16
- package/cli/init.test.ts +310 -163
- package/cli/prompt.mjs +1 -1
- package/cli/self-update.mjs +1 -1
- package/package.json +15 -50
- /package/{scripts → .rulesync/scripts}/board.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/browser.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/check-globals.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/emit-agent-shell-tools.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/emit-gemini.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/emit-maps.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/emit-mcp-policy.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/guarded-roots.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/interactive.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/jsonc.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/package-manager.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/parse-need.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/persist-handoff.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/persist-implementation.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/persist-plan.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/persist-tmp.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/prompt.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/purge-global-mcps.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/scrub-spawn-prompt.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/scrub-text +0 -0
- /package/{scripts → .rulesync/scripts}/scrub-text-lib.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/skill-conflicts.mjs +0 -0
- /package/{scripts → .rulesync/scripts}/sync-global-settings.mjs +0 -0
|
@@ -5,7 +5,7 @@ description: "Longer human recap this reply only."
|
|
|
5
5
|
This reply only: explain for a human. Not a mode switch or session flag. After this reply, revert to output.md.
|
|
6
6
|
|
|
7
7
|
Still concise. Complete sentences. Prioritize clarity over token compression. Do not dump, sprawl, or narrate process.
|
|
8
|
-
|
|
8
|
+
Open with the verdict, failures included. The four buckets are the middle (completed / in-flight / remainder / blocker). Close on the same facts. Completed work = past tense. Omit empty. Natural language; no key tokens. Longer expansion this reply only — not the only grammar for complete sentences.
|
|
9
9
|
|
|
10
10
|
en-US unless asked. Keep need: JSON and plan grammar when those apply.
|
|
11
11
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: google-workspace
|
|
3
|
-
description: "Google Sheets, Docs, Slides, Calendar, Gmail via node scripts/google-workspace.mjs."
|
|
3
|
+
description: "Google Sheets, Docs, Slides, Calendar, Gmail via node .rulesync/scripts/google-workspace.mjs."
|
|
4
4
|
---
|
|
5
5
|
# google-workspace
|
|
6
6
|
|
|
7
|
-
When the user wants a Google sheet, doc, slide, meeting, or mail, run `node scripts/google-workspace.mjs`. Spec: `.rulesync/reference/google-workspace.md`. If Calendar/Gmail/sheet set fail or login is missing, tell them to run `node scripts/setup.mjs google-workspace` (TTY) for the handheld walk. Do not share creds. Do not invent OAuth JSON. Do not ask them to write Apps Script.
|
|
7
|
+
When the user wants a Google sheet, doc, slide, meeting, or mail, run `node .rulesync/scripts/google-workspace.mjs`. Spec: `.rulesync/reference/google-workspace.md`. If Calendar/Gmail/sheet set fail or login is missing, tell them to run `node .rulesync/scripts/setup.mjs google-workspace` (TTY) for the handheld walk. Do not share creds. Do not invent OAuth JSON. Do not ask them to write Apps Script.
|
|
8
8
|
|
|
9
9
|
`whoami` · `scopes` · `accounts` · `login` · `sheet create|set|get|append|clear` · `doc create|append` · `drive list` · `slide create` · `meeting create [--attendees a@b,c@d]` · `mail send|list`. `--account NAME` for a second Google user on this machine.
|
|
10
10
|
|
|
11
|
-
Auth: `node scripts/setup.mjs google-workspace` then `login` as needed. Two Google users on one machine: `--account NAME`. Creds stay in `~/.grunt/` (or `~/.grunt/workspace/NAME/`). Do not share OAuth JSON or tokens. Doctor: `node scripts/doctor.mjs` reports google-workspace as optional (`oauth` `tokens` `adc` `clasprc`; no secrets). `clasprc` is Drive-only. Spec: `.rulesync/reference/google-workspace.md` `.rulesync/reference/setup.md`.
|
|
11
|
+
Auth: `node .rulesync/scripts/setup.mjs google-workspace` then `login` as needed. Two Google users on one machine: `--account NAME`. Creds stay in `~/.grunt/` (or `~/.grunt/workspace/NAME/`). Do not share OAuth JSON or tokens. Doctor: `node .rulesync/scripts/doctor.mjs` reports google-workspace as optional (`oauth` `tokens` `adc` `clasprc`; no secrets). `clasprc` is Drive-only. Spec: `.rulesync/reference/google-workspace.md` `.rulesync/reference/setup.md`.
|
|
@@ -56,9 +56,9 @@ Facts only. Absolute paths. No transcript paste, no dump, no secrets/tokens.
|
|
|
56
56
|
|
|
57
57
|
Line 1 of the body: `HANDOFF_NAME: <3-6 word name>`, then the body only.
|
|
58
58
|
|
|
59
|
-
Write under `.tmp/grunt/handoffs/` (any filename in that dir). Grok `orchestrate-parent.js` runs
|
|
59
|
+
Write under `.tmp/grunt/handoffs/` (any filename in that dir). Grok `orchestrate-parent.js` runs `.rulesync/scripts/persist-handoff.mjs`: serial/slug from `HANDOFF_NAME:` / heading, injects frontmatter, rewrites path + content. Invalid handoff or a write outside that dir is denied — fix the body, do not retry elsewhere.
|
|
60
60
|
|
|
61
|
-
Host without that hook: name the file per **Path** yourself, or pipe the body to `node scripts/persist-handoff.mjs --workspace {repo}` and use its `path`.
|
|
61
|
+
Host without that hook: name the file per **Path** yourself, or pipe the body to `node .rulesync/scripts/persist-handoff.mjs --workspace {repo}` and use its `path`.
|
|
62
62
|
|
|
63
63
|
## Report
|
|
64
64
|
|
|
@@ -4,10 +4,10 @@ description: "Execute remaining leaves in a .tmp/grunt/plans checklist. Skip [x]
|
|
|
4
4
|
---
|
|
5
5
|
# implement-plan
|
|
6
6
|
|
|
7
|
-
You execute the plan in this session. Skip `[x]`. Start at the first open leaf. Flip only the box after each leaf. When a phase's children are `[x]`, mark the phase `[x]`. Frontmatter `in-progress` then `done`.
|
|
7
|
+
You execute the plan in this session. Start only on a plan the user approved, or when the request said "plan and do it". Skip `[x]`. Start at the first open leaf. Flip only the box after each leaf. When a phase's children are `[x]`, mark the phase `[x]`. Frontmatter `in-progress` then `done`.
|
|
8
8
|
|
|
9
9
|
Arg `{n|path}` picks that file. Empty arg: unique in-progress, else unique ready, else list serials.
|
|
10
10
|
|
|
11
|
-
Format: `.rulesync/reference/plan-format.md`. Write-allowlist = paths listed in the plan. Run Verify leaves. Do not skip a test leaf. Do not flip a behavior leaf `[x]` until its test ran. Fat dumps go through `node scripts/grunt-job.mjs`.
|
|
11
|
+
Format: `.rulesync/reference/plan-format.md`. Write-allowlist = paths listed in the plan. Run Verify leaves. Do not skip a test leaf. Do not flip a behavior leaf `[x]` until its test ran. Fat dumps go through `node .rulesync/scripts/grunt-job.mjs`.
|
|
12
12
|
|
|
13
13
|
On start: if this plan has no journal, Write one under `.tmp/grunt/implementations/` (`IMPL_NAME:`, `IMPL_PLAN: {n}`). Format: `.rulesync/reference/implementation-format.md`. After each leaf: append `N.M [x] …` to Log, update Files (repo-relative product paths) and Done. Blocked → `status: blocked` and Blockers. Verify done → `status: done`. Straight shots do not write a journal.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jev
|
|
3
|
-
description: "Yes/no or named-option decision on text already saved. Run node scripts/jev.mjs --available first. On yes, one decision call. On no, decide yourself and do not mention Jev."
|
|
3
|
+
description: "Yes/no or named-option decision on text already saved. Run node .rulesync/scripts/jev.mjs --available first. On yes, one decision call. On no, decide yourself and do not mention Jev."
|
|
4
4
|
---
|
|
5
5
|
# jev
|
|
6
6
|
|
|
7
7
|
Use this when the source text is already saved and the leftover question is a yes/no or a choice among options the research already named. Spec: `.rulesync/reference/jev.md`.
|
|
8
8
|
|
|
9
|
-
Run `node scripts/jev.mjs --available`. It prints `yes` or `no` and exits 0.
|
|
9
|
+
Run `node .rulesync/scripts/jev.mjs --available`. It prints `yes` or `no` and exits 0.
|
|
10
10
|
|
|
11
11
|
`no`: answer the question yourself. Do not run a decision call. Do not mention Jev, a missing key, or setup.
|
|
12
12
|
|
|
13
|
-
`yes`: read `.rulesync/reference/jev.md`. Write the passage and one questions file under `.tmp/grunt/jev/`. Run `node scripts/jev.mjs --state <state> --questions <questions>` once. Use the printed label and confidence. A low confidence is the result. Do not call again.
|
|
13
|
+
`yes`: read `.rulesync/reference/jev.md`. Write the passage and one questions file under `.tmp/grunt/jev/`. Run `node .rulesync/scripts/jev.mjs --state <state> --questions <questions>` once. Use the printed label and confidence. A low confidence is the result. Do not call again.
|
|
14
14
|
|
|
15
15
|
Open research, code, and grunt-job stay with the session. If the decision call exits non-zero, answer from the sources. Do not invent a label.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: listen
|
|
3
|
-
description: "Speech-to-text via node scripts/listen.mjs (ffmpeg mic + local whisper.cpp, OpenAI fallback). Input only."
|
|
3
|
+
description: "Speech-to-text via node .rulesync/scripts/listen.mjs (ffmpeg mic + local whisper.cpp, OpenAI fallback). Input only."
|
|
4
4
|
---
|
|
5
5
|
# listen
|
|
6
6
|
|
|
7
|
-
When the user wants to dictate, transcribe a recording, or toggle a mic, run `node scripts/listen.mjs`. Spec: `.rulesync/reference/listen.md`. Input only (audio → text). Do not speak. Do not use `/speak`.
|
|
7
|
+
When the user wants to dictate, transcribe a recording, or toggle a mic, run `node .rulesync/scripts/listen.mjs`. Spec: `.rulesync/reference/listen.md`. Input only (audio → text). Do not speak. Do not use `/speak`.
|
|
8
8
|
|
|
9
9
|
`whoami` · `devices` · `rec [--seconds N]` · `start` · `stop` · `toggle` · `status` · `file --path P` · `latest`. `--clip` copies the transcript. `--cwd DIR` when the process is not already in the repo (hotkeys). `rec` prints the transcript and `transcript=.tmp/grunt/listen/latest.txt`.
|
|
10
10
|
|
|
11
11
|
STT: local `whisper-cli` first (mac: `brew install whisper-cpp`); first listen downloads the ggml model to `~/.grunt/whisper/`. Else `OPENAI_API_KEY`. Mic verbs need ffmpeg. Do not tell them to pip-install openai-whisper or curl the model by hand.
|
|
12
12
|
|
|
13
|
-
If the CLI exits non-zero, print its message. Lines with `setup:` are for the user — show that command. Tell them to run `node scripts/setup.mjs listen` (or `grunt setup`) in their terminal. Do not dump JSON. Do not invent a key. Spec: `.rulesync/reference/listen.md` `.rulesync/reference/setup.md`.
|
|
13
|
+
If the CLI exits non-zero, print its message. Lines with `setup:` are for the user — show that command. Tell them to run `node .rulesync/scripts/setup.mjs listen` (or `grunt setup`) in their terminal. Do not dump JSON. Do not invent a key. Spec: `.rulesync/reference/listen.md` `.rulesync/reference/setup.md`.
|
|
@@ -18,7 +18,7 @@ Load a handoff and continue in this session. Not a mode. Not `/handoff`. Inverse
|
|
|
18
18
|
|
|
19
19
|
## Resolve
|
|
20
20
|
|
|
21
|
-
Read `.tmp/grunt/handoffs/`. Use `node scripts/grunt-job.mjs --job search|exec` when the listing is fat.
|
|
21
|
+
Read `.tmp/grunt/handoffs/`. Use `node .rulesync/scripts/grunt-job.mjs --job search|exec` when the listing is fat.
|
|
22
22
|
|
|
23
23
|
Order:
|
|
24
24
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: speak
|
|
3
|
-
description: "Text-to-speech via node scripts/speak.mjs (ElevenLabs or OpenAI). Output only."
|
|
3
|
+
description: "Text-to-speech via node .rulesync/scripts/speak.mjs (ElevenLabs or OpenAI). Output only."
|
|
4
4
|
---
|
|
5
5
|
# speak
|
|
6
6
|
|
|
7
|
-
When the user wants spoken audio, run `node scripts/speak.mjs`. Spec: `.rulesync/reference/speak.md`. Output only (text → mp3). Do not record a mic. Do not transcribe.
|
|
7
|
+
When the user wants spoken audio, run `node .rulesync/scripts/speak.mjs`. Spec: `.rulesync/reference/speak.md`. Output only (text → mp3). Do not record a mic. Do not transcribe.
|
|
8
8
|
|
|
9
9
|
`whoami` · `voices` · `say --text T [--provider elevenlabs|openai] [--voice ID] [--out path] [--play]`.
|
|
10
10
|
|
|
11
11
|
Auth: `ELEVENLABS_API_KEY` or `OPENAI_API_KEY` or `~/.grunt/speak.json`. Do not commit the key. Default voices: ElevenLabs George (`JBFqnCBsd6RMkjVDRZzb`), OpenAI `coral`.
|
|
12
12
|
|
|
13
|
-
If the CLI exits non-zero, print its message. Lines with `setup:` are for the user — show that command. Tell them to run `node scripts/setup.mjs speak` (or `grunt setup`) in their terminal. Do not dump JSON. Do not invent a key. Spec: `.rulesync/reference/speak.md` `.rulesync/reference/setup.md`.
|
|
13
|
+
If the CLI exits non-zero, print its message. Lines with `setup:` are for the user — show that command. Tell them to run `node .rulesync/scripts/setup.mjs speak` (or `grunt setup`) in their terminal. Do not dump JSON. Do not invent a key. Spec: `.rulesync/reference/speak.md` `.rulesync/reference/setup.md`.
|
|
@@ -33,9 +33,9 @@ TMP_EXT: md
|
|
|
33
33
|
<artifact only>
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
`TMP_EXT` optional. Write any root filename under `.tmp/grunt/` (not `plans|handoffs|implementations|browser|orchestrator-logs`). Grok `orchestrate-parent.js` runs
|
|
36
|
+
`TMP_EXT` optional. Write any root filename under `.tmp/grunt/` (not `plans|handoffs|implementations|browser|orchestrator-logs`). Grok `orchestrate-parent.js` runs `.rulesync/scripts/persist-tmp.mjs`: serial/slug/ext from `TMP_*`, strips those lines, no YAML frontmatter, rewrites path + content. Write outside that root or missing `TMP_NAME:` is denied.
|
|
37
37
|
|
|
38
|
-
Host without that hook: name the file per **Path** yourself, or pipe the body to `node scripts/persist-tmp.mjs --workspace {repo}` and use its `path`.
|
|
38
|
+
Host without that hook: name the file per **Path** yourself, or pipe the body to `node .rulesync/scripts/persist-tmp.mjs --workspace {repo}` and use its `path`.
|
|
39
39
|
|
|
40
40
|
Never rewrite an existing dump; new serial. Artifact file content after hook = artifact only (no TMP_* lines no YAML frontmatter).
|
|
41
41
|
|
|
@@ -4,10 +4,12 @@ description: "Write a local checklist under .tmp/grunt/plans/. Then /implement-p
|
|
|
4
4
|
---
|
|
5
5
|
# write-plan
|
|
6
6
|
|
|
7
|
-
You author the plan. Persist under `.tmp/grunt/plans/` via Write (hook runs
|
|
7
|
+
You author the plan. Persist under `.tmp/grunt/plans/` via Write (hook runs `.rulesync/scripts/persist-plan.mjs`). Format: `.rulesync/reference/plan-format.md`.
|
|
8
8
|
|
|
9
9
|
Empty task → ask for a task and stop.
|
|
10
10
|
|
|
11
11
|
Body starts with `PLAN_NAME: <3-6 word name>`, then Goal, Context, Constraints, Watch-outs, Steps, Verify. All boxes `[ ]`. Tests: new behavior or bug → failing test leaf before impl; other behavior → test leaf right after impl; docs/rename/config/generated → skip. Verify is the end gate.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
The plan is the proposal and caps the result (`.rulesync/reference/scope.md`). Before writing, research until every leaf is defensible; ask any plan-shaping question the user alone can answer, then research again on the answer. Do not default a plan-shaping choice. A minor open choice goes under Constraints as the chosen default plus "confirm".
|
|
14
|
+
|
|
15
|
+
Report: serial N at `.tmp/grunt/plans/{file}`, the goal, the phase list, the top risks, and any assumption to confirm. Do not dump the plan. Stop and ask for approval; on feedback, revise this file and stop again. Run `/implement-plan {n}` in the same turn only when the request said "plan and do it".
|
|
@@ -32,4 +32,4 @@ antigravity-cli:
|
|
|
32
32
|
geminicli:
|
|
33
33
|
model: gemini-2.5-pro
|
|
34
34
|
---
|
|
35
|
-
Follow AGENTS.md. Do the work. Concise complete sentences with natural grammar. Scratch in `.tmp/grunt/`. Browse with `node scripts/browser.mjs`; the rail swaps to Chromium when Lightpanda is blocked. App e2e uses Playwright.
|
|
35
|
+
Follow AGENTS.md. Do the work. Concise complete sentences with natural grammar. Scratch in `.tmp/grunt/`. Browse with `node .rulesync/scripts/browser.mjs`; the rail swaps to Chromium when Lightpanda is blocked. App e2e uses Playwright.
|
package/AGENTS.md
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
<!-- grunt:begin -->
|
|
2
|
-
You are the session agent. Do the work. Use en-US unless asked. Write concise complete sentences with natural grammar. Skip filler and fluff. Ship optimal solutions only; rewrite if not. Flag blockers. Do not monkey-patch. When advising, recommend the optimal choice based on research, data, and reasoning, not the user's preference. Change it only for new evidence or a flaw found in it. Pushback or a leading question is not a reason to switch; keep the recommendation and explain why. Do and verify the work yourself with every tool and credential you have. Don't guess, say "likely" or similar, trust older memory, stop short, leave placeholders, or hand the user anything you could do. Ask only when you truly lack the means, and say what you tried. Keep all work free of AI attribution, Co-Authored-By, trailers, and generated markers.
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
You are the session agent. Do the work. Use en-US unless asked. Write concise complete sentences with natural grammar. Skip filler and fluff. Ship optimal solutions only; rewrite if not. Flag blockers. Do not monkey-patch. When advising, recommend the optimal choice based on research, data, and reasoning, not the user's preference. Change it only for new evidence or a flaw found in it. Pushback or a leading question is not a reason to switch; keep the recommendation and explain why. Do and verify the work yourself with every tool and credential you have. Don't guess, say "likely" or similar, trust older memory, stop short, leave placeholders, or hand the user anything you could do. Stopping for approval of a written plan is not stopping short. Ask only when you truly lack the means (the user's intent and preferences count), and say what you tried. Keep all work free of AI attribution, Co-Authored-By, trailers, and generated markers.
|
|
4
|
+
|
|
5
|
+
Examples are a class. `...`, `etc` / etcetera, and a `;` between specimens are that same class. An example, an open list, or a negative example means infer the class and do what reasonably fits this case, including what they did not name. Do not copy the example's words, stop at the named items, or add work outside the class. In a plan or a spawn prompt, pass the class. A `;` in code or an ordinary clause is not that cue. Closed instructions stay literal. Detail: `.rulesync/reference/output.md`.
|
|
6
|
+
|
|
7
|
+
A question or a work result opens with the verdict, the counts, or the outcome, failures included. The middle is the concise explanation. The last line lands those same facts as the decision or the one real next step. Do not invent a question or change the numbers. Skip this shape for a one-line answer, a raw artifact, or a reply a skill already shapes.
|
|
8
|
+
|
|
9
|
+
Plan first. A straight shot is one file, one obvious edit, and nothing to decide: do it. Anything else: the plan caps the result, so research until every leaf is defensible, ask what only the user can answer, and research again on each answer. A clear task gets one plan; an unclear one gets rounds. Then `/write-plan`, stop for approval, revise on feedback, and `/implement-plan`. Detail: `.rulesync/reference/scope.md`.
|
|
5
10
|
Default `/auto`: keep going; ask on blockers. `/ask`: one step, then ask.
|
|
6
11
|
Ask before destructive git (stash, reset, checkout, restore, clean, rebase, push -f); others share the tree. In a loop, skip it and edit code instead.
|
|
7
12
|
|
|
8
13
|
Read `.rulesync/reference/INDEX.md` once. When a row matches the work, read that reference in full.
|
|
9
|
-
To learn the repo layout, use the folder map if it is in your context. If it is missing, or you need more depth, run `node scripts/folder-map.mjs [dir]` instead of exploring with `ls` or `find`.
|
|
14
|
+
To learn the repo layout, use the folder map if it is in your context. If it is missing, or you need more depth, run `node .rulesync/scripts/folder-map.mjs [dir]` instead of exploring with `ls` or `find`.
|
|
10
15
|
|
|
11
16
|
Large dumps are compressed (search, test logs, snaps). Scratch and dumps live in `.tmp/grunt/` (gitignored). After a write, recap the path; edit with an offset slice when you need lines.
|
|
12
|
-
Fat dumps: `node scripts/grunt-job.mjs --job search|exec|slice|fetch|test` first; spawn grunt only when the dump needs judgment.
|
|
17
|
+
Fat dumps: `node .rulesync/scripts/grunt-job.mjs --job search|exec|slice|fetch|test` first; spawn grunt only when the dump needs judgment.
|
|
18
|
+
|
|
19
|
+
Browse with `node .rulesync/scripts/browser.mjs`. Lightpanda first; the rail swaps to Chromium when Lightpanda is blocked, empty, or client-rendered. Do not stop and say you cannot. App e2e is `playwright test`.
|
|
13
20
|
|
|
14
|
-
Browse with `node scripts/browser.mjs`. Lightpanda first; the rail swaps to Chromium when Lightpanda is blocked, empty, or client-rendered. Do not stop and say you cannot. App e2e is `playwright test`.
|
|
15
21
|
<!-- grunt:end -->
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.11.0] - 2026-10-12
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Breaking: grunt's product scripts moved from root `scripts/` to `.rulesync/scripts/`. Hooks, `grunt:*` package scripts, the pipeline, skills, and references use the new path. `grunt upgrade` moves them: it deletes grunt-owned names from a root `scripts/` that held a grunt install, removes that dir if it ends up empty, and rewrites `scripts/<grunt name>` refs in package scripts and `.rulesync/grunt.pipeline.jsonc`. Consumer scripts and `scripts/lib/env.mjs` stay where they are. No forwarding stubs
|
|
15
|
+
- Plan by default: a straight shot is one file, one obvious edit, and nothing to decide. Anything else gets research proportional to the work, plan-shaping questions the user alone can answer (with more research on each answer), then `/write-plan`, a stop for approval, revisions on feedback, and `/implement-plan`. A clear task gets one plan; an unclear one gets rounds
|
|
16
|
+
- The folder map lists `.rulesync/scripts`, and `grunt-job --job search` searches dot directories (`.gitignore` still applies)
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- `grunt:begin` / `grunt:end` blocks use blank lines around the body, the form prettier and other markdown formatters produce, and grunt reads either form. Formatters and `grunt:rulesync:generate` no longer rewrite each other's output, and `grunt:rulesync:check` stops reporting drift after a format
|
|
21
|
+
|
|
22
|
+
## [0.10.1] - 2026-10-11
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Session voice: an example, an open list, a negative example, `...`, `etc` / etcetera, or a semicolon between specimens is a class to carry out or avoid. Questions and work results open with the verdict and close on those same facts. Detail in `.rulesync/reference/output.md`
|
|
27
|
+
|
|
28
|
+
## [0.10.0] - 2026-10-09
|
|
29
|
+
|
|
10
30
|
### Added
|
|
11
31
|
|
|
12
32
|
- `scripts/jev.mjs`: one TypeSafe System One call for an external research decision, with a per-process and UTC-day cap. Key via `node scripts/setup.mjs jev` (`~/.grunt/jev.json`) or `TYPESAFE_API_KEY`. Doctor reports present or absent. `--available` prints `yes` or `no` and exits 0
|
|
@@ -14,6 +34,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
14
34
|
- Live agent board at `~/.grunt/board/`: one line per running agent (time, provider, model, effort, session, directory, work). A read drops a dead process. SessionStart `additionalContext` stays the folder map. UserPromptSubmit can append up to 8 other live lines.
|
|
15
35
|
- `google-workspace`, `listen`, `speak`, and `clasp` are opt-in. Init and upgrade ask with a multiselect that starts clear. `--packs` selects them without a TTY (`none` selects nothing). A repo with no `.rulesync/grunt.features.jsonc` drops those copies on the next init or upgrade. The npm package still ships them. Browser stays installed. Setup lists enabled packs and always lists browser and jev. Doctor always reports jev, and reports the other four only when that pack is enabled.
|
|
16
36
|
|
|
37
|
+
## [0.9.5] - 2026-10-05
|
|
38
|
+
|
|
17
39
|
### Fixed
|
|
18
40
|
|
|
19
41
|
- `grunt upgrade` keeps extra `##` sections in shared reference docs such as `law.md`, so consumer INDEX content survives the copy
|
package/CLAUDE.md
CHANGED
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ All OS. Print-only. Never auto-install.
|
|
|
43
43
|
|
|
44
44
|
```
|
|
45
45
|
grunt doctor
|
|
46
|
-
node scripts/doctor.mjs
|
|
46
|
+
node .rulesync/scripts/doctor.mjs
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
Exit 1 if any required missing; 0 if all required ok. Optional tools are reported; missing optional does not fail.
|
|
@@ -59,12 +59,12 @@ Exit 1 if any required missing; 0 if all required ok. Optional tools are reporte
|
|
|
59
59
|
| chromium-family | yes | linux `sudo apt install chromium` · mac `brew install --cask chromium` or `google-chrome` · win `winget install Google.Chrome` / `Microsoft.Edge` + PATH |
|
|
60
60
|
| gh | no | report only |
|
|
61
61
|
| clasp | no | `npm i -g @google/clasp` · custom Apps Script only |
|
|
62
|
-
| google-workspace | no | `node scripts/google-workspace.mjs` · Sheets Docs Slides Calendar Gmail · doctor reports `oauth`/`tokens`/`adc`/`clasprc` (no secrets) · `grunt setup` / `node scripts/setup.mjs google-workspace` |
|
|
63
|
-
| speak | no | `node scripts/speak.mjs` · TTS output (ElevenLabs or OpenAI) · `grunt setup` / `node scripts/setup.mjs speak` · or `ELEVENLABS_API_KEY` / `OPENAI_API_KEY` / `~/.grunt/speak.json` |
|
|
62
|
+
| google-workspace | no | `node .rulesync/scripts/google-workspace.mjs` · Sheets Docs Slides Calendar Gmail · doctor reports `oauth`/`tokens`/`adc`/`clasprc` (no secrets) · `grunt setup` / `node .rulesync/scripts/setup.mjs google-workspace` |
|
|
63
|
+
| speak | no | `node .rulesync/scripts/speak.mjs` · TTS output (ElevenLabs or OpenAI) · `grunt setup` / `node .rulesync/scripts/setup.mjs speak` · or `ELEVENLABS_API_KEY` / `OPENAI_API_KEY` / `~/.grunt/speak.json` |
|
|
64
64
|
| ffmpeg | no | mic capture for `/listen` · mac `brew install ffmpeg` · linux `sudo apt install ffmpeg` · win `winget install Gyan.FFmpeg` |
|
|
65
65
|
| whisper-cli | no | local STT for `/listen` · mac `brew install whisper-cpp` · first listen downloads `ggml-base.en.bin` · setup in `.rulesync/reference/listen.md` |
|
|
66
|
-
| listen | no | `node scripts/listen.mjs` · STT input · `grunt setup` / `node scripts/setup.mjs listen` · local whisper.cpp then OpenAI Whisper |
|
|
67
|
-
| jev | no | `node scripts/jev.mjs --state FILE --questions FILE` · one closed external research decision · `grunt setup` / `node scripts/setup.mjs jev` · `TYPESAFE_API_KEY` or `~/.grunt/jev.json` · local cap, one request per process |
|
|
66
|
+
| listen | no | `node .rulesync/scripts/listen.mjs` · STT input · `grunt setup` / `node .rulesync/scripts/setup.mjs listen` · local whisper.cpp then OpenAI Whisper |
|
|
67
|
+
| jev | no | `node .rulesync/scripts/jev.mjs --state FILE --questions FILE` · one closed external research decision · `grunt setup` / `node .rulesync/scripts/setup.mjs jev` · `TYPESAFE_API_KEY` or `~/.grunt/jev.json` · local cap, one request per process |
|
|
68
68
|
|
|
69
69
|
Rulesync schema doctor is separate: `grunt:rulesync:doctor` (or SoT `rulesync:doctor`).
|
|
70
70
|
|
|
@@ -83,10 +83,10 @@ Rulesync schema doctor is separate: `grunt:rulesync:doctor` (or SoT `rulesync:do
|
|
|
83
83
|
- `check` → run `grunt:rulesync:check`
|
|
84
84
|
- `sync-globals` → run `grunt:sync:globals` (dry-run); `--apply` → `grunt:sync:globals:apply`
|
|
85
85
|
- `purge-mcps` → run `grunt:purge:global-mcps` (dry-run); `--apply` → `grunt:purge:global-mcps:apply`
|
|
86
|
-
- `doctor` → run `grunt:doctor` (`grunt doctor` / `node scripts/doctor.mjs` stay). Rulesync schema: `grunt:rulesync:doctor`
|
|
87
|
-
- `setup` → run `grunt:setup` (`node scripts/setup.mjs`). The menu lists enabled packs and always lists browser and jev. Flags for non-TTY keys/`--creds`
|
|
86
|
+
- `doctor` → run `grunt:doctor` (`grunt doctor` / `node .rulesync/scripts/doctor.mjs` stay). Rulesync schema: `grunt:rulesync:doctor`
|
|
87
|
+
- `setup` → run `grunt:setup` (`node .rulesync/scripts/setup.mjs`). The menu lists enabled packs and always lists browser and jev. Flags for non-TTY keys/`--creds`
|
|
88
88
|
- `upgrade` → install the latest grunt as a devDependency and re-run with it, then the same merge as init for an already-inited repo: copy owned trees/scripts, prune retired grunt-owned names, print reserved skill names
|
|
89
|
-
- `map [dir]` → code-only folder map (
|
|
89
|
+
- `map [dir]` → code-only folder map (`.rulesync/scripts/folder-map.mjs`); no package manager needed. See [Folder map](#folder-map)
|
|
90
90
|
- `help`
|
|
91
91
|
- `version`
|
|
92
92
|
|
|
@@ -136,16 +136,16 @@ SoT: `.rulesync/subagents/{orchestrator grunt}.md`
|
|
|
136
136
|
|
|
137
137
|
Emit: `.claude/` `.grok/` `.agents/` `.gemini/`
|
|
138
138
|
|
|
139
|
-
- **orchestrator** — session agent. Tools on. Does the work. en-US unless asked. Concise complete sentences with natural grammar. Skip filler and fluff. Optimal solutions only; rewrite if not. Flag blockers. Do not monkey-patch. Runs `node scripts/grunt-job.mjs` for fat dumps; spawn grunt only when the dump needs judgment.
|
|
139
|
+
- **orchestrator** — session agent. Tools on. Does the work. en-US unless asked. Concise complete sentences with natural grammar. Skip filler and fluff. Optimal solutions only; rewrite if not. Flag blockers. Do not monkey-patch. Runs `node .rulesync/scripts/grunt-job.mjs` for fat dumps; spawn grunt only when the dump needs judgment.
|
|
140
140
|
- **grunt** — isolation worker. Facts only (≤8 lines, stash receipt when needed).
|
|
141
141
|
|
|
142
|
-
Fat dumps rewrite to
|
|
142
|
+
Fat dumps rewrite to `.rulesync/scripts/grunt-job.mjs` (squeez + stash). Scratch goes in `.tmp/grunt/`. Voice: `.rulesync/reference/output.md`. Examples are a class. Questions and work results open with the verdict and close on those same facts. `GEMINI.md` → `@AGENTS.md`.
|
|
143
143
|
|
|
144
144
|
## Browser
|
|
145
145
|
|
|
146
|
-
Lightpanda-first session CLI: `node scripts/browser.mjs`. Zero MCP. Zero env knobs. The rail swaps to Chromium for `shot`/`pdf`/`trace`, Windows, missing Lightpanda, probe-fail, Chromium-first hosts (figma, Google docs/sheets/slides, Gmail, earth, Amazon), or a blocked/empty/client-rendered snap. Session: `.tmp/grunt/browser/`. Spec: [`.rulesync/reference/browser.md`](.rulesync/reference/browser.md). App e2e uses Playwright. URL-in-a-cite is a cite.
|
|
146
|
+
Lightpanda-first session CLI: `node .rulesync/scripts/browser.mjs`. Zero MCP. Zero env knobs. The rail swaps to Chromium for `shot`/`pdf`/`trace`, Windows, missing Lightpanda, probe-fail, Chromium-first hosts (figma, Google docs/sheets/slides, Gmail, earth, Amazon), or a blocked/empty/client-rendered snap. Session: `.tmp/grunt/browser/`. Spec: [`.rulesync/reference/browser.md`](.rulesync/reference/browser.md). App e2e uses Playwright. URL-in-a-cite is a cite.
|
|
147
147
|
|
|
148
|
-
`node scripts/browser.mjs doctor` (alias `ensure`) runs the unified doctor (
|
|
148
|
+
`node .rulesync/scripts/browser.mjs doctor` (alias `ensure`) runs the unified doctor (`.rulesync/scripts/doctor.mjs`). Install engines: [Prerequisites](#prerequisites).
|
|
149
149
|
|
|
150
150
|
## Skills
|
|
151
151
|
|
|
@@ -159,7 +159,7 @@ Present under `.claude` / `.rulesync` / `.agents` / `.grok` (`rulesync -f skills
|
|
|
159
159
|
|
|
160
160
|
Reserved names: do not reuse those stems for consumer custom skills. Same name → one SSOT under `.rulesync/skills/<name>/`; re-init force-refresh overwrites grunt-owned names; extras kept; maps `origin` badge ≠ content picker. Retired 0.5 names (`parent` `solo` `cascade` plus subagents `implementer` `thinker`) are pruned on init/upgrade. See `.rulesync/reference/law.md` (flows into INDEX).
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
Plan first: `.rulesync/reference/scope.md`. Straight shot (one file, one obvious edit, nothing to decide) → do it. Else research → `/write-plan` → approval → `/implement-plan`.
|
|
163
163
|
|
|
164
164
|
`/write-plan` and `/implement-plan` SSOT: `.rulesync/skills/{write-plan,implement-plan}/`; format SSOT `.rulesync/reference/plan-format.md`. `/write-plan` plan-only inspect-pause → `next: /implement-plan {n}`; empty `/implement-plan` resumes unique in-progress or starts unique ready, else lists (need serial); slash `/implement-plan {n}` disk/file. The session agent executes the plan. `/implement-plan` also writes `.tmp/grunt/implementations/` (format `.rulesync/reference/implementation-format.md`): Files / Log / Done for commits. Straight shots skip the journal.
|
|
165
165
|
|
|
@@ -187,7 +187,7 @@ Emit writes other-CLI trees from `.rulesync` for the **next** process of that CL
|
|
|
187
187
|
|
|
188
188
|
### Folder map
|
|
189
189
|
|
|
190
|
-
Claude and Codex get a folder map at SessionStart (
|
|
190
|
+
Claude and Codex get a folder map at SessionStart (`.rulesync/scripts/session-map.mjs`), so agents skip `ls`/`find` loops. Agents run `node .rulesync/scripts/folder-map.mjs <dir>` (same as `grunt map <dir>`) for depth. Grok and Antigravity get the `AGENTS.md` line only. The injected map stays under Claude Code's 10,000-character per-hook `additionalContext` limit (about 2.4k tokens); past it, Claude keeps only a 2KB preview inline. `grunt map` itself uses the full `budget`. SessionStart `additionalContext` stays that map.
|
|
191
191
|
|
|
192
192
|
- Folders only, never files. Source: `git ls-files --cached --others --exclude-standard`, so gitignored paths never show
|
|
193
193
|
- A folder shows when it or a descendant holds a code file (`codeExt`) and no path segment is a dot dir or in `skip`
|
|
@@ -212,13 +212,13 @@ Optional `.rulesync/grunt.map.jsonc` (missing or invalid → defaults):
|
|
|
212
212
|
|
|
213
213
|
One live line per running agent, stored in `~/.grunt/board/` (one file per session, this machine). The line is time, provider, model, effort, session id, directory, and current work. A missing model or effort is `-`. A read deletes a line whose process is gone, so quit, crash, and OOM drop off at the next read.
|
|
214
214
|
|
|
215
|
-
Claude and Codex write the row at SessionStart. `additionalContext` stays the folder map. Every UserPromptSubmit refreshes the row and may append up to 8 other live lines. Grok writes on the prompt. Antigravity runs `node scripts/board.mjs set --work` when the work changes and `node scripts/board.mjs` to read.
|
|
215
|
+
Claude and Codex write the row at SessionStart. `additionalContext` stays the folder map. Every UserPromptSubmit refreshes the row and may append up to 8 other live lines. Grok writes on the prompt. Antigravity runs `node .rulesync/scripts/board.mjs set --work` when the work changes and `node .rulesync/scripts/board.mjs` to read.
|
|
216
216
|
|
|
217
217
|
### Secrets (machine)
|
|
218
218
|
|
|
219
219
|
Not git. Not `sync-globals`.
|
|
220
220
|
|
|
221
|
-
First-hand: `grunt setup` (TTY). The menu lists enabled packs and always lists browser and jev. Per target: `node scripts/setup.mjs speak|listen|google-workspace|browser`. Spec: `.rulesync/reference/setup.md`.
|
|
221
|
+
First-hand: `grunt setup` (TTY). The menu lists enabled packs and always lists browser and jev. Per target: `node .rulesync/scripts/setup.mjs speak|listen|google-workspace|browser`. Spec: `.rulesync/reference/setup.md`.
|
|
222
222
|
|
|
223
223
|
| | where |
|
|
224
224
|
| --- | --- |
|
|
@@ -313,14 +313,14 @@ Same topology as the session recap; every legal edge labeled.
|
|
|
313
313
|
|
|
314
314
|
### `need:` / grunt-job
|
|
315
315
|
|
|
316
|
-
The session agent runs `node scripts/grunt-job.mjs --job search|exec|slice|fetch|test` for fat dumps. A grunt child that still needs a fat dump **stops** on a `need:` JSON line. SubagentStop intercepts `search|exec|slice|fetch` (cap 4) in-hook. Spawn a grunt **model** only when the dump needs judgment. Grunt does not emit `need:` for its own tool use.
|
|
316
|
+
The session agent runs `node .rulesync/scripts/grunt-job.mjs --job search|exec|slice|fetch|test` for fat dumps. A grunt child that still needs a fat dump **stops** on a `need:` JSON line. SubagentStop intercepts `search|exec|slice|fetch` (cap 4) in-hook. Spawn a grunt **model** only when the dump needs judgment. Grunt does not emit `need:` for its own tool use.
|
|
317
317
|
|
|
318
318
|
```
|
|
319
319
|
session agent
|
|
320
320
|
│
|
|
321
321
|
│ grunt-job first
|
|
322
322
|
▼
|
|
323
|
-
node scripts/grunt-job.mjs --job search|exec|slice|fetch|test
|
|
323
|
+
node .rulesync/scripts/grunt-job.mjs --job search|exec|slice|fetch|test
|
|
324
324
|
│
|
|
325
325
|
│ spawn grunt model only if the dump needs judgment
|
|
326
326
|
▼
|
|
@@ -343,7 +343,7 @@ The session agent runs `node scripts/grunt-job.mjs --job search|exec|slice|fetch
|
|
|
343
343
|
| `scrub-spawn-prompt` / `parse-need` / `grunt-job` | yes | **local** | Hooks and scripts. Isolation facts are grunt-job output, not a model hop. |
|
|
344
344
|
| emit / generate / init | yes (this repo / install) | **local** | Writes other-CLI configs. Not a runtime line to those CLIs. |
|
|
345
345
|
| WebSearch / web_fetch | tool from host | **remote-not-LLM** | Network search/fetch. Not a second Model API box. Snippet/cite/"what is X"/world fact: grunt `job: web`. Live URL/DOM: grunt browser rail, not this box. |
|
|
346
|
-
| `jev` | yes | **remote-not-LLM** | `node scripts/jev.mjs --state FILE --questions FILE`. One System One decision about external source text. Not the host Model API. Not grunt-job. |
|
|
346
|
+
| `jev` | yes | **remote-not-LLM** | `node .rulesync/scripts/jev.mjs --state FILE --questions FILE`. One System One decision about external source text. Not the host Model API. Not grunt-job. |
|
|
347
347
|
| MCP | policy deny | n/a | Denied by policy in-tree. Do not draw as a main path. |
|
|
348
348
|
| Model API | **no** (one box outside) | AI-server | This host’s vendor SDK only. Parent and child **turns** complete here. Spawn omits model; frontmatter on `.rulesync/subagents/*.md` picks the model. |
|
|
349
349
|
| Other CLIs | no (not this process) | emit/config only | Same protocol files emitted elsewhere. No hop, no shared peek. |
|
|
@@ -396,9 +396,9 @@ Repo-relative (repository root):
|
|
|
396
396
|
|
|
397
397
|
## Layout
|
|
398
398
|
|
|
399
|
-
Published (`package.json` `files`): `bin/grunt.js` `cli`
|
|
399
|
+
Published (`package.json` `files`): `bin/grunt.js` `cli` `.rulesync/scripts/check-globals.mjs` `.rulesync/scripts/emit-agent-shell-tools.mjs` `.rulesync/scripts/emit-gemini.mjs` `.rulesync/scripts/emit-maps.mjs` `.rulesync/scripts/guarded-md.mjs` `.rulesync/scripts/guarded-roots.mjs` `.rulesync/scripts/emit-mcp-policy.mjs` `.rulesync/scripts/gate-fat-tools.mjs` `.rulesync/scripts/hooks-union.mjs` `.rulesync/scripts/pipeline.mjs` `.rulesync/scripts/grunt-job.mjs` `.rulesync/scripts/parse-need.mjs` `.rulesync/scripts/persist-handoff.mjs` `.rulesync/scripts/persist-implementation.mjs` `.rulesync/scripts/persist-tmp.mjs` `.rulesync/scripts/persist-plan.mjs` `.rulesync/scripts/purge-global-mcps.mjs` `.rulesync/scripts/scrub-spawn-prompt.mjs` `.rulesync/scripts/scrub-text-lib.mjs` `.rulesync/scripts/sync-global-settings.mjs` `.rulesync/scripts/board.mjs` `.rulesync/scripts/browser.mjs` `.rulesync/scripts/feature-packs.mjs` `.rulesync/scripts/speak.mjs` `.rulesync/scripts/listen.mjs` `.rulesync/scripts/jev.mjs` `.rulesync/scripts/google-workspace.mjs` `.rulesync/scripts/interactive.mjs` `.rulesync/scripts/prompt.mjs` `.rulesync/scripts/setup.mjs` `.rulesync/scripts/doctor.mjs` `.rulesync/scripts/skill-conflicts.mjs` `.rulesync/scripts/scrub-text` `.rulesync` `.grok` `.codex` `.claude` `.agents` `AGENTS.md` `CLAUDE.md` `.mcp.json` `README.md` `LICENSE` `CHANGELOG.md`
|
|
400
400
|
|
|
401
|
-
No
|
|
401
|
+
No `.rulesync/scripts/*.test.ts` `.rulesync/scripts/fixtures/` `docs/` `coverage/` `vitest.config.ts` in `files`. `cli` dir ships whole (includes `cli/*.test.ts`).
|
|
402
402
|
|
|
403
403
|
Not packed: `GEMINI.md` `.gemini/` — `emit-gemini.mjs` writes them on `generate` / `init` (`GEMINI.md` → `@AGENTS.md`). Not in `files`.
|
|
404
404
|
|
|
@@ -406,7 +406,7 @@ Repo root (also): `coverage/` `.gemini/` `GEMINI.md` — no `src/` no `CONTRIBUT
|
|
|
406
406
|
|
|
407
407
|
- `bin/grunt.js` — CLI bin
|
|
408
408
|
- `cli/grunt.mjs` — commands
|
|
409
|
-
-
|
|
409
|
+
- `.rulesync/scripts/` — init copies product scripts (`grunt-job.mjs` `scrub-text` …). Re-init sentinels: `.grok/hooks/orchestrate-parent.js` `.rulesync` `<!-- grunt:begin -->`
|
|
410
410
|
- `.rulesync/` — SoT (subagents skills reference). Skills + reference maps on generate; host trees are mirrors
|
|
411
411
|
- `.claude/` `.grok/` `.codex/` `.agents/` `.gemini/` — host emit; not SoT; no mirror scan
|
|
412
412
|
- `coverage/` — vitest local not published
|
|
@@ -420,7 +420,7 @@ npm i && npm test
|
|
|
420
420
|
```
|
|
421
421
|
|
|
422
422
|
- Test: `vitest run --coverage`
|
|
423
|
-
- Test include:
|
|
423
|
+
- Test include: `.rulesync/scripts/**/*.test.ts` `cli/**/*.test.ts`
|
|
424
424
|
- Coverage include: `cli/**`
|
|
425
425
|
- Coverage thresholds: 100% lines / functions / branches / statements
|
|
426
426
|
- Dev deps include rulesync vitest typescript
|
package/cli/grunt.mjs
CHANGED
|
@@ -12,9 +12,9 @@ import {
|
|
|
12
12
|
detectPackageManager,
|
|
13
13
|
isPackageManager,
|
|
14
14
|
runScriptArgs,
|
|
15
|
-
} from "
|
|
16
|
-
import { mapCommand } from "
|
|
17
|
-
import { PACK_OPTIONS, parsePacksFlag, selectedPacks } from "
|
|
15
|
+
} from "../.rulesync/scripts/package-manager.mjs"
|
|
16
|
+
import { mapCommand } from "../.rulesync/scripts/folder-map.mjs"
|
|
17
|
+
import { PACK_OPTIONS, parsePacksFlag, selectedPacks } from "../.rulesync/scripts/feature-packs.mjs"
|
|
18
18
|
|
|
19
19
|
const PKG_ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), "..")
|
|
20
20
|
|
package/cli/grunt.test.ts
CHANGED
|
@@ -34,9 +34,9 @@ vi.mock("./init.mjs", () => ({
|
|
|
34
34
|
}));
|
|
35
35
|
vi.mock("./spawn.mjs", () => ({ execFileSync }));
|
|
36
36
|
vi.mock("./self-update.mjs", () => ({ selfUpdate }));
|
|
37
|
-
vi.mock("
|
|
38
|
-
vi.mock("
|
|
39
|
-
const actual = await importOriginal<typeof import("
|
|
37
|
+
vi.mock("../.rulesync/scripts/folder-map.mjs", () => ({ mapCommand }));
|
|
38
|
+
vi.mock("../.rulesync/scripts/package-manager.mjs", async (importOriginal) => {
|
|
39
|
+
const actual = await importOriginal<typeof import("../.rulesync/scripts/package-manager.mjs")>();
|
|
40
40
|
actualDetect.fn = actual.detectPackageManager;
|
|
41
41
|
detectPackageManager.mockImplementation((...args: unknown[]) =>
|
|
42
42
|
actual.detectPackageManager(
|
|
@@ -53,15 +53,15 @@ vi.mock("./prompt.mjs", () => ({
|
|
|
53
53
|
spinner,
|
|
54
54
|
bailIfCancel,
|
|
55
55
|
}));
|
|
56
|
-
vi.mock("
|
|
57
|
-
const actual = await importOriginal<typeof import("
|
|
56
|
+
vi.mock("../.rulesync/scripts/feature-packs.mjs", async (importOriginal) => {
|
|
57
|
+
const actual = await importOriginal<typeof import("../.rulesync/scripts/feature-packs.mjs")>();
|
|
58
58
|
return { ...actual, selectedPacks };
|
|
59
59
|
});
|
|
60
60
|
|
|
61
61
|
import {
|
|
62
62
|
PACKAGE_MANAGER_ASK,
|
|
63
63
|
UNKNOWN_PACKAGE_MANAGER,
|
|
64
|
-
} from "
|
|
64
|
+
} from "../.rulesync/scripts/package-manager.mjs";
|
|
65
65
|
import { APPLY_GLOBALS_CONFIRM, parseArgv, start } from "./grunt.mjs";
|
|
66
66
|
|
|
67
67
|
const USAGE = `Usage: grunt [command]
|