@lovrozagar/grunt 0.3.10 → 0.4.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.
Files changed (50) hide show
  1. package/.agents/agents/grunt.md +1 -0
  2. package/.agents/agents/implementer.md +3 -2
  3. package/.agents/agents/orchestrator.md +4 -3
  4. package/.agents/skills/browser/SKILL.md +17 -0
  5. package/.agents/skills/handoff/SKILL.md +2 -2
  6. package/.agents/skills/pickup/SKILL.md +64 -0
  7. package/.agents/skills/solo/SKILL.md +1 -1
  8. package/.claude/agents/grunt.md +1 -0
  9. package/.claude/agents/implementer.md +3 -2
  10. package/.claude/agents/orchestrator.md +4 -3
  11. package/.claude/skills/browser/SKILL.md +17 -0
  12. package/.claude/skills/handoff/SKILL.md +2 -2
  13. package/.claude/skills/pickup/SKILL.md +64 -0
  14. package/.claude/skills/solo/SKILL.md +1 -1
  15. package/.codex/agents/grunt.toml +1 -0
  16. package/.codex/agents/implementer.toml +3 -2
  17. package/.codex/agents/orchestrator.toml +4 -3
  18. package/.grok/agents/grunt.md +1 -0
  19. package/.grok/agents/implementer.md +3 -2
  20. package/.grok/agents/orchestrator.md +4 -3
  21. package/.grok/hooks/orchestrate-parent.js +4 -3
  22. package/.grok/skills/browser/SKILL.md +17 -0
  23. package/.grok/skills/handoff/SKILL.md +2 -2
  24. package/.grok/skills/pickup/SKILL.md +64 -0
  25. package/.grok/skills/solo/SKILL.md +1 -1
  26. package/.rulesync/reference/browser.md +59 -0
  27. package/.rulesync/reference/cascade.md +2 -1
  28. package/.rulesync/reference/hooks.md +1 -1
  29. package/.rulesync/reference/map.md +6 -3
  30. package/.rulesync/reference/rtk.md +4 -1
  31. package/.rulesync/rules/CLAUDE.md +3 -2
  32. package/.rulesync/rules/overview.md +3 -2
  33. package/.rulesync/skills/browser/SKILL.md +19 -0
  34. package/.rulesync/skills/handoff/SKILL.md +2 -2
  35. package/.rulesync/skills/pickup/SKILL.md +64 -0
  36. package/.rulesync/skills/solo/SKILL.md +1 -1
  37. package/.rulesync/subagents/grunt.md +1 -0
  38. package/.rulesync/subagents/implementer.md +3 -2
  39. package/.rulesync/subagents/orchestrator.md +4 -3
  40. package/AGENTS.md +3 -2
  41. package/CLAUDE.md +3 -2
  42. package/README.md +35 -5
  43. package/cli/grunt.mjs +2 -2
  44. package/cli/grunt.test.ts +3 -3
  45. package/cli/init.mjs +2 -0
  46. package/cli/init.test.ts +2 -0
  47. package/package.json +5 -2
  48. package/scripts/browser.mjs +764 -0
  49. package/scripts/doctor.mjs +252 -0
  50. package/scripts/gate-fat-tools.mjs +19 -4
@@ -0,0 +1,59 @@
1
+ ---
2
+ tags: [browser]
3
+ ---
4
+
5
+ # Browser
6
+
7
+ Zero-config in-tree session rail. Not MCP. Not env. Not raw Playwright.
8
+
9
+ ```
10
+ node scripts/browser.mjs nav|snap|click|fill|shot|pdf|stop|doctor|ensure
11
+ ```
12
+
13
+ Default engine: **Lightpanda** (`lightpanda` on PATH). Chromium only when a rule below requires it.
14
+
15
+ ## Verbs
16
+
17
+ | verb | purpose |
18
+ | --- | --- |
19
+ | `nav <url>` | launch or reuse session; go to URL |
20
+ | `snap` | markdown + numbered AX refs (default read) |
21
+ | `click <ref>` | click a ref from last `snap` |
22
+ | `fill <ref> <text>` | fill a ref from last `snap` |
23
+ | `shot` | screenshot (Chromium paint) |
24
+ | `pdf` | PDF (Chromium paint) |
25
+ | `stop` | reap engine pid; clear session; idempotent |
26
+ | `doctor` | unified prereq doctor (`scripts/doctor.mjs`); alias `ensure` |
27
+ | `ensure` | alias of `doctor` |
28
+
29
+ Session + profile + artifacts: `.tmp/grunt/browser/` only.
30
+
31
+ ## Install
32
+
33
+ Run `grunt doctor` / `node scripts/doctor.mjs`. See README Prerequisites.
34
+
35
+ ## Engine
36
+
37
+ Lightpanda first (`lightpanda serve` internally, CDP, `LP.getMarkdown` + AX refs).
38
+
39
+ Chromium immediately when any of:
40
+
41
+ - verb is `shot` | `pdf` | `trace`
42
+ - `process.platform === "win32"`
43
+ - paint-host URL (tiny set): figma, Google docs / sheets / slides, mail.google, earth
44
+ - `lightpanda` missing from PATH and a Chromium binary is present
45
+ - Lightpanda probe fails **once** → one Chromium replay of last URL; no loop
46
+
47
+ No user env. Never `GRUNT_BROWSER*`. Never `LIGHTPANDA_CDP_URL`.
48
+
49
+ ## Non-goals
50
+
51
+ - MCP browser servers
52
+ - user env knobs
53
+ - raw Playwright as the agent tool
54
+ - grunt `job:browse`
55
+ - teaching thinker / orchestrator to browse
56
+
57
+ ## RTK
58
+
59
+ `playwright` on the RTK command list is the **test-runner family only**. Browser rail is `lightpanda` + `scripts/browser.mjs`.
@@ -13,7 +13,7 @@ Always-do lives in orchestrator/overview (do not open this file first). Peek/kil
13
13
  Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
14
14
 
15
15
  Always spawn + prompt. First token = spawn. Parent Read/Bash deny expected if forgotten. Only `/solo` (session stamp) escapes spawn workflow. `/parent` is last-ditch hook stamp not skill-instructed Read/Bash. No try-then-spawn. No parent probe. No tiny-read/grep/list_dir/bash/grunt-job for the user. No skip-spawn.
16
- Create/change product files → first token spawn implementer (thinker then implementer if no spec). Never parent Write/Edit/Bash/Skill-that-writes. Child returned is not terminal if writes remain or spawn count is 0 on a file-change turn. plan/spec ready + writes remain → persist plan if needed; spawn implementer; do not recap-stop. plan-only `/write-plan` → recap + `next: /implement-plan`.
16
+ Create/change product files → first token spawn implementer if small/simple or prompt-is-spec. Large/complex + no spec → thinker then implementer. Never parent Write/Edit/Bash/Skill-that-writes. Child returned is not terminal if writes remain or spawn count is 0 on a file-change turn. plan/spec ready + writes remain → persist plan if needed; spawn implementer; do not recap-stop. plan-only `/write-plan` → recap + `next: /implement-plan`.
17
17
 
18
18
  1. Tools (facts / search / exec / git / web / test / low-reason mechanical write) → grunt. Facts/search → grunt, never thinker.
19
19
  2. Write defined solution → implementer.
