# Classification Bucket Catalog

The SSOT for occurrence buckets used by the `migration-classifier` (Phase 02) and consumed by `migration-cluster-worker` (Phase 04). Every occurrence of a `from_pattern` is assigned exactly ONE bucket from this catalog. The bucket name dictates the default transformation in `transform-rules.md`.

This file is the authoritative definition. If the catalog and the `migration-classifier.md` agent prompt disagree on a bucket's recognition heuristic, the agent prompt is canonical (it ships with the agent's tool whitelist); this catalog mirrors the agent's bucket set and explains the rationale for each.

---

## Table of Contents

1. [Bucket Inventory](#bucket-inventory)
2. [Recognition Heuristics](#recognition-heuristics)
3. [Per-Bucket Transformation Table](#per-bucket-transformation-table)
4. [DOC Sub-Discrimination](#doc-sub-discrimination)
5. [MIXED Files](#mixed-files)
6. [FILES-NEEDING-NO-EDIT](#files-needing-no-edit)
7. [Extending with Migration-Specific Buckets](#extending-with-migration-specific-buckets)
8. [Worked Recognition Examples](#worked-recognition-examples)

---

## Bucket Inventory

The classifier emits exactly six buckets. Every occurrence the classifier finds is assigned exactly ONE bucket; no occurrence is omitted.

| Bucket | Default disposition | Used by |
|--------|---------------------|---------|
| `READ-OP` | TRANSFORM | Phase 04 cluster workers |
| `LISTING` | TRANSFORM | Phase 04 cluster workers |
| `PATH-VALIDATION` | TRANSFORM | Phase 04 cluster workers |
| `DOC` | TRANSFORM current-state / LEAVE historical | Phase 04 cluster workers (with sub-discrimination) |
| `ALREADY-MIGRATED` | LEAVE | Phase 04 cluster workers |
| `EXCLUDED` | LEAVE (out of scope) | Phase 02 only; never reaches cluster workers as a transform candidate |

Bucket disposition is a CATALOG default — `transform-rules.md` Section 3 can override per-migration if the orchestrator and user agree.

---

## Recognition Heuristics

A bucket assignment is GROUNDED by matching the occurrence to ONE of the heuristics below. If two heuristics match, the higher-numbered bucket wins (PATH-VALIDATION over LISTING, LISTING over DOC) — the classifier records the rationale in the `quote` column of `classification.md`.

### Bucket 1 — `READ-OP`

**Definition:** A directive to *Read / load / open / parse* the `from_pattern` file.

**Recognition patterns:**

- `Read(file_path="…<from_pattern>")` — native-tool call.
- `Glob(pattern="…<from_pattern>")` whose intent is to find the one file (not to enumerate sibling files).
- Prose `Read <from_pattern>` or `Load <from_pattern>` as an imperative.
- `"<from_pattern>"` as an element of a `required_files`, `must_read`, or `inputs` array.

**Examples:**

```python
Read(file_path="devforgeai/specs/context/source-tree.md")          # READ-OP
required_files: ["tech-stack.md", "source-tree.md", "anti-patterns.md"]  # READ-OP for source-tree.md
"Read source-tree.md to confirm placement."                        # READ-OP
```

**Why TRANSFORM by default:** The consumer's intent is to obtain the artifact's content; if the artifact moved or was redistributed, the Read target must move with it.

### Bucket 2 — `LISTING`

**Definition:** The `from_pattern` appears in an ENUMERATION of related artifacts — context-file list, references table, comma-separated prose, table row.

**Recognition patterns:**

- A list/table/array enumerating related files where `<from_pattern>` is one element.
- Comma-separated prose: `A, B, <from_pattern>, C, D`.
- Markdown table row referencing the artifact alongside siblings.

**Examples:**

```markdown
The 6 context files: tech-stack.md, source-tree.md, dependencies.md, …  # LISTING

| File | Purpose |
|------|---------|
| `source-tree.md` | Directory governance |    # LISTING
```

**Why TRANSFORM by default:** An enumeration referencing the old name confuses readers who consult the new artifact.

### Bucket 3 — `PATH-VALIDATION`

**Definition:** Prose directing an agent to validate / check / verify / enforce file placement against the `from_pattern`.

**Recognition patterns:**

- "validate against `<from_pattern>`", "check `<from_pattern>` rules".
- "place files per `<from_pattern>` constraints".
- "the source of truth for directory rules is `<from_pattern>`".
- Agent prompt instructions naming `<from_pattern>` as a governance authority.

**Examples:**

```markdown
Output paths MUST be validated against source-tree.md.    # PATH-VALIDATION
Place new agents per source-tree.md § Agents.             # PATH-VALIDATION
The source-tree.md is the SSOT for directory layout.      # PATH-VALIDATION
```

**Why TRANSFORM by default:** Path validation is operationally load-bearing; pointing to the old artifact when the SSOT moved is a workflow break.

### Bucket 4 — `DOC`

**Definition:** Incidental mention — citation example, References list entry, descriptive prose, "Source: …" citation.

**Recognition patterns:**

- "Source: `<from_pattern>`, lines X-Y" — citation in the citation-requirements format.
- Reference table at the end of a file listing related artifacts.
- Descriptive prose explaining what the artifact contains (not directing an action).
- README-style narrative.

**Examples:**

```markdown
Source: source-tree.md, lines 12-14                       # DOC (citation)
See source-tree.md for details on directory layout.       # DOC (descriptive)
This skill is documented in source-tree.md.               # DOC
```

**Sub-discrimination:** DOC has a `DOC-historical` sub-disposition — see [DOC Sub-Discrimination](#doc-sub-discrimination) below.

**Why TRANSFORM current-state by default:** Citations and references stale when the artifact moves; readers who follow the citation hit a missing file.

### Bucket 5 — `ALREADY-MIGRATED`

**Definition:** The text ALREADY explains the migration / cites the new artifact + the ADR that superseded the old one. The migration has effectively already landed here — naive re-application would corrupt the explanation.

**Recognition patterns:**

- "`<from_pattern>` was retired per ADR-NNN" / "replaced by `<to_pattern>` (ADR-NNN)".
- "Use `<to_pattern>` instead of `<from_pattern>` — see ADR-NNN".
- Prose explicitly describing the FROM → TO transition with the superseding ADR named.

**Examples:**

```markdown
source-tree.md was retired in ADR-071; consult source-tree/ instead.   # ALREADY-MIGRATED
The legacy source-tree.md (superseded by ADR-071) is the basis for source-tree/.  # ALREADY-MIGRATED
```

**Why LEAVE:** This text is the public explanation of the migration; editing it removes the explanation. A file that mixes ALREADY-MIGRATED prose with not-yet-migrated occurrences appears in the classifier's MIXED list.

### Bucket 6 — `EXCLUDED`

**Definition:** The occurrence is in a file whose PATH matches an `EXCLUSIONS` pattern from `intent.json` — the file is out of migration scope by design.

**Recognition patterns:** Not based on occurrence content; based on the FILE PATH matching any exclusion glob (e.g. `_archive/`, `/plans/`, template paths).

**Examples (excluded paths):**

- `devforgeai/specs/_archive/*` — historical record snapshots.
- `.claude/plans/*` — execution plans (record-keeping).
- `spec-driven-system-architecture/assets/context-templates/*` — template trees that intentionally reference the old artifact.

**Why LEAVE:** Templates and archives reference the old name on purpose; touching them breaks template-driven generation or rewrites history.

---

## Per-Bucket Transformation Table

This is the default transformation table the catalog supplies to a fresh migration. `transform-rules.md` Section 3 may override any row per-migration after orchestrator/user discussion in Phase 03.

| Bucket | Default transformation directive |
|--------|----------------------------------|
| `READ-OP` | Replace the literal `<from_pattern>` inside `Read(file_path=…)` or array-element strings with the new target (`<to_pattern>` plus any required suffix like `/_manifest.json` for a `to_type=folder` migration). |
| `LISTING` | Pure noun-swap: `<from_pattern>` → `<to_pattern>`. |
| `PATH-VALIDATION` | Pure noun-swap, AND if the migration introduces a CLI alternative (e.g. `query-source-tree --validate-path`), the orchestrator-authored rule may recommend replacing the prose entirely. |
| `DOC` (current-state) | Pure noun-swap: `<from_pattern>` → `<to_pattern>`. |
| `DOC-historical` | LEAVE — historical records must read true at the time they were written. |
| `ALREADY-MIGRATED` | LEAVE. |
| `EXCLUDED` | LEAVE (file never opened). |

---

## DOC Sub-Discrimination

A DOC occurrence is `DOC-historical` (LEAVE) instead of current-state (TRANSFORM) when the surrounding sentence records a PAST event:

- A changelog row / Change Log table entry.
- A `MIGRATION-NOTES.md` historical entry.
- "STORY-NNN: …" or "ADR-NNN: …" provenance prose recording what was done.
- Retrospective / postmortem prose ("STORY-413 produced source-tree.md before ADR-071").

The classifier marks the disposition in the per-file table's `quote` column (e.g. `quote="STORY-413 produced source-tree.md before ADR-071"` → DOC-historical). The cluster worker applies the LEAVE disposition for any DOC occurrence the orchestrator's `transform-rules.md` Section 3 flagged as historical.

When a single file mixes current-state DOC with DOC-historical (e.g. a README that both cites the old artifact in a current-state Section AND lists the migration in a changelog), the classifier produces per-occurrence rows so the cluster worker handles each line independently.

---

## MIXED Files

A file is MIXED when it contains BOTH `ALREADY-MIGRATED` occurrences AND any other transformable bucket. A naive find-replace across the file would corrupt the already-migrated prose.

The classifier emits MIXED files in a dedicated section of `classification.md`. The cluster worker handles them line-by-line, applying TRANSFORM to non-ALREADY-MIGRATED occurrences and LEAVE to the ALREADY-MIGRATED ones — never `Edit(replace_all=true)` on a MIXED file.

Typical MIXED scenario: an ADR file that BOTH explains the migration in its Decision section (ALREADY-MIGRATED) AND lists the old artifact in its References section (LISTING / DOC).

---

## FILES-NEEDING-NO-EDIT

A file appears under FILES-NEEDING-NO-EDIT when every occurrence is `DOC-historical` or `ALREADY-MIGRATED` — no operational directive needs editing. Cluster workers skip these files entirely; they appear in the classification artifact for audit completeness.

---

## Extending with Migration-Specific Buckets

A migration may need a domain-specific bucket the 6-bucket catalog doesn't cover. Examples:

- `TEMPLATE-EXCLUDED` — pattern appears inside `{{TEMPLATE_VAR}}` interpolation that the template engine will resolve at install time. Disposition: LEAVE.
- `TEST-FIXTURE` — pattern appears in a `*.test.*` or `tests/*` golden file that tests the old behaviour. Disposition: LEAVE (test owns the assertion).
- `URL-CITATION` — pattern appears in an external URL the migration must not break (e.g. `github.com/.../source-tree.md` permalink). Disposition: LEAVE.

**Procedure for adding a migration-specific bucket:**

1. Discover the need during Phase 02 (the classifier returns MIXED / Uncertain calls that don't fit the 6 buckets).
2. The orchestrator and user discuss in Phase 03 and add a new bucket subsection to `transform-rules.md` Section 3 with its definition, recognition heuristic, and disposition.
3. The orchestrator's Phase 04 worker prompts reference the new bucket explicitly (it's in `transform-rules.md`, which workers read first).
4. The new bucket is local to the migration — not promoted to this catalog without a follow-up framework-level decision.

The 6-bucket catalog is the floor; per-migration extensions are documented in `transform-rules.md` and never bleed into other migrations.

---

## Worked Recognition Examples

### Example A — `source-tree.md` → `source-tree/`, file `.claude/skills/spec-driven-stories/SKILL.md`

```
Line 12: `Source: source-tree.md, lines 12-14`                        → DOC (current-state, citation)
Line 47: `tech-stack.md, source-tree.md, dependencies.md, …`          → LISTING
Line 89: `Read(file_path="devforgeai/specs/context/source-tree.md")`  → READ-OP
Line 142: `Validate path against source-tree.md.`                     → PATH-VALIDATION
Line 311 (Change Log): `2026-04-12 — STORY-413 promoted source-tree.md` → DOC-historical (LEAVE)
```

### Example B — `source-tree.md` → `source-tree/`, file `devforgeai/specs/adrs/ADR-071-source-tree-decomposition.md`

```
Line 8 (Decision): `source-tree.md retired; replaced by source-tree/ folder.` → ALREADY-MIGRATED (LEAVE)
Line 14 (References list): `Source: source-tree.md (legacy)`                  → ALREADY-MIGRATED (LEAVE)
```

The ADR is FILES-NEEDING-NO-EDIT — every occurrence is ALREADY-MIGRATED because the ADR IS the migration's explanation.

### Example C — `source-tree.md` → `source-tree/`, MIXED file

```
README.md
  Line 7  (current-state):  `Place new agents per source-tree.md.`     → PATH-VALIDATION (TRANSFORM)
  Line 41 (Change Log):     `2026-05-19 — source-tree.md retired.`     → DOC-historical (LEAVE)
  Line 88 (References):     `See source-tree/ for the new artifact.`   → ALREADY-MIGRATED (LEAVE)
```

This file is MIXED — the cluster worker edits Line 7 only, leaves Lines 41 and 88 untouched, and never uses `replace_all=true`.

---

## References

- `migration-classifier.md` — the agent whose Workflow consumes these heuristics in Phase 02.
- `migration-cluster-worker.md` — the agent whose Workflow applies the transformations in Phase 04.
- `transform-rules-schema.md` — the per-migration rules-file schema whose Section 3 instantiates the directives.
- `type-change-bug-flagging.md` — orthogonal cross-cut that FLAGs occurrences whose transformation requires more than a noun-swap, regardless of bucket.
- `[[feedback_dual_path_mechanical_migration]]` — the playbook that proved the 6-bucket model on PR #68.
