fix(ultraplan-local): v2.3.2 — skill-drafter slug-collision hint

skill-drafter now reads {catalog_root}/<slug>.md before writing its
draft and prepends a warning block to its confirmation output when
an existing skill would be overwritten during manual `mv` promotion.
The draft is still written to .drafts/<slug>.md — the check is a
hint, not a block.

Closes v2.3.0 dogfood finding (post_dogfood_findings[0]): the
drafter produced .drafts/hooks-pattern.md when an approved
hooks-pattern.md seed already existed, giving no signal that `mv`
during promotion would silently overwrite the seed. v2.3.1
introduced the qualified-slug mechanism to resolve such collisions;
v2.3.2 surfaces them at the right moment — before promotion.

Changes:
- agents/skill-drafter.md — new Step 2 between slug computation and
  source reading. Reads {catalog_root}/<slug>.md, inspects
  review_status, derives a kebab-case qualifier from the concept
  handle (or source basename fallback). Subsequent steps renumbered
  3→7. Output format gains Collision: field and optional warning
  block. New Hard Rule.
- tests/fixtures/skill-drafter/slug-collision-expected.md — reference
  fixture documenting expected confirmation shape across four
  scenarios (no collision, approved collision, soft pending
  collision, collision with no good qualifier). Skill-drafter is
  prompt-driven; fixture anchors shape for human verification and
  downstream parsers.
- CHANGELOG [2.3.2], plugin.json 2.3.1→2.3.2, README badge, plugin
  CLAUDE.md slug-convention Collision-hint bullet, marketplace root
  README summary, marketplace root CLAUDE.md plugin table.

Non-breaking. No frontmatter/drafts-layout/tool-scope/regex changes.
Existing pipelines see one extra field and an optional warning —
both purely additive.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-04-18 18:06:37 +02:00
commit efbb43094f
8 changed files with 276 additions and 11 deletions

View file

@ -0,0 +1,159 @@
# Skill-drafter slug-collision — expected output fixture
This fixture documents the expected confirmation-message shape from
`skill-drafter` when it detects a slug collision at the catalog root.
It is a reference fixture — not an auto-executed test — used to
verify the agent by running a synthetic scenario by hand and
comparing output against the shapes below.
## Scenario A — no collision (baseline)
### Synthetic input
- **Catalog root:** `skills/cc-architect-catalog/`
- **Concept JSON (from concept-extractor):**
```json
{
"cc_feature": "worktrees",
"layer": "pattern",
"concept": "parallel feature isolation",
"description": "Isolate concurrent feature work in per-task worktrees to avoid git race conditions.",
"source_path": "/tmp/worktrees-notes.md",
"out_of_scope": false
}
```
- **Catalog state at time of run:** no `worktrees-pattern.md` present
at catalog root (only `worktrees-reference.md`).
### Expected confirmation output
```
Drafted: /Users/…/skills/cc-architect-catalog/.drafts/worktrees-pattern.md
Word count: 312
Frontmatter: 9 fields, review_status=pending, ngram_overlap_score=null
Collision: none
Next: ip-hygiene-checker for IP scoring
```
No warning block. `Collision: none`.
## Scenario B — approved collision (primary case)
### Synthetic input
- **Catalog root:** `skills/cc-architect-catalog/`
- **Concept JSON:**
```json
{
"cc_feature": "hooks",
"layer": "pattern",
"concept": "observability progressive alerts",
"description": "Progressive-alert observability pattern for hook-driven telemetry.",
"source_path": "/tmp/hooks-telemetry-notes.md",
"out_of_scope": false
}
```
- **Catalog state:** `hooks-pattern.md` exists with
`review_status: approved` (the v2.3.0 seed).
### Expected confirmation output
```
⚠️ Slug collision at catalog root
Existing: skills/cc-architect-catalog/hooks-pattern.md (review_status=approved)
Draft: skills/cc-architect-catalog/.drafts/hooks-pattern.md (this run)
Risk: manual `mv` during promotion will silently overwrite the existing file.
Suggested qualified slug: hooks-observability-pattern.md
Reason for qualifier: concept handle names "observability" as the named sub-pattern.
Action: rename the draft before `mv`, or revise the existing baseline.
Drafted: /Users/…/skills/cc-architect-catalog/.drafts/hooks-pattern.md
Word count: 287
Frontmatter: 9 fields, review_status=pending, ngram_overlap_score=null
Collision: approved
Next: ip-hygiene-checker for IP scoring
```
The warning is prepended. The draft is still written — the collision
check is a hint, not a block. `Collision: approved` appears in the
confirmation for downstream-log parsers.
## Scenario C — soft collision (pending existing)
### Synthetic input
- **Catalog state:** `subagents-pattern.md` exists with
`review_status: pending` (a prior draft that was `mv`-ed up without
the status being flipped, or a skill-factory auto-merged entry).
### Expected confirmation output
```
⚠️ Slug collision at catalog root
Existing: skills/cc-architect-catalog/subagents-pattern.md (review_status=pending)
Draft: skills/cc-architect-catalog/.drafts/subagents-pattern.md (this run)
Risk: manual `mv` during promotion will silently overwrite the existing file.
Suggested qualified slug: subagents-delegation-pattern.md
Reason for qualifier: concept handle centers on "delegation chains".
Action: rename the draft before `mv`, or revise the existing baseline.
Drafted: /Users/…/skills/cc-architect-catalog/.drafts/subagents-pattern.md
Word count: 256
Frontmatter: 9 fields, review_status=pending, ngram_overlap_score=null
Collision: pending
Next: ip-hygiene-checker for IP scoring
```
`Collision: pending` signals a soft collision — the existing file is
not necessarily a guaranteed baseline. Reviewer decides.
## Scenario D — collision but no good qualifier
### Synthetic input
- **Concept handle:** `generic feature note` (no specific noun)
- **Catalog state:** `skills-reference.md` exists (approved).
### Expected confirmation output
```
⚠️ Slug collision at catalog root
Existing: skills/cc-architect-catalog/skills-reference.md (review_status=approved)
Draft: skills/cc-architect-catalog/.drafts/skills-reference.md (this run)
Risk: manual `mv` during promotion will silently overwrite the existing file.
Suggested qualified slug: none — reviewer must pick one manually.
Action: rename the draft before `mv`, or revise the existing baseline.
Drafted: /Users/…/skills/cc-architect-catalog/.drafts/skills-reference.md
Word count: 198
Frontmatter: 9 fields, review_status=pending, ngram_overlap_score=null
Collision: approved
Next: ip-hygiene-checker for IP scoring
```
The fallback line replaces the "Suggested qualified slug" value.
`Reason for qualifier` is omitted.
## How to verify against this fixture
This is not an auto-run test. To verify:
1. Stage a synthetic concept JSON matching one of the scenarios above.
2. Invoke `skill-drafter` via the `Agent` tool with the concept JSON,
source path, and catalog root.
3. Capture the confirmation output.
4. Compare structurally against the corresponding scenario. The exact
word counts and paths will differ; the warning block, collision
field, and suggested-slug line are the load-bearing shapes.
If a future change alters the confirmation format, update this file
alongside the agent prompt so the two remain in lockstep.
## Why a reference fixture and not a unit test
`skill-drafter` is a prompt-driven Sonnet agent. There is no in-repo
harness that executes prompts deterministically, so a unit test is
not practical. The reference fixture is the next-best anchor — it
documents the expected shape for human verification and for
downstream agents that parse the confirmation (e.g., the
skill-author-orchestrator's summary phase).