@@ -37,6 +37,7 @@ Then print recap as `[orchestrator]: …` (or the child role tag) with real chil
37
37
 
38
38
  Parent Stop (`MAX_STOP=3`): do not waive fenced/impl finals for `tools-used` stamp. Parent `end_turn` is tagged+one-line or `[orchestrator]: wait grunt`. First non-empty line must match legal `[orchestrator|grunt|implementer|thinker|handoff]:`. Siblings still run → role tag + one-line echo. In-flight wait recap is `[orchestrator]: wait grunt` only. Or consume `parent-escape-{sid}` once. Else block. No `isCheap` / trivia / long definitions.
39
39
  `/handoff` is the other in-parent turn: context large + work unfinished → parent writes one `.tmp/grunt/handoffs/` file from its own transcript (no child sees the session), recaps `[handoff]: serial=… path=…`, tells the user to continue in a new session. No spawn, one write, not a mode.
40
+ `/pickup` is spawn-first pickup, not in-parent write; parent never Read. Inverse of `/handoff`.
40
41
  `/solo` is the session mode (not one-turn): `beforeSubmitPrompt` writes `.tmp/orchestrator-logs/grunt-off-{sid}`, every gate short-circuits while it exists, `/cascade` unlinks it. Everything above resumes next turn. Antigravity: skill-only, no stamp create (see hooks.md). `/parent` is last-ditch hook stamp (not a mode, not skill-instructed Read/Bash): UserPromptSubmit writes `.tmp/orchestrator-logs/parent-escape-{sid}`; Stop consumes+unlinks once. Next Stop resumes spawn/recap rules. `/explain` is human recap after children; never parent Read; not a mode; not spawn-escape. Skills point here; do not paste this file. Never parent-Read protocol files.
41
42
 
42
43
  Host mapping (in-tree only; do not invent peek/kill APIs). GAP rows: no fake peeks, no auto-kill.
@@ -10,7 +10,7 @@ Grok PostToolUse / UserPromptSubmit / SessionStart are observe-only — do not a
10
10
 
11
11
  Claude / Codex / Antigravity PreToolUse still run `scripts/scrub-spawn-prompt.mjs` and `scripts/gate-fat-tools.mjs`. Grok does not — spawn/fat rewrite is `orchestrate-parent.js` only. RTK stays `rtk.json`.
12
12
 
13
- Parent Read|Write|Edit|Bash|Skill deny unless `/solo` (session) or `/parent` last-ditch stamp. Grok PreToolUse has no matcher (Read included). Skills spawn-first; do not instruct parent Read/Bash. `.tmp/plans/` and `.tmp/grunt/handoffs/` Write still persist. Parent Bash still allowed for workspace `grunt-job.mjs` `--job search|exec`. Children with a type skip parent-deny (fat-only). Skill allowlist without escape: `parent|explain|solo|cascade|handoff|write-plan|implement-plan`. Deny reason: `First action=spawn implementer|grunt|thinker. Deny expected. Only /solo this session escapes.`. Parent `end_turn` is tagged+one-line or `[orchestrator]: wait grunt`.
13
+ Parent Read|Write|Edit|Bash|Skill deny unless `/solo` (session) or `/parent` last-ditch stamp. Grok PreToolUse has no matcher (Read included). Skills spawn-first; do not instruct parent Read/Bash. `.tmp/plans/` and `.tmp/grunt/handoffs/` Write still persist. Parent Bash still allowed for workspace `grunt-job.mjs` `--job search|exec`. Children with a type skip parent-deny (fat-only). Skill allowlist without escape: `parent|explain|solo|cascade|handoff|pickup|write-plan|implement-plan`. Deny reason: `First action=spawn implementer|grunt|thinker. Deny expected. Only /solo this session escapes.`. Parent `end_turn` is tagged+one-line or `[orchestrator]: wait grunt`.
14
14
 
15
15
  Parent `run_terminal_command` is deny-by-default except `node` (optional leading `rtk`) invoking `{workspace}/scripts/grunt-job.mjs` with `--job search|exec` and `--query`. Optional `--path` `--glob` (repeatable) `--cwd`. Not `web|test`, not other scripts. META strips `--query` value first so `|` inside query is allowed; pipes/`&&` outside query still deny. Never `cd &&`. Exec shell-meta in query is grunt-job FALLBACK (exit 2), not a parent-bash allow. Unknown flags → FALLBACK.
16
16
 
@@ -9,6 +9,7 @@ Cheap outline. Not a file dump.
9
9
  ## Protocol
10
10
  - `.rulesync/reference/cascade.md` — spawn / need / resume
11
11
  - `.rulesync/reference/rtk.md` — shell compression
12
+ - `.rulesync/reference/browser.md` — Lightpanda-first session CLI (`nav|snap|click|fill|shot|pdf|stop`); not MCP
12
13
  - `.rulesync/reference/hooks.md` — hook policy
13
14
  - `.rulesync/reference/map.md` — this file
14
15
  - `.rulesync/reference/output.md` — default voice
@@ -23,13 +24,13 @@ Cheap outline. Not a file dump.
23
24
  - `.grok/hooks/orchestrate-parent.js` + `orchestrate-parent.json` — parent spawn/fat/stop/plan-write / SubagentStop intercept
24
25
  - `.grok/hooks/rtk.json` — RTK
25
26
  - `.grok/skills/{write-plan,implement-plan,shared}/` — hand-only (no rulesync SSOT); point to cascade, do not paste
26
- - `.grok/skills/{parent,explain,handoff,solo,cascade,commit,commit-and-push,commit-push,commit-push-deploy,commit-push-release}/` — generated from `.rulesync/skills/`; do not hand-edit
27
+ - `.grok/skills/{parent,explain,handoff,pickup,solo,cascade,commit,commit-and-push,commit-push,commit-push-deploy,commit-push-release}/` — generated from `.rulesync/skills/`; do not hand-edit
27
28
  - `.grok/parent.md` — 1-line pointer to orchestrator agent; not SessionStart
28
29
  - `.grok/roles/*.toml`
29
30
  - `.grok/global-settings.toml` — merged into `~/.grok/config.toml` by `scripts/sync-global-settings.mjs` (not auto-loaded; project config cannot set `[features]`)
30
31
  - `.rulesync/global-settings/` — host manifest and reserved noop payloads
31
32
  - `.rulesync/mcp-policy.jsonc` — MCP deny-default SSOT (`default: deny`, `allow: []`)
32
- - `.rulesync/skills/{parent,explain,handoff,solo,cascade,commit,commit-and-push,commit-push,commit-push-deploy,commit-push-release}/` — skill SSOT; `rulesync -f skills` emits `.grok/skills/`, `.claude/skills/`, `.agents/skills/` byte-equal. `/cascade` = exit solo / restore cascade (not a sticky second mode)
33
+ - `.rulesync/skills/{parent,explain,handoff,pickup,solo,cascade,commit,commit-and-push,commit-push,commit-push-deploy,commit-push-release,browser}/` — skill SSOT; `rulesync -f skills` emits `.grok/skills/`, `.claude/skills/`, `.agents/skills/` byte-equal. `/cascade` = exit solo / restore cascade (not a sticky second mode)
33
34
 
34
35
  ## Scripts
35
36
  - `scripts/check-globals.mjs` — `$HOME/.grok/config.toml` `[agent].name==orchestrator` + `[features].two_pass_compaction==true`; project `.grok/config.toml` must not have `[features]`/`[agent]`; wired as `sync:globals:check` (also after emit-mcp in `rulesync:check`)
