From ed133cc11614bd132f9475adc701a5182fe5b4e5 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Sun, 6 Sep 2026 13:37:47 -0400 Subject: [PATCH] enhance(#3085): add Grep to allowed-tools for 21 skills (#4397) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * enhance(#3085): add Grep to allowed-tools for 21 skills 29 of 71 skills omit Grep from allowed-tools, forcing Bash grep for structured search instead of the dedicated tool. Adds Grep to the 21-skill subset confirmed safe in prior review (excludes the 6 gsd-ns-* dispatchers, gsd-help, and gsd-surface, which have no plausible structured-search need). Hand-edits commands/gsd/*.md only; skills/*/SKILL.md is regenerated via `npm run gen:plugin-skills` from that source. Updates the one hardcoded copilot-install test assertion affected by gsd-health's new tool order. * chore(#3085): backfill changeset PR number Co-Authored-By: Claude Sonnet 5 * test(#2618): assert the Needs clause on the structured field, not the path-length-dependent bullet The bullet embeds the todo file's ABSOLUTE path, so its total length varies by runner tmpdir: on macOS CI, /private/var/folders/… plus the test harness's gsd-test-run-* wrapper pushed the full bullet to 244 chars — past renderPendingTodoBullet's intended 240-char cap, whose documented first degradation step drops the Needs clause. The product behavior is correct (#2618 design); the assertion was runner-dependent. The extraction is now pinned on json.todos[0].needs; the rendered-bullet shape stays covered by the path-independent title assertion and the renderer's own unit rows. Found blocking #4186's CI on the macOS shard (test landed 30 minutes earlier in b7406b293f / PR #4384). --------- Co-authored-by: sim Co-authored-by: Claude Sonnet 5 --- .changeset/calm-quails-snooze.md | 6 ++++++ commands/gsd/cleanup.md | 1 + commands/gsd/complete-milestone.md | 1 + commands/gsd/config.md | 1 + commands/gsd/debug.md | 1 + commands/gsd/graphify.md | 1 + commands/gsd/health.md | 1 + commands/gsd/mempalace-capture.md | 1 + commands/gsd/mempalace-recall.md | 1 + commands/gsd/new-milestone.md | 1 + commands/gsd/new-project.md | 1 + commands/gsd/next.md | 1 + commands/gsd/pause-work.md | 1 + commands/gsd/phase.md | 1 + commands/gsd/pr-branch.md | 1 + commands/gsd/resume-work.md | 1 + commands/gsd/review-backlog.md | 1 + commands/gsd/settings.md | 1 + commands/gsd/stats.md | 1 + commands/gsd/thread.md | 1 + commands/gsd/workspace.md | 1 + commands/gsd/workstreams.md | 1 + skills/gsd-cleanup/SKILL.md | 1 + skills/gsd-complete-milestone/SKILL.md | 1 + skills/gsd-config/SKILL.md | 1 + skills/gsd-debug/SKILL.md | 1 + skills/gsd-graphify/SKILL.md | 1 + skills/gsd-health/SKILL.md | 1 + skills/gsd-mempalace-capture/SKILL.md | 1 + skills/gsd-mempalace-recall/SKILL.md | 1 + skills/gsd-new-milestone/SKILL.md | 1 + skills/gsd-new-project/SKILL.md | 1 + skills/gsd-next/SKILL.md | 1 + skills/gsd-pause-work/SKILL.md | 1 + skills/gsd-phase/SKILL.md | 1 + skills/gsd-pr-branch/SKILL.md | 1 + skills/gsd-resume-work/SKILL.md | 1 + skills/gsd-review-backlog/SKILL.md | 1 + skills/gsd-settings/SKILL.md | 1 + skills/gsd-stats/SKILL.md | 1 + skills/gsd-thread/SKILL.md | 1 + skills/gsd-workspace/SKILL.md | 1 + skills/gsd-workstreams/SKILL.md | 1 + tests/copilot-install.test.cjs | 2 +- tests/state-todos-render.test.cjs | 14 ++++++++++++-- 45 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 .changeset/calm-quails-snooze.md diff --git a/.changeset/calm-quails-snooze.md b/.changeset/calm-quails-snooze.md new file mode 100644 index 000000000..c0962c607 --- /dev/null +++ b/.changeset/calm-quails-snooze.md @@ -0,0 +1,6 @@ +--- +type: Changed +pr: 4397 +--- + +**21 GSD skills now declare `Grep` in `allowed-tools`** — cleanup, complete-milestone, config, debug, graphify, health, mempalace-capture, mempalace-recall, new-milestone, new-project, next, pause-work, phase, pr-branch, resume-work, review-backlog, settings, stats, thread, workspace, and workstreams can now use the dedicated structured-search tool instead of shelling out through Bash grep. diff --git a/commands/gsd/cleanup.md b/commands/gsd/cleanup.md index 51fd13cc8..813daf2cd 100644 --- a/commands/gsd/cleanup.md +++ b/commands/gsd/cleanup.md @@ -5,6 +5,7 @@ allowed-tools: - Read - Write - Bash + - Grep - AskUserQuestion requires: [phase] --- diff --git a/commands/gsd/complete-milestone.md b/commands/gsd/complete-milestone.md index 20e73adf0..38188cbda 100644 --- a/commands/gsd/complete-milestone.md +++ b/commands/gsd/complete-milestone.md @@ -7,6 +7,7 @@ allowed-tools: - Read - Write - Bash + - Grep requires: [audit-milestone, discuss-phase, execute-phase, new-milestone, phase, plan-phase, stats, update] --- diff --git a/commands/gsd/config.md b/commands/gsd/config.md index b080c0dae..c0c67c3e7 100644 --- a/commands/gsd/config.md +++ b/commands/gsd/config.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep - AskUserQuestion requires: [code-review, review, settings] --- diff --git a/commands/gsd/debug.md b/commands/gsd/debug.md index c339fd593..55e712c1e 100644 --- a/commands/gsd/debug.md +++ b/commands/gsd/debug.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep - Agent - AskUserQuestion --- diff --git a/commands/gsd/graphify.md b/commands/gsd/graphify.md index 8be09ad98..c9b14fa71 100644 --- a/commands/gsd/graphify.md +++ b/commands/gsd/graphify.md @@ -5,6 +5,7 @@ argument-hint: "[build|query |status|diff]" allowed-tools: - Read - Bash + - Grep requires: [config, fast, phase, update] --- diff --git a/commands/gsd/health.md b/commands/gsd/health.md index 81b8df0e2..148205899 100644 --- a/commands/gsd/health.md +++ b/commands/gsd/health.md @@ -5,6 +5,7 @@ argument-hint: "[--repair] [--context]" allowed-tools: - Read - Bash + - Grep - Write - AskUserQuestion requires: [thread] diff --git a/commands/gsd/mempalace-capture.md b/commands/gsd/mempalace-capture.md index 7a2537fc5..2cc5a9e01 100644 --- a/commands/gsd/mempalace-capture.md +++ b/commands/gsd/mempalace-capture.md @@ -5,6 +5,7 @@ argument-hint: "[CONTEXT.md|PLAN.md|SUMMARY.md]" allowed-tools: - Read - Bash + - Grep requires: [config] --- diff --git a/commands/gsd/mempalace-recall.md b/commands/gsd/mempalace-recall.md index f043be0a2..cc9ec2928 100644 --- a/commands/gsd/mempalace-recall.md +++ b/commands/gsd/mempalace-recall.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep requires: [config] --- diff --git a/commands/gsd/new-milestone.md b/commands/gsd/new-milestone.md index 5783c710c..6020c6bf4 100644 --- a/commands/gsd/new-milestone.md +++ b/commands/gsd/new-milestone.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep - Agent - AskUserQuestion requires: [new-project, phase, plan-phase] diff --git a/commands/gsd/new-project.md b/commands/gsd/new-project.md index 98b0d8469..273926012 100644 --- a/commands/gsd/new-project.md +++ b/commands/gsd/new-project.md @@ -5,6 +5,7 @@ argument-hint: "[--auto]" allowed-tools: - Read - Bash + - Grep - Write - Agent - AskUserQuestion diff --git a/commands/gsd/next.md b/commands/gsd/next.md index 8ca19c1a1..49d8541e9 100644 --- a/commands/gsd/next.md +++ b/commands/gsd/next.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Bash - Glob + - Grep - SlashCommand - AskUserQuestion --- diff --git a/commands/gsd/pause-work.md b/commands/gsd/pause-work.md index 4a1af80bb..d6a54759c 100644 --- a/commands/gsd/pause-work.md +++ b/commands/gsd/pause-work.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep requires: [phase, progress] --- diff --git a/commands/gsd/phase.md b/commands/gsd/phase.md index b5e2ba972..f5aff8d5a 100644 --- a/commands/gsd/phase.md +++ b/commands/gsd/phase.md @@ -7,6 +7,7 @@ allowed-tools: - Write - Bash - Glob + - Grep --- diff --git a/commands/gsd/pr-branch.md b/commands/gsd/pr-branch.md index 23a4e1f69..40d66988e 100644 --- a/commands/gsd/pr-branch.md +++ b/commands/gsd/pr-branch.md @@ -4,6 +4,7 @@ description: Create a clean PR branch by filtering out .planning/ commits — re argument-hint: "[target branch, default: main]" allowed-tools: - Bash + - Grep - Read - AskUserQuestion requires: [review] diff --git a/commands/gsd/resume-work.md b/commands/gsd/resume-work.md index e049dfb37..990cea719 100644 --- a/commands/gsd/resume-work.md +++ b/commands/gsd/resume-work.md @@ -4,6 +4,7 @@ description: Resume work from previous session with full context restoration allowed-tools: - Read - Bash + - Grep - Write - AskUserQuestion - SlashCommand diff --git a/commands/gsd/review-backlog.md b/commands/gsd/review-backlog.md index c72a457eb..7da8cc7b1 100644 --- a/commands/gsd/review-backlog.md +++ b/commands/gsd/review-backlog.md @@ -5,6 +5,7 @@ allowed-tools: - Read - Write - Bash + - Grep - AskUserQuestion requires: [phase, review] --- diff --git a/commands/gsd/settings.md b/commands/gsd/settings.md index 740371023..18cc3889e 100644 --- a/commands/gsd/settings.md +++ b/commands/gsd/settings.md @@ -5,6 +5,7 @@ allowed-tools: - Read - Write - Bash + - Grep - AskUserQuestion requires: [quick] --- diff --git a/commands/gsd/stats.md b/commands/gsd/stats.md index ebdba3cca..489f95566 100644 --- a/commands/gsd/stats.md +++ b/commands/gsd/stats.md @@ -5,6 +5,7 @@ effort: low allowed-tools: - Read - Bash + - Grep requires: [phase, progress] --- diff --git a/commands/gsd/thread.md b/commands/gsd/thread.md index 13cdb1cde..3335a9d98 100644 --- a/commands/gsd/thread.md +++ b/commands/gsd/thread.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep requires: [phase] --- diff --git a/commands/gsd/workspace.md b/commands/gsd/workspace.md index 749251b38..d196f0151 100644 --- a/commands/gsd/workspace.md +++ b/commands/gsd/workspace.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep - AskUserQuestion --- diff --git a/commands/gsd/workstreams.md b/commands/gsd/workstreams.md index 2c6bf22c4..414bff64a 100644 --- a/commands/gsd/workstreams.md +++ b/commands/gsd/workstreams.md @@ -4,6 +4,7 @@ description: Manage parallel workstreams — list, create, switch, status, progr allowed-tools: - Read - Bash + - Grep requires: [new-milestone, phase, progress, resume-work] --- diff --git a/skills/gsd-cleanup/SKILL.md b/skills/gsd-cleanup/SKILL.md index f5e8822c6..6e858c30b 100644 --- a/skills/gsd-cleanup/SKILL.md +++ b/skills/gsd-cleanup/SKILL.md @@ -5,6 +5,7 @@ allowed-tools: - Read - Write - Bash + - Grep - AskUserQuestion --- diff --git a/skills/gsd-complete-milestone/SKILL.md b/skills/gsd-complete-milestone/SKILL.md index 10d940495..48248d83d 100644 --- a/skills/gsd-complete-milestone/SKILL.md +++ b/skills/gsd-complete-milestone/SKILL.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep --- diff --git a/skills/gsd-config/SKILL.md b/skills/gsd-config/SKILL.md index 2e2bbc008..30efc9b95 100644 --- a/skills/gsd-config/SKILL.md +++ b/skills/gsd-config/SKILL.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep - AskUserQuestion --- diff --git a/skills/gsd-debug/SKILL.md b/skills/gsd-debug/SKILL.md index 0fc9b0404..6cfe24ac6 100644 --- a/skills/gsd-debug/SKILL.md +++ b/skills/gsd-debug/SKILL.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep - Agent - AskUserQuestion --- diff --git a/skills/gsd-graphify/SKILL.md b/skills/gsd-graphify/SKILL.md index bf18826b3..786740c61 100644 --- a/skills/gsd-graphify/SKILL.md +++ b/skills/gsd-graphify/SKILL.md @@ -5,6 +5,7 @@ argument-hint: "[build|query |status|diff]" allowed-tools: - Read - Bash + - Grep --- diff --git a/skills/gsd-health/SKILL.md b/skills/gsd-health/SKILL.md index d52c09430..9d2b22252 100644 --- a/skills/gsd-health/SKILL.md +++ b/skills/gsd-health/SKILL.md @@ -5,6 +5,7 @@ argument-hint: "[--repair] [--context]" allowed-tools: - Read - Bash + - Grep - Write - AskUserQuestion --- diff --git a/skills/gsd-mempalace-capture/SKILL.md b/skills/gsd-mempalace-capture/SKILL.md index 3ca959181..337209f92 100644 --- a/skills/gsd-mempalace-capture/SKILL.md +++ b/skills/gsd-mempalace-capture/SKILL.md @@ -5,6 +5,7 @@ argument-hint: "[CONTEXT.md|PLAN.md|SUMMARY.md]" allowed-tools: - Read - Bash + - Grep --- diff --git a/skills/gsd-mempalace-recall/SKILL.md b/skills/gsd-mempalace-recall/SKILL.md index 40b619f16..466c0943b 100644 --- a/skills/gsd-mempalace-recall/SKILL.md +++ b/skills/gsd-mempalace-recall/SKILL.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep --- diff --git a/skills/gsd-new-milestone/SKILL.md b/skills/gsd-new-milestone/SKILL.md index aecac14ce..fe3611b9e 100644 --- a/skills/gsd-new-milestone/SKILL.md +++ b/skills/gsd-new-milestone/SKILL.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep - Agent - AskUserQuestion --- diff --git a/skills/gsd-new-project/SKILL.md b/skills/gsd-new-project/SKILL.md index bd62c32f0..b9892d5fe 100644 --- a/skills/gsd-new-project/SKILL.md +++ b/skills/gsd-new-project/SKILL.md @@ -5,6 +5,7 @@ argument-hint: "[--auto]" allowed-tools: - Read - Bash + - Grep - Write - Agent - AskUserQuestion diff --git a/skills/gsd-next/SKILL.md b/skills/gsd-next/SKILL.md index fcd0b05b2..4ab9e370d 100644 --- a/skills/gsd-next/SKILL.md +++ b/skills/gsd-next/SKILL.md @@ -5,6 +5,7 @@ allowed-tools: - Read - Bash - Glob + - Grep - SlashCommand - AskUserQuestion --- diff --git a/skills/gsd-pause-work/SKILL.md b/skills/gsd-pause-work/SKILL.md index e1962277a..f92c3e0a7 100644 --- a/skills/gsd-pause-work/SKILL.md +++ b/skills/gsd-pause-work/SKILL.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep --- diff --git a/skills/gsd-phase/SKILL.md b/skills/gsd-phase/SKILL.md index 2ce83adbf..73ce244e9 100644 --- a/skills/gsd-phase/SKILL.md +++ b/skills/gsd-phase/SKILL.md @@ -7,6 +7,7 @@ allowed-tools: - Write - Bash - Glob + - Grep --- diff --git a/skills/gsd-pr-branch/SKILL.md b/skills/gsd-pr-branch/SKILL.md index 0a0ad7aa0..00f8a926a 100644 --- a/skills/gsd-pr-branch/SKILL.md +++ b/skills/gsd-pr-branch/SKILL.md @@ -4,6 +4,7 @@ description: "Create a clean PR branch by filtering out .planning/ commits — r argument-hint: "[target branch, default: main]" allowed-tools: - Bash + - Grep - Read - AskUserQuestion --- diff --git a/skills/gsd-resume-work/SKILL.md b/skills/gsd-resume-work/SKILL.md index 66dd1c544..12838e654 100644 --- a/skills/gsd-resume-work/SKILL.md +++ b/skills/gsd-resume-work/SKILL.md @@ -4,6 +4,7 @@ description: "Resume work from previous session with full context restoration" allowed-tools: - Read - Bash + - Grep - Write - AskUserQuestion - SlashCommand diff --git a/skills/gsd-review-backlog/SKILL.md b/skills/gsd-review-backlog/SKILL.md index 0a3f3a94f..58933d4ae 100644 --- a/skills/gsd-review-backlog/SKILL.md +++ b/skills/gsd-review-backlog/SKILL.md @@ -5,6 +5,7 @@ allowed-tools: - Read - Write - Bash + - Grep - AskUserQuestion --- diff --git a/skills/gsd-settings/SKILL.md b/skills/gsd-settings/SKILL.md index 86e176541..efc780e89 100644 --- a/skills/gsd-settings/SKILL.md +++ b/skills/gsd-settings/SKILL.md @@ -5,6 +5,7 @@ allowed-tools: - Read - Write - Bash + - Grep - AskUserQuestion --- diff --git a/skills/gsd-stats/SKILL.md b/skills/gsd-stats/SKILL.md index 57d0db82f..cb21f59f8 100644 --- a/skills/gsd-stats/SKILL.md +++ b/skills/gsd-stats/SKILL.md @@ -4,6 +4,7 @@ description: "Display project statistics — phases, plans, requirements, git me allowed-tools: - Read - Bash + - Grep --- diff --git a/skills/gsd-thread/SKILL.md b/skills/gsd-thread/SKILL.md index 215d6e5f3..793fcbc88 100644 --- a/skills/gsd-thread/SKILL.md +++ b/skills/gsd-thread/SKILL.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep --- diff --git a/skills/gsd-workspace/SKILL.md b/skills/gsd-workspace/SKILL.md index 8028f5abc..70ef63eaf 100644 --- a/skills/gsd-workspace/SKILL.md +++ b/skills/gsd-workspace/SKILL.md @@ -6,6 +6,7 @@ allowed-tools: - Read - Write - Bash + - Grep - AskUserQuestion --- diff --git a/skills/gsd-workstreams/SKILL.md b/skills/gsd-workstreams/SKILL.md index 08f8aec0c..dd5ec5617 100644 --- a/skills/gsd-workstreams/SKILL.md +++ b/skills/gsd-workstreams/SKILL.md @@ -4,6 +4,7 @@ description: "Manage parallel workstreams — list, create, switch, status, prog allowed-tools: - Read - Bash + - Grep --- diff --git a/tests/copilot-install.test.cjs b/tests/copilot-install.test.cjs index ccaa0bc24..a434f3fcd 100644 --- a/tests/copilot-install.test.cjs +++ b/tests/copilot-install.test.cjs @@ -743,7 +743,7 @@ describe('installRuntimeArtifacts (copilot integration)', () => { const skillContent = fs.readFileSync(path.join(skillsDir, 'gsd-health', 'SKILL.md'), 'utf8'); // Frontmatter format checks assert.ok(skillContent.startsWith('---\nname: gsd-health\n'), 'starts with name: gsd-health'); - assert.ok(skillContent.includes('allowed-tools: Read, Bash, Write, AskUserQuestion'), + assert.ok(skillContent.includes('allowed-tools: Read, Bash, Grep, Write, AskUserQuestion'), 'allowed-tools is comma-separated'); assert.ok(!skillContent.includes('allowed-tools:\n -'), 'NOT YAML multiline format'); // CONV-06/07 applied diff --git a/tests/state-todos-render.test.cjs b/tests/state-todos-render.test.cjs index d47b5db80..1852fb06f 100644 --- a/tests/state-todos-render.test.cjs +++ b/tests/state-todos-render.test.cjs @@ -319,9 +319,19 @@ test('cmdInitTodos: real todo file produces a rendered bullet via the CLI', (t) const json = runQueryInitTodos(dir); assert.equal(json.pending_read_ok, true); - assert.equal(json.todo_count, 1); assert.match(json.pending_todos_markdown, /Fix retry logic/); - assert.match(json.pending_todos_markdown, /Needs Add a max-attempts cap\.$/m); + // The Needs clause is asserted on the STRUCTURED field, not the rendered + // bullet: the bullet embeds the todo file's ABSOLUTE path, so its total + // length varies by runner tmpdir (macOS CI's /private/var/folders/… plus + // the test harness's gsd-test-run-* wrapper pushed the full bullet past + // renderPendingTodoBullet's intended 240-char cap, whose documented first + // degradation step is to drop the Needs clause — a correct product + // behavior this test must not depend on the runner's path length for). + assert.equal(json.todo_count, 1); + assert.ok(Array.isArray(json.todos) && json.todos.length === 1, 'todos array must carry the one todo'); + // (the raw field keeps the trailing period; only the rendered bullet + // strips it — renderPendingTodoBullet's own unit rows pin that.) + assert.equal(json.todos[0].needs, 'Add a max-attempts cap.'); }); test('cmdInitTodos: needs clause survives a deterministically long base path (#4384 macOS shape)', (t) => {