Compare commits
11 Commits
research/c
...
main
| Author | SHA1 | Date |
|---|---|---|
|
|
3f76755e85 | |
|
|
e82bfcb0cd | |
|
|
b062ac354e | |
|
|
39356ebdbf | |
|
|
3466159f7c | |
|
|
0d303caf43 | |
|
|
9f11df3e2a | |
|
|
807dcc8d90 | |
|
|
fe04297604 | |
|
|
7b9afb1f6a | |
|
|
e1d22d83ba |
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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 -->
|
||||
|
|
|
|||
|
|
@ -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-0038–0041): 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);
|
||||
|
|
|
|||
|
|
@ -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-0038–0041)** — 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).
|
||||
|
|
|
|||
|
|
@ -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._
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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)"
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
@ -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.
|
||||
|
|
@ -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`
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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?"
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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`
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -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`
|
||||
|
|
@ -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
|
||||
|
|
@ -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`
|
||||
|
|
@ -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`
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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.
|
||||
```
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
```
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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}
|
||||
```
|
||||
|
|
@ -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.
|
||||
|
|
@ -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).
|
||||
|
|
@ -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?"
|
||||
|
|
@ -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
|
||||
|
|
@ -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)"
|
||||
|
|
@ -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)"
|
||||
|
|
@ -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 |
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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`
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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?
|
||||
|
|
@ -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. |
|
||||
|
|
@ -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`
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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`
|
||||
|
|
@ -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
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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-0038–0041.
|
||||
|
||||
## 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
Loading…
Reference in New Issue