@@ -45,11 +46,13 @@ Cheap outline. Not a file dump.
45
46
  - `scripts/emit-gemini.mjs` — `GEMINI.md` (`@AGENTS.md`) + `.gemini/agents/{id}/agent.md` from `.rulesync/subagents` (not `rulesync -t geminicli`); no prune; does not touch settings
46
47
  - `scripts/emit-agent-shell-tools.mjs` — after rulesync subagents: rewrite `.claude/agents/grunt.md` body `Bash`; grok/codex/gemini/generic keep `run_terminal_command`
47
48
  - `scripts/telemetry.mjs` — append-only `.tmp/orchestrator-logs/telemetry.ndjson` from hooks / grunt-job CLI; fail-open; never stdout
49
+ - `scripts/browser.mjs` — session browser rail `nav|snap|click|fill|shot|pdf|stop`; Lightpanda default; Chromium on verb/OS/probe/paint-host/one-escalate; `.tmp/grunt/browser/`
48
50
 
49
51
  ## Tmp
50
52
  - `.tmp/plans/` — persist-plan / parent / implementer
51
53
  - `.tmp/orchestrator-logs/` — hooks + grunt-job telemetry (shared; not grunt scratch)
52
54
  - `.tmp/grunt/` — grunt scratch/tmp only
55
+ - `.tmp/grunt/browser/` — browser session/profile/shot/pdf (not MCP)
53
56
  - `.tmp/grunt/handoffs/` — persist-handoff / `/handoff`; own serial counter (not plan serials)
54
57
 
55
58
  ## Stamps (`.tmp/orchestrator-logs/`)
@@ -58,7 +61,7 @@ Cheap outline. Not a file dump.
58
61
 
59
62
  ## Generated (do not hand-edit; committed, not gitignored)
60
63
  - `AGENTS.md`, `CLAUDE.md`
61
- - `.claude/skills/*`, `.agents/skills/*`, `.grok/skills/{parent,explain,handoff,solo,cascade,commit,commit-and-push,commit-push,commit-push-deploy,commit-push-release}/` (from `.rulesync/skills/`)
64
+ - `.claude/skills/*`, `.agents/skills/*`, `.grok/skills/{parent,explain,handoff,pickup,solo,cascade,commit,commit-and-push,commit-push,commit-push-deploy,commit-push-release}/` (from `.rulesync/skills/`)
62
65
  - `.grok/agents/*`
63
66
  - `.claude/agents/*`
64
67
  - `.codex/agents/*`
@@ -10,7 +10,7 @@ Grok PostToolUse is observe-only — do not attempt output scrub; compress via R
10
10
 
11
11
  ## Commands
12
12
 
13
- ls · tree · read · smart · git · gh · glab · aws · psql · pnpm · err · test · json · deps · env · find · diff · log · dotnet · docker · kubectl · oc · summary · grep · rg · init · wget · wc · gain · cc-economics · config · jest · vitest · prisma · tsc · next · lint · prettier · format · playwright · cargo · npm · npx · curl · discover · session · telemetry · learn · run · proxy · pipe · trust · untrust · verify · ruff · pytest · mypy · rake · rubocop · rspec · pip · go · gt · golangci-lint · gradlew · mvn · hook-audit · rewrite · hook · help
13
+ ls · tree · read · smart · git · gh · glab · aws · psql · pnpm · err · test · json · deps · env · find · diff · log · dotnet · docker · kubectl · oc · summary · grep · rg · init · wget · wc · gain · cc-economics · config · jest · vitest · prisma · tsc · next · lint · prettier · format · playwright · lightpanda · cargo · npm · npx · curl · discover · session · telemetry · learn · run · proxy · pipe · trust · untrust · verify · ruff · pytest · mypy · rake · rubocop · rspec · pip · go · gt · golangci-lint · gradlew · mvn · hook-audit · rewrite · hook · help
14
14
 
15
15
  **git:** diff · log · status · show · add · commit · push · pull · branch · fetch · stash (list show pop apply drop push) · worktree
16
16
  **cargo:** build · test · clippy · check · install · nextest
@@ -21,3 +21,6 @@ ls · tree · read · smart · git · gh · glab · aws · psql · pnpm · err
21
21
  Flags: `-v`/`-vv`/`-vvv` · `--ultra-compact` · `--skip-env` · `-h` · `-V`
22
22
 
23
23
  Unknown cmds passthrough. `rtk run` unfiltered.
24
+
25
+ **playwright:** test-runner family only — not the browser rail.
26
+ **lightpanda:** browser-rail CDP via `scripts/browser.mjs` (not MCP, not env).
@@ -11,7 +11,7 @@ Always-do:
11
11
 
12
12
  | signal | next |
13
13
  |---|---|
14
- | create/change product files | spawn implementer (thinker then implementer if no spec). Never parent Write/Bash/Skill |
14
+ | create/change product files | small/simple or prompt-is-spec → implementer; large/complex + no spec → thinker then implementer. Never parent Write/Bash/Skill |
15
15
  | plan/spec ready + file writes remain | persist plan if needed; spawn implementer; do not recap-stop |
16
16
  | tools/facts/git/test/mechanical write | spawn grunt |
17
17
  | world fact | spawn grunt `job:web` |
@@ -24,6 +24,7 @@ Always-do:
24
24
  | children done + no findings | recap; stop allowed only if no writes remain and spawn count > 0 when the user asked for a file change |
25
25
  | `/parent` | spawn-first; hook last-ditch `parent-escape`; never Read/Bash |
26
26
  | `/handoff` | one-turn write `.tmp/grunt/handoffs/`; recap `[handoff]:` |
27
+ | `/pickup` | spawn-first; grunt resolve if needed; never parent Read; not a mode |
27
28
  | `/write-plan` plan-only | recap + `next: /implement-plan` |
28
29
  | `/explain` | spawn if facts/work; then human recap of child output; screenshot/visible=context no Read |
29
30
  | `/solo` | session escape only; stamp grunt-off-{sid}; else spawn-first |
@@ -31,7 +32,7 @@ Always-do:
31
32
 
32
33
  Parent = this file not `.claude/agents/orchestrator.md`. You do not talk. Spawn wait echo.
33
34
  Spawn only grunt|implementer|thinker. Never spawn orchestrator. Children never spawn.
34
- You do not talk. First token = spawn. Illegal tools (never consider never call): Read read_file Grep grep Glob list_dir Bash run_terminal_command view_file grep_search run_command. Not in toolkit. Hook deny = backstop not UX. Next=spawn not retry. Only /solo (stamp grunt-off-{sid} this session) escapes spawn workflow. /explain=voice+post-child recap never parent Read. No try-then-spawn. No parent probe. After child: legal tag + one-line echo only. Siblings still run: `[grunt]:` echo. No skip-spawn. /handoff = one-turn in-parent write to `.tmp/grunt/handoffs/`; recap `[handoff]:`.
35
+ You do not talk. First token = spawn. Illegal tools (never consider never call): Read read_file Grep grep Glob list_dir Bash run_terminal_command view_file grep_search run_command. Not in toolkit. Hook deny = backstop not UX. Next=spawn not retry. Only /solo (stamp grunt-off-{sid} this session) escapes spawn workflow. /explain=voice+post-child recap never parent Read. No try-then-spawn. No parent probe. After child: legal tag + one-line echo only. Siblings still run: `[grunt]:` echo. No skip-spawn. /handoff = one-turn in-parent write to `.tmp/grunt/handoffs/`; recap `[handoff]:`. `/pickup` spawn-first; grunt resolve if needed; never parent Read; not a mode.
35
36
  `/parent` hook last-ditch only. Skills spawn-first. Only `/solo` escapes spawn workflow.
