Six pre-push hooks were validating overlapping sets of the same manifests. check-manifests (marketplace.json/plugin.json path checks) is redundant with validate-plugins (claude plugin validate) and apm-pack-check-clean, which already cover the same ground. Deletes the check-manifests hook entry, scripts/check-manifests.sh (282 lines), and tests/test-check-manifests.sh (771 lines). scripts/lib/marketplace-plugins.sh is kept — it is still sourced by sync-plugin-content.sh. Updates the now-stale check-manifests.sh mentions and hook counts in README.md and docs/spec/gates.md. The apm-audit-ci and apm-marketplace-check hooks named in the same finding are left untouched — the audit flags them as needing a separate decision. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD
32 KiB
Simplification audit
Date: 2026-09-10. Read-only analysis; nothing has been changed. Purpose: a hand-off for deciding what to remove, merge, and shrink. Findings are ranked by payoff within each area; effort is S/M/L. Claims were independently re-verified against the repo by a clean reviewer; corrections have been applied.
Assumptions agreed before analysis: anything is on the table, Claude Code and Copilot CLI both stay supported, findings are ranked with effort.
Counting convention: line counts are hand-edited .apm/ source unless marked "incl. mirror". Every .apm/ file has a byte-identical generated copy at the plugin root, so plugin cuts count double in the repo total.
1. The shape of the problem
| Measure | Value |
|---|---|
| Tracked files / lines | 820 / 102,000 |
Lines in plugins/ |
70,600 (69% of repo) |
Of which the 39 SKILL.md files a model actually loads |
~2,600 lines (under 4% of plugin lines) |
Generated flat mirror files (byte copies of .apm/) |
263 files, ~22,000 lines |
docs/research/ vendored inside plugins |
~19,000 lines, nothing executable reads it |
Repo-level docs/research/ + docs/notes/ |
4,500 lines, 47% of all prose words, 6 of 11 research files linked only from each other |
Enforcement: hook entries in .pre-commit-config.yaml / pre-push hooks |
33 / 14 |
Enforcement: tests/*.sh + runners + scripts/ |
12,400 + 475 + 4,500 lines |
| Validator scripts inside kyberforge (+ their bats tests) | 6,800 + 5,300 lines |
| Preload tax (39 skill names + descriptions) | 10,987 chars, ~2,750 tokens per session |
| Commits since 2026-05-10 / share touching hook, test, gate, vale, or sync | 447 / ~25% |
The pattern across every area is the same: the payload (skill bodies, rules, decisions) is small and the scaffolding around it (mirrors, research dumps, sync gates, tests of tests, justification prose) is 10 to 30 times larger. A quarter of all commits have gone into maintaining the scaffolding.
2. Measured baseline: hooks and tests
Measured on this machine, clean tree, all hooks passing. pre-commit run --all-files per stage.
| Gate | Wall time |
|---|---|
| Full pre-push stage (everything below, sequential) | ~5 min 10 s |
run-tests (26 bash suites + 351 bats tests) |
276 s |
apm-audit-ci (7 manifests) |
12.2 s |
validate-plugins (6 × claude plugin validate) |
4.9 s |
check-plugin-content-sync |
4.5 s |
apm-pack-check-clean |
3.1 s |
| Other 9 pre-push hooks combined | 7.6 s |
| Full pre-commit stage, all files | 18.2 s |
run-tests is 90% of the wall time. Every push pays it in full: the runner has no change detection and the config sets always_run: true. apm-audit-ci is the second-slowest hook; per its own comment block its earlier description overclaimed, and what it verifies today is that seven manifests parse and the lockfile exists.
Where the 276 s goes (each suite run alone, sequential):
| Suite | Time | Note |
|---|---|---|
test-sync-plugin-content.sh |
83 s | 14 temp trees, 2 git init, repeated apm pack |
| all 351 bats tests (10 files, kyberforge and core validators) | 64 s | mostly validate.sh / validate-provenance.sh fixtures |
test-adr0020-differential.sh |
29 s | 12 assertions; re-runs two validators over the live corpus and a fixture tree |
test-check-vale-style-sync.sh |
25 s | guards a byte-identical copy |
test-vale-wrap.sh |
14 s | |
test-adr0020-frontmatter.sh + -targets.sh |
25 s | |
| Remaining 20 suites | 36 s | 12 of them run in under 2 s each |
Five suites account for 215 s of 276 s. Three of those five (sync-plugin-content, vale-style-sync, adr0020-differential) test tooling that findings 2, 7, and 14 propose to delete or shrink, so the fastest path to a quick pre-push is removing the duplication those tests guard rather than optimising the tests.
3. Enforcement layer: hooks, tests, scripts
This is the area you named as hardest to understand and slowest. Root cause: most pre-push hooks exist to keep two copies of something in sync, or to re-validate what another hook already validates.
-
Six hooks validate overlapping sets of the same manifests.
check-manifests,validate-plugins,validate-marketplace,apm-pack-check-clean,apm-marketplace-check,apm-audit-ci. Keep the twoclaude plugin validatehooks plusapm-pack-check-clean.Deletecheck-manifests(282 lines + 771 test lines; itslib/marketplace-plugins.shstays becausesync-plugin-content.shsources it).apm-audit-cispends 12 s confirming that manifestsapm packalready parses do parse; drop or keep on that basis. Move the network-dependentapm-marketplace-checkto a release checklist. Effort S.Done (2026-09-12): see commit
9051d14ondocs/simplification-audit. Deleted thecheck-manifestspre-commit hook entry,scripts/check-manifests.sh(282 lines), andtests/test-check-manifests.sh(771 lines); keptscripts/lib/marketplace-plugins.sh, still sourced bysync-plugin-content.sh. Updated the now-stalecheck-manifests.shmentions inREADME.mdanddocs/spec/gates.md(hook table row and hook counts). Theapm-audit-ciandapm-marketplace-checkdecisions in this finding remain open — out of scope for this change. -
Four "keep two copies in sync" gates: 1,100 script lines + 1,600 test lines. Each one is a symptom of duplication that could be removed instead of guarded:
check-vale-style-sync: 413 lines + 798 test lines guarding a byte-identical 526-linevale-wrap.shand style directory copied between skill-audit and agent-audit. About 350 of its lines run Vale glob probes against the hook file patterns. Disappears if the two audit skills merge (finding 14); the probes belong intest-vale-wrap.sh.check-scope-walkup-sync: 365 lines cross-checking four independent ports of the same package-root walk-up. Disappears if the ports share one script or the skills merge.check-marketplace-mirror-sync: guards.github/plugin/marketplace.json. The script header calls it Copilot's legacy convention path and says Copilot also accepts the Claude path; the vendored Copilot docs list it as primary. Verify against current Copilot CLI before deleting hook, script, test, and mirror file.check-executables-allow-sync: 474 lines to assert one string equals kyberforge's version. A six-line grep, or drop it (the failure mode is visible and recoverable). Effort S each, M for the walk-up.
-
Tests of the test harness: 1,090 lines testing 475 lines.
test-run-tests.shandtest-run-bats.shdefend "green either way" holes that exist only because the runners hand-roll TAP parsing and set-equality checks. Replace both runners with about 40 lines (bats -r pluginsplus a parallelfind | xargsovertest-*.sh) and delete the meta-tests.lib/batch-run.shstays;sync-plugin-content.shsources it. Effort M. -
skill-frontmatteris a 62-line bash script inlined in YAML with its own 366-line test.skill-size-check.shalready parses the same frontmatter with PyYAML. Fold it in (about 15 Python lines), delete the inline hook, its test, and the 79 lines ingates.mdarguing for the split. Effort S. -
skill-size-check.shhas six test files totalling 3,589 lines for one 1,497-line script, split by ADR section rather than behaviour.test-adr0020-differential.shis 452 lines for 12 assertions. Merge to two files. Effort M. -
Prose-grep tests.
test-governance-layer.shandtest-instructions-and-docs.sh(583 lines) grep markdown for phrases, including a one-shot "issue 0015 refactor incomplete" assertion made permanent and an assertion thatdocs/notes/exists. Delete both.check-apm-agents-valid.sh(161 + 264 test lines) is a loop plus fail-closed guards aroundvalidate.sh; it folds into the merged audit skill's own tests (finding 14). Effort S. -
check-plugin-content-sync.shis 813 lines wrappingapm pack, with a 1,291-line test. The mirror itself must stay (Claude Code marketplace installs need flat directories), and the script does real work a baregit diffwould lose: it stripstests/from the mirror, regenerates bothplugin.jsonfiles withmcpServersreinjected, and packs into a scratch copy so--checknever mutates. Even so, 2,100 lines for that is disproportionate; target a third. Effort M. -
docs/spec/gates.md(1,048 lines) is roughly 15% "what is enforced" and 85% post-mortems of defects already fixed and pinned by tests. The 60-line hook table is the useful part. Target 200 lines. The same applies to the 106 comment lines in.pre-commit-config.yamland toscripts/, where 8 of 15 files are 40 to 60% comments. Effort M.
Proposed target. Pre-push 14 hooks to 6: run-tests, validate-plugins, validate-marketplace, apm-pack-check-clean, check-plugin-content-sync, check-release-needed. Pre-commit stays roughly as is minus skill-frontmatter, and minus check-ast once finding 9 removes the only .py files. Tests 26 files to about 10 (12,400 to about 5,000 lines). Keep bats and its three submodules; the 351 bats tests ship inside plugins and are the right tool there. Do not port the bash suites to bats; delete them instead.
4. Plugins
The shared pattern: per-skill README.md files no model reads, a docs/research/ dump per plugin, a sources.md provenance chain with its own validator, and reference files that restate man pages.
4.1 Cross-plugin (apply everywhere)
-
Delete
docs/research/from every plugin (~19,000 lines). kyberforge's alone is 14,143 lines, 32% of the plugin, and about 8,900 of those are vendored third-party content (Anthropicskill-creatorincluding a 1,325-lineviewer.htmland ten.pyfiles, obra/superpowers, mattpocock). The rest is copied tool documentation. The gitea references explicitly say the research doc "has a known history of drifting from the deployed server". Everyapm.ymlusesincludes: auto; whether the directory ships to consumers needs one check. Keep upstream URLs in one line per plugin README; git history keeps the rest. Check obra/superpowers licence if anything is retained. Goes together with finding 11: 32sources.mdfiles carry "Research doc" paths into these directories. Effort S.Decision (2026-09-12): Keep.
docs/research/is retained on purpose — it's read by agents doing work sourced from those docs. Not proceeding. -
Delete per-skillREADME.mdandreferences/README.md(48 files, 1,574 lines). They restate the SKILL.md in narrative form. The pre-commit config itself notes a skill README "is consumer-facing prose that no agent ever loads". Keep one plugin-level README with one line per skill. Requires dropping the README criterion inskill-audit/references/file-structure.mdand the README step innew-skill.sh. Effort S.
Done (2026-09-12): see commit
edcc57condocs/simplification-audit. Deleted the 48 per-skill/reference READMEs plus 2 scaffold templates; dropped the README criterion fromskill-audit'sfile-structure.mdandfinding-criteria.mdand the README-generation step fromnew-skill.sh; updatednew-skill.batsto match. Plugin-root READMEs were kept, not part of this finding.
-
Drop the provenance chain:
sources.md,source_keysfrontmatter,validate-provenance.sh. 32 plugin and skillsources.mdfiles (about 1,300 lines) plus 9 research indexes, 216 source files withsource_keys, two copies of the validator (1,198 and 632 lines) with ten checks, and 125 bats tests exist to track which upstream informed which file. Git blame and a URL in the README do the same job. This is more code than the content it tracks. Effort M (touches skill-audit, both validator copies, two repo tests, and every skill's frontmatter). -
Strip ADR and changelog narration from model-facing files.ADR-0020is cited in 3 of 7 kyberforge SKILL.md files and 16 references; ADR-0023 is cited inline 21 times in the git plugin. Examples: "was the old house rule and ADR-0020 deleted it", "were removed per ADR-0015 once issue #90 landed", "this file previously recordedlist_issuesas having neither atypenor amilestonesparameter".skill-author/references/retrofit.md(197 lines) is a one-time migration guide; it is loaded fromimprove.mdand listed insources.md, so remove those in the same change. These belong in git history or the ADR, not in context. Effort S.
Done (2026-09-12): see commit
edcc57condocs/simplification-audit. Historical narration stripped from kyberforge (ADR-0020) and git (ADR-0023) skill content;retrofit.mddeleted along with its load-step andsources.mdentries. Caught in review: someADR-0023tags were not narration but thecheck-rtk-prefixhook's required opt-out marker for intentionally-bare git commands — those 12 were restored, not left stripped.
State repeated boilerplate once or delete it. A near-identical "Resolve owner and repo" block in 5 of 7 gitea skills; 404-masks-403 in 6 files; manual pagination in 7; main/master refusal in 9 git files; the "use the project's domain glossary, respect ADRs" paragraph in 5 bin skills. Three git skills define three different structured-result JSON shapes whose only consumer isgit-orchestrate(finding 19). Effort S.Done (2026-09-12): see commit
b4c3d5e. Trimmed each repeated instance in place — same meaning, fewer words — rather than extracting to a shared file (blocked by the one-file-per-skill install constraint, ADR-0014): the "Resolve owner and repo" block across 5gitea-*skills, the 404-masks-403 note across 6 gitea files, the manual-pagination explanation across 8 gitea files, the main/master force-push refusal across 7 git plugin files (some with multiple internal restatements), and the domain-glossary/ADR paragraph across 5binskills. This was a trim-in-place pass, not a merge: the cross-skill duplication itself remains and is coupled to the (out-of-scope) skill-merge findings 19/20. Left the three git skills' structured-result JSON shapes untouched, as directed. Verified no regressions withscripts/skill-size-check.sh(pre/post diff) andclaude plugin validateon both plugins.
4.2 kyberforge (290 files, 44,568 lines incl. mirror; the 7 SKILL.md bodies are 333 lines, under 1%)
-
Merge
skill-audit+agent-auditinto oneauditskill (removes about 3,300 lines and two pre-push hooks).vale-wrap.shis byte-identical in both; five Vale rules byte-identical (agent-audit carries one extra, so it is the superset);validate.shshares a 1,061-line boundary-target resolver block that diffs as zero lines; SKILL.md steps 1, 3, 4 and the gotchas are the same text. Each copy is hard-wired to one mode, so the merged script needs a path switch. The duplication exists because a plugin-cache install copies only each skill's own files (the rule ADR-0014 follows), so a script cannot be shared across skills; merging the skills is the only way to remove the copy. Effort M. -
Merge
skill-author+agent-authorlikewise.contract.mdshares most of its Description section;new-skill.shandnew-agent.shimplement the same package-root walk-up with different mode names; step 1 dispatch tables and step 3 gates are near-identical. Keep the agent scope logic (plugin vs project/user) as its own reference. Effort M. -
Cut the validators by an order of magnitude.
validate.shis 1,677 lines of bash with embedded Python, ported twice;skill-size-check.shis 1,497. Target about 200 lines total: frontmatter present, size ceilings, boundary targets resolve. The 526-linevale-wrap.shexists to work around folded>scalars in descriptions; writing descriptions as|literal blocks removes the folding problem, but the wrapper is also the exported hook entry in.pre-commit-hooks.yamland carries the NOT RUN guard the audits depend on, so it shrinks rather than disappears. This is where the real complexity lives and is the item most worth discussing. Effort L. -
Fold
forgeandapm-install.forgeis a four-row routing table plus 207 lines of references explaining fork vs inline; it should be 25 lines with no references.apm-install(53 lines + 17-line sources) becomes a sixth dispatch row inapm-workflow. Effort S. -
Delete prose the model already knows. "Valid characters: lowercase letters, numbers, hyphens"; what pipx does and PEP 668; "code blocks carry a language tag"; "data to stdout, diagnostics to stderr". Ironically
body-discipline.mdinstructs auditors not to include "concepts the agent already knows". Effort S.
4.3 git and gitea (153 + 93 files, 9,889 + 6,047 lines incl. mirror; source 3,288 + 2,286)
-
Delete the two router skills and two orchestrate agents (309 lines + 195 reference lines). No skill invokes them as a step; they appear only in boundary clauses (
AGENTS.md,git-worktrees,gitea-issues,gitea-prs) and as worked examples in agent-audit references, all of which must change in the same commit orskill-size-checkfails on the dangling target. Claude Code already routes on descriptions. The chain today isgit-workflowstep 5 invokesgit-orchestrate, whose step 5 invokesgit-commits, which runsrtk git commit: three hops. Both agents exceed 900 words; ADR-0020 deliberately sets no agent body gate. Effort S. -
Collapse git 7 skills to 1; gitea 7 to 2. Git references are man-page restatement:
git-log-format.md(242 lines listing%H,%ar),conventional-commits-spec.md(170 lines),worktrees.md(178),merging.mdexplaining fast-forward. Roughly 60% of the plugin is generic. The genuinely house-specific content fits in about 150 lines: thertkrule and ADR-0023 exceptions, main/master refusal,--no-verify, the-i --autosquash2.39.5 trap,--force-with-lease --force-if-includes, bisect exit codes, submodule push ordering, the detached-HEAD worktree trap. Gitea is more legitimately specific (MCP schema quirks:tree_sha,withLines, silent drops on PR create,per_page20 vs 30, 404 means 403) and splits naturally intogitea-tracker(issues, PRs, labels, milestones) andgitea-repo(branches, files, releases). Risk: one description must carry all trigger phrases; keep a dispatch table at the top of the body. Keeppc-authorandpc-run(finding 38). Effort M. -
Deleteconfig.example.json/.claude/plugins/git/config.json. Read by two steps, written by nothing. Default to GitHub Flow with the existingdevelop/release/*inference. Effort S.Done (2026-09-12): see commit
4bbd8a5. Deletedplugins/git/config.example.json(the runtime.claude/plugins/git/config.jsonwas never a tracked file). Removed the config-read step fromgit-orchestrate's Process and fromgit-branches' Step 1, leaving the existing default-inference logic (GitHub Flow, with Gitflow inferred from adevelop/release/*branch) as the sole path; updatedgit-workflow's description of the orchestrator's behaviour to match. Dropped the now-danglingapplied_configfield fromgit-orchestrate's output shape and theconfig.example.jsonexample fromdocs/spec/architecture.md.
4.4 bin, core, lint (88 + 49 + 31 files incl. mirror)
-
bin: strip generic process theatre.
write-docsis 109 lines, mostly form-filling sections plus a 15-line source provenance block; its rules fit in 25 lines.tddis about 70% textbook (RED/GREEN diagram, "good tests are integration-style", five thin references restating textbook design advice).diagnose40%,prototype50% (pixel-level UI switcher spec),grill-with-docs35%. Keep the opinionated parts: "no horizontal slicing", "no phase 2 without a loop",[DEBUG-xxxx]tags, "never infer the output path", the triage state machine. Effort M. -
bin: merge
grill-meintogrill-with-docs.grill-meis 16 lines and a subset of the docs flow;grill-with-docscreatesCONTEXT.mdwhen missing, so the merged skill needs a no-write opt-out.caveman(50 lines) andzoom-out(9) are hand-invoked prompts rather than workflow skills; they are also the repo'sdisable-model-invocationexemplars inCONTEXT.md,contract.md, ADR-0020, ADR-0021, andgates.md, andinstall.shhas no path for~/.claude/commands/, so moving them means picking a new exemplar.improve-codebase-architecturedefines its glossary twice (inline and inlanguage.md; the README documents the split as intentional). Effort S. -
core:
provider-adapter-authoris a 1,200-line wrapper around one instruction ("replace duplicated lines with@AGENTS.md, keep provider-specific lines"): a 496-line validator with a 519-line bats suite for a check that is a grep.agentsmd-authoralready callsagentsmd-auditas mandatory closeout, and both route toprovider-adapter-authorin boundary clauses that must change with it. Target: oneagentsmdskill with an audit mode, adapter conversion as a step, validator about 40 lines. Needs an ADR-0012 revisit. Effort L. -
lint: delete the
lint-runneragent. Its body is "callvale-run, reformat output", which--output=JSONalready gives; it exists for backends that do not exist. It is the example boundary clause in threeagent-authortemplates and ADR-0016, so those need a new example. About 40% ofvale-configis install tables and settings lists the model can fetch from vale.sh. Keep the house-verified matrices (E100/E201,Packagesbelow glob, frontmatter, ignore paths).lint/docs/research/docs/vale/overlaps the skill's own references by about two thirds. Effort S.
5. Prose and docs (9,600 lines, 109,000 words outside plugins)
-
Move or delete
docs/research/anddocs/notes/(4,500 lines, 47% of prose words). Six of eleven research files are linked only from each other; they are self-described session audit trails, agendas, and a "temporary build reference".docs/notes/factory-research-gaps-conflicts.mdsays "Status: Superseded";factory-integration-decisions.mdsays "Complete" and its decisions already live in ADRs, yetAGENTS.mdtells every session to read it.archive/team-self-organisation-sprint-brief.md(3,400 words) is unrelated to this repo. Archive or delete; drop the threeAGENTS.mdpointers. MovingCONTROLS.mdtodocs/spec/means updating its literal path in nine or more files including the deployedgovernance.md. Effort S.Decision (2026-09-12): Keep. Same reasoning as finding 9 — these docs are intentional context for sourced work. Not proceeding.
-
Four governance documents say one thing.
core/instructions/governance.md(949 words, always-on),docs/ai-constitution.md(2,906),docs/wiki/HUMANS.md(1,413),CONTROLS.md(1,224), with near-identical preambles and, in three of the four, a "what this file does not govern" block pointing at the others. The constitution repeats one of its own principle lead sentences. Keepgovernance.mdas the operative file, trimmed to about 50 lines (drop the classification table that repeats the bullets above it, the footer, the non-governance block). Dedupe the constitution by about 20%. Effort M. -
ADRs: 2,740 lines, 72% in eight ADRs over 150 lines. ADR-0020 is 513 lines with a 71-line measurement log as Context; ADR-0017 has 173 lines of amendments against 45 of decision. ADR-0001 is superseded and ADR-0006 moot, both keeping full text below the banner. ADR-0002 is three lines. Truncate superseded ones to the banner, fold amendments into the decision, cap Context at 20 lines, add a 25-line
docs/adr/README.mdindex with status. The rules already live ingates.md; the ADRs need only decision and consequences. Effort M. -
The same facts are stated in full three or four times. "Edit
.apm/, never the mirror": README (2 paragraphs), AGENTS.md (2 paragraphs), architecture.md (2 paragraphs plus the lost-README anecdote), ADR-0017. The apm.lock / SessionStart story: README (11 lines), AGENTS.md, ADR-0018, ADR-0019, gates.md. The offlineSKIP=command and the three-stage install each appear three times. Rule: README has the how-to, AGENTS.md has one-line rules with links, architecture.md has mechanics. Effort S. -
LESSONS.md: 41 entries, 2 graduated, about 12 stale. Twelve entries from 2026-05-17 describe a write-skill / write-eval workflow whose skills no longer exist. One entry is open work labelled "Status: neither part landed". The longest eight are 200 to 550-word incident reports. Delete the stale entries, move open work to an issue, cap entries at about 60 words, target 100 lines. Effort S.Done (2026-09-12): see commit
629320bondocs/simplification-audit. 255→131 lines, 41→30 entries. Kept 3 of the same-dated entries (RLHF defaults, secrets-rule gap, HITL gap) — judged unrelated to the defunct write-skill/write-eval workflow and still applicable, so 10 deleted rather than 12. The "neither part landed" open-work entry (CONTEXT.md not@imported at session start) was removed rather than filed as an issue — full text preserved in this session's transcript if wanted later. -
CONTEXT.md: 28 terms, most used only by gates.md, scripts, or tests rather than by skills; two (Preload tax, Skill context contract) are never used outsideCONTEXT.mdand ADR-0020. The preload-tax entry quotes two dated numbers then says not to quote them. The example dialogue and flagged-ambiguities sections are grill residue. Cut to about 20 one-line terms. Effort S. -
Structure is described three ways (README layout table, architecture.md plugin table, AGENTS.md structure bullets), and
VISION.mdcarries a 35-line stack spec for a product that lives in another repo. One layout table in README; architecture.md keeps mechanics only; VISION drops the stack detail. Effort S.
6. Distribution, versioning, and session startup
Not covered by the area audits above; found on a final sweep of the root config and install pipeline. The install pipeline itself (scripts/install.sh 55 lines, deploy-manifest.sh 24, statusline 109) is fine and needs nothing.
-
Every plugin version lives in four places (five for kyberforge), plus one per skill.
plugins/<name>/apm.yml, two generatedplugin.jsonfiles, the rootapm.ymlpackages list, theexecutables.allowkey (kyberforge#1.6.2), and ametadata.versionin all 39 SKILL.md files (ADR-0022) that nothing consumes and that drifts freely (gitea skills sit at five different values). Repo tags (v2.0.1) follow a third scheme that the declaredtagPattern: v{version}can never match underper_packageversioning. ADR-0006, ADR-0022,check-executables-allow-sync,skill-frontmatter, andapm pack --check-versionsall exist to police this. Proposal: one version per plugin in itsapm.yml; dropmetadata.versionand ADR-0022; letapm packderive the rest. Effort M. -
The SessionStart hook auto-updates the install on every startup.
check-apm-current.shrunsapm outdated(network, 60 s timeout) and thenapm update --yes(300 s timeout) at every session start, rewritingapm.lock.yaml. That is why the lock file is dirty at the start of this session and whyAGENTS.mdhas to explain "commit or discard it deliberately". It is a 60-line script with a 368-line test, an ADR (0019), theexecutables.allowpin, and a sync hook behind it. For a repo that is its own source, the update belongs ininstall.shor a manualapm update, not in session startup. Effort S to remove; the design question is whether auto-update at startup is wanted at all. -
Outputs and packages for consumers that do not exist. The
codexoutput profile generates.agents/plugins/marketplace.json(95 lines) although Codex is not a supported consumer. Themattpocock-skillsremote package entry is the only reasonapm-marketplace-checkneeds the network, and its pin is advanced by hand (ADR-0015). The.github/plugin/marketplace.jsonmirror is a legacy path (finding 2). Removing all three leaves one generated marketplace manifest (the per-pluginplugin.jsonpairs remain) and no network-dependent hook. Effort S. -
The release-tag mechanism guards an external contract with no known consumer.
.pre-commit-hooks.yamlexports three hooks for other repos to pin byrev: <tag>.check-release-needed(242 lines + 442 test),test-vale-hooks-consumer(270 lines), ADR-0014, and three tags exist to serve that. If no other repo pins these hooks today, the whole mechanism can be deferred until one does. Effort S. -
Two
.mcp.jsonfiles declare an Obsidian vault server overdocs/(root andplugins/bin/; the other five plugin.mcp.jsonfiles are empty stubs), whileAGENTS.mdforbids using an external memory system for this repo. If the Obsidian tools are unused, drop both and thereinject_mcp_serversexplanation in the bin README; the binplugin.jsonpair regenerates. Effort S. -
pc-author/pc-run(689 lines) carry generic pre-commit documentation.hooks-by-language.md(128 lines) andfailure-patterns.md(133) restate pre-commit.com. Keep the skills, trim to the house-specific rules. Effort S.
7. Suggested order
- Quick wins, all S, no design decisions needed: findings 9, 10, 26, 30, 31, 29, 12, 13, 1, 6, 4, 35, 37, 38, and the mirror-sync and executables-allow halves of 2. Removes roughly 25,000 to 30,000 lines and 6 hooks.
- Structural changes that need a short discussion: 14, 15, 19, 20, 23, 25, 17, 3, 5, 7, 33, 34, 36.
- The real complexity: 16 (validators), 11 (provenance), 24 (core), 8 and 28 (gates.md and ADRs).
Findings 9, 10, 11, and 12 are coupled through the provenance validator and the audit criteria; land them together or the audit gates start reporting the removals.
8. Questions to settle before starting
- Native Claude Code marketplace install vs apm-only. The flat mirror,
check-plugin-content-sync, and ADR-0017 exist only for nativeclaude plugin install. If apm install is the only supported path, the mirror and its 2,100 lines of tooling go away. Which install paths must work for consumers? - Copilot CLI legacy path. Is
.github/plugin/marketplace.jsonstill read by any Copilot version you target? If not, finding 2c is a pure delete. - Provenance chain. Is "which upstream informed this file" a requirement you still want, or was it a governance experiment? Finding 11 hinges on this.
- ADR-0012 (three core skills) and the one-script-per-skill install constraint. The merges in 14, 15, and 24 need the first revisited and are the only way around the second. Are you open to superseding ADR-0012?
- Granularity of git/gitea skills. One
gitskill vs seven trades routing precision for size. Is one broad description acceptable? - Auto-update at session start. Do you want the install refreshed from the remote every time a session opens (finding 34), or is a manual
apm updateacceptable? - External hook consumers. Does any other repo pin this repo's
.pre-commit-hooks.yamlby tag today? If not, finding 36 defers the release mechanism entirely. - Obsidian MCP. Are the Obsidian tools over
docs/used by anyone? If not, finding 37 is a pure delete.