# taxonomy/placement.project.taxonomy.md

> 205 lines of code and 0 definitions.

Tree: Coordination tree
Language: markdown
Canonical: https://banes-lab.com/anatomy/coordination#file-coordination-taxonomy-placement-project-taxonomy-md
Source text: https://banes-lab.com/assets/sources/source.207008c570dc5d318e5fa872cd7b5b28a3fb5077c53cd67e651f7523ad02d037.generated.txt

## Source

````markdown
---
name: placement
summary: The concern-taxonomy standard — the container-subject-concern folder chain, the subject.variant.concern.ext filename, the depth cap, jurisdiction, and the disambiguation law.
type: taxonomy
concern: governance
status: current
---

# Placement and naming standard

The authoritative, machine-resolvable standard for how every governed file is **named** and
**placed**, so the tree is queryable by glob and enforceable by a gate. One source the SSOT, the
gate and the classifier all derive from.

Vocabulary: `vocabulary.project.taxonomy.md`. Machine truth: `taxonomy.config.ts`. Slot resolution:
`.{provider}/bindings/adapter.binding.md`.

## 1. The grammar

```text
folder = <container> | <subject> | <concern>        one word, never a dot
file   = <subject>.<concern>.<ext>
       | <subject>.<variant>.<concern>.<ext>        overflow form
```

A folder carries exactly one word and no separator; the file carries the dotted form. What ties them
is that **the file's concern equals its parent folder's concern.**

That equality is the load-bearing guarantee: one pair of globs resolves the whole system —
`**/*.<concern>.<ext>` for every file of a role, `**/<concern>/` for every folder of one — and
neither is anchored to depth, so grouping a set behind a subject folder never costs findability.

- **`<subject>`** — the entity or target the file serves. Always required; never a bare
  `<concern>.<ext>`. May equal its subject folder when the file is the canonical one for it.
- **`<concern>`** — the concern tag, matching the parent folder, in the plurality form the registry
  records for it.
- **`<variant>`** — present only when a **collision** would occur on `<subject>.<concern>` in one
  folder, or when a **facet** of the subject needs naming. Drawn from `variants` ∪ `subjects`.

Resolution is **positional, not lexical**. The only lexical bar is subject ≠ concern.

Kebab-case throughout. A hyphen inside a slot is spelling; the dot is the only separator. A folder
never carries a dot, so a dotted folder name is always wrong.

**The member never restates the set.** Where a subject folder groups a concern, the file subject
names the member within it — inside a billing subject folder's validators folder the file is `invoice.validator.ts`, never `billing-invoice.validator.ts`.

## 2. Depth — the ordered-role rule

```text
container(1) → subject(2, optional) → concern(3) → file
```

Every governed file resolves within **≤ 3 folders from its governed root**, the container included
and the file excluded, so `container/concern/file` is depth 2.

- **The anchor is the governed root**, and counting starts at the container.
- **Roles are ordered and skippable.** They resolve in the sequence `container < subject < concern`.
  Each depth consumes a role strictly _later_ than the one before it, so a role may be skipped but
  never repeated and never revisited. `caches/` under a container is legal; `caches/validators/` is not.
- **The file's parent is always a concern folder.** A file sitting anywhere else is the finding.
- **A subject folder exists if and only if** the container holds two or more sets of one concern that
  must not merge. One set gets a bare `<concern>/`.

The "if and only if" is what keeps one legal path per file. Make grouping optional and classification
gets two right answers, and a gate cannot check placement at all.

**Overflow relieves sideways, never downward.** A collision takes the filename's variant slot;
breadth takes a sibling subject folder. The depth cap is _why_ both slots exist — remove the cap and
both degenerate into nesting. This coupling is the load-bearing invariant.

## 3. Jurisdiction is declared

A key of `containers` is a governed root: **no declaration, no enforcement.** Its array is the closed
set of folders legal directly beneath it. `specialContainers` names which are flat buckets — a bucket
holds one collection concern, files and never folders, and the depth cap does not apply to it. Its
name is that concern's folder label.

Both kinds are declared, never derived from shape. _"A folder with no subfolders is a bucket"_ is
inference, and inference is what an SSOT exists to remove: a container that lost its last folder
would silently reclassify, and its next loose file would pass unnoticed.

`Ignored.foldersFiles` is the single escape, global rather than per-root, for things outside the
taxonomy entirely. **It is never an answer to a finding on authored source** — an entry that silences
real code hides that violation and every future one under the same name.

### A folder at a governed root is not a license to declare a container

