da95fa2a9ed7982049691317a619432e6e1d0d7c
91 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 1a66ee939a |
fix(research): add a serial fallback, patch-bump the version, trim the body under target
The fan-out restored in
|
|||
| f48f3d9926 |
docs(adr): rewrite ADR-0027 to match what the branch does and what is verified
The first draft claimed omitting allowed-tools grants spawning and that the list was a restriction. The repo's own sources describe the field as pre-approval, and the code now keeps the list. Rewrite the ADR to say the #116 defect was step text disclaiming spawning, that per-target behaviour for an unlisted tool is unverified, that the spawn tool is left out because its name is sourced for Claude Code only, and that the orchestrator-writes mitigation is prose, with the unmitigated security cost recorded. Rename to fit the new decision. Refs #116 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGHFJextYtVQseaHPDDhxB |
|||
| 6683da54ac |
fix(research): restore subagent fan-out, record that a skill body and its allowed-tools must agree
research instructed "spawn one subagent per URL" while its allowed-tools granted no spawn tool, so it silently degraded to serial fetches. Three other skills spawn subagents without trouble because they declare no allowed-tools. The defect was the mismatch, not the spawning. ADR-0027 records the agreement rule. research drops allowed-tools and gets its steps 4-5 fan-out and the orchestrator-writes gotcha back (1.0.1 -> 1.1.0). Closes #116 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EGHFJextYtVQseaHPDDhxB |
|||
| fbd030c7ea |
fix(gates): waive lockfile-exists for a package, which is not an install root
plugins/onedev is the first plugin package to declare a real dependency, and that arms a check every previous plugin left vacuous. apm treats any directory holding both apm.yml and apm.lock.yaml as an install root; a package is not one, so there is no green state for it. Without a package lockfile, lockfile-exists fails outright. With one, it passes and thereby arms the other nine checks, where drift then demands the dependency's skills be deployed inside the package and apm lock leaves an apm_modules/ tree behind. scripts/apm-audit-ci.sh replaces the inline bash -c loop and waives that single check for a non-root manifest. It fails closed on three axes: the root is never waived; the failing check must be lockfile-exists and no other, asserted by matching "1 of 1 check(s) failed"; and unrecognised output fails. Dropping --ci for package directories was the smaller change and is wrong. Verified on apm 0.28.0 against a scratch package whose dependency entry carried no git/path/registry field: apm audit --ci exits 1 naming it, while plain apm audit exits 0 and says nothing. Malformed-dependency detection is the reason gates.md gives for auditing packages at all, and a package with dependencies is the only kind that can carry a malformed dependency entry. The waiver matches on apm's stdout, so an apm upgrade rewording either line turns it off. That fails the push rather than hiding a defect. Also records the onedev entry in apm.lock.yaml, which PR #136 could not carry because the plugin was not yet resolvable from the remote's main. ADR: 0026 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NwD8Egs5r4ndqeFLmhusX2 |
|||
| 44bde9e9c9 |
docs(adr): correct the records the branch left describing deleted things
Seven ADRs described code that no longer exists or behaviour the gates do
not have. Where the wrong text came from main it carries a dated
correction; where this branch introduced it, it is fixed in place, because
main never published it and there is no record to preserve.
Fixed in place, branch-introduced:
- ADR-0021's 2026-09-14 correction asserted apm audit --ci "was never a
drift gate at all". It is one: it replays the install and diffs. The
claim contradicted this branch's own AGENTS.md and gates.md.
- ADR-0015 said unconditionally that no pre-push hook needs the network.
The guarantee holds only once apm install has populated apm_modules/.
- ADR-0014's 2026-09-16 correction said restoring .pre-commit-hooks.yaml
would ship a hook that fails for every consumer, because their checkout
has no lib-boundary-resolver.sh. pre-commit clones the whole hook repo
and skill-size-check.sh resolves the library from BASH_SOURCE, so the
hook would work.
- ADR-0019's "twelve hooks pass under unshare -rn" matched neither HEAD
(8) nor main (14), and stated the offline guarantee unconditionally.
Corrected, inherited from main:
- ADR-0022 and ADR-0013 named skill-frontmatter's pre-commit hook as the
enforcer of mandatory metadata.version. That hook was deleted on this
branch; the check lives in skill-size-check.sh.
- ADR-0022 enumerated the tip rule's carve-outs as a closed list and
described a single merge-base. The gate also exempts a tree-identical
skill and intersects every base from merge-base --all, and emits a third
failure form.
|
|||
| c84f1f4145 |
docs: close the self-contradictions left by the branch's own cuts
CONTEXT.md used two terms it no longer defines. This branch deleted the Preload tax and Skill context contract entries as audit finding 31, but the Hand-invoked skill definition and the example dialogue still used both, bolded, which is this file's convention for a defined term. The definitional file contradicted itself while AGENTS.md tells every session to read it as authoritative. Rephrased in place, the way |
|||
| 1614bcef23 |
docs: correct the executables.allow version-pinning claim
gates.md's check-executables-allow-sync section and ADR-0019 both stated
that apm matches executables.allow on an exact `<package>#<version>`
dictionary lookup with no wildcard and no version-less form, and drew the
conclusion that a kyberforge version bump silently stops the entry
matching and the SessionStart hook deploying.
Verified against apm 0.28.0: is_package_approved is an exact lookup, but
install/exec_gate.py calls it across a candidate list carrying the
version-blind name, materialize_exec_map stores each approved key under
its version-blind name as well, and _map_grants matches exact key,
version-blind name, or any stored key sharing that name. Approving
kyberforge#2.0.0 therefore keeps covering kyberforge#2.1.0.
The decision is unchanged: check-executables-allow-sync stays, justified
by this repo's own requirement that the key track plugins/kyberforge/
apm.yml's version:, rather than by an apm-level failure mode. ADR-0019
keeps its original text with a dated correction, since whether apm
behaved this way when it was written was not established.
Follows the same correction applied to root apm.yml's comment in
|
|||
| 82b7bbcf5c |
docs: close the PR #135 documentation review findings
Group 3 of the validated PR #135 review fixes. Every figure and commit citation below was re-verified at HEAD before being written. ADR and architecture: - #7 ADR-0025 cited 61b0b9c, which no published branch reaches. Repointed to |
|||
| e62188c3c3 |
docs(adr): record the author-pair drift decision in ADR-0020
The accepted ADR still called the skill-author/agent-author duplication an open input to #101. The branch decided it: continued drift, no sync gate, on the measured 150-180 line overlap. State that decision so the ADR stops contradicting the PR that closes #101, and mark the old skill-audit citation historical. Refs: #101 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
| 3d245dce5e |
docs: record the review round and move the simplification audit to docs/notes
Correct the hashes left by the branch rewrite (467bbd7 -> |
|||
| 1f3d4f9962 |
docs: correct stale resolver, status and duplication claims
ADR-0014 gains a dated correction: skill-size-check now sources the
boundary resolver from kyberforge (
|
|||
| 3a9d257225 |
fix(apm): commit the hook ownership sidecar so fresh installs stay idempotent
apm recognises its own settings.json hook entries only through the .claude/apm-hooks.json sidecar. With the sidecar gitignored, apm install in a fresh clone keeps the committed SessionStart entry as user-owned and appends a duplicate, so apm audit --ci reports drift and the apm-audit-ci pre-push hook fails. Reproduced on main and this branch with apm 0.28.0. Commit the sidecar in apm's exact serialisation, exclude it from pretty-format-json alongside settings.json, and record the correction in ADR-0019. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
| ef27c9751a |
refactor(gates): source the boundary resolver into skill-size-check
Why: scripts/skill-size-check.sh embedded a byte-identical 1,061-line copy
of the ADR-0020 boundary resolver only because it was also exported
through .pre-commit-hooks.yaml, whose consumers could not reach a file
inside the plugin.
|
|||
| 02d5774a99 |
docs: refute finding 15 on measurement
Why: finding 15 proposed merging skill-author and agent-author on the claim that they share most of contract.md and near-identical steps. Measured, the pair shares about 150-180 distinct non-blank lines, against the 2,934 the factory-audit merge removed. ADR-0020's exclusion of the pair holds, so the merge does not proceed. Implementation Notes: finding 15 is struck through and carries a dated Refuted note with per-file counts and the command that reproduces them. The §7 order and status notes and the §8 ADR-0012 bullet now show no open finding, with 22 deferred with bin. ADR-0020's rejected alternative records the measurement; ADR-0025 point 7 no longer calls the finding open and unmeasured. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
| 14248e04b9 |
docs: fix the review findings on the hook-contract retirement
Why: a review of |
|||
| 4de5b6b355 |
chore(gates): retire the external pre-commit hook contract
Why: .pre-commit-hooks.yaml and its release-tag gate served external consumers that do not exist. No repo on the Gitea instance pins these hooks, and the README names apm as the only supported install path. The mechanism was also already failing: skill-size-check.sh changed after v2.0.1 with no tag cut, and the gate cannot fire through Gitea's merge button. (Simplification audit finding 36.) Implementation Notes: - Delete .pre-commit-hooks.yaml, scripts/check-release-needed.sh, tests/test-check-release-needed.sh and tests/test-vale-hooks-consumer.sh, and remove the check-release-needed pre-push hook. The repo: local skill-size-check and vale-audit-prefilter-* hooks are unchanged. - ADR-0014 is amended, not retired: its runtime decision to bundle Vale inside factory-audit stands. The amendment keeps the entry[0]-only constraint (LESSONS.md:101,105) in case the export returns. ADR-0025 gets a pointer. - test-vale-wrap.sh: drop case 33 (the cross-manifest drift check) and case 28's hook-scope half, which read the published manifest. Case 32 now also requires each hook to select every tracked file of its class, which keeps case 33's one-plugin-narrowing guard, with a mutation test. - test-skill-size-check.sh and test-adr0020-contract.sh now assert the hook contract and verbose: true on .pre-commit-config.yaml only. - gates.md: pre-push count goes from 9 to 8 authored hooks (11 to 10 reported), and the Release table, the External consumers section and the two-manifest scope table are removed. README and script/test comments no longer describe the export as live. The resolver comment is edited identically in both copies. - The v1.0.0/v2.0.0/v2.0.1 tags are left in place; they are inert. ADR: 0014 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
| 807caf22ee |
fix(kyberforge): give branch-aware advice for the refreshed apm lock
Why: the docs said to discard a refreshed apm.lock.yaml on a feature branch because the refresh records main's commit, but the branch's own lock records a (older) main commit too, and the SessionStart notice gave the same "commit or discard" advice on every branch. Implementation Notes: - check-apm-current.sh picks fixed advice by branch: commit or discard deliberately on the default branch (origin/HEAD, else main), discard and reinstall on a feature branch; the branch name is never interpolated. - README, AGENTS.md and ADR-0019 give the real reasons (no lock churn in the branch diff, deployed tree matches the committed lock), the cost (the session runs the older main) and that the next session start refreshes again. - ADR-0019's check-clean and stale-server claims restated to match apm's source. ADR: 0019 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
| 398515bcad |
chore: drop the duplicated package descriptions from root apm.yml
Why: for a local-path marketplace entry, apm treats a root description: as
an override of the package's own apm.yml, reported only at verbose level,
so the "two copies stay identical" rule had no enforcement. Same fix as
|
|||
| 1d40544075 |
fix(gates): hold skill versions above main's tip as well as the merge-base
Why: two branches that both bump a skill 1.0.0 -> 1.0.1 with different content merge without a conflict, and each passed the gate against its own merge-base, so main could ship two changes under one version. Implementation Notes: - check-skill-version-bump requires the pushed version to exceed both the merge-base and the main tip; failures name the baseline they missed. - Presence is read from the tree, so a blob missing from a partial clone is a read failure instead of a silently exempt "new" skill. - A leading UTF-8 BOM no longer reads as a missing version. - Version parts reject leading zeros in all three validators (check-skill-version-bump, skill-size-check, factory-audit). - New tests cover equal bumps, moved files, major/minor ordering, bad refs, unreadable blobs, mode-only changes, symlinks and tag peeling. Impact: ADR-0022 amended (reverses "not main's current tip"); gates.md updated to match, including pre-commit 4.6.1's exact ref selection. ADR: 0022 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
| dd0b9233e6 |
docs: correct the version-bump gate and branch-refresh documentation
ADR-0022 and gates.md now state the merge-base baseline, the fail-closed cases, the PyYAML requirement and the multi-ref push gap (shared with check-release-needed); the new hook gets its own gates.md group. Both ADR additions follow each file's amendment format. README and AGENTS.md now say to discard a refreshed apm.lock.yaml on a feature branch, and that an .apm/ edit is live only once it is on the remote's main. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
| afcf477ede |
docs(adr): record the feature-branch refresh hazard in ADR-0019
The session-start refresh resolves against main, so on a branch it redeploys content the branch removed and rewrites the lock to main's commit. Documented as a consequence rather than skipped in code, since a skip would only freeze the session on an older main. Also records the re-measured refresh time (~24-26 s). Simplification audit finding 34. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
| 8451169d2b |
feat(gates): enforce metadata.version bumps on changed skills at pre-push
check-skill-version-bump fails a push when a skill directory changed against its merge-base with main (tests/ excluded) without a strictly higher metadata.version than main. New, renamed and deleted skills are exempt; every plugin is covered. Recorded as a dated section in ADR-0022 and documented in gates.md. Patch-bumps the 17 skills that changed on this branch without a bump, so the branch passes its own gate. Simplification audit finding 33. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
| 69119f4754 |
docs: reconcile the ADRs, gates and audit log with the shipped behaviour
Why A six-agent review of the two preceding commits found their code sound -- the differential claim holds, the published hook contract is byte-unchanged -- but their prose drifted from it in three ways: statements of fact the code contradicts, markers in a convention this repo does not use, and figures that went stale when the merge changed what they counted. Implementation Notes ADR-0025's edge-path table is rewritten around one stated doctrine: exit 0 is audited and clean, exit 1 is audited with findings or a target present but unreadable, exit 2 is that nothing was audited. Its old row 1 promised "one generic matches-neither message" for three different inputs; there are three distinct messages, and the missing-path case exited 1 until the preceding commit fixed it. Rows are added for the preflight and CDPATH changes, because a table claiming to enumerate every entry-point behaviour change reproduces its own "an earlier revision of this ADR said they were behaviour-neutral" failure if it omits any. ADR-0025 also gains a Consequences supersession record in ADR-0016's form: partially-superseded entries for 0008, 0014, 0020 and 0021, and explicit "is not superseded" entries with reasoning for the rest. Twelve ADRs are amended and it previously listed none. ADR-0008 moves from an amendment note to partially superseded. Its contract genuinely narrowed -- an agent .md outside an agents/ directory was audited before the merge and is refused now -- and ADR-0020 already recorded that the merge "reopens ADR-0008". Its detector description said "a path under .apm/agents/", the phrasing ADR-0025 rejects as wider than the script and circular; the shipped rule is a .md whose immediate parent is named agents/, at any scope. ADR-0020's amendment claimed the boundary resolver is sourced by validate-provenance.sh. It is not, and never was; only validate.sh sources it, once per mode branch. Three Home-column entries pointed at reference filenames the merge renamed, one of which now resolves to two files because its row covers skills and agents. Five ADRs opened with "Skill renamed per ADR-0025", a form this repo does not use, in the same commit that used the conventional "Amended by ADR-0025" twice. They are normalized. "Renamed" was also wrong: the BREAKING-CHANGE trailer says the skills were removed and their flows merged. SIMPLIFICATION-AUDIT.md had 2026-09-15 notes attached to headlines that were never updated, against its own convention of correcting in place with strikethrough. Every figure here was re-derived at HEAD by command, and several differed from the review's own numbers, so the notes record the basis rather than the result alone. LESSONS.md asserted the two review-time suite failures were the SIGPIPE race. The commit that fixed that race explicitly declined to claim it -- the suite was running while agents edited live config files -- so the hedge is restored. Impact No code, test or configuration change; documentation only. Suites stay 20/20 strict with 0 skipped and 374/374 bats. No gate parses ADR or gates.md content, so nothing here is load-bearing for a hook. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD |
|||
| 620f20b0fd |
refactor(kyberforge)!: merge skill-audit and agent-audit into factory-audit
Why The two audit skills carried 1,724 lines of byte-identical duplication: the ADR-0020 boundary resolver (1,061), vale-wrap.sh (526), the Vale style rules (44) and the Contributing-files parser (93). Nothing shared them — they were held in sync by a 413-line pre-push gate and its 797-line test suite. Sync-by-gate had already failed once: at |
|||
| 062ca47a18 |
docs: correct claims left stale by today's apm-only commits
A five-agent review of today's seven commits found no executable
regressions and no dangling references, but a set of documents still
asserting, in present tense, machinery that ADR-0024 and its commits
removed. This corrects them in place, keeping the original text as the
historical record wherever the repo's amendment convention applies.
LESSONS.md: the 2026-06-21 entry prescribed a `claude plugin validate`
sweep that now fails on every plugin, so it is marked superseded with
the surviving gates named. The 2026-08-09 entry gained a recurrence
note: today's manifest deletion broke apm's MCP propagation exactly as
that lesson describes, and its prescribed repo-local grep could not
have caught it, because `plugin_parser.py` ships in the apm toolchain
installed outside this repository.
ADR-0019, ADR-0011 and ADR-0021: amendments extended to passages the
earlier correction passes stepped over -- a dead native-consumer guard,
Consequences bullets still calling for a `plugins/gitea/.mcp.json` that
must not be recreated, and a drift-gate list naming a deleted script.
ADR-0021's list is down to one gate, not two: `apm audit --ci` never
read `description` and was never a drift gate.
architecture.md and enrichments.md: the self-containment constraint is
restated on its live source, the agentskills.io APM package-mode spec,
rather than on Claude Code's plugin cache-install, which ADR-0024
consequence 6 pins as a superseded rationale. releasing.md's pointer to
the deleted sync script is rewritten as history.
tests/run-bats.sh and scripts/lib/batch-run.sh: comment-only. The
`.claude/skills/` exclusion comment claimed a duplication that is not
live yet; apm does not strip `tests/`, and the deployed tree is empty
of them only because the lockfile still resolves the six dependencies
to a pre-ADR-0024 commit carrying the flat mirror. The exclusion is
correct but forward-looking, and now says so.
SIMPLIFICATION-AUDIT.md: reconciled against what the commits actually
did. Two closed findings recorded conclusions that ADR-0024 reversed
hours later; findings 1, 3, 31 and 35 carried prescriptions voided the
same day; finding 28 is now recorded as having moved backwards, with
docs/adr/ measured at +336 lines over the day. The section 1 headline
table is re-measured at
|
|||
| a6434e0cdb |
docs: amend ADR-0021 and close the loose ends ADR-0024 left behind
A six-agent review of today's commits found three documentation defects that the apm-only change left behind. All three are records that describe deleted machinery in the present tense; no code or gate is affected. ADR-0021 was the one ADR that ADR-0024 invalidates without carrying an amendment note -- 0001, 0006, 0011, 0013, 0014, 0015, 0017, 0018 and 0019 all got one. Its Context section still compiles a plugin description into four generated files and its Consequences section still names eight, but |
|||
| c96ca9ca0d |
fix: remove the obsidian MCP server and the unreadable .mcp.json files
|
|||
| 061bb3d5b4 |
docs: correct the apm-only change after a five-agent review
A five-agent review of |
|||
| 718c79af70 |
chore: drop the flat content mirror and native install support (ADR-0024)
apm becomes the only supported install path. The flat mirror at each plugin root existed solely so Claude Code's native `claude plugin install` could convention-scan plugin content (ADR-0017). With no native consumers, it cost ~20,000 tracked lines plus ~2,100 lines of sync tooling and ~88s of every push to guard content apm never reads — and its only automated gate, `claude plugin validate --strict`, passes on a plugin with zero content, so it could not detect the defect ADR-0017 was created to fix. Removes the mirror (213 files), the six per-plugin manifest pairs, sync-plugin-content.sh, its 1,289-line test, the orphaned marketplace-plugins.sh, and the check-plugin-content-sync and validate-plugins pre-push hooks. The root `marketplace:` block and .claude-plugin/ catalogue stay: apm's own marketplace consumers read that same file, so `<name>@holocron` short names keep working. tests/run-bats.sh now excludes .claude/skills/. apm installs from .apm/, which carries the tests/ dirs the mirror stripped, so deployed .bats files would otherwise be discovered and double-run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD |
|||
| af80d27b9b |
docs(adr): flag stale codex-profile mention in ADR-0021 context
The Context section still described .agents/plugins/marketplace.json (apm's codex profile) as an existing, unaffected generated file. It was removed today in 568ca74; point to the removal instead of leaving the text describing a file that no longer exists. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD |
|||
| 568ca749f0 |
chore: remove codex output profile and mattpocock-skills remote entry
Neither has a real consumer: Codex is not a supported target, and mattpocock-skills was the sole remote marketplace.packages[] entry forcing apm-marketplace-check and apm-pack-check-clean to git ls-remote on every push. Removing both drops .agents/plugins/marketplace.json (the codex output artifact) and makes every pre-push hook resolve fully offline. Updates README, AGENTS.md, gates.md, architecture.md, and ADR-0015/ADR-0021 to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD |
|||
| a3e721e937 |
docs: retire the META.md guidance ADR-0022 overruled, bump touched plugins
Why: ADR-0022 made `metadata.version` mandatory in SKILL.md frontmatter, but three documents still instructed the opposite — that `version:`, `source:`, `references:` and `when:` belong in a separate META.md. That recommendation was never implemented: META.md exists exactly once in this repo, inside a vendored third-party research example, and all 39 skills now contradict it. A stale instruction that outranks nothing is worse than no instruction, because an author following it undoes the ADR. Implementation notes: - Two LESSONS.md entries deleted outright — their entire payload was the rejected fix. Two kept and rewritten: the copy-fill entry loses only its META-TEMPLATE clause, and the `model:` entry keeps the provider-extension fact and the invocation-time boundary rule, which stand on their own. - One factual error corrected in passing: the `extracted` slug entry claimed provenance is recorded in META.md. It lives in `references/sources.md` keyed by `source_keys:`, verified against validate-provenance.sh. - Both docs/notes files gain `metadata.version` in their required-field lists. Deleting the stale paragraph while leaving those lists silent would have re-created the gap. - `bin/write-docs` carried `metadata.version: "1.0"` — the only non-semver value in the corpus, and the result of relocating its old top-level `version:` without normalising it. Now `1.0.0`. ADR-0022 records the relocation it previously omitted, which issue #127 had asked it to decide. Impact: patch bumps for the four plugins whose `.apm/` content changed — bin, git, gitea, kyberforge. core and lint are untouched and stay put. Root apm.yml's `executables.allow` key and marketplace package versions move in lockstep; the marketplace release version is unchanged. Refs: #127 ADR: 0022 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EeH8SCbcrCAQrtymkNuhKP |
|||
| ed8c99efbd |
fix(git): stop prefixing rtk where it rewrites the output skills parse
The #113 sweep rested on CLAUDE.md's premise that rtk either filters or passes through unchanged, so prefixing is always safe. Measured against rtk 0.42.4, that premise is false for several of the commands the sweep prefixed, and two skills were left giving wrong answers silently. Why: - `rtk git worktree list --porcelain -z` discards both flags and renders its own format. The `locked`/`lock_reason` fields git-worktrees Step 2 must emit are absent entirely, and paths under $HOME are abbreviated to `~/`. - `rtk git branch --list <name>` prints a phantom `* ` line even when nothing matches, so git-branches' stated ambiguity test — "output from both means the name is ambiguous" — reported every name as ambiguous. `tag --list` is a clean passthrough, so only one half broke. - `rtk git diff --name-only`/`--name-status` append a `Changes:` trailer to output documented as "one per line"; `--word-diff` emits none of the `[-removed-] {+added+}` markers its table describes; `rtk git log -L` truncates each line at ~72 chars, on the one command whose purpose is showing line content. - `rtk git stash pop` prints only `FAILED: git stash pop`, swallowing the conflict diagnostic and retained-entry message the surrounding prose tells the agent to rely on. Implementation notes: - Eleven sites reverted to bare `git`, each carrying its reason inline so the next sweep does not undo it. `mergetool` and `rebase -i` are reverted on clause 3's interactive limb only: the TTY defect does not reproduce — rtk filters exactly twelve subcommands and execs the rest — and ADR-0023 records that measurement rather than a convenient one. - ADR-0023 states the rule repo-wide with a third clause: a command whose output the skill parses, or which is interactive, stays bare. `plugins/git/README.md` is reduced to a pointer; its claim that gitea skills "contain no git/rtk mentions at all" was false, and its citation of `hard-rules.md` pointed at a file containing no occurrence of "rtk". - Eight gitea sites swept, all verified byte-identical passthroughs first. - `scripts/check-rtk-prefix.sh` gates clause 1. Run against main's pre-sweep corpus it reports 99 findings including every gitea site, so it would have caught the drift #113 was filed about. Impact: the gate covers clause 1 only, in shell-tagged fences and the opening span of Run cells. Clause 2 is not gateable — "Run `git switch`" and "`git switch` refuses" are the same tokens — and prose bullets are invisible to it. Both limits are recorded in gates.md rather than left implied. Refs: #113 ADR: 0023 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EeH8SCbcrCAQrtymkNuhKP |
|||
| 60be7b3232 |
refactor(skills): mandate metadata.version on every skill's frontmatter
Only 12 of 39 skills carried metadata.version, and adoption tracked which plugin a skill lived in rather than any stated rule: core, gitea and lint were consistent adopters, bin and kyberforge were consistent non-adopters, git was split with one outlier. There was no documented convention, and skill-author's own bump logic was already written as if presence were conditional. metadata.version is now required on every skill. The 19 skills here that never carried one (bin, kyberforge, gitea-files) are seeded at 1.0.0, not 0.1.0 -- that value stays reserved for a skill's actual creation point under skill-author's existing convention. The skill-frontmatter pre-commit hook now fails a SKILL.md missing the field, the same class of failure as a missing name/description. Full rationale in the new ADR. The git-plugin skills that also need this field follow in the next commit, bundled with issue #113's rtk normalization since both touch the same files. Refs: #127 ADR: 0022 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EeH8SCbcrCAQrtymkNuhKP |
|||
|
|
598a7c326a |
refactor(skills): retrofit the corpus to the ADR-0020 context contract (#129)
Retrofits all 39 skills to ADR-0020's description/body context contract, then fixes what six rounds of independent review found in that retrofit — including four ways the hot gate itself failed open. Closes #99, #107, #108, #110, #111, #114, #115, #120. ## The retrofit (waves 1-5) | | Start | Now | |---|---|---| | Description FAILs (>400 chars) | 26 | **0** | | Body FAILs (>900 words, body-only) | 9 | **0** | | Dangling routing targets | 2 | **0** | | `Kyberforge.CompositionNote` | 10 | **0** | | Preload tax | 21,005 chars | **~10,500** | Under the 12,000-char success criterion. Per-wave detail is on #99. ## The review fixes **The gate failed open four ways, three of them found after the retrofit shipped.** An unrecognised follower token made a dangling target vanish. A skill directory with no `SKILL.md` resolved as a valid target, so a commit could be green locally and red in a fresh clone — three existing fixtures were relying on that, one of which made the install-leak A/B pass vacuously. Then the free-standing `/name` sweep turned out to be gated on the sentence carrying a boundary marker, so route notation in any other sentence was invisible — not an ERROR, not a SUGGESTION, not an INFO — which left the documented "`/name` always blocks" promise false from a second direction. All four fixed and pinned. **Two checks were silently not running.** `validate-provenance.sh` checks 7-8 were dead across nine skills. Waking them exposed a deeper problem: they assume `Research doc:` names a source index, but 30 of 121 entries point at topic content documents, so every new check-7 INFO was a false positive and check 8 was saved from a false-FAIL flood only by an *unannounced* skip. Checks 7/8 are now scoped to source indexes and every skip announces itself (#121). **The retrofit's own anti-goal, four times.** ADR-0020 warns that a blunt gate gets satisfied by deleting content rather than relocating it. `diagnose` and `skill-audit` relocated prose and then read it unconditionally; `prototype` and `vale-config` deleted rules outright that survived nowhere. All four addressed. ## Verification - `bash tests/run-tests.sh --strict` — 24 suites, 0 skipped, 0 failed - `bash tests/run-bats.sh` — 325 tests, 0 failures - `pre-commit run --all-files` — 17/17 - `pre-commit run --hook-stage pre-push --all-files` — 16/16, with `apm marketplace check` and `apm pack --check-clean` run against the remote, not skipped - `scripts/skill-size-check.sh` over all 39 skills — rc 0, 0 ERROR/FAIL, SUGGESTION-only - Preload tax measured at **10,498 chars**, max description 390 — both inside budget - Every new test proven non-vacuous by a deliberate mutation of the behaviour it covers **Per-commit sync, stated accurately:** the ten commits from the latest review round each pass `check-plugin-content-sync` in isolation, verified by checking each out in a detached worktree with a clean between. The earlier gitea window (`dfacf05..bedbd1d`, nine commits) does **not** — its mirror was regenerated in one batch at `bbc7300`. An earlier revision of this description claimed the property held for every commit; it does not, and a bisect through that window lands on a red commit. **Squash-merge** to collapse it, or accept that this range is not bisectable. ## Version bump Six plugins and the catalog take a **patch**, not a minor. The branch is **89 commits — 40 `fix` / 30 `refactor` / 12 `docs` / 5 `chore` / 2 `test` — zero `feat`, zero `!`, zero `BREAKING CHANGE`** — and adds no skill, agent, command or hook. (Two earlier revisions of this section cited a stale histogram, most recently 78 commits; the figures above are measured at HEAD.) Both rules this repo ships (`forge/references/version-bump.md`, landing in this PR, and `git-commits/references/conventional-commits-spec.md`) make that a patch, and the catalog set is unchanged at 7 entries. Not settled by that: four published files were removed from the installed tree, three moved, and `caveman` gained `disable-model-invocation`, retiring its old triggers. Under a strict reading those are major-class and currently ship under `refactor:` with no marker. Whether the deployed skill surface is a public contract is written down nowhere — worth deciding, but it outlives this PR. ## Deliberately not in scope #112 (cherry-pick ownership, now resolved in favour of `git-commits`), #113 (`rtk git` normalisation), #116 (research fan-out), #101 (audit-skill merge), #122 (non-spec skill-root files), #123 (no PRD producer) stay open. #117 is the one worth reading: the contract's remedy is to move prose into `references/`, which is exactly where neither the size gate nor Vale looks — and the blind spot is wider than #117 currently records, since there is no root `.vale.ini` at all, so every ADR, `CONTEXT.md` and `README.md` is unlinted too. That blind spot let this branch carry two `level: error` `Kyberforge.SentenceOpenerThereIs` violations into `references/` files it created — `provider-adapter-author/references/provider-matrix.md:31` and `agent-audit/references/finding-criteria.md:95`. Both are reworded in `afadaae`, confirmed by routing each file through the audit's own `vale-wrap.sh` (1 error each before, 0 after). Five further occurrences sit in `references/` files already on `main`; those are the pre-existing corpus and stay with #117, which is the real fix. Also unfixed and not this PR's: `apm install` appends a duplicate `SessionStart` entry to `.claude/settings.json`, so a fresh clone cannot get pre-push green without an edit AGENTS.md warns against. Reproduces identically on `main`. Co-authored-by: Defame1297 <gitea@rkdr.net> Reviewed-on: https://git.dev.rkdr.net/Defame1297/holocron/pulls/129 Co-authored-by: Claude Code AI - Gitea MCP <claude@noreply.git.dev.rkdr.net> Co-committed-by: Claude Code AI - Gitea MCP <claude@noreply.git.dev.rkdr.net> |
||
| d42f6368fe |
fix(docs): correct claims the first fix round asserted without measuring
Why: two blind verifiers re-ran the five preceding commits and found four defects of the same class this branch exists to close -- a confidently stated measured claim that does not survive re-measurement -- this time inside the fixes themselves. - AGENTS.md:41 still carried both phrasings |
|||
| c7ba3d2ccf |
chore(apm): retire skill enumeration from published descriptions
Why: enumerating a plugin's skills in its published description has now failed three times in four days, the third time inside the correction for the second. |
|||
| 4d336bbf35 |
docs: stop the preloaded instruction set asserting machine state
Why: four defects in the files every session pays for, all introduced or left behind by the trim. AGENTS.md told agents the `<plugin>:` form still resolves "because user-scope native installs were left enabled on purpose", and that a working namespaced call "is not something to fix". That premise is false on this machine: installed_plugins.json is empty, no enabledPlugins key exists in ~/.claude.json, and ~/.apm/marketplaces.json is empty. ADR-0018 already reversed itself once on this exact claim (Correction 2026-08-14) using that same enablement as its evidence, so flipping the assertion again would be the third revision in three. Both files now assert nothing about install state at all, which removes the flip-flop surface instead of re-aiming it. The other three are guard-rails whose instruction survived the trim while the caveat that made it safe did not: - The run-tests.sh line omitted --strict, so it named the one invocation that reports SKIPPED rather than failed when a dependency is missing. gates.md records this gate going green having verified 15 of 17 suites on a vale-less PATH. .pre-commit-config.yaml:70 already uses --strict for that reason. - The .claude/settings.json prohibition lost its ADR-0019 exception, so an agent applying it literally would strip apm's own merged SessionStart entry and create the drift the rule exists to prevent. - LESSONS.md still routed graduated rules to CONTEXT.md's Principles section, which this branch deleted. Implementation notes: the six terms the trim dropped while AGENTS.md still claimed CONTEXT.md glosses everything -- authoring root, content mirror, apm package, output profile, near-miss, vacuous green -- are restored as one-line entries per CONTEXT-FORMAT.md, sourced from architecture.md, gates.md and skill-audit's description-quality.md rather than reworded. ADR-0018 gets a third dated note recording the observation and the fact that the state has now been described two ways, and its stale user-scope inventory is replaced by a pointer to it; the decision it records is untouched. LESSONS.md:3 carried the identical stale claim as :5 and is fixed with it. Impact: preloaded context is now free of assertions about machine state. Refs: #105 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TmFqzpuExLJv3m114XVE9w |
|||
| ba7cec7672 |
docs(adr): amend ADR-0007 and ADR-0015 for the CONTEXT.md trim
Why:
|
|||
| b9c7762463 |
docs: trim CONTEXT.md to a glossary and demote VISION.md
Why: CONTEXT.md is an instructed every-session read at 33,799 bytes (~8,450
tokens), and CONTEXT.md:17 layered docs/VISION.md on top. After the AGENTS.md
trim, that left ~9,650 tokens of instructed reads sitting behind a file whose
own format contract — grill-with-docs/CONTEXT-FORMAT.md:43, "Keep definitions
tight. One sentence max." — it was not following. 22 glossary entries averaged
190 words; the top four were 55% of the file, and one ("Vale audit prefilter")
was 1,444 words of pre-commit forensics filed as a definition.
Implementation notes:
- CONTEXT.md rewritten to CONTEXT-FORMAT.md's prescribed template: ## Language
(five clusters, 22 terms with _Avoid_ aliases), ## Relationships,
## Example dialogue, ## Flagged ambiguities. 33,799 -> 9,762 bytes.
- Vale prefilter forensics moved to docs/spec/gates.md under nine subsections:
the two-copy style layout, vale-wrap.sh and the Vale 3.15.2
text.frontmatter.description limitation, the --config argv defect (E100),
glob scoping, the rule inventory, and 0-files-means-NOT-RUN.
- Instruction-file format and the bidirectional-reference principle moved to
docs/spec/architecture.md, the latter flagged as aspirational: no instruction
file carries a `when:` field, only 2 of 39 skills do, and the reference
scanner script it names does not exist.
- Added a per-plugin scope table to architecture.md so "which plugin owns this
skill" survives the trim, and corrected its claim that the content index
lives in providers/claude-code/CLAUDE.md — that file is now two import lines
and the index sits in core/AGENTS.md.
- "Repo and Gitea are the only source of truth" moved from CONTEXT.md's
Principles into AGENTS.md session rules; it was operative guidance in a
glossary. docs/VISION.md and LESSONS.md added to the on-demand list.
- The apm-consumed install entry (432 words) was deleted outright: all four
consequences are already carried by README.md, ADR-0018, gates.md and
AGENTS.md.
- ADR-0013, ADR-0015 and ADR-0017 each pointed at CONTEXT.md sections that
moved; amended with dated supersession notes rather than left dangling.
Impact: the every-session set drops from ~15,700 to ~4,140 tokens across both
passes (-74%). The deleted "lint plugin" entry was also stale on a safety
claim — it said lint-runner inherits Edit, but ADR-0016 restored
`disallowedTools: Edit, Write, NotebookEdit` and CONTEXT.md was never updated.
Refs: #99
|
|||
| 54d7bd80ba |
docs: rule host built-ins out of the routing target universe
Closes the second open design decision on PR #103. The `/compact` finding was recorded as a false positive needing an allowlist or a suppression mechanism. It is neither: the routing universe is the apm marketplace, so a target either resolves to a skill or an agent or it does not resolve, and `/compact`, `/clear` and `/init` are Claude Code slash commands with no counterpart in Copilot CLI or Codex. `.apm/` source compiles for all three, so a vendor-neutral description routing to one is a portability defect and the hard FAIL is a true positive. An allowlist was rejected for a concrete reason, not a stylistic one: it answers a different question ("does this exist on some host?"), it cannot answer that portably from a single source file, and it goes stale the next time a host ships a command — reintroducing the same-commit-two-verdicts failure ADR-0020 already closed for deployed trees. Nothing is blocked today: zero of the 43 descriptions name a host built-in, and an author who needs to mention one writes it un-slashed, which is not route notation and carries no routing claim. Recorded in ADR-0020 and in both author-facing contract references, so the next agent reads the decision rather than "fixing" the gate. ADR: 0020 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
| 75a13c82f6 |
fix(kyberforge): scope corroboration to a real sentence boundary
A prose-form routing target blocks a commit only when its own sentence names another target that resolves. That makes the sentence splitter part of the ADR-0020 contract rather than an implementation detail, and the naive "period, space, capital" rule got it wrong in both directions: - OVER-SPLIT: `e.g. "..."` is not a sentence end, but the quote looks like a start. The clause was cut in half and the corroborator stranded on the far side, so a genuinely dangling target silently demoted to SUGGESTION — a measurement taken and then discarded, the vacuous-green shape this gate exists to prevent. Seven such splits are live in the current corpus. - UNDER-SPLIT: a sentence opening with a code span or a lowercase skill name was not seen as a start, so two sentences merged and a resolving target vouched for an unresolvable one it never stood beside — a hard FAIL with no escape hatch, which is the exact failure corroboration was added to prevent. The splitter now excludes the five abbreviations that occur in routing prose and admits a backtick or lowercase letter as a sentence opener. Applied byte-identically to all three copies of the shared resolver. Verified zero-delta against the corpus: 37 ERROR / 58 SUGGESTION / 2 dangling before and after, findings byte-identical. The exposure this closes is to the descriptions #99 is about to rewrite, not to the ones already measured — which is why the deferral reason recorded on PR #103 ("can move the documented corpus counts") does not hold and the fix lands here rather than after the retrofit. Three regression tests, one per direction plus the backtick opener, each proven non-vacuous by reverting the splitter alone and watching it go red. Refs: #99 ADR: 0020 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
| 79c9089122 |
docs: make the resolution contract match what the gate actually does
Both AGENTS.md and ADR-0020 said deployed .claude/.agents trees are consulted "only
when no authoring root exists". That stopped being true in
|
|||
| 64ffb9f35a |
docs: make ADR-0020 match what actually shipped, and record what did not
The ADR was written against base commit `f9b919d` and then not updated as the implementation moved, so several of its numbers were measuring one thing and being read as another — the exact conflation the ADR exists to stop, reproduced inside it. Corrections, all reproducible now that each figure states its method: - The preload tax is 23,427 chars / ~5,900 tokens, not 23,612 / ~6,200. - `MAX_WORDS=2770` is a density proxy for the agentskills.io ~5,000-token ceiling, not "2× p90". Neither percentile reaches it: 2× the body-only p90 is 2,698 and 2× the whole-file p90 is 3,052. Reading it as a percentile pairs a whole-file gate against a body-only distribution. - `apm-workflow` is a 421-word body; 554 is its whole-file count. `skill-author` and `agent-author` were 2,623 and 2,582 body words — 2,760 and 2,758 whole-file, which is where "within twelve words of the gate" comes from. Two numbers for one file is the point, and only one of them is what either gate measures. - Every `file:line` citation now says it resolves against `f9b919d`, since this change rewrites most of the cited files. Three things the ADR asserted that no validator implemented are now filed by tier in an exhaustive enforcement table — deterministic, prose-pattern, or auditor judgment — because a rule filed under "Enforcement" that nothing enforces is the failure mode this ADR is most exposed to. The Gotchas entry count moves to SUGGESTION to match the script; the paraphrase FAIL is marked as an auditor's, since semantic equivalence is not pattern-matchable. Two gaps recorded rather than quietly left: - The agent body-gate exemption lives in `agent-audit`'s validator and in the `skill-size-check` hook's `SKILL.md`-only `files:` pattern — *not* in `scripts/skill-size-check.sh`, which measures whatever path it is handed and today reports 900-word body FAILs on `git-orchestrate` (933), `gitea-orchestrate` (1,199) and `apm-orchestrate` (1,080). Agents escape by file pattern, not because the script knows the difference, so widening that pattern would silently enforce a gate this ADR declines to set. - The `skill-audit`/`agent-audit` merge is deferred to #101. This change made the split deeper, not shallower: the dispatch retrofit took them from 3 and 4 reference files to 7 and 8, and their two same-named `description-quality.md` files now differ on 100 of ~120 lines after normalising skill/agent. The merge reopens ADR-0008 and touches every call site in `skill-author`, `agent-author` and `forge`, so it is its own change. #100 carries the dangling-target fixes. AGENTS.md and CONTEXT.md take the same corrections plus the two live setup changes: PyYAML is now a hard requirement rather than an optional accelerator (a fallback that mis-parses an unfamiliar scalar shape reports a clean pass on a file it never measured), and `.claude/settings.json`'s `pretty-format-json` exclusion is documented as load-bearing rather than as a tidy-up candidate. LESSONS.md's autofix entry is corrected on its own provenance, which it got wrong in both directions. `git log --date=iso` puts the introducing commit at 18:47 and the fix at 21:54 — three hours, not "weeks" — and `git branch -a --contains` puts the introducing commit on this branch only, not on main. It was manufactured inside the same PR that diagnosed it. The added lesson is that "pre-existing" is a claim about history and history is queryable: a defect found while working on a branch feels inherited, and the feeling is not evidence. Refs: ADR-0020, #99, #100, #101 |
|||
| 4a5c3c0cff |
feat(kyberforge): enforce the ADR-0020 context contract for skills and agents
Skill name+description pairs are preloaded into every session, costing ~6,200 tokens across 39 skills before any skill is invoked. The authoring rules mandated that growth: skill-author:104 and description-quality.md:21 both required padding, while skill-author:102 (the deflating rule) had no FAIL condition behind it. Gates (blocking, no baseline file): - description 250 chars SUGGESTION / 400 FAIL, measured on the folded YAML value - body-only 600 words SUGGESTION / 900 FAIL, independent of the unchanged whole-file 2770-word / 500-line spec backstop - every boundary-clause routing target must resolve to a real skill or agent; catches skill-improve, neuledge-context and gitea-labels - agents take the description gates but deliberately no body gate; a test pins that absence Vale: DescriptionOpener widened to ^This\b, new CompositionNote rule banning architecture notes from descriptions. 10 hits, 0 false positives. Kyberforge's own four skills retrofitted: descriptions 3,364 -> 938 chars (-72%), bodies 8,306 -> 2,487 words (-70%), all via the apm-workflow dispatch pattern. Fixes the skill-improve dangling route and the agent-author misroute to manual review. Also fixes a pre-existing false positive where any line-initial 'read ' was flagged as interactive input, which had already caused two scripts to be rewritten around it. Refs: ADR-0020 |
|||
| 1c6eababb0 |
docs(adr): set a context contract for skill and agent authoring
Every installed skill's name+description is preloaded every session - 23,612 chars (~6,200 tokens) across 39 skills. The authoring rules optimised for triggering reliability with no counter-pressure on size: skill-author:104 and description-quality.md:21 both mandate padding, while skill-author:102 (the rule that would deflate it) is judgment-only and absent from description-quality.md's FAIL conditions. ADR-0020 sets the description shape (trigger + one capability + boundary), two-tier size gates sitting below the unchanged agentskills.io ceilings, a mandatory dispatch pattern for multi-branch bodies, a Gotchas constraint, an agent-side delegation check, and invocation as a design axis. Gates ship blocking with no baseline. Adds five CONTEXT.md glossary entries: preload tax, skill context contract, dispatch body, hand-invoked skill, delegation discipline. Refs: ADR-0020 |
|||
| c9fe2e8ab2 |
docs: correct the namespace claim and record the hook fixes
AGENTS.md and CONTEXT.md asserted that the `<plugin>:<skill>` form "no longer resolves here". It does: ~/.claude.json still enables core, git, gitea, kyberforge and lint at user scope, which ADR-0018 left in place deliberately. Both names are live at once, so a working `gitea:gitea-prs` is the user-scope copy answering — not evidence that the apm install is broken and not something to "fix". ADR-0018 contradicted itself on this, claiming every namespaced reference went stale while its own "User scope is untouched" consequence said otherwise; recorded as a dated correction alongside the existing one. Bare names stay the documented default. Five stale pre-push hook counts updated for the new check-executables-allow-sync gate: 13 -> 14 repo-defined hooks, 15 -> 16 reported by pre-commit, eleven -> twelve passing offline. The gate reads two local manifests and makes no network call, so the SKIP pair for offline pushes stays exactly two. "Four pre-push hooks shell out to apm" is unchanged and still correct — the new hook parses YAML directly. ADR-0019 gains the timeout arithmetic, the singular/plural failure and why mocking every apm call hid it, and a consequence recording that the trust gate is keyed on version rather than content: an edit to a hook script landing on main deploys and executes unattended on the next session start, since the dependency is unpinned and the hook runs `apm update --yes`. That is accepted, not overlooked, but it is why the gate should not be read as a supply-chain control. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT |
|||
| 3bfdf58960 |
chore(release): kyberforge 1.5.0, marketplace 0.4.0
Why
---
The SessionStart freshness hook is a new kyberforge feature and was committed
without a version bump. It also cannot ship unbumped: apm's executable-trust
allow key is version-pinned, so `kyberforge#1.4.1` would have stopped matching
the moment the package version moved, silently blocking the very hook the entry
exists to authorise.
Implementation notes
-----------------
kyberforge 1.4.1 -> 1.5.0 (MINOR, new feature); marketplace and root manifest
0.3.4 -> 0.4.0, following the convention in
|
|||
| dee56c506a |
feat(kyberforge): refresh the apm install at SessionStart, not at push
Why --- ADR-0018 left deployed skills tracking the remote default branch with nothing watching for drift. The mechanism that was supposed to cover this, scripts/git-hooks/post-push, could never have worked: git has no client-side post-push hook. install.sh copied it into .git/hooks/ so it looked installed, and it had never once fired. Issue #78 reported it as skipping the gitea plugin; it was skipping everything. Refreshing on push was also the wrong shape. Your install goes stale when someone else merges, so a push of your own is neither necessary nor sufficient for staleness to have occurred. Implementation notes -------------------- kyberforge ships a SessionStart hook (startup matcher only) that runs `apm outdated`, and when anything is behind runs `apm update --yes` and returns reloadSkills:true so the running session picks up redeployed content. It exits silently with no apm.lock.yaml present, which keeps it inert for hosts that installed this plugin natively rather than through apm. Two findings drove the wiring, both verified rather than assumed: - apm resolves ${CLAUDE_PLUGIN_ROOT} against the installed package root, and `apm pack` keeps only *.json from .apm/hooks/. A .../hooks/<script> reference therefore points into the generated mirror where the script does not exist — apm reports "Hook script not found" and deploys a hook aimed at nothing. The reference must be .apm/-relative, and a test pins it. - apm's executable-trust gate is OFF unless apm.yml carries an `executables:` block; until now every hook, bin and MCP primitive a dependency shipped would have deployed unprompted. Root apm.yml now enables it. The allow key is version-pinned by apm's design, so a kyberforge version bump silently blocks the hook until the key is bumped too — called out in the block and the ADR. Also corrects ADR-0018 and AGENTS.md, which named `apm install` as the refresh command. It is not: `apm install` deploys from apm.lock.yaml's pinned commit and does not re-resolve refs. `apm update` does. Impact ------ Session startup costs ~0.7s when current and ~10.4s when six packages are behind. Auto-refresh rewrites apm.lock.yaml, so an unexplained modification to it after opening a session is expected; the emitted notice says so. .claude/settings.json stops being exactly {"hooks": {}} once the hook lands there — the merged entry is apm's own output, and the rule that nothing repo-authored goes in that file is unchanged. .claude/hooks/ and the .claude/apm-hooks.json sidecar are gitignored install output. The hook cannot install itself: dependencies resolve from the remote, so it takes effect only after this merges and `apm update` runs once against the new default branch. scripts/git-hooks/ is now empty. install.sh's copy block is kept and test-git-hooks-install.sh synthesizes its own fixture, so the mechanism stays tested without requiring a dead hook to exist. ADR: 0019 Refs: #78 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT |
|||
| 2e8732a8e5 |
build(apm): consume holocron plugins through apm instead of plugin install
Why:
The repo published apm packages but consumed them the old way — `claude plugin install
<name>@holocron`, six plugins enabled per project. Dogfooding stopped one layer short of the
install tooling kyberforge itself ships.
Implementation notes:
- Root apm.yml declares the six packages as dependencies.apm git+path objects against the
holocron remote. Object form over `<name>@holocron` aliases on purpose: an alias first needs
`apm marketplace add`, which writes to ~/.apm/marketplaces.json — user scope, absent on a fresh
clone. Unpinned against the default branch, matching the autoUpdate the native install had.
- apm.lock.yaml is committed; .claude/skills/, .claude/agents/ and apm_modules/ are gitignored
regenerable install output. Committing the deployed skills would add a third mirror of content
ADR-0017 already governs two copies of.
- .mcp.json is generated by apm from plugins/bin/.mcp.json, so the obsidian MCP server survives
the switch.
- .claude/settings.json is reduced to {"hooks": {}}. apm replays the install into a scratch tree
and diffs, so any repo-owned key there is permanent drift that fails apm-audit-ci. Nothing was
lost: enabledPlugins was empty after the uninstall and the only hooks entry was PreToolUse: [].
- tests/run-bats.sh and tests/run-tests.sh exclude apm_modules/. It holds a full copy of every
plugin, and a copied .bats file resolves its helpers against the dependency root rather than
this repo — 334 tests, 167 failures before the exclusion.
Impact:
Skills are now unnamespaced — `git-commits`, not `git:git-commits` — because apm deploys plain
project skills with no plugin to prefix. AGENTS.md, CONTEXT.md and docs/spec/architecture.md are
updated accordingly. Root apm.yml now declares dependencies, which arms apm-audit-ci's
lockfile-exists check for the root manifest. External consumers are unaffected: the marketplace
manifests are untouched and `apm pack --check-clean` stays clean. Project scope only.
ADR: 0018
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT
|