From 7ba3d9cf1d585669d2f10022d6e9e2522ffaf44f Mon Sep 17 00:00:00 2001 From: Defame1297 Date: Fri, 14 Aug 2026 11:04:38 +0000 Subject: [PATCH] fix(apm): pin the remote package and restore the agent write fence mattpocock-skills was pinned as the range ^1.2.0 with no lockfile, so apm re-resolved it against upstream on every pack. An upstream v1.2.4 would invalidate the committed ref/sha and fail apm-pack-check-clean with exit 4, blocking every push in the repo at an unrelated moment, triggered by a third party. ADR-0015 claimed the opposite -- that nothing advances it. Pinned to 1.2.3, which resolves to the already-committed sha, so the only compiled change is the version key the remote entry alone was missing. marketplace.owner.email was dropped on a false premise: ADR-0015 said apm has no key for it, but yml_schema.py defines _AUTHOR_OBJECT_KEYS as {name, email, url} and the key compiles through. Restored. (displayName is genuinely unsupported and stays dropped.) ADR-0016 dropped per-agent tools: because the allowlist shape is unportable -- Claude takes a comma list, Copilot a {Tool: true} map. That holds. But a denylist has no such conflict: disallowedTools is honoured by Claude Code and is absent from its plugin-subagent ignore list, and Copilot copies agent frontmatter verbatim so an unknown key is inert. gitea-orchestrate, apm-orchestrate and lint-runner were all write-denied on main and lost that fence silently; only lint-runner's loss was disclosed, and only lint-runner had prose to fall back on. All three regain the fence, and the two with no no-edit language gain three statements each. git-orchestrate is untouched -- it legitimately had edit. Four plugins shipped changed compiled output under unchanged versions, against the policy this PR itself wrote: bin 1.1.1->1.1.2, git 1.3.2->1.3.3, gitea 1.3.3->1.3.4, lint 1.1.5->1.1.6, each in both the plugin manifest and the root packages[] entry. Root catalog 0.3.3->0.3.4: patch, because the set of entries is unchanged and what moved is the owner block and four versions. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT --- apm.yml | 15 ++++++++------- plugins/bin/apm.yml | 2 +- plugins/git/apm.yml | 2 +- .../gitea/.apm/agents/gitea-orchestrate.agent.md | 6 ++++-- plugins/gitea/apm.yml | 2 +- .../.apm/agents/apm-orchestrate.agent.md | 7 +++++-- plugins/lint/.apm/agents/lint-runner.agent.md | 2 ++ plugins/lint/apm.yml | 2 +- 8 files changed, 23 insertions(+), 15 deletions(-) diff --git a/apm.yml b/apm.yml index cae2bfb..4afd41e 100644 --- a/apm.yml +++ b/apm.yml @@ -1,5 +1,5 @@ name: holocron -version: 0.3.3 +version: 0.3.4 description: AI development skills for Claude Code and GitHub Copilot CLI — factory, design, implement, review, and cross-cutting workflows. license: MIT marketplace: @@ -8,9 +8,10 @@ marketplace: # top-level apm.yml description:/version: above are NOT inherited into the # compiled output despite being used elsewhere (e.g. by `apm audit`). description: AI development skills for Claude Code and GitHub Copilot CLI — factory, design, implement, review, and cross-cutting workflows. - version: 0.3.3 + version: 0.3.4 owner: name: Defame1297 + email: defame1297@rkdr.net url: https://git.dev.rkdr.net/Defame1297/ # Default tag pattern used to resolve version ranges for each package. @@ -40,19 +41,19 @@ marketplace: - name: bin description: A place for things to be binned source: ./plugins/bin - version: 1.1.1 + version: 1.1.2 category: Utilities - name: git description: Skills for working with Git — conventional commits, branch management, pull requests, and feature flow. source: ./plugins/git - version: 1.3.2 + version: 1.3.3 category: Version Control - name: gitea description: Skills for managing Gitea repositories — issues, pull requests, milestones, releases, and wikis. source: ./plugins/gitea - version: 1.3.3 + version: 1.3.4 category: Version Control - name: core @@ -64,11 +65,11 @@ marketplace: - name: mattpocock-skills description: Skills for Real Engineers — planning, TDD, architecture, and debugging workflows from Matt Pocock's .claude directory. source: mattpocock/skills - version: "^1.2.0" + version: "1.2.3" category: Productivity - name: lint description: Skills and agents for configuring and running linters. source: ./plugins/lint - version: 1.1.5 + version: 1.1.6 category: Developer Tools diff --git a/plugins/bin/apm.yml b/plugins/bin/apm.yml index 5d869c2..8499010 100644 --- a/plugins/bin/apm.yml +++ b/plugins/bin/apm.yml @@ -1,5 +1,5 @@ name: bin -version: 1.1.1 +version: 1.1.2 description: A place for things to be binned author: name: Defame1297 diff --git a/plugins/git/apm.yml b/plugins/git/apm.yml index 2bc0cd8..7e270fb 100644 --- a/plugins/git/apm.yml +++ b/plugins/git/apm.yml @@ -1,5 +1,5 @@ name: git -version: 1.3.2 +version: 1.3.3 description: Skills for working with Git — conventional commits, branch management, pull requests, and feature flow. author: name: Defame1297 diff --git a/plugins/gitea/.apm/agents/gitea-orchestrate.agent.md b/plugins/gitea/.apm/agents/gitea-orchestrate.agent.md index 05ca1c5..45f93ce 100644 --- a/plugins/gitea/.apm/agents/gitea-orchestrate.agent.md +++ b/plugins/gitea/.apm/agents/gitea-orchestrate.agent.md @@ -9,9 +9,10 @@ source_keys: - context7-websites-gitea - context7-gitea-tea-cli +disallowedTools: Edit, Write, NotebookEdit --- -You are the orchestrator for the gitea plugin — a composable workflow dispatcher designed for other agents to invoke multi-step Gitea operations reliably. Your one job is routing and safety-gating: you do not call `mcp__gitea__*` tools yourself, you delegate to domain skills and enforce confirmation on destructive operations. +You are the orchestrator for the gitea plugin — a composable workflow dispatcher designed for other agents to invoke multi-step Gitea operations reliably. Your one job is routing and safety-gating: you do not call `mcp__gitea__*` tools yourself, you delegate to domain skills and enforce confirmation on destructive operations. You never edit files. Every write you cause reaches its target through a domain skill's Gitea API call — never through an edit you make to the local working tree. You resolve `owner`/`repo` once per session (via `git remote -v` on `origin`) and carry that forward as session context to every domain skill you dispatch to, rather than making each skill re-resolve it. @@ -28,6 +29,7 @@ These are non-negotiable regardless of `confirm` or any skill-local override: - Issues and PRs share one number space. Before dispatching an operation keyed on a bare number, resolve whether it's an issue or a PR yourself (see Number resolution) — never infer the domain from operation phrasing alone. - `list_releases`/`list_tags` default to `per_page: 20` (other domains default to 30) with no server-side auto-pagination — when a caller needs a complete result set, loop `page` upward until a page returns fewer than `per_page` results before returning. - Never commit secrets, credentials, or environment-specific config into any file written via `gitea-files`. +- You are read-only against the local working tree. Never create, edit, or delete a local file — not a manifest, not a config, not a scratch note. Local state is the caller's, and you only read it (e.g. `git remote -v`) to resolve context. ### Number resolution @@ -69,7 +71,7 @@ When invoked, you: 5. If the operation targets a bare number and the domain isn't specified, run Number resolution above before dispatch 6. Invoke the appropriate domain skill via `Skill` with the operation, parameters, and resolved context (`owner`, `repo`) 7. Catch and handle Gitea errors: disambiguate 404s (not-found vs. permission-hidden), retry transient failures, loop pagination for `list_releases`/`list_tags` until exhausted -8. If recovery succeeds, continue; if not, return error structure with diagnostics and suggestions +8. If recovery succeeds, continue; if not, return error structure with diagnostics and suggestions. If the blocker looks trivially fixable by a local edit — a stale `origin` URL, a malformed config, a missing label the repo obviously wants — name that fix in `suggestions` and stop. Do not act on it, and do not route it as a write operation the caller never asked for 9. Aggregate all outputs and return as structured JSON ## Output diff --git a/plugins/gitea/apm.yml b/plugins/gitea/apm.yml index f90441c..4ee17bc 100644 --- a/plugins/gitea/apm.yml +++ b/plugins/gitea/apm.yml @@ -1,5 +1,5 @@ name: gitea -version: 1.3.3 +version: 1.3.4 description: Skills for managing Gitea repositories — issues, pull requests, milestones, releases, and wikis. author: name: Defame1297 diff --git a/plugins/kyberforge/.apm/agents/apm-orchestrate.agent.md b/plugins/kyberforge/.apm/agents/apm-orchestrate.agent.md index ae6d836..3d135ad 100644 --- a/plugins/kyberforge/.apm/agents/apm-orchestrate.agent.md +++ b/plugins/kyberforge/.apm/agents/apm-orchestrate.agent.md @@ -5,9 +5,11 @@ description: Orchestrates apm package/marketplace operations for other agents. I source_keys: - context7-microsoft-apm + +disallowedTools: Edit, Write, NotebookEdit --- -You are the orchestrator for apm package/marketplace operations — a composable workflow dispatcher designed for other agents to invoke multi-step `apm` operations reliably, especially the same operation repeated across several packages in a monorepo-hybrid layout. Your one job is routing and safety-gating: you do not decide manifest content yourself, you delegate to `apm-workflow` and enforce confirmation on irreversible operations. +You are the orchestrator for apm package/marketplace operations — a composable workflow dispatcher designed for other agents to invoke multi-step `apm` operations reliably, especially the same operation repeated across several packages in a monorepo-hybrid layout. Your one job is routing and safety-gating: you do not decide manifest content yourself, you delegate to `apm-workflow` and enforce confirmation on irreversible operations. You never edit files. Every manifest or primitive that changes under your dispatch is written by `apm-workflow` or by `apm` itself — never by an edit you make. You resolve the package root once per dispatched operation (the directory containing that package's `apm.yml`) and carry it forward as session context rather than making every call re-resolve it. @@ -21,6 +23,7 @@ These are non-negotiable regardless of `confirm` or any skill-local override: - `apm.yml`'s `type:` field constrains what `.apm/` may contain — when scaffolding (`init-package`), set `type:` before any primitive content is added; do not defer it. - A clean plain `apm audit` is not a CI-equivalent pass — if the caller's intent is a CI gate, dispatch `audit-ci`, not `audit`. - Check the `apm experimental enable registries` precondition before dispatching any operation that depends on a named registry, and fail with a clear diagnostic rather than silently no-op'ing like apm itself does — see apm-workflow/SKILL.md Gotchas for the underlying constraint. +- You are read-only against the working tree. Never create, edit, or delete a file — not an `apm.yml`, not a `.apm/` primitive, not compiled output, not a scratch note. `edit-config` is an operation you *route* to `apm-workflow`, never one you perform: dispatching it is allowed only when the caller asked for that edit, never as your own repair of something you noticed. When invoked, you: 1. Parse the incoming workflow request (operation type, parameters, target package(s), context overrides) @@ -52,7 +55,7 @@ When invoked, you: 4. Verify `apm --version` succeeds; if not, fail with a diagnostic pointing to `apm-install` 5. Invoke `apm-workflow` via `Skill` with the resolved action, `package_root`, and parameters 6. If fanning across multiple packages, dispatch independent packages in parallel when no shared state or ordering dependency exists between them; loop package-by-package (strictly sequential) only for packages with a real dependency on another package's completion. Either way, collect per-package results and failures rather than aborting on the first failure -7. Catch and handle apm errors: retry once for a dependency-not-yet-scaffolded failure after the caller confirms the dependency exists; otherwise return error structure with diagnostics +7. Catch and handle apm errors: retry once for a dependency-not-yet-scaffolded failure after the caller confirms the dependency exists; otherwise return error structure with diagnostics. If the failure looks trivially fixable by a one-line manifest edit — a missing `category:`, a typo'd `source:`, a version that disagrees between a package and the catalog — name that fix in `suggestions` and stop. Do not apply it yourself and do not self-dispatch an `edit-config` to apply it 8. Aggregate all outputs and return as structured JSON ## Output diff --git a/plugins/lint/.apm/agents/lint-runner.agent.md b/plugins/lint/.apm/agents/lint-runner.agent.md index 3b3ef60..d7ba8ab 100644 --- a/plugins/lint/.apm/agents/lint-runner.agent.md +++ b/plugins/lint/.apm/agents/lint-runner.agent.md @@ -5,6 +5,8 @@ description: Runs a linter sweep over a target file or directory scope and repor source_keys: - context7-websites-vale-sh + +disallowedTools: Edit, Write, NotebookEdit --- You are a linter runner. When invoked, you run the appropriate linter(s) over the requested scope, collect their findings, and report them back in a structured, reviewable form. You never edit files. diff --git a/plugins/lint/apm.yml b/plugins/lint/apm.yml index 6599235..6b66297 100644 --- a/plugins/lint/apm.yml +++ b/plugins/lint/apm.yml @@ -1,5 +1,5 @@ name: lint -version: 1.1.5 +version: 1.1.6 description: Skills and agents for configuring and running linters. author: name: Defame1297