Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions .agents/skills/implementation-plan-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,34 @@ gh auth login

## Workflow

1) Read the two inputs in full:
1) Prepare clean scratchpads:
- Before reading or listing any scratchpad files, run from this skill directory:

```bash
python scripts/prepare_scratchpads.py <plan-file>
```

- Use the printed `OK <scratchpad-path>` directory for all scratchpads in this review.
- Existing scratchpads are stale working artifacts; never read or preserve them for a new review.
- If the script reports `ERROR`, stop and report the failure.

2) Read the two inputs in full:
- Plan file
- Issue description file (or the fetched `/tmp/issue.md`)

2) Apply versioning neutrality policy:
3) Apply versioning neutrality policy:
- Do **not** request a missing version bump (package version, `server.json`, manifests, etc.) unless a repo rule, user instruction, release plan, or issue text explicitly requires one.
- Do **not** suggest removing version bump steps merely because the issue does not mention versioning. Issues usually describe the problem, motivation, or code-level improvement; they are not expected to spell out release mechanics.
- If the plan already includes version bump steps, review them only for correctness and consistency with applicable repo rules: required files, matching version strings, valid version format, and no unrelated version/manifests changed.
- Raise a versioning finding only when the plan's versioning steps are internally inconsistent, contradict explicit requirements, or are objectively attached to the wrong files/surfaces.

3) Apply review-noise policy:
4) Apply review-noise policy:
- Do not raise findings only because an implementation plan omits developer execution mechanics such as checking `/.dockerenv`, choosing host vs devcontainer command prefixes, or spelling out both command variants.
- Do not teach command invocation mechanics in recommendations.
- Review verification semantically: required test/lint/integration categories, targets, and coverage, not how a developer invokes commands in their environment.
- Still flag objectively wrong verification scope, such as requiring only a narrow test subset when repo rules require the full default suite.

