f4bb1cf4e5532f6b0b515b37a2ca69c99078a9bf
10 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| f4bb1cf4e5 |
docs: finish reconciling the agent write fence across the toolchain
The previous round taught agent-audit's validator to permit disallowedTools but left the skill that writes agents still forbidding it, in six places. Running agent-author on any of the three fenced orchestrators would have stripped the fence, and nothing would have caught it: the validator's allowlist is a permit list, so an absent field passes. The template was the worst of them, since its comment is copied verbatim into every new plugin-scope agent. Where a list had to be restated it is now a pointer to field-inventory.md's apm-agent-allowlist instead -- the same data validate.sh reads -- because a roster copied into a template goes stale one step further out than the roster itself. Where the text has to teach something it teaches the shape rule rather than the exception: tools is an allowlist whose vocabulary differs per harness, so verbatim copy makes one value wrong on one target; disallowedTools is a denylist, where an unrecognised name denies nothing, so the worst case is a missing fence rather than a wrongly granted capability. ADR-0016's amendment claimed an unrecognised key is inert on Copilot while the same ADR's Context says that behaviour is unconfirmed by research -- asserting as settled the exact thing it flags as unknown, and justifying it with apm's compile-time behaviour, which says nothing about Copilot's runtime. It is rewritten into labelled tiers: confirmed for Claude Code with citations, inferred by analogy for Copilot with the analogy's limits stated, unverified where it is unverified, and the residual risk accepted explicitly with its blast radius. It also no longer claims to restore a write sandbox: the denylist does not deny Bash, which these agents inherit and legitimately need. docs/hooks.md called the old root hooks.json a stale sync artifact -- it was added in the plugin's creating commit and pointed at by main's Copilot manifest -- and claimed both ecosystems now resolve hooks/hooks.json. Copilot does not: its hooks field has no default and no compiled manifest declares one, so it resolves nothing. Recorded as the gap it is, with re-injection noted as a follow-up rather than asserted away. Its event list is marked partial. Also: new-agent.bats asserted a hardcoded four-field allowlist and would have rejected a scaffolded agent carrying the field the ADR now blesses; it reads field-inventory.md too. And ADR-0016's premise that Claude's tools: is space-separated was wrong -- it takes a comma-separated string or a YAML list. The incompatibility with Copilot is the vocabulary, not the punctuation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT |
|||
| 430f46b8e8 |
docs: correct the claims this review found false
AGENTS.md told an offline agent to push with SKIP=apm-marketplace-check and asserted that hook was "the only one whose failure mode is 'no network'". Running all 12 pre-push hooks under a network namespace shows two fail, for one shared cause: apm-pack-check-clean resolves the same remote entry. An exact pin does not remove the ls-remote, so both hooks are named now. AGENTS.md also said everything in a plugin root except .apm/ is generated. Plugin roots carry hand-authored README.md, docs/, bin/, sources.md and .mcp.json, so an agent would hunt for an .apm/ source that does not exist or refuse the edit. The rule is positional: immunity belongs to the plugin root, and anything inside a mirrored directory is still rm -rf'd. ADR-0017 said apm strips a hooks field. The real loop is (agents, skills, commands, instructions) -- hooks absent, instructions never mentioned -- and it can never fire, because synthesize_plugin_json_from_apm_yml only emits the eight identity fields. The decision stands; the mechanism was overstated. Its mcpServers amendment is rewritten for the pointer payload and now records the real reason: inlining bypassed apm's credential sanitizer. ADR-0015's owner.email and version-pin passages are corrected against the apm source, and ADR-0016 gains the disallowedTools amendment. agent-audit's allowlist is data, so it gains disallowedTools too -- the ADR and the validator that enforces it had come apart. architecture.md described a root CLAUDE.md that imports two files (it imports one, plus an RTK block) and pointed at an ADR index that does not exist. Seven skill READMEs listed tests/ files the mirror strips, promising installed users files their install lacks; those rows are marked source-only, with the depth-4 template tests explicitly called out as surviving. And plugins/kyberforge/hooks/README.md, deleted during the conversion and preserved nowhere, is restored to a path the mirror does not own -- verified by running a sync against a scratch copy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT |
|||
| 013b913bd4 |
docs: correct claims the apm conversion left false
Documentation asserted things the code no longer did, which is how several of this round's defects survived three review passes. - `docs/spec/architecture.md` still described the pre-APM model — "each plugin has a `plugin.json` manifest" — when no such file exists. AGENTS.md routes agents here for the current structure, so it was live drift, not archive. Also cited ADR-0012 where ADR-0003 is meant. - AGENTS.md never said `.apm/` is the sole hand-edited source, while the generated mirror is byte-identical with no marker — an agent reading only AGENTS.md would edit the mirror and find out at pre-push. It also omitted that `apm` and `jq` are now required to push, unlike the `vale` bullet that exists for exactly that reason, and understated the pre-push gate. `apm marketplace check` hard-fails offline and `--offline` does not help, so the `SKIP=` escape hatch is documented rather than new machinery built. - ADR-0017 carried hardcoded line numbers that drifted twice within one PR, and said `mcpServers` reinjection was real-syncs-only where the script's own header says both modes. Line numbers dropped rather than corrected. - ADR-0015 asserted issue #90 was closed. It is open. Reworded to defer to the issue's own state rather than depend on someone remembering to close it. - ADR-0014 said both audit skills pass `--config`; both SKILL.md files say pass none, and passing one fails with E100. The ADR was wrong. - ADR-0007 cross-referenced an archived ADR-0011 whose number was later reused. Disambiguated with a note — renumbering a published ADR rewrites an immutable record and breaks every existing citation. - CONTEXT.md claimed `lint-runner` is report-only via a missing `Edit` tool. Plugin-scope APM agents cannot express `tools:` (ADR-0016), so it is report-only by instruction now; ADR-0016 accepted that regression but CONTEXT.md was not updated. - Recorded two undocumented consequences of the conversion: `displayName` dropped from all six compiled manifests and `owner.email` from the marketplace, and `mattpocock-skills` silently version-pinned and manually maintained. - Wrote the version-bump policy issue #90 specified but never delivered. Its previous carrier, `marketplace-author`, was deleted in this PR, leaving the per-package rule documented nowhere. - README fixes: kyberforge listed skills belonging to the `git` plugin and a deleted hooks path, `bin` advertised an agents directory it never had, and the docs index listed files that do not exist. Refs: #90 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT |
|||
| 38f1ba4e03 |
fix(kyberforge): bridge apm content to Claude Code's flat plugin discovery
Claude Code's (and Copilot's) native plugin installer has zero awareness of .apm/ nesting -- it convention-scans only flat skills/, agents/, commands/, hooks.json at each plugin's root. Confirmed via strings on the installed claude binary and live installs of git@holocron/gitea@holocron/kyberforge@ holocron, all reporting Skills(0) Agents(0) Hooks(0) post ADR-0015's apm conversion. Root cause (apm_cli/core/plugin_manifest.py): apm's plugin.json compiler deliberately strips skills/agents/commands keys, assuming the host already auto-discovers those convention directories -- it has no model of .apm/ being host-visible at all. Separately, apm's own bundle exporter (apm_cli/bundle/plugin_exporter.py, behind `apm pack --format plugin`) implements the correct .apm/ -> flat mapping, but only ever targeted build/<name>-<version>/, a path nothing in marketplace.json's source: points at. scripts/sync-plugin-content.sh wraps that bundle exporter and copies its agents/, skills/, commands/, instructions/, extensions/, and merged hooks.json back into each plugin's own root as a second tracked compiled-output category -- same governance status as .claude-plugin/plugin.json: generated from .apm/, never hand-edited. tests/ subdirectories are excluded from the mirror (dev fixtures, not host-visible runtime content; several hardcode a relative repo-root walk-up sized for the .apm/-nested depth, which breaks when duplicated one level shallower). Applied for real across all 6 plugins and verified two ways: `claude plugin validate --strict` passes on every real plugin directory, and a live `claude --plugin-dir <path> -p "list skills/agents"` behavioral test confirms content is now actually discovered. Also, from the same issue #90 review round: - scripts/check-manifests.sh pointed at each plugin's root-level plugin.json (checking skills/hooks/mcpServers/agents pointer fields) -- that file was a stale near-duplicate of .claude-plugin/plugin.json nothing else read or wrote, now deleted across all 6 plugins. check-manifests.sh is rewritten to validate .claude-plugin/plugin.json instead, and drops the pointer-field checks entirely (nothing to check -- those fields are correctly absent by design). Content-presence drift is now check-plugin-content-sync's job, a new pre-push hook wired in .pre-commit-config.yaml. docs/adr/0017 records the root cause and decision in full, including two rejected alternatives (patching plugin.json's path fields directly -- apm's compiler strips them on every run; pointing marketplace.json at apm pack's build/ output -- a version-suffixed non-source directory nothing can install from without an extra build step). ADR-0015 and CONTEXT.md are updated to point at it. Refs: #90 |
|||
| 7910b8b12c |
docs(kyberforge): fix path drift and content gaps from apm conversion
The apm conversion (
|
|||
| 5e232503c4 |
feat(kyberforge): execute plugin-to-apm marketplace conversion
Why: ADR-0015 established that Microsoft APM (apm.yml + .apm/) should replace this repo's hand-authored plugin.json/marketplace.json model, with those files becoming compiled output of `apm pack` instead of files edited by hand via the (now-retired) plugin-author/marketplace-author skills. Issue #90 was the deferred execution of that decision, gated on #88 (apm tooling) and #89 (apm-native agent-author/skill-author routing). Implementation notes: - All six plugins (bin, core, git, gitea, kyberforge, lint) now carry apm.yml + .apm/{skills,agents,hooks} as their authoring source. Skills moved with a plain git mv (content-identical across targets). Agents were re-authored, not moved: per ADR-0016, .apm/agents/*.agent.md compiles verbatim to both Claude and Copilot, so plugin-scope agents now carry only name/description/model/source_keys -- no tools: field, no Claude-only knobs (isolation, maxTurns, effort, memory, permissionMode). - Root apm.yml registers all 7 marketplace packages (6 local plus mattpocock-skills as a remote entry) under versioning: per_package, matching this repo's existing independent-plugin-versioning practice. - .claude-plugin/marketplace.json and every plugin's plugin.json are now apm-pack-compiled output, verified against the prior hand-maintained content: same names/descriptions/versions/licenses/authors, only cosmetic serialization differences (JSON key order, owner email vs. url, Unicode escaping). - plugin-author and marketplace-author are retired now that apm-based authoring fully replaces their job; kyberforge bumped 1.3.1 -> 1.4.0 for that removal, and the root marketplace catalog bumped 0.3.1 -> 0.3.2 to match, per the version-bump convention now documented in apm-workflow's reference docs instead of a dedicated script (apm has no native version-bump automation). - Fixed hardcoded pre-.apm/ path assumptions across .pre-commit-config.yaml, .pre-commit-hooks.yaml, scripts/check-scope-walkup-sync.sh, scripts/sync-vale-styles.sh, scripts/check-vale-style-sync.sh, six plugins' root plugin.json (stale skills/hooks/agents pointer fields that check-manifests.sh validates), and several tests/*.bats and tests/*.sh fixtures -- including a bats REPO_ROOT relative-path depth bug (10 files, one extra .apm/ directory level to walk up) and a vale probe-path isolation regression introduced mid-fix. - Corrected empirically-wrong assumptions surfaced this session in apm-workflow/apm-install's own reference docs: `apm marketplace package add` does not accept local paths (only owner/repo remote shorthand -- local packages are registered by editing apm.yml's marketplace.packages[] directly); `apm compile` is a consumer-side AGENTS.md/CLAUDE.md generator, not the plugin.json producer, and hard-fails on skill/agent-only packages without --clean; `apm plugin init <name>` nests a stray subdirectory when run with a positional name arg from inside a same-named directory; no native Copilot marketplace output profile exists; .mcp.json is merged into the compiled plugin.json content-aware and target-scoped, with no dependencies.mcp entry needed for simple passthrough; pipx is the correct pip fallback on externally-managed Python environments. - Renamed agent-author's copilot.agent.md template asset to copilot.agent.md.template so apm compile's recursive *.agent.md glob stops misparsing the placeholder template as a real agent primitive. Impact: plugin.json and marketplace.json are compiled artifacts from here on -- editing them by hand is no longer the workflow; edit apm.yml/.apm/ and run apm pack. CONTEXT.md's Plugin/Plugin marketplace glossary entries reflect this. ADR-0001 is marked superseded, ADR-0006 moot, and ADR-0010 updated for the new .apm/agents/ path (project/user scope unaffected, per ADR-0016). Full local verification: claude plugin validate --strict on all 6 plugins, apm audit --ci, apm marketplace check, check-manifests.sh, and the full test suite (165/165 bats, 13/13 shell scripts) all pass clean. Fixes: #90 Refs: #88, #89 ADR: 0015 ADR: 0016 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ub96PyaSRD9BHPktotj1pC |
|||
| 92e7ff26aa |
docs(kyberforge): narrow issue #89 scope, migrate CC platform facts to apm-workflow
A grill-me session determined plugin-author/marketplace-author are fully superseded by the landed apm-install/apm-workflow/apm-orchestrate artifacts and will be deleted (not adapted) under issue #90, narrowing issue #89 to skill-author/agent-author only; forge stays untouched. ADR-0015 is amended to record this correction plus a three-way content-migration audit. Claude Code platform-constraint facts that lived only in plugin-author/marketplace-author (reserved name prefixes, the ADR-0010 agents/ stray-.md validator gotcha, claude plugin validate as a terminal check, and a removal/re-pack confirm-before-proceeding note) remain true post-conversion and are migrated into apm-workflow's reference docs via kyberforge:skill-author, which also updated the skill's README and sources.md provenance records. Dual-manifest-specific conventions (ADR-0006 parity, CC/Copilot field-placement split) do not carry forward since they no longer apply. ADR: 0015 |
|||
| 394052ff66 |
docs(kyberforge): fix remaining PR #91 review findings, add apm install routing
Re-review (comment 24) of fix commit
|
|||
| e16c3dc95f |
docs(kyberforge): fix PR #91 review findings in ADR-0015 and apm docs
ADR-0015's Decision bullet stated ADR-0001 was superseded as present fact while Consequences framed it as conditional on issue #90 — reworded Decision to match, and added a Supersedes header (repo convention per ADR-0007/ADR-0010) so the pending change is visible from the title. Also fixed a forward-note that misattributed the pre-existing .agent.md convention (ADR-0005/0010) to the APM move, and reworded the rejected-plugins/apm/ rationale to acknowledge the shipped skills are actually generic rather than repo-specific. CONTEXT.md's Plugin/Plugin-marketplace glossary entries got a forward-pointer to ADR-0015 so a session-start read surfaces the pending manifest-authoring change. apm-orchestrate.md/.agent.md: removed a Hard Rule requiring ${VAR} secret indirection that can never fire (the orchestrator has no Edit/Write tool and never touches apm.yml — apm-workflow's SKILL.md already owns this rule where content is actually written); removed compile-manifest-check, an operation with no backing apm CLI command anywhere in the research docs; added explicit CLI mappings for add-package/add-marketplace so an executing agent can't invert them. marketplace.md's release steps shelled out to raw git add/commit/ tag/push — replaced with a pointer to the git-commits/git-remotes skills per AGENTS.md's "prefer plugin skills over raw shell" rule. compile.md now states audit runs after compile/pack (audit scans deployed output, not the source apm.yml) — answers a reviewer question that had no documented answer. Refs: #91 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186ERbyACLRuRxPRnqwpa4m |
|||
| 0e421acdbb |
docs(adr): add ADR-0015 for outright APM conversion
Records the grill-with-docs decision on issue #88: replace the hand-authored plugin/marketplace manifest model with Microsoft APM (apm.yml + .apm/) as this repo's authoring source of truth. The plugins/<name>/ monorepo-hybrid layout survives; marketplace.json and provider plugin.json files become compiled output. Supersedes ADR-0001; touches but does not resolve ADR-0006/0010/0014. Follow-up work tracked in issues #89 and #90. |