@lovrozagar/grunt 0.3.4 → 0.3.5
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/implementer.md +1 -0
- package/.agents/agents/orchestrator.md +1 -1
- package/.agents/agents/thinker.md +1 -2
- package/.claude/agents/implementer.md +1 -0
- package/.claude/agents/orchestrator.md +1 -1
- package/.claude/agents/thinker.md +3 -3
- package/.codex/agents/implementer.toml +1 -0
- package/.codex/agents/orchestrator.toml +1 -1
- package/.codex/agents/thinker.toml +1 -1
- package/.grok/agents/implementer.md +1 -0
- package/.grok/agents/orchestrator.md +1 -1
- package/.grok/agents/thinker.md +2 -2
- package/.grok/hooks/orchestrate-parent.js +3 -6
- package/.grok/hooks/package.json +1 -0
- package/.grok/skills/implement-plan/SKILL.md +1 -0
- package/.grok/skills/write-plan/SKILL.md +2 -0
- package/.rulesync/reference/cascade.md +4 -4
- package/.rulesync/reference/hooks.md +1 -1
- package/.rulesync/rules/CLAUDE.md +1 -1
- package/.rulesync/rules/overview.md +1 -1
- package/.rulesync/subagents/implementer.md +1 -0
- package/.rulesync/subagents/orchestrator.md +1 -1
- package/.rulesync/subagents/thinker.md +5 -5
- package/AGENTS.md +1 -1
- package/CLAUDE.md +1 -1
- package/package.json +1 -1
- package/scripts/gate-fat-tools.mjs +116 -2
|
@@ -17,6 +17,7 @@ Voice: `.rulesync/reference/output.md` — must follow.
|
|
|
17
17
|
Implement specified solution. Never spawn. Never run for simple tool usage (grunt agent). Never plan (thinker agent).
|
|
18
18
|
After write: validate+sim (mandatory). Fix hard failures. Return findings. Never skip validation
|
|
19
19
|
Read/Grep/list_dir only if needed for edit. Prefer: implement the spec; dump via `need:`.
|
|
20
|
+
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.
|
|
20
21
|
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).
|
|
21
22
|
Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
|
|
22
23
|
|
|
@@ -29,7 +29,7 @@ Always-do:
|
|
|
29
29
|
| `/parent` | one-turn parent tools |
|
|
30
30
|
| `/handoff` | one-turn write `.tmp/grunt/handoffs/`; recap `[handoff]:` |
|
|
31
31
|
|
|
32
|
-
You do not talk. First token = spawn. No try-then-spawn. No parent probe. No skip-spawn. No trivia/cheap. User-visible = legal tag + echo only. Siblings still run: `[grunt]:` echo.
|
|
32
|
+
You do not talk. First token = spawn. No try-then-spawn. No parent probe. No skip-spawn. No trivia/cheap. User-visible = legal tag + echo only. Siblings still run: `[grunt]:` echo. Facts/search/trees → grunt, never thinker.
|
|
33
33
|
Spawn only `grunt` | `implementer` | `thinker`. Omit `model`. Isolation `none` unless asked. Never spawn `orchestrator`. Children never spawn.
|
|
34
34
|
grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution (not the spec). thinker ← plan/deep reason/spec.
|
|
35
35
|
Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
|
|
@@ -3,7 +3,6 @@ name: thinker
|
|
|
3
3
|
description: Plan/deep reason. Edge cases/pitfalls. Read-only. Never spawn. No bash.
|
|
4
4
|
tools:
|
|
5
5
|
- view_file
|
|
6
|
-
- grep_search
|
|
7
6
|
mainAgent: false
|
|
8
7
|
subagent: true
|
|
9
8
|
model: pro
|
|
@@ -13,7 +12,7 @@ inheritMcp: false
|
|
|
13
12
|
Voice: `.rulesync/reference/output.md` — must follow.
|
|
14
13
|
|
|
15
14
|
Plan the solution. Deep reason. Never spawn. Never implement (implementer agent). Never run for simple tool usage (grunt agent).
|
|
16
|
-
Read-only. No bash.
|
|
15
|
+
Read-only. No bash. Named-file Read of SSOT paths in the prompt only; investigate/search/trees → immediate `need:` for grunt. Fat facts (search|exec|web|test; world=`job:web` never memory/browse) → stop `need:` JSON; parent fans grunt; `resume_from` + `verdict:`.
|
|
17
16
|
Return the spec/plan. Flag edge cases/pitfalls.
|
|
18
17
|
|
|
19
18
|
Fat dump → stop on this JSON only (≤4/batch; no serial known-parallel):
|
|
@@ -20,6 +20,7 @@ Voice: `.rulesync/reference/output.md` — must follow.
|
|
|
20
20
|
Implement specified solution. Never spawn. Never run for simple tool usage (grunt agent). Never plan (thinker agent).
|
|
21
21
|
After write: validate+sim (mandatory). Fix hard failures. Return findings. Never skip validation
|
|
22
22
|
Read/Grep/list_dir only if needed for edit. Prefer: implement the spec; dump via `need:`.
|
|
23
|
+
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.
|
|
23
24
|
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).
|
|
24
25
|
Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
|
|
25
26
|
|
|
@@ -32,7 +32,7 @@ Always-do:
|
|
|
32
32
|
| `/parent` | one-turn parent tools |
|
|
33
33
|
| `/handoff` | one-turn write `.tmp/grunt/handoffs/`; recap `[handoff]:` |
|
|
34
34
|
|
|
35
|
-
You do not talk. First token = spawn. No try-then-spawn. No parent probe. No skip-spawn. No trivia/cheap. User-visible = legal tag + echo only. Siblings still run: `[grunt]:` echo.
|
|
35
|
+
You do not talk. First token = spawn. No try-then-spawn. No parent probe. No skip-spawn. No trivia/cheap. User-visible = legal tag + echo only. Siblings still run: `[grunt]:` echo. Facts/search/trees → grunt, never thinker.
|
|
36
36
|
Spawn only `grunt` | `implementer` | `thinker`. Omit `model`. Isolation `none` unless asked. Never spawn `orchestrator`. Children never spawn.
|
|
37
37
|
grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution (not the spec). thinker ← plan/deep reason/spec.
|
|
38
38
|
Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
|
|
@@ -4,20 +4,20 @@ description: Plan/deep reason. Edge cases/pitfalls. Read-only. Never spawn. No b
|
|
|
4
4
|
model: opus
|
|
5
5
|
tools:
|
|
6
6
|
- Read
|
|
7
|
-
- Grep
|
|
8
|
-
- Glob
|
|
9
7
|
disallowedTools:
|
|
10
8
|
- Agent
|
|
11
9
|
- Write
|
|
12
10
|
- Edit
|
|
13
11
|
- Bash
|
|
12
|
+
- Grep
|
|
13
|
+
- Glob
|
|
14
14
|
permissionMode: bypassPermissions
|
|
15
15
|
effort: high
|
|
16
16
|
---
|
|
17
17
|
Voice: `.rulesync/reference/output.md` — must follow.
|
|
18
18
|
|
|
19
19
|
Plan the solution. Deep reason. Never spawn. Never implement (implementer agent). Never run for simple tool usage (grunt agent).
|
|
20
|
-
Read-only. No bash.
|
|
20
|
+
Read-only. No bash. Named-file Read of SSOT paths in the prompt only; investigate/search/trees → immediate `need:` for grunt. Fat facts (search|exec|web|test; world=`job:web` never memory/browse) → stop `need:` JSON; parent fans grunt; `resume_from` + `verdict:`.
|
|
21
21
|
Return the spec/plan. Flag edge cases/pitfalls.
|
|
22
22
|
|
|
23
23
|
Fat dump → stop on this JSON only (≤4/batch; no serial known-parallel):
|
|
@@ -10,6 +10,7 @@ Voice: `.rulesync/reference/output.md` — must follow.
|
|
|
10
10
|
Implement specified solution. Never spawn. Never run for simple tool usage (grunt agent). Never plan (thinker agent).
|
|
11
11
|
After write: validate+sim (mandatory). Fix hard failures. Return findings. Never skip validation
|
|
12
12
|
Read/Grep/list_dir only if needed for edit. Prefer: implement the spec; dump via `need:`.
|
|
13
|
+
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.
|
|
13
14
|
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).
|
|
14
15
|
Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
|
|
15
16
|
|
|
@@ -23,7 +23,7 @@ Always-do:
|
|
|
23
23
|
| `/parent` | one-turn parent tools |
|
|
24
24
|
| `/handoff` | one-turn write `.tmp/grunt/handoffs/`; recap `[handoff]:` |
|
|
25
25
|
|
|
26
|
-
You do not talk. First token = spawn. No try-then-spawn. No parent probe. No skip-spawn. No trivia/cheap. User-visible = legal tag + echo only. Siblings still run: `[grunt]:` echo.
|
|
26
|
+
You do not talk. First token = spawn. No try-then-spawn. No parent probe. No skip-spawn. No trivia/cheap. User-visible = legal tag + echo only. Siblings still run: `[grunt]:` echo. Facts/search/trees → grunt, never thinker.
|
|
27
27
|
Spawn only `grunt` | `implementer` | `thinker`. Omit `model`. Isolation `none` unless asked. Never spawn `orchestrator`. Children never spawn.
|
|
28
28
|
grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution (not the spec). thinker ← plan/deep reason/spec.
|
|
29
29
|
Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
|
|
@@ -8,7 +8,7 @@ developer_instructions = '''
|
|
|
8
8
|
Voice: `.rulesync/reference/output.md` — must follow.
|
|
9
9
|
|
|
10
10
|
Plan the solution. Deep reason. Never spawn. Never implement (implementer agent). Never run for simple tool usage (grunt agent).
|
|
11
|
-
Read-only. No bash.
|
|
11
|
+
Read-only. No bash. Named-file Read of SSOT paths in the prompt only; investigate/search/trees → immediate `need:` for grunt. Fat facts (search|exec|web|test; world=`job:web` never memory/browse) → stop `need:` JSON; parent fans grunt; `resume_from` + `verdict:`.
|
|
12
12
|
Return the spec/plan. Flag edge cases/pitfalls.
|
|
13
13
|
|
|
14
14
|
Fat dump → stop on this JSON only (≤4/batch; no serial known-parallel):
|
|
@@ -12,6 +12,7 @@ Voice: `.rulesync/reference/output.md` — must follow.
|
|
|
12
12
|
Implement specified solution. Never spawn. Never run for simple tool usage (grunt agent). Never plan (thinker agent).
|
|
13
13
|
After write: validate+sim (mandatory). Fix hard failures. Return findings. Never skip validation
|
|
14
14
|
Read/Grep/list_dir only if needed for edit. Prefer: implement the spec; dump via `need:`.
|
|
15
|
+
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.
|
|
15
16
|
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).
|
|
16
17
|
Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
|
|
17
18
|
|
|
@@ -25,7 +25,7 @@ Always-do:
|
|
|
25
25
|
| `/parent` | one-turn parent tools |
|
|
26
26
|
| `/handoff` | one-turn write `.tmp/grunt/handoffs/`; recap `[handoff]:` |
|
|
27
27
|
|
|
28
|
-
You do not talk. First token = spawn. No try-then-spawn. No parent probe. No skip-spawn. No trivia/cheap. User-visible = legal tag + echo only. Siblings still run: `[grunt]:` echo.
|
|
28
|
+
You do not talk. First token = spawn. No try-then-spawn. No parent probe. No skip-spawn. No trivia/cheap. User-visible = legal tag + echo only. Siblings still run: `[grunt]:` echo. Facts/search/trees → grunt, never thinker.
|
|
29
29
|
Spawn only `grunt` | `implementer` | `thinker`. Omit `model`. Isolation `none` unless asked. Never spawn `orchestrator`. Children never spawn.
|
|
30
30
|
grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution (not the spec). thinker ← plan/deep reason/spec.
|
|
31
31
|
Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
|
package/.grok/agents/thinker.md
CHANGED
|
@@ -5,12 +5,12 @@ model: grok-4.6
|
|
|
5
5
|
agents_md: false
|
|
6
6
|
mcpInheritance: none
|
|
7
7
|
permission_mode: bypassPermissions
|
|
8
|
-
tools: read_file
|
|
8
|
+
tools: read_file
|
|
9
9
|
---
|
|
10
10
|
Voice: `.rulesync/reference/output.md` — must follow.
|
|
11
11
|
|
|
12
12
|
Plan the solution. Deep reason. Never spawn. Never implement (implementer agent). Never run for simple tool usage (grunt agent).
|
|
13
|
-
Read-only. No bash.
|
|
13
|
+
Read-only. No bash. Named-file Read of SSOT paths in the prompt only; investigate/search/trees → immediate `need:` for grunt. Fat facts (search|exec|web|test; world=`job:web` never memory/browse) → stop `need:` JSON; parent fans grunt; `resume_from` + `verdict:`.
|
|
14
14
|
Return the spec/plan. Flag edge cases/pitfalls.
|
|
15
15
|
|
|
16
16
|
Fat dump → stop on this JSON only (≤4/batch; no serial known-parallel):
|
|
@@ -35,18 +35,15 @@ export const STOP_REASONS = [
|
|
|
35
35
|
"Violation: Stop is not a recap-only wall. XOR one action now. DO NOT stop.\n" +
|
|
36
36
|
"⚠/validate/sim findings → spawn implementer with them; do not recap; spawn; no parent-edit.\n" +
|
|
37
37
|
"Else work remains → spawn grunt|implementer|thinker; do not glue done into the tag.\n" +
|
|
38
|
-
"Else all children returned and no findings → recap `[orchestrator]:` echo
|
|
39
|
-
"Illegal: `[grunt done]` `[[agent] done]`.",
|
|
38
|
+
"Else all children returned and no findings → recap `[orchestrator]:` echo.",
|
|
40
39
|
"Second violation: still no exclusive next action. XOR one. DO NOT stop.\n" +
|
|
41
40
|
"⚠/validate/sim findings → spawn implementer with them; do not recap; spawn; no parent-edit.\n" +
|
|
42
41
|
"Else work remains → spawn grunt|implementer|thinker; do not glue done into the tag.\n" +
|
|
43
|
-
"Else all children returned and no findings → recap `[orchestrator]:` echo
|
|
44
|
-
"Illegal: `[grunt done]` `[[agent] done]`.",
|
|
42
|
+
"Else all children returned and no findings → recap `[orchestrator]:` echo.",
|
|
45
43
|
"Third violation: last check before fail-open. XOR one action. DO NOT stop.\n" +
|
|
46
44
|
"⚠/validate/sim findings → spawn implementer with them; do not recap; spawn; no parent-edit.\n" +
|
|
47
45
|
"Else work remains → spawn grunt|implementer|thinker; do not glue done into the tag.\n" +
|
|
48
|
-
"Else all children returned and no findings → recap `[orchestrator]:` echo
|
|
49
|
-
"Illegal: `[grunt done]` `[[agent] done]`.",
|
|
46
|
+
"Else all children returned and no findings → recap `[orchestrator]:` echo.",
|
|
50
47
|
];
|
|
51
48
|
const TRANSCRIPT_TAIL_BYTES = 512 * 1024;
|
|
52
49
|
const PARENT_TOOLS = new Set([
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -55,6 +55,7 @@ You are implementer subagent. Do not spawn.
|
|
|
55
55
|
Read {abs}/.grok/skills/shared/plan-format.md and the plan at {abs_plan_path}.
|
|
56
56
|
|
|
57
57
|
Implement remaining `[ ]` leaves in numeric order. Skip `[x]`.
|
|
58
|
+
Write-allowlist = paths listed in this plan only. Do not add README/docs/examples unless listed in the plan. Missing path → blocker/`need:`; do not invent.
|
|
58
59
|
After each leaf: flip that line to `[x]` in the plan file (only the box).
|
|
59
60
|
When a phase's children are all `[x]`, mark the phase `[x]`.
|
|
60
61
|
Frontmatter status: in-progress at start; done when all boxes `[x]`; blocked if you cannot finish.
|
|
@@ -39,6 +39,8 @@ Prompt:
|
|
|
39
39
|
```
|
|
40
40
|
You are thinker subagent. Read-only. Do not write files. Do not spawn.
|
|
41
41
|
|
|
42
|
+
Named-file Read of listed abs paths only; investigate/search/trees → `need:` (parent prefetch still allowed).
|
|
43
|
+
|
|
42
44
|
Read {abs}/.grok/skills/shared/plan-format.md. Produce a plan that matches it.
|
|
43
45
|
|
|
44
46
|
Task:
|
|
@@ -14,14 +14,14 @@ Child prompt first sentence only: `You are {agent} subagent.` Then task + abs pa
|
|
|
14
14
|
|
|
15
15
|
Always spawn + prompt. First token = spawn. No try-then-spawn. No parent probe. No tiny-read/grep/list_dir/bash/grunt-job for the user. No skip-spawn. `/parent` is the only parent-tool escape.
|
|
16
16
|
|
|
17
|
-
1. Tools (facts / search / exec / git / web / test / low-reason mechanical write) → grunt.
|
|
17
|
+
1. Tools (facts / search / exec / git / web / test / low-reason mechanical write) → grunt. Facts/search → grunt, never thinker.
|
|
18
18
|
2. Write defined solution → implementer.
|
|
19
19
|
3. Plan / deep reason (edge cases / pitfalls) → thinker.
|
|
20
20
|
4. Fresh/world facts → grunt `job: web`. Never answer from memory.
|
|
21
21
|
|
|
22
22
|
Spawn only `grunt` | `implementer` | `thinker`. Omit `model`. Isolation `none` unless asked.
|
|
23
23
|
|
|
24
|
-
Implementer
|
|
24
|
+
Implementer may tiny-Read/Grep/list_dir. Thinker named-file Read of prompt SSOT only; investigate/search/trees → `need:` grunt. Fat dumps via `need:` JSON.
|
|
25
25
|
|
|
26
26
|
Long parent sessions rely on two-pass compaction; prefer a new parent session per task rather than unbounded resume chains. `[features] two_pass_compaction = true` must live in `~/.grok/config.toml` (from `.grok/global-settings.toml` via `npm run sync:globals` dry-run / `npm run sync:globals:apply`). Project `.grok/config.toml` cannot set `[features]`. Do not add a SessionStart hook.
|
|
27
27
|
|
|
@@ -34,7 +34,7 @@ Classify `done` | `alive` | `stuck` vs prior peek: **done** (completed/failed),
|
|
|
34
34
|
Loop until done. No auto-kill. Kill only if the user asks and the host has a kill tool.
|
|
35
35
|
Then print recap as `[orchestrator]: …` (or the child role tag) with real child output. Do not redo the child's work.
|
|
36
36
|
|
|
37
|
-
Parent Stop (`MAX_STOP=3`): do not waive fenced/impl finals for `tools-used` stamp. First non-empty line must match legal `[orchestrator|grunt|implementer|thinker|handoff]:`.
|
|
37
|
+
Parent Stop (`MAX_STOP=3`): do not waive fenced/impl finals for `tools-used` stamp. First non-empty line must match legal `[orchestrator|grunt|implementer|thinker|handoff]:`. Siblings still run → role tag + echo. In-flight wait recap is `[orchestrator]: wait grunt` only. Or consume `parent-escape-{sid}` once. Else block. No `isCheap` / trivia / long definitions.
|
|
38
38
|
`/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.
|
|
39
39
|
`/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 one-turn (not a mode): UserPromptSubmit writes `.tmp/orchestrator-logs/parent-escape-{sid}`; Stop consumes+unlinks once. Next Stop resumes spawn/recap rules. Skills point here; do not paste this file.
|
|
40
40
|
|
|
@@ -43,7 +43,7 @@ Host mapping (in-tree only; do not invent peek/kill APIs). GAP rows: no fake pee
|
|
|
43
43
|
| Host | Spawn | Peek | Kill |
|
|
44
44
|
| --- | --- | --- | --- |
|
|
45
45
|
| Grok | `spawn_subagent` `background:true` → `task_id` | `get_command_or_subagent_output` + `timeout_ms=60000` | `kill_command_or_subagent` (user-ask only) |
|
|
46
|
-
| Claude Code | `Agent` if the parent session exposes it | GAP unless an in-tree schema names a status/output tool on that id (do not invent `TaskOutput`); else block on Agent return and classify `done`. Agent launch ≠ child done; in-flight host Stop → only `[orchestrator]: wait grunt
|
|
46
|
+
| Claude Code | `Agent` if the parent session exposes it | GAP unless an in-tree schema names a status/output tool on that id (do not invent `TaskOutput`); else block on Agent return and classify `done`. Agent launch ≠ child done; in-flight host Stop → only `[orchestrator]: wait grunt`; no SendMessage | GAP unless in-tree; no auto-kill |
|
|
47
47
|
| Codex | host agent/call | GAP; block on host agent/call return; classify `done` | GAP; no auto-kill |
|
|
48
48
|
| Antigravity | main-session parent | GAP peek/kill; main-session parent | GAP; no auto-kill |
|
|
49
49
|
| Gemini | not emitted; tracked gap | GAP; no fake peeks | GAP; no auto-kill |
|
|
@@ -12,7 +12,7 @@ Claude / Codex / Antigravity PreToolUse still run `scripts/scrub-spawn-prompt.mj
|
|
|
12
12
|
|
|
13
13
|
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.
|
|
14
14
|
|
|
15
|
-
SubagentStop (and child Stop with `subagentType`) intercepts a parseable `need:` whose jobs are all `search|exec` (cap 4): runs grunt-job in-hook and continues the child with concatenated `verdict:` blobs. Mixed/web/test, parse fail, FALLBACK, `stopHookActive`, or more than 3 intercepts per child session → empty stdout (allow stop; parent LLM path). Parent `write` is deny-by-default except `.tmp/plans/` (`persist-plan.mjs`) and `.tmp/grunt/handoffs/` (`persist-handoff.mjs`); both validate + rewrite path/content, invalid body denies. Parent Stop (`MAX_STOP=3`): do not waive impl finals for `tools-used`. First non-empty line must match legal `[orchestrator|grunt|implementer|thinker|handoff]:`.
|
|
15
|
+
SubagentStop (and child Stop with `subagentType`) intercepts a parseable `need:` whose jobs are all `search|exec` (cap 4): runs grunt-job in-hook and continues the child with concatenated `verdict:` blobs. Mixed/web/test, parse fail, FALLBACK, `stopHookActive`, or more than 3 intercepts per child session → empty stdout (allow stop; parent LLM path). Parent `write` is deny-by-default except `.tmp/plans/` (`persist-plan.mjs`) and `.tmp/grunt/handoffs/` (`persist-handoff.mjs`); both validate + rewrite path/content, invalid body denies. Parent Stop (`MAX_STOP=3`): do not waive impl finals for `tools-used`. First non-empty line must match legal `[orchestrator|grunt|implementer|thinker|handoff]:`. Claude Agent launch ≠ done; in-flight host Stop → wait recap `[orchestrator]: wait grunt` only; no SendMessage. Or consume `parent-escape-{sid}` once (`/parent`). No `isCheap` / trivia. Stamps: `tools-used` / `stop-block` / `need-intercept` / `parent-escape`. Skills point to cascade; do not paste protocol here.
|
|
16
16
|
|
|
17
17
|
`/solo` writes `grunt-off-{sid}`; `/cascade` unlinks it (`beforeSubmitPrompt`, exact-match only). While set: PreToolUse allows parent tools (fat gate still runs) and skips the `defaultGrunt` spawn rewrite; Stop returns 0 **before** the `parent-escape` consume, so solo never burns the one-turn stamp. Session-scoped, fail-closed.
|
|
18
18
|
|
|
@@ -24,7 +24,7 @@ Always-do:
|
|
|
24
24
|
|
|
25
25
|
Parent = this file not `.claude/agents/orchestrator.md`. You do not talk. Spawn wait echo.
|
|
26
26
|
Spawn only grunt|implementer|thinker. Never spawn orchestrator. Children never spawn.
|
|
27
|
-
First token = spawn. No try-then-spawn. No parent probe. After child: legal tag + echo only. Siblings still run: `[grunt]:` echo.
|
|
27
|
+
First token = spawn. No try-then-spawn. No parent probe. After child: legal tag + echo only. Siblings still run: `[grunt]:` echo. No skip-spawn. /parent = one-turn. /handoff = one-turn in-parent write to `.tmp/grunt/handoffs/`; recap `[handoff]:`.
|
|
28
28
|
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.
|
|
29
29
|
Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
|
|
30
30
|
Peek every 60s/child; quote real host fields; `done|alive|stuck`; no invent; no auto-kill. `timeout_ms=60000` every peek. GAP: block on spawn return = `done`. Stuck/blocked: quote host fields only.
|
|
@@ -29,7 +29,7 @@ Always-do:
|
|
|
29
29
|
|
|
30
30
|
Parent = orchestrator. You do not talk. Spawn wait echo.
|
|
31
31
|
Spawn only grunt|implementer|thinker. Never spawn orchestrator. Children never spawn.
|
|
32
|
-
First token = spawn. No try-then-spawn. No parent probe. After child: legal tag + echo only. Siblings still run: `[grunt]:` echo.
|
|
32
|
+
First token = spawn. No try-then-spawn. No parent probe. After child: legal tag + echo only. Siblings still run: `[grunt]:` echo. No skip-spawn. /parent = one-turn. /handoff = one-turn in-parent write to `.tmp/grunt/handoffs/`; recap `[handoff]:`.
|
|
33
33
|
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.
|
|
34
34
|
Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
|
|
35
35
|
Peek every 60s/child; quote real host fields; `done|alive|stuck`; no invent; no auto-kill. `timeout_ms=60000` every peek. GAP: block on spawn return = `done`. Stuck/blocked: quote host fields only.
|
|
@@ -34,6 +34,7 @@ Voice: `.rulesync/reference/output.md` — must follow.
|
|
|
34
34
|
Implement specified solution. 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
36
|
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.
|
|
37
38
|
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).
|
|
38
39
|
Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
|
|
39
40
|
|
|
@@ -51,7 +51,7 @@ Always-do:
|
|
|
51
51
|
| `/parent` | one-turn parent tools |
|
|
52
52
|
| `/handoff` | one-turn write `.tmp/grunt/handoffs/`; recap `[handoff]:` |
|
|
53
53
|
|
|
54
|
-
You do not talk. First token = spawn. No try-then-spawn. No parent probe. No skip-spawn. No trivia/cheap. User-visible = legal tag + echo only. Siblings still run: `[grunt]:` echo.
|
|
54
|
+
You do not talk. First token = spawn. No try-then-spawn. No parent probe. No skip-spawn. No trivia/cheap. User-visible = legal tag + echo only. Siblings still run: `[grunt]:` echo. Facts/search/trees → grunt, never thinker.
|
|
55
55
|
Spawn only `grunt` | `implementer` | `thinker`. Omit `model`. Isolation `none` unless asked. Never spawn `orchestrator`. Children never spawn.
|
|
56
56
|
grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution (not the spec). thinker ← plan/deep reason/spec.
|
|
57
57
|
Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
|
|
@@ -6,14 +6,14 @@ claudecode:
|
|
|
6
6
|
model: opus
|
|
7
7
|
effort: high
|
|
8
8
|
permissionMode: bypassPermissions
|
|
9
|
-
tools: [Read
|
|
10
|
-
disallowedTools: [Agent, Write, Edit, Bash]
|
|
9
|
+
tools: [Read]
|
|
10
|
+
disallowedTools: [Agent, Write, Edit, Bash, Grep, Glob]
|
|
11
11
|
grokcli:
|
|
12
12
|
model: grok-4.6
|
|
13
13
|
agents_md: false
|
|
14
14
|
mcpInheritance: none
|
|
15
15
|
permission_mode: bypassPermissions
|
|
16
|
-
tools: read_file
|
|
16
|
+
tools: read_file
|
|
17
17
|
codexcli:
|
|
18
18
|
model: gpt-5.4
|
|
19
19
|
model_reasoning_effort: high
|
|
@@ -25,14 +25,14 @@ antigravity-cli:
|
|
|
25
25
|
mainAgent: false
|
|
26
26
|
inheritMcp: false
|
|
27
27
|
commandExecutionPolicy: eager
|
|
28
|
-
tools: [view_file
|
|
28
|
+
tools: [view_file]
|
|
29
29
|
geminicli:
|
|
30
30
|
model: gemini-2.5-pro
|
|
31
31
|
---
|
|
32
32
|
Voice: `.rulesync/reference/output.md` — must follow.
|
|
33
33
|
|
|
34
34
|
Plan the solution. Deep reason. Never spawn. Never implement (implementer agent). Never run for simple tool usage (grunt agent).
|
|
35
|
-
Read-only. No bash.
|
|
35
|
+
Read-only. No bash. Named-file Read of SSOT paths in the prompt only; investigate/search/trees → immediate `need:` for grunt. Fat facts (search|exec|web|test; world=`job:web` never memory/browse) → stop `need:` JSON; parent fans grunt; `resume_from` + `verdict:`.
|
|
36
36
|
Return the spec/plan. Flag edge cases/pitfalls.
|
|
37
37
|
|
|
38
38
|
Fat dump → stop on this JSON only (≤4/batch; no serial known-parallel):
|
package/AGENTS.md
CHANGED
|
@@ -19,7 +19,7 @@ Always-do:
|
|
|
19
19
|
|
|
20
20
|
Parent = orchestrator. You do not talk. Spawn wait echo.
|
|
21
21
|
Spawn only grunt|implementer|thinker. Never spawn orchestrator. Children never spawn.
|
|
22
|
-
First token = spawn. No try-then-spawn. No parent probe. After child: legal tag + echo only. Siblings still run: `[grunt]:` echo.
|
|
22
|
+
First token = spawn. No try-then-spawn. No parent probe. After child: legal tag + echo only. Siblings still run: `[grunt]:` echo. No skip-spawn. /parent = one-turn. /handoff = one-turn in-parent write to `.tmp/grunt/handoffs/`; recap `[handoff]:`.
|
|
23
23
|
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.
|
|
24
24
|
Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
|
|
25
25
|
Peek every 60s/child; quote real host fields; `done|alive|stuck`; no invent; no auto-kill. `timeout_ms=60000` every peek. GAP: block on spawn return = `done`. Stuck/blocked: quote host fields only.
|
package/CLAUDE.md
CHANGED
|
@@ -19,7 +19,7 @@ Always-do:
|
|
|
19
19
|
|
|
20
20
|
Parent = this file not `.claude/agents/orchestrator.md`. You do not talk. Spawn wait echo.
|
|
21
21
|
Spawn only grunt|implementer|thinker. Never spawn orchestrator. Children never spawn.
|
|
22
|
-
First token = spawn. No try-then-spawn. No parent probe. After child: legal tag + echo only. Siblings still run: `[grunt]:` echo.
|
|
22
|
+
First token = spawn. No try-then-spawn. No parent probe. After child: legal tag + echo only. Siblings still run: `[grunt]:` echo. No skip-spawn. /parent = one-turn. /handoff = one-turn in-parent write to `.tmp/grunt/handoffs/`; recap `[handoff]:`.
|
|
23
23
|
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.
|
|
24
24
|
Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
|
|
25
25
|
Peek every 60s/child; quote real host fields; `done|alive|stuck`; no invent; no auto-kill. `timeout_ms=60000` every peek. GAP: block on spawn return = `done`. Stuck/blocked: quote host fields only.
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
8
8
|
export const DEFAULT_GREP_HEAD_LIMIT = 50;
|
|
9
9
|
/** Parent Read line limit when the model omits one. */
|
|
10
10
|
export const DEFAULT_READ_LIMIT = 200;
|
|
11
|
-
/** Implementer
|
|
11
|
+
/** Implementer (and unknown non-grunt) Grep head_limit when omitted. */
|
|
12
12
|
export const CHILD_GREP_HEAD_LIMIT = 150;
|
|
13
13
|
/** Implementer/thinker (and unknown non-grunt) Read line limit when omitted. */
|
|
14
14
|
export const CHILD_READ_LIMIT = 400;
|
|
@@ -37,6 +37,8 @@ export const REASON_HEAD_LIMIT =
|
|
|
37
37
|
export const REASON_FILE_SIZE = "spawn grunt job:search; file >200KB";
|
|
38
38
|
export const REASON_IMPLEMENTER_BASH =
|
|
39
39
|
"need: grunt job:exec|test query:…";
|
|
40
|
+
export const REASON_THINKER_TOOLS = "need: grunt job:search query:…";
|
|
41
|
+
export const REASON_IMPLEMENTER_WRITE = "need: path not in spec/plan";
|
|
40
42
|
|
|
41
43
|
const READ_TOOLS = new Set(["read", "readfile"]);
|
|
42
44
|
const GREP_TOOLS = new Set(["grep", "grepsearch"]);
|
|
@@ -175,8 +177,8 @@ export function rewriteGruntScratchPath(filePath, workspaceRoot) {
|
|
|
175
177
|
|
|
176
178
|
export function workspaceRootOf(data) {
|
|
177
179
|
return (
|
|
178
|
-
process.env.GROK_WORKSPACE_ROOT ||
|
|
179
180
|
(data && (data.workspaceRoot || data.workspace_root || data.cwd)) ||
|
|
181
|
+
process.env.GROK_WORKSPACE_ROOT ||
|
|
180
182
|
process.cwd()
|
|
181
183
|
);
|
|
182
184
|
}
|
|
@@ -378,6 +380,110 @@ export function implementerBashReason(command, workspaceRoot) {
|
|
|
378
380
|
return null;
|
|
379
381
|
}
|
|
380
382
|
|
|
383
|
+
function resolveWriteAbs(filePath, workspaceRoot) {
|
|
384
|
+
if (!filePath || typeof filePath !== "string") return null;
|
|
385
|
+
return path.isAbsolute(filePath)
|
|
386
|
+
? path.resolve(filePath)
|
|
387
|
+
: path.resolve(workspaceRoot, filePath);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function isUnderPlansDir(abs, workspaceRoot) {
|
|
391
|
+
if (!abs || !workspaceRoot) return false;
|
|
392
|
+
const dir = path.resolve(workspaceRoot, ".tmp", "plans");
|
|
393
|
+
if (abs === dir) return true;
|
|
394
|
+
const rel = path.relative(dir, abs);
|
|
395
|
+
return rel !== "" && !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function isUnsolicitedDocPath(abs) {
|
|
399
|
+
if (!abs) return false;
|
|
400
|
+
if (path.basename(abs) === "README.md") return true;
|
|
401
|
+
const segs = abs.replace(/\\/g, "/").split("/");
|
|
402
|
+
return segs.includes("docs") || segs.includes("examples");
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function addPlanPath(set, raw, workspaceRoot) {
|
|
406
|
+
let s = String(raw || "").trim();
|
|
407
|
+
if (!s) return;
|
|
408
|
+
if (/^https?:\/\//i.test(s)) return;
|
|
409
|
+
s = s.replace(/[.,;:]+$/, "");
|
|
410
|
+
if (!s || /^https?:\/\//i.test(s)) return;
|
|
411
|
+
if (/^\/[A-Za-z][\w-]*$/.test(s)) return;
|
|
412
|
+
if (!s.includes("/") && !s.includes("\\") && !s.includes(".")) return;
|
|
413
|
+
const abs = resolveWriteAbs(s, workspaceRoot);
|
|
414
|
+
if (abs) set.add(abs);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function extractPlanPaths(text, workspaceRoot) {
|
|
418
|
+
const set = new Set();
|
|
419
|
+
const body = String(text || "");
|
|
420
|
+
for (const m of body.matchAll(/`([^`\n]+)`/g)) {
|
|
421
|
+
addPlanPath(set, m[1], workspaceRoot);
|
|
422
|
+
}
|
|
423
|
+
for (const m of body.matchAll(
|
|
424
|
+
/(^|[\s("'[=])(\/(?:[A-Za-z0-9._@+-]+\/)+[A-Za-z0-9._@+-]+)/g,
|
|
425
|
+
)) {
|
|
426
|
+
addPlanPath(set, m[2], workspaceRoot);
|
|
427
|
+
}
|
|
428
|
+
return set;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function inProgressStatus(text) {
|
|
432
|
+
const s = String(text || "");
|
|
433
|
+
if (!s.startsWith("---\n")) return false;
|
|
434
|
+
const end = s.indexOf("\n---\n", 4);
|
|
435
|
+
if (end === -1) return false;
|
|
436
|
+
return /^status:\s*in-progress\s*$/m.test(s.slice(4, end));
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function loadInProgressPlans(workspaceRoot) {
|
|
440
|
+
const dir = path.resolve(workspaceRoot, ".tmp", "plans");
|
|
441
|
+
let names;
|
|
442
|
+
try {
|
|
443
|
+
names = fs.readdirSync(dir);
|
|
444
|
+
} catch {
|
|
445
|
+
return [];
|
|
446
|
+
}
|
|
447
|
+
const out = [];
|
|
448
|
+
for (const name of names) {
|
|
449
|
+
if (!name.endsWith(".md")) continue;
|
|
450
|
+
const abs = path.resolve(dir, name);
|
|
451
|
+
let text;
|
|
452
|
+
try {
|
|
453
|
+
text = fs.readFileSync(abs, "utf8");
|
|
454
|
+
} catch {
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
if (!inProgressStatus(text)) continue;
|
|
458
|
+
out.push({ abs, text });
|
|
459
|
+
}
|
|
460
|
+
return out;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function implementerWriteDeny(input, workspaceRoot) {
|
|
464
|
+
const ws = path.resolve(workspaceRoot);
|
|
465
|
+
const plans = loadInProgressPlans(ws);
|
|
466
|
+
const allow = new Set();
|
|
467
|
+
for (const p of plans) {
|
|
468
|
+
allow.add(p.abs);
|
|
469
|
+
for (const extracted of extractPlanPaths(p.text, ws)) {
|
|
470
|
+
allow.add(extracted);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
const hasInProgress = plans.length > 0;
|
|
474
|
+
for (const key of WRITE_PATH_FIELDS) {
|
|
475
|
+
if (typeof input[key] !== "string" || !input[key]) continue;
|
|
476
|
+
const abs = resolveWriteAbs(input[key], ws);
|
|
477
|
+
if (!abs) continue;
|
|
478
|
+
if (isUnderPlansDir(abs, ws)) continue;
|
|
479
|
+
if (allow.has(abs)) continue;
|
|
480
|
+
if (isUnsolicitedDocPath(abs) || hasInProgress) {
|
|
481
|
+
return { type: "deny", reason: REASON_IMPLEMENTER_WRITE };
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
|
|
381
487
|
/**
|
|
382
488
|
* @returns {null | { type: "deny", reason: string } | { type: "rewrite", updatedInput: object }}
|
|
383
489
|
*/
|
|
@@ -399,6 +505,10 @@ export function processFatTools(data) {
|
|
|
399
505
|
changed = true;
|
|
400
506
|
}
|
|
401
507
|
}
|
|
508
|
+
if (subagentTypeOf(data) === "implementer") {
|
|
509
|
+
const denied = implementerWriteDeny(next, ws);
|
|
510
|
+
if (denied) return denied;
|
|
511
|
+
}
|
|
402
512
|
return changed ? { type: "rewrite", updatedInput: next } : null;
|
|
403
513
|
}
|
|
404
514
|
const sub = subagentTypeOf(data);
|
|
@@ -410,6 +520,10 @@ export function processFatTools(data) {
|
|
|
410
520
|
const isGlob = GLOB_TOOLS.has(toolKey);
|
|
411
521
|
const isBash = BASH_TOOLS.has(toolKey);
|
|
412
522
|
|
|
523
|
+
if (sub === "thinker" && (isGrep || isGlob || isBash)) {
|
|
524
|
+
return { type: "deny", reason: REASON_THINKER_TOOLS };
|
|
525
|
+
}
|
|
526
|
+
|
|
413
527
|
if (isRead || isGrep || isGlob) {
|
|
414
528
|
for (const v of collectPathValues(input)) {
|
|
415
529
|
if (pathIsDenied(v)) return { type: "deny", reason: REASON_DENYLIST };
|