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: 8 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ auto-discovers `SKILL.md` at the install root and ignores everything else. Produ
| `references/` | ✓ | Implementation guidance: framework idioms (Rust + others), project structure, Rust/clap patterns. |
| `templates/` | ✓ | Drop-in starter files for greenfield Rust CLIs (`clap-main.rs`, `error-types.rs`, `output-format.rs`, `agents-md-template.md`). |
| `VERSION` | ✓ | Single-line current version. `bin/check-update` reads this for the upgrade comparison. |
| `scripts/sync-spec.sh` | — | Vendor `agentnative-spec` into `spec/` at a pinned `SPEC_REF`. Mirror of the agentnative-cli script. |
| `scripts/sync-spec.sh` | — | Vendor the latest `agentnative-spec` v\* tag into `spec/`. Mirror of the agentnative-cli script. |
| `scripts/generate-changelog.sh` | — | Release-time CHANGELOG generator (git-cliff + PR-body extraction). |
| `AGENTS.md`, `RELEASES.md`, `CONTRIBUTING.md`, `README.md`, `SECURITY.md` | — | Producer-repo docs. |
| `.github/rulesets/` | — | Version-controlled GitHub repository rulesets. |
Expand All @@ -46,15 +46,16 @@ tooling agree.
## Spec sync