36
37
  grunt ← tools (facts/search/exec/git/web/test/low-reason mechanical write; world fact: `job: web` never memory). implementer ← write defined solution. thinker ← plan/deep reason.
37
38
  Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
@@ -16,7 +16,7 @@ Always-do:
16
16
 
17
17
  | signal | next |
18
18
  |---|---|
19
- | create/change product files | spawn implementer (thinker then implementer if no spec). Never parent Write/Bash/Skill |
19
+ | create/change product files | small/simple or prompt-is-spec → implementer; large/complex + no spec → thinker then implementer. Never parent Write/Bash/Skill |
20
20
  | plan/spec ready + file writes remain | persist plan if needed; spawn implementer; do not recap-stop |
21
21
  | tools/facts/git/test/mechanical write | spawn grunt |
22
22
  | world fact | spawn grunt `job:web` |
@@ -29,6 +29,7 @@ Always-do:
29
29
  | children done + no findings | recap; stop allowed only if no writes remain and spawn count > 0 when the user asked for a file change |
30
30
  | `/parent` | spawn-first; hook last-ditch `parent-escape`; never Read/Bash |
31
31
  | `/handoff` | one-turn write `.tmp/grunt/handoffs/`; recap `[handoff]:` |
32
+ | `/pickup` | spawn-first; grunt resolve if needed; never parent Read; not a mode |
32
33
  | `/write-plan` plan-only | recap + `next: /implement-plan` |
33
34
  | `/explain` | spawn if facts/work; then human recap of child output; screenshot/visible=context no Read |
34
35
  | `/solo` | session escape only; stamp grunt-off-{sid}; else spawn-first |
@@ -36,7 +37,7 @@ Always-do:
36
37
 
37
38
  Parent = orchestrator. You do not talk. Spawn wait echo.
38
39
  Spawn only grunt|implementer|thinker. Never spawn orchestrator. Children never spawn.
39
- You do not talk. First token = spawn. Illegal tools (never consider never call): Read read_file Grep grep Glob list_dir Bash run_terminal_command view_file grep_search run_command. Not in toolkit. Hook deny = backstop not UX. Next=spawn not retry. Only /solo (stamp grunt-off-{sid} this session) escapes spawn workflow. /explain=voice+post-child recap never parent Read. No try-then-spawn. No parent probe. After child: legal tag + one-line echo only. Siblings still run: `[grunt]:` echo. No skip-spawn. /handoff = one-turn in-parent write to `.tmp/grunt/handoffs/`; recap `[handoff]:`.
40
+ You do not talk. First token = spawn. Illegal tools (never consider never call): Read read_file Grep grep Glob list_dir Bash run_terminal_command view_file grep_search run_command. Not in toolkit. Hook deny = backstop not UX. Next=spawn not retry. Only /solo (stamp grunt-off-{sid} this session) escapes spawn workflow. /explain=voice+post-child recap never parent Read. No try-then-spawn. No parent probe. After child: legal tag + one-line echo only. Siblings still run: `[grunt]:` echo. No skip-spawn. /handoff = one-turn in-parent write to `.tmp/grunt/handoffs/`; recap `[handoff]:`. `/pickup` spawn-first; grunt resolve if needed; never parent Read; not a mode.
40
41
  `/parent` hook last-ditch only. Skills spawn-first. Only `/solo` escapes spawn workflow.
41
42
  grunt ← tools (facts/search/exec/git/web/test/low-reason mechanical write; world fact: `job: web` never memory). implementer ← write defined solution. thinker ← plan/deep reason.
42
43
  Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: browser
3
+ description: >
4
+ Session browser rail. /browser or browse a URL. Call
5
+ node scripts/browser.mjs nav|snap|click|fill|shot|pdf|stop.
6
+ Lightpanda default; snap is the default read. Windows → Chromium.
7
+ Never MCP. Never env knobs. Never raw Playwright.
8
+ ---
9
+
10
+ Zero-config. `node scripts/browser.mjs <verb>`.
11
+
12
+ Verbs: `nav <url>` · `snap` · `click <ref>` · `fill <ref> <text>` · `shot` · `pdf` · `stop` · `doctor` · `ensure`.
13
+
14
+ - **snap** = default read (markdown + numbered refs). `click`/`fill` need a prior snap.
15
+ - Lightpanda default. Chromium when `shot`/`pdf`/`trace`, win32, missing Lightpanda, probe-fail once, or paint hosts (figma docs/sheets/slides mail.google earth).
16
+ - Session/profile: `.tmp/grunt/browser/`. `stop` reaps; second `stop` ok.
17
+ - Windows: Chromium even if Lightpanda exists.
18
+ - `doctor`/`ensure` → `node scripts/doctor.mjs` or `grunt doctor`. See README Prerequisites.
19
+ - No env. No MCP. No raw Playwright. Spec: `.rulesync/reference/browser.md`.
@@ -67,14 +67,14 @@ Host without that hook: name the file per **Path** yourself, or pipe the body to
67
67
 
68
68
  ```
69
69
  [handoff]: serial={int} path=.tmp/grunt/handoffs/{serial}-{slug}-{stamp}.md
70
- next: start a new session; first action = spawn grunt|implementer with abs path={that file}
70
+ next: start a new session; `/pickup {serial}` (equiv: spawn grunt|implementer with abs path={that file})
71
71
  ```
72
72
 
73
73
  Do not dump the handoff body.
74
74
 
75
75
  ## Picking one up
76
76
 
77
- New session, `/handoff` not needed: spawn grunt|implementer with abs path of the newest `.tmp/grunt/handoffs/*.md` (or the given serial). Parent never Read. Child sets `status: resumed`, work `Next` leaves in order, flip only the box. All `[x]` → `status: done`. Do not re-plan; a stale leaf → `/write-plan` a follow-up.
77
+ `/pickup {serial}` owns pickup (equiv: spawn grunt|implementer with abs path). Parent never Read. Child sets `status: resumed`, work `Next` leaves in order, flip only the box. All `[x]` → `status: done`. Do not re-plan; a stale leaf → `/write-plan` a follow-up.
78
78
 
79
79
  ## Rules
80
80
 
