Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions .github/workflows/update-agent-skills.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ on:
options:
- all
- agentic-engineering
- engineering-practices
schedule:
- cron: "0 6 * * *"

permissions:
contents: write
pull-requests: write
permissions: {}

# All scopes can update the same per-skill branches. Keep their digest/version
# follow-ups inside the same non-cancelling queue as the updater itself.
concurrency:
group: agent-plugins-skill-sync-${{ github.repository }}
cancel-in-progress: false
queue: max

jobs:
scope:
Expand All @@ -40,6 +46,9 @@ jobs:

update:
needs: scope
permissions:
contents: write # The shared updater writes the signed skill-sync commits.
pull-requests: write # The shared updater opens per-skill update proposals.
uses: devantler-tech/.github/.github/workflows/update-agent-skills.yaml@e271b7ff25d4ce97b067612e7ba0c5d657b6a17a # v6.1.0
with:
dir: ${{ needs.scope.outputs.dir }}
Expand Down
12 changes: 8 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ which records the true upstream in the skill's `metadata.github-*` frontmatter (
`anthropics/skills`, our own sibling [`devantler-tech/agent-skills`](https://github.com/devantler-tech/agent-skills),
…), each tracked independently. The daily
[`update-agent-skills.yaml`](.github/workflows/update-agent-skills.yaml) workflow runs
[`gh skill update --all`](https://github.com/devantler-tech/actions/tree/main/update-agent-skills) via
the [`update-agent-skills`](https://github.com/devantler-tech/actions/blob/main/.github/workflows/update-agent-skills.yaml)
[`gh skill update --all`](https://github.com/devantler-tech/.github/tree/main/actions/update-agent-skills) via
the [`update-agent-skills`](https://github.com/devantler-tech/.github/blob/main/.github/workflows/update-agent-skills.yaml)
reusable workflow and opens one PR per drifted skill, from `deps/agent-skills-update-<slug>`, so a
blocked update holds back only its own skill — **no lockfile, no sync bot, no custom metadata.** Never hand-edit anything inside a bundled skill — not the `SKILL.md`, and not the
`references/`, `scripts/` and `assets/` files beside it, which are equally the upstream's and equally
Expand All @@ -143,9 +143,13 @@ distributed notice. A changed notice or incomplete read refuses validation; refr
a reviewed curation change rather than replacing the notice silently. Run
`bash scripts/check-matt-skill-license.test.sh` for its offline source and notice regressions.
For a portfolio-owned repair, dispatch `update-agent-skills.yaml` with
`scope=agentic-engineering` to update only that plugin's skills through the same programmed
PRs. The default `all` scope and scheduled updates cover the full catalogue. Unsupported
`scope=agentic-engineering` or `scope=engineering-practices` to update only the selected plugin's
skills through the same programmed, per-skill PRs. Each scope retains the canonical branch
identity and existing one-skill edit boundary. The default `all` scope and scheduled updates
cover the full catalogue. Unsupported
scope observations refuse before the updater starts.
All scopes share one non-cancelling workflow queue, including their digest, version and release-note
follow-ups, so overlapping selections cannot rewrite the same update branch concurrently.
`guard-bundled-skill-edits.sh` covers the rest of the tree: a PR that changes any file inside a
synced skill fails and names the upstream to fix it in, so the edit is refused at review instead of
being silently reverted by the next sync. The programmed sync PR is exempt for its own skill, a wholly new skill
Expand Down
1 change: 1 addition & 0 deletions docs/scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ complete inventory; read a script's header for its arguments and safeguards.
| Check a change | Follow the [validation steps](validation.md), including dependency installation |
| Update versions and release notes | Use [bump-plugin-version.sh](../scripts/bump-plugin-version.sh) and add a matching changelog entry; skill syncs use [plugin-changelog.sh write](../scripts/plugin-changelog.sh) |
| Refresh generated resource digests | [refresh-desired-state-digests.sh](../scripts/refresh-desired-state-digests.sh) |
| Synchronize one curated plugin | Dispatch [Update Agent Skills](../.github/workflows/update-agent-skills.yaml) with `agentic-engineering` or `engineering-practices`; [skill-update-scope.sh](../scripts/skill-update-scope.sh) resolves only declared selections before the normal per-skill updater runs. Default and scheduled `all` updates still cover the full catalogue. |
| Prepare or inspect a marketplace release | [Release guide](marketplace-releases.md) and [prepare-marketplace-release.sh](../scripts/prepare-marketplace-release.sh) |
| Propose or publish a marketplace release | [Release guide](marketplace-releases.md), which explains the separate opt-in steps and recovery |
| Recheck open pull requests after changing CI | [recheck-open-prs.sh](../scripts/recheck-open-prs.sh) |
Expand Down
1 change: 1 addition & 0 deletions scripts/skill-update-scope.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ refuse() { printf 'skill update scope: unsupported dispatch\n' >&2; exit 2; }
case "$1:${2:-all}" in
schedule:all|workflow_dispatch:all) printf 'dir=plugins\nbranch=deps/agent-skills-update\n' ;;
workflow_dispatch:agentic-engineering) printf 'dir=plugins/agentic-engineering/skills\nbranch=deps/agent-skills-update-agentic-engineering-skills\n' ;;
workflow_dispatch:engineering-practices) printf 'dir=plugins/engineering-practices/skills\nbranch=deps/agent-skills-update-engineering-practices-skills\n' ;;
*) refuse ;;
esac
31 changes: 27 additions & 4 deletions scripts/skill-update-scope.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,38 @@ bash "$here/skill-update-scope.sh" workflow_dispatch all > "$work/out"
[[ $(cat "$work/out") == $'dir=plugins\nbranch=deps/agent-skills-update' ]]
bash "$here/skill-update-scope.sh" workflow_dispatch agentic-engineering > "$work/out"
[[ $(cat "$work/out") == $'dir=plugins/agentic-engineering/skills\nbranch=deps/agent-skills-update-agentic-engineering-skills' ]]
for scope in unknown ../outside $'agentic-engineering\ndir=plugins'; do
bash "$here/skill-update-scope.sh" workflow_dispatch engineering-practices > "$work/out"
[[ $(cat "$work/out") == $'dir=plugins/engineering-practices/skills\nbranch=deps/agent-skills-update-engineering-practices-skills' ]]
# A scoped producer must still create the canonical per-skill branch accepted
# by the existing actor-and-one-skill guard, not a broader exemption.
branch=$(sed -n 's/^branch=//p' "$work/out")
[[ "$branch-ways-of-working" == deps/agent-skills-update-engineering-practices-skills-ways-of-working ]]
for scope in unknown ../outside $'agentic-engineering\ndir=plugins' $'engineering-practices\nbranch=other'; do
rc=0
bash "$here/skill-update-scope.sh" workflow_dispatch "$scope" > "$work/out" 2> "$work/err" || rc=$?
[[ $rc == 2 && ! -s $work/out && -s $work/err ]]
done
rc=0
bash "$here/skill-update-scope.sh" schedule agentic-engineering > "$work/out" 2> "$work/err" || rc=$?
[[ $rc == 2 && ! -s $work/out ]]
for scope in agentic-engineering engineering-practices; do
rc=0
bash "$here/skill-update-scope.sh" schedule "$scope" > "$work/out" 2> "$work/err" || rc=$?
[[ $rc == 2 && ! -s $work/out ]]
done
rc=0
bash "$here/skill-update-scope.sh" pull_request all > "$work/out" 2> "$work/err" || rc=$?
[[ $rc == 2 && ! -s $work/out ]]
printf 'skill update scopes: PASS (9 cases)\n'
options=$(yq -o=json '.on.workflow_dispatch.inputs.scope' "$here/../.github/workflows/update-agent-skills.yaml")
printf '%s\n' "$options" | jq -se 'length == 1 and (.[0] | .type == "choice" and .default == "all" and
(.options | sort) == ["agentic-engineering","all","engineering-practices"])' > /dev/null
workflow=$(yq -o=json '.' "$here/../.github/workflows/update-agent-skills.yaml")
if ! printf '%s\n' "$workflow" | jq -se 'length == 1 and (.[0].concurrency == {
group:"agent-plugins-skill-sync-${{ github.repository }}",
"cancel-in-progress":false, queue:"max"})' > /dev/null; then
printf 'skill update scopes: require one non-cancelling queue across all scopes and follow-up jobs\n' >&2
exit 1
fi
printf '%s\n' "$workflow" | jq -se 'length == 1 and (.[0] |
.permissions == {} and .jobs.scope.permissions == {contents:"read"} and
.jobs.update.permissions == {contents:"write","pull-requests":"write"} and
.jobs."bump-versions".permissions == {contents:"read"})' > /dev/null
printf 'skill update scopes: PASS (declared selections, canonical branch and fail-closed dispatch)\n'
Loading