Compare commits

...

11 Commits

Author SHA1 Message Date
jared 3f76755e85 Adopt cc-architect from cc-plugins (Phase B)
cc-architect (plugin standards authority, v1.0.1) now lives here with the
other universal system plugins, registered in the marketplace manifest and
installed via the standard local-plugins symlink.

Also sync the os-backlog marketplace description to its updated
plugin.json so the cross-repo acceptance gate passes; that rewrite is
otherwise untouched here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UmdZ3xYPSGpuGv8V3mNv6c
2026-07-16 15:07:46 -04:00
jared e82bfcb0cd Add marketplace manifest for os-* plugins
Centralizes plugin registry in a committed, machine-independent format
rather than relying solely on local ~/.claude/plugins install state.
Enables cc-architect's structural validator to verify plugins against the
manifest, and makes the registry shareable across clones. Part of
cross-repo standards-centralization (jaredswanson/cc-plugins#13).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UmdZ3xYPSGpuGv8V3mNv6c
2026-07-16 13:11:54 -04:00
jared b062ac354e docs: hygiene cleanup (2 edits across 2 files)
Auto: 1 (freeze ×1)
Confirmed: 1 (delete ×1)
Skipped (re-analysis recommended): 1
2026-07-15 15:41:55 -04:00
jared 39356ebdbf wip: checkpoint before hygiene cleanup 2026-07-15 15:41:09 -04:00
jared 3466159f7c os-doc-hygiene: sync calibrate-assessment-inventory delta specs to main + archive change
Main specs updated: lifecycle-rulebook (+nominations memory, +canonical
writer-enforced ordering, envelope modified), calibrate (+intake filter,
+consult persistence, persistence-by-scope and class-never-path modified),
doc-clean (extract-then-delete extracted.md pointer). Change archived to
openspec/changes/archive/2026-07-15-calibrate-assessment-inventory/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LjFRroqLsvkL2WrMJtRBrK
2026-07-15 15:06:38 -04:00
jared 0d303caf43 os-doc-hygiene: calibrate assessment inventory implemented (map #49)
RulesFileWriter (canonical .dochygiene-rules.json serialization) +
NominationIntakeFilter (deterministic Step 3.5) in calibrate_helpers.py;
calibrate SKILL.md Steps 3.5/5/6 wired (open-consults exits, keep/decline/
consult persistence through the writer); patch_applier extract-then-delete
appends the extracted.md vault pointer fail-closed; clean SKILL.md Step 6.5
supplies extraction_pointer. Suite 434 passed (26 new tests). OpenSpec
change: calibrate-assessment-inventory.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LjFRroqLsvkL2WrMJtRBrK
2026-07-15 14:59:58 -04:00
jared 9f11df3e2a os-doc-hygiene: calibrate assessment-inventory design locked — spec deltas + ADR amendments (map #49, ticket #58)
Persist the full :calibrate assessment inventory + rulebook refinements
per wayfinder map #49 (tickets #51-#57, #59): nominations memory
(consults/rejected) in the rules file, deterministic nomination intake
filter, writer-enforced canonical ordering, keep-verdict persistence with
keep-tier relaxation, enumerate-siblings rule-quality test, extracted.md
extract-index convention + global keep rule, judge.md corrective edits,
and the test-coverage decisions. Implementation hands off to an OpenSpec
change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LjFRroqLsvkL2WrMJtRBrK
2026-07-15 13:58:07 -04:00
jared 807dcc8d90 os-doc-hygiene: post-calibration follow-ups
- Rules: 4 new lifecycle rules for OpenSpec trees (specs/** keep;
  changes/archive/*/ temporary retain 3 / 90d), root + plugins/*
- Fill TBD Purpose placeholders in doc-check + doc-clean specs (the
  doc-check one was a check-run miss: sat under file_length thresholds)
- Report header: "findings: N" + "cleared: K of M evaluated entries"
  (cleared no longer masquerades as files-scanned)
- CLAUDE.md: vault user-guide pointer; fix stale .dochygiene/ state
  path to .cc-os/dochygiene/ (ADR-0027)

Suite: 408 passed, 3 skipped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LAw7YxP71Fk6K9AHNaYPj2
2026-07-15 10:22:41 -04:00
jared fe04297604 os-doc-hygiene: sync lifecycle delta specs to main + archive change
Main specs gain calibrate, determinism-promotion, lifecycle-deletion,
lifecycle-rulebook (new) and rulebook-aware updates to doc-check,
doc-clean, report-schema. Change archived to
openspec/changes/archive/2026-07-15-lifecycle-aware-doc-hygiene.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LAw7YxP71Fk6K9AHNaYPj2
2026-07-15 08:51:21 -04:00
jared 7b9afb1f6a os-doc-hygiene: lifecycle-aware hygiene implementation + calibration pass #1 (map #31)
Implements the lifecycle-aware-doc-hygiene change (ADR-0038..0041):
rulebook loader (global rulebook.json + per-project .dochygiene-rules.json,
add-only merge, two-axis precedence, IGNORE-sentinel zero-emission prune),
scanner lifecycle signals + temporary/delete-once-served tiers, report
schema delete/extract-then-delete ops with git-state tier derivation,
promotion_candidates from conventions.json, patch-applier deletion ops with
apply-time git re-verification, and the /os-doc-hygiene:calibrate skill.

Calibration pass #1 (cc-os) PASSED: protected-set hard gate + recall floor
9/10 with all 4 mandatory rows; 4 human-approved rules persisted to
repo-root .dochygiene-rules.json. invariants.md #3 (.cc-os/dochygiene per
ADR-0027) and #9 (rulebook IGNORE as third ignore mechanism) corrected
with explicit human approval per the META-RULE.

test_no_global_index_created now runs against an isolated HOME (the real
~/.cc-os legitimately exists since os-backlog's projects registry).
Suite: 408 passed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LAw7YxP71Fk6K9AHNaYPj2
2026-07-15 07:41:59 -04:00
jared e1d22d83ba os-doc-hygiene: lifecycle-aware hygiene design locked — spec + ADR set (map #31, ticket #46)
lifecycle-spec.md consolidates wayfinder decisions #32-#48; ADR-0038
(repo-root .dochygiene-rules.json override), ADR-0039 (evidence-quality
deletion tiers), ADR-0040 (no ignore-surface propagation), ADR-0041
(determinism promotion + conventions catalog).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bvc6togVPDXvkoq8fbHj3e
2026-07-14 16:33:26 -04:00
164 changed files with 20224 additions and 196 deletions

View File

@ -0,0 +1,53 @@
{
"name": "cc-os",
"owner": {
"name": "Jared Swanson"
},
"plugins": [
{
"name": "cc-architect",
"source": "./plugins/cc-architect",
"description": "Model-tier-optimized execution plans, scaffolding, and configuration operations for building and managing Claude Code extensions (plugins, skills, workflows, descriptions)"
},
{
"name": "os-adr",
"source": "./plugins/os-adr",
"description": "Architecture Decision Records, consistently in every project: one template, docs/adr/NNNN-title.md + mechanical index, deterministic SessionStart existence check, non-destructive migration, and deterministic-first retrieval."
},
{
"name": "os-backlog",
"source": "./plugins/os-backlog",
"description": "Git-issues backlog across projects: deterministic tracker routing (forgejo/github/repo), mid-session capture as labeled issues, pull-only listing (ADR-0042)."
},
{
"name": "os-context",
"source": "./plugins/os-context",
"description": "Prompt-composer SessionStart plugin: concatenates prompts/session-start/*.md (currently session-orchestration rules — delegation threshold, explicit model routing on Agent spawns) into one additionalContext block, injected at session start and after compaction."
},
{
"name": "os-doc-hygiene",
"source": "./plugins/os-doc-hygiene",
"description": "Monitor and manage stale and bloated project documentation. Deterministic SessionStart reminder + AI-assisted check/clean skills with git-safe, scoped cleanup."
},
{
"name": "os-sdlc",
"source": "./plugins/os-sdlc",
"description": "Harness-driven software development lifecycle for cc-os: grill/wayfinder/to-spec/to-tickets/implement/review, adapted from Matt Pocock's skill lifecycle and Delta Refinery's multi-level pipeline, wired into os-backlog and os-adr."
},
{
"name": "os-shortcuts",
"source": "./plugins/os-shortcuts",
"description": "User-invoked QOL shortcut commands for the cc-os plugin family — the 'keybindings' of cc-os, ritual multi-step sequences invoked on demand (not automatic hook injection). Starts with /os-shortcuts:wrap (session-close ritual); expect more shortcuts to accumulate here."
},
{
"name": "os-status",
"source": "./plugins/os-status",
"description": "Aggregated deterministic SessionStart status checks for the cc-os plugin family: per-project artifacts (ADR system, vault hub note) and environment hazards (subagent model env override). At most one banner per session; snooze/suppress state in .cc-os/."
},
{
"name": "os-vault",
"source": "./plugins/os-vault",
"description": "Vault and graph memory system for Claude Code — integrates SecondBrain knowledge graph, episodic journal, and convention summaries into every session"
}
]
}

99
.dochygiene-rules.json Normal file
View File

@ -0,0 +1,99 @@
{
"schema_version": 1,
"rules": [
{
"glob": "docs/orchestration-audit/auditor-reports/S*-report.md",
"lifetime": "delete-once-served",
"served_when": "The run's synthesis findings doc (docs/orchestration-audit/<audit-date>-findings.md) has been written and verified; these per-session reports are the raw inputs it condenses.",
"confirmed_by": "human",
"confirmed_on": "2026-07-15",
"source": "calibration pass #2 (2026-07-15)",
"note": "Per-session raw auditor reports condensed by the run's synthesis findings doc; delete-once-served is always confirm-tier (ADR-0039)."
},
{
"glob": "plugins/*/HANDOFF-*.md",
"lifetime": "delete-once-served",
"served_when": "The handoff it describes has been picked up and its follow-on work completed in a later session.",
"confirmed_by": "human",
"confirmed_on": "2026-07-15",
"source": "calibration pass #1 (lifecycle-aware-doc-hygiene)",
"note": "Classifier-judged served_when \u2014 always confirm-tier by ADR-0039; never auto-deleted."
},
{
"glob": "autoresearch/classic-*/",
"lifetime": "temporary",
"retain_recent": 3,
"max_age_days": 30,
"confirmed_by": "human",
"confirmed_on": "2026-07-15",
"source": "calibration pass #1 (lifecycle-aware-doc-hygiene); narrowed from autoresearch/*/ 2026-07-15",
"note": "Autoresearch run directories are disposable run output; keep the 3 newest, age out the rest. Narrowed to conventional prefixes so autoresearch/ can hold keep-worthy content."
},
{
"glob": "autoresearch/improve-*/",
"lifetime": "temporary",
"retain_recent": 3,
"max_age_days": 30,
"confirmed_by": "human",
"confirmed_on": "2026-07-15",
"source": "calibration pass #1 (lifecycle-aware-doc-hygiene); narrowed from autoresearch/*/ 2026-07-15",
"note": "Autoresearch run directories are disposable run output; keep the 3 newest, age out the rest. Narrowed to conventional prefixes so autoresearch/ can hold keep-worthy content."
},
{
"glob": "docs/orchestration-audit/factsheets/*.md",
"lifetime": "temporary",
"retain_recent": 10,
"max_age_days": 90,
"confirmed_by": "human",
"confirmed_on": "2026-07-15",
"source": "calibration pass #1 (lifecycle-aware-doc-hygiene)",
"note": "Regenerable precompute for the orchestration IRL audit; the audit skill rebuilds them on each run."
},
{
"glob": "openspec/changes/archive/*/",
"lifetime": "temporary",
"retain_recent": 3,
"max_age_days": 90,
"confirmed_by": "human",
"confirmed_on": "2026-07-15",
"source": "conversation 2026-07-15 (openspec lifecycle rules)",
"note": "Archived change dirs are redundant once synced into specs/ and stay recoverable from git history; age out after a quarter."
},
{
"glob": "plugins/*/.pytest_cache/",
"lifetime": "temporary",
"retain_recent": 0,
"max_age_days": 7,
"confirmed_by": "human",
"confirmed_on": "2026-07-15",
"source": "calibration pass #1 (lifecycle-aware-doc-hygiene)",
"note": "Regenerable pytest cache. Judge noted a .gitignore entry may be preferable long-term."
},
{
"glob": "plugins/*/openspec/changes/archive/*/",
"lifetime": "temporary",
"retain_recent": 3,
"max_age_days": 90,
"confirmed_by": "human",
"confirmed_on": "2026-07-15",
"source": "conversation 2026-07-15 (openspec lifecycle rules)",
"note": "Archived change dirs are redundant once synced into specs/ and stay recoverable from git history; age out after a quarter."
},
{
"glob": "openspec/specs/**",
"lifetime": "keep",
"confirmed_by": "human",
"confirmed_on": "2026-07-15",
"source": "conversation 2026-07-15 (openspec lifecycle rules)",
"note": "Live OpenSpec capability specs \u2014 source of truth future changes diff against; never age out."
},
{
"glob": "plugins/*/openspec/specs/**",
"lifetime": "keep",
"confirmed_by": "human",
"confirmed_on": "2026-07-15",
"source": "conversation 2026-07-15 (openspec lifecycle rules)",
"note": "Live OpenSpec capability specs \u2014 source of truth future changes diff against; never age out."
}
]
}

View File

@ -0,0 +1,27 @@
---
id: "0037"
date: 2026-07-14
status: Accepted
supersedes:
superseded-by:
affected-paths: [plugins/os-sdlc/, docs/matt-pocock-skills-v1.1-notes.md]
affected-components: [os-sdlc, os-backlog, os-adr, os-vault]
---
# 0037 — os-sdlc lives inside cc-os as a new plugin, not a separate cc-sdlc marketplace
## Context
User is adopting Matt Pocock's v1.1 skill lifecycle (grill/to-spec/to-tickets/implement/wayfinder/research/code-review) and wants to blend it with ~/dev/delta-refinery's heavier multi-level pipeline pattern plus cc-os's existing os-backlog/os-adr systems, to automate large chunks of the dev process for upcoming projects. The open question was whether this SDLC layer should be a new plugin inside the cc-os monorepo (registered in the existing local-plugins marketplace) or a separate cc-sdlc marketplace/repo, motivated by wanting shared tooling reusable across harnesses (Claude Code/Codex/pi) and separation of concerns from general os-* tooling.
## Decision
os-sdlc lives at plugins/os-sdlc/ inside the cc-os repo, registered in the existing local-plugins marketplace, following the os-[domain] naming convention (cc-os-plugin-skill-naming-convention.md). It is scoped to include skills, agents, hooks, reference material, and scripts (not skills-only like most current os-* plugins). The first skill is /os-sdlc:review, cherry-picking Matt Pocock's standards-conformance + spec-fidelity + Fowler refactor-smell review axes, coexisting with the existing generic /code-review (correctness + reuse/simplification) rather than replacing it. Full pipeline design (how much of Delta Refinery's multi-level/resumable-handoff machinery to adopt, how implement/wayfinder are shaped) is deferred to a follow-up brainstorming session; plugins/os-sdlc/OVERVIEW.md is the launching-point doc for that session.
## Consequences
Adding a new SDLC lifecycle domain becomes easier: it reuses the existing marketplace manifest, refresh-plugins tooling, and os-[domain] naming convention instead of standing up new infrastructure. os-sdlc's skills can call directly into os-backlog (tickets) and os-adr (decisions) as sibling plugins in the same repo, keeping ADR-0023's cooperating-plugins bet intact. The tradeoff: os-sdlc is not independently reusable outside cc-os without extraction later if the user ever wants to publish/share just the SDLC layer decoupled from the personal vault/memory stack — that would require a future split, not ruled out here, just not chosen now. Running two coexisting review commands (/code-review and /os-sdlc:review) is an explicit, intentional consequence of this decision, not an oversight.
## Alternatives rejected
Separate cc-sdlc marketplace/repo — rejected because the user confirmed it would be installed globally too, so a split buys no functional/loading separation, only a second repo/manifest to keep in sync, and it fragments coupling to os-backlog/os-adr/os-vault across repos against ADR-0023's cooperating-plugins bet. Enhancing the existing generic /code-review in place instead of a namespaced /os-sdlc:review — rejected because the two review skills serve genuinely different axes (correctness/reuse/simplification vs standards-doc conformance/spec-fidelity/refactor-smells) and the user explicitly chose coexistence over a merge.

View File

@ -0,0 +1,31 @@
---
id: "0038"
date: 2026-07-14
status: Accepted
supersedes:
superseded-by:
affected-paths: [plugins/os-doc-hygiene/rulebook.json, plugins/os-doc-hygiene/lifecycle-spec.md, plugins/os-doc-hygiene/scripts/]
affected-components: [os-doc-hygiene]
---
# 0038 — Per-project doc-hygiene rulebook override lives at repo-root .dochygiene-rules.json, not in .cc-os/
## Context
The lifecycle-aware doc hygiene design (wayfinder map #31, ticket #40) gives os-doc-hygiene a global rulebook shipped in the plugin (plugins/os-doc-hygiene/rulebook.json) plus a thin per-project override for exceptions (e.g. repos where specs are the product). cc-os also has a gitignored .cc-os/ directory used for local machine config (e.g. tracker keys), which raised the question of where the override belongs. The override participates in deletion decisions, so it must be reviewable, versioned, and shared by every collaborator and agent working the repo.
## Decision
The per-project override is a committed repo-root dotfile: .dochygiene-rules.json. It follows the existing .dochygiene-ignore precedent. Envelope {"schema_version": 1, "rules": [...]}; merged add-only over the global rulebook with source-then-specificity precedence (project file-rule > project directory-rule > global file-rule > global directory-rule; ties by longest pattern, then last-defined). A project neutralizes a global rule by shadowing it with lifetime "keep" — no rule-removal mechanism.
## Consequences
Rule overrides are visible in review and travel with the repo — a rule that can authorize deletion is never invisible local state. One more root dotfile per opted-in project. Because the merge is add-only, a bad global rule is neutralized by shadowing, not deleted, keeping merge semantics trivially predictable. Full schema: plugins/os-doc-hygiene/lifecycle-spec.md.
## Alternatives rejected
(1) .cc-os/dochygiene-rules.json — rejected: .cc-os/ is gitignored local config; deletion-authorizing rules must be committed, reviewable, and shared, not per-machine. (2) Global rulebook only, no override — rejected: repos where specs/plans are the product need exceptions (ticket #34). (3) YAML/TOML with comments — rejected in #40: JSON parses with stdlib in both the Python pipeline and any tooling; a per-rule note field substitutes for comments.
## Amendment (2026-07-15 — wayfinder map #49)
The rules file's scope now includes **nominations memory**: an optional second top-level key `nominations` with two sub-keys — `consults` (open judge questions that resurface each `:calibrate` run until answered) and `rejected` (declined nominations, judge- or human-declined, that block exact glob+lifetime repeats at nomination intake and travel to the judge as context for variants). The key is additive to schema_version 1 (the v1 loader ignores unknown top-level keys); `rulebook.py` stays nomination-unaware — only the calibrate pipeline reads it. Serialization of the whole file is writer-enforced canonical ordering (rules grouped delete-once-served → temporary → keep, glob-sorted within groups; `nominations` after `rules`, `consults` before `rejected`) — no hook. The global rulebook additionally carries a `**/extracted.md → keep` rule, protecting the per-directory extract-index convention (map #49 ticket #57) in every project with zero per-project bookkeeping. Detail: plugins/os-doc-hygiene/lifecycle-spec.md (§1 extract index; §2 nominations memory + canonical ordering); decision tickets #51#53, #56, #57.

View File

@ -0,0 +1,31 @@
---
id: "0039"
date: 2026-07-14
status: Accepted
supersedes:
superseded-by:
affected-paths: [plugins/os-doc-hygiene/lifecycle-spec.md, plugins/os-doc-hygiene/scripts/, plugins/os-doc-hygiene/skills/]
affected-components: [os-doc-hygiene]
---
# 0039 — Doc-hygiene deletion autonomy is tiered on evidence quality and recoverability, not file type
## Context
Lifecycle rules let os-doc-hygiene:clean delete files (true git deletion in a dedicated hygiene commit; git history is the archive — ticket #35). The question (ticket #43) was what deletes silently versus what requires confirmation. Re-confirming every run would reduce the rulebook to an advisory list and strip :calibrate of its payoff; but an LLM judgment must never silently destroy a file, and untracked or dirty files have no history to recover from. /os-adr:find confirmed no existing ADR governed clean's safety tiers.
## Decision
Rule-backed deletes are auto — a rule confirmed per the strong-model gate (#39) is the standing consent. The auto/confirm line is drawn on evidence quality plus recoverability: tracked + clean worktree + deterministic signal = auto; tracked-but-dirty or untracked = confirm (verified at runtime via git ls-files + dirty check, never trusting the rule); classifier-judged served_when signals are ALWAYS forced to confirm regardless of tracked status, while scanner-proven served_when_path signals may delete silently. The temporary tier defaults to retain_recent 3 + max_age_days 3, age measured from git commit time falling back to mtime for untracked entries (directory-inode mtime, no recursive walk — #48). graphify-out/** and .dochygiene/** form an explicit IGNORE surface that is never walked — the ignore surface is its own list, never inferred from .gitignore (gitignored ≠ deletable, gitignored ≠ keepable). A per-rule confirm:true escape hatch exists but is human-settable only; a model-proposed rule may only ask a human to set it.
## Consequences
Routine hygiene runs unattended on the safe population while every non-recoverable or judgment-based deletion stops at a human. The auto/confirm line moves exactly where evidence quality changes, so improving a rule's evidence (see the determinism-promotion ADR) directly buys silence. 3-day/retain-3 retention is aggressive by design; the newest 3 entries per rule always survive to show current trajectory. Full tier matrix: plugins/os-doc-hygiene/lifecycle-spec.md.
## Alternatives rejected
(1) Confirm everything — rejected: rulebook becomes advisory; confirm-fatigue makes the human rubber-stamp. (2) Tier by file type or a recoverable_via/regenerate class — rejected: recoverability is a property of git state at runtime, not of the rule's claim. (3) 90-day retention windows — rejected as far too slow in the age of AI. (4) mtime-only age — rejected: clone/branch-switch resets every mtime, silently putting the whole rulebook to sleep. (5) Model-settable confirm:true — rejected: used too liberally, everything drifts back to always-confirm.
## Amendment (2026-07-15 — wayfinder map #49)
Tier interactions decided on map #49: (1) the "class, never path" rule-quality test is relaxed for the **keep tier only** — exact-path singleton keep rules are allowed (the test exists to prevent bad deletion rules; a singleton keep merely protects) and leave the rulebook only by hand-deletion, never an automated revisit: an automated revisit would be the one place a machine argues a keep back toward deletion, the exact failure mode the keep tier prevents. Instance globs stay forbidden for temporary/delete-once-served. (2) Nominations memory (ADR-0038 amendment) is memory, not deletion authority: rejections and consults never filter files and are not individually gated at persistence; rules alone authorize deletion. (3) Consults resurface in `:calibrate` only — `:check`/`:clean` are unchanged. Detail: plugins/os-doc-hygiene/lifecycle-spec.md §2/§8; decision tickets #51, #52, #56.

View File

@ -0,0 +1,27 @@
---
id: "0040"
date: 2026-07-14
status: Accepted
supersedes:
superseded-by:
affected-paths: [plugins/os-doc-hygiene/lifecycle-spec.md, plugins/os-vault/, docs/adr/0017-project-graph-onboarding-assesses-the-repo-and-writes-graphifyignore-before-extracting.md]
affected-components: [os-doc-hygiene, os-vault, graphify]
---
# 0040 — Doc-hygiene rules never write other tools' ignore surfaces (no propagate_ignore)
## Context
Ticket #44 asked whether a lifecycle rule marking files temporary/delete-once-served should also propagate into .graphifyignore (keeping disposable docs out of the session-start knowledge graph) and the scanner's own .dochygiene-ignore. The #40 rulebook schema had reserved a propagate_ignore field pending this decision.
## Decision
No propagation, ever: a lifecycle rule never writes into any other tool's ignore/config surface, and the propagate_ignore field is removed from the rulebook schema entirely (not left as an empty slot). .dochygiene-ignore remains a hand-authored, human-only escape hatch unmanaged by the rulebook. os-doc-hygiene stays in its own lane — separation of concerns.
## Consequences
The glob-dialect mismatch problem (rulebook glob.translate vs gitignore vs fnmatch) dissolves — no rule glob is ever translated into a foreign dialect. Delete-once-served files leave the knowledge graph at the next rebuild anyway, so the lost payoff was only the narrow temporary-but-not-yet-served window. If disposable files polluting the knowledge graph later proves painful, the fix belongs to graphify or os-vault:onboard-project, not a hygiene rule reaching across the seam. Noted while verifying: ADR-0017's premise that graphify does not honor .gitignore is stale — graphifyy 0.8.31 (detect.py:707-711) falls back to .gitignore per-directory where no .graphifyignore exists; this does not change ADR-0017's decision.
## Alternatives rejected
(1) Propagate into .dochygiene-ignore — moot, not rejected on principle: the rulebook itself is already the scanner's skip instruction (directory-rule matches prune the walk), so propagation would create two sources of truth for one fact in a weaker dialect (fnmatch) with no precedence rule. (2) Append to .graphifyignore — rejected on ownership and on ADR-0017: onboard-project generates that file per-project WITH user confirmation, and ADR-0017 explicitly rejected auto-writing it without confirmation; automatic appends would reinstate the rejected alternative and add a second writer with no arbiter. (3) Propagate to memsearch — not applicable: memsearch indexes its own ~/.memsearch/memory/ daily files and has no ignore surface for project docs.

View File

@ -0,0 +1,27 @@
---
id: "0041"
date: 2026-07-14
status: Accepted
supersedes:
superseded-by:
affected-paths: [plugins/os-doc-hygiene/conventions.json, plugins/os-doc-hygiene/lifecycle-spec.md, plugins/os-doc-hygiene/skills/]
affected-components: [os-doc-hygiene]
---
# 0041 — Determinism promotion: hygiene nudges projects toward structurally-obvious completion conventions
## Context
The deletion-autonomy tiers force every classifier-judged served_when signal to confirm (the LLM may propose, never silently destroy). Left there, projects with subjective completion signals would accumulate permanent confirm-fatigue, and the human would rubber-stamp gates. Tickets #43 (item 7) and #47 asked how the tool should respond when a rule's served signal is subjective.
## Decision
When a rule's served signal is classifier-judged, the tool does not merely downgrade it to confirm: it names the subjectivity and recommends a concrete structural convention that would graduate the rule to a scanner-proven served_when_path and make it silent. Conventions live in a global-only, machine-readable catalog at plugins/os-doc-hygiene/conventions.json so the deterministic pipeline emits nudges without an LLM; v1 holds exactly two entries: archive-bucket (done = file moved to a sibling archive/ dir, precedent: openspec changes) and status-frontmatter (done = a status: shipped|done frontmatter key). Surfacing splits by capability: :check names promotion candidates in every report; :calibrate may draft the adoption (graduated rule + file moves) for human approval but never applies it unasked.
## Consequences
Confirm-fatigue is converted into the incentive to fix the convention rather than a cost to endure — adopting a convention directly buys silent automation. The catalog only recommends; adoption lands in the project's own rulebook, so no per-project catalog override is needed. A two-entry catalog that gets adopted beats a taxonomy; successor-artifact checks stay out until a calibration pass demands one. The :check report schema gains a promotion-candidates section.
## Alternatives rejected
(1) Just downgrade subjective rules to confirm and stop — rejected: permanent confirm-fatigue with no exit path. (2) A rich taxonomy of completion conventions — rejected: adoption beats coverage; entries are added when calibration passes demand them. (3) Per-project catalog override — rejected: the catalog only recommends, so there is nothing project-specific to override. (4) :calibrate applies adoptions automatically — rejected: violates the model-proposes/human-disposes constraint from #42.

View File

@ -43,4 +43,9 @@ One file per decision, `NNNN-kebab-title.md`, created via `/os-adr:create`.
| 0034 | [Cross-project filing: file-dont-fix with a derived global project index](0034-cross-project-filing-file-dont-fix-with-a-derived-global-project-index.md) | Accepted | 2026-07-13 |
| 0035 | [Issue-triggered project AI wakeup via polling, not webhooks](0035-issue-triggered-project-ai-wakeup-via-polling-not-webhooks.md) | Accepted | 2026-07-13 |
| 0036 | [tmux session convention for AI-run sessions: cc-<project>-<purpose>](0036-tmux-session-convention-for-ai-run-sessions-cc-project-purpose.md) | Accepted | 2026-07-13 |
| 0037 | [os-sdlc lives inside cc-os as a new plugin, not a separate cc-sdlc marketplace](0037-os-sdlc-lives-inside-cc-os-as-a-new-plugin-not-a-separate-cc-sdlc-marketplace.md) | Accepted | 2026-07-14 |
| 0038 | [Per-project doc-hygiene rulebook override lives at repo-root .dochygiene-rules.json, not in .cc-os/](0038-per-project-doc-hygiene-rulebook-override-lives-at-repo-root-dochygiene-rules-json-not-in-cc-os.md) | Accepted | 2026-07-14 |
| 0039 | [Doc-hygiene deletion autonomy is tiered on evidence quality and recoverability, not file type](0039-doc-hygiene-deletion-autonomy-is-tiered-on-evidence-quality-and-recoverability-not-file-type.md) | Accepted | 2026-07-14 |
| 0040 | [Doc-hygiene rules never write other tools' ignore surfaces (no propagate_ignore)](0040-doc-hygiene-rules-never-write-other-tools-ignore-surfaces-no-propagate-ignore.md) | Accepted | 2026-07-14 |
| 0041 | [Determinism promotion: hygiene nudges projects toward structurally-obvious completion conventions](0041-determinism-promotion-hygiene-nudges-projects-toward-structurally-obvious-completion-conventions.md) | Accepted | 2026-07-14 |
<!-- adr-index:end -->

View File

@ -68,6 +68,14 @@ entry is in the leaf file named.
convention + derived global project index (issue #27, ADR-0034); wakeup-polling +
tmux-convention spike with dry-run pilot (issue #28, ADR-0035/0036). Detail:
os-context / os-doc-hygiene / os-backlog leaves.
- **2026-07-14** — os-sdlc plugin scaffolded (ADR-0037): new plugin inside cc-os (not a
separate marketplace) for a harness-driven SDLC lifecycle, adapting Matt Pocock's v1.1
skill lifecycle and Delta Refinery's multi-level pipeline; registered in local-plugins,
no skills/agents/hooks implemented yet. Launching-point doc: `plugins/os-sdlc/OVERVIEW.md`;
full design deferred to a follow-up brainstorming session.
- **2026-07-15** — os-doc-hygiene lifecycle-aware hygiene shipped (ADR-00380041): rulebook
layer, lifetime taxonomy + tier matrix, no-ignore-propagation, conventions.json promotion,
new `:calibrate` skill; calibration pass #1 (cc-os) passed. Detail: os-doc-hygiene leaf.
**Remaining optional items:** additional project onboarding (one at a time, per ADR-0013);
bulk vault migration; os-adr rollout to pilot projects; os-backlog routing rollout (#14);

View File

@ -29,3 +29,31 @@ _Leaf file of [../implementation-status.md](../implementation-status.md). Read o
`check`/`clean`; the `commands/hygiene.md` dispatcher was removed in favor of two new
skills (`status`, `sweep`), aligning with the no-`commands/`-directory pattern
(2026-07-03).
- **Lifecycle-aware hygiene (2026-07-15, ADR-00380041)** — adds a rulebook layer on top of
the existing stale/bloat scanner: a global `rulebook.json` plus an optional per-project
`.dochygiene-rules.json` declare lifetime rules for known-temporary artifacts (ADR-0038).
Rules classify matched paths into the lifetime taxonomy and drive a tier matrix from
scanner-proven+tracked+clean (`auto`) down to classifier-judged (`confirm`) (ADR-0039); an
IGNORE sentinel prunes matched paths with zero emission and does not propagate ignore
status to children (ADR-0040). Classifier-judged matches that recur are surfaced
deterministically as `promotion_candidates` from `conventions.json`, not model-authored
(ADR-0041). New `/os-doc-hygiene:calibrate` skill runs the cluster/nominate/judge/
human-report protocol to tune rules against a real project. Calibration pass #1 (cc-os)
ran 2026-07-14/15 and passed both the protected-set hard gate and the recall floor across
all 4 mandatory rows; rule persistence to `.dochygiene-rules.json` is pending human
approval. Results: `plugins/os-doc-hygiene/openspec/changes/lifecycle-aware-doc-hygiene/calibration-pass-1-results.md`.
Design: `plugins/os-doc-hygiene/lifecycle-spec.md`. Suite: 407 passed.
- **Calibrate assessment inventory implemented (2026-07-15, map #49 / ADR-0038-0039
amendments)** — the locked nominations-memory design is now code: `RulesFileWriter`
(single canonical serialization path for `.dochygiene-rules.json`; tier-grouped,
glob-sorted, idempotent, unknown fields warn-and-round-trip) and `NominationIntakeFilter`
(deterministic Step 3.5 — exact glob+lifetime repeats dropped, variants annotated via
shortlist match-set intersection, open consults always forwarded) in
`calibrate_helpers.py`; calibrate SKILL.md Steps 3.5/5/6 wired (Open-consults report
section with the three exits; keep verdicts, human declines, and consults all persist
through the writer); `patch_applier.py` extract-then-delete appends the `extracted.md`
vault pointer (keyed off `extraction_target: "cross-repo"` + a skill-supplied
`extraction_pointer`, fail-closed: no pointer → no delete); clean SKILL.md Step 6.5
supplies the pointer metadata. OpenSpec change:
`plugins/os-doc-hygiene/openspec/changes/calibrate-assessment-inventory/`. Suite: 434
passed (26 new unit tests across writer/intake-filter/applier seams).

View File

@ -1,3 +1,6 @@
---
hygiene: frozen
---
# Implementation Process
_Last updated: 2026-07-02_ | _Status: Steps 2a/2b/2d executed — toolchain installed, context fix applied, vault graph built; model selected (qwen2.5-coder:7b); Step 2c (reference set) previously complete. Step 2 fully executed._

View File

@ -0,0 +1,680 @@
source: https://youtu.be/VQy50fuxI34?si=fENPEi7_hFppIftM
Forget Loop Engineering
0:00
It's time for us to talk about loop engineering. I was hoping this would just blow over after a couple weeks. I
0:05
was hoping a cracked engineer would call this stupid phrase what it really is, but no one has. So, I'll do it myself.
0:13
Forget about loop engineering. It's the wrong way to think about building valuable software with agents at scale
0:20
consistently. Loop engineering is a terrible rebrand of the software development life cycle. It's as unclear
0:28
as it is hype-filled. In this video, we simplify loop engineering and call it
0:33
what it really is. If you understand this concept properly, we're going to break down in this video, [music]
0:39
you'll accelerate far ahead of the AI industry. Clarity and simplicity of
0:45
information gives you [music] speed and performance in your work. It's much more
0:50
valuable and helpful to think about building with [music] agents as if you're building developer workflows
0:57
inside your software factory. Your props [music] go into your software factory. A
1:03
specific workflow runs. Each workflow [music] is a combination of code plus agents and then your results [music]
1:10
come out. Forget about loop engineering. Focus your valuable engineering time and
1:16
tokens on building AI developer workflows.
Who Is IndyDevDan?
1:25
So, first off, who am I to go up against big ideas from AI engineers like Boris
1:31
Churnney from Anthropic and Peter Steinberg, now from OpenAI? If you already know who I am and the work I've
1:37
done, or you don't care, skip to this timestamp. My name is Dan Eisler aka Indie Dev Dan. I'm a software engineer
1:43
with over 15 years of EXP. I started out building Adobe Flash games with Action Script 2 and three with my brothers. I
1:50
interned at Blizzard and then I quickly moved into the finance and accounting space programming in C, TypeScript,
1:57
Python, God awful React and God bless Evanu for creating Vue. I was AI coding
2:03
before anyone had a name for it with tools like Ader and classic models like GPT3.5 Turbo, GPT4, and Sonnet 3. Tools
2:12
and models you've probably never heard of or used. I own the domain name agenticengineer.com
2:18
where thousands of engineers you've heard of from companies you know have improved their agentic engineering
2:24
thanks to information products I've built by hand. But anyone can pick up a domain name and create a course though,
2:31
right? Sure. I also have an irrefutable trail of code and content for engineers
2:37
on GitHub and this YouTube channel every single week for years now. You can see
2:42
myself and engineers that follow this channel consistently ahead of the curve of the AI industry. I don't just farm
2:49
news for views like every other tech content creator. On this channel, we think, plan, and build. Every few
2:56
months, it's important for me to sit down and say this. I'm not a content creator. I'm a software engineer that
3:03
does content creation on the side. Why? Because this technology is too valuable
3:09
to fall into the hands of a lucky few. And yes, I sell courses. And yes, I
3:14
benefit from it. Big whoop. Don't do anything you're great at for free. Welcome to capitalism. Enough about me.
3:19
I don't show up here every single Monday to gloat and talk about myself. I show up here to give engineers like you an
3:25
advantage you can use to accelerate your career, your work, your business, your engineering in the age of AI, no hype.
3:33
So, forget about loop engineering and focus on this instead. There are now
Your 3 Actors of Value Creation
3:39
three actors of value creation for engineering work. The engineers like you and I, there are the agents and there's
3:46
the code. Knowing when and where to place each of these is the name of the
3:52
game of agentic engineering. And you might be thinking, where is he going with this? How does this relate to loop engineering and developer workflows?
3:59
Stick with me here. We're going to work up to it. If you master the fundamentals, you'll master the compositions. Everyone in their AI
4:05
psychosis seems to forget code is fast, always runs the same way unless you tell
4:11
it not to. And guess what? It costs nothing. There are no token costs associated with code. the thing that
4:17
truly moves at light speed. There's a hidden cost to implementing every single one of these actors of value creation.
4:25
Everyone's talking about agents. We're all well aware of the cost of engineers, but code is the unsung hero of all of
4:32
this. Consistent value creation creates consistent business value. And out of these three, code is the most reliable
4:39
by miles followed by engineers [music] and then agents. So let's start with the
Your First Ever AI Developer Workflow
4:44
most basic developer workflow.
4:50
An engineer prompts an LLM and the engineer reviews the result. This is the simple foundation that makes up every
4:58
single loop, every single workflow, every single piece of work moving forward. Now, of course, we're not just
5:05
using the LLM anymore. In this central node, we have an agent. Insert your favorite agent. Insert your favorite
5:11
model. It doesn't matter anymore. It's about the workflow that you and I execute every single day. Great. Let's
5:19
scale it up. Now, we have code, agents, and engineers all involved in the
5:24
process. We're building up to more and more advanced developer workflows. You'll notice something really important
5:31
here. We now have code. In this case, we're just running a llinter. We have a condition. If the llinter fails, the
5:37
results go back into our build agent. If they're successful, it passes. This condition and this routing back to our
5:45
build agent creates our first loop. Hence the term loop engineering. But
5:50
loop engineering is too simple. It's too inaccurate. And there's a lot more to this story. So what comes next? How can
5:56
we continue to enhance our developer workflow to get better results? We can of course add more deterministic code.
Adding Code to Your ADW
6:03
Now we have multiple pass fill statements routing back into our build agent. Your codeex, your cloud code,
6:08
your pi coding agent, whatever your agent harness is. This is the foundation of what it means to build with agents.
6:14
Now you have three actors in this. Engineers, agents, and raw code. You
6:20
have to leverage them all in the right location at the right time. Here we're adding a code formatter. It doesn't
6:25
matter what language you're in. linting your code, formatting your code, type check your code, and then keep scaling
6:31
up the validation loops to run back into your agents. Once again, you'll see here
6:37
these conditions is what makes up what is called the loop. But there's a lot more going on here. This is really a
6:44
workflow of how information travels within a system. Okay, keep scaling it
6:50
up. What comes next? We can add more code. A very valuable piece of code here
6:55
is testing your code. So test. Now we take all these results, feed it back
7:00
into our build agent over and over and over until the results all pass. And
7:05
that gives us our final engineering review. You'll notice a pattern here. You and I always show up at the ends.
7:12
These are the two constraints of a gentic engineering. Prompting, also known as planning, and reviewing, also
7:18
known as validation. If you're a gent engineering at scale properly, you're showing up at the beginning and the end
7:25
with a few exceptions. Your AI developer workflows start simple like this, but they should continue to grow. Real
7:31
engineering work looks a lot more complex than this, [music] right? What do we do next?
Scale Your Compute to Scale Your Impact
7:40
We can scale all of our testing, all of our validation, all of our linting, all of our type checking into a single test
7:47
agent. So now we're scaling our compute to scale our impact. We're adding compute to add confidence. Now you can
7:54
imagine we've handed this test agent all the things we want to do to test. And if something goes wrong, we send the
8:01
context back to the build agent. If it passes, the engineer reviews and then we can ship the deliverable. We can ship
8:08
the code. All right. So notice a couple themes working here. As you scale up your developer workflows, you add agents
8:14
and you add code. But what you don't want to add is more engineering effort outside of building the system that
8:21
builds the system. Let's keep scaling this up. Let's add planning to the workflow. You're very familiar with
8:26
these ideas, right? We're building workflows. These are all steps that you and I, the engineer, used to take and
8:33
used to execute ourself, right? We would plan work, we would build the work, we would test the work, we would then have
8:40
another engineer review the work, and then we would finally ship it into production. All right? It's a developer
8:45
workflow and all we've done here is added AI to it. The loops is just one
8:50
piece of it. You can call it loop engineering but it's inaccurate and it's not encapsulating the whole picture. If
8:55
we have loop engineering, we need to have condition engineering and then we need to have function engineering and then we need to have a word plus
9:02
engineering for every type of control flow inside of the software development life cycle which is going to go on
9:07
forever. Okay. So a very popular pattern is to push each one of your agents into
9:13
their own work tree. This creates isolation. This creates parallelism. This lets you do more work in parallel.
9:19
And there's a nice side effect here where the agents don't trip over each other. So, guess what we're going to do?
9:24
We're going to write another prompt. And this time, we're going to write a prompt into a piece of code that's going to
9:31
build our work trees. All right. So, here we have a deterministic piece of code that's going to kick off multiple
9:37
work trees based on the prompt. And then we're going to execute several different agents running in line. So we have once
9:44
again scaled our compute to scale our impact. We have multiple work trees
9:49
running our plan, build, test, review, merge, ship pipeline, our developer
9:56
workflow. The workflow you and I used to go through as engineers building by
10:02
hand. Now we have AI, hence AI developer workflows. And this is really important
10:07
to think through. This is where you should focus in your engineering time. How can I combine the three actors of
10:14
value creation, engineers, agents, and code to create workflows that execute
10:20
large amounts of work on my behalf, on behalf of my company, on behalf of your users and products? That's the name of
10:27
the game. Okay, so great, we have work trees. Work trees are um like I like to say, a great place to start, not a great
10:34
place to end. There are a lot of problems with work trees. We can do one better by giving our agents each their
10:40
own sandbox. Okay? So instead of spinning up work trees, we're now giving every single agent their own computer,
10:47
right? Their own agent sandbox to operate. Because once you do this, you have full isolation. You yourself can
10:54
jump into the sandbox to look at the work, look at the result, look at the web page, look at the tests, look at the
11:00
application, whatever you need to do, do your review. And then of course once all the work comes back in you merge and you
11:06
ship. So once again notice the three actors of value creation working together. And notice how your ability to
11:14
create these AI developer workflows is your ability to scale your impact with
11:19
agents. It's designing these AI developer workflows that is the most value accreative thing an engineer can
11:26
do. Hence the term I like to say on the channel all the time. You want to be building the system that builds the
11:33
system. Okay? As you can see here, you'll start to see similarities in these workflows with a lot of work
11:39
you've seen, a lot of work that you've done, and hopefully work that you're building into your teams, your
11:44
co-workers, your business, your tools themselves. Okay? We're just getting started, [laughter] right? Uh real work
11:51
gets more and more complex. And this is the art and science of agentic engineering. So, let's keep scaling it.
The Kanban Queue
12:02
A very common thing to do as you continue to progress is to set up a conbon board, some type of ticket
12:09
system. Input comes from all over your organization, right? It comes from support, it comes from product, and it
12:14
comes from engineers, right? So now things get interesting because now we have a new unit, a new wrapper around
12:20
our code, right? We have some type of ticketing system. And so once again, like there's this really important delineation that I make inside of
12:28
tactical agentic coding. And it is this idea of the agentic layer. The agents,
12:33
the prompts, the skills, the system prompts that wrap your application are
12:39
the thing to be focused on right now. Because when you put those together with your code, with your system, with your
12:45
entire team and your organization, you are agentic engineering. Agentic engineering is not just about the
12:51
agents. Spoiler alert, it's about your team and most importantly your users and putting together the most valuable stack
12:58
of the actors of value creation. Okay, so conbon board, right? Let's let's jump into this. What does this look like?
13:04
Okay, so for most teams, your tickets are then analyzed by your engineer who actually knows what's going on and
13:10
they'll translate that into a mid to low-level prompt that you'll then pass into another full workflow, another
13:17
agent sandbox. But some advanced teams if you're teaching your organization how to write prompts well enough and as
13:23
models become more capable uh you can skip your engineer input prompt here right because your engineer's job should
13:29
be building the system we act on the meta layer we act on the layer that can compound across our organization okay so
13:35
advanced teams can skip the engineering prompt if this step is done properly all right but so you know this is code right
13:42
conbon boards it's just code there are no agents there then we enter the meat of our workflow where we run code to
13:48
move that ticket into planning. Guess what happens next? Our agents take over the pipeline. We'll have a scout agent
13:54
look for all the code, look for all the tickets, look for all the documentation, look for previous spec files, and then
13:59
it'll hand that to a plan agent. Right? So, we're splitting up our searching and our planning between two agents here.
14:05
Once again, scaling compute, scaling impact. And after that happens, you know, plan phase is complete. So, we run
14:11
code to update our ticket to move context to do some specific work inside of our sandbox. And then of course our
14:17
build agent kicks off. And you know what happens from here. You've done it a million times yourself. And now with
14:23
agents, your build agent moves it into testing after it's done. And then your test agent tests, right? This individual
14:30
loop, which is just one part of the developer workflow, executes until the result passes. And then we're going to
14:37
run our CI/CD. And guess what can happen here? This can pass or it can fail and
14:42
go right back to the build agent to resolve the issues. All right. And then we get outside the sandbox. Engineer
14:47
reviews the code. You know what this looks like now? Fail, pass, ship. Right? So you can see this is much more than
14:54
just prompt engineering. It's much more than context engineering. It's much more than harness engineering. It's much more than loop engineering. This is about how
15:00
teams move as an organism with all the actors inside. Okay? And if you're a
15:07
small solo dev shop, same deal, right? It's about how you and your agents work together with code to generate valuable
15:15
results. But this isn't the end. The future of engineering is vast. Okay, let's keep pushing this. What happens
15:21
next? Let's let's imagine another scenario here. Imagine you have a support crisis. Production is down.
Production Goes Down
15:28
Okay, production has crashed. So, what AI developer workflow do you have planned in your organization right now
15:35
when production goes down? How are you leveraging engineers, agents, and code
15:40
to resolve this issue and to stop your business from leaking cash as your production system is down? Let's walk
15:47
through it, okay? Because we've thought through this, right? We've designed, we've architected the AI developer
15:53
workflow to account for this situation. Support files a ticket. In our case here, this goes right to Slack. It goes
15:58
right to Teams, goes right to your communication channel, and one of your cracked engineers picks this up immediately. What do they do? They
16:04
prompt a scout agent that routes right into a hot fix agent. Your hot fix agent
16:10
has a specialized set of mental memory. It's an agent expert that knows and is
16:16
prioritized to get things fixed. It's not doing things the right way. It's not doing things the fancy way. It's not
16:21
optimizing anything. It's getting the fix out ASAP and nothing else. This is a surgical hotfix agent, a custom agent
16:28
that you have specialized, that you've templated your engineering into. Now, what happens here? Human in the loop.
16:34
This is a hot fix. We need to know the solution is going to work. So you put in human effort, right? You use engineering
16:39
effort to approve or reject. This creates a single loop. All right? If we approve, guess what happens? We're going
16:45
to build up a bunch of sandboxes to run the solution in parallel. And guess what? We're using multiple sandboxes. I
16:52
want the first fastest agent that has the solution to win. Okay? Whatever your compute budget is, you'll scale this up.
16:57
You'll scale this down. If you're in a production system that's complex, you might want three, five, 10 agents
17:02
running and racing toward a solution in their own agent sandbox, you don't care. You have the compute, you've done the agentic engineering to scale your
17:09
impact. And guess what happens here? You already know what happens. It runs its individual loop in their sandbox. And
17:15
then it passes or fails. If it fails, it goes right back to your hot fix agent and to you to resolve. And of course, if
17:21
it's all successful, you the engineer validate it and you get the hot fix shipped ASAP. Okay. A question for you
17:28
and your organization. Do you have an agentic workflow for production crashes? Can you get that resolved in record time
17:35
using the three actors of value creation in the age of agents? Engineers, agents,
17:41
and code. All three. Okay, this continues to scale and scale and scale.
17:46
Let's push these workflows further. After some point, what you get is a structure like this.
The Software Factory
17:57
And this is what really starts turning into a software factory. Okay, you'll see here we have many different types of
18:04
specialized agent sandbox workflows. Some are for chores, one is for a bug,
18:09
one is for a feature, one is for this hot fix that we just walked through. And you get the idea here, right? Any
18:15
specialized AI developer workflow you need can be built and routed to thanks
18:21
to your routing system. Okay, this is the art and science of agentic
18:26
engineering, right? This is all of it put together. The loops are just one small piece of this picture. I hope you
18:32
can see that. Now, in all this is a great level of prompt context harness
18:38
engineering. There are a million ways to do this. There are a million different multi- aent orchestration patterns to
18:45
build into this. The key here is this. is that you have the right combination
18:51
at the right time to push engineering work through end to end with agents with
18:57
code with engineers. Okay, I know I'm repeating myself. I'm doing it on purpose. Most success in any domain is
19:04
about doing a few things and saying a few things and focusing on a few things over and over and over. Let's walk
19:11
through a full software factory. You can imagine how this looks, right? Let's keep with a conbon ticket example. Now,
19:18
anyone can file a ticket. This is a feature. This is a bug. This is a chore. Advanced teams are going to skip wasting
19:24
engineering time transferring your conbon ticket into a low-level or mid-level engineering breakdown of what
19:31
needs to happen. Advanced teams are going to go right to kicking off a software factory. The moment your conbon ticket lands, once the factory starts,
19:37
it's going to mark that ticket in progress and move it. And now we have a factory router agent. This could just be
19:43
a simple LLM call. This could be some deterministic code. The exact nodes are
19:48
up to you to decide, but you get the idea here. I'm going to throw a factory agent here to intake the results. Do a
19:55
quick look at the codebase, understand what AI developer workflow we need to execute for the system. First though,
20:01
we're going to set up a sandbox. We're not limiting our agents anymore. We know that agents are going to continue to
20:07
expand. This is what the CPU crunch is all about. CPUs are getting wiped off the board outside of scaling RL and
20:14
other ML engineering related work. Agent sandboxes are going to, I can guarantee you this, be the majority of computers
20:20
out there in the world. You and I will be using fewer and fewer devices while our agents continue to scale up and use
20:25
more sandboxes. Okay, but set up the sandbox. After that, our agent has already decided what type of workflow we
20:31
need to get the job done at the best price, at the best performance, and at the right speed. Because as you likely
20:37
know, you're not going to run your hot fix AI developer workflow or your feature AI developer workflow where
20:43
you're scaling out your very best agents. Maybe your build agent is a workhorse model, but your planner and
20:48
your scouters are going to be state-of-the-art model so nothing gets missed. Of course, there's a whole slew of multi- aent orchestration work that
20:55
can happen here. But the whole point is you're not going to deploy your heavy AI developer workflows for a chore, right?
21:00
for your chore. Throw a single agent at this with a workhorse model, maybe even a lightweight model. Build it, run the
21:06
lint, run the CI/CD, engineer reviews it, and ship it out. We'll talk about ZTE in a second, but the best teams are
21:12
going to start dropping off engineering review because they've built the best system possible that they know is going
21:18
to execute for them. But every single unique workflow is unique for a reason,
21:24
right? There are multiple workflows you want to build out here, multiple AI developer workflows you should be building out, not just one. I'll give my
21:30
recommendation some really, really great practices you can use when building these out in a moment here. But the
21:36
general rule of thumb is just to start simple. Once you start scaling this up, what you're going to end up with is a
21:41
software factory. A software factory that can operate your application as
21:46
well. And if you're doing it right, better than you and your engineering team. This is why all your effort, all
21:52
of your effort goes into this. Now, the agentic layer, right? This is the al the
21:57
agentic layer, not the app layer. The app layer is for your agents. The the
22:03
best engineering teams never touch the product themselves. Okay, I know this might be like controversial. Some
22:09
engineers are going to hate hearing this, but the best teams are doing meta work on the agentic layer. They're
22:16
building the system that builds the system. That is the central thesis inside of tactical agentic coding.
22:22
Thousands of engineers know that and you're going to figure it out too sooner or later. Okay, that doesn't mean you can't jump into the app to do work. But
22:29
when you have a successful product scaled with users, the name of the game is this. Building a software factory
22:37
that operates everything better than you alone could, better than code alone could, and better than agents alone
22:44
could. Right? Three actors of value creation, agents, engineers, code. Where does that all lead us? It leads us to
22:50
the simple conclusion that it's not a loop you're after. It's an AI developer workflow. Okay, you might be, you know,
22:56
listening to this and thinking, but you you drew a million loops. Like, isn't this a loop? Fine. If you want to call
23:02
it a loop, I don't really care. I think a loop is too constrained. If you're going to call it a loop, we're going to need if engineer, we're going to need
23:09
throw engineering. We're going to need exception engineering, right? We're going to need to name all these things engineering. This is a developer
23:14
workflow. This used to be what engineers did. Engineers used to decide if something was a chore, if something was
23:20
a bug. We used to write the plan, we used to execute it, so on and so forth. But now we have a new tool and that's
23:26
all it is. It's a new tool. We have agents to work with that gives us AI
23:32
developer workflows. Okay. So at the highest levels of agentic engineering, you're building software factories that
23:39
execute the right work and the right combination of engineers, agents, and code across your organization. Once you
23:45
really start to scale it up, you're going to add your other teammates, right? Your other team members from other cross cutting concerns inside of
23:52
your business. But at the core of it, the engineers are responsible for the code. Okay? I think a lot of orgs are
23:58
going to have a a problem with this once they start scaling in and adding other team members, right? Especially ones
24:04
that can't write clear tickets for the life of them. You've seen this a million times, right? It's the most painful
24:09
thing when your product manager, your your CTO, your your tech lead [laughter]
24:14
just writes a ticket and you have to translate it, right? So there's there's a lot of like, you know, people
24:19
organizational level work to be done here. But you at the end of the day, you know, you the engineer plus the agents
24:25
plus the code making up the AI developer workflow. This is what it's all about. This is where value is going to be
24:31
created at absurd levels, at absurd scales. Because once you get this right,
24:37
here's the dirty secret of all software, right? You already know it. Once you get this right, you set up the right
24:43
guardrails, the right harness, right? Again, prompt, context, harness engineering, all of it. Once you do this
24:48
right, you have a repeatable workflow that you can run tens, hundreds, and thousands of times, delivering
24:54
consistent results to you over and over and over again if you template your
25:00
engineering into the fabric of your AI developer workflows. Okay? And so I've
25:05
been pushing against out of the box agents for a long time. Um, you know, specialization is the name of the game.
25:11
What is a product? What is a company? Right? Unless you're a big tech giant, like a product in a company is a a set
25:18
of people in technology that solve a specific problem for a specific avatar for a specific user for a specific
25:24
customer. By very definition is specialization, right? Your expertise is
25:30
the most valuable thing you have now. And you can template that into your engineering. You can template that into
25:36
your AI developer workflows. All right, this is the greatest leverage point of agentic coding. It's building out these
25:43
full AI developer workflows that puts it all together. Okay, and so you know once again we are pushing away from vibe
25:51
coding. This is not vibe coding. Vibe coding is not knowing how the system works and it's not looking at how the
25:56
system works. Okay, agentic engineering is knowing your system works so well you don't have to look. And that is because
26:03
you the engineer have moved up a layer. You're meta-engineering. You're compounding an advantage by optimizing
26:10
the three actors of agentic engineering engineer code agents into the right
26:16
developer workflow at the right time at the right performance at the right price with the right speed. And after time
26:22
you'll realize something really important is that you'll be building AI developer workflows into your products
26:28
for your customers right with your customers as nodes and then as mentioned with your companies every user that can
26:35
prompt into the system and receive results out the system right you have to design this system it's just another
How to Build Great AI Developer Workflows
26:40
system
26:45
so I've written hundreds and probably thousands of these AI developer workflows by now. So, let me give you
26:50
the oil of everything I've learned so far with what I've seen and what I've recommended to engineers as they're
26:56
building out their ADWs. Um, first off, keep it simple. When you start building these out, start with the simplest
27:02
workflow you can think of, right? And typically that looks something like this, right? After you get an agent
27:07
running, you prompt back and forth and you're babysitting your agent. Everyone knows what this looks like. Just let it lent your code. You know, to be clear,
27:13
so that you can really feel this. Separate this out. I'm not saying write a skill, have your agent build, and then
27:19
at the bottom of the skill, run lint. Separate this out. Use an agent SDK, run
27:24
a build agent, do work, and then run a llinter. And when the llinter fails, pass that back into the build agent with
27:30
the same session ID. You have to separate your code and your agents. Otherwise, you just have an agent
27:36
calling code. That's not what we want. We want separation of concerns all the way through. If that doesn't make sense
27:42
to you right now, don't worry. It'll make sense once you start building it. This is not a big skill where you run a
27:48
hundred different nodes of workflows. There are massive testing, massive validation problems with doing that. And
27:54
then what do you do after that? You add a couple nodes, right? Start solving real problems. Run your type checker,
28:00
run your llinter. If things go wrong, funnel it back into your build agent. What you'll notice here is that you're
28:05
starting to build a larger unit, a larger system that operates without you.
28:10
You show the beginning and the end. the two constraints of agent coding, planning and reviewing, and your system
28:16
does everything else. Okay? And then once you get to a certain point, you'll start separating out your agents. You'll
28:21
start specializing your agents. Maybe you want to separate your front end and your back end. Maybe you want building
28:26
and testing. Again, the key here is just that you separate the context out so that your context can move between
28:33
individual agents and code. When you're starting, remember KISS, keep it simple, stupid. You can absolutely start with
28:40
pure skill-based workflows where it's all one skill outside of the prompt and the review. But as soon as you start
28:47
productionizing, as soon as you run to get serious about your AWS, you must separate code out of the skills because
28:53
that's still your agent running it, right? You have to be super super clear about those steps so that you can set up
28:58
the proper guard rails and information flows in your AI developer workflows. My next really big piece of advice here is
Do It by Hand First
29:04
design your ADWs by doing the work yourself first. For a lot of engineers, this will sound insanely painful, but
29:11
you can like, you know, use your agent in the terminal. Run the build workflow. Do the testing, right? You can still use
29:17
your agent for that. I'm not saying do it by hand. That would be a waste of time now. But what I am saying is whatever workflow you're setting up, run
29:23
it end to end. Step into each node yourself. run the pass, run the condition, watch the functions get
29:30
executed, do the review, and then do the ship to production and then start writing this all as a combination of
29:37
agents, engineers, and code. And I recommend you take something like mermaid. And you know, by the way, this is like a adaptation of mermaid diagram.
29:45
I had an agent create using a plan build test AI developer workflow in one shot. I created a animated application which
29:52
is of course based on a mermaid diagram. Okay, so shout out to mermaid. Shout out to mermaid.live. But that's my second
29:58
piece of advice, right? Walk through it all yourself first. Sit down pencil and a piece of paper or use mermaid or use
30:04
whatever. Really sit down and like write out your workflow. And then lastly, make sure you're not just using agents,
Make Sure You're Not Just Using Agents
30:11
right? Use agents and code. As I mentioned, you can always start with agents and skills, but as soon as you
30:18
start hitting production, as soon as you want to get serious, move some of that skill work into code. This is not just
30:23
about token cost. This is about performance, reliability, and speed. Again, everyone in their AI psychosis
30:28
has like forgotten that speed costs zero tokens. There's no hallucination. It
30:34
does the exact same thing every time. And it literally runs at the speed of light. So, don't overleverage on agents.
30:41
Okay? Balance it out with actual code, right? Code execution. And yes, there's
30:46
information orchestration. There is this is what context engineering is. You're going to need a place for all the
30:52
results in between each step. Yes, it's going to take some time. Yes, it's going to be a little knowing. Yes, during the
30:57
process, you'll wonder, I should just throw this all in the skill. You'll be wrong down the road. I can guarantee you that. I've been there. Don't waste your
31:04
time doing other engineers have already done wrong. Separate it out as you scale this. Okay, so that's the big
31:09
third tip. Use agents and code. Okay, because agents plus code beats either
31:15
alone, especially when you start really scaling these into legitimately large AI
31:20
developer workflows that do serious work for you and your organization. Why? Because you're going to need to test
31:26
this node. You're going to need to test plan into build. You're going to need to test plan into build and to update the
31:32
status and to testing and to fail. This is all still a system you the engineer are responsible for. So keep using great
31:39
classic engineering patterns, isolatable, decoupled, single interface, right? All that stuff matters probably
31:47
even more, right? It matters even more now because once you do it right and you set up your AI developer workflow, it
31:52
gets multiplied hundreds and thousands of times and your agents plus your code can drive the outcomes for you. Okay?
31:59
So, you know, let's step away from the vibes a little bit and let's step out away from the AI psychosis a little bit
32:04
because if we're going to do serious agentic engineering, you need to know what's going to happen in your system.
Tactical Agentic Coding Pitch
32:10
So, if you made it to the end here, I want to just say thank you for trusting me. For everyone that's been with the channel for a while, for years now, you
32:16
know, big shout out to you. I appreciate you trusting me and following along this massive journey of Agentic Engineering
32:21
that we're on. Um, if you want more, I recommend you check out agenticengineer.com, specifically
32:27
tactical agentic coding. As I mentioned, I've been pretty early to a lot of these ideas. In tactical agent coding, you're
32:34
going to hear a lot of what I just said really broken down step by step across eight lessons and then six additional
32:41
upgradable lessons if you're interested. Okay, so the big idea here is AI developer workflows. It's building
32:47
systems that build systems. We're not touching the application layer anymore. We're touching the agentic system, the
32:53
agentic layer that builds it on our behalf. Okay? So, if you want to pay to play, you want to get a big advantage
32:59
that again thousands of engineers that you know of and have heard of at companies you know the names of, they
33:05
are in here and they have gotten the advantage and they are getting the advantage, right? It's tactical agent coding is the first eight lessons you
33:11
can upgrade to agentic horizon to get some upgradeable ideas. really big idea there is of course multi- aent
33:16
orchestration but agent experts is turning out to be a massively banger idea a massively important idea for
33:23
engineering in the age of agents if you want to build true specialists that outperform out of the box agent anyway
33:29
lots more in there's a very clear 30-day refund before you start lesson 4. So if
33:34
you don't like my style or you're not getting the core of it it's fine I don't want you in here if you don't want to be
33:39
30-day refund before you start lesson 4. This is going to be linked in the description for you. Also, I recommend if you vibe with the ideas here, if you
33:46
understand the ideas and you don't want to jump in the tactical agent coding right away, check out this blog. I'll
33:51
link in the description as well, thinking in threads. It covers a lot of the same ideas we've been discussing 99%
33:58
of everything I do here on this channel. It's all free. It's out there for you to understand and master agentic
34:04
engineering. If you made it to the end, do me a favor, like this video, leave a comment, and share it with your coworker
34:09
before your competition sends it to theirs. You know where to find me every single Monday. Stay focused and keep
34:16
building.

View File

@ -0,0 +1,5 @@
{
"name": "cc-architect",
"version": "1.0.1",
"description": "Model-tier-optimized execution plans, scaffolding, and configuration operations for building and managing Claude Code extensions (plugins, skills, workflows, descriptions)"
}

View File

@ -0,0 +1,18 @@
# Changelog
## [Unreleased] - 2026-01-26
### Breaking Changes
- **agent-architect → workflow-architect:** The agent-architect skill has been renamed to workflow-architect. It now teaches creating workflow documents for general-purpose subagents instead of creating custom agent files.
- **agents/ directory removed:** Custom agent files are no longer used. Skills dispatch general-purpose subagents with workflow documents.
- **commands/ directory removed:** Standalone commands are deprecated. All functionality is accessed via skills (`/skill-name`).
### Changed
- **slash-command-architect:** Now marked as legacy-maintenance only. For new functionality, use skill-architect to create skills instead.
- **SKILL.md files condensed:** Reduced from ~40-55 lines to ~13-17 lines. Theory removed, workflow routing preserved.
- **Workflow files condensed:** Reduced by ~38% on average. Goal/Why sections removed, step sequences and templates preserved.
- **Task tool invocations:** Changed to use Skill tool with `/description-architect` instead of invoking custom agents.
### Migration Details
- Aligned with `references/plugin-architecture-philosophy.md`
- Backup available at `~/dev/backup/cc-architect-2026-01-25/` (delete after 2026-03-25)

View File

@ -0,0 +1,80 @@
# CC Architect
Build Claude Code extensions: plugins, skills, workflows, commands, and descriptions.
## Entry Point
**Use `/cc-architect` for everything.** It analyzes your request and orchestrates the appropriate workflows automatically.
Examples:
- "Create a new plugin for X"
- "Add a skill to the Y plugin"
- "Audit my skill for compliance"
- "Write a description for this component"
The orchestrator reads the workflow catalog, builds an execution plan with optimal model tiers, and coordinates subagents to complete your request.
## Architecture
```
User request
|
v
/cc-architect (reads SKILL.md)
|
v
Planner subagent (Sonnet)
- Reads workflows/catalog.md
- Builds execution plan with model tiers
|
v
Execution subagents (per plan)
- Haiku: scaffolding, validation, cleanup
- Sonnet: drafting, analysis
- Opus: synthesis, quality decisions
|
v
Final output presented to user
```
## Available Workflows
The orchestrator can invoke any of these (see `workflows/catalog.md` for details):
| Category | Workflows |
|----------|-----------|
| Plugin | create-plugin, plugin-add-skill, audit-plugin, improve-plugin-docs |
| Skill | create-skill, audit-skill, improve-skill |
| Workflow | create-workflow, audit-workflow, improve-workflow |
| Description | generate-description |
| Command (legacy) | create-command, audit-command, improve-command |
## Shared References
**Knowledge philosophy** (`references/knowledge-philosophy.md`)
Document what AI doesn't know from training: rubrics, templates, process steps, custom conventions.
**Progressive disclosure** (`references/progressive-disclosure/`)
Knowledge architecture for non-code files. Creates navigable tree structure for just-in-time discovery.
**Self-improvement** (`references/self-improvement/`)
Reflection step for every workflow. After completing any task, identify friction for future improvements.
**Tool patterns** (`references/tool-patterns/catalog.md`)
Patterns for robust tools: audit, verification, brainstorming, reversion protection.
---
## Legacy Skills (Removed)
The following individual architect skills have been **removed**; their functionality was folded into `/cc-architect`'s workflows. Some workflow docs still reference these by their old names (`skill-architect`, `slash-command-architect`) — treat any such reference as a pointer to the replacement workflow below, not to a live skill directory.
| Legacy Skill | Replacement |
|--------------|-------------|
| `/plugin-architect` | `/cc-architect` + create-plugin workflow |
| `/skill-architect` | `/cc-architect` + create-skill workflow |
| `/workflow-architect` | `/cc-architect` + create-workflow workflow |
| `/slash-command-architect` | `/cc-architect` + create-command workflow |
| `/description-architect` | `/cc-architect` + generate-description workflow |
These no longer exist at `skills/{name}/SKILL.md`; only `skills/cc-architect/SKILL.md` remains.

View File

@ -0,0 +1,7 @@
---
description: "Model-tier-optimized execution plans and scaffolding for building Claude Code extensions"
---
Invoke the cc-architect skill.
Read and follow: `skills/cc-architect/SKILL.md`

View File

@ -0,0 +1,359 @@
# CC-Architect Migration Plan
## Overview
Migrate cc-architect plugin to align with `plugin-architecture-philosophy.md`.
**Backup:** `~/dev/backup/cc-architect-2026-01-25/` (delete after 2026-03-25, 60 days)
**Philosophy Core Principles:**
- Skills dispatch general subagents (no custom agents)
- Commands consolidated into skills (skills are directly invocable)
- SKILL.md as 6-8 line dispatcher
- Workflows contain rubrics/templates/steps only (no theory)
- Trust AI knowledge; don't pre-document what AI knows
---
## Phase 0: Pre-Flight Checks
**Subagent:** Sonnet
**Purpose:** Resolve architectural paradoxes and validate prerequisites before migration.
### 0.1 Backup Validation
- Verify `~/dev/backup/cc-architect-2026-01-25/` exists and is complete
- Confirm backup is restorable (test copy one file back)
- Check available disk space
### 0.2 Resolve Agent-Architect Paradox
**Problem:** agent-architect skill teaches custom agent creation, but philosophy says "Custom agents are relics."
**Decision options:**
1. **Delete agent-architect** - Remove skill entirely
2. **Transform to workflow-architect** - Teach general subagent + workflow pattern instead
**Resolution:** Transform agent-architect to **workflow-architect** that teaches:
- Creating workflow documents (not agent files)
- Using general-purpose subagent with workflow paths
- This preserves the skill's purpose (helping users extend Claude) while aligning with philosophy
**Execution steps:**
1. `git mv skills/agent-architect skills/workflow-architect`
2. Update `skills/workflow-architect/SKILL.md` frontmatter: `name: workflow-architect`
3. Update `.claude-plugin/plugin.json` skills list (if referenced)
4. Grep for `/agent-architect` or `agent-architect` references → update to `/workflow-architect`
5. Update CLAUDE.md architect table
6. Update workflow files to teach workflow creation instead of agent creation
### 0.3 Resolve Slash-Command-Architect Fate
**Problem:** slash-command-architect teaches command creation, but philosophy says "Do not create new standalone commands."
**Decision:** Keep slash-command-architect for **legacy maintenance only**. Update SKILL.md to clearly state:
- Use for maintaining existing commands
- For new functionality, create skills instead
- Link to philosophy document
### 0.4 Audit Task Tool Invocations
**Action:** Grep all workflow files for `Task tool` or `Task:` invocations of custom agents.
**Known issues:**
- `new-agent.md` line 90 references description-architect agent
- `new-command.md` line 77 references description-architect agent
- `new-skill.md` line 155 references description-architect agent
**Fix strategy:** Identify all occurrences in Phase 0.4. Apply fixes during Phase 4 (workflow condensing) when those files are already being edited. This avoids duplicate file edits.
**Fix:** Update all workflows to use `Skill tool` with `/description-architect` instead of Task tool with custom agent.
### 0.5 Update Reference Docs
**Action:** Update plugin-structure.md and layout docs to mark `agents/` and `commands/` as deprecated/legacy patterns.
**Verification:**
- [ ] Backup validated
- [ ] Agent-architect transformation decision documented
- [ ] Slash-command-architect scope clarified
- [ ] All Task tool invocations of custom agents identified and fix strategy defined
- [ ] Reference docs updated to deprecate agents/commands directories
---
## Phase 1: Delete Custom Agents
**Subagent:** Haiku
**Prerequisite:** Phase 0 complete
**Files to delete (using `git rm`):**
- `agents/skill-architect.md`
- `agents/agent-architect.md`
- `agents/slash-command-architect.md`
- `agents/description-architect.md`
- `agents/plugin-architect.md`
**Before deletion:**
- Verify all workflows updated to not invoke these agents via Task tool (from Phase 0.4)
**After deletion:**
- Remove `agents/` directory if empty
**Verification:**
- `agents/` directory is empty or removed
- No workflow files contain Task tool invocations to deleted agents
- Check plugin.json doesn't reference deleted agents
**Rollback:** Restore from backup
---
## Phase 2: Delete Standalone Commands
**Subagent:** Haiku
**Files to delete (using `git rm`):**
- `commands/skill-architect.md`
- `commands/agent-architect.md`
- `commands/slash-command-architect.md`
**After deletion:**
- Remove `commands/` directory if empty
**Verification:**
- `commands/` directory is empty or removed
- Skills remain invocable via `/skill-name`
- Check plugin.json doesn't reference deleted commands
**Rollback:** Restore from backup
---
## Phase 3: Condense SKILL.md Files
**Subagent:** Sonnet (judgment required for what to keep)
**Target files:**
- `skills/skill-architect/SKILL.md`
- `skills/agent-architect/SKILL.md` → rename to `skills/workflow-architect/SKILL.md`
- `skills/slash-command-architect/SKILL.md`
- `skills/description-architect/SKILL.md`
- `skills/plugin-architect/SKILL.md`
**Transformation:**
From ~40 lines to ~10-15 lines:
```markdown
---
name: skill-architect
description: [keep existing]
---
# Skill Architect
## Workflows
- **New skill:** `workflows/new-skill.md`
- **Improve skill:** `workflows/improve-skill.md`
- **Audit skill:** `workflows/audit-skill.md`
Read `../../references/subagent-pattern.md` for dispatch rules.
```
**Verification (focus-based, not line-count):**
- Theory/explanation removed (architecture details, "why" sections)
- Workflow routing preserved (list of workflows with use-case triggers)
- Reference to subagent-pattern.md included
- Fits on one screen (~25 lines max, but clarity over count)
- All workflow paths correct and resolve
- Description frontmatter preserved
**Rollback:** Restore from backup
---
## Phase 4: Condense Workflow Files
**Subagent:** Sonnet (judgment required for what to keep)
**Prerequisite:** Read condensing rubric (below)
**Target:** All `workflows/*.md` files in each skill
### Condensing Rubric
**Remove (AI knows this):**
- "Goal:" explanations (AI understands task goals)
- "Why:" sections (trust AI reasoning)
- Framework explanations (AI knows frameworks)
- Conceptual overviews (AI has training data)
**Keep (AI doesn't know this):**
- Step numbers and sequence
- Specific file paths (project-specific)
- Templates and output formats (custom conventions)
- Rubrics and checklists (custom criteria)
- Subagent delegation hints ("Subagent: haiku/sonnet/opus")
- Checkpoints ("Confirm with user")
- Task document instructions
**Preserve invariants:**
- Workflows must include subagent hints (per skill-architect/invariants.md)
- Format can be concise but delegation info must remain
**Example transformation:**
```markdown
# Before (verbose)
### 2. Design the structure
**Goal:** Plan the skill's directory layout before creating files.
**Who:** Main agent or general subagent (cheap model).
**Must read:**
- `references/layout/reference.md`
**Do:**
- Map workflows to `workflows/*.md` files
# After (minimal)
### 2. Design structure
Subagent (haiku). Read: `references/layout/reference.md`
- Map workflows → `workflows/*.md`
- Write to task doc `## Proposed Structure`
Checkpoint: Confirm with user.
```
**User checkpoint after each workflow:**
- Show before/after comparison
- Highlight removed sections
- User confirms: "Proceed" or "Restore section X"
**Red flags (stop and review with user):**
- Step numbers changed or removed
- File paths removed
- Templates removed
- Subagent hints removed
- User checkpoints removed
**Verification:**
- Workflow files condensed (aim for 40-60% reduction, prioritize clarity over target)
- All action items preserved
- All file path references preserved and correct
- All templates/rubrics preserved
- Subagent hints preserved (invariant requirement)
**Rollback:** Restore from backup
---
## Phase 4.5: Intermediate Review
**Subagent:** Sonnet
**Purpose:** Catch major issues before final phases
**Check:**
- All condensed SKILL.md files are valid
- All condensed workflow files are functional
- No critical information lost in condensing
- Reference paths still resolve
**Output:** Quick P0-P1 issue list. Fix before proceeding.
---
## Phase 5: Update CLAUDE.md
**Subagent:** Haiku
**File:** `CLAUDE.md`
**Changes:**
- Remove references to deleted agents/commands
- Update task-to-workflow mapping if needed
- Update architect table if agent-architect renamed to workflow-architect
- Ensure skill invocation instructions are clear
**Verification:**
- No dangling references
- All listed skills exist
- Invoke instructions match current structure
**Rollback:** Restore from backup
---
## Phase 6: Validate Structure and Functionality
**Subagent:** Sonnet
**Actions:**
### Structural Validation
- Run any existing validation scripts
- Verify all internal file references resolve
- Check for broken links in reference paths
- Verify no orphaned files
### Functional Testing
For each architect skill:
- Invoke via `/skill-name` (or simulate invocation)
- Verify correct workflow is selected
- Verify subagent dispatch would work
- Complete one simple task if possible
**Output:** List of any remaining issues
---
## Phase 7: Post-Migration Review
**Subagent:** Opus (comprehensive review)
**Scope:** Full review of migrated plugin
**Checklist:**
- [ ] Alignment with plugin-architecture-philosophy.md
- [ ] No regression in capability (all workflows still work)
- [ ] Standards compliance (kebab-case, frontmatter, etc.)
- [ ] Architecture integrity (progressive disclosure maintained)
- [ ] No orphaned files
- [ ] No broken references
- [ ] Reversion protection preserved (invariants, golden examples, decisions)
- [ ] Under-scripting blind spot documented as known issue (from philosophy doc)
**Output:** P0-P3 issue report with recommendations
---
## Phase 8: Documentation
**Subagent:** Haiku
**Actions:**
- Create/update `CHANGELOG.md` (at plugin root: `cc-architect/CHANGELOG.md`) with migration notes
- Document breaking changes:
- agent-architect → workflow-architect rename (if applicable)
- commands/ directory removed
- agents/ directory removed
- Note that slash-command-architect is now legacy-only
---
## Success Criteria
1. **No custom agents** - `agents/` deleted
2. **No standalone commands** - `commands/` deleted
3. **Lean SKILL.md** - Theory removed, workflow routing preserved, fits one screen
4. **Condensed workflows** - Reduced while preserving all action items
5. **No broken references** - All paths resolve
6. **No capability loss** - All workflows still executable
7. **Philosophy aligned** - Passes checklist from philosophy doc
8. **Functional testing passed** - Each skill invocable, each workflow path tested
9. **Reversion protection intact** - invariants.md, examples/golden/, .decisions/ preserved
---
## Execution Order
```
Phase 0 (pre-flight) → Phase 1 (agents) → Phase 2 (commands) → Phase 3 (SKILL.md) → Phase 4 (workflows) → Phase 4.5 (intermediate review) → Phase 5 (CLAUDE.md) → Phase 6 (validate) → Phase 7 (review) → Phase 8 (docs)
```
Each phase completes before next begins. Review after each phase for early issue detection.
---
## Rollback Procedure
If any phase fails critically:
1. Stop migration
2. Document what failed and why
3. Restore from `~/dev/backup/cc-architect-2026-01-25/`
4. Address root cause before retrying

View File

@ -0,0 +1,72 @@
# Phase 0: Task Tool Invocation Issues
This document identifies Task tool invocations that reference custom agents (description-architect, skill-architect, etc.) in workflow files. These issues should be addressed in Phase 4 when those workflow files are being edited to avoid duplicate edits.
## Identified Issues
### Issue 1: new-skill.md
**File:** `/home/jared/dev/cc-plugins/cc-architect/skills/skill-architect/workflows/new-skill.md`
**Line:** 155
**Status:** RESOLVED (Phase 4)
**Original text:**
```markdown
- Generate description via description-architect (Task tool with `description-architect` agent)
- Input: type=skill, name, purpose, triggers from task document
- Output: description string for frontmatter
```
**Resolution:** Updated to use Skill tool invocation with `/description-architect` pattern instead of Task tool with custom agent reference.
---
### Issue 2: new-command.md
**File:** `/home/jared/dev/cc-plugins/cc-architect/skills/slash-command-architect/workflows/new-command.md`
**Line:** 77
**Status:** RESOLVED (Phase 4)
**Original text:**
```markdown
2. Generate description via description-architect (Task tool with `description-architect` agent)
- Input: type=command, name, purpose, triggers from requirements
- Output: description string for frontmatter
```
**Resolution:** Updated to use Skill tool invocation with `/description-architect` pattern. Note that this workflow is in the legacy-maintenance skill slash-command-architect.
---
### Issue 3: new-workflow.md (ALREADY FIXED)
**File:** `/home/jared/dev/cc-plugins/cc-architect/skills/workflow-architect/workflows/new-workflow.md`
**Original line:** ~90
**Status:** ALREADY FIXED during Phase 0
The original file (new-agent.md) had a reference to description-architect on line 90, but this has been removed during the agent-architect → workflow-architect transformation in Phase 0.
---
## Additional Findings
### Other description-architect references (NOT Task tool invocations)
These are not Task tool invocations but references to the description-architect skill in documentation:
1. **Invariants files** - Multiple skills reference "Always generates descriptions via description-architect" as an invariant. These are policy statements, not invocations.
2. **Golden examples** - Multiple golden example files mention description-architect in their workflow descriptions. These are documentation, not invocations.
3. **Redirect files** (`descriptions.md`) - Multiple plugins have redirect files pointing to description-architect. These are navigation aids, not invocations.
These documentation references may need updating in Phase 4 depending on the final architecture decision, but they are not the critical Task tool invocations that need immediate attention.
---
## Resolution Summary
All identified Task tool invocation issues have been resolved in Phase 4:
1. **Issue #1 (new-skill.md):** RESOLVED - Updated to use Skill tool with `/description-architect`
2. **Issue #2 (new-command.md):** RESOLVED - Updated to use Skill tool with `/description-architect`
3. **Issue #3 (new-workflow.md):** RESOLVED during Phase 0 - No Task tool invocations present
The migration to the general subagent pattern with Skill tool invocations is complete.

View File

@ -0,0 +1,130 @@
# Domain Hooks
Architect-specific questions and anti-patterns for brainstorming. Reference the relevant section based on what's being designed.
---
## Skill
### Key Questions
- **Trigger**: When should this skill activate? What user intent or request invokes it?
- **Context needs**: What does Claude need to know to execute? Where does that knowledge live?
- **Boundaries**: What is explicitly out of scope? What should trigger a different skill?
- **Output**: What does success look like? A file? A conversation? An action?
### Anti-patterns to Critique
| Anti-pattern | What to look for |
|--------------|------------------|
| Over-specification | Skill tells Claude HOW to do things instead of WHAT knowledge exists and WHERE |
| Kitchen-sink scope | Skill tries to handle too many scenarios; should be split |
| Missing escape hatch | No guidance on when NOT to use the skill |
| Implementation in SKILL.md | SKILL.md contains code examples or step-by-step procedures instead of pointers to references |
### Progressive Disclosure Check
- Does SKILL.md fit in ~50 lines?
- Are details in referenced docs, not inline?
- Can Claude load context incrementally as needed?
---
## Plugin
### Key Questions
- **Cohesion**: What unifies the skills in this plugin? What's the theme?
- **Boundary**: Where does this plugin's responsibility end? What's adjacent but separate?
- **Dependencies**: Does this plugin depend on others? Should it?
- **User**: Who installs this plugin? What problem are they solving?
### Anti-patterns to Critique
| Anti-pattern | What to look for |
|--------------|------------------|
| Kitchen-sink | Plugin contains unrelated skills that happen to be made by same author |
| Overlapping scope | Skills within plugin have unclear boundaries with each other |
| Missing entry point | No clear CLAUDE.md or SKILL.md directing users to capabilities |
| Dependency bloat | Plugin requires many other plugins to function |
### Structure Check
- Does plugin have clear CLAUDE.md explaining what it offers?
- Are skills cohesive (related purpose) not just co-located?
- Is the plugin installable and usable independently?
---
## Agent
### Key Questions
- **Task fit**: What specific task type does this agent handle? When is it dispatched?
- **Tools**: What tools does the agent need? What tools should it NOT have?
- **Autonomy level**: How much should it decide on its own vs. ask for guidance?
- **Output contract**: What does the agent return to the caller?
### Anti-patterns to Critique
| Anti-pattern | What to look for |
|--------------|------------------|
| Tool overload | Agent has access to tools it doesn't need |
| Unclear boundaries | Agent's responsibility overlaps with other agents or main thread |
| Missing output contract | Caller doesn't know what to expect back |
| Over-autonomy | Agent makes decisions that should be escalated |
### Dispatch Check
- Is it clear when to use this agent vs. doing the work in main thread?
- Does the agent description in Task tool registry accurately describe capability?
- Can the agent complete its task with the tools provided?
---
## Slash Command
### Key Questions
- **Trigger**: What does the user type to invoke? Is it memorable?
- **Input**: What arguments does it accept? What's required vs. optional?
- **Output**: What happens when invoked? File created? Action taken? Skill loaded?
- **Discoverability**: How does user learn this command exists?
### Anti-patterns to Critique
| Anti-pattern | What to look for |
|--------------|------------------|
| Overloaded command | Command does too many different things based on args |
| Unclear invocation | User can't guess what to type |
| Missing feedback | Command runs silently without confirming action |
| Duplicates skill | Command is just an alias for a skill with no added value |
### Naming Check
- Is the command name a verb? (commit, audit, review)
- Is it 1-2 words max?
- Does it conflict with existing commands?
---
## Description (Frontmatter)
### Key Questions
- **Escape hatch**: Does the description help Claude know when NOT to use this?
- **Trigger clarity**: Is it clear what user intent/request activates this?
- **Specificity**: Is it specific enough to avoid false positives?
### Anti-patterns to Critique
| Anti-pattern | What to look for |
|--------------|------------------|
| Too broad | Description matches requests it shouldn't handle |
| Too narrow | Description misses valid use cases |
| Missing negative triggers | No "don't use when" guidance |
| Marketing language | Description sells rather than describes |
### Test
Read the description and ask: "If I were Claude seeing a user request, would this description help me decide correctly whether to use this?"

View File

@ -0,0 +1,118 @@
# Brainstorming Workflow
Refines rough ideas into conceptual designs through drafting, self-critique, and trade-off surfacing.
## When to Use
**Explicit trigger only.** Use when user:
- Asks to "brainstorm" a concept
- Wants to "explore" or "think through" an idea
- Has a nascent idea not ready for implementation
- Requests interactive design refinement
**Do not use** when user provides clear instructions and expects execution. Most interactions are execution-focused - don't add friction by brainstorming unsolicited.
## Core Principles
1. **Draft first, ask later.** Don't pepper the user with questions. Use your judgment to draft, then surface gaps.
2. **Conceptual, not implementation.** Output is design decisions and constraints. The implementing AI decides HOW.
3. **Always checkpoint.** Write a defer file after critique. User can leave or continue - nothing is lost.
4. **Subagents for execution.** If continuing to implementation, dispatch subagents. Keep main thread focused on coordination.
## Workflow
### Phase 1: Understand Intent
Quickly gather context:
- What problem does this solve?
- Who/what consumes it?
- What constraints exist?
If context is clear from the user's input, skip questions. If ambiguous, ask 1-2 clarifying questions max - don't interrogate.
Check domain hooks in `domain-hooks.md` for architect-specific questions.
### Phase 2: Draft Conceptual Design
Generate a complete conceptual draft:
- Purpose and scope
- Key design decisions
- Structure/architecture (conceptual, not file-by-file)
- Constraints and boundaries
- What it explicitly does NOT do
**Adapt scope to input clarity:**
- Nascent idea → high-level design, major decision points
- Clear concept → fuller design with more specifics
- Near-implementation ready → detailed design, edge cases
### Phase 3: Self-Critique
Before showing the user, critique your draft against:
- Alignment with stated intent
- Domain anti-patterns (see `domain-hooks.md`)
- Missing pieces or unstated assumptions
- Over-engineering or unnecessary complexity
Note issues found. Revise draft if issues are clear fixes. Flag trade-offs that need user input.
### Phase 4: Present & Checkpoint
Present the design to the user. Then immediately write a defer file (see `../defer-work/workflow.md`) containing:
- The conceptual design
- Trade-offs requiring decisions
- Issues found during critique
- Tasks to move toward implementation
Tell the user:
```
Design captured to .claude/deferred/YYYY-MM-DD-<topic>.md
Trade-offs to decide:
- <trade-off 1>
- <trade-off 2>
You can:
- Clear context and resume later with "pick up <topic>"
- Continue here - I'll work from the checkpoint
What would you like to do?
```
### Phase 5: Resolution (if continuing)
If user continues:
1. Work through trade-offs with user
2. Update defer file with decisions
3. Use subagents to execute tasks from the defer file
4. Subagents check off tasks as they complete
5. Main thread coordinates, delegates execution
## Output Format
The brainstorming output is a **conceptual design**, not a specification. Example structure:
```markdown
## Purpose
<What this solves, in one paragraph>
## Design Decisions
- <Decision 1>: <choice and why>
- <Decision 2>: ...
## Structure
<Conceptual architecture - components, relationships, boundaries>
## Constraints
- <What this must do>
- <What this must NOT do>
## Open Questions
- <Questions that surfaced during drafting>
```
Keep it scannable. User should understand the design in 60 seconds.

View File

@ -0,0 +1,83 @@
# Plugin Data Convention
Standard convention for plugins that create files in user projects.
## Path Convention
```
.claude/plugin-data/<plugin-name>/<data-type>/
```
Plugins creating files in user projects MUST use this path structure.
## Examples
| Plugin | Path | Purpose |
|--------|------|---------|
| ux | `.claude/plugin-data/ux/audits/` | UX audit findings |
| seo-audit | `.claude/plugin-data/seo-audit/reports/` | SEO audit reports |
| commit | `.claude/plugin-data/commit/history/` | If commit needed state |
## File Naming
Use descriptive, sortable names:
```
<date>-<type>-<subject>.md
```
Examples:
- `2024-01-15-heuristic-checkout-flow.md`
- `2024-01-15-accessibility-homepage.md`
- `2024-01-15-report-full-audit.md`
## Gitignore
User projects should add to `.gitignore`:
```
.claude/plugin-data/
```
This data is transient and project-specific. It should not be committed.
For specific plugin types, consider more granular patterns:
```
# Temporary files
**/.claude/plugin-data/<plugin-name>/tmp/
# Cached data
**/.claude/plugin-data/<plugin-name>/cache/
# Log files
**/.claude/plugin-data/<plugin-name>/*.log
```
## Artifact Lifecycle
When designing functionality that creates plugin data files, consider cleanup needs.
### Lifecycle Types
| Type | Example | Recommended Approach |
|------|---------|---------------------|
| Audit findings | UX heuristic evaluation | Manual cleanup, historical value |
| Temporary state | In-progress work | Auto-archive or TTL-based cleanup |
| Reports | SEO audit summary | Archival policy, version-dated |
### Documentation Requirements
1. **In the skill/workflow**: Document expected lifecycle of created artifacts
2. **In plugin CLAUDE.md**: Add cleanup guidance section
## Plugin Author Checklist
When your plugin creates files in user projects:
- [ ] Use `.claude/plugin-data/<plugin>/` path
- [ ] Choose semantic subdirectory name (audits/, reports/, state/)
- [ ] Document cleanup expectations in workflow
- [ ] Consider if automated cleanup is warranted
- [ ] Add note to generated files about their transient nature
- [ ] Include cleanup guidance in plugin CLAUDE.md

View File

@ -0,0 +1,75 @@
# Defer File Template
Use this structure when creating defer files.
---
```markdown
# Deferred: <Brief Title>
Created: YYYY-MM-DD
Status: In Progress | Blocked | Ready to Resume
## Context
<2-3 sentences: What were we doing? What triggered this deferral?>
## Original Intent
<What is the user trying to accomplish? Capture the goal, not the implementation.>
## Findings
<What did the critique/check surface? List issues, trade-offs, or open questions.>
### Trade-offs Requiring Decision
- [ ] **<Trade-off 1>**: <Option A> vs <Option B>
- A: <pros/cons>
- B: <pros/cons>
- Recommendation: <if any>
- [ ] **<Trade-off 2>**: ...
### Issues Found
- [ ] <Issue 1>: <brief description>
- [ ] <Issue 2>: ...
## Tasks
<Concrete tasks to complete this work. Check off as completed.>
- [ ] Resolve trade-off decisions with user
- [ ] <Task based on findings>
- [ ] <Implementation task>
- [ ] Verify work meets original intent
- [ ] Delete this file when complete
## Resumption Notes
<Any context that would help a fresh session pick this up:>
- Key files: <paths>
- Related docs: <paths>
- Commands to run: <if any>
## Implementation Guidance
When resuming this work:
1. Read this file completely before starting
2. Use subagents (Task tool) for individual tasks - keeps context focused
3. Have subagents check off tasks in this file as they complete
4. Coordinate from main thread, delegate execution to subagents
```
---
## Usage Notes
**Keep it conceptual.** Capture decisions and constraints, not implementation details. The implementing AI has patterns and context to decide HOW.
**Tasks should be actionable.** Each task should be completable by a subagent with access to the file and codebase. Avoid vague tasks like "figure out the approach."
**Trade-offs need options.** Don't just flag a trade-off - present the options and your recommendation. User should be able to decide quickly.
**Include cleanup task.** Always end with "Delete this file when complete" so defer files don't accumulate.

View File

@ -0,0 +1,87 @@
# Defer Work Pattern
Captures work-in-progress to a file so users can resume in a fresh session without losing context.
## When to Use
- After critique/trade-off checks surface issues requiring decisions
- When context window is getting full
- When work is too complex to complete in current session
- When user explicitly requests deferral
## Core Principle
**Always write the file.** Don't wait for the user to say "defer." After any critique or trade-off check, write the defer file immediately. This gives the user options:
1. **Leave** - Context is captured. Start fresh session anytime.
2. **Continue** - Work from the defer file as the task tracker.
Either way, the file exists and nothing is lost.
## Workflow
### 1. Write the Defer File
Location: `.claude/deferred/YYYY-MM-DD-<topic>.md`
Use the template in `template.md`. Include:
- What we were doing and why
- Findings from critique/check
- Open questions requiring decisions
- Concrete tasks to complete the work
### 2. Inform the User
After writing the file, tell the user:
```
Checkpoint saved to .claude/deferred/YYYY-MM-DD-<topic>.md
You can:
- Clear context now and resume later with "pick up <topic>"
- Continue here - I'll work from the checkpoint file
What would you like to do?
```
### 3. If Continuing
When the user chooses to continue (or in a resumed session):
**Use subagents for efficiency.** Dispatch Task tool agents to:
- Read the defer file for context
- Execute individual tasks
- Mark tasks complete in the file
This keeps the main thread focused on coordination, not implementation. The defer file becomes the shared source of truth between main thread and subagents.
### 4. Cleanup
When all tasks are complete:
- Verify the work meets original intent
- Delete the defer file
- Inform the user the deferred work is complete
## File Naming
Format: `YYYY-MM-DD-<topic>.md`
Examples:
- `2026-01-20-skill-brainstorming.md`
- `2026-01-20-plugin-audit-findings.md`
- `2026-01-20-agent-design-tradeoffs.md`
Keep `<topic>` short but descriptive. It's used for resumption: "pick up <topic>".
## Resumption
Users can resume with natural language:
- "pick up skill brainstorming"
- "continue the plugin audit"
- "what deferred work do I have?"
On resumption:
1. Read the defer file
2. Summarize current state
3. Ask which task to tackle first (or recommend one)
4. Use subagents to execute tasks

View File

@ -0,0 +1,102 @@
# Knowledge Philosophy
How to decide what to document in plugins, skills, and workflows.
## Core Principle: Trust AI Training First
AI models know frameworks, best practices, and domain knowledge from training. Don't re-document what they already know.
**Examples of what NOT to document:**
- What Nielsen's 10 heuristics mean
- How WCAG guidelines work
- Standard programming patterns
- Framework APIs and conventions
**What TO document:**
- Rubrics (what to evaluate, severity scales)
- Templates (output formats, task file structures)
- Process steps (sequence of actions, decision points)
- Your specific conventions (naming, file locations)
## Decision Framework
### When to add documentation
Only add explicit documentation when:
1. **Consistent failure** - AI repeatedly gets something wrong
2. **Output variance** - Results vary significantly across runs
3. **Specific rubric needed** - You need consistent scoring/evaluation
4. **Custom template required** - Output must match a specific format
5. **Non-obvious convention** - Your codebase has conventions AI can't infer
### When NOT to add documentation
Skip documentation when:
- AI already knows it from training
- It's explaining theory rather than specifying process
- It's describing a framework rather than applying it
- A quick inline hint would suffice
## Iterate to Specificity
**Start minimal.** Run the skill/workflow. Observe what the AI gets wrong.
**Add incrementally.** Each addition should be:
- The minimum change needed to fix the observed problem
- Targeted at the specific failure, not general improvement
- Testable (you can verify it fixed the issue)
**Resist preemptive documentation.** Don't document "just in case." Document when you have evidence it's needed.
## Workflow Document Formula
Workflow documents should contain:
```
Rubric + Template + Process Steps
(what to + (output + (sequence of
evaluate) format) actions)
```
They should NOT contain:
```
Theory + Explanations + Framework descriptions
(why it + (how it + (what the framework
matters) works) is)
```
## Guidance Levels
| Level | What to specify | What to delegate |
|-------|-----------------|------------------|
| Role/Orchestrator | What workflows to run, when to synthesize, what to present | How workflows execute their evaluations |
| Workflow | What to evaluate, output format, severity scale | How to apply the framework, what the framework means |
| Subagent execution | (nothing - receives workflow doc) | Everything about execution |
## Anti-Patterns
### The Encyclopedia
**Wrong:** 500-line reference doc explaining a framework.
**Right:** 50-line doc with checklist, severity scale, and output template.
### Preemptive Specification
**Wrong:** Documenting every edge case before seeing if AI handles them.
**Right:** Running the skill, noting failures, adding targeted fixes.
### Inline Theory
**Wrong:** Workflow doc starts with "Nielsen's heuristics were developed in 1994..."
**Right:** Workflow doc starts with "Evaluate against these 10 heuristics:"
### Copy-Paste Documentation
**Wrong:** Duplicating framework descriptions from the web.
**Right:** Referencing what AI knows, specifying only your application of it.
## Practical Test
Before adding documentation, ask:
1. **Would a senior AI researcher need this written down?** If they'd know it from training, skip it.
2. **Is this a rubric, template, or process step?** If not, probably skip it.
3. **Did I observe a failure this fixes?** If not, wait until you do.
4. **Is this the minimum change needed?** If not, reduce scope.

View File

@ -0,0 +1,23 @@
# Writing Descriptions
Short guidance for description fields on skills, agents, commands, and plugins.
## Formula
`[Action verb] [what]. [Unambiguous trigger].`
- Action verb (Build, Generate, Create, Run)
- What it does (2-5 words)
- Trigger that prevents an "escape hatch" — a reader should not be able to
rationalize skipping the tool while still doing the task it covers.
Examples:
- skill: `Build Claude Code skills. Use when creating a skill.`
- agent: `Review code against implementation plan. Use after completing a major project step.`
- command: `Stage and commit changes. Use when ready to commit.`
## Full process
For the complete drafting process (reading the formula reference, the
escape-hatch test, and how to return the result), run:
`${CLAUDE_PLUGIN_ROOT}/workflows/generate-description.md`

View File

@ -0,0 +1,75 @@
# Plugin Registration
How to make a plugin discoverable and installable in a marketplace.
## Registry file
`.claude-plugin/marketplace.json` at the host repo's root controls which
plugins are discoverable and installable.
## Adding a plugin
Add an entry to the `plugins` array:
```json
{
"name": "plugin-name",
"source": "./plugin-name",
"description": "Brief description of what it does"
}
```
**Required fields:**
- `name` - Plugin identifier (must match directory name)
- `source` - Relative path to plugin directory (may be nested, e.g. `./plugins/plugin-name`)
- `description` - One-line description for discovery
Prefer the `register`/`unregister` operations of
`${CLAUDE_PLUGIN_ROOT}/workflows/plugin-config.md` (backed by
`plugin_config.rb`) over hand-editing this file — the script verifies the
write and supports `--marketplace_file` to target a marketplace.json
anywhere on disk. If no marketplace file exists at all, marketplace checks
are skipped rather than failing.
## Checklist
1. Plugin directory exists with `.claude-plugin/plugin.json`
2. Entry added to `.claude-plugin/marketplace.json`
3. Description matches between both files
## Verification
After registering, the plugin should be installable via:
```
/install plugin-name@<marketplace-id>
```
## Project-Scoped Installation
After `/install plugin@marketplace --scope=project`:
1. Plugin is registered in `~/.claude/plugins/installed_plugins.json`
2. **REQUIRED**: Enable in project via `/enable-plugin` or manually add to `.claude/settings.json`
Without step 2, the plugin will not activate in the project context.
### Manual Enablement
If not using `/enable-plugin`, create or update `.claude/settings.json` in the target project:
```json
{
"enabledPlugins": {
"{plugin-name}@{marketplace-id}": true
}
}
```
Example:
```json
{
"enabledPlugins": {
"decomposer@cc-plugins": true
}
}
```

View File

@ -0,0 +1,38 @@
# Plugin Structure
Minimal structure for a Claude Code plugin.
## Required
```
plugin-name/
└── .claude-plugin/
└── plugin.json # {"name": "plugin-name"}
```
## Common additions
```
plugin-name/
├── .claude-plugin/
│ └── plugin.json
├── skills/
│ └── skill-name/
│ └── SKILL.md
└── CLAUDE.md # Plugin-specific guidance
```
## Marketplace layout
The standard pattern is a single flat marketplace: each plugin lives as a
top-level directory alongside a `.claude-plugin/marketplace.json` that lists
every plugin's `source` as `./plugin-name`.
Marketplace sources may also be nested (e.g. `./plugins/<name>`) — check the
host repo's `.claude-plugin/marketplace.json` for its actual convention
before assuming the flat layout.
## Creating new plugins
Follow the cc-architect workflow:
`${CLAUDE_PLUGIN_ROOT}/workflows/create-plugin.md`

View File

@ -0,0 +1,39 @@
# What Makes a Good reference.md
`reference.md` is the routing file required in every `references/`
subdirectory (see
`${CLAUDE_PLUGIN_ROOT}/references/layout/skill-structure.md`). It exists so
a model can decide what to read next without opening every knowledge doc.
This file is a pointer to the full pattern, kept here so
`references/layout/` stays a complete map of the layout — the actual
authoring detail lives in progressive-disclosure:
`${CLAUDE_PLUGIN_ROOT}/references/progressive-disclosure/reference-md-pattern.md`
(required sections: what's here table, when to use this module, model
guidance; anti-patterns like duplicating child content or exceeding ~50
lines)
## When to split a reference doc out
A `reference.md` should point to a separate knowledge doc — rather than
inline the knowledge itself — whenever the content stops being "what's
here and when to read it" and becomes the knowledge itself. Concretely:
- The explanation would push `reference.md` past ~50 lines
- The content is only needed for a subset of workflows, not every reader
of this directory
- The doc covers a distinct concept that could stand alone under a
different topic subdirectory
Full splitting criteria (the "always needed together?" test, size
guidelines, how to split, depth limits) are in:
`${CLAUDE_PLUGIN_ROOT}/references/progressive-disclosure/splitting-knowledge.md`
## Quick checklist
1. Table of files/subdirs with purpose + "when to read"
2. "When to use this module" section
3. "Model guidance" (cheap vs. stronger model)
4. No duplication of child file content
5. <=50 lines total

View File

@ -0,0 +1,86 @@
# Skill Structure
The standard anatomy of a Claude Code skill, and how content is split across
it via progressive disclosure.
## Required
```
skills/<skill-name>/
└── SKILL.md
```
`SKILL.md` is routing-only: "when to use" plus pointers to `workflows/*.md`
and `references/*`. It should not inline substantial content — see
`${CLAUDE_PLUGIN_ROOT}/references/progressive-disclosure/splitting-knowledge.md`
for the size guidance that applies here too (SKILL.md itself should stay
<=50 lines).
## Frontmatter expectations
```yaml
---
name: skill-name
description: [Action verb] [what]. [Unambiguous trigger].
---
```
- `name` - kebab-case, <=64 chars, matches the directory name
- `description` - follows the formula in
`${CLAUDE_PLUGIN_ROOT}/references/layout/descriptions.md`; this is the
only field another model sees before deciding whether to open the skill,
so the trigger must be unambiguous
## Common additions
```
skills/<skill-name>/
├── SKILL.md
├── workflows/
│ └── <workflow-name>.md # one file per distinct task the skill handles
├── references/
│ └── <topic>/
│ ├── reference.md # required routing file, see reference.md below
│ └── <knowledge-doc>.md
├── templates/ # repetitive structures to copy/fill
├── scripts/ # mechanical, deterministic operations
└── state/ # gitignored working data, if the skill needs it
```
- `workflows/` - one file per task the skill handles (e.g. "create X",
"audit X"). Each workflow states inputs, subtasks with subagent-tier
hints, and outputs.
- `references/` - knowledge organized by topic subdirectory. Every
subdirectory needs a `reference.md` (see
`${CLAUDE_PLUGIN_ROOT}/references/layout/reference.md`).
- `templates/` and `scripts/` are optional and only added when the skill
has mechanical, repeatable work to offload from the model.
## Progressive disclosure
Splitting is not optional past a certain size — it's how the skill stays
navigable for a model that only reads what it needs:
- SKILL.md: routing only, <=50 lines
- `reference.md` files: <=50 lines, list what's here and when to read each
file, never duplicate the child files' content
- Knowledge docs: target <=150 lines, hard limit ~200 (split if approaching)
- Directory depth: <=3 levels (`references/topic/subtopic/`)
Full splitting criteria (the "always needed together?" test, signs a doc
should split, how to split) live in
`${CLAUDE_PLUGIN_ROOT}/references/progressive-disclosure/splitting-knowledge.md`.
## Reversion protection (optional, added once a skill stabilizes)
- `invariants.md` at skill root - behaviors that must not change without
explicit approval
- `examples/golden/` - golden examples that pin correct behavior
- `.decisions/` - dated decision records
See `${CLAUDE_PLUGIN_ROOT}/references/tool-patterns/reversion-protection.md`.
## Creating a new skill
Follow the cc-architect workflow:
`${CLAUDE_PLUGIN_ROOT}/workflows/create-skill.md`

View File

@ -0,0 +1,89 @@
# Workflow Structure
The standard anatomy of a `workflows/*.md` document, and what makes one
compliant.
## Required sections
```
# Workflow: <Name>
## When to use
## Inputs required
## Output
## Subtasks (or "Phases")
```
- **When to use** - trigger conditions, so a router (human or model) can
match a request to this workflow without reading the whole file.
- **Inputs required** - named parameters the caller must supply.
- **Output** - what gets written and where (file path, or "returned to
caller").
- **Subtasks/Phases** - the ordered steps. Each one states:
- **Who** does it - main thread or subagent, with model tier
(Haiku/Sonnet/Opus) if a subagent
- **Must read** - any file the step needs, if applicable
- **Do** - the concrete instructions
## Ownership clarity
Every subtask/phase must unambiguously assign ownership:
- Main-thread tasks require user interaction or judgment about scope
- Subagent tasks are dispatched with an explicit model tier
- A main-thread step must never silently perform subagent-tier work (file
writes, content drafting) — delegate it
## Completeness checklist
- [ ] Purpose and trigger conditions are clear
- [ ] Inputs are well-defined (names, not just prose)
- [ ] Output format and location specified
- [ ] Every subtask/phase has necessary context (what to read)
- [ ] Verification step included if the workflow modifies files
- [ ] No missing steps in the flow (a reader could execute this cold)
## Quality bar
- Logical step ordering — later steps don't need something an earlier step
hasn't produced yet
- Subagent model assignments match the work (mechanical → Haiku, drafting/
analysis → Sonnet, judgment/synthesis → Opus)
- File artifacts (task docs, scratch files) are passed between phases by
path, not assumed shared context
- No redundant steps
## Minimal skeleton
```markdown
# Workflow: <name>
## When to use
- <trigger 1>
- <trigger 2>
## Inputs required
- **<input_name>** - <description>
## Output
- <what gets written, and where>
---
## Subtasks
### 1. <step name>
Subagent: <main | haiku | sonnet | opus>.
Read: <files this step needs, if any>
**Do:**
- <instruction>
```
## Creating a new workflow
Follow the cc-architect workflow:
`${CLAUDE_PLUGIN_ROOT}/workflows/create-workflow.md`

View File

@ -0,0 +1,166 @@
# Plugin Architecture Philosophy - Review Report
## Summary
The document is well-structured and provides comprehensive guidance for building Claude Code plugins. It successfully establishes a coherent philosophy around skill orchestration, subagent delegation, and workflow composition. However, there are several gaps in implementation details (particularly around friction tracking infrastructure and phase transitions), some inconsistencies with referenced documents, and one reference to a non-existent directory structure.
## Document Reviewed
**Path:** `/home/jared/dev/cc-plugins/cc-architect/references/plugin-architecture-philosophy.md`
**Purpose:** Defines the architectural philosophy for Claude Code plugins, covering plugin hierarchy, lifecycle management, core components (skills, workflows, scripts, hooks), execution model, model selection, and anti-patterns.
**Recent additions reviewed:**
- Plugin Lifecycle section with friction tracking phases
- Command Consolidation decision tree
- Model Selection friction tracking
- Workflow Composition with UX plugin reference
- Known Issues table
- Under-scripting warnings
## Issues Found
### P0 - Blocking (must fix before using document)
**1. Friction directory does not exist**
- **Section:** Plugin Lifecycle > Friction Files (lines 43-48)
- **Problem:** The document specifies friction files live at `.claude/friction/{plugin-name}/{date}-{issue-slug}.md`, but this directory does not exist in the codebase. The friction tracking infrastructure is described but not implemented.
- **Why it matters:** Someone following this document during Active Development would try to write friction files to a location that doesn't exist, with no template or example to follow.
- **Suggested fix:** Either:
1. Create the `.claude/friction/` directory with a README explaining the format and an example friction file, OR
2. Add a note that friction tracking is planned but not yet implemented, with a TODO reference
**2. No definition of "reflection step" referenced**
- **Section:** Plugin Lifecycle > Active Development (line 27), Enabling/Disabling Friction Tracking (lines 61-66)
- **Problem:** The document says "Reflection step runs after every workflow execution" and "The reflection step itself is a workflow that can be attached to any skill's completion phase" but no such workflow exists, and there's no reference to where it would be defined.
- **Why it matters:** A reader cannot implement friction tracking without knowing what this reflection step looks like or how to attach it to a skill.
- **Suggested fix:** Either:
1. Add a concrete example of what a reflection step contains and how it integrates with a skill (e.g. inline in the philosophy doc, alongside `references/self-improvement/friction-reflection.md`), OR
2. Mark this as "planned but not implemented"
### P1 - High (fix soon)
**1. UX plugin reference path is incorrect**
- **Section:** Workflow Composition (line 98), Integration (line 235)
- **Problem:** The document references `../ux/` as the implementation reference. This is a relative path that only works from within the `references/` directory. The actual UX plugin is at `/home/jared/dev/cc-plugins/ux/`.
- **Why it matters:** Someone reading the philosophy document from a different context (e.g., main CLAUDE.md) cannot find the UX plugin.
- **Suggested fix:** Change to an absolute reference from the marketplace root: `ux/` (relative to marketplace root) with a note about where to find it.
**2. UX plugin example doesn't match actual implementation**
- **Section:** Workflow Composition (lines 92-97)
- **Problem:** The document describes three roles (UX Consultant, UX Strategist, UX Architect) with shared workflows. The actual UX plugin only implements UX Consultant in V1, with UX Strategist and UX Architect marked as "Planned for V2+".
- **Why it matters:** The example suggests a more complex multi-role implementation than exists. Readers looking at the actual plugin will be confused by the mismatch.
- **Suggested fix:** Update the example to accurately reflect V1 implementation, or add a note that the example shows the target architecture (V2+) not current state.
**3. Subagent pattern document uses different terminology**
- **Section:** Core Components > Workflows (line 86), Integration (line 232)
- **Problem:** The philosophy document references `subagent-pattern.md` and says findings go to "scratch workspace." But the actual `subagent-pattern.md` uses "scratch/" for findings, while the role-workflow pattern uses "task files." These are different mechanisms.
- **Why it matters:** Unclear whether to use scratch files or task files for subagent findings.
- **Suggested fix:** Clarify that:
- Simple subagents can use scratch files
- Role-Workflow pattern uses task files as shared state
- Update `subagent-pattern.md` to mention task file pattern as an alternative or reference role-workflow pattern
**4. Missing link between "Task File Pattern" and where it's defined**
- **Section:** Plugin Checklist (line 244)
- **Problem:** Checklist item says "Task file template defined (if using task file pattern)" but doesn't link to where the task file pattern is documented.
- **Why it matters:** Reader doesn't know if they should use the task file pattern or what it entails.
- **Suggested fix:** Add a reference: "See `tool-patterns/role-workflow-pattern.md` for task file template structure"
**5. Phase transition criteria undefined**
- **Section:** Plugin Lifecycle > Phases (lines 25-38)
- **Problem:** The phases are described (Active Development, Tuned, Maintenance) but there's no guidance on when to transition between them. What makes a plugin "stable, producing reliable results"? How many sessions without friction before removing the reflection step?
- **Why it matters:** Without criteria, phase transitions become subjective and inconsistent.
- **Suggested fix:** Add concrete transition criteria:
- Active Development → Tuned: "No P0-P1 friction for [N] executions" or "User explicitly marks as tuned"
- Tuned → Maintenance: "No friction of any kind for [M] weeks"
### P2 - Medium (fix when convenient)
**1. Model Selection table differs from role-workflow pattern**
- **Section:** Model Selection (lines 189-205)
- **Problem:** Philosophy says "Workflow execution: Haiku." Role-workflow pattern says "Complex analysis workflows: Opus (when judgment required in workflow)." These aren't contradictory but could cause confusion about when to use Opus for subagent work.
- **Why it matters:** Developers may unnecessarily use Haiku for workflows requiring judgment, degrading results.
- **Suggested fix:** Add nuance to the Model Selection table: "Workflow execution | Haiku (mechanical), Opus (judgment-heavy)"
**2. Scripts section doesn't mention scripts directory convention**
- **Section:** Core Components > Scripts (lines 100-112)
- **Problem:** The section explains what scripts are and signs of under-scripting, but doesn't establish where scripts should live in a plugin structure.
- **Why it matters:** Without a convention, scripts end up in inconsistent locations.
- **Suggested fix:** Add: "Scripts live in `scripts/` directory at the plugin root."
**3. Hooks section missing example hooks.json**
- **Section:** Core Components > Hooks (lines 115-139)
- **Problem:** Mentions "Plugin-level: `hooks/hooks.json`" but provides no example of what this file looks like.
- **Why it matters:** Someone implementing hooks has to guess the JSON schema.
- **Suggested fix:** Either add a brief example or reference a document that shows the schema.
**4. Anti-patterns could link to positive patterns**
- **Section:** Anti-Patterns table (lines 207-218)
- **Problem:** Anti-patterns list fixes but don't link to the documents that explain the correct approach in detail.
- **Why it matters:** Readers know what not to do but may not find the detailed guidance on what to do instead.
- **Suggested fix:** Add references to each fix, e.g., "Use general subagent + workflow document (see `subagent-pattern.md`)"
**5. No example of 6-8 line dispatch**
- **Section:** Execution Model (line 213), referenced multiple times
- **Problem:** "6-8 line dispatch" is mentioned as the target, but no example is provided in this document.
- **Why it matters:** The role-workflow pattern has an example, but someone reading only the philosophy document doesn't see it.
- **Suggested fix:** Add a brief example or explicit reference: "See `tool-patterns/role-workflow-pattern.md` for dispatch template."
### P3 - Low (nice to have)
**1. "Community consensus (Jan 2026)" lacks citation**
- **Section:** General Subagents Over Custom Agents (line 168)
- **Problem:** Claims "Community consensus" but doesn't link to where this consensus was documented or discussed.
- **Why it matters:** Minor credibility issue; readers may wonder where this consensus came from.
- **Suggested fix:** Add a link to the discussion/decision record, or change to "Based on testing and team consensus"
**2. Plugin Hierarchy examples could include more context**
- **Section:** Plugin Hierarchy table (lines 5-9)
- **Problem:** Examples are single words (cc-architect, ux, commit) without brief descriptions of what they do.
- **Why it matters:** New readers don't know what these plugins are.
- **Suggested fix:** Add a brief description column or parenthetical: "cc-architect (meta-plugin for building plugins)"
**3. Known Issues table has only one entry**
- **Section:** Known Issues (lines 220-226)
- **Problem:** A single-entry table feels like placeholder content.
- **Why it matters:** Minor visual inconsistency; suggests more issues should be tracked.
- **Suggested fix:** Either populate with known issues or change format to a simple bullet point until more issues exist.
**4. Checklist could be a reusable template**
- **Section:** Plugin Checklist (lines 237-249)
- **Problem:** Checklist is embedded in the philosophy document. If it needs updates, this document must be modified.
- **Why it matters:** Checklists are operational artifacts that may need independent versioning.
- **Suggested fix:** Consider replacing the inline checklist with a pointer to `templates/audit-checklist-template.md`, which already covers plugin/skill/workflow-specific attributes and can be extended instead of duplicated.
## No Issues Found In
The following areas were reviewed and found to be clear, consistent, and well-documented:
- **Plugin Hierarchy concept** - Clear tiers with sensible dependency rules
- **Core Components > Skills (Orchestrators)** - Clear responsibilities
- **Core Components > Workflows** - Aligns well with knowledge-philosophy.md
- **Main Thread Delegates** - Clear "3 file" heuristic, good anti-bloat guidance
- **General Subagents Over Custom Agents** - Well-argued with clear migration path
- **Command Consolidation** - Comprehensive decision tree
- **knowledge-philosophy.md alignment** - Philosophy correctly defers framework knowledge to AI training
- **deterministic-scripting.md alignment** - Under-scripting warnings are consistent
- **tool-patterns/catalog.md alignment** - References are accurate and bidirectional
## Recommendations
**Immediate (before using document for new plugins):**
1. Add note that friction tracking infrastructure is not yet implemented
2. Fix UX plugin reference path and clarify it shows planned (V2) architecture
3. Add reference to role-workflow pattern for task file template
**Short-term (next documentation pass):**
4. Define phase transition criteria for Plugin Lifecycle
5. Add scripts directory convention
6. Clarify subagent findings location (scratch vs task file)
7. Add dispatch example or explicit cross-reference
**When convenient:**
8. Add example hooks.json schema
9. Link anti-patterns to positive pattern documents
10. Extract checklist to reusable template

View File

@ -0,0 +1,263 @@
# Plugin Architecture Philosophy
## Plugin Hierarchy
| Level | Scope | Examples |
|-------|-------|----------|
| High | Teams/orchestration | cc-architect |
| Medium | Domain specialists | ux, rails-dev, n8n |
| Low | Tools/services | invoice-ninja, commit, push |
Higher-level plugins may depend on lower-level. No circular dependencies.
## Plugin Lifecycle
Plugins move through phases. Friction tracking intensity varies by phase.
```
New/Changed → Active Development → Tuned → Maintenance
↑ | |
└──────────────┴─────── (changes) ───────┘
```
### Phases
**Active Development** - New plugins or plugins with recent changes.
- Reflection step runs after every workflow execution
- Friction logged to central friction directory
- Model uncertainty documented as friction
- Expect frequent iteration
Note: The friction tracking infrastructure described here is planned for V2+. Current V1 implementation tracks friction informally.
**Tuned** - Plugin is stable, producing reliable results.
- Reflection step removed (reduces overhead)
- Friction tracking disabled
- Changes trigger return to Active Development
**Maintenance** - Long-term stable, minimal changes.
- No active friction tracking
- Major changes restart the lifecycle
### Friction Files
Friction files live at user level, outside any project:
```
~/.claude/friction/
{plugin-name}/
{date}-{issue-slug}.md
```
Each friction file uses YAML frontmatter for discoverability:
```yaml
---
plugin: cc-architect
skill: skill-architect
priority: P1
date: 2026-01-25
slug: audit-missing-step
---
```
Body contains:
- What happened (symptoms)
- Suspected cause
- Recommended investigation path
This separation lets friction accumulate without polluting plugin directories. User chooses when to address—urgent issues (P0-P1) get handled fast; optimization opportunities (P2-P3) wait.
### Enabling/Disabling Friction Tracking
Like inserting a debugger breakpoint:
- Add reflection step when developing or debugging a plugin
- Remove when plugin is tuned
- Re-add when making changes
The reflection step itself is a workflow that can be attached to any skill's completion phase.
## Core Components
### Skills (Orchestrators)
- Know available workflows and when to use each
- Dispatch general-purpose subagents with workflow documents
- Define reporting standards and persistence conventions
- Handle user interaction in main thread
- Do NOT execute detail work themselves
### Workflows
- Live in `workflows/` as `.md` files
- Contain: rubrics, templates, process steps
- Do NOT contain: theory, framework explanations
- Can be static (files) or dynamic (runtime-selected)
- Multiple skills/roles can dispatch the same workflow
See `knowledge-philosophy.md` for what belongs in workflows.
#### Workflow Composition
Roles dispatch workflows. Multiple roles can share workflows.
Example from UX plugin:
- **UX Consultant** (audit-focused) dispatches: heuristic evaluation, accessibility audit
- **UX Strategist** (planning-focused) dispatches: journey orchestration, feature prioritization
- **UX Architect** (system-level) dispatches: navigation model design, state-machine mapping
- **Shared workflows**: All roles might dispatch a common "reporting" workflow for consistent output format
Note: This example shows planned V2+ architecture with multiple specialized roles. Current V1 uses simpler single-role approach.
See `ux/` (marketplace root) for implementation reference.
### Scripts
- Deterministic, repeatable tasks
- Binary correctness (valid/invalid, not good/better)
- Pre-analysis before AI judgment
- Verification of work completion
**Under-scripting is a common failure mode.** When AI runs multiple deterministic commands sequentially (e.g., `git status`, `git diff`, `git log`), a script should batch them and return a structured report. Signs of under-scripting:
- AI running 3+ tool calls for data gathering that could be one script
- Same commands executed repeatedly across sessions
- Structured output parsed differently each time
See `tool-patterns/deterministic-scripting.md` for when to script.
### Hooks
Event-driven automation that runs at specific lifecycle points.
**When to use hooks:**
| Use Case | Hook Type | Example |
|----------|-----------|---------|
| Validate before execution | PreToolUse | Block writes to .env files |
| Format/lint after changes | PostToolUse | Run prettier on edited files |
| Inject session context | SessionStart | Load project-specific settings |
| Custom notifications | Notification | Desktop alerts for permissions |
| Control agent stopping | Stop, SubagentStop | Evaluate task completion |
**When NOT to use hooks:**
- Workflow logic that requires AI judgment (use subagents)
- Complex multi-step processes (use workflows)
- User interaction (use skills)
**Configuration levels:**
1. Plugin-level: `hooks/hooks.json` - applies when plugin enabled
2. Component-level: skill/agent frontmatter - scoped to component execution
**Key principle:** Hooks handle mechanical guardrails and automation. Skills handle orchestration and judgment.
## Execution Model
### Main Thread Delegates
Main thread responsibilities:
- Understand request
- Select workflow
- Create task file (if using task file pattern)
- Dispatch subagent
- Synthesize returned findings
- Present to user
Main thread does NOT:
- Read more than 3 files for workflow selection
- Execute evaluations
- Accumulate context through exploration
When exploration is needed, dispatch a subagent.
### General Subagents Over Custom Agents
**Decision:** Custom agents are relics. Use general-purpose + workflow documents.
Why:
- Same 294-token base overhead (no efficiency difference)
- More flexible (workflow docs can be composed, selected dynamically)
- No "context gatekeeping" (custom agents hide information from main thread)
- Community consensus (Jan 2026)
Migration path:
1. Extract agent logic into workflow document
2. Update skill to dispatch `general-purpose` subagent with workflow path
3. Delete agent file
### Command Consolidation
**Decision:** Skills are directly invocable with `/skill-name`. Standalone commands are redundant.
**Decision tree for existing commands:**
1. **Plugin+skill already does this** → Delete command (confirm with user first)
2. **Useful functionality, fits existing plugin** → Add as skill to that plugin, delete command
3. **Multiple related commands exist** → Create a plugin to house them as skills
- Example: `commit` command + `repo-init` command → `git` plugin with `commit` and `repo-init` skills
4. **Doesn't fit anywhere** → Case-by-case; may warrant new plugin or remain standalone
**Do not create new standalone commands.** New functionality goes into plugins as skills.
## Model Selection
| Task | Model |
|------|-------|
| Orchestration/synthesis | Opus |
| Workflow execution | Haiku |
| Script implementation | Haiku |
| Trade-off decisions | Opus |
**Default to Opus when uncertain.**
When model choice is uncertain during Active Development phase, log as friction:
- What task triggered uncertainty
- Why Haiku seemed potentially sufficient
- Outcome (did Opus quality justify cost?)
This creates data for future model selection refinement. User can later test Haiku for that task type to evaluate cost/quality tradeoff.
## Anti-Patterns
| Anti-Pattern | Fix |
|--------------|-----|
| Custom agent proliferation | Use general subagent + workflow document |
| Main thread execution | Dispatch subagent, synthesize returned findings |
| Inline workflow content in dispatch | 6-8 line dispatch pointing to workflow path |
| Over-scripting judgment | Script validates format; AI judges quality |
| Under-scripting deterministic work | Batch sequential commands into scripts returning structured reports |
| Command-skill duplication | Delete command or migrate to plugin skill |
| Hooks for complex logic | Move to workflow document |
| Theory in workflow docs | Move to skill description or delete |
## Known Issues
Issues identified but deferred for prioritization.
| Issue | Description | Priority |
|-------|-------------|----------|
| Architect under-scripting blind spot | skill-architect and plugin-architect do not flag sequential deterministic commands as scripting opportunities (e.g., commit skill runs git commands individually instead of via script) | P1 |
## Integration
Works with:
- `knowledge-philosophy.md` - What to document
- `subagent-pattern.md` - When/how to dispatch
- `tool-patterns/role-workflow-pattern.md` - Multi-workflow orchestration
- `tool-patterns/deterministic-scripting.md` - When to script
- `ux/` (marketplace root) - Reference implementation for role-workflow pattern
## Plugin Checklist
When creating or auditing a plugin:
- [ ] Skills dispatch general subagents (no custom agents)
- [ ] Workflows in `workflows/` as `.md` files
- [ ] Scripts handle mechanical tasks (watch for under-scripting)
- [ ] Task file template defined (if using `tool-patterns/role-workflow-pattern.md`)
- [ ] Reporting standards documented
- [ ] Model selection follows table
- [ ] Commands migrated to skills or deleted
- [ ] Hooks used only for guardrails/automation (not logic)
- [ ] Friction tracking enabled (if Active Development phase)

View File

@ -0,0 +1,69 @@
# The reference.md Pattern
Every directory in `references/` must have a `reference.md` file. It's the routing layer that tells the AI what's here and when to go deeper.
## Purpose
The reference.md file answers three questions:
1. What knowledge lives in this directory?
2. When should I read each file?
3. Do I need to go deeper into subdirectories?
## Required sections
### What's here
A table listing each file/subdirectory with:
- Name
- Purpose (one line)
- When to read it
```markdown
## What's here
| File | Purpose | When to read |
|------|---------|--------------|
| `foo.md` | Explains X | When doing Y |
| `bar/` | Details about Z | When you need deep Z knowledge |
```
### When to use this module
Brief description of the scenarios where this directory's knowledge applies.
### Model guidance
Hints about whether cheap or stronger models should handle this content.
## Optional sections
- **Prerequisites**: What the AI should know/have before reading this
- **Child topics**: If subdirectories exist, brief descriptions of when to descend
## Anti-patterns
- Don't duplicate knowledge from child files in reference.md
- Don't make reference.md longer than ~50 lines
- Don't skip the "when to read" column - it's the whole point
## Example
```markdown
# Authentication References
## What's here
| File | Purpose | When to read |
|------|---------|--------------|
| `oauth-flow.md` | OAuth 2.0 implementation details | When the API uses OAuth |
| `api-keys.md` | API key authentication patterns | When the API uses simple API keys |
| `rate-limiting.md` | How to handle rate limits | After auth is working, before production |
## When to use this module
You're implementing authentication for an API wrapper and need to understand the auth mechanism.
## Model guidance
Factual/procedural content. Cheap model is fine.
```

View File

@ -0,0 +1,21 @@
# Progressive Disclosure References
How to organize knowledge so the AI reads only what it needs.
## What's here
| File | Purpose | When to read |
|------|---------|--------------|
| `reference-md-pattern.md` | How to write effective reference.md files | When creating a new references directory |
| `splitting-knowledge.md` | When and how to split knowledge docs | When a doc is getting too long, or deciding structure upfront |
## When to use this module
- You're creating reference.md files for a new skill
- You're deciding whether to split a knowledge doc
- A knowledge doc has grown past ~150 lines and needs restructuring
## Model guidance
- Writing reference.md files: cheap model (it's templated)
- Deciding *whether* to split: stronger model (requires judgment about cohesion)

View File

@ -0,0 +1,60 @@
# Splitting Knowledge Docs
When to keep knowledge together vs. split it apart.
## The core question
> "Will these pieces of knowledge always be needed together, or are there times you need one but not the other?"
If always together → keep in one file.
If sometimes separate → split into multiple files.
## Size guidelines
- Target: under 150 lines per knowledge doc
- Hard limit: 200 lines (split if approaching this)
- reference.md files: under 50 lines
## Signs you should split
- The doc covers multiple distinct concepts
- You find yourself scrolling past irrelevant sections
- Different workflows need different parts of the doc
- The doc has more than 3-4 top-level sections
## Signs you should NOT split
- The concepts are tightly coupled (understanding A requires B)
- The doc is under 100 lines and cohesive
- Splitting would create files under 30 lines (too granular)
## How to split
1. Identify the natural boundaries (usually top-level headings)
2. Create a subdirectory if splitting creates 3+ files
3. Move content to new files
4. Update the parent reference.md to describe the new structure
5. Add a reference.md to any new subdirectory
## Depth limits
- Maximum recommended depth: 3 levels (`references/topic/subtopic/`)
- If you need deeper, consider whether this belongs in a separate skill
## Example split
Before:
```
references/
└── api-design.md (250 lines covering auth, pagination, errors)
```
After:
```
references/
└── api-design/
├── reference.md
├── authentication.md
├── pagination.md
└── error-handling.md
```

View File

@ -0,0 +1,95 @@
# Friction Reflection
How to identify and record friction at the end of a task.
## What is friction?
Friction is anything that made the task harder than it should have been.
### Documentation friction
Knowledge docs didn't serve you well:
- Information was missing
- Information was hard to find
- Information was unclear or ambiguous
- You made a mistake because docs were misleading
### Operational friction
Process or architecture caused unnecessary work:
- **Navigation friction**: Too many index files read to reach knowledge (tree too deep)
- **Context friction**: Work in main thread that cluttered context (should've been subagent)
- **Automation friction**: Deterministic subtask that would be faster/reliable as script
## The reflection prompt
At the end of every workflow, ask yourself:
> "Did I encounter friction during this task?"
Consider both documentation friction (docs missing, unclear, hard to find) and operational friction (too many hops, context clutter, scripting opportunities).
**If no:** Proceed to report. No action needed.
**If yes:** Record it in the task document under `## Friction / Improvement Notes`
## What to record
For each friction point, write:
```markdown
## Friction / Improvement Notes
### [target-file-path or process-name]
**Type:** Documentation | Navigation | Context | Automation
**What happened:** Brief description of the friction
**Suggestion:** What would have helped
```
## Examples
### Good friction note
```markdown
### references/layout/skill-structure.md
**What happened:** Didn't explain where project-level skills live vs plugin skills
**Suggestion:** Add a "Where skills live" section with both paths
```
### Bad friction note (too vague)
```markdown
### references/layout/skill-structure.md
**What happened:** Confusing
**Suggestion:** Make it better
```
### Good operational friction notes
```markdown
### Navigation
**Type:** Navigation
**What happened:** Read 4 index files before reaching the actual content I needed
**Suggestion:** Add direct link from CLAUDE.md or flatten the tree
```
```markdown
### Subagent opportunity
**Type:** Context
**What happened:** Ran 15-step verification in main thread, cluttered context
**Suggestion:** Document this as a subagent workflow or script
```
```markdown
### Script opportunity
**Type:** Automation
**What happened:** Manually checked 8 files for the same pattern
**Suggestion:** Create a lint script that checks this automatically
```
## When NOT to record friction
- One-time mistakes that won't recur
- Friction caused by user's unclear requirements (not a docs problem)
- Issues you already fixed in this task
- Extremely minor issues (typos, formatting)
## The goal
Build a trail of actionable improvements that the improvement workflow can harvest later. Quality over quantity.

View File

@ -0,0 +1,58 @@
# Patch Workflow
How to propose and apply improvements to knowledge docs.
## Overview
The improve-docs workflow harvests friction notes from task documents, prioritizes them, and applies targeted patches. This file describes the mechanics.
## Patch format
A patch is a proposed change to a specific file:
```markdown
### Patch: references/layout/plugin-structure.md
**Source:** task doc `new-plugin-foo-2024-01-15.md`
**Change type:** Addition
**Location:** After "## plugin.json format" section
**Content to add:**
> **Path requirements:** All paths in plugin.json must be relative and start with `./`
**Rationale:** Multiple tasks hit friction because this wasn't documented.
```
## Change types
- **Addition**: Add new content (most common)
- **Clarification**: Reword existing content for clarity
- **Correction**: Fix incorrect information
- **Restructure**: Move content or split files
- **Removal**: Delete outdated or wrong content (rare)
## Patch size guidelines
- Keep patches small and focused
- One friction point = one patch
- If a patch would make a file exceed 150 lines, propose a split instead
## Approval levels
Not all patches need the same scrutiny:
| Change type | Approval |
|-------------|----------|
| Addition (small) | Auto-apply OK |
| Clarification | Auto-apply OK |
| Correction | Review recommended |
| Restructure | User approval required |
| Removal | User approval required |
## After applying patches
1. Update any parent reference.md if file structure changed
2. Note applied patches in the task document
3. Consider re-running a workflow that hit this friction to verify improvement

View File

@ -0,0 +1,23 @@
# Self-Improvement References
How skills learn from friction and improve their knowledge docs and processes.
## What's here
| File | Purpose | When to read |
|------|---------|--------------|
| `friction-reflection.md` | How to identify and record friction during tasks | At the end of any workflow, during reflection |
| `patch-workflow.md` | How to propose and apply improvements to knowledge docs | When running an improve workflow |
## When to use this module
- You just finished a task and are reflecting on friction (documentation or operational)
- You're running an improvement workflow
- You want to understand how self-improvement works in this system
- You noticed a scripting opportunity or context management issue
## Model guidance
- Recording friction: cheap model (templated)
- Deciding what friction is worth fixing: stronger model (judgment)
- Writing patches: depends on complexity of the change

View File

@ -0,0 +1,176 @@
# Subagent Architecture Pattern
## Principle
Main thread orchestrates and communicates with user. Subagents handle detail work.
This keeps the main conversation focused. Context bloat in the main thread degrades response quality and loses important details.
## When to Dispatch Subagents
- Task involves reading/analyzing multiple files
- Work can be parallelized across independent concerns
- Detail work would bloat main thread context
- Task has clear, bounded scope a subagent can complete
## When NOT to Dispatch
- Simple, single-file operations
- Tasks requiring ongoing user dialogue
- Work that depends heavily on conversation context
## Model Selection
**Haiku:** Clear, mechanical, straightforward tasks
- File existence checks, YAML validation, pattern matching
- Tasks with unambiguous right/wrong answers
- Cleanup operations (removing temp files, archiving artifacts)
**Sonnet:** Moderate complexity, filtering, intermediate synthesis
- Filtering noise from Haiku research results
- Applying frameworks and patterns to gathered data
- Writing workflows, templates, documentation
- Intermediate decisions within established guidelines
- Pattern application (not pattern creation)
**Opus:** Judgment, analysis, higher-level thinking
- Quality assessments, trade-off evaluation
- Anything requiring interpretation of standards
- Pattern creation and architecture decisions
- Final synthesis and high-stakes decisions
**Default:** When uncertain, choose Opus
- Better to spend more on accuracy than fail cheaply
## Workflow Structure
**Maximum 2-3 subagents per workflow**
- More than 3 subagents indicates over-engineering
- Break complex work into phases, not more subagents
- Consider whether work truly needs delegation
## Phase Structure
Well-designed workflows follow a three-phase pattern:
**Phase 1: Setup + Research (Haiku)**
- Create necessary directories and scratch workspace
- Read files and gather data
- Pattern matching and data collection
- Output: Structured data files in scratch
**Phase 2: Processing (Sonnet)**
- Filter noise from Phase 1 results
- Apply frameworks and patterns to gathered data
- Make intermediate decisions within established guidelines
- Write drafts of workflows, templates, or documentation
- Output: Processed artifacts ready for review
**Phase 3: Synthesis + Cleanup (Opus + Haiku)**
- Opus: Final decisions, quality assessments, generate final output
- Haiku: Remove scratch files, archive temp artifacts
- Output: Final deliverables in correct locations
Not all workflows need all three phases. Simple workflows may only need Phase 1 + Phase 3.
## Single Responsibility
Each subagent should have one clear job:
| Good | Bad |
|------|-----|
| "Check frontmatter validity" | "Check frontmatter and also evaluate description quality and find patterns" |
| "Assess description trigger quality" | "Review the whole skill" |
| "Filter research findings to top 5 relevant items" | "Research everything and also decide what matters" |
## Cleanup Subagent Pattern
**When:** After workflow completion, when temp artifacts exist
**Model:** Haiku (mechanical operation)
**Tasks:**
- Remove scratch files and directories
- Archive temp artifacts if needed for audit trail
- Delete intermediate processing files
- Leave only final deliverables
**Example:**
```bash
# Haiku cleanup subagent prompt
rm -rf .claude/scratch/skill-audit-2025-02-09/
# OR if archiving needed
mv .claude/scratch/skill-audit-2025-02-09/ .claude/archive/
```
## Artifact Handoff
**Key principle:** Subagents write to files, not context.
Main thread should not read subagent outputs into context unless absolutely necessary for user communication. Instead:
1. Subagent writes findings to file in scratch workspace
2. Next subagent reads the file directly (file path passed in prompt)
3. Main thread only reads final deliverables for user summary
**Why:**
- Prevents context bloat in main thread
- Creates audit trail in scratch workspace
- Allows parallel subagent execution
- Enables cleanup without losing work
**Example flow:**
```
Main: Dispatch Haiku to gather data → writes scratch/data.json
Main: Dispatch Sonnet to filter → reads scratch/data.json, writes scratch/filtered.md
Main: Dispatch Opus to synthesize → reads scratch/filtered.md, writes final/output.md
Main: Read final/output.md to summarize for user
Main: Dispatch Haiku to cleanup → rm -rf scratch/
```
## Reporting Back
Subagents write findings to scratch workspace in structured format. Main thread assembles final output.
Example scratch structure:
```
scratch/
structure-findings.md
content-findings.md
quality-findings.md
patterns-findings.md
```
## Adoption for Other Plugins
**Migration steps for existing workflows:**
1. **Identify current subagent usage**
- Count subagents per workflow
- Classify by model tier
- Map to phase structure
2. **Apply 2-3 subagent limit**
- Consolidate over-dispatched workflows
- Break complex workflows into phases
- Consider whether delegation is needed
3. **Add Sonnet tier where appropriate**
- Replace Opus for filtering/processing tasks
- Use for documentation generation
- Apply for pattern-following work
4. **Implement cleanup subagents**
- Add Haiku cleanup at end of workflows
- Remove scratch workspace after completion
- Archive if audit trail needed
5. **Update artifact handoff**
- Ensure subagents write to files
- Pass file paths to next subagent
- Keep main thread context minimal
6. **Document in workflow**
- Mark phases clearly
- Note model selection rationale
- Include cleanup step

View File

@ -0,0 +1,123 @@
# Adaptive Verbosity Pattern
## Purpose
Scale output detail to match task complexity. Simple tasks get minimal output; complex tasks get thorough analysis.
## Applicability
Use this pattern when:
- Skill handles both simple and complex scenarios
- Output length/detail should vary based on input
- User experience suffers from one-size-fits-all output
Do NOT use when:
- Skill always produces fixed output (lookups, status checks)
- User explicitly controls verbosity via flags
- Output is inherently simple (single values, yes/no)
## Core Principle
Before generating output, assess complexity using multiple signals. Use the HIGHEST complexity level indicated by any signal.
## Complexity Assessment
| Signal Type | Minimal | Standard | Detailed |
|-------------|---------|----------|----------|
| Entity count | 1-5 | 6-10 | 10+ |
| Conversation context | Clear what/why from recent messages | Partial context | No context provided |
| Risk indicators | None | Minor (warnings) | Major (secrets, destructive) |
| User request style | Terse ("do it", "commit") | Neutral | Explicit detail request |
**Note:** Entity count thresholds (1-5/6-10/10+) are defaults. Adjust based on domain - e.g., 1-3 may be appropriate for complex entities like database migrations.
**Precedence rule:** If ANY signal indicates higher complexity, use that level.
**Example:** 2 entities (Minimal) + secrets detected (Detailed risk) → Use Detailed level
## Output Formats
### Minimal (simple tasks)
Direct result with single confirmation. No explanatory sections.
**Example - Git commit:**
```
Committed: `fix: correct typo in README`
```
**Example - File operation:**
```
Created: src/utils/helper.ts
```
### Standard (moderate tasks)
Brief summary with key details. Clear action items if needed.
**Example - Git commit:**
```
Staged 4 files:
- src/auth/login.ts (new)
- src/auth/logout.ts (new)
- src/auth/index.ts (updated exports)
- tests/auth.test.ts (new)
Proposed: `feat(auth): add login and logout functions`
Commit? (y/n)
```
### Detailed (complex tasks)
Full analysis with reasoning visible. Structured sections. Recommendations.
**Example - Git commit:**
```
Analysis of 15 changed files:
By concern:
- Authentication (8 files): New OAuth integration
- Validation (4 files): Extracted to shared module
- Tests (3 files): Coverage for above
Recommendation: Split into 3 commits:
1. `refactor(validation): extract shared module` [4 files]
2. `feat(auth): implement OAuth integration` [8 files]
3. `test: add auth and validation coverage` [3 files]
Rationale: Validation refactor is independent, should land first.
Proceed with split? (y/n/single commit)
```
### Warning-focused (risky tasks)
Warnings FIRST and prominent. Risk explanation before any action. Explicit confirmation required.
**Example - Git commit with secrets:**
```
WARNING: Potential secrets detected
Files flagged:
- config/api-keys.json (contains "api_key" field)
- .env.production (environment file)
These files should NOT be committed.
Options:
1. Remove from staging: `git reset HEAD config/api-keys.json .env.production`
2. Add to .gitignore and remove
3. Proceed anyway (NOT RECOMMENDED)
Choice? (1/2/3)
```
## Anti-patterns
| Anti-pattern | Problem | Fix |
|--------------|---------|-----|
| One-size-fits-all | Same verbose output for 1 file and 50 files | Assess complexity first |
| Always verbose | Detailed output when context is obvious | Trust conversation context |
| Always terse | Missing details when complexity warrants | Check entity count and risk signals |
| Ignoring risk | Burying warnings in normal output | Risk signals override other assessments |

View File

@ -0,0 +1,84 @@
# Audit Pattern
Smart implicit audits that run automatically when modifying tools or handling vague requests.
## Purpose
Prevent drift and degradation by auditing before changes, not just when explicitly requested.
## When to Use
**Implicit audit triggers:**
- User asks to "modify" or "update" an existing tool
- User gives vague request like "improve this skill"
- User asks to "add" something to an existing tool
- Any change to a tool that has golden examples
**Explicit audit triggers:**
- User asks to "audit" or "review" a tool
- User pulls a tool from marketplace and wants evaluation
**Skip audit when:**
- Creating a brand new tool (nothing to audit yet)
- User gives specific, unambiguous instructions
- Quick fixes to obvious bugs (typos, syntax errors)
## Implementation Checklist
Tools implementing this pattern must:
- [ ] Define audit scope in workflow (what gets checked)
- [ ] Check for prior decisions in `.decisions/` before auditing
- [ ] Run audit as subagent(s) to keep main thread light
- [ ] Write findings to scratch workspace (gitignored)
- [ ] Classify findings by severity
- [ ] Check golden examples for behavioral impact
- [ ] Record new decisions made during audit
- [ ] Clean up scratch files after user acts on findings
## Workflow Structure
```
1. Detect implicit trigger
└─→ "modify" / "update" / "add to" / vague request
2. Load prior context
└─→ Read .decisions/ for this tool
└─→ Read invariants.md if exists
└─→ Read golden examples
3. Run audit subtasks (parallel where possible)
└─→ Structure audit (haiku)
└─→ Content audit (opus)
└─→ Quality audit (opus)
└─→ Change impact analysis
4. Assemble findings
└─→ Classify severity
└─→ Flag golden example impacts
5. Present to user
└─→ Summary with verdict
└─→ What will change and why
6. Record decisions
└─→ Write to .decisions/
```
## Example Reference
See `${CLAUDE_PLUGIN_ROOT}/workflows/audit-skill.md` for a complete audit workflow implementation.
## Anti-patterns
**Audit theater:** Running audits but ignoring findings. Every significant finding must be addressed or explicitly deferred.
**Audit fatigue:** Auditing every tiny change. Reserve for modifications that could affect behavior.
**Silent audits:** Running audits without telling the user. Always surface findings.
## Cross-references
- [Verification Pattern](verification-pattern.md) - Audits feed into verification
- [Decisions Record](decisions-record.md) - Audits must record decisions
- [Reversion Protection](reversion-protection.md) - Audits check golden examples

View File

@ -0,0 +1,109 @@
# Brainstorming Pattern
Required design refinement for non-trivial concepts before implementation.
## Purpose
Refine rough ideas into clear designs through drafting, self-critique, and trade-off surfacing. Prevents building the wrong thing.
## When to Use
**Required for:**
- New tool concepts (skills, agents, commands)
- Significant architectural changes
- User has nascent idea not ready for implementation
- Multiple valid approaches exist
**Skip when:**
- User gives clear, unambiguous instructions
- Task is purely mechanical (file moves, renames)
- Fixing specific bugs with obvious solutions
- User explicitly says "just do it"
## Core Principles
1. **Draft first, ask later.** Don't interrogate the user. Use judgment to draft, then surface gaps.
2. **Conceptual, not implementation.** Output is design decisions and constraints. Implementation details come later.
3. **Always checkpoint.** Write a defer file after critique. Nothing is lost if user leaves.
4. **Self-critique before presenting.** Find your own issues before the user does.
## Implementation Checklist
Tools implementing this pattern must:
- [ ] Detect when brainstorming is needed (vs execution)
- [ ] Draft a complete conceptual design first
- [ ] Self-critique against domain anti-patterns
- [ ] Surface trade-offs requiring user decisions
- [ ] Write checkpoint to `.claude/deferred/`
- [ ] Give user clear options: leave or continue
## Workflow Structure
```
1. Understand intent (1-2 questions max)
└─→ What problem? Who consumes it? Constraints?
2. Draft conceptual design
└─→ Purpose, decisions, structure, constraints
└─→ Identify script candidates (mechanical, repeatable components)
3. Self-critique
└─→ Alignment with intent
└─→ Domain anti-patterns
└─→ Missing pieces
└─→ Over-engineering
4. Present and checkpoint
└─→ Show design
└─→ Write defer file
└─→ Offer: leave or continue
5. Resolution (if continuing)
└─→ Work through trade-offs
└─→ Dispatch subagents for implementation
```
## Output Format
```markdown
## Purpose
What this solves, in one paragraph.
## Design Decisions
- Decision 1: choice and why
- Decision 2: ...
## Structure
Conceptual architecture - components, relationships, boundaries.
## Constraints
- What this must do
- What this must NOT do
## Open Questions
- Questions that surfaced during drafting
```
## Anti-patterns
**Question barrage:** Asking 5+ questions before drafting anything. Draft with assumptions, then validate.
**Implementation creep:** Including file paths, code snippets, exact structures. Stay conceptual.
**Skipping critique:** Presenting first draft without self-review. Always critique before showing.
**Forced brainstorming:** Brainstorming when user gave clear instructions. Most interactions are execution, not exploration.
## Script Identification
When refining a skill design, identify which components are mechanical vs. judgment-based. Mechanical components (validation, scaffolding, structured transformations) are script candidates—note these in the design output. See [Deterministic Scripting](deterministic-scripting.md) for heuristics and language selection.
## Cross-references
- [Defer Work](../defer-work/workflow.md) - Checkpoint mechanism
- [Domain Hooks](../brainstorming/domain-hooks.md) - Domain-specific questions
- [Deterministic Scripting](deterministic-scripting.md) - When to use scripts vs AI

View File

@ -0,0 +1,82 @@
# Tool Patterns Catalog
Patterns for building robust, self-correcting Claude Code tools (skills, agents, commands).
## Pattern Summary
| Pattern | Purpose | When to Use |
|---------|---------|-------------|
| [Audit](audit-pattern.md) | Smart implicit audits | Modifying existing tools, vague requests |
| [Verification](verification-pattern.md) | Mandatory completion checks | Before claiming any work complete |
| [Brainstorming](brainstorming-pattern.md) | Design decision refinement | Design decisions, new concepts |
| [Reversion Protection](reversion-protection.md) | Prevent behavior regression | All tools with defined behaviors |
| [Decisions Record](decisions-record.md) | Capture audit decisions | During any audit workflow |
| [Deterministic Scripting](deterministic-scripting.md) | Shift mechanical work to scripts | Planning/design, identifying automation |
| [Adaptive Verbosity](adaptive-verbosity.md) | Scale output to complexity | Skills with variable complexity (simple to complex scenarios) |
| [Role-Workflow](role-workflow-pattern.md) | Multi-workflow orchestration | Plugins with 2+ subagent workflows needing synthesis |
## Quick Decision Guide
**Starting a new tool?**
1. Brainstorm the design first (if non-trivial)
2. If orchestrating 2+ subagent workflows with synthesis → use Role-Workflow pattern
3. Identify scripting opportunities (mechanical, repeatable tasks)
4. Define invariants and golden examples (reversion protection)
5. Build with verification hooks
**Modifying an existing tool?**
1. Check for prior decisions (`.decisions/`)
2. Run implicit audit before changes
3. Verify against golden examples
4. Record any new decisions made
**Reviewing a tool?**
1. Run audit workflow
2. Record decisions made
3. Update golden examples if behavior changes were intentional
**During planning/design?**
1. For each component, ask: "Is this mechanical, repeatable, and unambiguous?"
2. If yes → recommend a script (see deterministic-scripting pattern)
3. Choose language based on project context
## Integration Points
These patterns work together:
```
Brainstorming ──→ Design decisions captured
Planning ──→ Script opportunities identified
│ Multi-workflow orchestration? → Role-Workflow pattern
Building ──→ Invariants + golden examples defined
│ Scripts implement mechanical tasks
│ Role-Workflow: Task files + dispatch structure
Modifying ──→ Audit runs implicitly
│ │
│ ↓
│ Decisions recorded
│ │
↓ ↓
Verification ──→ Golden examples checked
Scripts provide deterministic evidence
Role-Workflow: Synthesis step verifies completeness
```
## Model Guidance
| Pattern | Recommended Model |
|---------|-------------------|
| Audit execution - structure | Haiku |
| Audit execution - content/quality | Opus |
| Decision recording | Haiku |
| Brainstorming | Opus |
| Verification | Haiku |
| Golden example comparison | Opus |
| Role-Workflow - research | Haiku |
| Role-Workflow - processing | Sonnet |
| Role-Workflow - judgment | Opus |
| Cleanup | Haiku |

View File

@ -0,0 +1,21 @@
# Cleanup Pattern
Systematic removal of temporary artifacts after workflow completion.
## When to Use
- After audit workflows complete
- After creation workflows succeed
- After any workflow with scratch files
## Model Selection
Always Haiku - cleanup is mechanical.
## What to Clean
- scratch/ workspace files
- Intermediate task file sections
- Temporary validation outputs
## What to Keep
- Final reports
- Decision records
- Task file Summary section

View File

@ -0,0 +1,132 @@
# Decisions Record Pattern
Capture and persist decisions made during audits and reviews.
## Purpose
Prevent re-litigating settled decisions. Create institutional memory for tools.
## Directory Structure
```
<tool-root>/
.decisions/
2026-01-15-description-formula.md
2026-01-18-routing-depth.md
2026-01-20-golden-example-update.md
```
Decisions live in the tool's `.decisions/` directory, committed to version control.
## File Format
```markdown
---
date: 2026-01-20
context: audit / review / modification
decision_type: invariant_change / pattern_adoption / exception
---
# [Decision Title]
## Context
What prompted this decision? What audit or review surfaced it?
## Options Considered
1. **Option A:** Description. Trade-offs.
2. **Option B:** Description. Trade-offs.
3. **Option C:** Description. Trade-offs.
## Decision
We chose **Option B** because [reasoning].
## Consequences
- Golden example X updated to reflect this
- Invariant Y modified/added/removed
- [Other impacts]
## Participants
- Human: [name/handle if known]
- AI: [model used for audit]
```
## When to Record
**Always record:**
- Any change to an invariant
- Updates to golden examples
- Adoption of new patterns
- Exceptions to existing patterns
- Resolutions of audit findings
**Don't record:**
- Obvious bug fixes
- Typo corrections
- Formatting changes
- Decisions made by user without discussion
## Workflow Integration
### During Audits
```
1. Check .decisions/ before auditing
└─→ Load relevant prior decisions
2. Reference prior decisions in audit
└─→ "Per decision from 2026-01-15, X is intentional"
3. Record new decisions during audit
└─→ Write to .decisions/ before completing
```
### During Modifications
```
1. Check .decisions/ for this area
└─→ Understand why things are the way they are
2. If changing a decided behavior
└─→ Create new decision explaining why
3. Reference chain of decisions
└─→ "This supersedes decision from 2026-01-15"
```
## Naming Convention
`YYYY-MM-DD-<topic>.md`
Keep `<topic>` short but descriptive:
- `description-formula.md`
- `routing-depth-exception.md`
- `golden-example-auth-flow.md`
## Implementation Checklist
- [ ] Create `.decisions/` directory in tool root
- [ ] Audit workflows check `.decisions/` first
- [ ] Record decisions during audits (not after)
- [ ] Include context, options, reasoning, consequences
- [ ] Reference prior decisions when relevant
- [ ] Commit decisions to version control
## Anti-patterns
**Decision amnesia:** Not checking prior decisions before auditing. Always check first.
**Over-documentation:** Recording trivial decisions. Keep to substantive choices.
**Orphan decisions:** Decisions without context or reasoning. Future readers need the "why."
**Decision conflicts:** Multiple decisions on same topic without resolution. Use "supersedes" to clarify.
## Cross-references
- [Audit Pattern](audit-pattern.md) - Audits read and write decisions
- [Reversion Protection](reversion-protection.md) - Invariant changes require decisions

View File

@ -0,0 +1,256 @@
# Deterministic Scripting Pattern
## Purpose
Shift mechanical, repeatable work from AI context to deterministic scripts. Scripts improve consistency, reduce context bloat, and let AI focus on judgment-based work.
This pattern applies during skill design and planning phases. The AI should recognize scripting opportunities and recommend them, rather than asking the user unprompted.
## Core Principle
When the AI encounters a task component during planning, it should ask:
> "Is this mechanical, repeatable, and unambiguous? If yes, a script will do this more reliably than I can."
Scripts are not replacements for AI judgment—they're complements. Scripts handle the deterministic foundation; AI handles interpretation and decisions built on that foundation.
## Quick Heuristics
Self-check during planning:
1. **Binary correctness?** - Is the output valid/invalid rather than good/better/best?
2. **Identical execution?** - Would I do this the same way every time?
3. **Structured data?** - Does it involve parsing, transforming, or validating structured formats?
4. **No interpretation?** - Can correctness be determined without judgment?
If 3+ answers are "yes" → strong script candidate.
## Examples
| Task | Script? | Reasoning |
|------|---------|-----------|
| Validate YAML frontmatter | Yes | Binary correctness, structured data |
| Scaffold directory structure | Yes | Deterministic file operations |
| Parse and normalize field values | Yes | Mechanical transformation |
| Check description length limits | Yes | Quantitative constraint |
| Verify naming conventions | Yes | Pattern matching, no judgment |
| Generate boilerplate from template | Yes | Deterministic substitution |
| Evaluate description quality | No | Qualitative judgment required |
| Choose between design approaches | No | Trade-off analysis |
| Assess code readability | No | Subjective evaluation |
| Decide what to include in a skill | No | Requires understanding intent |
### Hybrid Tasks
Some tasks appear qualitative but have quantitative components scripts can handle:
| Task | Script Portion | AI Portion |
|------|----------------|------------|
| Review description | Length limits, forbidden characters, required fields | Clarity, specificity, tone |
| Audit skill structure | File existence, naming conventions, size limits | Content quality, completeness |
| Validate workflow | Required sections present, link validity | Logical flow, clarity |
**Principle:** Extract quantitative guardrails into scripts. Let AI focus on the qualitative judgment that remains.
## Language Selection
Choose language based on project context and tool fit, not personal preference.
### Principles
1. **Match project context** - A Ruby script in a Rails project integrates naturally. A Python script in a Rails project adds cognitive overhead.
2. **Use best-in-class for domains** - Some tools have clear language winners. Playwright is best supported in Python. Data science tasks favor Python. Shell automation favors Bash.
3. **Prefer OOP-capable languages** - Ruby, Python, JavaScript/TypeScript support clean object-oriented design. Bash does not—use it only for simple orchestration or when it's genuinely the best fit.
4. **Consider maintenance** - Who will maintain this script? If the project team knows Ruby, write Ruby. If you're building a general-purpose skill, Python has broader reach.
### Examples
| Project Context | Recommended | Reasoning |
|-----------------|-------------|-----------|
| Rails application | Ruby | Matches project, team knows it |
| Ruby gem | Ruby | Same ecosystem, natural fit |
| General-purpose skill | Python | Broad reach, well-supported |
| Browser automation | Python | Playwright's best support |
| Data transformation | Python | Rich ecosystem (pandas, etc.) |
| Simple file operations | Bash | Lightweight, universal |
| Node.js project | JavaScript/TypeScript | Matches project context |
| Cross-platform CLI tool | Python or Go | Portability matters |
### Anti-patterns
- Writing Bash for complex logic (use a real language)
- Choosing Python for a Ruby project because "Python is more popular"
- Using JavaScript for non-JS projects just because you know it
- Mixing languages within a single skill's scripts without good reason
## OOP Principles
Scripts should follow object-oriented principles for maintainability and evolution. These principles, drawn from Sandi Metz's teachings, apply to Ruby, Python, and JavaScript alike.
### Single Responsibility
Each class/module does one thing. Each method does one thing.
```ruby
# Good: Single responsibility
class FrontmatterValidator
def validate(content)
# Only validates frontmatter
end
end
class StructureValidator
def validate(path)
# Only validates directory structure
end
end
# Bad: Multiple responsibilities
class SkillValidator
def validate_everything(path)
# Validates frontmatter AND structure AND content AND...
end
end
```
### Dependency Injection
Objects receive their dependencies; they don't create them.
```python
# Good: Dependencies injected
class SkillScaffolder:
def __init__(self, file_system, template_loader):
self.fs = file_system
self.templates = template_loader
# Bad: Dependencies created internally
class SkillScaffolder:
def __init__(self):
self.fs = RealFileSystem() # Hard to test
self.templates = TemplateLoader() # Tightly coupled
```
### Small, Composable Objects
Prefer many small objects over few large ones. Compose behavior through collaboration.
```ruby
# Good: Small, composable
validator = CompositeValidator.new([
NameValidator.new,
FrontmatterValidator.new,
StructureValidator.new
])
# Bad: Monolithic
validator = MegaValidator.new # 500 lines, does everything
```
### Immutable Data Where Possible
Prefer transformations that return new objects over mutations.
```python
# Good: Returns new object
def with_updated_name(skill, new_name):
return Skill(name=new_name, **skill.other_attrs)
# Bad: Mutates in place
def update_name(skill, new_name):
skill.name = new_name # Side effect
```
### Tell, Don't Ask
Tell objects what to do; don't ask for their data and make decisions externally.
```ruby
# Good: Tell the object
validator.validate_and_report(skill_path)
# Bad: Ask and decide externally
if validator.has_frontmatter?(skill_path) && validator.frontmatter_valid?(skill_path)
# External decision-making
end
```
## Integration with Workflows
This pattern integrates at two points:
### During Brainstorming
When refining a skill concept, the AI should identify script candidates:
> "This skill involves validating workflow YAML and scaffolding directories. Both are mechanical tasks—I recommend scripts for consistency. The qualitative review of workflow clarity stays with the AI."
### During Planning (new-skill workflow)
Step 2 (Analyze and Plan) should explicitly consider:
- Which components are script candidates?
- What language fits this project?
- What quantitative guardrails can be extracted?
The planning output should list identified scripts before implementation begins.
## Model Guidance
| Task | Recommended Model |
|------|-------------------|
| Writing scripts | Haiku (mechanical, clear requirements) |
| Designing script interfaces | Opus (API design is judgment) |
| Reviewing script correctness | Haiku (mechanical verification) |
| Deciding what to script | Opus (requires understanding intent) |
## Verification
Two distinct concepts:
**Scripts must be verifiable** - Scripts themselves should be reliable and testable:
1. **Exit codes** - 0 for success, non-zero for failure
2. **Structured output** - JSON or clear text for parsing
3. **Idempotent** - Running twice produces same result
4. **Testable** - Can be run in isolation with test inputs
**Scripts as verification tools** - Scripts can serve as verification mechanisms for skills:
```bash
python scripts/validate_skill.py path/to/skill
# Exit code 0 = valid, 1 = invalid
# Output describes any issues found
```
This complements the Verification Pattern—scripts provide deterministic evidence that work is complete and correct.
## Anti-patterns
### Over-scripting
Not everything needs a script. If a task requires judgment, context, or interpretation, keep it in AI domain.
**Signs of over-scripting:**
- Script has many special cases and edge case handling
- Script needs to "understand" content, not just parse it
- Script requires frequent updates as requirements evolve
- Script is longer than the AI instructions it replaced
### Under-scripting
Repeated mechanical work that stays in AI context wastes tokens and introduces inconsistency.
**Signs of under-scripting:**
- Same validation logic described in multiple places
- AI makes occasional errors on mechanical tasks
- Structured data processed differently each time
- No verification possible because there's no script to run
### Wrong Abstraction Level
Scripts should operate at the right level—not too granular, not too broad.
**Too granular:** Separate scripts for checking each frontmatter field
**Too broad:** One script that validates, scaffolds, and generates content
**Right level:** One script for frontmatter validation, one for scaffolding, one for structure checks

View File

@ -0,0 +1,152 @@
# Reversion Protection Pattern
Four-layer system to prevent behavioral regression in tools.
## Purpose
Protect critical behaviors from accidental changes. Make regressions structurally difficult.
## The Four Layers
### Layer 1: Invariants Declaration
Tools declare their behavioral invariants in `invariants.md`.
```markdown
# Invariants
Behaviors that must not change without explicit human approval.
## Critical Invariants
- Description always follows "When/Why, Not How" formula
- Trigger must be unambiguous (no escape hatches)
- SKILL.md must be routing-only (no prose)
## Structural Invariants
- Maximum file depth: 3 levels
- Maximum routing file length: 50 lines
- Required directories: workflows/, references/
```
**Implementation:**
- Create `invariants.md` in tool root
- List behaviors that define the tool's identity
- Distinguish critical (never change) from structural (rarely change)
### Layer 2: Golden Examples
3-5 canonical examples showing correct behavior.
```
examples/
golden/
example-1.md # Input + expected output
example-2.md
example-3.md
```
**Golden example format:**
```markdown
# Golden Example: [Name]
## Input
[The input or request]
## Expected Output
[What the tool should produce]
## Why This Matters
[What invariant this tests]
```
**Implementation:**
- Create `examples/golden/` directory
- Add 3-5 examples covering key invariants
- Each example tests a specific behavior
### Layer 3: Change Impact Analysis
Every audit must analyze impact on invariants and golden examples.
```markdown
## Change Impact Analysis
### Invariants Affected
- [ ] None
- [x] Critical: description formula (explain why)
- [ ] Structural: ...
### Golden Examples Affected
- [ ] None
- [x] example-2.md: output will change because...
### Risk Assessment
[LOW/MEDIUM/HIGH] - [explanation]
```
**Implementation:**
- Include change impact section in every audit
- Flag any changes affecting invariants or examples
- Require explicit acknowledgment for critical changes
### Layer 4: Human Review Gate
Changes affecting golden examples require human approval.
```
Golden example affected?
Yes ──→ Present change to human
│ │
│ ↓
│ Approved? ──→ No ──→ Do not proceed
│ │
│ ↓
│ Yes
│ │
↓ ↓
No ──────→ Proceed with change
```
**Implementation:**
- Detect golden example changes during audit
- Present specific changes to user before applying
- Get explicit approval: "This will change how X works. Proceed?"
- Log approval in decisions record
## Implementation Checklist
- [ ] Create `invariants.md` listing behavioral invariants
- [ ] Create `examples/golden/` with 3-5 canonical examples
- [ ] Audit workflow includes change impact analysis
- [ ] Changes affecting golden examples flagged for review
- [ ] Human approval required for critical invariant changes
- [ ] Approvals logged in `.decisions/`
## Verification
Before completing any modification:
1. Run tool against all golden examples
2. Compare output to expected
3. If any mismatch: flag for review
4. If intentional change: update golden example + record decision
## Anti-patterns
**Invariants creep:** Adding too many invariants makes everything "critical." Keep to 3-7 true invariants.
**Stale examples:** Golden examples that no longer represent real usage. Review annually.
**Rubber-stamp reviews:** Auto-approving golden example changes. Each should be a real decision.
**Missing layer:** Implementing some layers but not all. The system works together.
## Cross-references
- [Audit Pattern](audit-pattern.md) - Audits must check reversion protection
- [Verification Pattern](verification-pattern.md) - Golden examples are verification
- [Decisions Record](decisions-record.md) - Approvals are recorded as decisions

View File

@ -0,0 +1,168 @@
# Role-Workflow-Subagent Pattern
A pattern for building plugins where a Role skill orchestrates multiple Workflows through subagent dispatch.
## When to Use
**Good fit:**
- Plugin has 2+ distinct workflows that produce structured findings
- Workflows execute in subagent context (multi-file analysis, long-running evaluations)
- Synthesis across workflow outputs is needed
- Context bloat is a concern in the orchestrating thread
**Not a fit:**
- Single workflow with no synthesis step
- Workflows that need to share live state (not just task file)
- Simple tools that don't need orchestration
- Tight coupling between workflows requiring shared context
## Components
| Component | Responsibility | State |
|-----------|----------------|-------|
| Thread | User conversation | Persistent |
| Role Skill | Orchestration, synthesis | Reads/writes task file Summary |
| Workflow Document | Framework, rubrics, templates | Static (read-only) |
| Task File | Shared state | Written by role (Context) and subagents (their sections) |
| Subagent | Execution | Ephemeral (discarded after completion) |
## Flow
```
┌─────────────────────────────────────────────────────────┐
│ THREAD (Main Conversation) │
│ ┌───────────────────────────────────────────────────┐ │
│ │ ROLE SKILL │ │
│ │ 1. Understand request │ │
│ │ 2. Create task file with Context section │ │
│ │ 3. Dispatch subagents ───────────────────────────┼──┼──┐
│ │ 4. Wait for completion │ │ │
│ │ 5. Read task file │ │ │
│ │ 6. Synthesize & present │ │ │
│ └───────────────────────────────────────────────────┘ │ │
└─────────────────────────────────────────────────────────┘ │
┌───────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ SUBAGENT (Fresh Context) │
│ 1. Read workflow document │
│ 2. Read task file Context section │
│ 3. Execute evaluation using workflow's framework │
│ 4. Write findings to workflow's section in task file │
│ 5. Return summary to role │
│ [Context discarded after completion] │
└─────────────────────────────────────────────────────────┘
```
## File Structure
```
plugin/
├── skills/
│ └── <role>/
│ └── SKILL.md # Role orchestration logic
├── workflows/
│ ├── <workflow-1>.md # Workflow document
│ └── <workflow-2>.md # Workflow document
└── .claude/<plugin>/tasks/ # Task files (runtime, gitignored)
└── <date>-<role>-<subject>.md
```
## Task File Template
```markdown
# Task: [Workflow Name] - [Subject]
## Context
[Role writes: input parameters, files, goals, concerns]
## [Workflow 1 Name]
Status: Pending
[Subagent writes findings here]
## [Workflow 2 Name]
Status: Pending
[Subagent writes findings here]
## Summary
[Role synthesizes after all workflows complete]
```
## Dispatch Instructions
Keep dispatch prompts brief (6-8 lines), pointing to documents:
```
Execute the [workflow-name] workflow.
Task file: [path]
Workflow: [path]
Read the workflow document for process and templates.
Read task file Context for scope.
Write findings to your section in the task file.
Return a brief summary.
```
## Design Principles
1. **Subagent Containerization** - Fresh context per workflow. Prevents context bloat.
2. **Workflow Documents Over Inline Prompts** - Dispatch instructions reference documents, not duplicate content.
3. **Task File as Shared State** - Only communication channel between role and subagents.
4. **Trust AI Training** - Workflow docs contain rubrics and templates, not explanations of known frameworks.
5. **Role Owns Synthesis** - Role reads full task file, synthesizes across all workflows.
6. **No Concurrent Writes** - One subagent per section. Role owns Summary.
7. **User Drives Iteration** - No automatic retry. User provides feedback, role re-dispatches.
## Anti-Patterns
| Wrong | Right |
|-------|-------|
| 25-line dispatch prompts duplicating workflow steps | 6-8 line dispatch pointing to workflow document |
| Multiple workflows in same subagent | Fresh subagent per workflow |
| Workflow documents as separate skills | Workflows are `.md` documents read by subagents |
| Explaining frameworks in workflow docs | Listing frameworks with severity scale and output template |
| Role returns raw findings | Role synthesizes, prioritizes, presents top issues |
| Subagent manages cross-workflow state | Role manages state, subagent executes one workflow |
## Model Guidance
Align model selection with workflow phases (typically 2-3 subagents maximum):
| Phase | Model | Use case |
|-------|-------|----------|
| Phase 1: Research | Haiku | Data gathering, file scanning, extracting information |
| Phase 2: Processing | Sonnet | Pattern application, filtering research output, applying frameworks, moderate judgment |
| Phase 3: Synthesis | Opus | Role orchestration, cross-workflow synthesis, high-stakes decisions |
**Sonnet tier characteristics:**
- Intermediate processing between research and synthesis
- Apply established rubrics/frameworks to gathered data
- Filter and structure findings for final synthesis
- Lower-stakes decisions (e.g., severity classification, pattern matching)
**Note:** Most workflows use 2-3 subagents. Avoid over-segmentation.
## Implementation Checklist
- [ ] Role skill created at `skills/<role>/SKILL.md`
- [ ] Workflow documents created at `workflows/<workflow>.md`
- [ ] Task file template includes Context section
- [ ] Dispatch instructions are 6-8 lines referencing workflow docs
- [ ] Workflow docs have: framework/checklist, output template, severity scale
- [ ] Role synthesizes findings after all workflows complete
- [ ] No inline duplication of workflow content in skill
- [ ] Task file location gitignored
## Related Patterns
- **[Subagent Pattern](../subagent-pattern.md)** - General subagent guidance
- **[Audit Pattern](audit-pattern.md)** - Single audit workflow (simpler than role-workflow)
- **[Brainstorming Pattern](brainstorming-pattern.md)** - Design refinement before building

View File

@ -0,0 +1,32 @@
# Audit Severity Guide
Shared three-tier severity classification used by all cc-architect audit
workflows (`${CLAUDE_PLUGIN_ROOT}/workflows/audit-plugin.md`,
`${CLAUDE_PLUGIN_ROOT}/workflows/audit-skill.md`,
`${CLAUDE_PLUGIN_ROOT}/workflows/audit-workflow.md`,
`${CLAUDE_PLUGIN_ROOT}/workflows/audit-command.md`).
## Tiers
| Tier | Meaning | Verdict impact |
|------|---------|-----------------|
| **Significant** | Breaks compliance or correctness: missing required structure, broken references, invalid manifest/frontmatter, ambiguous ownership, incomplete flow | 1+ significant → **Not Ready** |
| **Minor** | Works but deviates from convention: missing optional files, inconsistent patterns, suboptimal structure, missing recommended infrastructure | Does not block verdict; must still be reported |
| **Polish** | Cosmetic: wording, formatting, organization | Does not block verdict; optional to fix |
**Verdict rule:** Ready only if there are zero significant findings,
regardless of minor/polish count.
## Per-artifact specifics
Each audit workflow defines what counts as significant/minor/polish for its
artifact type (a plugin's significant findings differ from a skill's). Look
for the "Severity for X" section in the specific audit workflow — this
document only defines the shared tiers and verdict rule.
## Applying it
1. Classify every finding into exactly one tier.
2. Group findings by tier in the report (significant → minor → polish).
3. Compute the verdict from the significant count alone.
4. Present significant findings first when reporting to the user.

View File

@ -0,0 +1,96 @@
# Decision Record Template
Use this template to document significant decisions about tool behavior. Decision records prevent rehashing settled questions and preserve context for future maintainers.
## How to Use
1. Create a decision record when choosing between meaningful alternatives
2. Write while the decision is fresh - context fades quickly
3. Store in a `decisions/` directory alongside the tool
4. Reference in related invariants or golden examples
## Template
```markdown
# Decision: [Brief title]
**Date:** YYYY-MM-DD
**Context:** [Why this came up - what problem or question prompted this decision]
**Decision:** [What was decided - be specific and unambiguous]
**Rationale:** [Why this approach - what factors drove the choice]
**Alternatives Considered:**
- [Alternative 1]: [Why rejected]
- [Alternative 2]: [Why rejected]
**Future Considerations:** [When to revisit, if ever - what would change this decision]
```
## Field Definitions
**Brief title**: Action-oriented summary. Start with verb when possible: "Use X for Y", "Require Z before W".
**Date**: When decided. Helps assess if context has changed enough to revisit.
**Context**: The situation that forced a decision. Without this, future readers can't evaluate if the decision still applies.
**Decision**: The actual choice. Should be clear enough to verify compliance.
**Rationale**: Why this choice over others. Focus on the deciding factors, not comprehensive analysis.
**Alternatives Considered**: What else was evaluated. Prevents re-evaluation of already-rejected options.
**Future Considerations**: Conditions that would invalidate this decision. Explicitly stating "never" is valid if true.
## Example: Filled-in Template
```markdown
# Decision: Require subagent for all creation work
**Date:** 2026-01-15
**Context:** Architect skills were creating files directly, leading to inconsistent patterns and context pollution in main conversation.
**Decision:** All architect skills must spawn a subagent for creation work. The main agent handles only dispatch and summary.
**Rationale:**
- Fresh context prevents pattern drift from accumulated conversation
- Subagent can fail without losing main conversation state
- Forces explicit instruction writing, which catches missing requirements
- Enables parallel work on independent tasks
**Alternatives Considered:**
- Direct creation with context management: Rejected because context pollution is subtle and hard to detect until patterns degrade
- Optional subagent for complex tasks: Rejected because "complex" is subjective and would lead to inconsistent application
**Future Considerations:** Revisit if subagent spawn overhead becomes significant (currently ~2s). Would need 10x improvement in direct creation consistency to justify reverting.
```
## When to Create Decision Records
**Do create for:**
- Choosing between valid approaches
- Rejecting commonly-requested features
- Establishing patterns that constrain future work
- Resolving disagreements or confusion
**Skip for:**
- Obvious choices with no real alternatives
- Temporary workarounds with clear end dates
- Implementation details that don't affect behavior
## Organizing Decision Records
Store in chronological order with date prefix:
```
my-tool/
SKILL.md
decisions/
2026-01-15-require-subagent.md
2026-01-18-description-validation.md
```
Link from SKILL.md or invariants when relevant.

View File

@ -0,0 +1,110 @@
# Golden Example Template
Use this template to document canonical examples that define correct tool behavior. Golden examples serve as regression tests for tool identity.
## How to Use
1. Create one golden example per critical use case
2. Document actual behavior, not theoretical ideals
3. Run golden examples after any tool modification
4. If behavior changes, either fix the tool or update the example with justification
## Template
```markdown
# Golden Example: [scenario name]
## Input
[What the user provides - be specific about context, phrasing, and state]
## Expected Behavior
[What the tool should do - step by step if complex]
## Expected Output
[What the tool produces - include format, structure, key content]
## Why This Matters
[What would break if this changed - user impact, downstream effects]
```
## Field Definitions
**scenario name**: Short identifier for this example. Should be memorable and searchable.
**Input**: The exact trigger for this behavior. Include user message, context state, any relevant conditions.
**Expected Behavior**: What the tool does internally. Focus on observable actions and decision points.
**Expected Output**: The artifact produced. Be specific enough to verify but not so rigid that cosmetic changes cause false failures.
**Why This Matters**: The user-facing impact of this behavior. Explains why this is a golden example rather than just an example.
## Example: Filled-in Template
```markdown
# Golden Example: Simple skill creation
## Input
User says: "Create a skill that formats JSON files"
Current directory contains an existing plugin with skills/ folder.
## Expected Behavior
1. Spawn subagent with skill-architect instructions
2. Subagent reads existing skills in plugin for patterns
3. Subagent creates SKILL.md with:
- Clear frontmatter description
- Input/output specification
- Usage examples
4. Subagent runs description-architect for frontmatter
5. Subagent runs audit workflow
6. Returns to main agent with summary
## Expected Output
- `skills/json-formatter/SKILL.md` created
- Frontmatter passes escape-hatch test
- Audit workflow passes or documents issues
- Summary includes file path and usage instructions
## Why This Matters
This is the minimal happy path. If this breaks:
- Users can't create basic skills
- Pattern adherence fails at the most common use case
- Trust in the tool degrades
```
## Guidelines for Good Golden Examples
**Choose scenarios that:**
- Represent common use cases
- Exercise critical decision points
- Have clear success criteria
- Would cause visible user impact if broken
**Avoid scenarios that:**
- Test implementation details
- Depend on external state
- Have ambiguous success criteria
- Overlap significantly with other golden examples
## Organizing Golden Examples
Store golden examples in a `golden-examples/` directory alongside the tool:
```
my-tool/
SKILL.md
golden-examples/
simple-creation.md
error-handling.md
edge-case-empty-input.md
```
Reference them in the tool's invariants documentation.

View File

@ -0,0 +1,133 @@
# Impact Analysis Template
Use this template before making changes to document what will be affected. Impact analysis prevents accidental regressions by forcing explicit consideration of downstream effects.
## How to Use
1. Complete this analysis before implementing changes
2. Review against invariants and golden examples
3. Get sign-off if impact is significant
4. Store with the change (commit message, PR description, or dedicated file)
## Template
```markdown
# Impact Analysis: [Brief description of change]
**Date:** YYYY-MM-DD
**Proposed By:** [Who]
## What Will Change
[Specific, observable differences after the change]
- [Change 1]
- [Change 2]
## What Could Degrade
[Potential negative effects - be honest about risks]
- [Risk 1]: [Likelihood and severity]
- [Risk 2]: [Likelihood and severity]
## Invariants Affected
| Invariant | Status | Notes |
|-----------|--------|-------|
| [Invariant text] | preserved / violated / modified | [Explanation] |
## Golden Examples Affected
| Example | Status | Notes |
|---------|--------|-------|
| [Example name] | passes / fails / needs update | [Explanation] |
## Recommendation
[ ] Proceed - changes are safe
[ ] Proceed with monitoring - watch for [specific signals]
[ ] Defer - needs [what's missing]
[ ] Reject - violates [what constraint]
**Rationale:** [Why this recommendation]
```
## Field Definitions
**What Will Change**: Observable differences. Focus on behavior, not implementation. Users should be able to notice these changes.
**What Could Degrade**: Honest risk assessment. Include low-probability high-impact risks. "Nothing could go wrong" is almost never true.
**Invariants Affected**: Check each documented invariant. "Preserved" means behavior unchanged. "Modified" means the invariant itself needs updating (rare and significant).
**Golden Examples Affected**: Run each golden example mentally or actually. "Needs update" means the example is wrong, not the change.
**Recommendation**: Clear action with justification. Defer and Reject are valid outcomes - not every change should proceed.
## Example: Filled-in Template
```markdown
# Impact Analysis: Add caching to skill-architect subagent spawn
**Date:** 2026-01-20
**Proposed By:** Developer
## What Will Change
- Subagent instructions cached for 5 minutes after first read
- Subsequent skill creations in same session use cached instructions
- Cache invalidated on any file change in skill-architect directory
## What Could Degrade
- Stale instructions if files change during session: Low likelihood, medium severity
- Memory usage from cache: Low likelihood, low severity
- Debugging difficulty if cache behavior unexpected: Medium likelihood, low severity
## Invariants Affected
| Invariant | Status | Notes |
|-----------|--------|-------|
| Always uses subagent for creation work | preserved | Cache is for instructions, not execution |
| Never creates files without reading existing patterns | preserved | Patterns still read, just cached |
| Always runs description-architect for frontmatter | preserved | Unaffected |
## Golden Examples Affected
| Example | Status | Notes |
|---------|--------|-------|
| Simple skill creation | passes | Behavior identical, just faster on repeat |
| Error handling | passes | Errors still propagate correctly |
## Recommendation
[x] Proceed with monitoring - watch for stale instruction complaints
**Rationale:** Performance improvement with low risk. Cache invalidation on file change handles the main failure mode. Monitor for user reports of unexpected behavior in first week.
```
## When to Create Impact Analysis
**Always create for:**
- Changes to documented invariants
- Changes affecting multiple tools
- Performance optimizations (often have subtle behavior changes)
- Removing or deprecating features
**Consider creating for:**
- Adding new features (may affect existing behavior)
- Refactoring (should be behavior-preserving but verify)
- Dependency updates
**Skip for:**
- Documentation-only changes
- Adding tests without behavior changes
- Fixing bugs to match documented behavior
## Using Impact Analysis Results
- **Proceed**: Implement, commit, done
- **Proceed with monitoring**: Implement, set reminder to check signals, document what to watch
- **Defer**: Document what's needed, create task to revisit
- **Reject**: Document in decision record why this change was rejected

View File

@ -0,0 +1,66 @@
# Invariants Template
Use this template to document tool invariants - behaviors that must never change regardless of improvements or refactoring.
## How to Use
1. Copy the YAML block below into your tool's documentation
2. Fill in each field based on actual behavior, not aspirations
3. Review invariants after any significant change
4. Add new invariants when discovered through use
## Template
```yaml
# Tool: [name]
invariants:
- "[Behavior that must not change]"
- "[Constraint that defines the tool]"
- "[Add more as needed]"
value_proposition: "[What makes this tool valuable - speed? reliability? flexibility?]"
deliberate_omissions:
- reason: "[Why this was excluded]"
pattern: "[Pattern intentionally NOT included]"
- reason: "[Another reason]"
pattern: "[Another omitted pattern]"
```
## Field Definitions
**invariants**: Behaviors that define the tool's identity. If these change, the tool becomes something else. Test these after every modification.
**value_proposition**: The core reason users choose this tool. Guides prioritization when constraints conflict.
**deliberate_omissions**: Patterns you consciously decided NOT to include. Documents "why not" to prevent future reversion through well-intentioned additions.
## Example: Filled-in Template
```yaml
# Tool: skill-architect
invariants:
- "Always uses subagent for creation work"
- "Never creates files without reading existing patterns first"
- "Always runs description-architect for frontmatter"
- "Produces skills that pass audit workflow"
value_proposition: "Consistent, high-quality skills through mandatory patterns and automated validation"
deliberate_omissions:
- reason: "Skills should be standalone; coupling creates maintenance burden"
pattern: "Multi-skill creation in single invocation"
- reason: "Descriptions require specialized knowledge"
pattern: "Inline description generation (use description-architect instead)"
- reason: "Audits provide feedback loop for improvement"
pattern: "Skipping audit step for 'simple' skills"
```
## When to Update
- After discovering behavior that breaks user expectations
- When refusing a "helpful" change that would violate core identity
- When finding undocumented constraints through debugging
- During retrospectives on tool failures

View File

@ -0,0 +1,111 @@
# Verification Pattern
Mandatory verification before claiming any work complete.
## Purpose
Prevent false completion claims. Every tool must specify how to verify it works.
## Core Rule
**Never claim work is complete without running verification.**
This applies to:
- Building new tools
- Modifying existing tools
- Fixing issues found in audits
- Any task that changes behavior
## Implementation Checklist
Tools implementing this pattern must:
- [ ] Declare verification method in tool definition
- [ ] Verification must be executable (not just "review")
- [ ] Run verification before completion claim
- [ ] Report verification output, not just "it passed"
- [ ] If verification fails, do not claim completion
## Verification Types
### Script-based
```yaml
verification:
type: script
command: python scripts/validate_skill.py <skill-path>
success_criteria: "Exit code 0, no errors"
```
### Example-based
```yaml
verification:
type: golden_examples
examples_path: examples/
check: "Output matches expected for all examples"
```
### Behavioral
```yaml
verification:
type: behavioral
test: "Invoke with test input, check output matches invariants"
invariants_path: invariants.md
```
### Manual (last resort)
```yaml
verification:
type: manual
steps:
- "Run skill with test case X"
- "Verify output contains Y"
- "Check file Z was created"
```
## Workflow Integration
```
Work complete?
Run verification ──→ Failed ──→ Fix issues ──→ (loop)
Passed
Check golden examples ──→ Changed ──→ Flag for review
Report completion with verification output
```
## Anti-patterns
**Verification-by-assertion:** "I verified it works" without running anything. Always show evidence.
**Partial verification:** Checking one thing when multiple things changed. Verify all affected behaviors.
**Verification deferral:** "Will verify later." Verify now or don't claim completion.
**Silent failure:** Verification failed but reporting success. If it fails, say so.
## Evidence Format
When reporting completion, include:
```markdown
## Verification Results
**Method:** [script/examples/behavioral/manual]
**Command:** [what was run]
**Output:**
[actual output or summary]
**Status:** PASSED / FAILED
```
## Cross-references
- [Audit Pattern](audit-pattern.md) - Audits require verification of fixes
- [Reversion Protection](reversion-protection.md) - Golden examples are a verification method

View File

@ -0,0 +1,55 @@
# frozen_string_literal: true
require 'json'
module PluginConfig
class SchemaError < StandardError
attr_reader :check_result
def initialize(check_result)
@check_result = check_result
super(check_result[:error])
end
def to_diagnostic_json
{
error: 'schema_mismatch',
details: check_result
}
end
end
module Expectations
SETTINGS = {
description: 'Project settings file',
required_keys: %w[enabledPlugins]
}.freeze
MARKETPLACE = {
description: 'Marketplace registry',
required_keys: %w[name plugins]
}.freeze
INSTALLED_PLUGINS = {
description: 'Installed plugins registry',
required_keys: %w[plugins]
}.freeze
def self.check(file_path, expected_keys)
unless File.exist?(file_path)
return { ok: false, error: "File not found: #{file_path}", missing_keys: expected_keys }
end
data = JSON.parse(File.read(file_path))
missing = expected_keys.reject { |key| data.key?(key) }
if missing.empty?
{ ok: true }
else
{ ok: false, error: "Missing required keys in #{file_path}", missing_keys: missing }
end
rescue JSON::ParserError => e
{ ok: false, error: "Invalid JSON in #{file_path}: #{e.message}", missing_keys: expected_keys }
end
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
module PluginConfig
module FileLocations
INSTALLED_PLUGINS_PATH = File.join(Dir.home, '.claude', 'plugins', 'installed_plugins.json')
KNOWN_MARKETPLACES_PATH = File.join(Dir.home, '.claude', 'plugins', 'known_marketplaces.json')
SETTINGS_RELATIVE_PATH = File.join('.claude', 'settings.json')
end
end

View File

@ -0,0 +1,65 @@
# frozen_string_literal: true
require 'json'
module PluginConfig
class FileVerifier
attr_reader :path
def initialize(path)
@path = path
end
def verify_written(expected_content)
return { verified: false, details: "File not found: #{path}" } unless File.exist?(path)
actual = File.read(path)
if actual == expected_content
{ verified: true, details: 'Write verified: content matches' }
else
{ verified: false, details: 'Write verification failed: content mismatch' }
end
rescue StandardError => e
{ verified: false, details: "Verification error: #{e.message}" }
end
def verify_key(section, key, expected_value)
return { verified: false, details: "File not found: #{path}" } unless File.exist?(path)
data = JSON.parse(File.read(path))
container = data.dig(section)
if container.nil?
return { verified: false, details: "Section '#{section}' not found" }
end
if container.key?(key) && container[key] == expected_value
{ verified: true, details: "Key '#{key}' has expected value #{expected_value.inspect}" }
else
actual = container.key?(key) ? container[key].inspect : '(absent)'
{ verified: false, details: "Key '#{key}' expected #{expected_value.inspect}, got #{actual}" }
end
rescue JSON::ParserError => e
{ verified: false, details: "JSON parse error: #{e.message}" }
rescue StandardError => e
{ verified: false, details: "Verification error: #{e.message}" }
end
def verify_key_absent(section, key)
return { verified: false, details: "File not found: #{path}" } unless File.exist?(path)
data = JSON.parse(File.read(path))
container = data.dig(section)
if container.nil? || !container.key?(key)
{ verified: true, details: "Key '#{key}' is absent from '#{section}'" }
else
{ verified: false, details: "Key '#{key}' still present in '#{section}'" }
end
rescue JSON::ParserError => e
{ verified: false, details: "JSON parse error: #{e.message}" }
rescue StandardError => e
{ verified: false, details: "Verification error: #{e.message}" }
end
end
end

View File

@ -0,0 +1,124 @@
# frozen_string_literal: true
require_relative 'base'
module PluginConfig
module Operations
class Audit < Base
def call
checks = {}
issues = []
fixes = []
checks[:marketplace] = check_marketplace
checks[:installed] = check_installed
checks[:settings] = check_settings
checks.each_value do |check|
next if check[:status] == 'ok'
issues << check[:issue]
fixes << check[:fix] if check[:fix]
end
{
status: issues.empty? ? 'ok' : 'issues_found',
checks: checks,
issues: issues,
fixes: fixes
}
end
private
def check_marketplace
path = marketplace_file
return missing_check('marketplace', path, register_fix) unless path && File.exist?(path)
data = read_json(path)
return parse_error_check('marketplace', path) unless data
registered = data['plugins']&.any? { |p| p['name'] == plugin }
if registered
{ status: 'ok', path: path }
else
{
status: 'issue',
path: path,
issue: "Plugin '#{plugin}' not registered in #{path}",
fix: register_fix
}
end
end
def check_installed
path = installed_plugins_path
return missing_check('installed_plugins', path, install_fix) unless File.exist?(path)
data = read_json(path)
return parse_error_check('installed_plugins', path) unless data
installed = data['plugins']&.key?(plugin_key)
if installed
{ status: 'ok', path: path }
else
{
status: 'issue',
path: path,
issue: "Plugin '#{plugin_key}' not found in installed plugins",
fix: install_fix
}
end
end
def check_settings
path = settings_path
return missing_check('settings', path, enable_fix) unless project && File.exist?(path)
data = read_json(path)
return parse_error_check('settings', path) unless data
enabled = data['enabledPlugins']&.key?(plugin_key)
if enabled
{ status: 'ok', path: path }
else
{
status: 'issue',
path: path,
issue: "Plugin '#{plugin_key}' not enabled in #{path}",
fix: enable_fix
}
end
end
def missing_check(name, path, fix)
{
status: 'issue',
path: path,
issue: "#{name} file not found at #{path}",
fix: fix
}
end
def parse_error_check(name, path)
{
status: 'issue',
path: path,
issue: "#{name} file at #{path} contains invalid JSON"
}
end
def register_fix
"Register plugin: ruby plugin_config.rb register --plugin=#{plugin} --marketplace_file=<path>"
end
def install_fix
"Install plugin: /install #{plugin_key}"
end
def enable_fix
"Enable plugin: ruby plugin_config.rb enable --plugin=#{plugin} --marketplace=#{marketplace} --project=#{project}"
end
end
end
end

View File

@ -0,0 +1,52 @@
# frozen_string_literal: true
require 'json'
require 'fileutils'
require_relative '../file_locations'
require_relative '../file_verifier'
module PluginConfig
module Operations
class Base
attr_reader :plugin, :marketplace, :project, :marketplace_file
def initialize(params)
@plugin = params[:plugin]
@marketplace = params[:marketplace]
@project = params[:project]
@marketplace_file = params[:marketplace_file]
end
private
def plugin_key
"#{plugin}@#{marketplace}"
end
def read_json(path)
return nil unless File.exist?(path)
JSON.parse(File.read(path))
rescue JSON::ParserError
nil
end
def write_json(path, data)
FileUtils.mkdir_p(File.dirname(path))
content = JSON.pretty_generate(data, indent: ' ') + "\n"
File.write(path, content)
verifier = FileVerifier.new(path)
verifier.verify_written(content)
end
def settings_path
File.join(project, '.claude', 'settings.json')
end
def installed_plugins_path
File.join(Dir.home, '.claude', 'plugins', 'installed_plugins.json')
end
end
end
end

View File

@ -0,0 +1,46 @@
# frozen_string_literal: true
require_relative 'base'
require_relative '../expectations'
module PluginConfig
module Operations
class Disable < Base
def call
# Validate settings schema if file exists
if File.exist?(settings_path)
check_result = Expectations.check(settings_path, %w[enabledPlugins])
raise SchemaError, check_result unless check_result[:ok]
end
data = read_json(settings_path)
unless data && data['enabledPlugins']&.key?(plugin_key)
return {
status: 'not_found',
plugin: plugin_key,
path: settings_path,
verified: true,
remaining_plugins: data ? (data['enabledPlugins'] || {}).keys.sort : []
}
end
data['enabledPlugins'].delete(plugin_key)
data['enabledPlugins'] = data['enabledPlugins'].sort.to_h
write_json(settings_path, data)
verifier = FileVerifier.new(settings_path)
key_check = verifier.verify_key_absent('enabledPlugins', plugin_key)
{
status: 'disabled',
plugin: plugin_key,
path: settings_path,
verified: key_check[:verified],
remaining_plugins: data['enabledPlugins'].keys.sort
}
end
end
end
end

View File

@ -0,0 +1,48 @@
# frozen_string_literal: true
require_relative 'base'
require_relative '../expectations'
module PluginConfig
module Operations
class Enable < Base
def call
# Validate settings schema if file exists
if File.exist?(settings_path)
check_result = Expectations.check(settings_path, %w[enabledPlugins])
raise SchemaError, check_result unless check_result[:ok]
end
data = read_json(settings_path) || { 'enabledPlugins' => {} }
data['enabledPlugins'] ||= {}
already = data['enabledPlugins'].key?(plugin_key)
data['enabledPlugins'][plugin_key] = true
data['enabledPlugins'] = data['enabledPlugins'].sort.to_h
created = !File.exist?(settings_path)
write_result = write_json(settings_path, data)
verifier = FileVerifier.new(settings_path)
key_check = verifier.verify_key('enabledPlugins', plugin_key, true)
status = if already
'already_enabled'
elsif created
'created_and_enabled'
else
'enabled'
end
{
status: status,
plugin: plugin_key,
path: settings_path,
verified: key_check[:verified],
enabled_plugins: data['enabledPlugins'].keys.sort
}
end
end
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
require_relative 'base'
module PluginConfig
module Operations
class List < Base
def call
data = read_json(settings_path)
plugins = if data && data['enabledPlugins']
data['enabledPlugins'].keys.sort
else
[]
end
{
status: 'ok',
project: project,
enabled_plugins: plugins,
count: plugins.length
}
end
end
end
end

View File

@ -0,0 +1,67 @@
# frozen_string_literal: true
require_relative 'base'
require_relative '../expectations'
module PluginConfig
module Operations
class Register < Base
def initialize(params)
super
@description = params[:description] || ''
end
def call
path = marketplace_file
# Validate marketplace schema if file exists
if path && File.exist?(path)
check_result = Expectations.check(path, %w[name plugins])
raise SchemaError, check_result unless check_result[:ok]
end
data = read_json(path)
unless data
return {
status: 'error',
error: "Marketplace file not found or invalid: #{path}"
}
end
data['plugins'] ||= []
existing = data['plugins'].find { |p| p['name'] == plugin }
if existing
return {
status: 'already_registered',
plugin: plugin,
path: path,
verified: true
}
end
data['plugins'] << {
'name' => plugin,
'source' => "./#{plugin}",
'description' => @description
}
data['plugins'].sort_by! { |p| p['name'] }
write_json(path, data)
verifier = FileVerifier.new(path)
readback = read_json(path)
found = readback && readback['plugins']&.any? { |p| p['name'] == plugin }
{
status: 'registered',
plugin: plugin,
path: path,
verified: found == true
}
end
end
end
end

View File

@ -0,0 +1,55 @@
# frozen_string_literal: true
require_relative 'base'
require_relative '../expectations'
module PluginConfig
module Operations
class Unregister < Base
def call
path = marketplace_file
# Validate marketplace schema if file exists
if path && File.exist?(path)
check_result = Expectations.check(path, %w[name plugins])
raise SchemaError, check_result unless check_result[:ok]
end
data = read_json(path)
unless data
return {
status: 'error',
error: "Marketplace file not found or invalid: #{path}"
}
end
data['plugins'] ||= []
original_count = data['plugins'].length
data['plugins'].reject! { |p| p['name'] == plugin }
if data['plugins'].length == original_count
return {
status: 'not_found',
plugin: plugin,
path: path,
verified: true
}
end
write_json(path, data)
readback = read_json(path)
absent = readback && readback['plugins']&.none? { |p| p['name'] == plugin }
{
status: 'unregistered',
plugin: plugin,
path: path,
verified: absent == true
}
end
end
end
end

View File

@ -0,0 +1,262 @@
# frozen_string_literal: true
require_relative 'base'
module PluginConfig
module Operations
# Structural validation for a plugin directory: plugin.json shape,
# marketplace registration/consistency, and skills/ layout.
class Validate < Base
def initialize(params)
super
@plugin_path = params[:plugin_path]
end
attr_reader :plugin_path
def call
return missing_plugin_path_result unless plugin_path && !plugin_path.to_s.strip.empty?
load_state
checks = {
plugin_json: check_plugin_json,
required_fields: check_required_fields,
name_matches_directory: check_name_matches_directory,
marketplace_entry: check_marketplace_entry,
description_matches: check_description_matches,
skill_md_present: check_skill_md_present,
skills_array_matches: check_skills_array_matches,
marketplace_source: check_marketplace_source
}
build_result(checks)
end
private
# ─── State loading ──────────────────────────────────────────────────────
def load_state
@plugin_json = load_plugin_json
@marketplace_data = read_json(marketplace_file_path)
@marketplace_entry = find_marketplace_entry
end
# True when no --marketplace_file was given and the default marketplace
# location can't be found. In this case marketplace-dependent checks are
# skipped rather than failed, so the validator works against plugin
# directories that aren't registered in any marketplace.json (e.g. when
# invoked from a different repo). If --marketplace_file was explicitly
# given, a missing/invalid file is still a hard failure.
def marketplace_explicitly_given?
!marketplace_file.to_s.strip.empty?
end
def skip_marketplace_checks?
!marketplace_explicitly_given? && !File.exist?(default_marketplace_file)
end
def plugin_json_path
File.join(plugin_path, '.claude-plugin', 'plugin.json')
end
def load_plugin_json
return nil unless File.exist?(plugin_json_path)
read_json(plugin_json_path)
end
def marketplace_file_path
marketplace_file || default_marketplace_file
end
def default_marketplace_file
File.join(File.dirname(File.expand_path(plugin_path)), '.claude-plugin', 'marketplace.json')
end
def find_marketplace_entry
return nil unless @plugin_json && @marketplace_data
(@marketplace_data['plugins'] || []).find { |p| p['name'] == @plugin_json['name'] }
end
def skills_root
File.join(plugin_path, 'skills')
end
def skill_directories
return [] unless Dir.exist?(skills_root)
Dir.children(skills_root).select { |entry| File.directory?(File.join(skills_root, entry)) }.sort
end
# ─── Checks ─────────────────────────────────────────────────────────────
def check_plugin_json
path = plugin_json_path
return fail_check("plugin.json not found at #{path}") unless File.exist?(path)
return fail_check("plugin.json at #{path} contains invalid JSON") unless @plugin_json
pass_check("plugin.json exists and is valid JSON at #{path}")
end
def check_required_fields
return fail_check('Cannot check required fields: plugin.json is missing or invalid') unless @plugin_json
missing = %w[name description].select { |key| blank?(@plugin_json[key]) }
return fail_check("Missing or empty required field(s): #{missing.join(', ')}") unless missing.empty?
pass_check('Required fields present: name, description')
end
def check_name_matches_directory
return fail_check('Cannot check name: plugin.json is missing or invalid') unless @plugin_json
expected = directory_basename
actual = @plugin_json['name']
return fail_check("plugin.json name #{actual.inspect} does not match directory basename #{expected.inspect}") unless actual == expected
pass_check("plugin.json name '#{actual}' matches directory basename '#{expected}'")
end
def check_marketplace_entry
if skip_marketplace_checks?
return skip_check(
"No --marketplace_file given and default location #{default_marketplace_file} not found; " \
'skipping marketplace registration check'
)
end
return fail_check('Cannot check marketplace entry: plugin.json is missing or invalid') unless @plugin_json
return fail_check("Marketplace file not found at #{marketplace_file_path}") unless File.exist?(marketplace_file_path)
return fail_check("Marketplace file at #{marketplace_file_path} contains invalid JSON") unless @marketplace_data
return fail_check("No marketplace entry found for plugin '#{@plugin_json['name']}' in #{marketplace_file_path}") unless @marketplace_entry
pass_check("Found marketplace entry for '#{@plugin_json['name']}' in #{marketplace_file_path}")
end
def check_description_matches
if skip_marketplace_checks?
return skip_check(
"No --marketplace_file given and default location #{default_marketplace_file} not found; " \
'skipping description consistency check'
)
end
unless @plugin_json && @marketplace_entry
return fail_check('Cannot check description: plugin.json or marketplace entry is unavailable')
end
plugin_description = @plugin_json['description']
marketplace_description = @marketplace_entry['description']
if plugin_description == marketplace_description
pass_check('plugin.json description matches marketplace.json description byte-for-byte')
else
fail_check(
"Description drift: plugin.json has #{plugin_description.inspect}, " \
"marketplace.json has #{marketplace_description.inspect}"
)
end
end
def check_skill_md_present
return pass_check('No skills/ directory present; nothing to check') unless Dir.exist?(skills_root)
missing = skill_directories.reject { |dir| File.exist?(File.join(skills_root, dir, 'SKILL.md')) }
return fail_check("Missing SKILL.md in skill directories: #{missing.join(', ')}") unless missing.empty?
pass_check('All skill directories contain SKILL.md')
end
def check_skills_array_matches
return fail_check('Cannot check skills array: plugin.json is missing or invalid') unless @plugin_json
return pass_check('plugin.json declares no skills array; nothing to check') unless @plugin_json.key?('skills')
declared = Array(@plugin_json['skills']).sort
actual = skill_directories
if declared == actual
pass_check('plugin.json skills array matches skills/ directories')
else
fail_check("plugin.json skills array #{declared.inspect} does not match actual directories #{actual.inspect}")
end
end
def check_marketplace_source
if skip_marketplace_checks?
return skip_check(
"No --marketplace_file given and default location #{default_marketplace_file} not found; " \
'skipping marketplace source check'
)
end
return fail_check('Cannot check marketplace source: marketplace entry is unavailable') unless @marketplace_entry
actual = @marketplace_entry['source']
return fail_check('Marketplace entry has no source field') if blank?(actual)
resolved = File.expand_path(actual, marketplace_root)
expected = File.expand_path(plugin_path)
if resolved == expected
pass_check("Marketplace source '#{actual}' resolves to plugin directory")
else
fail_check(
"Marketplace source #{actual.inspect} resolves to #{resolved.inspect}, " \
"which does not match plugin directory #{expected.inspect}"
)
end
end
# The directory a marketplace entry's `source` is resolved relative to.
# marketplace.json conventionally lives at <root>/.claude-plugin/marketplace.json,
# with sources relative to <root>. If the marketplace file isn't nested under a
# .claude-plugin/ directory (e.g. a flat fixture file), fall back to its own
# containing directory.
def marketplace_root
dir = File.dirname(File.expand_path(marketplace_file_path))
File.basename(dir) == '.claude-plugin' ? File.dirname(dir) : dir
end
# ─── Helpers ────────────────────────────────────────────────────────────
def directory_basename
File.basename(plugin_path.to_s.chomp('/'))
end
def blank?(value)
value.nil? || (value.is_a?(String) && value.strip.empty?)
end
def pass_check(message)
{ status: 'pass', message: message }
end
def fail_check(message)
{ status: 'fail', message: message }
end
def skip_check(message)
{ status: 'skipped', message: message }
end
def build_result(checks)
failed = checks.values.select { |check| check[:status] == 'fail' }
{
status: failed.empty? ? 'ok' : 'issues_found',
valid: failed.empty?,
plugin_path: plugin_path,
checks: checks,
issues: failed.map { |check| check[:message] }
}
end
def missing_plugin_path_result
{
status: 'issues_found',
valid: false,
plugin_path: plugin_path,
checks: {},
issues: ['No plugin_path given. Usage: validate --plugin_path=<path-to-plugin>']
}
end
end
end
end

View File

@ -0,0 +1,79 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'json'
require_relative 'file_locations'
require_relative 'file_verifier'
require_relative 'runtime_verifier'
require_relative 'expectations'
require_relative 'operations/enable'
require_relative 'operations/disable'
require_relative 'operations/register'
require_relative 'operations/unregister'
require_relative 'operations/audit'
require_relative 'operations/list'
require_relative 'operations/validate'
module PluginConfig
OPERATIONS = {
'enable' => Operations::Enable,
'disable' => Operations::Disable,
'register' => Operations::Register,
'unregister' => Operations::Unregister,
'audit' => Operations::Audit,
'list' => Operations::List,
'validate' => Operations::Validate
}.freeze
def self.run(argv)
operation_name = argv.shift
unless operation_name && OPERATIONS.key?(operation_name)
valid = OPERATIONS.keys.join(', ')
$stderr.puts JSON.pretty_generate(
error: 'invalid_operation',
message: "Usage: plugin_config.rb <operation> [--key=value ...]",
valid_operations: valid
)
exit 1
end
params = {}
snapshot_requested = false
argv.each do |arg|
if arg == '--snapshot'
snapshot_requested = true
elsif arg.start_with?('--')
key, value = arg.sub(/^--/, '').split('=', 2)
params[key.to_sym] = value
end
end
runtime = RuntimeVerifier.new if snapshot_requested
before = runtime&.snapshot
operation = OPERATIONS[operation_name].new(params)
result = operation.call
if snapshot_requested && runtime
after = runtime.snapshot
result[:runtime_diff] = RuntimeVerifier.diff(before, after)
end
puts JSON.pretty_generate(result)
exit(result[:valid] == false ? 1 : 0)
rescue SchemaError => e
$stderr.puts JSON.pretty_generate(e.to_diagnostic_json)
exit 2
rescue StandardError => e
$stderr.puts JSON.pretty_generate(
error: 'unexpected_error',
message: e.message,
operation: operation_name
)
exit 1
end
end
PluginConfig.run(ARGV.dup) if __FILE__ == $PROGRAM_NAME

View File

@ -0,0 +1,87 @@
# frozen_string_literal: true
require 'json'
require 'open3'
module PluginConfig
class RuntimeVerifier
STATUSES = %w[enabled disabled failed_to_load not_present].freeze
def initialize(capture3: Open3.method(:capture3))
@capture3 = capture3
end
def snapshot
stdout, _stderr, status = @capture3.call('claude', 'plugin', 'list')
return {} unless status.success?
parse_plugin_list(stdout)
rescue Errno::ENOENT
{}
end
def verify_status(plugin_key, expected_status)
current = snapshot
actual = current[plugin_key] || 'not_present'
if actual == expected_status
{ verified: true, details: "Plugin '#{plugin_key}' status is '#{expected_status}'" }
else
{ verified: false, details: "Plugin '#{plugin_key}' expected '#{expected_status}', got '#{actual}'" }
end
end
def self.diff(before, after)
all_keys = (before.keys + after.keys).uniq
changed = 0
unchanged = 0
all_keys.each do |key|
if before[key] == after[key]
unchanged += 1
else
changed += 1
end
end
{ changed: changed, unchanged: unchanged }
end
private
def parse_plugin_list(output)
plugins = {}
output.each_line do |line|
line = line.strip
next if line.empty?
# Expected format: "plugin-name@marketplace status"
# or variations with columns/tabs
parts = line.split(/\s{2,}|\t/)
next unless parts.length >= 2
key = parts[0].strip
status = parts[1].strip.downcase
next unless key.include?('@')
normalized = if STATUSES.include?(status)
status
elsif status.include?('enabled')
'enabled'
elsif status.include?('disabled')
'disabled'
elsif status.include?('fail')
'failed_to_load'
else
status
end
plugins[key] = normalized
end
plugins
end
end
end

View File

@ -0,0 +1,114 @@
# frozen_string_literal: true
require_relative 'test_helper'
require 'open3'
class TestEntryPoint < Minitest::Test
include TestHelpers
SCRIPT_PATH = File.expand_path('../plugin_config.rb', __dir__)
def setup
setup_temp_dirs
end
def teardown
teardown_temp_dirs
end
def test_valid_enable_operation_exits_0_with_valid_json
create_settings({})
create_marketplace(plugins: [])
stdout, stderr, status = run_script(
'enable',
"--plugin=test-plugin",
"--marketplace=test-marketplace",
"--project=#{@project_dir}"
)
assert status.success?, "Expected exit 0, got #{status.exitstatus}. stderr: #{stderr}"
parsed = JSON.parse(stdout)
assert_includes %w[created_and_enabled enabled], parsed['status']
end
def test_unknown_operation_exits_1
_stdout, stderr, status = run_script('bogus_operation')
assert_equal 1, status.exitstatus
parsed = JSON.parse(stderr)
assert_equal 'invalid_operation', parsed['error']
end
def test_no_operation_exits_1
_stdout, stderr, status = run_script
assert_equal 1, status.exitstatus
parsed = JSON.parse(stderr)
assert_equal 'invalid_operation', parsed['error']
end
def test_list_operation_exits_0
create_settings('a@b' => true)
stdout, _stderr, status = run_script(
'list',
"--project=#{@project_dir}"
)
assert status.success?
parsed = JSON.parse(stdout)
assert_equal 'ok', parsed['status']
assert_includes parsed['enabled_plugins'], 'a@b'
end
def test_output_is_always_valid_json_on_error
# Pass a bad project path so the script hits an error path
_stdout, stderr, status = run_script('bogus')
refute status.success?
# Should be valid JSON on stderr
parsed = JSON.parse(stderr) # will raise if not valid JSON
assert parsed.is_a?(Hash), 'Expected stderr to contain a JSON object'
end
def test_disable_operation_exits_0
create_settings('test-plugin@test-marketplace' => true)
stdout, _stderr, status = run_script(
'disable',
"--plugin=test-plugin",
"--marketplace=test-marketplace",
"--project=#{@project_dir}"
)
assert status.success?
parsed = JSON.parse(stdout)
assert_equal 'disabled', parsed['status']
end
def test_schema_error_exits_2_with_malformed_settings
# Create a malformed settings.json missing required 'enabledPlugins' key
# This will trigger schema validation in the Enable operation
malformed_settings = '{"badKey": "value"}'
FileUtils.mkdir_p(File.dirname(settings_path))
File.write(settings_path, malformed_settings)
_stdout, stderr, status = run_script(
'enable',
"--plugin=test-plugin",
"--marketplace=test-marketplace",
"--project=#{@project_dir}"
)
assert_equal 2, status.exitstatus, "Expected exit code 2 for schema error, got #{status.exitstatus}"
parsed = JSON.parse(stderr)
assert_equal 'schema_mismatch', parsed['error']
end
private
def run_script(*args)
Open3.capture3('ruby', SCRIPT_PATH, *args)
end
end

View File

@ -0,0 +1,78 @@
# frozen_string_literal: true
require_relative 'test_helper'
class TestExpectations < Minitest::Test
include TestHelpers
def setup
setup_temp_dirs
@json_path = File.join(@tmpdir, 'test.json')
end
def teardown
teardown_temp_dirs
end
def test_check_valid_file_with_all_expected_keys_returns_ok
File.write(@json_path, JSON.pretty_generate('enabledPlugins' => {}))
result = PluginConfig::Expectations.check(@json_path, %w[enabledPlugins])
assert result[:ok]
end
def test_check_with_missing_keys_returns_schema_mismatch
File.write(@json_path, JSON.pretty_generate('other' => {}))
result = PluginConfig::Expectations.check(@json_path, %w[enabledPlugins])
refute result[:ok]
assert_includes result[:missing_keys], 'enabledPlugins'
assert_match(/Missing required keys/, result[:error])
end
def test_check_missing_file_returns_file_missing
result = PluginConfig::Expectations.check('/nonexistent/path.json', %w[enabledPlugins])
refute result[:ok]
assert_match(/File not found/, result[:error])
assert_includes result[:missing_keys], 'enabledPlugins'
end
def test_check_invalid_json_returns_parse_error
File.write(@json_path, '{{{not json')
result = PluginConfig::Expectations.check(@json_path, %w[enabledPlugins])
refute result[:ok]
assert_match(/Invalid JSON/, result[:error])
end
def test_check_with_multiple_expected_keys
File.write(@json_path, JSON.pretty_generate('name' => 'test', 'plugins' => []))
result = PluginConfig::Expectations.check(@json_path, %w[name plugins])
assert result[:ok]
end
# ─── SchemaError ─────────────────────────────────────────────────────
def test_schema_error_to_diagnostic_json_returns_structured_output
check_result = { ok: false, error: 'Missing required keys', missing_keys: %w[enabledPlugins] }
error = PluginConfig::SchemaError.new(check_result)
diag = error.to_diagnostic_json
assert_equal 'schema_mismatch', diag[:error]
assert_equal check_result, diag[:details]
end
def test_schema_error_message_matches_error_field
check_result = { ok: false, error: 'test error message', missing_keys: [] }
error = PluginConfig::SchemaError.new(check_result)
assert_equal 'test error message', error.message
end
end

View File

@ -0,0 +1,108 @@
# frozen_string_literal: true
require_relative 'test_helper'
class TestFileVerifier < Minitest::Test
include TestHelpers
def setup
setup_temp_dirs
@json_path = File.join(@tmpdir, 'test.json')
end
def teardown
teardown_temp_dirs
end
# ─── verify_key ───────────────────────────────────────────────────────
def test_verify_key_with_correct_value_returns_ok
File.write(@json_path, JSON.pretty_generate('enabledPlugins' => { 'foo@bar' => true }))
v = PluginConfig::FileVerifier.new(@json_path)
result = v.verify_key('enabledPlugins', 'foo@bar', true)
assert result[:verified]
end
def test_verify_key_with_wrong_value_returns_not_ok
File.write(@json_path, JSON.pretty_generate('enabledPlugins' => { 'foo@bar' => false }))
v = PluginConfig::FileVerifier.new(@json_path)
result = v.verify_key('enabledPlugins', 'foo@bar', true)
refute result[:verified]
assert_match(/false/, result[:details])
end
def test_verify_key_missing_file_returns_file_missing
v = PluginConfig::FileVerifier.new('/nonexistent/path.json')
result = v.verify_key('enabledPlugins', 'foo@bar', true)
refute result[:verified]
assert_match(/File not found/, result[:details])
end
def test_verify_key_invalid_json_returns_parse_error
File.write(@json_path, 'not valid json {{{')
v = PluginConfig::FileVerifier.new(@json_path)
result = v.verify_key('enabledPlugins', 'foo@bar', true)
refute result[:verified]
assert_match(/JSON parse error/, result[:details])
end
def test_verify_key_missing_section_returns_not_found
File.write(@json_path, JSON.pretty_generate('other' => {}))
v = PluginConfig::FileVerifier.new(@json_path)
result = v.verify_key('enabledPlugins', 'foo@bar', true)
refute result[:verified]
assert_match(/Section.*not found/, result[:details])
end
# ─── verify_key_absent ────────────────────────────────────────────────
def test_verify_key_absent_when_key_is_absent_returns_ok
File.write(@json_path, JSON.pretty_generate('enabledPlugins' => {}))
v = PluginConfig::FileVerifier.new(@json_path)
result = v.verify_key_absent('enabledPlugins', 'foo@bar')
assert result[:verified]
end
def test_verify_key_absent_when_key_is_present_returns_not_ok
File.write(@json_path, JSON.pretty_generate('enabledPlugins' => { 'foo@bar' => true }))
v = PluginConfig::FileVerifier.new(@json_path)
result = v.verify_key_absent('enabledPlugins', 'foo@bar')
refute result[:verified]
assert_match(/still present/, result[:details])
end
# ─── verify_written ───────────────────────────────────────────────────
def test_verify_written_matching_content_returns_ok
content = '{"hello": "world"}'
File.write(@json_path, content)
v = PluginConfig::FileVerifier.new(@json_path)
result = v.verify_written(content)
assert result[:verified]
end
def test_verify_written_mismatched_content_returns_not_ok
File.write(@json_path, '{"hello": "world"}')
v = PluginConfig::FileVerifier.new(@json_path)
result = v.verify_written('{"hello": "different"}')
refute result[:verified]
assert_match(/mismatch/, result[:details])
end
end

View File

@ -0,0 +1,88 @@
# frozen_string_literal: true
require 'minitest/autorun'
require 'tmpdir'
require 'fileutils'
require 'json'
# Add the plugin_config directory to the load path
$LOAD_PATH.unshift(File.expand_path('..', __dir__))
require 'file_locations'
require 'file_verifier'
require 'runtime_verifier'
require 'expectations'
require 'operations/enable'
require 'operations/disable'
require 'operations/register'
require 'operations/unregister'
require 'operations/audit'
require 'operations/list'
require 'operations/validate'
module TestHelpers
def setup_temp_dirs
@tmpdir = Dir.mktmpdir('plugin_config_test')
@project_dir = File.join(@tmpdir, 'project')
@settings_dir = File.join(@project_dir, '.claude')
@marketplace_dir = @tmpdir
FileUtils.mkdir_p(@settings_dir)
end
def teardown_temp_dirs
FileUtils.rm_rf(@tmpdir) if @tmpdir && Dir.exist?(@tmpdir)
end
def settings_path
File.join(@project_dir, '.claude', 'settings.json')
end
def marketplace_path
File.join(@marketplace_dir, 'marketplace.json')
end
def create_settings(enabled_plugins = {})
data = { 'enabledPlugins' => enabled_plugins }
FileUtils.mkdir_p(File.dirname(settings_path))
File.write(settings_path, JSON.pretty_generate(data) + "\n")
settings_path
end
def create_marketplace(name: 'test-marketplace', plugins: [])
data = { 'name' => name, 'plugins' => plugins }
File.write(marketplace_path, JSON.pretty_generate(data) + "\n")
marketplace_path
end
def create_installed_plugins(path, plugins = {})
data = { 'plugins' => plugins }
FileUtils.mkdir_p(File.dirname(path))
File.write(path, JSON.pretty_generate(data) + "\n")
path
end
def create_plugin_json(plugin_dir, name:, description:, extra: {})
data = { 'name' => name, 'description' => description }.merge(extra)
path = File.join(plugin_dir, '.claude-plugin', 'plugin.json')
FileUtils.mkdir_p(File.dirname(path))
File.write(path, JSON.pretty_generate(data) + "\n")
path
end
def create_skill(plugin_dir, skill_name, with_skill_md: true)
skill_dir = File.join(plugin_dir, 'skills', skill_name)
FileUtils.mkdir_p(skill_dir)
File.write(File.join(skill_dir, 'SKILL.md'), "# #{skill_name}\n") if with_skill_md
skill_dir
end
def make_operation(klass, overrides = {})
params = {
plugin: 'test-plugin',
marketplace: 'test-marketplace',
project: @project_dir,
marketplace_file: marketplace_path
}.merge(overrides)
klass.new(params)
end
end

View File

@ -0,0 +1,368 @@
# frozen_string_literal: true
require_relative 'test_helper'
# ─── Enable ───────────────────────────────────────────────────────────────────
class TestEnable < Minitest::Test
include TestHelpers
def setup
setup_temp_dirs
end
def teardown
teardown_temp_dirs
end
def test_enable_new_plugin_creates_file_and_adds_entry
op = make_operation(PluginConfig::Operations::Enable)
result = op.call
assert_includes %w[created_and_enabled enabled], result[:status]
assert_equal 'test-plugin@test-marketplace', result[:plugin]
assert result[:verified], 'Expected verified to be true'
assert_includes result[:enabled_plugins], 'test-plugin@test-marketplace'
end
def test_enable_adds_to_existing_settings
create_settings('other-plugin@other-marketplace' => true)
op = make_operation(PluginConfig::Operations::Enable)
result = op.call
assert_equal 'enabled', result[:status]
assert_includes result[:enabled_plugins], 'other-plugin@other-marketplace'
assert_includes result[:enabled_plugins], 'test-plugin@test-marketplace'
end
def test_enable_already_enabled_returns_already_enabled
create_settings('test-plugin@test-marketplace' => true)
op = make_operation(PluginConfig::Operations::Enable)
result = op.call
assert_equal 'already_enabled', result[:status]
assert result[:verified]
end
def test_enabled_plugins_sorted_alphabetically
create_settings('z-plugin@z-marketplace' => true, 'a-plugin@a-marketplace' => true)
op = make_operation(PluginConfig::Operations::Enable)
result = op.call
expected = ['a-plugin@a-marketplace', 'test-plugin@test-marketplace', 'z-plugin@z-marketplace']
assert_equal expected, result[:enabled_plugins]
end
def test_verified_flag_is_true_on_success
op = make_operation(PluginConfig::Operations::Enable)
result = op.call
assert result[:verified]
end
end
# ─── Disable ──────────────────────────────────────────────────────────────────
class TestDisable < Minitest::Test
include TestHelpers
def setup
setup_temp_dirs
end
def teardown
teardown_temp_dirs
end
def test_disable_existing_plugin_removes_entry
create_settings('test-plugin@test-marketplace' => true)
op = make_operation(PluginConfig::Operations::Disable)
result = op.call
assert_equal 'disabled', result[:status]
refute_includes result[:remaining_plugins], 'test-plugin@test-marketplace'
end
def test_disable_nonexistent_plugin_returns_not_found
create_settings({})
op = make_operation(PluginConfig::Operations::Disable)
result = op.call
assert_equal 'not_found', result[:status]
end
def test_disable_preserves_other_plugins
create_settings(
'test-plugin@test-marketplace' => true,
'keep-me@other' => true
)
op = make_operation(PluginConfig::Operations::Disable)
result = op.call
assert_equal 'disabled', result[:status]
assert_includes result[:remaining_plugins], 'keep-me@other'
refute_includes result[:remaining_plugins], 'test-plugin@test-marketplace'
end
def test_verified_flag_confirms_key_absent
create_settings('test-plugin@test-marketplace' => true)
op = make_operation(PluginConfig::Operations::Disable)
result = op.call
assert result[:verified]
end
end
# ─── Register ─────────────────────────────────────────────────────────────────
class TestRegister < Minitest::Test
include TestHelpers
def setup
setup_temp_dirs
end
def teardown
teardown_temp_dirs
end
def test_register_new_plugin_adds_to_marketplace
create_marketplace(plugins: [])
op = make_operation(PluginConfig::Operations::Register, description: 'A test plugin')
result = op.call
assert_equal 'registered', result[:status]
assert result[:verified]
data = JSON.parse(File.read(marketplace_path))
names = data['plugins'].map { |p| p['name'] }
assert_includes names, 'test-plugin'
end
def test_register_already_present_returns_already_registered
create_marketplace(plugins: [{ 'name' => 'test-plugin', 'source' => './test-plugin', 'description' => '' }])
op = make_operation(PluginConfig::Operations::Register)
result = op.call
assert_equal 'already_registered', result[:status]
assert result[:verified]
end
def test_plugins_array_sorted_by_name
create_marketplace(plugins: [{ 'name' => 'z-plugin', 'source' => './z-plugin', 'description' => '' }])
op = make_operation(PluginConfig::Operations::Register, plugin: 'a-plugin')
result = op.call
data = JSON.parse(File.read(marketplace_path))
names = data['plugins'].map { |p| p['name'] }
assert_equal %w[a-plugin z-plugin], names
end
def test_description_is_stored_correctly
create_marketplace(plugins: [])
op = make_operation(PluginConfig::Operations::Register, description: 'My description')
result = op.call
data = JSON.parse(File.read(marketplace_path))
plugin_entry = data['plugins'].find { |p| p['name'] == 'test-plugin' }
assert_equal 'My description', plugin_entry['description']
end
end
# ─── Unregister ───────────────────────────────────────────────────────────────
class TestUnregister < Minitest::Test
include TestHelpers
def setup
setup_temp_dirs
end
def teardown
teardown_temp_dirs
end
def test_unregister_existing_plugin
create_marketplace(plugins: [{ 'name' => 'test-plugin', 'source' => './test-plugin', 'description' => '' }])
op = make_operation(PluginConfig::Operations::Unregister)
result = op.call
assert_equal 'unregistered', result[:status]
assert result[:verified]
data = JSON.parse(File.read(marketplace_path))
names = data['plugins'].map { |p| p['name'] }
refute_includes names, 'test-plugin'
end
def test_unregister_nonexistent_returns_not_found
create_marketplace(plugins: [])
op = make_operation(PluginConfig::Operations::Unregister)
result = op.call
assert_equal 'not_found', result[:status]
end
def test_unregister_preserves_other_plugins
create_marketplace(plugins: [
{ 'name' => 'keep-me', 'source' => './keep-me', 'description' => '' },
{ 'name' => 'test-plugin', 'source' => './test-plugin', 'description' => '' }
])
op = make_operation(PluginConfig::Operations::Unregister)
result = op.call
data = JSON.parse(File.read(marketplace_path))
names = data['plugins'].map { |p| p['name'] }
assert_includes names, 'keep-me'
refute_includes names, 'test-plugin'
end
end
# ─── Audit ────────────────────────────────────────────────────────────────────
class TestAudit < Minitest::Test
include TestHelpers
def setup
setup_temp_dirs
# Create installed_plugins in temp location; override the path
@installed_path = File.join(@tmpdir, 'installed_plugins.json')
end
def teardown
teardown_temp_dirs
end
def test_clean_state_returns_ok
# Create all required files with correct entries
create_marketplace(plugins: [{ 'name' => 'test-plugin', 'source' => './test-plugin', 'description' => '' }])
create_settings('test-plugin@test-marketplace' => true)
# Need to stub installed_plugins_path - create a subclass
op = make_audit_op_with_installed({ 'test-plugin@test-marketplace' => { 'status' => 'enabled' } })
result = op.call
assert_equal 'ok', result[:status]
assert_empty result[:issues]
end
def test_missing_marketplace_entry_reports_issue_with_fix
create_marketplace(plugins: []) # plugin not registered
create_settings('test-plugin@test-marketplace' => true)
op = make_audit_op_with_installed({ 'test-plugin@test-marketplace' => { 'status' => 'enabled' } })
result = op.call
assert_equal 'issues_found', result[:status]
marketplace_check = result[:checks][:marketplace]
assert_equal 'issue', marketplace_check[:status]
assert marketplace_check[:fix]
end
def test_missing_settings_entry_reports_issue_with_fix
create_marketplace(plugins: [{ 'name' => 'test-plugin', 'source' => './test-plugin', 'description' => '' }])
create_settings({}) # plugin not enabled
op = make_audit_op_with_installed({ 'test-plugin@test-marketplace' => { 'status' => 'enabled' } })
result = op.call
assert_equal 'issues_found', result[:status]
settings_check = result[:checks][:settings]
assert_equal 'issue', settings_check[:status]
assert settings_check[:fix]
end
def test_multiple_issues_all_reported
create_marketplace(plugins: []) # not registered
create_settings({}) # not enabled
op = make_audit_op_with_installed({}) # not installed
result = op.call
assert_equal 'issues_found', result[:status]
assert result[:issues].length >= 2, "Expected at least 2 issues, got #{result[:issues].length}"
end
private
# Create an Audit subclass that overrides installed_plugins_path to use temp dir
def make_audit_op_with_installed(installed_plugins)
installed_path = @installed_path
create_installed_plugins(installed_path, installed_plugins)
params = {
plugin: 'test-plugin',
marketplace: 'test-marketplace',
project: @project_dir,
marketplace_file: marketplace_path
}
op = PluginConfig::Operations::Audit.new(params)
# Override the installed_plugins_path method
op.define_singleton_method(:installed_plugins_path) { installed_path }
op
end
end
# ─── List ─────────────────────────────────────────────────────────────────────
class TestList < Minitest::Test
include TestHelpers
def setup
setup_temp_dirs
end
def teardown
teardown_temp_dirs
end
def test_list_returns_all_enabled_plugins
create_settings(
'b-plugin@marketplace' => true,
'a-plugin@marketplace' => true
)
op = make_operation(PluginConfig::Operations::List)
result = op.call
assert_equal 'ok', result[:status]
assert_equal %w[a-plugin@marketplace b-plugin@marketplace], result[:enabled_plugins]
assert_equal 2, result[:count]
end
def test_list_empty_settings_returns_empty_array
create_settings({})
op = make_operation(PluginConfig::Operations::List)
result = op.call
assert_equal 'ok', result[:status]
assert_empty result[:enabled_plugins]
assert_equal 0, result[:count]
end
def test_list_missing_file_returns_empty_array
# Don't create settings file
op = make_operation(PluginConfig::Operations::List)
result = op.call
assert_equal 'ok', result[:status]
assert_empty result[:enabled_plugins]
assert_equal 0, result[:count]
end
end

View File

@ -0,0 +1,96 @@
# frozen_string_literal: true
require_relative 'test_helper'
class TestRuntimeVerifier < Minitest::Test
# Hand-rolled fake status object; stands in for the Process::Status
# returned by Open3.capture3. Minitest 6 moved Minitest::Mock out of
# core (into the minitest-mock gem), so we avoid it entirely here.
FakeStatus = Struct.new(:success) do
def success?
success
end
end
# ─── snapshot (injected capture3) ─────────────────────────────────────
def test_snapshot_parses_output_into_plugin_hash
mock_output = <<~OUTPUT
my-plugin@marketplace enabled
other-plugin@marketplace disabled
OUTPUT
verifier = verifier_with_capture3(mock_output, success: true)
result = verifier.snapshot
assert_equal 'enabled', result['my-plugin@marketplace']
assert_equal 'disabled', result['other-plugin@marketplace']
end
def test_snapshot_returns_empty_hash_on_failure
verifier = verifier_with_capture3('', success: false)
result = verifier.snapshot
assert_equal({}, result)
end
def test_snapshot_returns_empty_hash_when_command_not_found
verifier = PluginConfig::RuntimeVerifier.new(
capture3: ->(*_args) { raise Errno::ENOENT, 'claude' }
)
result = verifier.snapshot
assert_equal({}, result)
end
# ─── verify_status (injected capture3) ────────────────────────────────
def test_verify_status_with_matching_status_returns_ok
mock_output = "my-plugin@marketplace enabled\n"
verifier = verifier_with_capture3(mock_output, success: true)
result = verifier.verify_status('my-plugin@marketplace', 'enabled')
assert result[:verified]
end
def test_verify_status_with_mismatched_status_returns_not_ok
mock_output = "my-plugin@marketplace disabled\n"
verifier = verifier_with_capture3(mock_output, success: true)
result = verifier.verify_status('my-plugin@marketplace', 'enabled')
refute result[:verified]
assert_match(/expected 'enabled', got 'disabled'/, result[:details])
end
def test_verify_status_missing_plugin_returns_not_present
verifier = verifier_with_capture3('', success: true)
result = verifier.verify_status('missing@marketplace', 'enabled')
refute result[:verified]
assert_match(/not_present/, result[:details])
end
# ─── self.diff ───────────────────────────────────────────────────────
def test_diff_identifies_changes
before = { 'a@m' => 'enabled', 'b@m' => 'enabled' }
after = { 'a@m' => 'disabled', 'b@m' => 'enabled', 'c@m' => 'enabled' }
result = PluginConfig::RuntimeVerifier.diff(before, after)
assert_equal 2, result[:changed] # a changed, c added
assert_equal 1, result[:unchanged] # b unchanged
end
def test_diff_identical_snapshots_returns_empty_changes
snap = { 'a@m' => 'enabled', 'b@m' => 'disabled' }
result = PluginConfig::RuntimeVerifier.diff(snap, snap)
assert_equal 0, result[:changed]
assert_equal 2, result[:unchanged]
end
private
def verifier_with_capture3(stdout, success:)
status = FakeStatus.new(success)
PluginConfig::RuntimeVerifier.new(capture3: ->(*_args) { [stdout, '', status] })
end
end

View File

@ -0,0 +1,306 @@
# frozen_string_literal: true
require_relative 'test_helper'
require 'open3'
class TestValidate < Minitest::Test
include TestHelpers
def setup
setup_temp_dirs
@plugin_dir = File.join(@tmpdir, 'my-plugin')
end
def teardown
teardown_temp_dirs
end
def build_valid_plugin(name: 'my-plugin', description: 'Does a thing', skills: nil)
extra = skills ? { 'skills' => skills } : {}
create_plugin_json(@plugin_dir, name: name, description: description, extra: extra)
create_skill(@plugin_dir, 'my-skill')
create_marketplace(plugins: [
{ 'name' => name, 'source' => "./#{File.basename(@plugin_dir)}", 'description' => description }
])
end
def make_validate_op(overrides = {})
params = { plugin_path: @plugin_dir, marketplace_file: marketplace_path }.merge(overrides)
PluginConfig::Operations::Validate.new(params)
end
# ─── Happy path ───────────────────────────────────────────────────────────
def test_valid_plugin_passes_all_checks
build_valid_plugin
result = make_validate_op.call
assert_equal 'ok', result[:status]
assert result[:valid]
assert_empty result[:issues]
result[:checks].each_value do |check|
assert_equal 'pass', check[:status], "Expected pass, got #{check.inspect}"
end
end
# ─── Failure modes ────────────────────────────────────────────────────────
def test_missing_plugin_json_fails
FileUtils.mkdir_p(@plugin_dir)
create_marketplace(plugins: [])
result = make_validate_op.call
refute result[:valid]
assert_equal 'issues_found', result[:status]
assert_equal 'fail', result[:checks][:plugin_json][:status]
end
def test_invalid_json_plugin_json_fails
path = File.join(@plugin_dir, '.claude-plugin', 'plugin.json')
FileUtils.mkdir_p(File.dirname(path))
File.write(path, '{ not valid json')
create_marketplace(plugins: [])
result = make_validate_op.call
refute result[:valid]
assert_equal 'fail', result[:checks][:plugin_json][:status]
end
def test_missing_required_field_fails
create_plugin_json(@plugin_dir, name: 'my-plugin', description: '')
create_skill(@plugin_dir, 'my-skill')
create_marketplace(plugins: [{ 'name' => 'my-plugin', 'source' => './my-plugin', 'description' => '' }])
result = make_validate_op.call
refute result[:valid]
assert_equal 'fail', result[:checks][:required_fields][:status]
end
def test_name_mismatch_with_directory_fails
build_valid_plugin(name: 'totally-different-name')
result = make_validate_op.call
refute result[:valid]
assert_equal 'fail', result[:checks][:name_matches_directory][:status]
end
def test_missing_marketplace_entry_fails
create_plugin_json(@plugin_dir, name: 'my-plugin', description: 'Does a thing')
create_skill(@plugin_dir, 'my-skill')
create_marketplace(plugins: []) # no entry for my-plugin
result = make_validate_op.call
refute result[:valid]
assert_equal 'fail', result[:checks][:marketplace_entry][:status]
end
def test_description_drift_fails
create_plugin_json(@plugin_dir, name: 'my-plugin', description: 'Does a thing.')
create_skill(@plugin_dir, 'my-skill')
create_marketplace(plugins: [
{ 'name' => 'my-plugin', 'source' => './my-plugin', 'description' => 'Does a thing' }
])
result = make_validate_op.call
refute result[:valid]
assert_equal 'fail', result[:checks][:description_matches][:status]
end
def test_missing_skill_md_fails
create_plugin_json(@plugin_dir, name: 'my-plugin', description: 'Does a thing')
create_skill(@plugin_dir, 'my-skill', with_skill_md: false)
create_marketplace(plugins: [
{ 'name' => 'my-plugin', 'source' => './my-plugin', 'description' => 'Does a thing' }
])
result = make_validate_op.call
refute result[:valid]
assert_equal 'fail', result[:checks][:skill_md_present][:status]
end
def test_skills_array_mismatch_fails
build_valid_plugin(skills: %w[my-skill a-second-skill-not-on-disk])
result = make_validate_op.call
refute result[:valid]
assert_equal 'fail', result[:checks][:skills_array_matches][:status]
end
def test_wrong_marketplace_source_fails
create_plugin_json(@plugin_dir, name: 'my-plugin', description: 'Does a thing')
create_skill(@plugin_dir, 'my-skill')
create_marketplace(plugins: [
{ 'name' => 'my-plugin', 'source' => './wrong-name', 'description' => 'Does a thing' }
])
result = make_validate_op.call
refute result[:valid]
assert_equal 'fail', result[:checks][:marketplace_source][:status]
end
def test_marketplace_source_resolves_path_for_nested_repo_layout
# marketplace.json lives at <root>/.claude-plugin/marketplace.json, and plugins
# live under <root>/plugins/<name> instead of directly under <root>.
root = File.join(@tmpdir, 'nested-repo')
plugin_dir = File.join(root, 'plugins', 'my-plugin')
create_plugin_json(plugin_dir, name: 'my-plugin', description: 'Does a thing')
create_skill(plugin_dir, 'my-skill')
nested_marketplace_dir = File.join(root, '.claude-plugin')
FileUtils.mkdir_p(nested_marketplace_dir)
nested_marketplace_path = File.join(nested_marketplace_dir, 'marketplace.json')
File.write(nested_marketplace_path, JSON.pretty_generate(
'name' => 'test-marketplace',
'plugins' => [
{ 'name' => 'my-plugin', 'source' => './plugins/my-plugin', 'description' => 'Does a thing' }
]
))
result = PluginConfig::Operations::Validate.new(
plugin_path: plugin_dir, marketplace_file: nested_marketplace_path
).call
assert_equal 'pass', result[:checks][:marketplace_source][:status], result[:checks][:marketplace_source].inspect
end
# ─── Cross-repo: graceful skip when no marketplace can be resolved ────────
def test_no_marketplace_resolvable_skips_marketplace_checks_without_failing
create_plugin_json(@plugin_dir, name: 'my-plugin', description: 'Does a thing')
create_skill(@plugin_dir, 'my-skill')
# No marketplace_file override, and no default marketplace.json anywhere near @plugin_dir.
result = PluginConfig::Operations::Validate.new(plugin_path: @plugin_dir).call
assert_equal 'ok', result[:status]
assert result[:valid]
%i[marketplace_entry description_matches marketplace_source].each do |key|
assert_equal 'skipped', result[:checks][key][:status], "Expected #{key} to be skipped, got #{result[:checks][key].inspect}"
end
%i[plugin_json required_fields name_matches_directory skill_md_present skills_array_matches].each do |key|
assert_equal 'pass', result[:checks][key][:status]
end
end
def test_explicit_missing_marketplace_file_still_fails
create_plugin_json(@plugin_dir, name: 'my-plugin', description: 'Does a thing')
create_skill(@plugin_dir, 'my-skill')
nonexistent = File.join(@tmpdir, 'does-not-exist.json')
result = PluginConfig::Operations::Validate.new(
plugin_path: @plugin_dir, marketplace_file: nonexistent
).call
refute result[:valid]
assert_equal 'fail', result[:checks][:marketplace_entry][:status]
end
def test_default_marketplace_resolution_used_when_present
create_plugin_json(@plugin_dir, name: 'my-plugin', description: 'Does a thing')
create_skill(@plugin_dir, 'my-skill')
default_dir = File.join(@tmpdir, '.claude-plugin')
FileUtils.mkdir_p(default_dir)
File.write(File.join(default_dir, 'marketplace.json'), JSON.pretty_generate(
'name' => 'test-marketplace',
'plugins' => [
{ 'name' => 'my-plugin', 'source' => './my-plugin', 'description' => 'Does a thing' }
]
))
result = PluginConfig::Operations::Validate.new(plugin_path: @plugin_dir).call
assert_equal 'ok', result[:status]
assert result[:valid]
result[:checks].each_value { |check| assert_equal 'pass', check[:status] }
end
end
# ─── Entry point (real exit code contract) ───────────────────────────────────
class TestValidateEntryPoint < Minitest::Test
include TestHelpers
SCRIPT_PATH = File.expand_path('../plugin_config.rb', __dir__)
def setup
setup_temp_dirs
@plugin_dir = File.join(@tmpdir, 'my-plugin')
end
def teardown
teardown_temp_dirs
end
def run_script(*args)
Open3.capture3('ruby', SCRIPT_PATH, *args)
end
def test_valid_plugin_exits_0
create_plugin_json(@plugin_dir, name: 'my-plugin', description: 'Does a thing')
create_skill(@plugin_dir, 'my-skill')
create_marketplace(plugins: [
{ 'name' => 'my-plugin', 'source' => './my-plugin', 'description' => 'Does a thing' }
])
stdout, stderr, status = run_script(
'validate',
"--plugin_path=#{@plugin_dir}",
"--marketplace_file=#{marketplace_path}"
)
assert status.success?, "Expected exit 0, got #{status.exitstatus}. stderr: #{stderr}"
parsed = JSON.parse(stdout)
assert_equal 'ok', parsed['status']
end
def test_invalid_plugin_exits_1
create_marketplace(plugins: []) # no plugin.json created at all
stdout, _stderr, status = run_script(
'validate',
"--plugin_path=#{@plugin_dir}",
"--marketplace_file=#{marketplace_path}"
)
assert_equal 1, status.exitstatus
parsed = JSON.parse(stdout)
assert_equal 'issues_found', parsed['status']
end
def test_validate_is_cwd_independent_with_absolute_plugin_path_and_default_marketplace
create_plugin_json(@plugin_dir, name: 'my-plugin', description: 'Does a thing')
create_skill(@plugin_dir, 'my-skill')
default_dir = File.join(@tmpdir, '.claude-plugin')
FileUtils.mkdir_p(default_dir)
File.write(File.join(default_dir, 'marketplace.json'), JSON.pretty_generate(
'name' => 'test-marketplace',
'plugins' => [
{ 'name' => 'my-plugin', 'source' => './my-plugin', 'description' => 'Does a thing' }
]
))
other_cwd = Dir.mktmpdir('elsewhere')
begin
stdout, stderr, status = Dir.chdir(other_cwd) do
run_script('validate', "--plugin_path=#{File.expand_path(@plugin_dir)}")
end
assert status.success?, "Expected exit 0, got #{status.exitstatus}. stderr: #{stderr}"
parsed = JSON.parse(stdout)
assert_equal 'ok', parsed['status']
assert parsed['valid']
ensure
FileUtils.rm_rf(other_cwd)
end
end
end

View File

@ -0,0 +1,148 @@
# frozen_string_literal: true
require_relative 'test_helper'
require 'open3'
require 'tmpdir'
require 'fileutils'
class TestValidateMarketplaces < Minitest::Test
include TestHelpers
SCRIPT_PATH = File.expand_path('../../validate_marketplaces.rb', __dir__)
def setup
@tmpdir = Dir.mktmpdir('validate_marketplaces_test')
end
def teardown
FileUtils.rm_rf(@tmpdir) if @tmpdir && Dir.exist?(@tmpdir)
end
# Builds <root>/.claude-plugin/marketplace.json plus one passing plugin
# (good-plugin) and one failing plugin (bad-plugin, missing plugin.json).
def build_marketplace_root(root)
FileUtils.mkdir_p(File.join(root, '.claude-plugin'))
good_dir = File.join(root, 'good-plugin')
create_plugin_json(good_dir, name: 'good-plugin', description: 'A good plugin')
FileUtils.mkdir_p(File.join(good_dir, 'skills'))
bad_dir = File.join(root, 'bad-plugin')
FileUtils.mkdir_p(bad_dir) # no plugin.json at all -> fails check_plugin_json
marketplace_data = {
'name' => File.basename(root),
'plugins' => [
{ 'name' => 'good-plugin', 'source' => './good-plugin', 'description' => 'A good plugin' },
{ 'name' => 'bad-plugin', 'source' => './bad-plugin', 'description' => 'A bad plugin' }
]
}
File.write(File.join(root, '.claude-plugin', 'marketplace.json'), JSON.pretty_generate(marketplace_data))
end
def build_all_passing_root(root)
FileUtils.mkdir_p(File.join(root, '.claude-plugin'))
good_dir = File.join(root, 'good-plugin')
create_plugin_json(good_dir, name: 'good-plugin', description: 'A good plugin')
FileUtils.mkdir_p(File.join(good_dir, 'skills'))
marketplace_data = {
'name' => File.basename(root),
'plugins' => [
{ 'name' => 'good-plugin', 'source' => './good-plugin', 'description' => 'A good plugin' }
]
}
File.write(File.join(root, '.claude-plugin', 'marketplace.json'), JSON.pretty_generate(marketplace_data))
end
def run_script(*args)
Open3.capture3('ruby', SCRIPT_PATH, *args)
end
def test_no_args_prints_usage_and_exits_2
stdout, _stderr, status = run_script
assert_equal 2, status.exitstatus
assert_match(/Usage: ruby validate_marketplaces\.rb/, stdout)
assert_match(%r{ruby .*validate_marketplaces\.rb .*/home/jared/dev/cc-plugins .*/home/jared/dev/cc-os}, stdout)
end
def test_all_passing_marketplace_exits_0
root = File.join(@tmpdir, 'passing-root')
build_all_passing_root(root)
stdout, stderr, status = run_script(root)
assert status.success?, "Expected exit 0, got #{status.exitstatus}. stdout: #{stdout} stderr: #{stderr}"
assert_match(/PASS\s+good-plugin/, stdout)
assert_match(/TOTAL: 1 plugin\(s\) checked, 1 passed, 0 failed/, stdout)
end
def test_mixed_marketplace_reports_pass_and_fail_and_exits_1
root = File.join(@tmpdir, 'mixed-root')
build_marketplace_root(root)
stdout, _stderr, status = run_script(root)
assert_equal 1, status.exitstatus
assert_match(/PASS\s+good-plugin/, stdout)
assert_match(/FAIL\s+bad-plugin/, stdout)
assert_match(/TOTAL: 2 plugin\(s\) checked, 1 passed, 1 failed/, stdout)
end
def test_missing_marketplace_file_exits_2
root = File.join(@tmpdir, 'empty-root')
FileUtils.mkdir_p(root)
stdout, _stderr, status = run_script(root)
assert_equal 2, status.exitstatus
assert_match(/ERROR: marketplace\.json not found/, stdout)
end
def test_mixed_marketplace_output_collapses_to_one_line_per_failure
root = File.join(@tmpdir, 'mixed-root-collapse')
build_marketplace_root(root)
stdout, _stderr, _status = run_script(root)
# bad-plugin fails multiple checks (missing plugin.json cascades into
# several "Cannot check..." failures); only the first issue should
# appear, on the same line as the FAIL marker, not as a multi-line dump.
fail_lines = stdout.lines.select { |l| l =~ /FAIL\s+bad-plugin/ }
assert_equal 1, fail_lines.size
assert_match(/FAIL\s+bad-plugin - plugin\.json not found/, fail_lines.first)
refute_match(/Cannot check required fields/, stdout)
end
def test_multiple_roots_one_failing_reports_both_and_exits_1
root1 = File.join(@tmpdir, 'root1-pass')
root2 = File.join(@tmpdir, 'root2-mixed')
build_all_passing_root(root1)
build_marketplace_root(root2)
stdout, _stderr, status = run_script(root1, root2)
assert_equal 1, status.exitstatus
assert_match(/== #{Regexp.escape(File.expand_path(root1))} ==/, stdout)
assert_match(/== #{Regexp.escape(File.expand_path(root2))} ==/, stdout)
assert_match(/PASS\s+good-plugin/, stdout)
assert_match(/FAIL\s+bad-plugin/, stdout)
assert_match(/TOTAL: 3 plugin\(s\) checked, 2 passed, 1 failed/, stdout)
end
def test_multiple_roots_are_all_reported
root1 = File.join(@tmpdir, 'root1')
root2 = File.join(@tmpdir, 'root2')
build_all_passing_root(root1)
build_all_passing_root(root2)
stdout, _stderr, status = run_script(root1, root2)
assert status.success?
assert_match(/== #{Regexp.escape(File.expand_path(root1))} ==/, stdout)
assert_match(/== #{Regexp.escape(File.expand_path(root2))} ==/, stdout)
assert_match(/TOTAL: 2 plugin\(s\) checked, 2 passed, 0 failed/, stdout)
end
end

View File

@ -0,0 +1,166 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
# Cross-repo marketplace acceptance script.
#
# For one or more marketplace roots (repos containing a
# .claude-plugin/marketplace.json), runs the plugin_config validate
# operation against every plugin the marketplace declares and reports a
# pass/fail table plus totals.
#
# Usage:
# ruby validate_marketplaces.rb <marketplace-root>...
#
# With no arguments, prints usage (including the documented default
# invocation for this machine) and exits 2.
#
# Exit status:
# 0 every plugin in every given marketplace passed validation
# 1 at least one plugin failed validation
# 2 usage error (no args, missing/invalid marketplace.json, etc.)
require 'json'
require 'open3'
SCRIPT_DIR = File.expand_path(__dir__)
PLUGIN_CONFIG_RB = File.join(SCRIPT_DIR, 'plugin_config', 'plugin_config.rb')
DEFAULT_MARKETPLACE_ROOTS = [
'/home/jared/dev/cc-plugins',
'/home/jared/dev/cc-os'
].freeze
def usage
<<~USAGE
Usage: ruby #{File.basename(__FILE__)} <marketplace-root>...
Each <marketplace-root> is a repo root containing
.claude-plugin/marketplace.json. Every plugin declared in that
marketplace is validated with the plugin_config `validate` operation,
against that marketplace's manifest.
Documented default invocation for this machine:
ruby #{__FILE__} #{DEFAULT_MARKETPLACE_ROOTS.join(' ')}
USAGE
end
# Runs `plugin_config.rb validate` for a single plugin and returns the
# parsed JSON result (or a synthetic failure result if the subprocess
# couldn't be run or produced unparseable output).
def validate_plugin(plugin_path, marketplace_file)
cmd = [
'ruby', PLUGIN_CONFIG_RB, 'validate',
"--plugin_path=#{plugin_path}",
"--marketplace_file=#{marketplace_file}"
]
stdout, stderr, _status = Open3.capture3(*cmd)
begin
JSON.parse(stdout, symbolize_names: true)
rescue JSON::ParserError
{
status: 'issues_found',
valid: false,
plugin_path: plugin_path,
checks: {},
issues: ["validator produced unparseable output: #{stdout.strip}#{stderr.strip}"]
}
end
end
# Validates every plugin declared by one marketplace root. Returns
# { root:, plugin_results: [{name:, plugin_path:, valid:, issues: []}], error: nil|String }
def validate_marketplace(root)
abs_root = File.expand_path(root)
marketplace_file = File.join(abs_root, '.claude-plugin', 'marketplace.json')
unless File.exist?(marketplace_file)
return { root: abs_root, marketplace_file: marketplace_file, plugin_results: [], error: "marketplace.json not found at #{marketplace_file}" }
end
data = begin
JSON.parse(File.read(marketplace_file))
rescue JSON::ParserError => e
return { root: abs_root, marketplace_file: marketplace_file, plugin_results: [], error: "invalid JSON in #{marketplace_file}: #{e.message}" }
end
plugins = data['plugins'] || []
if plugins.empty?
return { root: abs_root, marketplace_file: marketplace_file, plugin_results: [], error: "no plugins declared in #{marketplace_file}" }
end
plugin_results = plugins.map do |entry|
name = entry['name']
source = entry['source']
plugin_path = source ? File.expand_path(source, abs_root) : nil
if plugin_path.nil?
{ name: name || '(unnamed)', plugin_path: nil, valid: false, issues: ['marketplace entry has no source field'] }
else
result = validate_plugin(plugin_path, marketplace_file)
{
name: name || '(unnamed)',
plugin_path: plugin_path,
valid: result[:valid] == true,
issues: Array(result[:issues])
}
end
end
{ root: abs_root, marketplace_file: marketplace_file, plugin_results: plugin_results, error: nil }
end
def print_report(marketplace_reports)
total_plugins = 0
total_failed = 0
marketplace_reports.each do |report|
puts "== #{report[:root]} =="
if report[:error]
puts " ERROR: #{report[:error]}"
puts
next
end
report[:plugin_results].each do |pr|
total_plugins += 1
if pr[:valid]
puts " PASS #{pr[:name]}"
else
total_failed += 1
first_issue = pr[:issues].first
summary = first_issue ? first_issue.to_s.lines.first.to_s.strip : '(no issue detail)'
puts " FAIL #{pr[:name]} - #{summary}"
end
end
puts
end
[total_plugins, total_failed]
end
def main(argv)
if argv.empty?
puts usage
exit 2
end
marketplace_reports = argv.map { |root| validate_marketplace(root) }
total_plugins, total_failed = print_report(marketplace_reports)
hard_error = marketplace_reports.any? { |r| r[:error] }
puts "TOTAL: #{total_plugins} plugin(s) checked, #{total_plugins - total_failed} passed, #{total_failed} failed"
if hard_error
exit 2
elsif total_failed.positive?
exit 1
else
exit 0
end
end
main(ARGV) if __FILE__ == $PROGRAM_NAME

View File

@ -0,0 +1,75 @@
---
name: cc-architect
description: Model-tier-optimized execution plans, scaffolding, and configuration operations for building and managing Claude Code extensions (plugins, skills, workflows)
---
# CC Architect
Model-tier-optimized execution plans, scaffolding, and configuration operations for building and managing Claude Code extensions (plugins, skills, workflows).
## Trigger
Use this skill when creating, auditing, or improving any Claude Code extension component, or when managing plugin configuration (enable, disable, register, unregister, audit config, list plugins).
## Dispatch
Before building an execution plan, check if the request matches a fast-path operation. Fast-path operations bypass `${CLAUDE_PLUGIN_ROOT}/workflows/build-plan.md` and route directly to the appropriate workflow.
**Pattern match the user's request against these keywords:**
| Keywords | Operation | Route |
|----------|-----------|-------|
| enable plugin, turn on plugin, activate plugin | `enable` | `workflows/plugin-config.md` |
| disable plugin, turn off plugin, deactivate plugin | `disable` | `workflows/plugin-config.md` |
| register plugin, add to marketplace, add plugin to marketplace | `register` | `workflows/plugin-config.md` |
| unregister plugin, remove from marketplace, remove plugin from marketplace | `unregister` | `workflows/plugin-config.md` |
| audit config, check config, plugin config status, debug plugin, why isn't plugin working | `audit` | `workflows/plugin-config.md` |
| list plugins, show plugins, installed plugins, what plugins | `list` | `workflows/plugin-config.md` |
**If a fast-path match is found:**
1. Extract the operation and parameters from the user's request.
2. Dispatch a Haiku subagent with: "Read workflow at `${CLAUDE_PLUGIN_ROOT}/workflows/plugin-config.md` and execute with operation=`<op>`, plugin_name=`<name>`, and other relevant parameters."
3. Skip Step 1 (Build Execution Plan) and proceed directly to Step 2 execution with the single workflow step.
**If no fast-path match:** Continue to Step 1 (Build Execution Plan) as normal.
## Execution
### Step 1: Build Execution Plan
Dispatch a Sonnet subagent:
- Read: `workflows/catalog.md`
- Input: User's request
- Task: Select workflows and build structured execution plan with model tiers
- Write plan to: `.claude/plugin-data/cc-architect/plans/current-plan.md`
### Step 2: Execute Plan
For each step in the execution plan:
1. Read the step metadata from plan file (model tier, workflow path, input, output)
2. Dispatch subagent using Task tool:
- Use `subagent_type="general-purpose"`
- Pass instructions: "Read workflow at {workflow_path} and execute with inputs: {input_context}. Write results to {output_path}"
- The SUBAGENT reads the workflow document and executes it (NOT you)
3. Wait for subagent completion
4. Verify output file exists at specified location (do NOT read contents)
5. Continue to next step
Example dispatch for a scaffolding step:
```
Plan metadata: Model=haiku, Workflow=workflows/create-plugin.md, Output=.claude/plugin-data/cc-architect/tasks/step-1-scaffold.md
Dispatch: Task tool with instructions="Read workflow at ${CLAUDE_PLUGIN_ROOT}/workflows/create-plugin.md and execute. Write results to .claude/plugin-data/cc-architect/tasks/step-1-scaffold.md"
```
ANTI-PATTERNS - DO NOT:
- Read workflow documents yourself
- Interpret workflow logic in main thread
- Assemble context before dispatching
- Read subagent output files (except final synthesis in Step 3)
ONLY read: plan file, final output. ONLY verify: intermediate files exist. ONLY pass: file paths to subagents.
### Step 3: Present Results
Read the final output file specified in the plan.
Present to user.

View File

@ -0,0 +1,148 @@
# CC-Architect Audit Checklist
**Model**: Haiku (mechanical verification, no judgment)
## Instructions
Run this checklist against any cc-architect output (plugin, skill, workflow). Check each item and mark pass/fail. If any CRITICAL items fail, escalate to Sonnet for severity analysis.
---
## Universal Attributes (All Outputs)
### Structure
| # | Check | Command/Method | Pass | Fail |
|---|-------|----------------|------|------|
| 1 | Directory exists | `ls -d {target_path}` | ☐ | ☐ |
| 2 | Required files present | See per-type checklist below | ☐ | ☐ |
| 3 | No empty files | `find {path} -empty -type f` returns nothing | ☐ | ☐ |
| 4 | Naming convention | All files/dirs are `kebab-case` | ☐ | ☐ |
### Frontmatter
| # | Check | Validation | Pass | Fail |
|---|-------|------------|------|------|
| 5 | Description present | `description:` field in frontmatter | ☐ | ☐ |
| 6 | Description passes escape hatch | Would user skip reading full file? | ☐ | ☐ |
| 7 | No placeholder text | No `TODO`, `FIXME`, `[PLACEHOLDER]` | ☐ | ☐ |
### Cross-References
| # | Check | Validation | Pass | Fail |
|---|-------|------------|------|------|
| 8 | All paths resolve | Every `references/` path exists | ☐ | ☐ |
| 9 | No broken links | Every `[text](path)` link resolves | ☐ | ☐ |
### Model Annotations
| # | Check | Validation | Pass | Fail |
|---|-------|------------|------|------|
| 10 | Tasks have model tier | Each task annotated with Haiku/Sonnet/Opus | ☐ | ☐ |
| 11 | Pre-planning present | Orchestrator-invoked skills have pre-planning step | ☐ | ☐ |
---
## Plugin-Specific Attributes
### Required Files
- [ ] `CLAUDE.md` exists
- [ ] `.claude-plugin/plugin.json` exists and valid JSON
- [ ] At least one skill in `skills/` OR workflow in `workflows/`
### Plugin Manifest (plugin.json)
- [ ] `name` field present
- [ ] `description` field present
- [ ] `skills` array lists all skills in `skills/` directory
---
## Skill-Specific Attributes
### Required Files
- [ ] `SKILL.md` exists
- [ ] `invariants.md` exists (may be empty if no invariants yet)
- [ ] `examples/golden/` directory exists
### SKILL.md Content
- [ ] Has frontmatter with `description`
- [ ] Has "When to use" section
- [ ] Has phase structure (Setup → Process → Synthesize or equivalent)
- [ ] References to shared docs use relative paths
### Invariants
- [ ] At least 1 invariant defined OR explicit "no invariants yet" note
- [ ] Invariants are testable (not vague)
---
## Workflow-Specific Attributes
### Required Frontmatter Fields
```yaml
---
name: required
description: required
triggers: required (array)
model_tier: required (haiku|sonnet|opus)
complexity: optional (1-5)
requires_user_input: optional (true|false)
depends_on: optional (array of workflow names)
---
```
### Workflow Content
- [ ] "When to use" section present
- [ ] "Inputs required" section present
- [ ] "Phases" or "Steps" section present
- [ ] Each phase has model tier annotation
---
## Domain Plugin Attributes (Specialized Fields)
Only applies to domain-specialist plugins (e.g. plugins that encode a professional discipline's frameworks and heuristics, not general-purpose tooling).
- [ ] Domain expertise documented in references/
- [ ] Professional frameworks captured
- [ ] Heuristics are specific, not generic
- [ ] Workflow categories identified (if applicable)
---
## Escalation Criteria
**Escalate to Sonnet if**:
- More than 2 FAIL items in Universal Attributes
- Any CRITICAL item fails (marked below)
- Subjective judgment needed (e.g., "is description good enough?")
**CRITICAL Items** (must pass):
- #2 (Required files present)
- #5 (Description present)
- #10 (Tasks have model tier)
---
## Output Format
```markdown
## Audit Report: {target_name}
**Date**: {date}
**Auditor**: Haiku
**Target**: {path}
### Summary
- Universal: {X}/11 passed
- Type-specific: {Y}/{Z} passed
- **Status**: PASS | FAIL | ESCALATE
### Failed Items
1. #{number}: {description}
- Expected: {what should exist}
- Actual: {what was found}
### Recommendations
- {If ESCALATE, note what Sonnet should review}
```

View File

@ -0,0 +1,10 @@
---
description: "View or change {{plugin_name}} configuration"
---
Invoke the {{plugin_name}} config workflow.
Read and follow: `workflows/config.md`
Parse the user's request into `operation` (`get`/`set`/`list`), `key`, and
`value` (for `set`) before following the workflow.

View File

@ -0,0 +1,47 @@
# Workflow: Config
Read, validate, and update `{{plugin_name}}`'s configuration.
## When to use
- User wants to view or change `{{plugin_name}}` settings
- Another workflow needs a config value at runtime
## Inputs required
- **operation** - `get` | `set` | `list`
- **key** - Config key (dot-notation for nested values), required for `get`/`set`
- **value** - New value, required for `set`
## Config location
`.claude/plugin-data/{{plugin_name}}/config.json`
## Subtasks
### 1. Load config
Subagent: Haiku.
- Read `.claude/plugin-data/{{plugin_name}}/config.json`
- If missing, create with `{}` and note it was initialized
### 2. Apply operation
Subagent: Haiku.
- `list`: print all keys/values
- `get`: print the value at `key`, or "not set" if absent
- `set`: write `value` at `key`, preserving other keys, then re-read to confirm the write
### 3. Report
Subagent: Main.
- Confirm the operation and resulting value
- Note the config file path for manual edits if needed
---
Customize this workflow for `{{plugin_name}}`'s specific settings (API keys,
file paths, feature toggles, output formats).

View File

@ -0,0 +1,145 @@
---
status: legacy
note: "For maintenance of existing commands only. Prefer skills for new functionality."
model_tier:
setup: main
frontmatter: main
description: opus
instructions: main
report: main
cleanup: haiku
---
# Workflow: Audit Command (LEGACY)
> **LEGACY WORKFLOW**: This workflow is for maintaining existing slash commands. For new functionality, prefer creating skills via `/cc-architect` (create-skill workflow) instead.
## When to use
- Evaluating slash command for quality and compliance
- Checking slash-command-architect standards
- Reviewing description and tool permissions
## Inputs required
- **command_path** - Path to command file (e.g., `plugin/commands/my-command.md`)
## Output
- `.claude/plugin-data/slash-command-architect/audits/<command-name>-audit.md` (gitignored)
- Summary with verdict (Ready / Not Ready)
- Delete report after user acts on findings
---
## Note on scope
Commands are simpler than skills. This audit is lighter-weight with fewer subtasks.
---
## Subtasks
### 1. Pre-audit context loading
Subagent: Main.
**Check for:**
- `invariants.md` in command's plugin root
- `.decisions/` directory
**Record in scratch:**
- Applicable invariants (or "none")
- Prior decisions affecting commands (or "none")
---
### 2. Validate path and setup
Subagent: Main.
- Verify `command_path` exists, is `.md` file
- Verify in `commands/` directory
- Extract command name
---
### 3. Frontmatter audit
Subagent: Main (inline).
**Checks:**
- Valid YAML frontmatter
- Required fields: `name`, `description`
- Name kebab-case, matches filename
- If `allowed-tools`: valid tool names array
---
### 4. Description compliance audit
Subagent: opus.
Read: `${CLAUDE_PLUGIN_ROOT}/references/layout/descriptions.md`
**Checks:**
- Follows "When/Why, Not How"
- No implementation details
- No escape hatches ("if needed", "when appropriate")
- Clear trigger
Write: `scratch/description-findings.md`
---
### 5. Instruction completeness audit
Subagent: Main.
**Checks:**
- Clear context section
- Instructions actionable
- Handles user request interpretation
- Tool permissions match requirements
---
### 6. Assemble report
Subagent: Main.
**Do:**
- Combine findings
- Classify by severity (significant/minor/polish)
- Verdict: Ready (0 significant) or Not Ready (1+ significant)
- Write: `.claude/plugin-data/slash-command-architect/audits/<command-name>-audit.md`
**Severity for commands:**
- **Significant:** Invalid frontmatter, missing fields, escape hatches
- **Minor:** Broad tool permissions, unclear instructions
- **Polish:** Wording, organization
---
### 7. Act on findings
Subagent: Main.
- Walk through significant findings first
- Offer to fix or let user handle
- After user confirms: delete report
---
### 8. Record decisions
Subagent: Main.
**When to record:**
- Exceptions to description formula
- Unusual tool permission grants
**How:**
- Template: `references/tool-patterns/templates/decision-record-template.md`
- Write: `<plugin_path>/.decisions/YYYY-MM-DD-<topic>.md`
Prompt: "Were any significant decisions made?"

View File

@ -0,0 +1,154 @@
# Workflow: Audit Plugin
Comprehensive plugin evaluation against standards.
## Who should do this work
| Phase | Model | Why |
|-------|-------|-----|
| Research | Haiku | File gathering, structural validation |
| Deep analysis | Sonnet | Pattern matching, standards checking |
| Synthesis | Opus | Report writing, quality decisions |
| Cleanup | Haiku | File deletion |
## When to use
- Evaluating plugin from marketplace
- Checking plugin-architect standards compliance
- Comprehensive review
## Inputs required
- **plugin_path** - Path to plugin directory
- **audit_components** - `all` (default), `manifest-only`, `skills`, `agents`, `commands`
## Output
- `.claude/plugin-data/plugin-architect/audits/<plugin-name>-audit.md` (gitignored)
- Summary with verdict (Ready / Not Ready)
- Delete report after user acts on findings
---
## Phases
### Phase 1: Research and Setup (Haiku)
**Purpose:** Gather all inputs, validate requirements, perform initial structural checks.
**Tasks:**
1. Validate plugin path exists and is directory
2. Verify `.claude-plugin/plugin.json` exists
3. Extract plugin name and create scratch workspace
4. Inventory components: count skills, agents, commands
5. Check for reversion protection artifacts:
- `invariants.md` in plugin root
- `.decisions/` directory
- `examples/golden/`
6. Check for config infrastructure:
- `workflows/config.md` (config workflow for programmatic use)
- `commands/config.md` (slash command for user invocation)
- Run the Ruby config audit script for marketplace/installed/settings state:
```bash
ruby ${CLAUDE_PLUGIN_ROOT}/scripts/plugin_config/plugin_config.rb audit \
--plugin=<plugin-name> \
--marketplace=<marketplace-id> \
--project=<project-path> \
--marketplace_file=<path-to-marketplace.json>
```
Parse the JSON output and include check results (marketplace, installed, settings) in the research output. If the script is unavailable, fall back to manual file checks.
7. Read plugin manifest and validate structure
8. Check documentation existence (`CLAUDE.md`, `README.md`)
9. List all component entry files (SKILL.md, agent.md, command.md)
**References:**
- `${CLAUDE_PLUGIN_ROOT}/references/layout/plugin-structure.md`
**Output:** `scratch/research.md`
- Plugin metadata (name, version, component counts)
- Reversion protection inventory (invariants/decisions/golden examples)
- Config infrastructure status (workflows/config.md, commands/config.md)
- Manifest structure validation
- Documentation checklist
- Component file listing
---
### Phase 2: Deep Analysis (Sonnet)
**Purpose:** Perform detailed audits of manifest, documentation, and components.
**Tasks:**
1. Read `scratch/research.md` for context
2. Validate manifest fields:
- Required fields: `name`, `version`, `description`
- Name kebab-case format
- Version semver compliance
- Description non-empty and meaningful
3. Audit documentation quality:
- `CLAUDE.md` meaningful (not boilerplate)
- Documentation matches actual contents
- README presence (optional but noted)
4. Audit config infrastructure:
- Check if `workflows/config.md` exists -> flag as minor if missing
- Check if `commands/config.md` exists -> flag as minor if missing
- If either missing, add recommendation to create config infrastructure
5. If `audit_components != manifest-only`:
- Check entry file naming (kebab-case)
- Check description style consistency
- Pattern analysis:
- `workflows/` at plugin root -> Role-Workflow candidate
- Skills dispatching 2+ subagent workflows -> Should use Role-Workflow
- Optionally delegate to component-specific audit workflows:
- Skills: `${CLAUDE_PLUGIN_ROOT}/workflows/audit-skill.md`
- Workflows: `${CLAUDE_PLUGIN_ROOT}/workflows/audit-workflow.md`
- Commands: `${CLAUDE_PLUGIN_ROOT}/workflows/audit-command.md`
6. Classify all findings by severity (significant/minor/polish)
**References:**
- `${CLAUDE_PLUGIN_ROOT}/references/tool-patterns/severity-guide.md`
- `references/tool-patterns/role-workflow-pattern.md`
**Severity for plugins:**
- **Significant:** Invalid manifest, missing CLAUDE.md, broken component refs
- **Minor:** Missing README, inconsistent patterns, missing config infrastructure
- **Polish:** Documentation wording, organization
**Output:** `scratch/findings.md`
- Manifest findings (with severity)
- Documentation findings (with severity)
- Config infrastructure findings (with severity and recommendations)
- Component findings (with severity)
- Pattern recommendations
- Delegated audit summaries (if any)
---
### Phase 3: Synthesis and Cleanup (Opus for report, Haiku for cleanup)
**Purpose:** Generate final audit report with verdict, act on findings, clean up artifacts.
**Tasks (Opus):**
1. Read `scratch/research.md` and `scratch/findings.md`
2. Synthesize findings into cohesive report:
- Include reversion protection context
- Group by severity (significant -> minor -> polish)
- Include delegated audit summaries
- Calculate verdict: Ready (0 significant) or Not Ready (1+ significant)
3. Write final report: `.claude/plugin-data/plugin-architect/audits/<plugin-name>-audit.md`
4. Present findings to user:
- Walk through significant findings first
- Offer to fix or let user handle
- Prompt for decision recording if significant architectural decisions made
**Tasks (Haiku cleanup):**
1. After user acts on findings, delete audit report
2. Delete scratch workspace
3. If decision recording requested:
- Template: `references/tool-patterns/templates/decision-record-template.md`
- Write: `<plugin_path>/.decisions/YYYY-MM-DD-<topic>.md`
**Decision recording triggers:**
- Plugin-wide pattern decisions
- Exceptions to standards
- Component organization rationale

View File

@ -0,0 +1,131 @@
# Workflow: Audit Skill
**Model tier**: Haiku (research), Sonnet (analysis), Opus (synthesis), Haiku (cleanup)
## When to use
- Evaluating skill from marketplace
- Checking skill-architect standards compliance
- Discovering novel patterns
## Inputs required
- **skill_path** - Path to skill directory
## Output
- `.claude/plugin-data/skill-architect/audits/<skill-name>-audit.md` (gitignored)
- Summary with verdict (Ready / Not Ready)
- Delete report after user acts on findings
---
## Phase 1: Research
Subagent: haiku.
Read: `${CLAUDE_PLUGIN_ROOT}/references/layout/skill-structure.md`
Checklist: `${CLAUDE_PLUGIN_ROOT}/templates/audit-checklist-template.md` (Skill-Specific Attributes section)
**Setup:**
- Verify `skill_path` exists, contains `SKILL.md`
- Create scratch workspace
- Extract skill name
**Context loading:**
- Check for `invariants.md` in skill root
- Check for `.decisions/` directory
- Check for `examples/golden/` or `golden-examples/`
- Record: invariants list, prior decisions count/topics, golden examples list (or "none" for each)
**Structure audit:**
- SKILL.md at root
- Required dirs: `workflows/`, `references/`
- Optional dirs follow conventions: `templates/`, `scripts/`, `state/`
- Valid YAML frontmatter: `name`, `description`
- Name: kebab-case, <=64 chars
**Read all skill files:**
- SKILL.md
- All workflow files
- All reference files
- Templates, scripts if present
**File size checks:**
- SKILL.md <=50 lines
- reference.md files <=50 lines
- Knowledge docs <=150 lines (flag >200)
- Directory depth <=3 levels
Write: `scratch/research-findings.md`
---
## Phase 2: Analysis
Subagent: sonnet.
Read: `scratch/research-findings.md`, `${CLAUDE_PLUGIN_ROOT}/references/layout/skill-structure.md`, `references/layout/descriptions.md`, `references/progressive-disclosure/reference-md-pattern.md`, `references/progressive-disclosure/splitting-knowledge.md`, `references/subagent-pattern.md`, `workflows/create-skill.md`
**Content compliance evaluation:**
- SKILL.md routing-only vs inlined content
- reference.md files route properly
- Progressive disclosure structure appropriate
**Quality assessment:**
- Description follows "When/Why, Not How"
- Trigger unambiguous (no "if needed")
- Workflows have clear steps, subagent hints
**Skippability assessment (SINGLE primary workflow, referenced not inlined):**
1. SKILL.md protective measures? (blocking instruction, summary of key steps)
2. Workflow has non-obvious steps? (domain-specific logic vs general practice)
**Flag skip risk if:**
- Single workflow reference-only AND no blocking/summary AND non-obvious steps
**Don't flag:**
- Multiple workflows, matches general practice, inlined, or has blocking+summary
Write: `scratch/analysis-findings.md`
---
## Phase 3: Synthesis
Subagent: opus.
Read: `scratch/analysis-findings.md`, `${CLAUDE_PLUGIN_ROOT}/references/tool-patterns/severity-guide.md`, `references/tool-patterns/catalog.md`
**Pattern detection:**
- Note genuinely different approaches (not style)
- Evaluate trade-offs
- Flag substantive patterns to the user as candidates for the tool patterns
catalog (`references/tool-patterns/catalog.md`)
- Pattern capability assessment: Verification? Brainstorming? Audit? Role-Workflow?
- See `references/tool-patterns/catalog.md` for criteria
**Classify findings:**
- Classify by severity (significant/minor/polish)
- Verdict: Ready (0 significant) or Not Ready (1+ significant)
**Impact analysis per recommendation:**
- What could degrade?
- Invariant conflict?
- Golden example impact?
If contradicts invariant or affects golden example: note and require user approval.
Write: `.claude/plugin-data/skill-architect/audits/<skill-name>-audit.md`
**Present report to user:**
- Walk through significant findings first
- Offer to fix or let user handle
- Patterns worth adding: confirm before adding to `references/tool-patterns/catalog.md`
- After user confirms: invoke cleanup
**Cleanup (haiku):**
- Delete scratch workspace
- Delete audit report
- Record decisions if needed:
- Template: `references/tool-patterns/templates/decision-record-template.md`
- Write: `<skill_path>/.decisions/YYYY-MM-DD-<topic>.md`
- When: invariant changes, golden example updates, pattern adoptions, exceptions, trade-offs
- Prompt: "Were any significant decisions made? (invariants, golden examples, patterns, exceptions)"

View File

@ -0,0 +1,128 @@
# Workflow: Audit Workflow
Evaluate workflow documents for quality, compliance, and completeness against workflow-architect standards.
## Who should do this work
- **Haiku subagent**: Research phase (setup, context loading, structure audit)
- **Sonnet subagent**: Analysis phase (evaluation, quality assessment)
- **Opus subagent**: Synthesis phase (classification, verdict, report)
- **Haiku subagent**: Cleanup phase
## When to use
- Evaluating workflow for quality and compliance
- Checking workflow-architect standards
- Reviewing structure, clarity, completeness
## Inputs required
- **workflow_path** - Path to workflow file (e.g., `plugin/skills/my-skill/workflows/my-workflow.md`)
## Output
- `.claude/plugin-data/workflow-architect/audits/<workflow-name>-audit.md` (gitignored)
- Summary with verdict (Ready / Not Ready)
- Delete report after user acts on findings
---
## Phase 1: Research
Subagent: haiku.
Read: `${CLAUDE_PLUGIN_ROOT}/references/layout/workflow-structure.md`
**Setup:**
- Verify `workflow_path` exists, is `.md` file
- Verify in `workflows/` directory
- Create scratch workspace
- Extract workflow name
**Context loading:**
- Check for `invariants.md` in workflow's plugin root
- Check for `.decisions/` directory
- Check for `examples/golden/`
- Record: invariants list, prior decisions count/topics, golden examples list (or "none" for each)
**Structure audit:**
- Has "When to use"
- Has "Inputs required"
- Has "Output"
- Has "Subtasks" or "Phase" sections with clear steps
- Each subtask/phase: "Who" (main/subagent)
- Each subtask/phase: "Must read" if applicable
- Each subtask/phase: clear "Do" instructions
**Read workflow file:**
- Full workflow content
- Note all referenced files
Write: `scratch/research-findings.md`
---
## Phase 2: Analysis
Subagent: sonnet.
Read: `scratch/research-findings.md`, `${CLAUDE_PLUGIN_ROOT}/references/layout/workflow-structure.md`
**Ownership clarity evaluation:**
- Each subtask/phase clearly assigns ownership (main vs subagent)
- Subagent tasks reference model if specified
- Main tasks don't delegate subagent work
- No ambiguous ownership
**Completeness evaluation:**
- Clear purpose and trigger conditions
- Inputs well-defined
- Output format specified
- All subtasks/phases have necessary context
- Verification steps if modifies files
- No missing steps in workflow flow
**Quality assessment:**
- Logical step ordering
- Appropriate subagent model assignments
- File artifacts properly passed between phases
- No redundant steps
Write: `scratch/analysis-findings.md`
---
## Phase 3: Synthesis
Subagent: opus.
Read: `scratch/analysis-findings.md`, `${CLAUDE_PLUGIN_ROOT}/references/tool-patterns/severity-guide.md`, `references/tool-patterns/catalog.md`
**Classify findings:**
- Classify by severity (significant/minor/polish)
- Verdict: Ready (0 significant) or Not Ready (1+ significant)
**Severity for workflows:**
- **Significant:** Missing sections, ambiguous ownership, incomplete flow, missing verification
- **Minor:** Unclear wording, missing optional context, suboptimal structure
- **Polish:** Style, formatting
**Impact analysis per recommendation:**
- What could degrade?
- Invariant conflict?
- Golden example impact?
If contradicts invariant or affects golden example: note and require user approval.
Write: `.claude/plugin-data/workflow-architect/audits/<workflow-name>-audit.md`
**Present report to user:**
- Walk through significant findings first
- Offer to fix or let user handle
- After user confirms: invoke cleanup
**Cleanup (haiku):**
- Delete scratch workspace
- Delete audit report
- Record decisions if needed:
- Template: `references/tool-patterns/templates/decision-record-template.md`
- Write: `<plugin_path>/.decisions/YYYY-MM-DD-<topic>.md`
- When: non-standard structures, exceptions to best practices, complex delegation patterns
- Prompt: "Were any significant decisions made? (structure exceptions, pattern decisions, best practice deviations)"

View File

@ -0,0 +1,115 @@
# Workflow: Build Execution Plan
Build a structured execution plan that orchestrates cc-architect workflows. This is the CRITICAL first step in all cc-architect operations.
## Who should do this work
- **Sonnet subagent**: Always.
## Inputs
- User request (original message)
- `workflows/catalog.md` (workflow catalog)
## Steps
### 1. Read catalog
Read `workflows/catalog.md` and note workflow names, paths, triggers, complexity, and model tier recommendations.
### 2. Analyze request
Identify:
- Primary intent
- Artifact type (plugin, skill, workflow, command, description)
- Scope (new, modify, audit, improve)
- Dependencies
### 3. Select workflows
- Find primary workflow for main request
- Identify supporting workflows
- Prefer fewer workflows
- Only include workflows directly contributing to output
### 4. Determine sequence
Order: Setup (Haiku) → Processing (Sonnet) → Synthesis (Opus) → Cleanup (Haiku)
Rules:
- Gather before analyzing
- Analyze before synthesizing
- Scaffold before populating
- Cleanup last
### 5. Assign model tiers
| Work Type | Model | Examples |
|-----------|-------|----------|
| Busywork | Haiku | Scaffolding, file gathering, validation, cleanup |
| Processing | Sonnet | Filtering, drafting, analysis, pattern matching |
| Intelligence | Opus | Final artifacts, quality decisions, user-facing output |
Heuristics: Judgment? → Opus. Transform content? → Sonnet. Mechanical? → Haiku.
### 6. Apply batching
Batch same-tier steps with no dependencies. When uncertain, keep sequential.
### 7. Write plan
Write to `.claude/plugin-data/cc-architect/plans/current-plan.md` using format below.
## Output
Write plan to `.claude/plugin-data/cc-architect/plans/current-plan.md`:
```markdown
# Execution Plan
Generated: {timestamp}
Request: {one-line summary}
## Request Summary
{2-3 sentences}
## Selected Workflows
1. **{workflow-name}** - {why needed}
## Execution Steps
### Step N: {action name}
- **Model**: haiku | sonnet | opus
- **Workflow**: `workflows/{name}.md`
- **Input**: {context/files}
- **Output**: `.claude/plugin-data/cc-architect/tasks/{step-N-name}.md`
- **Purpose**: {what this accomplishes}
### Final Step: Synthesize (Opus)
- **Input**: All previous outputs
- **Output**: `.claude/plugin-data/cc-architect/output/final.md`
### Cleanup (Haiku)
- Remove temporary files
## Artifacts
**Final**: `.claude/plugin-data/cc-architect/output/final.md`
**Created**: {persistent files}
```
## Verification
The plan is valid if:
- [ ] Every workflow referenced exists in the catalog
- [ ] Every step has all five required fields (Model, Workflow, Input, Output, Purpose)
- [ ] Step outputs and inputs chain correctly (no references to nonexistent outputs)
- [ ] Final synthesis step uses Opus
- [ ] Cleanup step is present and uses Haiku
- [ ] Batched steps have no dependencies between them
## Anti-patterns
| Anti-Pattern | Why It's Wrong | Correct Approach |
|--------------|----------------|------------------|
| Skipping synthesis step | User output should always be Opus-polished | Always include synthesis |
| Using Opus for file gathering | Wastes expensive model on busywork | Use Haiku for mechanical tasks |
| Batching dependent steps | Creates race conditions | Keep dependent steps sequential |
| Vague output paths | Executor won't know where to write | Always specify exact paths |
| Missing cleanup step | Leaves temporary files cluttering plugin-data | Always include cleanup |
| Plan has AI "decide" something | Plan should be fully deterministic | Specify exact actions |

View File

@ -0,0 +1,164 @@
# Workflow Catalog
This catalog lists all workflows available in cc-architect. Use it to select the right workflow for your task.
---
## Plugin Architect Workflows
### create-plugin
**Path**: `workflows/create-plugin.md`
**Triggers**: create plugin, new plugin, scaffold plugin, plugin from scratch
**Complexity**: Medium
**Model tier**: Main (scope), Haiku (scaffolding), Sonnet (skill creation if included), Opus (validation)
**Description**: Creates a complete Claude Code plugin with manifest, directory structure, CLAUDE.md, and optionally an initial skill (via the plugin-add-skill workflow). Detects git author for plugin.json.
### plugin-add-skill
**Path**: `workflows/plugin-add-skill.md`
**Triggers**: add skill to plugin, create skill in plugin, plugin skill
**Complexity**: High
**Model tier**: Haiku (research/scaffold), Sonnet (processing/content), Opus (synthesis/review), Haiku (cleanup)
**Description**: Creates a skill within an existing plugin. Three-phase workflow: Research (domain understanding, structure design), Processing (write workflows, references, knowledge docs), Synthesis (quality review, friction reflection). Follows progressive disclosure patterns.
### audit-plugin
**Path**: `workflows/audit-plugin.md`
**Triggers**: audit plugin, review plugin, check plugin compliance, plugin quality
**Complexity**: High
**Model tier**: Haiku (research), Sonnet (deep analysis), Opus (synthesis/report), Haiku (cleanup)
**Description**: Comprehensive plugin evaluation against standards. Checks manifest, documentation, component structure, config infrastructure, and reversion protection artifacts. Can delegate to component-specific audits. Produces verdict (Ready/Not Ready) with severity-classified findings.
### improve-plugin-docs
**Path**: `workflows/improve-plugin-docs.md`
**Triggers**: improve docs, update documentation, doc friction, harvest learnings, periodic maintenance
**Complexity**: Medium
**Model tier**: Haiku (research), Sonnet (prioritize/patch), Opus (review), Haiku (apply/cleanup)
**Description**: Harvests friction notes from task documents and applies targeted improvements to knowledge docs. Filters noise, ranks by impact, proposes patches, splits docs exceeding 150 lines. Includes checkpoint for user approval before applying changes.
---
## Skill Architect Workflows
### create-skill
**Path**: `workflows/create-skill.md`
**Triggers**: create skill, new skill, build skill, skill from scratch
**Complexity**: High
**Model tier**: Haiku (research/scaffold), Sonnet (processing/content), Opus (synthesis), Haiku (cleanup)
**Description**: Creates a complete skill with SKILL.md, workflows, references, templates, and scripts. Three-phase approach: Research (domain understanding, structure plan, scaffold), Processing (write all content), Synthesis (validate, generate description, cleanup). Includes reversion protection scaffolding.
### audit-skill
**Path**: `workflows/audit-skill.md`
**Triggers**: audit skill, review skill, check skill compliance, skill quality, evaluate skill
**Complexity**: High
**Model tier**: Haiku (research), Sonnet (analysis), Opus (synthesis), Haiku (cleanup)
**Description**: Evaluates skill against standards including structure, progressive disclosure, description compliance, and skippability risk. Checks reversion protection artifacts. Detects novel patterns worth adding to patterns library. Produces verdict with severity-classified findings.
### improve-skill
**Path**: `workflows/improve-skill.md`
**Triggers**: improve skill, fix skill, skill friction, update skill, skill maintenance
**Complexity**: Medium
**Model tier**: Main/Haiku (gather), Opus (prioritize), varies (apply), Main (verify)
**Description**: Addresses friction encountered when using a skill. Collects friction data from task docs and user, prioritizes by frequency/impact, applies targeted edits to knowledge docs and workflows.
---
## Workflow Architect Workflows
### create-workflow
**Path**: `workflows/create-workflow.md`
**Triggers**: create workflow, new workflow, define process, workflow document
**Complexity**: Medium
**Model tier**: Main (requirements/design/verify), Haiku (create file)
**Description**: Creates a workflow document that defines a repeatable process for subagents. Includes "When to use", "Inputs required", "Output", and "Subtasks" sections. Each subtask specifies ownership (main vs subagent) and required reads.
### audit-workflow
**Path**: `workflows/audit-workflow.md`
**Triggers**: audit workflow, review workflow, check workflow, workflow quality
**Complexity**: Medium
**Model tier**: Haiku (research), Sonnet (analysis), Opus (synthesis), Haiku (cleanup)
**Description**: Evaluates workflow for structure, ownership clarity, and completeness. Checks required sections exist, steps have clear ownership, verification included if modifying files. Produces verdict with findings classified by severity (significant/minor/polish).
### improve-workflow
**Path**: `workflows/improve-workflow.md`
**Triggers**: improve workflow, fix workflow, workflow friction, update workflow
**Complexity**: Medium
**Model tier**: Main/Haiku (gather), Opus (prioritize), varies (apply), Main (verify)
**Description**: Refines workflow based on friction encountered during use. Focus areas: step clarity, missing steps, ownership ambiguity, missing required reads, inadequate verification. Offers follow-up audit after improvements.
---
## Slash Command Architect Workflows (LEGACY)
> **Note**: Slash commands are legacy. Prefer skills for new functionality.
### create-command
**Path**: `workflows/create-command.md`
**Triggers**: create command, new command, slash command, command file
**Complexity**: Low
**Model tier**: Main (requirements/design), Haiku (implementation)
**Status**: LEGACY - maintenance only
**Description**: Creates a slash command with frontmatter (name, description, allowed-tools), context section, and instructions. Commands are simpler than skills - single-purpose tools for specific actions.
### audit-command
**Path**: `workflows/audit-command.md`
**Triggers**: audit command, review command, check command, command quality
**Complexity**: Low
**Model tier**: Main (setup/frontmatter/instructions/report), Opus (description), Haiku (cleanup)
**Status**: LEGACY - maintenance only
**Description**: Lightweight audit for slash commands. Checks frontmatter validity, description compliance (no escape hatches), instruction completeness, and tool permissions. Produces verdict with severity-classified findings.
### improve-command
**Path**: `workflows/improve-command.md`
**Triggers**: improve command, fix command, command friction, update command
**Complexity**: Low
**Model tier**: Main (gather/prioritize/apply/verify)
**Status**: LEGACY - maintenance only
**Description**: Refines command based on friction. Focus areas: description triggers, instruction clarity, tool permissions. Lightweight workflow for simpler command artifacts.
---
## Configuration Workflows
### plugin-config
**Path**: `workflows/plugin-config.md`
**Triggers**: enable plugin, disable plugin, register plugin, unregister plugin, audit config, list plugins, debug plugin config
**Complexity**: Low
**Model tier**: Haiku (execute script), Sonnet (self-healing if needed), Main (interpret & report)
**Description**: Single flexible workflow for all plugin configuration operations. Runs a deterministic Ruby script (`scripts/plugin_config/plugin_config.rb`) with operation-parameter routing, handles verification failures with self-healing, and presents results to the user. Supports enable, disable, register, unregister, audit, and list operations.
---
## Orchestration Workflows (Internal)
> **Note**: These workflows are used internally by the cc-architect orchestrator. They are not invoked directly by users.
### build-plan
**Path**: `workflows/build-plan.md`
**Triggers**: (internal) First step when orchestrator receives any request
**Complexity**: Medium
**Model tier**: Sonnet (always executed by Sonnet subagent)
**Description**: Builds a structured execution plan that orchestrates cc-architect workflows. Reads the catalog, analyzes user request, selects workflows, determines step sequence, assigns model tiers, applies batching optimization, and writes the plan to `plugin-data/cc-architect/plans/current-plan.md`.
### synthesize
**Path**: `workflows/synthesize.md`
**Triggers**: (internal) Final step after all execution subagents complete
**Complexity**: Medium
**Model tier**: Opus (requires intelligent synthesis and quality judgment)
**Description**: Reads all previous step outputs, synthesizes into a coherent deliverable, and produces the final user-facing artifact. Handles different artifact types (plugin, skill, workflow, command, description, audit) with appropriate templates. Includes quality checks for completeness, coherence, and actionability.
### cleanup
**Path**: `workflows/cleanup.md`
**Triggers**: (internal) Runs after synthesis, as final orchestration step
**Complexity**: Low
**Model tier**: Haiku (mechanical file operations, no judgment required)
**Description**: Removes temporary task files from `plugin-data/cc-architect/tasks/` while preserving final outputs in `output/`. Optionally archives execution plans. Includes safety rules to never delete files outside `plugin-data/` or touch the output directory.
---
## Description Architect Workflows
### generate-description
**Path**: `workflows/generate-description.md`
**Triggers**: write description, generate description, frontmatter description, description for skill/agent/command/plugin
**Complexity**: Low
**Model tier**: Main (inline, no subagent needed)
**Description**: Creates compliant frontmatter descriptions using the formula: "[Action verb] [what]. [Unambiguous trigger]." Applies escape hatch test to ensure AI cannot rationalize skipping the component while still doing the task. Returns only the description string, no explanation.

View File

@ -0,0 +1,129 @@
# Workflow: Cleanup
## Model Tier
Haiku - mechanical file operations, no judgment required.
## When to Use
Final step of any orchestrated workflow execution. Runs after synthesis has completed and user-facing output is ready.
## Inputs
- **plan_path**: Path to execution plan (e.g., `.claude/plugin-data/cc-architect/plans/current-plan.md`)
## Outputs
- None (files deleted)
- Optional: Archived plan in `.claude/plugin-data/cc-architect/plans/archive/`
---
## Step 1: Read Execution Plan
Read the plan file at `plan_path` to identify:
- All temporary files listed in step outputs (paths containing `/tasks/`)
- The final output path (preserved)
- Any user-requested artifacts (preserved)
## Step 2: Identify Files to Delete
**Delete (temporary task files):**
- Any file in `.claude/plugin-data/cc-architect/tasks/`
- These are intermediate outputs between workflow steps
**Preserve (permanent artifacts):**
- Files in `.claude/plugin-data/cc-architect/output/` (synthesis results)
- Any paths explicitly listed under `## Artifacts` in the plan
- Files outside `.claude/plugin-data/` (never touch)
## Step 3: Safe Deletion
**Safety rules (enforced):**
1. ONLY delete files under `.claude/plugin-data/cc-architect/tasks/`
2. NEVER delete anything outside `.claude/plugin-data/`
3. NEVER delete the `output/` directory or its contents
4. Verify each path starts with expected prefix before deletion
**Deletion procedure:**
```
For each temp file identified in plan:
1. Verify path contains `.claude/plugin-data/cc-architect/tasks/`
2. Verify file exists
3. Delete file
4. Log deletion
```
## Step 4: Archive Execution Plan (Optional)
**When to archive:**
- Complex multi-step executions (debugging/audit trail)
- User requests plan preservation
- Execution had errors (for investigation)
**Archive procedure:**
1. Create archive directory: `.claude/plugin-data/cc-architect/plans/archive/`
2. Generate timestamp: `YYYY-MM-DD-HHMMSS`
3. Move plan: `current-plan.md` -> `archive/{timestamp}-{request-summary}.md`
**When to delete instead:**
- Simple single-workflow executions
- Successful completion with no issues
- User explicitly requests cleanup
## Step 5: Directory Cleanup
After file deletion:
1. Check if `tasks/` directory is empty
2. If empty, remove the directory
3. Leave `output/` and `plans/` directories intact
---
## File Classification Reference
| Path Pattern | Classification | Action |
|--------------|----------------|--------|
| `*/tasks/*.md` | Temporary | Delete |
| `*/output/*.md` | Final artifact | Preserve |
| `*/output/final.md` | Primary output | Preserve |
| `*/plans/current-plan.md` | Execution plan | Archive or delete |
| `*/plans/archive/*` | Archived plans | Preserve |
| Anything outside `plugin-data/` | External | Never touch |
## Error Handling
**File not found:**
- Log warning, continue (file may have been manually deleted)
**Permission denied:**
- Log error, skip file, continue with others
- Report at end: "N files could not be deleted"
**Path validation failure:**
- STOP immediately
- Report: "Unsafe path detected: {path}"
- Do not delete anything else
---
## Example Execution
Given plan with these steps:
```markdown
### Step 1: Gather Context
- Output: `.claude/plugin-data/cc-architect/tasks/step-1-context.md`
### Step 2: Draft Structure
- Output: `.claude/plugin-data/cc-architect/tasks/step-2-draft.md`
### Step 3: Synthesize
- Output: `.claude/plugin-data/cc-architect/output/final.md`
```
Cleanup actions:
1. Delete: `.claude/plugin-data/cc-architect/tasks/step-1-context.md`
2. Delete: `.claude/plugin-data/cc-architect/tasks/step-2-draft.md`
3. Preserve: `.claude/plugin-data/cc-architect/output/final.md`
4. Archive or delete: `.claude/plugin-data/cc-architect/plans/current-plan.md`
5. Remove empty `tasks/` directory

View File

@ -0,0 +1,98 @@
---
status: legacy
note: "For maintenance of existing commands only. Prefer skills for new functionality."
model_tier:
requirements: main
design: main
implementation: haiku
---
# Workflow: Create Command (LEGACY)
> **LEGACY WORKFLOW**: This workflow is for maintaining existing slash commands. For new functionality, prefer creating skills via the `create-skill` workflow instead.
## When to use
- Creating a new slash command (legacy maintenance only)
- Concept is clear and requirements understood
## Before you start
If concept unclear, brainstorm: `references/brainstorming/workflow.md`
## Pattern consideration
See `references/tool-patterns/catalog.md`.
| Question | If Yes |
|----------|--------|
| Is command concept unclear? | Brainstorm first |
| Will command modify files? | Include verification in instructions |
| Will command wrap a skill? | Skill handles patterns; command just invokes |
---
## Inputs
| Input | Example |
|-------|---------|
| `command_name` | `create-backup` (kebab-case) |
| `command_purpose` | "Create a backup of the current project" |
| `target_plugin_path` | `/home/user/my-plugin` |
## Subtasks
### 1. Understand requirements
Subagent: Main with user.
**Do:**
- What should this command do?
- What tools needed? (Read, Write, Bash, etc.)
- Wrap existing skill or standalone?
- What inputs from user?
### 2. Design the command
Subagent: Main.
**Do:**
- Determine command name (kebab-case, descriptive)
- Write one-line description
- List required tools
- Outline instructions
- If modifies files: include verification step
A command file has two parts: YAML frontmatter (`description`, optional
`allowed-tools`) and a body of plain instructions the model follows when the
command is invoked. See `${CLAUDE_PLUGIN_ROOT}/commands/cc-architect.md` for
a minimal real example, and `${CLAUDE_PLUGIN_ROOT}/templates/config-command.tmpl`
for one with input parsing.
### 3. Write the command file
Subagent: haiku.
Read: `${CLAUDE_PLUGIN_ROOT}/references/layout/descriptions.md`
**Do:**
1. Generate the description using the `generate-description` workflow
(`${CLAUDE_PLUGIN_ROOT}/workflows/generate-description.md`)
- Input: type=command, name, purpose, triggers
2. Create: `{target_plugin_path}/commands/{command_name}.md`
3. Write:
- Frontmatter (`description`, `allowed-tools` if the command needs
specific tools)
- Step-by-step instructions in the body
- Any user-request parsing guidance the command needs
## Validation
- [ ] Filename matches command name
- [ ] Description follows formula: "[Action verb] [what] when [trigger]"
- [ ] Only necessary tools listed
- [ ] Instructions clear and actionable
- [ ] Command does one thing well
## Output
`{target_plugin_path}/commands/{command_name}.md`

View File

@ -0,0 +1,151 @@
# Workflow: Create Plugin
Create a new Claude Code plugin from scratch with complete structure.
## Who should do this work
| Phase | Model | Why |
|-------|-------|-----|
| Scope clarification | Main | User interaction required |
| Scaffolding | Haiku | Mechanical file/directory creation |
| Skill creation | Sonnet | Content drafting (delegates to skill workflows) |
| Config creation | Haiku | Template-based file creation |
| Validation | Opus | Final quality decisions |
## When to use
- Creating new Claude Code plugin from scratch
- Plugin directory doesn't exist yet
## Before you start
If concept unclear, brainstorm: `references/brainstorming/workflow.md`
## Dependencies (optional)
Initial skill creation delegates to `${CLAUDE_PLUGIN_ROOT}/workflows/plugin-add-skill.md`.
## Inputs required
- **plugin_name** - kebab-case
- **plugin_purpose** - Problem this solves
- **include_skill** - yes/no (default yes)
- **skill_name** - If including skill (defaults to plugin_name)
For descriptions: Read `${CLAUDE_PLUGIN_ROOT}/references/layout/descriptions.md` - "when/why" formula, not implementation.
## Task document
Create: `.claude/plugin-data/plugin-architect/tasks/new-plugin-<plugin-name>-<date>.md`
---
## Pattern consideration
See `references/tool-patterns/catalog.md`.
| Question | If Yes |
|----------|--------|
| Plugin concept unclear? | Brainstorm first |
| Skills modify files? | Skills need verification (delegated to skill-architect) |
| Plugin creates files in user projects? | Follow [plugin-data-convention](../references/conventions/plugin-data-convention.md) |
| Maintained long-term? | Include reversion protection scaffolding |
| Orchestrate 2+ workflows with synthesis? | Consider [Role-Workflow pattern](../references/tool-patterns/role-workflow-pattern.md) |
---
## Subtasks
### 1. Clarify scope
Subagent: Main with user.
**Do:**
- Confirm plugin name and purpose
- Ask if needs initial skill (most do)
- Write to task doc: `## Scope`
---
### 2. Scaffold plugin structure
Subagent: Haiku.
Read: Task doc (scope), `${CLAUDE_PLUGIN_ROOT}/references/layout/plugin-structure.md`
**Do:**
- **Detect author name:**
```bash
git config user.name
```
- If returns a name: use it for `author.name` in plugin.json
- If empty/fails: inform user and tell them to set it:
```
Git author name not configured. Set it with:
git config --global user.name "Your Name"
```
Then prompt user for their name to continue.
- Create `../<plugin-name>/` in marketplace
- Create `.claude-plugin/plugin.json` with required fields including author
- Create empty `skills/` directory
- Reversion protection: `.decisions/` directory
- Note in task doc: "Skills create their own invariants.md and examples/golden/"
- Register in `marketplace.json` using the Ruby config script:
```bash
ruby ${CLAUDE_PLUGIN_ROOT}/scripts/plugin_config/plugin_config.rb register \
--plugin=<plugin-name> \
--marketplace_file=<path-to-marketplace.json>
```
If exit code is non-zero, fall back to manual JSON editing and note in task doc.
- Write to task doc: `## Scaffolded Files`
---
### 3. Create initial skill (if requested)
Subagent: Depends on availability.
**Do:**
- Use `${CLAUDE_PLUGIN_ROOT}/workflows/plugin-add-skill.md`
- Pass: plugin_path, skill_name, skill_purpose
---
### 4. Create config workflow and command (optional)
Subagent: Haiku.
Read: Task doc, `templates/config-workflow.tmpl`, `templates/config-command.tmpl`
**Do:**
- Ask user if plugin needs configuration (most don't initially)
- If yes:
- Create `workflows/config.md` from template
- Create `<plugin-path>/commands/config.md` from template
- Replace `{{plugin_name}}` placeholders with actual plugin name
- Write to task doc: `## Config Files Created`
- Remind user:
- "Customize the config workflow for your plugin's specific settings"
- "Common customizations: API keys, file paths, feature toggles, output formats"
- "Config is stored in `.claude/plugin-data/<plugin-name>/config.json`"
---
### 5. Finalize and report
Subagent: Main.
**Do:**
```bash
ruby ${CLAUDE_PLUGIN_ROOT}/scripts/plugin_config/plugin_config.rb validate \
--plugin_path=<plugin-path>
```
Exits 0 if all structural checks pass, 1 if any fail (see JSON `issues` array for details).
- Fix validation errors
- Verify structure matches Claude Code spec
- Summarize created
- Suggest next steps
---
## Reflection
Friction? Read `references/self-improvement/friction-reflection.md` and add to task doc.

View File

@ -0,0 +1,157 @@
# Workflow: Create Skill
**Model tier**: Haiku (research/scaffold), Sonnet (processing/content), Opus (synthesis), Haiku (cleanup)
## When to use
- Creating a new skill for a project or plugin
- The skill doesn't exist yet or needs to be rebuilt from scratch
## Before you start
If concept unclear, brainstorm: `references/brainstorming/workflow.md`
## Inputs required
- **target_location** - `.claude/skills/<skill-name>/` (project) or `<plugin-path>/skills/<skill-name>/` (plugin)
- **skill_name** - kebab-case
- **skill_purpose** - What problem this solves
- **initial_workflows** - At least one task to handle
## Task document
Create: `.claude/plugin-data/skill-architect/tasks/new-skill-<skill-name>-<date>.md`
All subagents append to this.
---
## Pattern consideration
See `references/tool-patterns/catalog.md`.
| Question | If Yes |
|----------|--------|
| Will skill make design decisions? | Include brainstorming triggers |
| Will skill modify files? | Include verification step |
| Will skill create files in user projects? | Follow [plugin-data-convention](../references/conventions/plugin-data-convention.md) |
| Will skill need maintenance/auditing? | Create reversion protection scaffolding |
| Will skill orchestrate 2+ subagent workflows with synthesis? | Use [Role-Workflow pattern](../references/tool-patterns/role-workflow-pattern.md) |
---
## Phases
### Phase 1: Research (Haiku)
**Objective:** Gather requirements, validate inputs, design structure, scaffold files.
**Read:**
- `${CLAUDE_PLUGIN_ROOT}/references/layout/reference.md`
- `references/tool-patterns/deterministic-scripting.md`
- `${CLAUDE_PLUGIN_ROOT}/references/layout/skill-structure.md`
**Do:**
1. Clarify with user: skill purpose, major workflows, knowledge domains
2. Map workflows to `workflows/*.md`
3. Map knowledge domains to `references/` subdirs
4. Identify scripting opportunities (mechanical, repeatable, unambiguous?)
5. Identify scripts vs templates vs knowledge docs
6. Write to task doc: `## Domain Understanding`, `## Proposed Structure`, `## Script Candidates`
7. Confirm with user (checkpoint)
8. Scaffold skill directory tree by hand, following
`${CLAUDE_PLUGIN_ROOT}/references/layout/skill-structure.md`:
- Omit `target-dir` or use "project" for `.claude/skills/<skill-name>/`
- Create: `SKILL.md` (empty stub), `workflows/`, `references/`, and
`templates/`/`scripts/` if the skill needs them
- Create empty `reference.md` in each references subdir
- Reversion protection: `invariants.md` (stub), `examples/golden/`, `.decisions/`
9. Write to task doc: `## Scaffolded Files`
**Invariants stub:**
```markdown
# Invariants
Behaviors that must not change without explicit human approval.
> TODO: Fill after skill stabilizes (2-3 uses). See `references/tool-patterns/reversion-protection.md`.
## Critical Invariants
- [To be defined]
## Structural Invariants
- [To be defined]
```
**Outputs:** Task document with domain understanding, structure plan, scaffolded files.
---
### Phase 2: Processing (Sonnet)
**Objective:** Write workflows, reference.md files, knowledge docs, scripts, and templates.
**Read:**
- Task document (all sections from Phase 1)
- `${CLAUDE_PLUGIN_ROOT}/references/layout/skill-structure.md`
- `references/progressive-disclosure/reference-md-pattern.md`
**Do:**
1. Write workflows:
- One `workflows/<workflow-name>.md` per workflow
- Include: when to use, inputs, subtasks with subagent hints, task doc instructions
- Pattern hooks: brainstorming reference (if design decisions), verification step (if modifies files)
- Write to task doc: `## Workflows Written`
2. Write reference.md files:
- For each references subdir: write `reference.md`
- Include: purpose, what's here, when to read which file, model hints
- Stub knowledge docs
- Write to task doc: `## Reference.md Files Created`
3. Fill knowledge docs:
- Write each knowledge doc, <=150 lines
- If longer, split and update parent `reference.md`
- May require user input for domain expertise
- Write to task doc: `## Knowledge Docs Written`
4. Create scripts and templates:
- Write scripts for mechanical tasks
- Write templates for repetitive structures
- Make scripts executable
- Write to task doc: `## Scripts and Templates Created`
**Outputs:** Complete workflow files, reference.md navigation, knowledge docs, scripts, templates.
---
### Phase 3: Synthesis (Opus + Haiku cleanup)
**Objective:** Write SKILL.md, validate, generate description, final review.
**Subagent:** Opus for decisions, then Haiku for cleanup.
**Read:**
- Task document (complete)
- `${CLAUDE_PLUGIN_ROOT}/references/layout/skill-structure.md`
- All created workflow files (spot-check)
**Do (Opus):**
1. **Inline vs Reference decision:**
- Count workflow content lines (exclude blanks, frontmatter, headings)
- Threshold: <=40 (inline full), 41-100 (inline checklist + reference), >100 (reference only)
- Multiple workflows -> router pattern
2. Generate description via the `generate-description` workflow
(`${CLAUDE_PLUGIN_ROOT}/workflows/generate-description.md`):
- Input: type=skill, name, purpose, triggers
3. Write `SKILL.md` with description, applying inline vs reference decision
4. Write to task doc: `## SKILL.md Structure Decision`
5. Validate against `${CLAUDE_PLUGIN_ROOT}/templates/audit-checklist-template.md`
(Skill-Specific Attributes section)
6. Fix validation errors
7. Verify structure matches plan
8. Verify `reference.md` files accurate
9. Friction? Add to task doc: `## Friction / Improvement Notes`
10. Write final summary
**Do (Haiku cleanup):**
1. Remove task document artifacts
2. Verify all placeholder text filled
3. Final file permissions check (scripts executable)
**Outputs:** Complete, validated skill with SKILL.md, ready for use.

View File

@ -0,0 +1,110 @@
# Workflow: Create Workflow
Create workflow documents for Claude Code plugins that define repeatable processes for subagents.
## Who should do this work
- **Main thread**: Requirements gathering, design, verification
- **Haiku subagent**: File creation
## When to use
- Creating new workflow document for plugin
- Workflow file doesn't exist yet
- Defining repeatable process for subagents
## Before you start
If concept unclear, brainstorm: `references/brainstorming/workflow.md`
## Inputs required
- **workflow_name** - kebab-case
- **workflow_purpose** - Repeatable process this defines
- **target_plugin_path** - Where to create (plugin's skill directory)
- **subagent_requirements** - What subagent needs (tools, model)
## Task document
Create: `.claude/plugin-data/workflow-architect/tasks/new-workflow-<workflow-name>-<date>.md`
---
## Pattern consideration
See `references/tool-patterns/catalog.md`.
| Question | If Yes |
|----------|--------|
| Workflow involves design decisions? | Brainstorm first |
| Subagents modify files? | Include verification guidance |
| Subagents create files in user projects? | Follow [plugin-data-convention](../references/conventions/plugin-data-convention.md) |
| Reused across projects? | Consider golden examples |
---
## Subtasks
### 1. Understand requirements
Subagent: Main with user.
Read: `${CLAUDE_PLUGIN_ROOT}/references/layout/workflow-structure.md`
**Do:**
- Confirm workflow name (kebab-case)
- Understand specific purpose
- Identify subagent needs (tools, model)
- Identify input/output requirements
- Write to task doc: `## Requirements`
---
### 2. Design the workflow
Subagent: Main.
Read: `${CLAUDE_PLUGIN_ROOT}/references/layout/workflow-structure.md`
**Do:**
- Draft purpose and trigger conditions
- Define subtasks/steps
- Specify who performs each (main vs subagent)
- Identify what must be read per step
- Define constraints and validation
- If modifies files: include verification
- Write to task doc: `## Design`
---
### 3. Create the workflow file
Subagent: haiku.
Read: Task doc (requirements, design), `${CLAUDE_PLUGIN_ROOT}/references/layout/workflow-structure.md` (minimal skeleton section)
**Do:**
- Create `<target_plugin_path>/skills/<skill-name>/workflows/` if needed
- Write `<target_plugin_path>/skills/<skill-name>/workflows/<workflow-name>.md`
- Include: "When to use", "Inputs required", "Output", "Subtasks"
- Per subtask: who (main/subagent), what to read, what to do
- Include verification if modifies files
- Write to task doc: `## Created Files`
---
### 4. Verify and report
Subagent: Main.
**Do:**
- Verify structure complete
- Verify correct location
- Check all subtasks have clear ownership
- Summarize created
- Suggest use via SKILL.md entry point
---
## Reflection
- Workflow focused on single purpose?
- Subtasks clearly defined with explicit ownership?
- Would another developer understand what this accomplishes?

View File

@ -0,0 +1,47 @@
---
model_tier:
all_steps: main
note: "Lightweight workflow - can be executed inline without subagent"
---
# Workflow: Generate Description
## When to use
- Writing frontmatter for skill, agent, command, or plugin
- Called by other architect skills
## Inputs required
- **type** - skill, agent, command, or plugin
- **name** - kebab-case
- **purpose** - What it does / problem it solves
- **triggers** - When AI should use this
## Process
### 1. Read the formula
Read: `${CLAUDE_PLUGIN_ROOT}/references/layout/descriptions.md`
### 2. Draft description
Formula: `[Action verb] [what]. [Unambiguous trigger].`
- Action verb (Build, Generate, Create, Run)
- What it does (2-5 words)
- Trigger (prevents escape hatches)
### 3. Escape hatch test
"Can AI rationalize NOT using this while still doing the task?"
If yes -> rewrite trigger. Focus on immediate action, not downstream purpose.
### 4. Return
Output ONLY the description string. No explanation, no formatting.
Example: `Build Claude Code skills. Use when creating a skill.`
## Examples
| Type | Name | Result |
|------|------|--------|
| skill | skill-architect | Build Claude Code skills. Use when creating a skill. |
| agent | code-reviewer | Review code against implementation plan. Use after completing a major project step. |
| command | commit | Stage and commit changes. Use when ready to commit. |

View File

@ -0,0 +1,115 @@
---
status: legacy
note: "For maintenance of existing commands only. Prefer skills for new functionality."
model_tier:
gather: main
prioritize: main
apply: main
verify: main
---
# Workflow: Improve Command (LEGACY)
> **LEGACY WORKFLOW**: This workflow is for maintaining existing slash commands. For new functionality, prefer creating skills via `/cc-architect` (create-skill workflow) instead.
## When to use
- After using command and finding friction
- Description doesn't trigger correctly
- Clarify or simplify instructions
- Periodic maintenance
## Inputs required
- **command_path** - Path to command file
- **friction_notes** (optional) - Specific friction points
## Task document
Create: `.claude/plugin-data/slash-command-architect/tasks/improve-command-<command-name>-<date>.md`
## Output
- Task doc records changes
- Improved command verified and ready
- Optional follow-up audit offered
---
## Note on scope
Commands are simpler. Workflow is lightweight with fewer steps.
---
## Subtasks
### 1. Gather friction data
Subagent: Main.
**Do:**
- Check `.claude/plugin-data/slash-command-architect/tasks/` for mentions
- Ask user for pain points
- List in task doc
**Focus areas:**
- Description triggers (not invoking when expected, or unexpectedly)
- Instruction clarity (doing wrong thing)
- Tool permissions (missing tools or overly broad)
---
### 2. Prioritize improvements
Subagent: Main (inline judgment).
**Do:**
- Review friction notes
- Filter one-time issues
- Prioritize by impact
- Write to task doc
---
### 3. Apply improvements
Subagent: Main.
Read: `${CLAUDE_PLUGIN_ROOT}/references/layout/descriptions.md`
**Do per improvement:**
- Read command file
- Make targeted edit
- Document in task doc
**Common improvements:**
- Refine description for clearer triggers
- Simplify/clarify instructions
- Adjust tool permissions
---
### 4. Verify and reflect
Subagent: Main.
**Do:**
- Verify frontmatter valid YAML
- Check description follows "When/Why, Not How"
- Report summary
Offer: "Run quick audit on improved command?"
---
### 5. Record decisions (if applicable)
Subagent: Main.
**When to record:**
- Exceptions to description formula
- Tool permission changes
**How:**
- Template: `references/tool-patterns/templates/decision-record-template.md`
- Write: `<plugin_path>/.decisions/YYYY-MM-DD-<topic>.md`

View File

@ -0,0 +1,90 @@
# Workflow: Improve Plugin Docs
Harvest friction notes and apply targeted improvements to plugin documentation.
## Who should do this work
| Phase | Model | Why |
|-------|-------|-----|
| Research | Haiku | File gathering, friction collection |
| Processing | Sonnet | Prioritization, patch drafting |
| Review | Opus | Quality decisions, structure verification |
| Apply + Cleanup | Haiku | Mechanical edits, file operations |
## When to use
- After several tasks, harvesting learnings
- Recurring friction in knowledge docs
- Periodic maintenance
## Inputs required
- **target_skill** - Path to skill directory
- **task_scope** - Task documents to scan (default: all `.claude/plugin-data/plugin-architect/tasks/`)
## Task document
Create: `.claude/plugin-data/plugin-architect/tasks/improve-docs-<skill-name>-<date>.md`
---
## Phase 1: Research (Haiku)
**Artifact:** Task doc with collected friction notes
**Do:**
- Read task docs in scope
- Extract `## Friction / Improvement Notes` sections
- Group by target file
- Read current state of affected docs
- Write to task doc:
- `## Collected Friction Notes` (grouped by file)
- `## Current Doc State` (file paths and line counts)
**Exit:** If no friction notes found, report and end workflow.
---
## Phase 2: Processing (Sonnet)
**Read:** Task doc (friction notes, doc state)
**Artifact:** Task doc with prioritized improvements and proposed patches
**Do:**
- Filter noise (one-offs, already fixed)
- Identify patterns (repeated = high priority)
- Rank by impact
- For each high-priority improvement:
- Read target file and parent `reference.md`
- Draft patch (add/change/remove)
- Keep small and focused
- If doc would exceed ~150 lines: propose split
- Write to task doc:
- `## Prioritized Improvements` (ranked list with reasoning)
- `## Proposed Patches` (per file, with before/after context)
**Checkpoint:** Confirm prioritization and patches with user before proceeding.
---
## Phase 3: Synthesis (Opus + Haiku cleanup)
**Read:** Task doc (prioritized improvements, proposed patches)
**Artifact:** Updated docs + final report in task doc
**Do (Opus review):**
- Verify no structure breakage
- Verify patches address friction
- Flag if needs user decision
- Mark: approved/rejected/needs-revision
**Do (Haiku apply + cleanup):**
- Apply approved patches
- If splitting doc: update parent `reference.md`
- Write to task doc:
- `## Applied Changes` (files changed, patch status)
- `## Summary` (rejected patches and why, verification suggestions)
**Exit:** Report files changed and suggest re-running affected workflows to verify.

View File

@ -0,0 +1,65 @@
# Workflow: Improve Skill
**Model tier**: Main/Haiku (gather), Opus (prioritize), varies (apply), Main (verify)
## When to use
- After task using skill and encountering friction
- Knowledge docs outdated or incomplete
- Periodic maintenance
## Inputs required
- **skill_path** - Path to skill
- **friction_notes** (optional) - Specific friction points
## Task document
Create: `.claude/plugin-data/skill-architect/tasks/improve-skill-<skill-name>-<date>.md`
---
## Subtasks
### 1. Gather friction data
Subagent: Main or haiku.
**Do:**
- Check `.claude/plugin-data/skill-architect/tasks/` for friction notes
- Ask user for pain points
- List in task doc
---
### 2. Prioritize improvements
Subagent: opus.
**Do:**
- Review friction notes
- Filter one-time issues
- Prioritize by frequency/impact
- Write prioritized list to task doc
---
### 3. Apply improvements
Subagent: Varies by complexity.
Read: Files being modified.
**Do:**
- For each improvement: read file, make targeted edit, document change
- Update task doc with changes
---
### 4. Verify and reflect
Subagent: Main.
**Do:**
- Spot-check modified files
- Verify reference.md files accurate
- Report summary

View File

@ -0,0 +1,117 @@
# Workflow: Improve Workflow
Refine workflow documents based on friction encountered during use.
## Who should do this work
- **Main/Haiku**: Gather friction data
- **Opus subagent**: Prioritize improvements
- **Varies by complexity**: Apply improvements
- **Main**: Verify and reflect
## When to use
- After using workflow and encountering friction
- Instructions need refinement
- Add missing steps or improve ownership
- Periodic maintenance
## Inputs required
- **workflow_path** - Path to workflow file
- **friction_notes** (optional) - Specific friction points
## Task document
Create: `.claude/plugin-data/workflow-architect/tasks/improve-workflow-<workflow-name>-<date>.md`
## Output
- Task doc records changes
- Improved workflow verified and ready
- Optional follow-up audit offered
---
## Subtasks
### 1. Gather friction data
Subagent: Main or haiku.
**Do:**
- Check `.claude/plugin-data/workflow-architect/tasks/` for mentions
- Ask user for pain points
- List in task doc
**Focus areas:**
- Step clarity (unclear what to do)
- Missing steps
- Ownership ambiguity (who does what)
- Missing required reads
- Inadequate verification
---
### 2. Prioritize improvements
Subagent: opus.
**Do:**
- Review friction notes
- Filter one-time issues
- Prioritize by frequency/impact
- Write to task doc
**Priority:**
- **High:** Missing critical steps, ambiguous ownership, missing verification
- **Medium:** Unclear instructions, missing context reads
- **Low:** Style, wording
---
### 3. Apply improvements
Subagent: Varies by complexity.
Read: `${CLAUDE_PLUGIN_ROOT}/references/layout/workflow-structure.md`
**Do per improvement:**
- Read workflow file
- Make targeted edit
- Document in task doc
**Common improvements:**
- Add missing steps
- Clarify ownership (main vs subagent)
- Add missing "Must read" refs
- Add verification steps
- Improve step descriptions
---
### 4. Verify and reflect
Subagent: Main.
**Do:**
- Spot-check modified file
- Verify subtasks have clear ownership
- Verify required sections present
- Report summary
Offer: "Run quick audit on improved workflow?"
---
### 5. Record decisions (if applicable)
Subagent: Main.
**When to record:**
- Non-standard structures
- Delegation pattern changes
- Exceptions to best practices
**How:**
- Template: `references/tool-patterns/templates/decision-record-template.md`
- Write: `<plugin_path>/.decisions/YYYY-MM-DD-<topic>.md`

View File

@ -0,0 +1,151 @@
# Workflow: Add Skill to Plugin
Add a new skill to an existing plugin.
## Who should do this work
| Phase | Model | Why |
|-------|-------|-----|
| Research | Haiku | File gathering, scaffolding |
| Processing | Sonnet | Content drafting, analysis |
| Synthesis | Opus | Quality review, final decisions |
| Cleanup | Haiku | Mechanical file operations |
## When to use
- Adding skill to existing plugin
- Skill doesn't exist or needs rebuild
## Before you start
If concept unclear, brainstorm: `references/brainstorming/workflow.md`
## Inputs required
- **plugin_path** - Where plugin lives (or "create new plugin first")
- **skill_name** - kebab-case
- **skill_purpose** - Problem this solves
- **initial_workflows** - At least one task to handle
For descriptions: Read `references/layout/descriptions.md` - "when/why" formula, not implementation.
## Task document
Create: `.claude/plugin-data/plugin-architect/tasks/new-skill-<skill-name>-<date>.md`
All phases append to this.
---
## Phase 1: Research (Haiku)
**Inputs:** User requirements, plugin path
**Outputs:** Task doc with domain analysis and validated structure plan
### Actions
1. **Understand the domain** (interactive with user)
- Clarify skill purpose and scope
- Identify major workflows (new X, update X, debug X)
- Identify knowledge domains needed
- Write to task doc: `## Domain Understanding`
2. **Design the structure**
- Read: `${CLAUDE_PLUGIN_ROOT}/references/layout/reference.md`
- Map workflows -> `workflows/*.md` files needed
- Map knowledge domains -> `references/` subdirs
- Identify scripts vs templates vs knowledge docs
- Write to task doc: `## Proposed Structure`
3. **Validate with user**
- Present structure plan
- Get confirmation or adjust
- Write to task doc: `## Structure Approved`
4. **Scaffold workspace**
- Follow `${CLAUDE_PLUGIN_ROOT}/references/layout/skill-structure.md`
- Create `skills/<skill-name>/` directory tree
- Create empty: `SKILL.md`, `workflows/`, `references/`, `templates/`, `scripts/`
- Create empty `reference.md` in each references subdir
- Write to task doc: `## Scaffolded Files`
---
## Phase 2: Processing (Sonnet)
**Inputs:** Task doc from Phase 1
**Outputs:** Complete skill structure with all content
### Actions
1. **Write SKILL.md**
- Read: Task doc, `${CLAUDE_PLUGIN_ROOT}/references/layout/skill-structure.md`
- Write `SKILL.md` with workflow routing only
- Just "when to use" and "read: workflows/X.md"
- Write to task doc: `## SKILL.md Written`
2. **Write workflow files**
- Read: Task doc, `${CLAUDE_PLUGIN_ROOT}/references/layout/skill-structure.md`, `workflows/plugin-add-skill.md`
- For each workflow from structure plan:
- Write `workflows/<workflow-name>.md`
- Include: when to use, inputs, subtasks with subagent hints, task doc instructions
- Write to task doc: `## Workflows Written`
3. **Write reference.md files**
- Read: Task doc, `references/progressive-disclosure/reference-md-pattern.md`, `${CLAUDE_PLUGIN_ROOT}/references/layout/reference.md`
- For each references subdir:
- Write `reference.md` with purpose, what's here, when to read which file
- Include model hints
- Stub knowledge docs
- Write to task doc: `## Reference Indices Written`
4. **Fill knowledge docs**
- Read: Task doc, relevant `reference.md` files
- Write each knowledge doc, <=150 lines
- If longer: split and update parent `reference.md`
- May require user input for domain expertise
- Write to task doc: `## Knowledge Docs Written`
5. **Create scripts and templates**
- Read: Task doc (scripts/templates from Phase 1 plan)
- Write scripts for mechanical tasks
- Write templates for repetitive structures
- Make scripts executable
- Write to task doc: `## Scripts and Templates Created`
---
## Phase 3: Synthesis (Opus + Haiku cleanup)
**Inputs:** Task doc, all created files
**Outputs:** Verified skill, reflection notes, clean workspace
### Actions (Opus)
1. **Comprehensive review**
- Read: Full task doc, `SKILL.md`, all workflows, spot-check references
- Verify structure matches approved plan
- Verify `reference.md` files accurate and navigable
- Check workflow quality: clear subagent hints, proper inputs/outputs
- Check consistency: naming, formatting, cross-references
- Write to task doc: `## Quality Review`
2. **Friction reflection**
- Read: `references/self-improvement/friction-reflection.md`
- Identify friction points during creation:
- Docs hard to find?
- Too many file reads?
- Work that should've been scripted?
- Structure unclear?
- Write to task doc: `## Friction / Improvement Notes`
3. **Final summary**
- Summarize what was created
- Note any limitations or future work
- Write to task doc: `## Final Summary`
### Actions (Haiku cleanup)
4. **Workspace cleanup**
- Remove any temporary files
- Verify task doc is complete and well-organized
- Confirm all files in correct locations

View File

@ -0,0 +1,186 @@
# Workflow: Plugin Config
Single flexible workflow for all plugin configuration operations. Routes through a deterministic Ruby script, handles verification failures with self-healing, and presents results to the user.
## Who should do this work
| Phase | Model | Why |
|-------|-------|-----|
| Execute operation | Haiku | Mechanical: run script, parse JSON |
| Self-healing (if needed) | Sonnet | Diagnosis, workaround, friction logging |
| Interpret & report | Main | User-facing presentation |
| Cross-operation intelligence (if needed) | Sonnet | Chain audit -> fix -> verify |
## When to use
- Enable or disable a plugin in a project
- Register or unregister a plugin in the marketplace
- Debug plugin configuration issues
- List installed/registered plugins
- Audit plugin config state (marketplace, installed, settings)
## Inputs required
| Input | Required | Description |
|-------|----------|-------------|
| **operation** | Yes | `enable` \| `disable` \| `register` \| `unregister` \| `audit` \| `list` |
| **plugin_name** | Yes (except `list`) | Plugin name (kebab-case) |
| **marketplace_id** | For enable/disable/audit | Marketplace identifier (e.g. `cc-plugins`) |
| **project_path** | For enable/disable/audit | Absolute path to project using the plugin |
| **marketplace_file** | For register/unregister/audit | Path to `marketplace.json` |
## Script location
```
${CLAUDE_PLUGIN_ROOT}/scripts/plugin_config/plugin_config.rb
```
## Exit codes
| Code | Meaning |
|------|---------|
| 0 | Success. JSON result on stdout. |
| 1 | Invalid operation or unexpected error. JSON diagnostic on stderr. |
| 2 | Schema mismatch. JSON diagnostic on stderr with `missing_keys`. |
---
## Phase 1: Execute Operation (Haiku)
**Purpose:** Run the Ruby script with the requested operation and parameters, parse the JSON output, and check for success.
**Steps:**
1. Build the command from inputs:
```bash
ruby ${CLAUDE_PLUGIN_ROOT}/scripts/plugin_config/plugin_config.rb <operation> \
--plugin=<plugin_name> \
--marketplace=<marketplace_id> \
--project=<project_path> \
--marketplace_file=<marketplace_file>
```
Omit parameters that are not applicable to the operation.
2. Execute the command and capture stdout, stderr, and exit code.
3. **If exit code = 0:**
- Parse stdout as JSON.
- Check for a `verified` field in the result. If `verified: false`, proceed to Phase 1b.
- If `verified: true` or no `verified` field, proceed to Phase 2.
4. **If exit code = 1:**
- Parse stderr as JSON diagnostic.
- Report the error in Phase 2. Do not retry.
5. **If exit code = 2:**
- Parse stderr as JSON diagnostic (schema mismatch with `missing_keys`).
- Proceed to Phase 1b (self-healing).
---
## Phase 1b: Self-Healing Mode (Sonnet)
**Purpose:** Triggered on verification failure (`verified: false`) or schema mismatch (exit code 2). Diagnose root cause, attempt workaround, log friction.
**Triggers:**
- Exit code 2 (schema mismatch -- file exists but missing expected keys)
- Successful operation but `verified: false` (file was written but verification failed)
**Steps:**
1. **Diagnose:** Read the diagnostic JSON. Identify:
- Which file failed (settings, marketplace, installed_plugins)
- What was expected vs. actual
- Whether the file exists, is valid JSON, and has the expected structure
2. **Attempt workaround:**
- **Schema mismatch (missing keys):** Read the file, add missing keys with safe defaults (empty objects/arrays), write it back, then re-run the original operation.
- **Verification failure:** Read the target file, compare with expected content, attempt a direct write if the content is close but not matching, then re-run.
3. **Assess severity:**
- **Low:** Workaround succeeded on retry. Note in friction log, continue to Phase 2.
- **Medium:** Workaround partially succeeded. Report to user with details, continue to Phase 2.
- **High:** Workaround failed. Report blocker to user, do not proceed to Phase 2.
4. **Log friction:** Append an entry to `.claude/plugin-data/cc-architect/cli-friction-log.md`:
```markdown
### <date> -- <operation> -- <severity>
**File:** <path>
**Expected:** <what was expected>
**Actual:** <what happened>
**Workaround:** <what was tried>
**Outcome:** <resolved | partially resolved | unresolved>
```
---
## Phase 2: Interpret & Report (Main)
**Purpose:** Present the operation result to the user in a clear, actionable format.
**Steps:**
1. Read the parsed JSON result from Phase 1.
2. Format based on operation type:
**enable/disable:**
- Confirm the action taken (plugin enabled/disabled in project).
- Show the settings file path that was modified.
- If `verified: true`, confirm success.
**register/unregister:**
- Confirm the plugin was added to/removed from marketplace.json.
- Show the marketplace file path.
**audit:**
- Present each check (marketplace, installed, settings) with status.
- List issues found with recommended fixes.
- Summarize: "N checks passed, M issues found."
**list:**
- Display plugins in a table or list format.
- Group by status if applicable.
3. If self-healing occurred (Phase 1b ran), include a note about what was auto-corrected.
---
## Phase 3: Cross-Operation Intelligence (Sonnet, conditional)
**Purpose:** When an audit reveals fixable issues, chain operations to resolve them automatically.
**Trigger:** Phase 2 completed an `audit` operation that found issues with available fixes.
**Steps:**
1. Review audit results for issues that have a `fix` field.
2. For each fixable issue, ask the user: "Would you like to fix these issues automatically?"
3. If user approves:
- For each fix, determine the corresponding operation (e.g., "not registered" -> `register`, "not enabled" -> `enable`).
- Execute each fix operation by re-entering Phase 1 with the appropriate parameters.
- After all fixes, re-run `audit` to verify all issues are resolved.
4. Present final state to user.
---
## Error handling
| Scenario | Action |
|----------|--------|
| Ruby not installed | Report: "Ruby is required. Install with your package manager." |
| Script file not found | Report path and suggest checking cc-architect installation. |
| JSON parse failure on stdout | Treat as unexpected error. Log raw output to friction log. |
| Permission denied on config files | Report which file and suggest permission fix. |
## Anti-patterns
| Anti-Pattern | Why Wrong | Correct Approach |
|--------------|-----------|------------------|
| Editing config files directly | Bypasses verification | Always use the Ruby script |
| Retrying indefinitely on failure | Wastes tokens | Max 1 self-healing retry per operation |
| Running audit after every operation | Unnecessary overhead | Only chain audit when explicitly requested |
| Skipping Phase 1b on exit code 2 | Schema issues are recoverable | Always attempt self-healing for exit code 2 |

View File

@ -0,0 +1,264 @@
# Workflow: Synthesize Results
**Model tier**: Opus (requires intelligent synthesis and quality judgment)
## When to use
Final step in any multi-workflow execution plan. Called after all execution subagents have completed and written their outputs.
## Purpose
Read all previous step outputs, synthesize into a coherent deliverable, and produce the final user-facing artifact.
## Inputs
- **plan_path**: Path to current execution plan (`.claude/plugin-data/cc-architect/plans/current-plan.md`)
- **artifact_type**: Type of final output (plugin, skill, workflow, command, description, audit)
## Output
- `.claude/plugin-data/cc-architect/output/final.md`
---
## Phase 1: Locate Outputs
Read the execution plan to identify all previous step outputs.
**Extract from plan:**
1. List of output files from each completed step
2. Artifact type being produced
3. Request summary (what user wanted)
**Build file manifest:**
```
Step 1: .claude/plugin-data/cc-architect/tasks/{step-1-output}.md
Step 2: .claude/plugin-data/cc-architect/tasks/{step-2-output}.md
...
```
---
## Phase 2: Read and Analyze
Read each output file in order.
**For each file, extract:**
- Key findings or artifacts created
- Decisions made
- Warnings or issues flagged
- Cross-references to other files
**Build synthesis context:**
- Deduplicate overlapping information
- Identify contradictions or conflicts
- Note dependencies between outputs
---
## Phase 3: Synthesize
Combine outputs according to artifact type.
### Artifact Type: Plugin
```markdown
# Plugin Created: {plugin-name}
## Summary
{One paragraph describing what was built}
## Files Created
| Path | Purpose |
|------|---------|
| `{path}` | {description} |
## Skill(s) Included
- **{skill-name}**: {brief description}
## Next Steps
1. {Actionable next step}
2. {Actionable next step}
## Configuration (if applicable)
{How to configure the plugin}
```
### Artifact Type: Skill
```markdown
# Skill Created: {skill-name}
## Summary
{One paragraph describing the skill's purpose and trigger}
## Files Created
| Path | Purpose |
|------|---------|
| `{path}` | {description} |
## Usage
Invoke with: `/{skill-name}` or triggered by: {trigger conditions}
## Workflows Included
- **{workflow-name}**: {when to use}
## Golden Examples Needed
{Suggest 1-2 golden examples user should create based on their domain}
## Next Steps
1. Test with a real use case
2. Create golden examples
3. Add invariants as patterns emerge
```
### Artifact Type: Workflow
```markdown
# Workflow Created: {workflow-name}
## Summary
{One paragraph describing what this workflow accomplishes}
## File Location
`{path-to-workflow}`
## Integration
{How this workflow is invoked - from which skill, with what triggers}
## Testing
{How to verify the workflow works correctly}
```
### Artifact Type: Audit
```markdown
# Audit Complete: {target-name}
## Verdict: {Ready / Not Ready}
## Summary
- Significant issues: {N}
- Minor issues: {N}
- Polish items: {N}
## Critical Findings
{List significant issues with severity and remediation}
## Recommendations
{Prioritized list of actions}
## Patterns Discovered
{Novel approaches worth considering for standards}
```
### Artifact Type: Description
```markdown
# Description Generated
## Result
`{the description string}`
## Escape Hatch Test
{Pass/Fail with reasoning}
## Usage
Add to frontmatter:
```yaml
description: {the description string}
```
```
---
## Phase 4: Quality Check
Before writing final output, verify:
**Completeness:**
- [ ] All execution steps represented in synthesis
- [ ] No orphaned outputs (created but not referenced)
- [ ] User's original request fully addressed
**Coherence:**
- [ ] No contradictory information
- [ ] Consistent terminology throughout
- [ ] Logical flow from problem to solution
**Actionability:**
- [ ] Clear next steps provided
- [ ] File paths are accurate and complete
- [ ] User can act on this without additional context
**Quality signals (Opus judgment):**
- Does this feel complete?
- Would a user be satisfied receiving this?
- Is anything important buried or unclear?
---
## Phase 5: Write Final Output
Write to: `.claude/plugin-data/cc-architect/output/final.md`
**Header:**
```markdown
# {Artifact Type}: {Name}
**Generated**: {date}
**Request**: {one-line summary}
**Status**: Complete
---
```
**Body:**
Use appropriate artifact template from Phase 3.
**Footer:**
```markdown
---
## Execution Details
| Step | Model | Output | Status |
|------|-------|--------|--------|
| {step} | {model} | {file} | Complete |
## Cleanup Pending
The following temporary files will be removed:
- {list of task files}
```
---
## Error Handling
**Missing output file:**
- Note which step failed
- Include partial synthesis of completed steps
- Flag incomplete sections clearly
- Recommend re-running failed step
**Conflicting outputs:**
- Present both versions
- Note the conflict
- Recommend resolution approach
**Quality check failure:**
- Do not write incomplete synthesis
- Return to orchestrator with specific gaps
- Recommend additional steps needed
---
## Anti-Patterns
| Wrong | Right |
|-------|-------|
| Copy-paste raw outputs | Synthesize and deduplicate |
| Hide warnings from user | Surface all issues clearly |
| Skip quality check | Always verify before writing |
| Vague next steps | Specific, actionable guidance |
| Bury important findings | Lead with critical information |

View File

@ -7,6 +7,18 @@ zero-token) on `SessionStart`; checks and cleans on demand via skills.
> Read `PRD.md` first — it is the source of truth for scope, decisions, and
> rationale. This file is the build map.
> Vault user guide (nuance/mental-model, not a how-to):
> `~/Documents/SecondBrain/user-guide/os-doc-hygiene-user-guide.md`.
## Lifecycle layer (2026-07-15)
A rulebook layer sits on top of the scan/classify/clean core: global
`rulebook.json` + optional per-project `.dochygiene-rules.json` declare
lifetime rules for known-temporary artifacts, feeding tier derivation and a
`/os-doc-hygiene:calibrate` skill for tuning rules against a real project.
Read `lifecycle-spec.md` before touching `rulebook.py`, the scanner's
lifecycle signals, or the calibrate skill; decisions are ADR-00380041.
## Core distinction (do not conflate)
- **Stale** = the doc is *wrong* (contradicted, orphaned, superseded,
@ -22,7 +34,8 @@ Severity scales with **injection frequency** — a stale line in `CLAUDE.md` (au
1. The `SessionStart` hook **only reminds** — it never runs analysis or mutates
anything, and spends no AI tokens. All mutation is user-invoked.
2. Reminder **snoozes** (≤ once/day while stale) via `last_reminded`.
3. State lives **in-project** under gitignored `.dochygiene/`. No global index.
3. State lives **in-project** under gitignored `.cc-os/dochygiene/` (ADR-0027;
legacy `.dochygiene/` is fallback-read only). No global index.
4. **Report rollover**: keep only the latest report. The tool must not become
the bloat it polices.
5. Cleanup is **git-safe**: clean/committed tree required (or auto WIP

Some files were not shown because too many files have changed in this diff Show More