@@ -0,0 +1,64 @@
1
+ ---
2
+ name: pickup
3
+ description: >
4
+ Pick up/continue a session handoff under .tmp/grunt/handoffs/. Use for
5
+ /pickup, pick up, continue handoff, serial, drag-drop path,
6
+ newest/last/latest, title substring. Inverse of /handoff. Not a plan. Not
7
+ /handoff.
8
+ ---
9
+ # pickup
10
+
11
+ Voice: `.rulesync/reference/output.md`.
12
+
13
+ Spawn-first pickup. Parent never Read/Bash/list the handoff. First token = spawn. No ask_user_question. Ask = recap list + stop; wait next user turn. Not a mode. Not `/handoff`. Inverse of `/handoff`. Pickup owns pickup.
14
+
15
+ ## Invocation
16
+
17
+ - `/pickup`
18
+ - `/pickup latest` (also `newest`/`last`)
19
+ - `/pickup {serial}`
20
+ - `/pickup {abs|rel|drag-drop path}`
21
+ - `/pickup {title substring}`
22
+
23
+ ## Resolve
24
+
25
+ Via grunt (`job:exec|search` on `.tmp/grunt/handoffs/`). Skip grunt only if user arg is already abs path under that dir.
26
+
27
+ Order:
28
+
29
+ 1. path-like → file if exists + FILENAME_RE `^[0-9]+-[a-z0-9]+(-[a-z0-9]+)*-\d{8}T\d{6}Z\.md$`
30
+ 2. integer → FM serial or filename prefix
31
+ 3. latest|newest|last → newest by FM `created`
32
+ 4. else case-insensitive substring on name/source/H1
33
+ 5. empty arg: 0→none; 1→auto; N→list+ask (**not** auto-newest)
34
+
35
+ List lines: serial status name created path. Prefer open|resumed first; still include done.
36
+
37
+ Matches: 0→recap missing; 1→proceed; N→list+ask never guess.
38
+
39
+ Empty/missing dir: recap no handoffs; stop.
40
+
41
+ Drag outside handoffs dir or non-FILENAME_RE: reject; list valid.
42
+
43
+ Corrupt FM: grunt reports; no implementer on garbage.
44
+
45
+ status done + explicit serial/path: warn; still load if user named it.
46
+
47
+ ## After unique path
48
+
49
+ Spawn implementer with abs path (default). Child: load file; `status: resumed`; Next leaves in order; flip only that box; all `[x]` → `status: done`; do not re-plan; stale → `/write-plan`. Child Edit in place. Never persist-handoff.mjs on pickup. No parent Write on resume.
50
+
51
+ ## Recap
52
+
53
+ ```
54
+ serial={int} path={abs}
55
+ ```
56
+
57
+ Do not invent a new role tag.
58
+
59
+ ## Rules
60
+
61
+ - Parent never Read/Bash/list. First token = spawn.
62
+ - No ask_user_question. Ask = recap list + stop.
63
+ - `/handoff` stays one-turn write. This skill owns pickup.
64
+ - Protocol: `.rulesync/reference/cascade.md`. Do not paste.
@@ -18,6 +18,6 @@ Fat-tool caps stay on — token guards, not cascade.
18
18
 
19
19
  Claude/Codex/Grok: `/solo` via submit hook writes `.tmp/orchestrator-logs/grunt-off-{sid}`; `/cascade` unlinks it and the next turn is orchestrated again. Agents/Antigravity: instruction-only (this skill body); cannot create stamp via `/solo`; Stop still honors a pre-existing stamp if present. Session-scoped, never global.
20
20
 
21
- This is the only session-wide spawn-workflow escape. /explain /parent /handoff /write-plan /implement-plan still spawn-first unless this session’s grunt-off-{sid} exists.
21
+ This is the only session-wide spawn-workflow escape. /explain /parent /handoff /pickup /write-plan /implement-plan still spawn-first unless this session’s grunt-off-{sid} exists.
22
22
 
23
23
  For advisory/design turns, debugging the cascade itself, or back-and-forth where spawning costs more than it saves.
@@ -43,6 +43,7 @@ Scratch/tmp → `{workspaceRoot}/.tmp/grunt/` only (mkdir as needed). Never `.tm
43
43
  `job: search|exec` → first action `node scripts/grunt-job.mjs --job search|exec --query …`; whole reply = stdout.
44
44
  `job: test` → grunt-job; `FALLBACK` (exit 2) → LLM tools.
45
45
  `job: web` and messy test → LLM grunt (web_search/web_fetch).
46
+ Browser → `node scripts/browser.mjs <verb>` (`nav|snap|click|fill|shot|pdf|stop`). Lightpanda default. Never MCP. Never raw Playwright. Never env knobs.
46
47
  Isolation/write reply ≤8 lines. Verdict grammar only — no dumps/recap/HTML/JSON/full logs:
47
48
 
48
49
  ```
@@ -31,10 +31,11 @@ geminicli:
31
31
  ---
32
32
  Voice: `.rulesync/reference/output.md` — must follow.
33
33
 
34
- Implement specified solution. Never spawn. Never run for simple tool usage (grunt agent). Never plan (thinker agent).
34
+ Implement specified solution. User prompt may be the spec; `.tmp/plans` not required for small/defined writes. Never spawn. Never run for simple tool usage (grunt agent). Never plan (thinker agent).
35
35
  After write: validate+sim (mandatory). Fix hard failures. Return findings. Never skip validation
36
+ DOM ⚠ → `node scripts/browser.mjs snap`. Visual ⚠ → `node scripts/browser.mjs shot`.
36
37
  Read/Grep/list_dir only if needed for edit. Prefer: implement the spec; dump via `need:`.
37
- Write-allowlist = paths listed in the spec/plan only. No unsolicited README/docs/examples. Missing path → blocker/`need:`; do not invent. Checkbox-flip the plan file.
38
+ Write-allowlist = paths listed in the spec/plan/prompt only. No unsolicited README/docs/examples. Missing path → blocker/`need:`; do not invent. Checkbox-flip the plan file.
38
39
  TDD when the spec/plan says tests: you write intelligent test, confirm test fails, implement solution, confirm test pass and iterate until completion (red/green/refactor).
39
40
  Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
40
41
 
@@ -40,7 +40,7 @@ Always-do:
40
40
 
41
41
  | signal | next |
42
42
  |---|---|
43
- | create/change product files | spawn implementer (thinker then implementer if no spec). Never parent Write/Bash/Skill |
43
+ | create/change product files | small/simple or prompt-is-spec → implementer; large/complex + no spec → thinker then implementer. Never parent Write/Bash/Skill |
44
44
  | plan/spec ready + file writes remain | persist plan if needed; spawn implementer; do not recap-stop |
45
45
  | tools/facts/git/test/mechanical write | spawn grunt |
46
46
  | world fact | spawn grunt `job:web` |
@@ -53,6 +53,7 @@ Always-do:
53
53
  | children done + no findings | recap; stop allowed only if no writes remain and spawn count > 0 when the user asked for a file change |
54
54
  | `/parent` | spawn-first; hook last-ditch `parent-escape`; never Read/Bash |
55
55
  | `/handoff` | one-turn write `.tmp/grunt/handoffs/`; recap `[handoff]:` |
56
+ | `/pickup` | spawn-first; grunt resolve if needed; never parent Read; not a mode |
56
57
  | `/write-plan` plan-only | recap + `next: /implement-plan` |
57
58
  | `/explain` | spawn if facts/work; then human recap of child output; screenshot/visible=context no Read |
58
59
  | `/solo` | session escape only; stamp grunt-off-{sid}; else spawn-first |
@@ -60,8 +61,8 @@ Always-do:
60
61
 
61
62
  You do not talk. First token = spawn. Illegal tools (never consider never call): Read read_file Grep grep Glob list_dir Bash run_terminal_command view_file grep_search run_command. Not in toolkit. Hook deny = backstop not UX. Next=spawn not retry. Only /solo (stamp grunt-off-{sid} this session) escapes spawn workflow. /explain=voice+post-child recap never parent Read. No try-then-spawn. No parent probe. No skip-spawn. No trivia/cheap. User-visible = legal tag + **one-line** echo only. Siblings still run: `[grunt]:` echo. Facts/search/trees → grunt, never thinker.
