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
1 change: 1 addition & 0 deletions .ai-ack
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
I used AI assistance and reviewed the generated changes before submission.
2 changes: 1 addition & 1 deletion docs/adr/0012-concise-technical-prose-for-agent-sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Date: 2026-05-19

Status: Accepted
Status: Superseded by [ADR-0013](0013-remove-optional-response-skill.md)

Supersedes: [ADR-0003](0003-caveman-voice-for-rules.md)

Expand Down
40 changes: 40 additions & 0 deletions docs/adr/0013-remove-optional-response-skill.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# ADR-0013: Remove optional caveman skill

Date: 2026-06-30

Status: Accepted

Supersedes: [ADR-0012](0012-concise-technical-prose-for-agent-sources.md)

## Context

ADR-0012 moved source authoring to concise normal prose but left the optional
`caveman` skill installed for users who explicitly requested a terse response
mode. That optional skill still created an active route in the skills catalog and
native skill outputs.

The harness goal is now narrower: install engineering practices, not response
personas. Concise prose remains a source-writing rule, but style-mode state is
better left to each agent or user session.

## Decision

Remove the `caveman` skill from `source/skills/`, the skills catalog, and routing
fixtures. Generated agent outputs must not install or advertise a `caveman`
skill.

Historical ADRs remain unchanged except for status links. They record the path
from compressed source prose to concise normal prose, then to removing the
optional skill.

## Consequences

**Positive.** Installed harness output no longer activates or advertises a
persona-style skill. Skill routing stays focused on engineering tasks.

**Negative.** Users who liked the packaged terse response mode must configure it
outside the harness.