4) Validate codebase reality (start targeted, expand as needed):
5) Validate codebase reality (start targeted, expand as needed):
- Start by finding referenced modules/configs/env vars/tests with `rg` (fast and low-noise).
- Prefer opening the minimal set of files *first* to confirm patterns and naming, but broaden freely if you suspect hidden coupling or cross-cutting behavior (e.g., shared helpers, config loading, response models, pagination, truncation).
- If the plan touches MCP tools, REST API, docs, or tests, cross-check relevant `.cursor/rules/*.mdc` guidance.
Expand All @@ -57,10 +68,8 @@ rg -n "ServerConfig\\(|BaseSettings\\(|BLOCKSCOUT_" blockscout_mcp_server/config
rg -n "pytest\\.mark\\.integration|tests/integration|tests/tools" tests -S
```

5) Ground findings with scratchpads:
- Before finalizing §4 comments, create a scratchpad directory next to the implementation plan file:
- General rule: `<plan directory>/<plan filename without final extension>-scratchpads/`
- Example: `.ai/impl_plans/issue-375.md` → `.ai/impl_plans/issue-375-scratchpads/`
6) Ground findings with scratchpads:
- Use only the clean scratchpad directory prepared in step 1.
- For each actionable candidate finding, create one deterministic scratchpad file in final report order:
- `finding-01-short-slug.md`
- `finding-02-short-slug.md`
Expand All @@ -80,7 +89,7 @@ Scratchpad discipline:
- Do not create scratchpads for pure summary text, obvious nits, or questions that require user/product input rather than code investigation.
- Do not use scratchpads to pad the report; use them only to make actionable recommendations more accurate.

6) Produce the review in the required format (next section).
7) Produce the review in the required format (next section).

## Required output format

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/usr/bin/env python3
"""Prepare a clean scratchpad directory for implementation-plan-review."""

from __future__ import annotations

import argparse
import shutil
import sys
from pathlib import Path

EXIT_OK = 0
EXIT_USAGE = 1
EXIT_ERROR = 2


def derive_scratchpad_dir(plan_path: Path) -> Path:
"""Derive the deterministic scratchpad directory for a plan file."""
if plan_path.name in {"", ".", ".."}:
msg = f"Unsafe plan filename: {plan_path}"
raise ValueError(msg)

scratchpad_name = f"{plan_path.stem}-scratchpads"
if scratchpad_name in {"", ".", ".."} or not scratchpad_name.endswith("-scratchpads"):
msg = f"Unsafe scratchpad directory name derived from: {plan_path.name}"
raise ValueError(msg)

return plan_path.parent / scratchpad_name


def prepare_scratchpads(plan_path: Path) -> Path:
"""Delete and recreate the scratchpad directory for a plan file."""
plan_path = plan_path.expanduser()
plan_parent = plan_path.parent

if not plan_parent.exists():
msg = f"Plan parent directory does not exist: {plan_parent}"
raise ValueError(msg)
if not plan_parent.is_dir():
msg = f"Plan parent path is not a directory: {plan_parent}"
raise ValueError(msg)
if not plan_path.exists():
msg = f"Plan file does not exist: {plan_path}"
raise ValueError(msg)
if not plan_path.is_file():
msg = f"Plan path is not a file: {plan_path}"
raise ValueError(msg)

scratchpad_dir = derive_scratchpad_dir(plan_path)
if scratchpad_dir.parent != plan_parent:
msg = f"Refusing scratchpad path outside the plan directory: {scratchpad_dir}"
raise ValueError(msg)

if scratchpad_dir.is_symlink():
msg = f"Refusing to remove symlink scratchpad path: {scratchpad_dir}"
raise ValueError(msg)

if scratchpad_dir.exists():
if not scratchpad_dir.is_dir():
msg = f"Scratchpad path exists and is not a directory: {scratchpad_dir}"
raise ValueError(msg)
shutil.rmtree(scratchpad_dir)

scratchpad_dir.mkdir()
return scratchpad_dir


def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Delete and recreate the deterministic scratchpad directory for an implementation plan."
)
parser.add_argument("plan_file", help="Path to the implementation plan file.")
return parser


def run_cli(argv: list[str] | None = None) -> int:
parser = build_parser()
try:
args = parser.parse_args(argv)
except SystemExit as exc:
return int(exc.code) if isinstance(exc.code, int) else EXIT_USAGE

try:
scratchpad_dir = prepare_scratchpads(Path(args.plan_file))
except ValueError as exc:
print(f"ERROR {exc}", file=sys.stderr)
return EXIT_ERROR

print(f"OK {scratchpad_dir}")
return EXIT_OK


if __name__ == "__main__":
raise SystemExit(run_cli())
3 changes: 3 additions & 0 deletions .agents/skills/plan-export/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ For each rule file:

### 3. Compose the Implementation Plan

**This skill is the complete and only source for the plan's format.** The template below, the slice-marker rules, and the `--inspect` validator in step 6 define every convention you need — section order, marker syntax, the shape of the verification command blocks, all of it. Because the format is fully specified here, you never need to look at another plan to copy its conventions, and you must not: do not open or grep any other file under `.ai/impl_plans/` or `temp/impl_plans/`. Reading a sibling plan does two kinds of harm — it spends context on a document irrelevant to this issue, and, more insidiously, it anchors you to another feature's scope, phasing, and wording, biasing the plan you're writing now. If you're unsure your markers are correct, don't compare against an example — write them per this template and let the step-6 `--inspect` check prove them. (The pattern examples this skill asks you to cite are *source and test files for this feature*, referenced by path — never other plans.)

Create a detailed Markdown document at `.ai/impl_plans/issue-$1.md` with the following structure.

**Slice markers — required.** Wrap every section in paired, namespaced HTML-comment markers so the plan can be sliced deterministically by `scripts/slice_impl_plan.py` (headings alone are unreliable — plans embed code blocks and exact documentation that legitimately contain `#`/`##` as content). Rules:
Expand Down Expand Up @@ -329,6 +331,7 @@ Awaiting your instructions to proceed.
- **Do NOT implement the plan** - only create the plan document
- **Slice markers are mandatory.** Wrap preamble / each phase / final checklist in paired `<!-- impl-plan:begin slug="…" -->` … `<!-- impl-plan:end slug="…" -->` markers (see step 3) and confirm the plan passes the step-6 `--inspect` self-check before handing back
- The plan must be self-contained and not assume access to conversation history
- **Never read other plans.** This SKILL.md fully defines the format; opening another `.ai/impl_plans/` or `temp/impl_plans/` file only burns context and biases this plan toward another feature (see step 3)
- **Only include phases with actual work** - do not create placeholder phases that say "no changes needed"
- **No code snippets** for functional changes or tests - explain WHAT and WHY instead
- Point to existing files as pattern examples (e.g., "follow the pattern in `tools/address/get_address_info.py`")
Expand Down
Loading