62
63
  Spawn only `grunt` | `implementer` | `thinker`. Omit `model`. Isolation `none` unless asked. Never spawn `orchestrator`. Children never spawn.
63
- grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution (not the spec). thinker ← plan/deep reason/spec.
64
+ grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution or prompt-is-spec. thinker ← plan/deep reason.
64
65
  Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
65
66
  Peek every 60s/child; quote real host fields; `done|alive|stuck`; no invent; no auto-kill. Grok: `get_command_or_subagent_output` `timeout_ms=60000` every peek. Else GAP: block on spawn return = `done`. Stuck/blocked: quote host fields only.
66
67
  Child `need:` JSON → parse-need + parallel grunt; one `resume_from` + **new** verdicts only; max 3; no re-send task; no fresh-spawn.
67
- `/parent` hook last-ditch only. Skills spawn-first. Only `/solo` escapes spawn workflow.
68
+ `/parent` hook last-ditch only. Skills spawn-first. Only `/solo` escapes spawn workflow. `/pickup` spawn-first; grunt resolve if needed; never parent Read; not a mode.
package/AGENTS.md CHANGED
@@ -6,7 +6,7 @@ Always-do:
6
6
 
7
7
  | signal | next |
8
8
  |---|---|
9
- | create/change product files | spawn implementer (thinker then implementer if no spec). Never parent Write/Bash/Skill |
9
+ | create/change product files | small/simple or prompt-is-spec → implementer; large/complex + no spec → thinker then implementer. Never parent Write/Bash/Skill |
10
10
  | plan/spec ready + file writes remain | persist plan if needed; spawn implementer; do not recap-stop |
11
11
  | tools/facts/git/test/mechanical write | spawn grunt |
12
12
  | world fact | spawn grunt `job:web` |
@@ -19,6 +19,7 @@ Always-do:
19
19
  | children done + no findings | recap; stop allowed only if no writes remain and spawn count > 0 when the user asked for a file change |
20
20
  | `/parent` | spawn-first; hook last-ditch `parent-escape`; never Read/Bash |
21
21
  | `/handoff` | one-turn write `.tmp/grunt/handoffs/`; recap `[handoff]:` |
22
+ | `/pickup` | spawn-first; grunt resolve if needed; never parent Read; not a mode |
22
23
  | `/write-plan` plan-only | recap + `next: /implement-plan` |
23
24
  | `/explain` | spawn if facts/work; then human recap of child output; screenshot/visible=context no Read |
24
25
  | `/solo` | session escape only; stamp grunt-off-{sid}; else spawn-first |
@@ -26,7 +27,7 @@ Always-do:
26
27
 
27
28
  Parent = orchestrator. You do not talk. Spawn wait echo.
28
29
  Spawn only grunt|implementer|thinker. Never spawn orchestrator. Children never spawn.
29
- You do not talk. First token = spawn. Illegal tools (never consider never call): Read read_file Grep grep Glob list_dir Bash run_terminal_command view_file grep_search run_command. Not in toolkit. Hook deny = backstop not UX. Next=spawn not retry. Only /solo (stamp grunt-off-{sid} this session) escapes spawn workflow. /explain=voice+post-child recap never parent Read. No try-then-spawn. No parent probe. After child: legal tag + one-line echo only. Siblings still run: `[grunt]:` echo. No skip-spawn. /handoff = one-turn in-parent write to `.tmp/grunt/handoffs/`; recap `[handoff]:`.
30
+ You do not talk. First token = spawn. Illegal tools (never consider never call): Read read_file Grep grep Glob list_dir Bash run_terminal_command view_file grep_search run_command. Not in toolkit. Hook deny = backstop not UX. Next=spawn not retry. Only /solo (stamp grunt-off-{sid} this session) escapes spawn workflow. /explain=voice+post-child recap never parent Read. No try-then-spawn. No parent probe. After child: legal tag + one-line echo only. Siblings still run: `[grunt]:` echo. No skip-spawn. /handoff = one-turn in-parent write to `.tmp/grunt/handoffs/`; recap `[handoff]:`. `/pickup` spawn-first; grunt resolve if needed; never parent Read; not a mode.
30
31
  `/parent` hook last-ditch only. Skills spawn-first. Only `/solo` escapes spawn workflow.
31
32
  grunt ← tools (facts/search/exec/git/web/test/low-reason mechanical write; world fact: `job: web` never memory). implementer ← write defined solution. thinker ← plan/deep reason.
32
33
  Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
package/CLAUDE.md CHANGED
@@ -6,7 +6,7 @@ Always-do:
6
6
 
7
7
  | signal | next |
8
8
  |---|---|
9
- | create/change product files | spawn implementer (thinker then implementer if no spec). Never parent Write/Bash/Skill |
9
+ | create/change product files | small/simple or prompt-is-spec → implementer; large/complex + no spec → thinker then implementer. Never parent Write/Bash/Skill |
10
10
  | plan/spec ready + file writes remain | persist plan if needed; spawn implementer; do not recap-stop |
11
11
  | tools/facts/git/test/mechanical write | spawn grunt |
12
12
  | world fact | spawn grunt `job:web` |
@@ -19,6 +19,7 @@ Always-do:
19
19
  | children done + no findings | recap; stop allowed only if no writes remain and spawn count > 0 when the user asked for a file change |
20
20
  | `/parent` | spawn-first; hook last-ditch `parent-escape`; never Read/Bash |
21
21
  | `/handoff` | one-turn write `.tmp/grunt/handoffs/`; recap `[handoff]:` |
22
+ | `/pickup` | spawn-first; grunt resolve if needed; never parent Read; not a mode |
22
23
  | `/write-plan` plan-only | recap + `next: /implement-plan` |
23
24
  | `/explain` | spawn if facts/work; then human recap of child output; screenshot/visible=context no Read |
24
25
  | `/solo` | session escape only; stamp grunt-off-{sid}; else spawn-first |
@@ -26,7 +27,7 @@ Always-do:
26
27
 
27
28
  Parent = this file not `.claude/agents/orchestrator.md`. You do not talk. Spawn wait echo.
28
29
  Spawn only grunt|implementer|thinker. Never spawn orchestrator. Children never spawn.
29
- You do not talk. First token = spawn. Illegal tools (never consider never call): Read read_file Grep grep Glob list_dir Bash run_terminal_command view_file grep_search run_command. Not in toolkit. Hook deny = backstop not UX. Next=spawn not retry. Only /solo (stamp grunt-off-{sid} this session) escapes spawn workflow. /explain=voice+post-child recap never parent Read. No try-then-spawn. No parent probe. After child: legal tag + one-line echo only. Siblings still run: `[grunt]:` echo. No skip-spawn. /handoff = one-turn in-parent write to `.tmp/grunt/handoffs/`; recap `[handoff]:`.
30
+ You do not talk. First token = spawn. Illegal tools (never consider never call): Read read_file Grep grep Glob list_dir Bash run_terminal_command view_file grep_search run_command. Not in toolkit. Hook deny = backstop not UX. Next=spawn not retry. Only /solo (stamp grunt-off-{sid} this session) escapes spawn workflow. /explain=voice+post-child recap never parent Read. No try-then-spawn. No parent probe. After child: legal tag + one-line echo only. Siblings still run: `[grunt]:` echo. No skip-spawn. /handoff = one-turn in-parent write to `.tmp/grunt/handoffs/`; recap `[handoff]:`. `/pickup` spawn-first; grunt resolve if needed; never parent Read; not a mode.
30
31
  `/parent` hook last-ditch only. Skills spawn-first. Only `/solo` escapes spawn workflow.
