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
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ TDD required. Red → Green → Refactor. No production code without a failing t

**Brainstorming** (`skills/brainstorming`, superpowers' unmodified): these are the partner's preferences its *Where it goes* defers to.
- A change to the service's behaviour amends the spec: a dated **Amended** entry in its header, plus the sections it touches. A design doc of its own only for work the spec doesn't cover: `docs/specs/YYYY-MM-DD-<issue>-<topic>-design.md`, never `docs/superpowers/specs/`.
- `superpowers:<name>` means this repo's `skills/<name>`, whichever vendor it links. `superpowers:writing-plans` is gregoryfoster's `writing-plans`, which writes the plan above to `docs/plans/`; `superpowers:using-git-worktrees` is gregoryfoster's too (§ Conventions).
- `superpowers:<name>` means this repo's `skills/<name>`, whichever vendor it links. `superpowers:writing-plans` is gregoryfoster's `writing-plans`, which writes the plan above to `docs/plans/`; `superpowers:using-git-worktrees` is gregoryfoster's too (§ Conventions → Workflow).
- The builder check runs as written. On an amendment, hand it the spec and name the amended sections.
- Its sizes don't replace the rules above: a "small change" that is non-trivial still gets a plan, and every change goes issue → branch → PR.

## Environment & Tooling

Expand Down
6 changes: 5 additions & 1 deletion tests/test_skills.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,14 @@ def test_superpowers_invocations_resolve_here() -> None:
"""A superpowers skill's ``superpowers:<n>`` is ``skills/<n>``; AGENTS.md maps strays."""
agents = (ROOT / "AGENTS.md").read_text()
ours = [n for n in _names(SKILLS) if _vendor_of(n) == "obra-superpowers"]
# A dangling link globs nothing, and an empty scan passes: fail on it instead.
for n in ours:
assert (SKILLS / n / "SKILL.md").is_file(), (n, DOCTOR_HINT)
invoked = {
m
for n in ours
for m in re.findall(r"superpowers:([\w-]+)", (SKILLS / n / "SKILL.md").read_text())
for md in (SKILLS / n).rglob("*.md")
for m in re.findall(r"superpowers:([\w-]+)", md.read_text())
}
missing = sorted(n for n in invoked if not (SKILLS / n).exists())
assert not missing, missing
Expand Down
Loading