@lovrozagar/grunt 0.3.10 → 0.3.11

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.
@@ -14,10 +14,10 @@ inheritMcp: false
14
14
  ---
15
15
  Voice: `.rulesync/reference/output.md` — must follow.
16
16
 
17
- Implement specified solution. Never spawn. Never run for simple tool usage (grunt agent). Never plan (thinker agent).
17
+ 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).
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
+ 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.
21
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).
22
22
  Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
23
23
 
@@ -15,7 +15,7 @@ Always-do:
15
15
 
16
16
  | signal | next |
17
17
  |---|---|
18
- | create/change product files | spawn implementer (thinker then implementer if no spec). Never parent Write/Bash/Skill |
18
+ | create/change product files | small/simple or prompt-is-spec → implementer; large/complex + no spec → thinker then implementer. Never parent Write/Bash/Skill |
19
19
  | plan/spec ready + file writes remain | persist plan if needed; spawn implementer; do not recap-stop |
20
20
  | tools/facts/git/test/mechanical write | spawn grunt |
21
21
  | world fact | spawn grunt `job:web` |
@@ -35,7 +35,7 @@ Always-do:
35
35
 
36
36
  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.
37
37
  Spawn only `grunt` | `implementer` | `thinker`. Omit `model`. Isolation `none` unless asked. Never spawn `orchestrator`. Children never spawn.
38
- grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution (not the spec). thinker ← plan/deep reason/spec.
38
+ grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution or prompt-is-spec. thinker ← plan/deep reason.
39
39
  Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
40
40
  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.
41
41
  Child `need:` JSON → parse-need + parallel grunt; one `resume_from` + **new** verdicts only; max 3; no re-send task; no fresh-spawn.
@@ -17,10 +17,10 @@ effort: medium
17
17
  ---
18
18
  Voice: `.rulesync/reference/output.md` — must follow.
19
19
 
20
- Implement specified solution. Never spawn. Never run for simple tool usage (grunt agent). Never plan (thinker agent).
20
+ 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).
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
+ 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.
24
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).
25
25
  Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
26
26
 
@@ -18,7 +18,7 @@ Always-do:
18
18
 
19
19
  | signal | next |
20
20
  |---|---|
21
- | create/change product files | spawn implementer (thinker then implementer if no spec). Never parent Write/Bash/Skill |
21
+ | create/change product files | small/simple or prompt-is-spec → implementer; large/complex + no spec → thinker then implementer. Never parent Write/Bash/Skill |
22
22
  | plan/spec ready + file writes remain | persist plan if needed; spawn implementer; do not recap-stop |
23
23
  | tools/facts/git/test/mechanical write | spawn grunt |
24
24
  | world fact | spawn grunt `job:web` |
@@ -38,7 +38,7 @@ Always-do:
38
38
 
39
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. 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.
40
40
  Spawn only `grunt` | `implementer` | `thinker`. Omit `model`. Isolation `none` unless asked. Never spawn `orchestrator`. Children never spawn.
41
- grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution (not the spec). thinker ← plan/deep reason/spec.
41
+ grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution or prompt-is-spec. thinker ← plan/deep reason.
42
42
  Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
43
43
  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.
44
44
  Child `need:` JSON → parse-need + parallel grunt; one `resume_from` + **new** verdicts only; max 3; no re-send task; no fresh-spawn.