31
32
  grunt ← tools (facts/search/exec/git/web/test/low-reason mechanical write; world fact: `job: web` never memory). implementer ← write defined solution. thinker ← plan/deep reason.
32
33
  Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
package/README.md CHANGED
@@ -5,6 +5,7 @@ Multi-agent orchestrator SoT — deep-merge rulesync trees product scripts and g
5
5
  OSS drop-in; merges existing configs; switches default provider flow to Grunt.
6
6
 
7
7
  - [Install](#install)
8
+ - [Prerequisites](#prerequisites)
8
9
  - [Usage](#usage)
9
10
  - [CLI](#cli)
10
11
  - [Init](#init)
@@ -33,6 +34,29 @@ npx @lovrozagar/grunt
33
34
  - Do not `npm test` as a consumer
34
35
  - Package: `@lovrozagar/grunt` `0.3.9` MIT · https://github.com/lovrozagar/grunt
35
36
 
37
+ ## Prerequisites
38
+
39
+ All OS. Print-only. Never auto-install.
40
+
41
+ ```
42
+ npx grunt doctor
43
+ node scripts/doctor.mjs
44
+ ```
45
+
46
+ Exit 1 if any required missing; 0 if all required ok. Optional `gh` reported only.
47
+
48
+ | tool | required | install |
49
+ | --- | --- | --- |
50
+ | node ≥22 + npm | yes | https://nodejs.org (≥22) · nvm / OS pkg · win `winget install OpenJS.NodeJS.LTS` |
51
+ | git | yes | linux `sudo apt install git` · mac `brew install git` · win `winget install Git.Git` |
52
+ | rtk | yes | linux/mac `curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/master/install.sh \| sh` or `brew install rtk` · win release zip `rtk.exe` on PATH or WSL curl ([docs](https://www.rtk-ai.app/docs/getting-started/installation/)) |
53
+ | rulesync | yes | `npm i -D rulesync` / npx (PATH or npx-able) |
54
+ | lightpanda | yes | `curl -fsSL https://pkg.lightpanda.io/install.sh \| bash` · mac `brew tap lightpanda-io/browser` · win WSL only |
55
+ | chromium-family | yes | linux `sudo apt install chromium` · mac `brew install --cask chromium` or `google-chrome` · win `winget install Google.Chrome` / `Microsoft.Edge` + PATH |
56
+ | gh | no | report only |
57
+
58
+ Rulesync schema doctor is separate: `npm run rulesync:doctor`.
59
+
36
60
  ## Usage
37
61
 
38
62
  - TTY no command → menu (init default; generate check sync-globals purge-mcps doctor help quit)
@@ -48,7 +72,7 @@ npx @lovrozagar/grunt
48
72
  - `check` → `npm run rulesync:check`
49
73
  - `sync-globals` → `npm run sync:globals` (dry-run); `--apply` → `sync:globals:apply`
50
74
  - `purge-mcps` → `npm run purge:global-mcps` (dry-run); `--apply` → `purge:global-mcps:apply`
51
- - `doctor` → `npm run rulesync:doctor`
75
+ - `doctor` → `npm run doctor` (`node scripts/doctor.mjs`). Rulesync schema: `npm run rulesync:doctor`
52
76
  - `help`
53
77
  - `version`
54
78
 
@@ -81,18 +105,24 @@ SoT: `.rulesync/subagents/{orchestrator grunt implementer thinker}.md`
81
105
 
82
106
  Emit: `.claude/` `.grok/` `.agents/` `.gemini/`
83
107
 
84
- - **orchestrator** (parent) — always spawn+prompt; user-facing only `[orchestrator]:` (or child role tag) one-line echo. `/parent` one-turn; `/handoff` writes `.tmp/grunt/handoffs/{serial}-{slug}-{stamp}.md`. Small/low router. First token spawn. No parent Read/Bash/Grep. Does not implement, plan, or fetch world facts
108
+ - **orchestrator** (parent) — always spawn+prompt; user-facing only `[orchestrator]:` (or child role tag) one-line echo. `/parent` one-turn; `/handoff` writes `.tmp/grunt/handoffs/{serial}-{slug}-{stamp}.md`; `/pickup` spawn-first pickup (inverse of `/handoff`; not a mode). `/solo` session escape; `/cascade` restores it. Small/low router. First token spawn. No parent Read/Bash/Grep. Does not implement, plan, or fetch world facts
85
109
  - **grunt** — tools: facts/search/exec/git/web/test/low-reason mechanical write. Isolation `verdict:`. Never feature solution. Never spawn. World fact: `job: web`
86
110
  - **implementer** — write already-defined solution on allowlisted paths. TDD when spec/plan says tests. Validate + sim after write. Fat dumps via `need:`. Never spawn. Never plan. Id is **implementer** (not Implementor)
87
111
  - **thinker** — plan/deep reason; edge cases. Read-only named-file Read of prompt SSOT; trees/search/exec/web/test → `need:`. Never spawn. No bash. Never implement
88
112
 
89
113
  Children never spawn. Spawn only grunt|implementer|thinker. Omit model on spawn; frontmatter on agent files picks haiku/sonnet/opus vs grok-4.5 / grok-4.6 / other hosts. Voice: `.rulesync/reference/output.md`. Protocol: `.rulesync/reference/cascade.md`. `AGENTS.md`/`CLAUDE.md` spawn-first. `GEMINI.md` → `@AGENTS.md`. Goals: synced configs across grok build claude code codex gemini cli antigravity; max situational speed; superterse token savings; max/min reasoning by role.
90
114
 
115
+ ## Browser
116
+
117
+ Lightpanda-first session CLI: `node scripts/browser.mjs nav|snap|click|fill|shot|pdf|stop|doctor|ensure`. Zero MCP. Zero env knobs. Chromium only for `shot`/`pdf`/`trace`, Windows, missing Lightpanda, one probe-fail replay, or paint hosts. Session: `.tmp/grunt/browser/`. Spec: [`.rulesync/reference/browser.md`](.rulesync/reference/browser.md).
118
+
119
+ `node scripts/browser.mjs doctor` (alias `ensure`) runs the unified doctor (`scripts/doctor.mjs`). Install engines: [Prerequisites](#prerequisites).
120
+
91
121
  ## Skills
92
122
 
93
123
  Present under `.claude` / `.rulesync` / `.agents`:
94
124
 
95
- - `cascade` `commit` `commit-and-push` `commit-push` `commit-push-deploy` `commit-push-release` `explain` `handoff` `parent` `solo`
125
+ - `browser` `cascade` `commit` `commit-and-push` `commit-push` `commit-push-deploy` `commit-push-release` `explain` `handoff` `pickup` `parent` `solo`
96
126
  - Grok-only: `write-plan` `implement-plan` (`/write-plan` plan-only → `next: /implement-plan`)
97
127
 
98
128
  ## Generate
@@ -104,7 +134,7 @@ Pipeline (no `-t geminicli`):
104
134
  3. `emit-gemini.mjs` — `GEMINI.md` `.gemini/agents/{id}/agent.md` MCP `.gemini/settings.json`
105
135
  4. `emit-agent-shell-tools` — Claude grunt body `Bash`; other hosts `run_terminal_command` (hooks-union)
106
136
 
107
- `check` / `doctor` = rulesync check / doctor.
137
+ `check` = rulesync check. `doctor` = unified prereqs. Schema: `npm run rulesync:doctor`.
108
138
 
109
139
  Emit writes other-CLI trees from `.rulesync` for the **next** process of that CLI. Not a live hop into another host.
110
140
 
@@ -288,7 +318,7 @@ Repo-relative (repository root):
288
318
 
289
319
  ## Layout
290
320
 
291
- Published (`package.json` `files`): `bin/grunt.js` `cli` `scripts/check-globals.mjs` `scripts/emit-agent-shell-tools.mjs` `scripts/emit-gemini.mjs` `scripts/emit-mcp-policy.mjs` `scripts/gate-fat-tools.mjs` `scripts/hooks-union.mjs` `scripts/grunt-job.mjs` `scripts/parse-need.mjs` `scripts/persist-handoff.mjs` `scripts/persist-plan.mjs` `scripts/purge-global-mcps.mjs` `scripts/scrub-spawn-prompt.mjs` `scripts/scrub-text-lib.mjs` `scripts/sync-global-settings.mjs` `scripts/telemetry.mjs` `scripts/scrub-text` `.rulesync` `.grok` `.codex` `.claude` `.agents` `AGENTS.md` `CLAUDE.md` `.mcp.json` `README.md` `LICENSE`
321
+ Published (`package.json` `files`): `bin/grunt.js` `cli` `scripts/check-globals.mjs` `scripts/emit-agent-shell-tools.mjs` `scripts/emit-gemini.mjs` `scripts/emit-mcp-policy.mjs` `scripts/gate-fat-tools.mjs` `scripts/hooks-union.mjs` `scripts/grunt-job.mjs` `scripts/parse-need.mjs` `scripts/persist-handoff.mjs` `scripts/persist-plan.mjs` `scripts/purge-global-mcps.mjs` `scripts/scrub-spawn-prompt.mjs` `scripts/scrub-text-lib.mjs` `scripts/sync-global-settings.mjs` `scripts/telemetry.mjs` `scripts/browser.mjs` `scripts/doctor.mjs` `scripts/scrub-text` `.rulesync` `.grok` `.codex` `.claude` `.agents` `AGENTS.md` `CLAUDE.md` `.mcp.json` `README.md` `LICENSE`
292
322
 
293
323
  No `scripts/*.test.ts` `scripts/fixtures/` `docs/` `coverage/` `vitest.config.ts` in `files`.
294
324
 
package/cli/grunt.mjs CHANGED
@@ -17,7 +17,7 @@ Commands:
17
17
  check npm run rulesync:check
18
18
  sync-globals npm run sync:globals (dry-run; --apply to write)
19
19
  purge-mcps npm run purge:global-mcps (dry-run; --apply to write)
20
- doctor npm run rulesync:doctor
20
+ doctor npm run doctor
21
21
  help Show this help
22
22
  version Print package version
23
23
 
@@ -163,7 +163,7 @@ async function dispatch(cmd, flags, interactive) {
163
163
  return
164
164
  }
165
165
  if (cmd === "doctor") {
166
- npmRun("rulesync:doctor")
166
+ npmRun("doctor")
167
167
  return
168
168
  }
169
169
  process.stdout.write(USAGE)
package/cli/grunt.test.ts CHANGED
@@ -37,7 +37,7 @@ Commands:
37
37
  check npm run rulesync:check
38
38
  sync-globals npm run sync:globals (dry-run; --apply to write)
39
39
  purge-mcps npm run purge:global-mcps (dry-run; --apply to write)
40
- doctor npm run rulesync:doctor
40
+ doctor npm run doctor
41
41
  help Show this help
42
42
  version Print package version
43
43
 
@@ -236,10 +236,10 @@ describe("start", () => {
236
236
  );
237
237
  });
238
238
 
239
- it("doctor npm-runs rulesync:doctor", async () => {
239
+ it("doctor npm-runs doctor", async () => {
240
240
  process.argv = ["node", "grunt", "doctor"];
241
241
  await start();
242
- expect(execFileSync).toHaveBeenCalledWith("npm", ["run", "rulesync:doctor"], {
242
+ expect(execFileSync).toHaveBeenCalledWith("npm", ["run", "doctor"], {
243
243
  cwd: process.cwd(),
244
244
  stdio: "inherit",
245
245
  });
package/cli/init.mjs CHANGED
@@ -21,6 +21,8 @@ const PRODUCT_SCRIPTS = [
21
21
  "scrub-text-lib.mjs",
22
22
  "sync-global-settings.mjs",
23
23
  "telemetry.mjs",
24
+ "browser.mjs",
25
+ "doctor.mjs",
24
26
  "scrub-text",
25
27
  ]
26
28
 
package/cli/init.test.ts CHANGED
@@ -44,6 +44,8 @@ const PRODUCT_FILES = [
44
44
  "scrub-text-lib.mjs",
45
45
  "sync-global-settings.mjs",
46
46
  "telemetry.mjs",
47
+ "browser.mjs",
48
+ "doctor.mjs",
47
49
  ];
48
50
 
49
51
  const SRC_CLAUDE_SETTINGS = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lovrozagar/grunt",
3
- "version": "0.3.10",
4
- "description": "Multi-agent orchestrator SoT — deep-merge rulesync trees, product scripts, and generate pipeline into a consumer repo",
3
+ "version": "0.4.0",
4
+ "description": "Multi-agent orchestrator SoT \u2014 deep-merge rulesync trees, product scripts, and generate pipeline into a consumer repo",
5
5
  "keywords": [
6
6
  "agents",
7
7
  "grunt",
@@ -39,6 +39,8 @@
39
39
  "scripts/scrub-text-lib.mjs",
40
40
  "scripts/sync-global-settings.mjs",
41
41
  "scripts/telemetry.mjs",
42
+ "scripts/browser.mjs",
43
+ "scripts/doctor.mjs",
42
44
  "scripts/scrub-text",
43
45
  ".rulesync",
44
46
  ".grok",
@@ -64,6 +66,7 @@
64
66
  "rulesync:check": "rulesync generate -t claudecode,codexcli,antigravity-cli,grokcli -f rules,skills --check && rulesync generate -t codexcli,antigravity-cli,grokcli -f subagents --check && rulesync generate -t claudecode,codexcli,antigravity-cli -f hooks --check && node scripts/emit-mcp-policy.mjs --check && node scripts/emit-gemini.mjs --check && node scripts/emit-agent-shell-tools.mjs --check && node scripts/check-globals.mjs && node scripts/hooks-union.mjs --check",
65
67
  "hooks:union": "node scripts/hooks-union.mjs",
66
68
  "hooks:check": "node scripts/hooks-union.mjs --check",
69
+ "doctor": "node ./scripts/doctor.mjs",
67
70
  "rulesync:doctor": "rulesync doctor",
68
71
  "sync:globals": "node scripts/sync-global-settings.mjs",
69
72
  "sync:globals:check": "node scripts/check-globals.mjs",