The canonical principle text lives in [`brettdavies/agentnative`](https://github.com/brettdavies/agentnative). This repo
vendors it via `scripts/sync-spec.sh` at a pinned `SPEC_REF`. To bump:
vendors the latest released `v*` tag via `scripts/sync-spec.sh`. To resync:

```bash
SPEC_REF=v0.3.0 scripts/sync-spec.sh # pulls from $HOME/dev/agentnative-spec by default
git diff spec/ # review
scripts/sync-spec.sh # queries the remote first; falls back to $HOME/dev/agentnative-spec if offline
git diff spec/ # review
```

Then commit the result with a message like `chore: bump spec to agentnative-spec@v0.3.0`. The current pin is recorded in
[`spec/README.md`](./spec/README.md) and the version itself is in `spec/VERSION`.
Then commit the result with a message like `chore: bump spec to agentnative-spec@<version>`. The vendored version is
recorded in `spec/VERSION`. Override `SPEC_REMOTE_URL` to query a different remote, or `SPEC_ROOT` to point at a
non-default local checkout.

## Branch + release model

Expand All @@ -79,7 +80,7 @@ table.
`release/*` branch — those paths are filtered by the cherry-pick pattern. Add to `dev` instead.
- Modify `SKILL.md`'s `name` or `description` frontmatter without coordinating with consumers — those fields drive skill
discovery on every host.
- Re-tag a published version. Tags are immutable historical anchors that the install endpoints pin to.
- Re-tag a published version. Tags are immutable historical anchors for released versions.
- Add Rust/Cargo scaffolding. There is no Rust code in this repo and there should be none — the standard is
language-prescriptive but the skill itself is markdown + a tiny bash update-check.

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ auto-discovers `SKILL.md` at the install root and ignores everything else. Produ
## Touching the skill content

- **`spec/`** is vendored. Do not edit by hand. Substantive principle changes happen in `brettdavies/agentnative`; bring
them here by re-running `scripts/sync-spec.sh` at a new `SPEC_REF`.
them here by re-running `scripts/sync-spec.sh` after a new upstream tag lands.
- **`SKILL.md`** is the host-discovered entry point. Changes to its `name` or `description` frontmatter affect skill
discovery on every host — coordinate before changing.
- **`getting-started.md`** is the agent's first read after `SKILL.md`. Keep it short and concrete; cite spec paths and
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ agentnative-skill/
├── getting-started.md three working loops; canonical anc invocations
├── bin/
│ └── check-update consumer-side update-check script (gstack-style)
├── spec/ vendored from agentnative-spec at a pinned ref (do not edit)
├── spec/ vendored from agentnative-spec (do not edit)
├── references/ implementation guidance: framework idioms, project structure, Rust/clap patterns
├── templates/ drop-in starter files (clap-main, error-types, output-format, agents-md-template)
├── VERSION single-line current version (read by bin/check-update)
├── scripts/
│ ├── sync-spec.sh vendor agentnative-spec into spec/ at a pinned ref
│ ├── sync-spec.sh vendor the latest agentnative-spec v* tag into spec/
│ └── generate-changelog.sh release-time CHANGELOG generator (git-cliff + PR-body extraction)
├── docs/plans/ engineering plans (dev-only — guarded out of main)
├── .github/ workflows, rulesets, issue templates, PR template
Expand Down Expand Up @@ -60,8 +60,8 @@ prompted by `bin/check-update`.
- [`bin/check-update`](./bin/check-update) — periodic version check. Compares local `VERSION` to GitHub `main`, emits
`UPGRADE_AVAILABLE` so the agent can offer to `git pull`.
- [`spec/`](./spec/) — vendored canonical principle text from
[`agentnative-spec`](https://github.com/brettdavies/agentnative). See [`spec/README.md`](./spec/README.md) for the pin
and resync procedure. **Do not edit by hand.**
[`agentnative-spec`](https://github.com/brettdavies/agentnative). See [`spec/README.md`](./spec/README.md) for the
resync procedure. **Do not edit by hand.**
- [`references/`](./references/) — implementation guidance: framework idioms (Rust + others), project structure,
Rust/clap patterns. Used when remediating `anc` findings.
- [`templates/`](./templates/) — drop-in starting points for greenfield Rust CLIs (`clap-main.rs`, `error-types.rs`,
Expand Down
15 changes: 7 additions & 8 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ PR number in its squash commit message, which keeps the history scannable, attri
feature branch (feat/*, fix/*, chore/*, docs/*) → PR to dev (squash merge)
→ cherry-pick non-docs commits to release/<slug>
→ PR release/* to main (squash merge)
→ tag v* on main → GitHub Release → site re-pins to commit SHA
→ tag v* on main → GitHub Release
```

This is the canonical brettdavies release pattern with `release/*` cherry-pick branches. Plans live on `dev` forever and
Expand Down Expand Up @@ -101,8 +101,7 @@ When the PR merges:
--notes "$(awk '/^## \[<X.Y.Z>\]/{flag=1; next} /^## \[/{flag=0} flag' CHANGELOG.md)"
```

5. The site at `anc.dev/skill` re-pins via its own PR (separate repo, separate session). The handoff is the new commit
SHA plus a note if the bundle layout changed.
Consumers detect the new release on their next `bin/check-update` run; nothing else to do here.

`dev` keeps moving forward. Never reset or rebase `dev` after a release — it is forever.

Expand Down Expand Up @@ -137,10 +136,10 @@ flow above). There is no separate version-bump PR to `dev`. Picking the version
- **Patch** — doc updates, internal cleanups, non-substantive template edits, vendoring a patch-level spec bump.
- **Minor** — new templates, new reference docs, new bundle files (backward-compatible additions), vendoring a
minor-level spec bump that adds requirements without tightening existing tiers.
- **Major** — breaking changes to the bundle's contract: renaming `SKILL.md` frontmatter fields, restructuring
directory layout in ways that break existing skill installations, moving content between `` and the
producer-ops root, or vendoring a major-level spec bump (renamed/removed principles or tightened MUSTs that would
regress existing consumers).
- **Major** — breaking changes to the bundle's contract: renaming `SKILL.md` frontmatter fields, restructuring directory
layout in ways that break existing skill installations, moving content between `` and the producer-ops root, or
vendoring a major-level spec bump (renamed/removed principles or tightened MUSTs that would regress existing
consumers).

The skill's version is independent of the spec it vendors. A spec bump that doesn't affect the skill's surface (e.g.,
prose-only edits) can ship as a patch even when the spec went minor. Use the SemVer guidance above against the *skill's*
Expand Down Expand Up @@ -171,7 +170,7 @@ Three rulesets are committed under `.github/rulesets/` and applied to the repo v
- **`protect-dev.json`** — required signatures, deletion blocked, non-fast-forward blocked. No PR-requirement at the
ruleset level; the PR-only norm is enforced by convention.
- **`protect-tags.json`** — `v*` tags: deletion, force-push (re-tag), and updates all blocked. Tags are immutable
historical anchors that the site's `install.json` pins to.
historical anchors for released versions.

### Apply (post-public-flip)

Expand Down
108 changes: 76 additions & 32 deletions scripts/sync-spec.sh
Original file line number Diff line number Diff line change
@@ -1,77 +1,121 @@
#!/usr/bin/env bash
# Vendor agentnative-spec into spec/.
#
# Extracts files at a pinned git ref via `git show <ref>:<path>` so the user's
# spec working tree is not perturbed. The vendored tree ships as part of the
# skill bundle so consumers carry the canonical principle text alongside the
# skill metadata.
# Resolves the latest v* tag of agentnative-spec, preferring the remote
# repository, and falls back to a local checkout if the remote is
# unreachable. Extracts files via `git show <tag>:<path>` so neither
# checkout's working tree is perturbed. The vendored tree ships as part
# of the skill bundle so consumers carry the canonical principle text
# alongside the skill metadata.
#
# Usage:
# scripts/sync-spec.sh
# SPEC_REF=v0.2.1 scripts/sync-spec.sh
# SPEC_ROOT=/path/to/agentnative-spec scripts/sync-spec.sh
# SPEC_REMOTE_URL=git@github.com:brettdavies/agentnative.git scripts/sync-spec.sh
#
# Env vars:
# SPEC_ROOT Path to agentnative-spec checkout. Default: $HOME/dev/agentnative-spec
# SPEC_REF Git ref (tag, branch, or SHA) to vendor. Default: v0.2.0
# SPEC_REMOTE_URL Remote URL to query first.
# Default: https://github.com/brettdavies/agentnative.git
# SPEC_ROOT Local checkout to fall back to when the remote is
# unreachable. Default: $HOME/dev/agentnative-spec
#
# Resync cadence: rerun after every new agentnative-spec tag. Stale orphan
# files in spec/principles/ (e.g., from a spec rename) are accepted;
# `git status` surfaces them at commit time.
# Resync cadence: rerun after every new agentnative-spec tag. The remote
# query picks up new tags automatically; a local fallback only sees what
# the local checkout already has fetched.
#
# Stale orphan files in spec/principles/ (e.g., from a spec rename) are
# accepted; `git status` surfaces them at commit time.
#
# Mirror of agentnative-cli/scripts/sync-spec.sh; only DEST_DIR differs.

set -euo pipefail

SPEC_REMOTE_URL="${SPEC_REMOTE_URL:-https://github.com/brettdavies/agentnative.git}"
SPEC_ROOT="${SPEC_ROOT:-$HOME/dev/agentnative-spec}"
SPEC_REF="${SPEC_REF:-v0.2.0}"

REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
DEST_DIR="$REPO_ROOT/spec"
DEST_PRINCIPLES="$DEST_DIR/principles"

if [[ ! -d "$SPEC_ROOT/.git" ]]; then
echo "error: SPEC_ROOT is not a git repository: $SPEC_ROOT" >&2
echo " set SPEC_ROOT to your agentnative-spec checkout, or clone it to the default" >&2
echo " location: \$HOME/dev/agentnative-spec" >&2
exit 1
fi
# Cleanup hook for the temp clone (set only after mktemp succeeds).
tmp_root=""
cleanup() {
if [[ -n "$tmp_root" && -d "$tmp_root" ]]; then
rm -rf "$tmp_root"
fi
}
trap cleanup EXIT

if ! git -C "$SPEC_ROOT" rev-parse --verify --quiet "$SPEC_REF^{commit}" >/dev/null; then
echo "error: SPEC_REF does not resolve to a commit in $SPEC_ROOT: $SPEC_REF" >&2
echo " try \`git -C $SPEC_ROOT fetch --tags\` or check the ref name" >&2
exit 1
# === Remote-first resolution ===========================================
spec_source=""
spec_tag=""

echo "querying $SPEC_REMOTE_URL for latest v* tag..."
remote_tag="$(git ls-remote --tags --sort='-version:refname' \
"$SPEC_REMOTE_URL" 'refs/tags/v*' 2>/dev/null \
| awk '{print $2}' \
| sed 's|refs/tags/||' \
| grep -v '\^{}$' \
| head -n 1 || true)"

if [[ -n "$remote_tag" ]]; then
tmp_root="$(mktemp -d -t agentnative-spec-XXXXXX)"
if git clone --depth 1 --branch "$remote_tag" --quiet \
"$SPEC_REMOTE_URL" "$tmp_root" 2>/dev/null; then
spec_source="$tmp_root"
spec_tag="$remote_tag"
resolved_sha="$(git -C "$spec_source" rev-parse --short=7 "$spec_tag^{commit}")"
echo "vendoring $spec_tag ($resolved_sha) from remote $SPEC_REMOTE_URL"
fi
fi

resolved_sha="$(git -C "$SPEC_ROOT" rev-parse --short=7 "$SPEC_REF^{commit}")"
echo "vendoring $SPEC_REF ($resolved_sha) from $SPEC_ROOT"
# === Local fallback ====================================================
if [[ -z "$spec_source" ]]; then
if [[ ! -d "$SPEC_ROOT/.git" ]]; then
echo "error: remote unreachable and SPEC_ROOT is not a git repository: $SPEC_ROOT" >&2
echo " remote: $SPEC_REMOTE_URL" >&2
echo " set SPEC_ROOT to your agentnative-spec checkout, or check network access." >&2
exit 1
fi
echo "warning: remote query failed; falling back to local $SPEC_ROOT" >&2

spec_source="$SPEC_ROOT"
spec_tag="$(git -C "$spec_source" tag --list 'v*' --sort='-version:refname' | head -n 1)"
if [[ -z "$spec_tag" ]]; then
echo "error: no v* tags found in $SPEC_ROOT" >&2
echo " try \`git -C $SPEC_ROOT fetch --tags\` to pick up upstream tags" >&2
exit 1
fi
resolved_sha="$(git -C "$spec_source" rev-parse --short=7 "$spec_tag^{commit}")"
echo "vendoring $spec_tag ($resolved_sha) from local $spec_source"
fi

# Verify the principles/ tree exists at the ref.
if ! git -C "$SPEC_ROOT" cat-file -e "$SPEC_REF:principles" 2>/dev/null; then
echo "error: $SPEC_REF has no principles/ directory in $SPEC_ROOT" >&2
# === Verify + extract (works identically for remote and local sources) =
if ! git -C "$spec_source" cat-file -e "$spec_tag:principles" 2>/dev/null; then
echo "error: $spec_tag has no principles/ directory in $spec_source" >&2
exit 1
fi

mkdir -p "$DEST_PRINCIPLES"

# VERSION and CHANGELOG.md are top-level in the spec repo.
git -C "$SPEC_ROOT" show "$SPEC_REF:VERSION" >"$DEST_DIR/VERSION"
git -C "$SPEC_ROOT" show "$SPEC_REF:CHANGELOG.md" >"$DEST_DIR/CHANGELOG.md"
git -C "$spec_source" show "$spec_tag:VERSION" >"$DEST_DIR/VERSION"
git -C "$spec_source" show "$spec_tag:CHANGELOG.md" >"$DEST_DIR/CHANGELOG.md"

# Enumerate principle files at the ref and extract each one.
# Enumerate principle files at the tag and extract each one.
copied=0
while IFS= read -r path; do
case "$path" in
principles/p*-*.md)
dest_name="${path#principles/}"
git -C "$SPEC_ROOT" show "$SPEC_REF:$path" >"$DEST_PRINCIPLES/$dest_name"
git -C "$spec_source" show "$spec_tag:$path" >"$DEST_PRINCIPLES/$dest_name"
copied=$((copied + 1))
;;
esac
done < <(git -C "$SPEC_ROOT" ls-tree --name-only "$SPEC_REF" principles/)
done < <(git -C "$spec_source" ls-tree --name-only "$spec_tag" principles/)

if [[ "$copied" -eq 0 ]]; then
echo "error: no principles/p*-*.md files found at $SPEC_REF" >&2
echo "error: no principles/p*-*.md files found at $spec_tag" >&2
exit 1
fi

Expand Down
18 changes: 9 additions & 9 deletions spec/README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
# Vendored agentnative-spec

This directory is a **vendored copy** of [`brettdavies/agentnative`](https://github.com/brettdavies/agentnative) — the
canonical specification of agent-native CLI principles. Files here are not edited by hand; they are mirrored from an
upstream tag and ship inside the skill bundle so consumers carry the canonical principle text alongside the skill
metadata. Each release of this bundle re-vendors against the latest spec tag.

**Current snapshot:** `v0.2.0`
canonical specification of agent-native CLI principles. Files here are not edited by hand; they are mirrored from the
latest upstream `v*` tag and ship inside the skill bundle so consumers carry the canonical principle text alongside the
skill metadata. Each release of this bundle re-vendors against the latest spec tag. The currently vendored version is
recorded in [`VERSION`](./VERSION).

## Resync

Run from the repo root:

```bash
scripts/sync-spec.sh # default: SPEC_REF=v0.2.0
SPEC_REF=v0.2.1 scripts/sync-spec.sh # bump to a newer tag
scripts/sync-spec.sh # queries the remote for the latest v* tag; falls back to local on network failure
```

The script extracts files at the named git ref via `git show`, so the spec checkout's working tree is not perturbed.
Override `SPEC_ROOT` if your spec checkout is not at `$HOME/dev/agentnative-spec`.
The script queries `https://github.com/brettdavies/agentnative.git` for the latest `v*` tag and shallow-clones that tag
into a temp directory for extraction. If the remote is unreachable, it falls back to a local checkout
(`$HOME/dev/agentnative-spec` by default; override with `SPEC_ROOT`). Override `SPEC_REMOTE_URL` to query a different
remote. The script extracts files via `git show`, so neither source's working tree is perturbed.

## Layout

Expand Down