Heuristics for identifying when a codebase needs a NEW archetype on the server, or when an EXISTING archetype is being stretched/misapplied/duplicated. Used by /analyze-archetypes, and by /analyze when recording the archetype gaps it hit. Defines what makes a good proposal, what to avoid, and how to phrase rationales.
Pro scans all 3 files and shows the line behind each finding
Scanned 9/25/2026
npx -y skills add provenmap/pmap-claude --skill archetype-analysis --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Archetype Analysis?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/provenmap-archetype-analysis)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: archetype-analysis
description: Heuristics for identifying when a codebase needs a NEW archetype on the server, or when an EXISTING archetype is being stretched/misapplied/duplicated. Used by /analyze-archetypes, and by /analyze when recording the archetype gaps it hit. Defines what makes a good proposal, what to avoid, and how to phrase rationales.
user-invokable: false
metadata:
author: ProvenMap
version: 0.2.0
---
# Archetype Analysis — Heuristics
When `/analyze-archetypes` runs, the architecture-analyzer agent invokes this skill in `--archetypes-only` mode to decide what proposals (if any) the codebase warrants. Archetypes are server-managed and approved by humans — a noisy proposal queue burns admin attention, so be selective.
Settling the vocabulary is **optional** — `/analyze` types every component with the closest available archetype and runs to completion regardless. These heuristics decide what is worth proposing: the same bar applies whether `/analyze-archetypes` is scanning for proposals up front, or `/analyze` is recording the gaps it hit in `metadata.archetypeGaps` so the user can act on them afterwards.
## When to run `/analyze-archetypes`
- After `/analyze` reported archetype gaps — it names the categories your codebase has that the catalogue doesn't.
- When you want to curate the vocabulary up front on a fresh project, before any board exists.
- After a codebase change that introduces a genuinely new component category (e.g. adding CDK stacks to a previously codebase-only repo).
- After admin approves proposals you previously submitted — re-running confirms the catalogue is now complete and updates the lock file. Then `/analyze --clean` retypes the affected components.
The command does **not** write board JSONs; it is a pre-analysis vocabulary check only. Approved proposals appear in `/code-plugin/archetypes` only after admin review in the ProvenMap UI — until then the live catalogue is unchanged, and `/analyze` warns if you have pending proposals submitted.
## Running the scan (`--archetypes-only`)
`/analyze-archetypes` Step 2 invokes the `architecture-analyzer` agent in `--archetypes-only` mode. The agent runs `/analyze` Steps 0, 3, 4, 5 (project detection → tech stack detection → component discovery + archetype classification) but stops there. It does **not** produce board JSON, edges, hierarchies, or manifest updates.
**Model.** If `.provenmap/config.json` has `analysis.subagentModel`, pass it as the model for the dispatched agent; otherwise inherit the session model. Same rule as `/analyze` Step 8.7 — the setting pins every analysis subagent, and this scan is one.
**Payload.** The agent's output conforms to `ArchetypeProposalPayloadSchema`: `proposed[]` (new-archetype candidates) plus `improvements[]` (improvement candidates — rename | split | redescribe | merge). Both are judged by the heuristics below, for what to propose and equally for what to skip.
**Surface the evidence before asking.** The scan runs for minutes in the background; a spawn line followed by a summary gives the user nothing to judge. Before the submit prompt, print for each proposal:
- the archetype name and the kind of gap (new archetype vs improvement)
- the files and components that evidence it — the concrete instances found
- which existing catalogue entries were considered and rejected, and why
That is precisely the material needed to sanity-check a proposal before it consumes admin review time. If the agent's payload does not carry it, say so explicitly rather than presenting an unevidenced proposal as ready.
## What makes a good NEW archetype
A proposal should clear all four bars:
1. **Coverage.** It applies to **≥2 distinct nodes** in the analyzed codebase. A one-off doesn't justify a new archetype — use an existing close-fit and add tags.
2. **Semantic role.** A clear verb-like answer to "what does this *do* on the board." Good: `lambda_function`, `event_bus`, `feature_flag`. Bad: `utility`, `helper`, `common`. **Agent-native stacks count**: repos built of prompt-ware — the prepass marks these skeleton nodes with `artifact.kind` (skill/command/agent) — commonly warrant archetypes like `agent_command`, `agent_skill`, `agent_definition` when the catalogue has no prompt-ware vocabulary yet; the detection pattern is mechanical (frontmatter signature), so bar 3 is trivially met.
3. **Observable detection pattern.** Something a future analyzer can detect mechanically — file path convention, dependency marker, import signature, naming pattern. If a human couldn't write the detection rule in one sentence, the archetype is too vague.
4. **No existing close fit.** Before proposing, scan the fetched archetype list for synonyms. If `database` already exists, don't propose `db_store`. If `service` exists, don't propose `microservice` unless you're splitting (then use an improvement instead).
## What makes a good IMPROVEMENT
There are four shapes (the `suggestedChange` enum):
| Change | When to use | Required field |
| --- | --- | --- |
| `rename` | Existing name is misleading or generic for what it's actually being used for. E.g., `service` always points to HTTP endpoints in this codebase. | `newName` |
| `split` | Same archetype is being applied to ≥2 clearly different node sub-populations. Identify the dividing axis. | `splitInto` (≥2 targets) |
| `redescribe` | Description doesn't match how it's actually being used. The name is fine; the docs are misleading. | `newDescription` |
| `merge` | Two existing archetypes are near-duplicates with no meaningful behavioral difference on the board. | `mergeIntoName` |
## How to phrase rationales
Three sentences max. Each does one thing:
1. **Pattern** — what you observed. *"12 nodes typed as `service` split cleanly into HTTP-facing controllers and background queue workers."*
2. **Impact** — what's worse without the change. *"Today these get the same icon and styling on the board, hiding the operational difference between sync and async work."*
3. **Proposed change** — what specifically would be done. *"Split into `http_service` and `worker_service`."*
No essays. No marketing language. No "for clarity" — explain *what* clarity, *for whom*.
## What NOT to propose
These all fail review:
- **Vendor names** as archetypes: `stripe_service`, `aws_lambda`, `postgres_db`. The archetype should describe the *role*, not the *vendor*. (`lambda_function` is fine because it describes the compute model; `aws_lambda` is not.)
- **Single-node coverage.** If only one node fits the proposed archetype, defer — it's not worth a server-side review cycle.
- **Archetypes already on the server.** Always check the fetched archetype list first.
- **Layered/board concepts** dressed up as archetypes. Boards have their own hierarchy; don't propose archetypes like `l0_overview` or `subsystem`.
- **Status/lifecycle** masquerading as archetypes: `deprecated_service`, `legacy_db`. Use tags for status; archetypes describe what a thing *is*, not its lifecycle stage.
## The role map (roles → archetypes)
`.provenmap/role-archetype-map.json` is the compiled bridge between the index's script-owned
role claims and the server archetype catalogue. `/analyze` Step 0 compiles it once per
catalogue hash: for every unmapped headline role (`controller`, `service`, `repository`,
`model`, `middleware`, `client`, `worker`, `module`, `migration`, `component`, `utility`) it
chooses one archetype name from the fetched catalogue, writes a draft, and runs
`pmap-prepass.js --role-map <draft>` to validate and save it. Once compiled, `--detail` rows
carry `archetype` directly — no more per-file guessing.
**An unmapped role is a legitimate outcome, not an error.** If no catalogue archetype
honestly fits a role, leave it in `unmappedRoles` — the projection shows the bare role and
those files get typed by hand. Don't force a bad fit just to close out the list.
**To re-pin a choice** (so it survives the next catalogue-hash recompile): write a draft with
`"pinned": true` on the entries you want to keep, then run
`pmap-prepass.js --role-map <draft>` again. Pinned entries are carried forward unchanged on
every future recompile; only unpinned entries get recomputed when the hash drifts.
## Examples
### Good — new archetype proposal
```json
{
"name": "feature_flag",
"visualPrimitiveType": "node",
"description": "A runtime toggle that gates code paths. Read at request-time from a flag service or env config; controls feature rollout.",
"detectionRules": "Imports from `unleash-client`, `launchdarkly-node-server-sdk`, `@growthbook/growthbook`, or local `flags.ts` with `FlagKey` enum.",
"exampleNodeSlugs": ["billing-flags", "experiments-runtime"],
"sourceContext": { "boardSlug": "overview" }
}
```
Why it passes:
- Two distinct nodes use it.
- Clear role: gates code paths.
- Detection rule a human can verify in seconds.
- No existing archetype covers it.
### Good — split improvement
```json
{
"existingArchetypeName": "service",
"suggestedChange": "split",
"rationale": "12 nodes typed as `service` split cleanly into 7 HTTP-facing controllers (use Fastify/Express) and 5 background workers (consume from SQS or run on schedule). Today they get the same icon and don't visually distinguish sync vs async work.",
"splitInto": [
{
"name": "http_service",
"description": "Synchronous HTTP service exposing REST or GraphQL endpoints.",
"visualPrimitiveType": "node"
},
{
"name": "worker_service",
"description": "Background async service consuming queues or running on a schedule.",
"visualPrimitiveType": "node"
}
],
"affectedNodeSlugs": [
"auth-svc", "billing-svc", "user-svc", "orders-svc", "search-svc",
"notifications-svc", "webhooks-svc",
"email-worker", "invoice-worker", "image-resize-worker",
"cleanup-worker", "report-scheduler"
],
"sourceContext": { "boardSlug": "overview" }
}
```
Why it passes:
- Clear dividing axis (sync HTTP vs async background).
- Population is balanced (7 vs 5 — not one outlier).
- Both targets are real archetypes in their own right.
### Bad — too narrow
```json
{
"name": "stripe_webhook_handler",
"visualPrimitiveType": "node",
"description": "Handles incoming Stripe webhook events.",
"exampleNodeSlugs": ["stripe-webhook"],
...
}
```
Why it fails:
- Vendor-specific (`stripe_`).
- Covers only one node.
- Already covered by a generic `webhook_handler` or `http_service` archetype.
For more examples and edge cases, see [`references/proposal-quality-rules.md`](references/proposal-quality-rules.md). For the command's own Steps 1–5 — every CLI call, decision branch, printed line, and the lock file plus its optional strict gate — see [`references/scan-workflow.md`](references/scan-workflow.md).
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!