1. Does it group two or more concern folders that must not merge? → it is a **subject** folder inside
   an existing container.
2. Does it hold files of one role? → it is a **concern** folder inside a container.
3. Does an existing container already group it? Containers partition by **axis**, not by feature.
4. Is it source at all? If not → an ignore entry, not a container.
5. Only a **new grouping axis** earns a container, by approved SSOT edit.

A container is not a home for files that resist placement, and never a way to shorten a path.

## 4. Governed roots

| root                   | containers         | buckets                                                                                                 |
| ---------------------- | ------------------ | ------------------------------------------------------------------------------------------------------- |
| `.{provider}`          | `intel` · `skills` | `rules` · `templates` · `bindings`                                                                      |
| `tools`                | `core`             | `rules`                                                                                                 |
| `tests`                | `core`             | —                                                                                                       |
| `.` (the package root) | —                  | `checklists` · `findings` · `templates` · `models` · `specifications` · `roles` · `config` · `taxonomy` |

`agents` is **outside jurisdiction and ignored**, under `foreign_grammar_is_never_claimed`. An agent's
filename and its `name:` field are the identifier the host runtime resolves it by, so renaming one to
satisfy this grammar breaks invocation rather than reorganising anything — the same reason any
tree another system names is not claimed. Ignoring it is the declared mechanism for a tree that exists and is not
ours to name.

**A governed root may carry its own entry document and its accumulators at root; everything else lives
in a concern folder.** Those two are the root's spine rather than content: the entry document is what a
reader opens first, and an accumulator is marked by its `_` prefix and is history by design. The rule
matches those constructs rather than any filename, so it holds for a root added later, and a root file
that is neither still fails as `looseFileAtRoot` — verified by planting one and watching it fire.

A container is declared when it exists, never in advance of it. A folder declared for work not
yet done is a deferral queue in the SSOT: it governs nothing, fails nothing, and reads as coverage.
The `declaration` gate holds this — every declared root, container and bucket must resolve to a
directory on disk.

### Corpus roots — the second grammar

A key of `corpusRoots` is governed too, by a different grammar:

```text
file = <key>[.<variant>].<facet>.<ext>
```

| root                  | key                                      | facet derived from                     | filed under          |
| --------------------- | ---------------------------------------- | -------------------------------------- | -------------------- |
| _(declared per host)_ | the file's canonical symbol, kebab-cased | a frontmatter field, else its fallback | the declared subtree |

**No corpus root ships declared.** A corpus is a body of material whose keys are set by whoever
authored it, so which tree qualifies is a host's fact and the array is empty until a host says so.

The concern grammar cannot claim such a tree, and that is a property of the tree rather than a
concession. Its key is an upstream identifier, so the key set is open by construction, while
`subjects` is closed by design. Declaring an upstream symbol set as subjects would empty the closure of
meaning, and relaxing the closure is forbidden outright — so the tree gets its own declared
jurisdiction instead of being bent into one that does not fit.

The facet is **derived, never chosen**. That is what makes this grammar gateable where a naming
convention is not: a convention can only be compared against itself, while a derived facet is
compared against evidence the file itself carries. A file whose upstream facet field changes keeps its
old filename, resolves into the wrong facet set on every glob, and errors nowhere — only re-deriving
on each run catches it.

A variant carries grouping the facet does not already encode. Where an origin's name would merely
restate its facet, it contributes none.

Everything else is ungoverned, and each for a stated reason.

| outside jurisdiction                                      | why                                                                                                                                                  |
| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| a tree carrying another system's ownership markers        | its names are identifiers that system resolves at runtime, so renaming to satisfy placement breaks what reads them rather than reorganising anything |
| a vendored artifact replaced wholesale on update          | an edit there is destroyed on the next update and may break the install                                                                              |
| a tree whose names are cited as invocations               | renaming breaks a documented command at the moment somebody needs it                                                                                 |
| a directory of archives or extracted third-party material | not authored here and not ours to rename                                                                                                             |
| the configuration itself                                  | **structurally exempt** — the gate's own definition cannot be governed by the gate it hosts                                                          |

**Each row is a SHAPE rather than a path**, because the trees a host holds are the host's and the reason
a tree is exempt transfers while its name does not. A host declares its own by matching a row.

## 5. Disambiguation law

1. **One concern per file.** A file's concern is its primary responsibility. Genuinely two concerns
   means it does too much → split it.
2. **Narrowest concern.** Classify to the narrowest accurate tag — `coordinator` over `service`. A
   saturated high-level label is a misclassification whenever a narrower one fits.