**Mitigation.** Keep concise technical prose in source files and generated rules.
If many users ask for the removed skill again, restore it through a new ADR and a
normal skill/catalog/eval change.
4 changes: 3 additions & 1 deletion docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ Implement `scripts/adapters/<agent>.py` with a class exposing `name: str` and `w

## Voice

Source files use concise technical prose. Keep them short, but do not force caveman grammar. README, this file, `docs/style-overview.md`, and ADRs also use normal prose so contributors have one writing style across the repo.
Source files use concise technical prose. Keep them short and use normal grammar
where it improves clarity. README, this file, `docs/style-overview.md`, and ADRs
use the same prose style so contributors have one writing style across the repo.

## ADRs

Expand Down
9 changes: 3 additions & 6 deletions docs/style-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,7 @@ in front of you.
## Why concise prose

Once an agent has the practices in context, every extra token of preamble costs
money and adds noise. The harness still removes filler, hedging, and throat-clearing,
but it no longer requires full caveman grammar. Concise normal prose keeps the token
budget low while preserving sequence, danger, and ownership where those details
matter.
money and adds noise. The harness removes filler, hedging, and throat-clearing
while keeping normal grammar where sequence, danger, and ownership matter.

See `docs/adr/0012-concise-technical-prose-for-agent-sources.md` for the current
decision. ADR-0003 records the earlier caveman default.
See `docs/adr/0013-remove-optional-response-skill.md` for the current decision.
2 changes: 2 additions & 0 deletions scripts/adapters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
WriteOp,
apply_op,
replace_managed_section,
stale_managed_delete_ops,
strip_managed_section,
walk_managed_files,
)
Expand Down Expand Up @@ -38,6 +39,7 @@
"WriteOp",
"apply_op",
"replace_managed_section",
"stale_managed_delete_ops",
"strip_managed_section",
"walk_managed_files",
]
12 changes: 11 additions & 1 deletion scripts/adapters/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from __future__ import annotations

import contextlib
from collections.abc import Iterator
from collections.abc import Iterable, Iterator
from dataclasses import dataclass, field
from pathlib import Path
from typing import Protocol
Expand Down Expand Up @@ -145,3 +145,13 @@ def walk_managed_files(directory: Path) -> Iterator[Path]:
yield path
except OSError:
continue


def stale_managed_delete_ops(directory: Path, keep_paths: Iterable[Path]) -> list[WriteOp]:
"""Delete managed files under `directory` that current install no longer writes."""
keep = set(keep_paths)
return [
WriteOp(path=path, content="", action="delete")
for path in walk_managed_files(directory)
if path not in keep
]
6 changes: 6 additions & 0 deletions scripts/adapters/claude.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
render_command_markdown,
replace_managed_section,
skill_bundle_ops,
stale_managed_delete_ops,
strip_managed_section,
walk_managed_files,
)
Expand Down Expand Up @@ -48,6 +49,11 @@ def write_all(
if rules:
report.add(self._claude_md_op(rules, root))

keep = [op.path for op in report.ops]
for directory in (root / "skills", root / "commands"):
for op in stale_managed_delete_ops(directory, keep):
report.add(op)

if not dry_run:
for op in report.ops:
apply_op(op)
Expand Down
5 changes: 5 additions & 0 deletions scripts/adapters/codex.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
apply_op,
replace_managed_section,
skill_bundle_ops,
stale_managed_delete_ops,
strip_managed_section,
walk_managed_files,
)
Expand Down Expand Up @@ -90,6 +91,10 @@ def write_all(

prune_merged_agents_md(target_root / "AGENTS.md", report)

keep = [op.path for op in report.ops]
for op in stale_managed_delete_ops(target_root / ".agents" / "skills", keep):
report.add(op)

if not dry_run:
for op in report.ops:
apply_op(op)
Expand Down
6 changes: 6 additions & 0 deletions scripts/adapters/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
apply_op,
render_command_markdown,
skill_bundle_ops,
stale_managed_delete_ops,
walk_managed_files,
)
from scripts.source import Source
Expand Down Expand Up @@ -46,6 +47,11 @@ def write_all(
elif s.kind == "command":
report.add(self._command_op(s, root))

keep = [op.path for op in report.ops]
for directory in (root / "rules", root / "skills", root / "commands"):
for op in stale_managed_delete_ops(directory, keep):
report.add(op)

if not dry_run:
for op in report.ops:
apply_op(op)
Expand Down
6 changes: 6 additions & 0 deletions scripts/adapters/opencode.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
apply_op,
replace_managed_section,
skill_bundle_ops,
stale_managed_delete_ops,
strip_managed_section,
walk_managed_files,
)
Expand Down Expand Up @@ -48,6 +49,11 @@ def write_all(
if rules:
report.add(self._agents_md_op(rules, root))

keep = [op.path for op in report.ops]
for directory in (root / "skills", root / "commands"):
for op in stale_managed_delete_ops(directory, keep):
report.add(op)

if not dry_run:
for op in report.ops:
apply_op(op)
Expand Down
6 changes: 6 additions & 0 deletions scripts/adapters/vibe.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
WriteOp,
apply_op,
render_aux_markdown,
stale_managed_delete_ops,
walk_managed_files,
)
from scripts.source import Source
Expand Down Expand Up @@ -72,6 +73,11 @@ def write_all(
for op in _vibe_ops(s, root / subdir):
report.add(op)

keep = [op.path for op in report.ops]
for subdir in ("rules", "skills", "commands"):
for op in stale_managed_delete_ops(root / subdir, keep):
report.add(op)

if not dry_run:
for op in report.ops:
apply_op(op)
Expand Down
2 changes: 1 addition & 1 deletion scripts/lint_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- Skill bundles: kind skill, id matches directory, aux files plain markdown
(see scripts/lint_bundle.py).

Caveman quality is NOT linted — that is a review concern.
Prose quality is NOT linted — that is a review concern.
"""

from __future__ import annotations
Expand Down
2 changes: 0 additions & 2 deletions source/evals/skill-routing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ cases:
load:
- data-privacy-and-retention
- threat-modeling
do_not_load:
- caveman

- id: slow-query
prompt: This LEFT JOIN on orders is taking 3s; suggest indexes.
Expand Down
1 change: 0 additions & 1 deletion source/rules/skills-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ guidance intact. Exception: skills whose topic is the language or format itself
| capacity-and-cost-engineering | sizing infrastructure for launch; planning capacity for peak load; setting up cost budgets or guardrails; running a load test |
| canonical-reference-in-docstrings | documenting an algorithm, protocol, or formula |
| ci-pipeline-design | designing or improving a CI/CD pipeline; setting up or modifying GitHub Actions or CI configuration |
| caveman | optional terse response style when the user explicitly asks for caveman mode or extreme brevity |
| centralized-ui-components | building UI components; enforcing one catalog source before page use |
| code-review-and-quality | reviewing a diff or PR across six axes |
| code-simplification | reducing complexity in tested code, one change at a time |
Expand Down
133 changes: 0 additions & 133 deletions source/skills/caveman.md

This file was deleted.

Loading
Loading