@@ -7,10 +7,10 @@ approval_policy = "never"
7
7
  developer_instructions = '''
8
8
  Voice: `.rulesync/reference/output.md` — must follow.
9
9
 
10
- Implement specified solution. Never spawn. Never run for simple tool usage (grunt agent). Never plan (thinker agent).
10
+ 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).
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
+ 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.
14
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).
15
15
  Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
16
16
 
@@ -12,7 +12,7 @@ Always-do:
12
12
 
13
13
  | signal | next |
14
14
  |---|---|
15
- | create/change product files | spawn implementer (thinker then implementer if no spec). Never parent Write/Bash/Skill |
15
+ | create/change product files | small/simple or prompt-is-spec → implementer; large/complex + no spec → thinker then implementer. Never parent Write/Bash/Skill |
16
16
  | plan/spec ready + file writes remain | persist plan if needed; spawn implementer; do not recap-stop |
17
17
  | tools/facts/git/test/mechanical write | spawn grunt |
18
18
  | world fact | spawn grunt `job:web` |
@@ -32,7 +32,7 @@ Always-do:
32
32
 
33
33
  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.
34
34
  Spawn only `grunt` | `implementer` | `thinker`. Omit `model`. Isolation `none` unless asked. Never spawn `orchestrator`. Children never spawn.
35
- grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution (not the spec). thinker ← plan/deep reason/spec.
35
+ grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution or prompt-is-spec. thinker ← plan/deep reason.
36
36
  Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
37
37
  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.
38
38
  Child `need:` JSON → parse-need + parallel grunt; one `resume_from` + **new** verdicts only; max 3; no re-send task; no fresh-spawn.
@@ -9,10 +9,10 @@ tools: read_file, grep, list_dir, write, search_replace, run_terminal_command, w
9
9
  ---
10
10
  Voice: `.rulesync/reference/output.md` — must follow.
11
11
 
12
- Implement specified solution. Never spawn. Never run for simple tool usage (grunt agent). Never plan (thinker agent).
12
+ 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).
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
+ 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.
16
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).
17
17
  Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
18
18
 
@@ -14,7 +14,7 @@ Always-do:
14
14
 
15
15
  | signal | next |
16
16
  |---|---|
17
- | create/change product files | spawn implementer (thinker then implementer if no spec). Never parent Write/Bash/Skill |
17
+ | create/change product files | small/simple or prompt-is-spec → implementer; large/complex + no spec → thinker then implementer. Never parent Write/Bash/Skill |
18
18
  | plan/spec ready + file writes remain | persist plan if needed; spawn implementer; do not recap-stop |
19
19
  | tools/facts/git/test/mechanical write | spawn grunt |
20
20
  | world fact | spawn grunt `job:web` |
@@ -34,7 +34,7 @@ Always-do:
34
34
 
35
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. 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.
36
36
  Spawn only `grunt` | `implementer` | `thinker`. Omit `model`. Isolation `none` unless asked. Never spawn `orchestrator`. Children never spawn.
37
- grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution (not the spec). thinker ← plan/deep reason/spec.
37
+ grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution or prompt-is-spec. thinker ← plan/deep reason.
38
38
  Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
39
39
  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.
40
40
  Child `need:` JSON → parse-need + parallel grunt; one `resume_from` + **new** verdicts only; max 3; no re-send task; no fresh-spawn.
@@ -34,9 +34,9 @@ import { logTelemetry, ORCHESTRATOR_LOGS_DIR } from "../../scripts/telemetry.mjs
34
34
  export const DENY_REASON =
35
35
  "First action=spawn implementer|grunt|thinker. Deny expected. Only /solo this session escapes.";
36
36
  export const STOP_REASONS = [
37
- "Spawn: ⚠/validate/sim findings or writes remain or parent just tried to Write → spawn implementer. Else facts → grunt. Else no spec → thinker. Else recap `[orchestrator]:` one-line.",
38
- "Still spawn: ⚠/validate/sim findings or writes remain or parent just tried to Write → spawn implementer. Else facts → grunt. Else no spec → thinker. Else recap `[orchestrator]:` one-line.",
39
- "Last spawn: ⚠/validate/sim findings or writes remain or parent just tried to Write → spawn implementer. Else facts → grunt. Else no spec → thinker. Else recap `[orchestrator]:` one-line.",
37
+ "Spawn: ⚠/validate/sim findings or writes remain or parent just tried to Write → spawn implementer. Else facts → grunt. Else large/complex + no spec → thinker. Else small/simple/defined → implementer. Else recap `[orchestrator]:` one-line.",
38
+ "Still spawn: ⚠/validate/sim findings or writes remain or parent just tried to Write → spawn implementer. Else facts → grunt. Else large/complex + no spec → thinker. Else small/simple/defined → implementer. Else recap `[orchestrator]:` one-line.",
39
+ "Last spawn: ⚠/validate/sim findings or writes remain or parent just tried to Write → spawn implementer. Else facts → grunt. Else large/complex + no spec → thinker. Else small/simple/defined → implementer. Else recap `[orchestrator]:` one-line.",
40
40
  ];
41
41
  const TRANSCRIPT_TAIL_BYTES = 512 * 1024;
42
42
  const PARENT_TOOLS = new Set([
@@ -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.
@@ -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` |
@@ -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` |
@@ -31,10 +31,10 @@ 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
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
+ 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
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).
39
39
  Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
40
40
 
@@ -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` |
@@ -60,7 +60,7 @@ Always-do:
60
60
 
61
61
  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
62
  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.
63
+ grunt ← tools. World fact → grunt `job: web`. Never memory. implementer ← specified solution or prompt-is-spec. thinker ← plan/deep reason.
64
64
  Child prompt first sentence only: `You are {agent} subagent.` Then task + abs paths + verdicts only.
65
65
  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
66
  Child `need:` JSON → parse-need + parallel grunt; one `resume_from` + **new** verdicts only; max 3; no re-send task; no fresh-spawn.
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` |
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` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovrozagar/grunt",
3
- "version": "0.3.10",
3
+ "version": "0.3.11",
4
4
  "description": "Multi-agent orchestrator SoT — deep-merge rulesync trees, product scripts, and generate pipeline into a consumer repo",
5
5
  "keywords": [
6
6
  "agents",
@@ -510,7 +510,20 @@ function loadInProgressPlans(workspaceRoot) {
510
510
  return out;
511
511
  }
512
512
 
513
- function implementerWriteDeny(input, workspaceRoot) {
513
+ function specTextOf(data) {
514
+ if (!data || typeof data !== "object" || Array.isArray(data)) return "";
515
+ const parts = [];
516
+ for (const k of ["prompt", "userPrompt", "user_prompt", "content"]) {
517
+ if (typeof data[k] === "string" && data[k]) parts.push(data[k]);
518
+ }
519
+ const agent = data.agent;
520
+ if (agent && typeof agent === "object" && !Array.isArray(agent)) {
521
+ if (typeof agent.prompt === "string" && agent.prompt) parts.push(agent.prompt);
522
+ }
523
+ return parts.join("\n");
524
+ }
525
+
526
+ function implementerWriteDeny(input, workspaceRoot, data) {
514
527
  const ws = path.resolve(workspaceRoot);
515
528
  const plans = loadInProgressPlans(ws);
516
529
  const allow = new Set();
@@ -520,14 +533,16 @@ function implementerWriteDeny(input, workspaceRoot) {
520
533
  allow.add(extracted);
521
534
  }
522
535
  }
523
- const hasInProgress = plans.length > 0;
536
+ const promptPaths = extractPlanPaths(specTextOf(data), ws);
537
+ for (const abs of promptPaths) allow.add(abs);
538
+ const restrictive = promptPaths.size > 0;
524
539
  for (const key of WRITE_PATH_FIELDS) {
525
540
  if (typeof input[key] !== "string" || !input[key]) continue;
526
541
  const abs = resolveWriteAbs(input[key], ws);
527
542
  if (!abs) continue;
528
543
  if (isUnderPlansDir(abs, ws)) continue;
529
544
  if (allow.has(abs)) continue;
530
- if (isUnsolicitedDocPath(abs) || hasInProgress) {
545
+ if (isUnsolicitedDocPath(abs) || restrictive) {
531
546
  return { type: "deny", reason: REASON_IMPLEMENTER_WRITE };
532
547
  }
533
548
  }
@@ -556,7 +571,7 @@ export function processFatTools(data) {
556
571
  }
557
572
  }
558
573
  if (subagentTypeOf(data) === "implementer") {
559
- const denied = implementerWriteDeny(next, ws);
574
+ const denied = implementerWriteDeny(next, ws, data);
560
575
  if (denied) return denied;
561
576
  }
562
577
  return changed ? { type: "rewrite", updatedInput: next } : null;