3. **Tie-break, irreducible overlap only:** the domain-ward layer wins.

### The determination protocol

A name is a claim about what the code does, and a claim is untrusted until checked.

```text
1. READ the file. what does it actually do?
2. NAME the concern — the narrowest accurate tag, not a saturated one
3. CHECK the vocabulary in order:
     in the ssot        → use it
     in the rejections  → use the meta concern it points to
     none of the above  → UNRESOLVED. a finding, not a blocker —
                           it usually means the file does two things
4. VERIFY the name against the content, never against the old filename
5. one concern per file. two concerns = split, never a compromise tag
```

## 6. Governed and exempt

**Governed:** every authored file of any language under a declared root. The grammar is
filetype-agnostic.

**Exempt, never renamed:**

- **Ecosystem-fixed names** — resolved by exact name by external tooling. Here: `SKILL.md`,
  `package.json`, `settings.json`, `settings.local.json`. Renaming breaks resolution outright.
- **Structurally exempt** — files carrying their own resolution contract or their own gate:
  the taxonomy canon itself, and the gate sources once they exist.
- **Compound markers** — `test`, `spec`, `d`, `generated`. A file whose second-to-last dot segment is
  one of these is **name-exempt but not placement-exempt**.
- **Flat buckets** keep their shape. A reshape renames within one and never scatters it.
- **Assets and binaries** — out of scope.

**The highest-risk slice is anything referenced by pattern rather than by literal path.** A rename is
safe only when every reference is a literal string a search can find. In this package that slice
is the `see:`, `source:` and `detect:` fields of the typed records, which `npm run govern:segment`
counts. They form a
reference graph encoded in text. A rename that misses them fails silently — the reference resolves to
nothing, nothing errors, and the graph is quietly disconnected.

## 7. The reshape

A manual reshape is the usual rule, on the reasoning that an automated renamer rewrites
literal path text while shape-discovered surfaces do not use literal path text.

**That reasoning is defeated, not ignored, by a segment matcher.** A tool that composes and matches
1→X segments as constructs, AST-typed rather than text-typed, sees the reference graph a literal-text
renamer cannot. Where such a tool exists and has been shown to resolve a surface, the conversion for
that surface is automated. Where it has not, the conversion is manual.

The precondition is unchanged and absolute: **enumerate every pattern-referenced surface before the
first rename**, and after the conversion verify that each still resolves what it resolved before. A
count that silently dropped to zero is the failure this procedure exists to catch.

Per container:

```text
1. ENUMERATE the container's files; assign each a concern + subject
2. RECORD split candidates — files that fit two concerns — split them first
3. CREATE the concern folders; qualify one ONLY where a sibling shares its
   concern; MOVE + RENAME
4. UPDATE every reference — literal and pattern — in the same pass
5. RE-POINT every pattern-discovered surface whose form encoded the old shape
6. VERIFY the discovery still discovers; compare counts against the baseline
```

Step 3 drops subject folders as often as it adds them. Expect paths to get **shorter**.

## 8. Enforcement chain

1. **SSOT** — `taxonomy.config.ts`. Data only: roots, containers, buckets, ignore list, grammar
   constants, the three vocabularies. Its type assertions prove no subject shadows a concern, no
   variant shadows either, and every declared layer is in the spine — so the vocabulary cannot go
   internally inconsistent without failing to typecheck.
2. **Gate — two rules, split on one line.**
   **Placement** walks the filesystem and must land first, because every later check counts depth
   from an anchor only it resolves. Findings: `missingRoot`, `missingContainer`, `undeclaredContainer`,
   `nestedInSpecial`, `looseFileAtRoot`, `badShape`.
   **Naming** runs per file. Findings: `unparsable`, `concernMismatch`.
   Splitting them there is what stops a misplaced file being reported twice.
3. **Classify** — assign each governed file its concern by reading it. Judgement, not pattern
   matching. A file that resists classification is a split candidate — a finding worth recording
   rather than forcing under an arbitrary tag.
4. **Reshape** — container by container, gate green between each.

## 9. Edge-case defaults

- **Small containers still get concern folders.** A three-file leaf becomes three single-file concern
  folders — uniformity over compactness; the glob guarantee holds everywhere.
- **A file with no obvious subject** takes the container or capability name as its subject, never a
  bare `<concern>.<ext>`.
- **Ordering is not a filename concern.** Numeric prefixes encode load order, which belongs in an
  import list or a registry, not in a name the grammar must parse.
````
